summaryrefslogtreecommitdiff
path: root/src/main/java/bjc/rgens/parser/elements
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-06-04 22:19:21 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-06-04 22:19:21 -0300
commit8062cff63f864178a2a73650870362871bc25224 (patch)
tree1da3005e66911182ae2433d7690fe98a0b8b6e37 /src/main/java/bjc/rgens/parser/elements
parent63c7fff30d41ab691d6f49d8d7b69e60f9a9e80f (diff)
Exhaustion pt. 2
There is now syntax for rule references. Use @ instead of $, and use := to indicate you want exhaustion enabled Use @ to refer to it
Diffstat (limited to 'src/main/java/bjc/rgens/parser/elements')
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/CaseElement.java53
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java2
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java2
-rw-r--r--src/main/java/bjc/rgens/parser/elements/RuleVarRefCaseElement.java47
-rw-r--r--src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java46
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/VariableCaseElement.java19
6 files changed, 143 insertions, 26 deletions
diff --git a/src/main/java/bjc/rgens/parser/elements/CaseElement.java b/src/main/java/bjc/rgens/parser/elements/CaseElement.java
index 103c00a..5263d03 100755
--- a/src/main/java/bjc/rgens/parser/elements/CaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/CaseElement.java
@@ -22,12 +22,7 @@ public abstract class CaseElement {
/** An element that represents a random range. */
RANGE(true),
/** An element that represents a variable that stores a string. */
- VARDEF(false),
- /**
- * An element that represents a variable that stores the result of generating a
- * rule.
- */
- EXPVARDEF(false);
+ VARIABLE(false);
public final boolean spacing;
@@ -36,9 +31,6 @@ public abstract class CaseElement {
}
}
- /* Regexps for marking rule types. */
- private static final String RANGE_CASELM = "\\[\\d+\\.\\.\\d+\\]";
-
/** The type of this element. */
public final ElementType type;
@@ -80,7 +72,7 @@ public abstract class CaseElement {
if (csepart.matches("\\{[^}]+\\}")) {
/*
- * Handle special cases.
+ * Handle special case elements.
*
*/
String specialBody = csepart.substring(1, csepart.length() - 1);
@@ -97,13 +89,8 @@ public abstract class CaseElement {
throw new GrammarException(msg);
}
- /*
- * @NOTE
- *
- * This should maybe check that parts[1] is a
- * valid rule name, since it gets used as one.
- */
- return new ExpVariableCaseElement(parts[0], parts[1]);
+ /* Trim $ */
+ return new ExpVariableCaseElement(parts[0].substring(1), parts[1]);
} else if (specialBody.matches("\\$\\S+=\\S+")) {
/* Handle regular variable definitions. */
String[] parts = specialBody.split("=");
@@ -114,7 +101,32 @@ public abstract class CaseElement {
throw new GrammarException(msg);
}
- return new LitVariableCaseElement(parts[0], parts[1]);
+ /* Trim $ */
+ return new LitVariableCaseElement(parts[0].substring(1), parts[1]);
+ } else if (specialBody.matches("\\@\\S+=\\S+")) {
+ /* Handle rule variable definitions. */
+ String[] parts = specialBody.split("=");
+
+ if (parts.length != 2) {
+ String msg = "Rule variables must be a name and a definition, seperated by =";
+
+ throw new GrammarException(msg);
+ }
+
+ /* Trim $ */
+ return new RuleVariableCaseElement(parts[0].substring(1), parts[1], false);
+ } else if (specialBody.matches("\\@\\S+:=\\S+")) {
+ /* Handle exhaustible rule variable definitions. */
+ String[] parts = specialBody.split("=");
+
+ if (parts.length != 2) {
+ String msg = "Rule variables must be a name and a definition, seperated by =";
+
+ throw new GrammarException(msg);
+ }
+
+ /* Trim $ */
+ return new RuleVariableCaseElement(parts[0].substring(1), parts[1], true);
} else if (specialBody.matches("empty")) {
/* Literal blank, for empty cases. */
return new BlankCaseElement();
@@ -151,6 +163,9 @@ public abstract class CaseElement {
}
return new VariableRuleReference(csepart);
+ } else if(csepart.contains("@")) {
+ // Trim @
+ return new RuleVarRefCaseElement(csepart.substring(1));
} else {
return new NormalRuleReference(csepart);
}
@@ -160,7 +175,7 @@ public abstract class CaseElement {
System.err.printf("\tTRACE: short ref to %s (%s)\n", rName, csepart);
return new NormalRuleReference(rName);
- } else{
+ } else {
return new LiteralCaseElement(csepart);
}
}
diff --git a/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java
index 58c5479..455fce6 100755
--- a/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java
@@ -9,7 +9,7 @@ import bjc.rgens.parser.RuleCase;
public class ExpVariableCaseElement extends VariableCaseElement {
public ExpVariableCaseElement(String name, String def) {
- super(name, def, true);
+ super(name, def, VariableType.EXPAND);
}
@Override
diff --git a/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java
index 91b8a2b..cd44ccb 100755
--- a/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java
@@ -4,7 +4,7 @@ import bjc.rgens.parser.GenerationState;
public class LitVariableCaseElement extends VariableCaseElement {
public LitVariableCaseElement(String name, String def) {
- super(name, def, false);
+ super(name, def, VariableType.NORMAL);
}
public void generate(GenerationState state) {
diff --git a/src/main/java/bjc/rgens/parser/elements/RuleVarRefCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RuleVarRefCaseElement.java
new file mode 100644
index 0000000..a7be1bb
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/RuleVarRefCaseElement.java
@@ -0,0 +1,47 @@
+package bjc.rgens.parser.elements;
+
+import bjc.utils.data.IPair;
+
+import bjc.rgens.parser.GenerationState;
+import bjc.rgens.parser.GrammarException;
+import bjc.rgens.parser.RecurLimitException;
+import bjc.rgens.parser.RGrammar;
+import bjc.rgens.parser.Rule;
+import bjc.rgens.parser.RuleCase;
+
+public class RuleVarRefCaseElement extends StringCaseElement {
+ public RuleVarRefCaseElement(String vl) {
+ super(vl, false);
+ }
+
+ public void generate(GenerationState state) {
+ if(!state.rlVars.containsKey(val)) {
+ throw new GrammarException("No rule variable named " + val);
+ }
+
+ IPair<RGrammar, Rule> par = state.rlVars.get(val);
+
+ GenerationState newState = state.newBuf();
+ newState.swapGrammar(par.getLeft());
+
+ if(par.getRight().doRecur()) {
+ RuleCase cse = par.getRight().getCase(state.rnd);
+ System.err.printf("\tFINE: Generating %s (from %s)\n", cse, par.getRight().name);
+
+ par.getLeft().generateCase(cse, newState);
+
+ par.getRight().endRecur();
+ } else {
+ throw new RecurLimitException("Rule recurrence limit exceeded");
+ }
+
+ String res = newState.contents.toString();
+
+ if (par.getRight().name.contains("+")) {
+ /* Rule names with pluses in them get space-flattened */
+ state.contents.append(res.replaceAll("\\s+", ""));
+ } else {
+ state.contents.append(res);
+ }
+ }
+}
diff --git a/src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java
new file mode 100644
index 0000000..55a1c1e
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java
@@ -0,0 +1,46 @@
+package bjc.rgens.parser.elements;
+
+import bjc.utils.data.IPair;
+import bjc.utils.data.Pair;
+
+import bjc.rgens.parser.GrammarException;
+import bjc.rgens.parser.GenerationState;
+import bjc.rgens.parser.Rule;
+import bjc.rgens.parser.RGrammar;
+
+public class RuleVariableCaseElement extends VariableCaseElement {
+ public final boolean exhaust;
+
+ public RuleVariableCaseElement(String varName, String varDef, boolean exhaust) {
+ super(varName, varDef, VariableType.RULE);
+
+ this.exhaust = exhaust;
+ }
+
+ public void generate(GenerationState state) {
+ Rule rl;
+ RGrammar grm;
+
+ if(state.rules.containsKey(varDef)) {
+ rl = state.rules.get(varDef);
+ grm = state.gram;
+ } else if(state.importRules.containsKey(varDef)) {
+ grm = state.importRules.get(varDef);
+ rl = grm.getRules().get(varDef);
+ } else {
+ throw new GrammarException("Can't create variable referencing non-existent rule " + varDef);
+ }
+
+
+ if(exhaust) rl = rl.exhaust();
+
+ if(state.rlVars.containsKey(varName)) {
+ IPair<RGrammar, Rule> par = state.rlVars.get(varName);
+
+ System.err.printf("WARN: Shadowing rule variable '%s' (%s with %s)\n",
+ varName, par.getRight().name, rl.name);
+ }
+
+ state.rlVars.put(varName, new Pair<>(grm, rl));
+ }
+}
diff --git a/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java
index 3e691d9..63abe16 100755
--- a/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java
@@ -1,6 +1,11 @@
package bjc.rgens.parser.elements;
public abstract class VariableCaseElement extends CaseElement {
+ public static enum VariableType {
+ NORMAL,
+ EXPAND,
+ RULE
+ }
/**
* The name of the variable this element defines.
*/
@@ -11,11 +16,15 @@ public abstract class VariableCaseElement extends CaseElement {
*/
public final String varDef;
- public VariableCaseElement(String name, String def, boolean isExp) {
- super(isExp ? ElementType.EXPVARDEF : ElementType.VARDEF);
+ public final VariableType varType;
+
+ public VariableCaseElement(String name, String def, VariableType varType) {
+ super(ElementType.VARIABLE);
varName = name;
varDef = def;
+
+ this.varType = varType;
}
@Override
@@ -51,10 +60,10 @@ public abstract class VariableCaseElement extends CaseElement {
@Override
public String toString() {
- if (type == ElementType.VARDEF) {
- return String.format("{%s:=%s}", varName, varDef);
+ if (type == ElementType.VARIABLE) {
+ return String.format("{$%s:=%s}", varName, varDef);
} else {
- return String.format("{%s=%s}", varName, varDef);
+ return String.format("{$%s=%s}", varName, varDef);
}
}
}