Files
cs8803p4/src/dk/itu/mario/level/grammar/LevelGrammarFactory.java
2012-03-18 16:17:04 -04:00

190 lines
5.9 KiB
Java

package dk.itu.mario.level.grammar;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import dk.itu.mario.level.LevelComponent;
public class LevelGrammarFactory {
public static LevelGrammar createGrammar(File grammarFile) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream(grammarFile);
LevelGrammar levelGrammar = new LevelGrammar();
try {
InputStreamReader reader = new InputStreamReader(fis);
BufferedReader buf = new BufferedReader(reader);
String line;
while ((line = buf.readLine()) != null) {
line = line.trim(); // trim off newline/whitespace
if (line.length() == 0 || line.startsWith("#")) {
continue;
}
//System.out.println("Read: " + line);
//split on whitespace
String[] fields;
if (line.startsWith("VAR")) {
fields = line.split("\\s");
if ("=".equals(fields[2]) && fields.length == 4) {
levelGrammar.addVariable(new Variable(fields[1],LevelComponent.TYPE.valueOf(fields[3])));
} else {
throw new RuntimeException("Invalid VAR syntax: " + line);
}
} else if (line.startsWith("RULE")) {
fields = line.split("->");
String ruleName = fields[0].split("\\s")[1];
//System.out.println("Rule name: " + ruleName);
Variable lhs = levelGrammar.getVariable(ruleName);
if (lhs == null) {
throw new RuntimeException("LHS variable not found: " + ruleName);
}
Clause rhs = getClause(fields[1].trim(),levelGrammar);
levelGrammar.addProductionRule(new ProductionRule(lhs,rhs));
} else if (line.startsWith("START")) {
fields = line.split("\\s");
if ("=".equals(fields[1]) && fields.length == 3) {
levelGrammar.setStart(fields[2]);
} else {
throw new RuntimeException("Invalid START syntax: " + line);
}
} else {
throw new RuntimeException("Unable to parse grammar file " + grammarFile.getName() + " due to invalid line: " + line);
}
}
return levelGrammar;
} finally {
fis.close();
}
}
private static Clause getClause(String clause, LevelGrammar grammar) {
if (!clause.contains("|") && !clause.contains("+")) {
return grammar.getVariable(clause);
}
int lBraceIndex = clause.indexOf("{");
boolean isOrClause = false;
int rBraceIndex = 0;
double[] chances = {};
if (lBraceIndex != -1) {
isOrClause = true;
rBraceIndex = clause.indexOf("}");
//System.out.println("Read OR-clause probabilities from: " + lBraceIndex + " to " + rBraceIndex);
String[] doubleFields = clause.substring(lBraceIndex+1,rBraceIndex).split(",");
chances = new double[doubleFields.length];
for (int i = 0; i < doubleFields.length; i++) {
chances[i] = Double.valueOf(doubleFields[i]);
}
}
String remainder = clause.substring(rBraceIndex);
if (remainder.startsWith("}, ")) {
remainder = remainder.substring(3);
}
List<String> rhsClauseStrings = new ArrayList<String>();
if (remainder.contains("(")) {
int nextLeftIndex = -1;
do {
nextLeftIndex = remainder.indexOf("(", nextLeftIndex+1);
if (nextLeftIndex != -1) {
int nextRightIndex = remainder.indexOf(")", nextLeftIndex+1);
if (nextRightIndex == -1) {
throw new RuntimeException("Unmatched left '(' in clause");
}
rhsClauseStrings.add(remainder.substring(nextLeftIndex+1,nextRightIndex));
nextLeftIndex = nextRightIndex;
}
} while (nextLeftIndex != -1);
} else {
isOrClause = remainder.contains("|");
if (isOrClause) {
for (String subclause : remainder.split("\\|")) {
rhsClauseStrings.add(subclause.trim());
}
} else {
for (String subclause : remainder.split("\\+")) {
rhsClauseStrings.add(subclause.trim());
}
}
}
List<Clause> rhsClauses = new ArrayList<Clause>();
for (String subclause : rhsClauseStrings) {
rhsClauses.add(getClause(subclause,grammar));
}
if (isOrClause) {
return new OrClause(chances, rhsClauses);
} else {
return new AndClause(rhsClauses);
}
}
public static LevelGrammar createGrammar() {
LevelGrammar grammar = new LevelGrammar();
Variable v_START = new Variable("S", LevelComponent.TYPE.LEVEL);
Variable v_LAND_SEGMENT = new Variable("HALF_LVL", LevelComponent.TYPE.LEVEL_SEGMENT);
Variable v_LO_HI = new Variable("LO_HI", LevelComponent.TYPE.LO_HI);
Variable v_HI_LO = new Variable("HI_LO", LevelComponent.TYPE.HI_LO);
Variable v_LO_PATH = new Variable("LO_PATH", LevelComponent.TYPE.LO_PATH);
Variable v_HI_PATH = new Variable("HI_PATH", LevelComponent.TYPE.HI_PATH);
Variable v_lo_path = new Variable("lo_path", LevelComponent.TYPE.FLAT_LO);
Variable v_hi_path = new Variable("hi_path", LevelComponent.TYPE.FLAT_HI);
grammar.addVariable(v_START);
grammar.addVariable(v_LAND_SEGMENT);
grammar.addVariable(v_LO_HI);
grammar.addVariable(v_HI_LO);
grammar.addVariable(v_LO_PATH);
grammar.addVariable(v_HI_PATH);
grammar.addProductionRule(new ProductionRule(v_START,v_LAND_SEGMENT,v_LAND_SEGMENT));
grammar.addProductionRule(
new ProductionRule(v_LAND_SEGMENT,
new OrClause( new double[] {0.25,0.65,0.10},
new AndClause(v_LO_HI,v_HI_LO),
v_LO_PATH,
new AndClause(v_LAND_SEGMENT,v_LAND_SEGMENT)
)
)
);
grammar.addProductionRule(
new ProductionRule(v_LO_HI, v_LO_PATH, v_HI_PATH)
);
grammar.addProductionRule(
new ProductionRule(v_HI_LO, v_HI_PATH, v_LO_PATH)
);
grammar.addProductionRule(
new ProductionRule(v_HI_PATH,
new OrClause( new double[] {0.25,0.75},
new AndClause(v_HI_PATH,v_HI_PATH),
v_hi_path
)
)
);
grammar.addProductionRule(
new ProductionRule(v_LO_PATH,
new OrClause( new double[] {0.25,0.75},
new AndClause(v_LO_PATH,v_LO_PATH),
v_lo_path
)
)
);
grammar.setStart(v_START);
return grammar;
}
}