diff options
Diffstat (limited to 'src/main/java/bjc/rgens/parser/Rule.java')
| -rwxr-xr-x[-rw-r--r--] | src/main/java/bjc/rgens/parser/Rule.java | 132 |
1 files changed, 121 insertions, 11 deletions
diff --git a/src/main/java/bjc/rgens/parser/Rule.java b/src/main/java/bjc/rgens/parser/Rule.java index 7043e0f..ac67158 100644..100755 --- a/src/main/java/bjc/rgens/parser/Rule.java +++ b/src/main/java/bjc/rgens/parser/Rule.java @@ -1,7 +1,9 @@ package bjc.rgens.parser; +import bjc.utils.data.IPair; import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.IList; +import bjc.utils.gen.WeightedRandom; import java.util.Random; @@ -11,12 +13,34 @@ import java.util.Random; * @author EVE */ public class Rule { + public RGrammar belongsTo; + /** The name of this grammar rule. */ - public final String name; + public String name; /* The cases for this rule. */ - private IList<RuleCase> cases; + private WeightedRandom<RuleCase> cases; + + public static enum ProbType { + NORMAL, + DESCENDING, + BINOMIAL + } + + public ProbType prob; + + public int descentFactor; + + public int target; + public int bound; + public int trials; + + public int recurLimit = 5; + private int currentRecur; + private final static Random BASE = new Random(); + + private int serial = 1; /** * Create a new grammar rule. * @@ -35,7 +59,9 @@ public class Rule { name = ruleName; - cases = new FunctionalList<>(); + cases = new WeightedRandom<>(); + + prob = ProbType.NORMAL; } /** @@ -45,11 +71,25 @@ public class Rule { * The case to add. */ public void addCase(RuleCase cse) { + addCase(cse, 1); + } + + /** + * Adds a case to the rule. + * + * @param cse + * The case to add. + */ + public void addCase(RuleCase cse, int weight) { if (cse == null) { throw new NullPointerException("Case must not be null"); } - cases.add(cse); + cse.belongsTo = this; + cse.debugName = String.format("%s-%d", name, serial); + serial += 1; + + cases.addProbability(weight, cse); } /** @@ -59,7 +99,7 @@ public class Rule { * A random case from this rule. */ public RuleCase getCase() { - return cases.randItem(); + return getCase(BASE); } /** @@ -72,7 +112,16 @@ public class Rule { * A random case from this rule. */ public RuleCase getCase(Random rnd) { - return cases.randItem(rnd::nextInt); + switch(prob) { + case DESCENDING: + return cases.getDescent(descentFactor, rnd); + case BINOMIAL: + return cases.getBinomial(target, bound, trials, rnd); + case NORMAL: + return cases.generateValue(rnd); + default: + return cases.generateValue(rnd); + } } /** @@ -81,8 +130,8 @@ public class Rule { * @return * All the cases in this rule. */ - public IList<RuleCase> getCases() { - return cases; + public IList<IPair<Integer, RuleCase>> getCases() { + return cases.getValues(); } /** @@ -91,8 +140,17 @@ public class Rule { * @param cases * The new list of cases. */ - public void replaceCases(IList<RuleCase> cases) { - this.cases = cases; + public void replaceCases(IList<IPair<Integer, RuleCase>> cases) { + this.cases = new WeightedRandom<>(); + + for(IPair<Integer, RuleCase> cse : cases) { + RuleCase cs = cse.getRight(); + cs.belongsTo = this; + cs.debugName = String.format("%s-%d", name, serial); + serial += 1; + + this.cases.addProbability(cse.getLeft(), cs); + } } @Override @@ -129,6 +187,58 @@ public class Rule { @Override public String toString() { - return String.format("Rule [ruleName='%s', ruleCases=%s]", name, cases); + return String.format("Rule '%s' with %d cases", name, cases.getValues().getSize()); + } + + public boolean doRecur() { + if(currentRecur > recurLimit) return false; + + currentRecur += 1; + + return true; + } + + public void endRecur() { + if(currentRecur > 0) currentRecur -= 1; + } + + public Rule exhaust() { + Rule rl = new Rule(name); + + rl.belongsTo = belongsTo; + + rl.cases = cases.exhaustible(); + + rl.prob = prob; + + rl.descentFactor = descentFactor; + + rl.target = target; + rl.bound = bound; + rl.trials = trials; + + rl.recurLimit = recurLimit; + /* @NOTE Is this the right thing to do? */ + rl.currentRecur = 0; + + return rl; + } + + public void generate(GenerationState state) { + state.swapGrammar(belongsTo); + + if(doRecur()) { + RuleCase cse = getCase(state.rnd); + + System.err.printf("\tFINE: Generating %s (from %s)\n", cse, belongsTo.name); + + belongsTo.generateCase(cse, state); + + endRecur(); + } + + if(name.contains("+")) { + state.contents = new StringBuilder(state.contents.toString().replaceAll("\\s+", "")); + } } } |
