package util.gdl.transforms;
import java.util.ArrayList;
import java.util.List;
import util.gdl.grammar.Gdl;
import util.gdl.grammar.GdlConstant;
import util.gdl.grammar.GdlDistinct;
import util.gdl.grammar.GdlFunction;
import util.gdl.grammar.GdlLiteral;
import util.gdl.grammar.GdlNot;
import util.gdl.grammar.GdlOr;
import util.gdl.grammar.GdlPool;
import util.gdl.grammar.GdlProposition;
import util.gdl.grammar.GdlRelation;
import util.gdl.grammar.GdlRule;
import util.gdl.grammar.GdlSentence;
import util.gdl.grammar.GdlTerm;
import util.gdl.grammar.GdlVariable;
//Cleans up various issues with games to make them more standardized.
public class GdlCleaner {
public static List<Gdl> run(List<Gdl> description) {
List<Gdl> newDescription = new ArrayList<Gdl>();
//First: Clean up all rules with zero-element bodies
for(Gdl gdl : description) {
if(gdl instanceof GdlRule) {
GdlRule rule = (GdlRule) gdl;
if(rule.getBody().size() == 0) {
newDescription.add(rule.getHead());
//System.out.println("Changing rule " + rule + " into relation " + rule.getHead());
} else {
newDescription.add(gdl);
}
} else {
newDescription.add(gdl);
}
}
//TODO: Add (role ?player) where appropriate, i.e. in rules for
//"legal" or "input" where the first argument is an undefined
//variable
//Get rid of "extra parentheses", i.e. zero-arity functions
description = newDescription;
newDescription = new ArrayList<Gdl>();
for(Gdl gdl : description) {
if(gdl instanceof GdlRelation) {
newDescription.add(cleanParentheses((GdlRelation)gdl));
} else if(gdl instanceof GdlRule) {
newDescription.add(cleanParentheses((GdlRule)gdl));
} else {
newDescription.add(gdl);
}
}
//TODO: Get rid of GdlPropositions in the description
return newDescription;
}
private static GdlRule cleanParentheses(GdlRule rule) {
GdlSentence cleanedHead = cleanParentheses(rule.getHead());
List<GdlLiteral> cleanedBody = new ArrayList<GdlLiteral>();
for(GdlLiteral literal : rule.getBody())
cleanedBody.add(cleanParentheses(literal));
return GdlPool.getRule(cleanedHead, cleanedBody);
}
private static GdlLiteral cleanParentheses(GdlLiteral literal) {
if(literal instanceof GdlSentence) {
return cleanParentheses((GdlSentence)literal);
} else if(literal instanceof GdlDistinct) {
GdlDistinct distinct = (GdlDistinct) literal;
GdlTerm term1 = cleanParentheses(distinct.getArg1());
GdlTerm term2 = cleanParentheses(distinct.getArg2());
return GdlPool.getDistinct(term1, term2);
} else if(literal instanceof GdlNot) {
return GdlPool.getNot(((GdlNot) literal).getBody());
} else if(literal instanceof GdlOr) {
GdlOr or = (GdlOr) literal;
List<GdlLiteral> disjuncts = new ArrayList<GdlLiteral>();
for(int i = 0; i < or.arity(); i++)
disjuncts.add(cleanParentheses(or.get(i)));
return GdlPool.getOr(disjuncts);
}
throw new RuntimeException("Unexpected literal type in GdlCleaner");
}
private static GdlSentence cleanParentheses(GdlSentence sentence) {
if(sentence instanceof GdlProposition)
return sentence;
List<GdlTerm> cleanedBody = new ArrayList<GdlTerm>();
for(GdlTerm term : sentence.getBody())
cleanedBody.add(cleanParentheses(term));
return GdlPool.getRelation(sentence.getName(), cleanedBody);
}
private static GdlTerm cleanParentheses(GdlTerm term) {
if(term instanceof GdlConstant || term instanceof GdlVariable)
return term;
if(term instanceof GdlFunction) {
GdlFunction function = (GdlFunction) term;
//The whole point of the function
if(function.arity() == 0)
return function.getName();
List<GdlTerm> cleanedBody = new ArrayList<GdlTerm>();
for(GdlTerm functionTerm : function.getBody())
cleanedBody.add(cleanParentheses(functionTerm));
return GdlPool.getFunction(function.getName(), cleanedBody);
}
throw new RuntimeException("Unexpected term type in GdlCleaner");
}
}