summaryrefslogtreecommitdiff
path: root/src/main/java/bjc/rgens/parser/elements
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-06-07 20:37:51 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-06-07 20:37:51 -0300
commit44a8d9d2d56a311293ec86ea40df7126748300a1 (patch)
treecc53c34a97a403ddb4a8d112f09124ee42c4507a /src/main/java/bjc/rgens/parser/elements
parent7422af49fa5c4da57323abe676a99468d401c44b (diff)
Refactoring
The main refactoring here is removing the type field from the various classes, but there are a few other smaller ones. This also contains the grounds for a refactoring on variable use
Diffstat (limited to 'src/main/java/bjc/rgens/parser/elements')
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/CaseElement.java49
-rw-r--r--src/main/java/bjc/rgens/parser/elements/ChanceCaseElement.java20
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java14
-rw-r--r--src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java31
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/RangeCaseElement.java2
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/RuleCaseElement.java13
-rw-r--r--src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java4
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/StringCaseElement.java2
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/VariableCaseElement.java11
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/ARefVariableElement.java35
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java15
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java35
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java43
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java29
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java59
15 files changed, 294 insertions, 68 deletions
diff --git a/src/main/java/bjc/rgens/parser/elements/CaseElement.java b/src/main/java/bjc/rgens/parser/elements/CaseElement.java
index 68f5368..d799dbe 100755
--- a/src/main/java/bjc/rgens/parser/elements/CaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/CaseElement.java
@@ -1,5 +1,7 @@
package bjc.rgens.parser.elements;
+import bjc.utils.funcutils.StringUtils;
+
import bjc.rgens.parser.GenerationState;
import bjc.rgens.parser.GrammarException;
@@ -32,7 +34,11 @@ public abstract class CaseElement {
}
/** The type of this element. */
- public final ElementType type;
+ public boolean spacing;
+
+ protected CaseElement() {
+ this(true);
+ }
/**
* Create a new case element.
@@ -40,13 +46,8 @@ public abstract class CaseElement {
* @param typ
* The type of this element.
*/
- protected CaseElement(ElementType typ) {
- type = typ;
- }
-
- @Override
- public String toString() {
- return String.format("Unknown type '%s'", type);
+ protected CaseElement(boolean spacing) {
+ this.spacing = spacing;
}
/**
@@ -70,15 +71,13 @@ public abstract class CaseElement {
throw new NullPointerException("Case part cannot be null");
}
- if (csepart.matches("\\{[^}]+\\}")) {
+ if (csepart.matches("\\{\\S+\\}")) {
/*
* Handle special case elements.
*
*/
String specialBody = csepart.substring(1, csepart.length() - 1);
- //System.out.printf("\t\tTRACE: special body is '%s'\n", specialBody);
-
if (specialBody.matches("\\S+:=\\S+")) {
String[] parts = specialBody.split(":=");
if(parts.length != 2) {
@@ -99,7 +98,7 @@ public abstract class CaseElement {
} else {
throw new IllegalArgumentException(String.format("Unknown special case part '%s'", specialBody));
}
- } else if (csepart.matches("\\[[^\\]]+\\]")) {
+ } else if (csepart.matches("\\[\\S+\\]")) {
String rawCase = csepart.substring(1, csepart.length() - 1);
if (rawCase.matches("\\d+\\.\\.\\d+")) {
@@ -107,23 +106,17 @@ public abstract class CaseElement {
int secondNum = Integer.parseInt(rawCase.substring(rawCase.lastIndexOf('.') + 1));
return new RangeCaseElement(firstNum, secondNum);
- } else if(rawCase.contains("|")) {
- String[] elms = rawCase.split("\\|");
+ } else if(rawCase.contains("||")) {
+ String[] elms = StringUtils.levelSplit(rawCase, "||").toArray(new String[0]);
+ //String[] elms = rawCase.split("\\|\\|");
- System.err.printf("\t\tTRACE: Split inline cases %s to ", rawCase);
- for(String elm : elms) {
- System.err.printf("%s, ", elm);
- }
- System.err.println();
+ return new InlineRuleCaseElement(elms);
+ } else if(rawCase.contains("|")) {
+ System.err.println("\t\tWARN: Inline rule using | found, they use || now");
+ String[] elms = StringUtils.levelSplit(rawCase, "|").toArray(new String[0]);
return new InlineRuleCaseElement(elms);
} else if(csepart.contains("$")) {
- /*
- * @NOTE
- *
- * Once the rule element execution has been refactored,
- * pass rawCase instead.
- */
if(csepart.contains("-")) {
return new DependantRuleReference(csepart);
}
@@ -135,7 +128,7 @@ public abstract class CaseElement {
} else {
return new NormalRuleReference(csepart);
}
- } else if(csepart.startsWith("%")) {
+ } else if(csepart.startsWith("%") && !csepart.equals("%")) {
String rName = String.format("[%s]", csepart.substring(1));
System.err.printf("\t\tTRACE: short ref to %s (%s)\n", rName, csepart);
@@ -150,7 +143,7 @@ public abstract class CaseElement {
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((type == null) ? 0 : type.hashCode());
+ result = prime * result + (spacing ? 0 : 2);
return result;
}
@@ -163,7 +156,7 @@ public abstract class CaseElement {
if (getClass() != obj.getClass())
return false;
CaseElement other = (CaseElement) obj;
- if (type != other.type)
+ if (spacing != other.spacing)
return false;
return true;
}
diff --git a/src/main/java/bjc/rgens/parser/elements/ChanceCaseElement.java b/src/main/java/bjc/rgens/parser/elements/ChanceCaseElement.java
new file mode 100644
index 0000000..483a103
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/ChanceCaseElement.java
@@ -0,0 +1,20 @@
+package bjc.rgens.parser.elements;
+
+import bjc.rgens.parser.GenerationState;
+
+public class ChanceCaseElement extends CaseElement {
+ public final CaseElement elm;
+
+ public int chance;
+
+ public ChanceCaseElement(CaseElement elm, int chance) {
+ super(elm.spacing);
+
+ this.elm = elm;
+ this.chance = chance;
+ }
+
+ public void generate(GenerationState state) {
+ if(state.rnd.nextInt(chance) == 0) elm.generate(state);
+ }
+}
diff --git a/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java
index 3972e7a..198b0db 100755
--- a/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java
@@ -23,16 +23,12 @@ public class ExpVariableCaseElement extends VariableCaseElement {
if(rl != null) {
RGrammar destGrammar = rl.belongsTo;
newState.swapGrammar(destGrammar);
- String res = destGrammar.generate(varDef, state);
-
- /*
- * @NOTE
- *
- * :Postprocessing
- *
- * This is because generate() returns a processed
- * string, but modifies the passed in StringBuilder.
+ /*
+ * Don't post-process the string, we should only do that
+ * once.
*/
+ String res = destGrammar.generate(varDef, state, false);
+
newState.contents = new StringBuilder(res);
} else {
String msg = String.format("No rule '%s' defined", varDef);
diff --git a/src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java b/src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java
index 6cb0ce3..ea22bb4 100644
--- a/src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java
@@ -3,23 +3,38 @@ package bjc.rgens.parser.elements;
import bjc.rgens.parser.GenerationState;
import bjc.rgens.parser.RGrammarParser;
+import bjc.utils.data.IPair;
import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.IList;
+import bjc.utils.gen.WeightedRandom;
public class InlineRuleCaseElement extends CaseElement {
- public final IList<CaseElement> elements;
+ public final WeightedRandom<CaseElement> elements;
- public InlineRuleCaseElement(String... elements) {
- this(RGrammarParser.parseElementString(elements).getLeft());
- }
+ public InlineRuleCaseElement(String... parts) {
+ super(true);
+
+ this.elements = new WeightedRandom<>();
+
+ for(String part : parts) {
+ String[] partArr;
+
+ if(part.contains("|")) {
+ partArr = part.split("\\|");
+ } else {
+ partArr = new String[] {part};
+ }
- public InlineRuleCaseElement(IList<CaseElement> elements) {
- super(ElementType.RULEREF);
+ IPair<IList<CaseElement>, Integer> par = RGrammarParser.parseElementString(partArr);
+ int prob = par.getRight();
- this.elements = elements;
+ for(CaseElement elm :par.getLeft()) {
+ elements.addProbability(prob, elm);
+ }
+ }
}
public void generate(GenerationState state) {
- elements.randItem(state.rnd::nextInt).generate(state);
+ elements.generateValue(state.rnd).generate(state);
}
}
diff --git a/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java
index cf8f161..e877dd1 100755
--- a/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java
@@ -7,7 +7,7 @@ public class RangeCaseElement extends CaseElement {
public final int end;
public RangeCaseElement(int beg, int en) {
- super(ElementType.RANGE);
+ super(true);
begin = beg;
end = en;
diff --git a/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java
index e0c847a..6aa50fc 100755
--- a/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java
@@ -39,16 +39,11 @@ public abstract class RuleCaseElement extends StringCaseElement {
if(rl != null) {
RGrammar destGrammar = rl.belongsTo;
newState.swapGrammar(destGrammar);
- String res = destGrammar.generate(actName, newState);
-
- /*
- * @NOTE
- *
- * :Postprocessing
- *
- * This is because generate() returns a processed
- * string, but modifies the passed in StringBuilder.
+ /*
+ * Don't postprocess the string, we should only do that
+ * once.
*/
+ String res = destGrammar.generate(actName, newState, false);
newState.contents = new StringBuilder(res);
} else {
/*
diff --git a/src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java b/src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java
index 594595e..348cfbb 100644
--- a/src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java
@@ -9,7 +9,7 @@ public class SerialCaseElement extends CaseElement {
public final int upper;
public SerialCaseElement(CaseElement rep, int lower, int upper) {
- super(rep.type);
+ super(rep.spacing);
this.rep = rep;
@@ -23,7 +23,7 @@ public class SerialCaseElement extends CaseElement {
for(int i = 0; i < num; i++) {
rep.generate(state);
- if(rep.type.spacing)
+ if(rep.spacing)
state.contents.append(" ");
}
}
diff --git a/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java b/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java
index 61ad48a..57e2cc7 100755
--- a/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java
@@ -4,7 +4,7 @@ public abstract class StringCaseElement extends CaseElement {
public final String val;
protected StringCaseElement(String vl, boolean isLiteral) {
- super(isLiteral ? ElementType.LITERAL : ElementType.RULEREF);
+ super(true);
val = vl;
}
diff --git a/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java
index a2c15a7..63701e0 100755
--- a/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java
@@ -21,7 +21,7 @@ public abstract class VariableCaseElement extends CaseElement {
public final VariableType varType;
public VariableCaseElement(String name, String def, VariableType varType) {
- super(ElementType.VARIABLE);
+ super(false);
varName = name;
varDef = def;
@@ -60,15 +60,6 @@ public abstract class VariableCaseElement extends CaseElement {
return true;
}
- @Override
- public String toString() {
- if (type == ElementType.VARIABLE) {
- return String.format("{$%s:=%s}", varName, varDef);
- } else {
- return String.format("{$%s=%s}", varName, varDef);
- }
- }
-
public static CaseElement parseVariable(String varName, String varDef, boolean colon) {
if(varName.startsWith("$")) {
// Handle normal/expanding variable definitions
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/ARefVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/ARefVariableElement.java
new file mode 100644
index 0000000..7a8910c
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/vars/ARefVariableElement.java
@@ -0,0 +1,35 @@
+package bjc.rgens.parser.elements.vars;
+
+import bjc.rgens.parser.GenerationState;
+import bjc.rgens.parser.GrammarException;
+import bjc.rgens.parser.Rule;
+
+public class ARefVariableElement extends VariableElement {
+ public String value;
+
+ private boolean forbidSpaces;
+
+ public ARefVariableElement(boolean forbidSpaces, String val) {
+ value = val;
+ }
+
+ public void generate(GenerationState state) {
+ if(!state.rlVars.containsKey(value)) {
+ throw new GrammarException("No rule variable named " + value);
+ }
+
+ Rule rl = state.rlVars.get(value);
+
+ GenerationState newState = state.newBuf();
+
+ rl.generate(newState);
+
+ String res = newState.contents.toString();
+
+ if(forbidSpaces && res.contains(" ")) {
+ throw new GrammarException("Spaces not allowed in this context (rule-var %s)");
+ }
+
+ state.contents.append(res);
+ }
+}
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java
new file mode 100644
index 0000000..080f849
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java
@@ -0,0 +1,15 @@
+package bjc.rgens.parser.elements.vars;
+
+import bjc.rgens.parser.GenerationState;
+
+public class LiteralVariableElement extends VariableElement {
+ public String val;
+
+ public LiteralVariableElement(String val) {
+ this.val = val;
+ }
+
+ public void generate(GenerationState state) {
+ state.contents.append(val);
+ }
+}
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java
new file mode 100644
index 0000000..6bf332f
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java
@@ -0,0 +1,35 @@
+package bjc.rgens.parser.elements.vars;
+
+import bjc.rgens.parser.GenerationState;
+import bjc.rgens.parser.GrammarException;
+import bjc.rgens.parser.Rule;
+
+public class RRefVariableElement extends VariableElement {
+ public String value;
+
+ private boolean forbidSpaces;
+
+ public RRefVariableElement(boolean forbidSpaces, String val) {
+ value = val;
+ }
+
+ public void generate(GenerationState state) {
+ if(!state.rlVars.containsKey(value)) {
+ throw new GrammarException("No rule variable named " + value);
+ }
+
+ Rule rl = state.findRule(value, true);
+
+ GenerationState newState = state.newBuf();
+
+ rl.generate(newState);
+
+ String res = newState.contents.toString();
+
+ if(forbidSpaces && res.contains(" ")) {
+ throw new GrammarException("Spaces not allowed in this context (rule-reference %s)");
+ }
+
+ state.contents.append(res);
+ }
+}
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java
new file mode 100644
index 0000000..b10af87
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java
@@ -0,0 +1,43 @@
+package bjc.rgens.parser.elements.vars;
+
+import bjc.rgens.parser.GenerationState;
+import bjc.rgens.parser.GrammarException;
+import bjc.rgens.parser.templates.GrammarTemplate;
+
+/*
+ * @TODO
+ *
+ * finish when template vars are implemented.
+ */
+public class TRefVariableElement extends VariableElement {
+ /*
+ public String value;
+
+ private boolean forbidSpaces;
+
+ public TRefVariableElement(boolean forbidSpaces, String val) {
+ value = val;
+ }*/
+
+ public void generate(GenerationState state) {
+ /*
+ if(!state.rlVars.containsKey(val)) {
+ throw new GrammarException("No rule variable named " + val);
+ }
+
+ Rule rl = state.rlVars.get(val);
+
+ GenerationState newState = state.newBuf();
+
+ rl.generate(newState);
+
+ String res = newState.contents.toString();
+
+ if(forbidSpaces && res.contains(" ")) {
+ throw new GrammarException("Spaces not allowed in this context (rule-var %s)");
+ }
+
+ return res;
+ */
+ }
+}
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java
new file mode 100644
index 0000000..c6921ba
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java
@@ -0,0 +1,29 @@
+package bjc.rgens.parser.elements.vars;
+
+import bjc.rgens.parser.GenerationState;
+import bjc.rgens.parser.GrammarException;
+
+public class VRefVariableElement extends VariableElement {
+ public final String nam;
+
+ private final boolean forbidSpaces;
+
+ public VRefVariableElement(boolean forbidSpaces, String nam) {
+ this.nam = nam;
+
+ this.forbidSpaces = forbidSpaces;
+ }
+
+ public void generate(GenerationState state) {
+ if (!state.vars.containsKey(nam)) {
+ throw new GrammarException(String.format("No variable '%s' defined", nam));
+ }
+
+ String strang = state.vars.get(nam);
+ if(forbidSpaces && strang.contains(" ")) {
+ throw new GrammarException(String.format("Cannot include variable %s w/ spaces in body in rule name", nam));
+ }
+
+ state.contents.append(strang);
+ }
+}
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java
new file mode 100644
index 0000000..7a4260f
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java
@@ -0,0 +1,59 @@
+package bjc.rgens.parser.elements.vars;
+
+import bjc.rgens.parser.GenerationState;
+import bjc.rgens.parser.GrammarException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class VariableElement {
+ public abstract void generate(GenerationState state);
+
+ public static List<VariableElement> parseVariableElements(String varElm) {
+ boolean forbidSpaces = varElm.contains("-");
+
+ String[] parts;
+
+ if(forbidSpaces) {
+ parts = varElm.split("(?<=[+-])|(?=[+-])");
+ } else {
+ parts = new String[] { varElm };
+ }
+
+ return parseVariableElements(forbidSpaces, parts);
+ }
+
+ public static List<VariableElement> parseVariableElements(boolean forbidSpaces, String... parts) {
+ List<VariableElement> elms = new ArrayList<>(parts.length);
+
+ VariableElement prevElement = null;
+
+ for (String part : parts) {
+ VariableElement elm = null;
+
+ if(part.startsWith("$")) {
+ elm = new VRefVariableElement(forbidSpaces, part.substring(1));
+ } else if (part.startsWith("@")) {
+ elm = new ARefVariableElement(forbidSpaces, part.substring(1));
+ } else if (part.startsWith("%")) {
+ elm = new RRefVariableElement(forbidSpaces, part.substring(1));
+ } else if (part.startsWith("/")) {
+ throw new GrammarException("Template variables aren't implemented yet");
+ } else {
+ if(prevElement instanceof LiteralVariableElement) {
+ /* Aggregate chain literals together */
+ ((LiteralVariableElement)prevElement).val += elm;
+ } else {
+ elm = new LiteralVariableElement(part);
+ }
+ }
+
+ if(elm != null) {
+ elms.add(elm);
+ prevElement = elm;
+ }
+ }
+
+ return elms;
+ }
+}