diff options
Diffstat (limited to 'RGens/src/main/java/bjc/rgens/parser/elements')
9 files changed, 328 insertions, 0 deletions
diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/BlankCaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/BlankCaseElement.java new file mode 100644 index 0000000..7229e92 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/BlankCaseElement.java @@ -0,0 +1,7 @@ +package bjc.rgens.parser.elements; + +public class BlankCaseElement extends LiteralCaseElement { + public BlankCaseElement() { + super(""); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/CaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/CaseElement.java new file mode 100644 index 0000000..7cad599 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/CaseElement.java @@ -0,0 +1,149 @@ +package bjc.rgens.parser.elements; + +import static bjc.rgens.parser.elements.CaseElement.ElementType.*; + +import bjc.rgens.parser.GrammarException; + +/* + * @TODO 10/11/17 Ben Culkin :CaseElementSplit Split this into multiple + * subclasses based off of a value of ElementType. + */ +/** + * A element in a rule case. + * + * @author EVE + */ +public class CaseElement { + /** + * The possible types of an element. + * + * @author EVE + */ + public static enum ElementType { + /** An element that represents a literal string. */ + LITERAL, + /** An element that represents a rule reference. */ + RULEREF, + /** An element that represents a random range. */ + RANGE, + /** An element that represents a variable that stores a string. */ + VARDEF, + /** + * An element that represents a variable that stores the result of generating a + * rule. + */ + EXPVARDEF; + } + + /* Regexps for marking rule types. */ + private static final String SPECIAL_CASELEM = "\\{[^}]+\\}"; + private static final String REFER_CASELEM = "\\[[^\\]]+\\]"; + private static final String RANGE_CASELM = "\\[\\d+\\.\\.\\d+\\]"; + + /** The type of this element. */ + public final ElementType type; + + /** + * Create a new case element. + * + * @param typ + * The type of this element. + */ + protected CaseElement(ElementType typ) { + type = typ; + } + + @Override + public String toString() { + switch (type) { + default: + return String.format("Unknown type '%s'", type); + } + } + + /** + * Create a case element from a string. + * + * @param csepart + * The string to convert. + * + * @return A case element representing the string. + */ + public static CaseElement createElement(String csepart) { + if (csepart == null) { + throw new NullPointerException("Case part cannot be null"); + } + + if (csepart.matches(SPECIAL_CASELEM)) { + /* Handle special cases. */ + String specialBody = csepart.substring(1, csepart.length() - 1); + + System.out.printf("\t\tTRACE: special body is '%s'\n", specialBody); + + if (specialBody.matches("\\S+:=\\S+")) { + /* Handle expanding variable definitions. */ + String[] parts = specialBody.split(":="); + + if (parts.length != 2) { + String msg = "Expanded variables must be a name and a definition, seperated by :="; + + throw new GrammarException(msg); + } + + return new ExpVariableCaseElement(parts[0], parts[1]); + } else if (specialBody.matches("\\S+=\\S+")) { + /* Handle regular variable definitions. */ + String[] parts = specialBody.split("="); + + if (parts.length != 2) { + String msg = "Variables must be a name and a definition, seperated by ="; + + throw new GrammarException(msg); + } + + return new LitVariableCaseElement(parts[0], parts[1]); + } else if (specialBody.matches("{empty}")) { + /* Literal blank, for empty cases. */ + return new BlankCaseElement(); + } else { + throw new IllegalArgumentException(String.format("Unknown special case part '%s'", specialBody)); + } + } else if (csepart.matches(REFER_CASELEM)) { + if (csepart.matches(RANGE_CASELM)) { + /* Handle ranges */ + String rawRange = csepart.substring(1, csepart.length() - 1); + + int firstNum = Integer.parseInt(rawRange.substring(0, rawRange.indexOf('.'))); + int secondNum = Integer.parseInt(rawRange.substring(rawRange.lastIndexOf('.') + 1)); + + return new RangeCaseElement(firstNum, secondNum); + } + + return new RuleCaseElement(csepart); + } else { + return new LiteralCaseElement(csepart); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CaseElement other = (CaseElement) obj; + if (type != other.type) + return false; + return true; + } +}
\ No newline at end of file diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java new file mode 100644 index 0000000..30925e2 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java @@ -0,0 +1,7 @@ +package bjc.rgens.parser.elements; + +public class ExpVariableCaseElement extends VariableCaseElement { + public ExpVariableCaseElement(String name, String def) { + super(name, def, true); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java new file mode 100644 index 0000000..11035b1 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java @@ -0,0 +1,7 @@ +package bjc.rgens.parser.elements; + +public class LitVariableCaseElement extends VariableCaseElement { + public LitVariableCaseElement(String name, String def) { + super(name, def, false); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java new file mode 100644 index 0000000..d96a32d --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java @@ -0,0 +1,7 @@ +package bjc.rgens.parser.elements; + +public class LiteralCaseElement extends StringCaseElement { + public LiteralCaseElement(String vl) { + super(vl, true); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java new file mode 100644 index 0000000..d98bc61 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java @@ -0,0 +1,43 @@ +package bjc.rgens.parser.elements; + +public class RangeCaseElement extends CaseElement { + public final int begin; + public final int end; + + public RangeCaseElement(int beg, int en) { + super(ElementType.RANGE); + + begin = beg; + end = en; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + begin; + result = prime * result + end; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + RangeCaseElement other = (RangeCaseElement) obj; + if (begin != other.begin) + return false; + if (end != other.end) + return false; + return true; + } + + @Override + public String toString() { + return String.format("[%d..%d]", begin, end); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java new file mode 100644 index 0000000..f4d3512 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java @@ -0,0 +1,7 @@ +package bjc.rgens.parser.elements; + +public class RuleCaseElement extends StringCaseElement { + public RuleCaseElement(String vl) { + super(vl, false); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java new file mode 100644 index 0000000..0e64fd3 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java @@ -0,0 +1,41 @@ +package bjc.rgens.parser.elements; + +public class StringCaseElement extends CaseElement { + public final String val; + + protected StringCaseElement(String vl, boolean isLiteral) { + super(isLiteral ? ElementType.LITERAL : ElementType.RULEREF); + + val = vl; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((val == null) ? 0 : val.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + StringCaseElement other = (StringCaseElement) obj; + if (val == null) { + if (other.val != null) + return false; + } else if (!val.equals(other.val)) + return false; + return true; + } + + @Override + public String toString() { + return val; + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java b/RGens/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java new file mode 100644 index 0000000..920445a --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java @@ -0,0 +1,60 @@ +package bjc.rgens.parser.elements; + +public class VariableCaseElement extends CaseElement { + /** + * The name of the variable this element defines. + */ + public final String varName; + + /** + * The definition of the variable this element defines. + */ + public final String varDef; + + public VariableCaseElement(String name, String def, boolean isExp) { + super(isExp ? ElementType.EXPVARDEF : ElementType.VARDEF); + + varName = name; + varDef = def; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((varDef == null) ? 0 : varDef.hashCode()); + result = prime * result + ((varName == null) ? 0 : varName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + VariableCaseElement other = (VariableCaseElement) obj; + if (varDef == null) { + if (other.varDef != null) + return false; + } else if (!varDef.equals(other.varDef)) + return false; + if (varName == null) { + if (other.varName != null) + return false; + } else if (!varName.equals(other.varName)) + return false; + return true; + } + + @Override + public String toString() { + if (type == ElementType.VARDEF) { + return String.format("{%s:=%s}", varName, varDef); + } else { + return String.format("{%s=%s}", varName, varDef); + } + } +} |
