diff options
| author | student <student@69.161.224.76> | 2018-03-29 11:38:02 -0400 |
|---|---|---|
| committer | student <student@69.161.224.76> | 2018-03-29 11:38:02 -0400 |
| commit | 6aa15e30fa75211964428e386b4b6b0f2c66dbc5 (patch) | |
| tree | 5beeb6016a94b284eeed80daf65b9c2800ec7e63 /RGens/src/main/java/bjc/rgens/parser/CaseElement.java | |
| parent | c921b00c99cf46bc33f724581ab9bde2b0d8bb6a (diff) | |
Rename package
Diffstat (limited to 'RGens/src/main/java/bjc/rgens/parser/CaseElement.java')
| -rw-r--r-- | RGens/src/main/java/bjc/rgens/parser/CaseElement.java | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/RGens/src/main/java/bjc/rgens/parser/CaseElement.java b/RGens/src/main/java/bjc/rgens/parser/CaseElement.java new file mode 100644 index 0000000..e9e3a0a --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/CaseElement.java @@ -0,0 +1,423 @@ +package bjc.rgens.parser; + +import static bjc.rgens.parser.CaseElement.ElementType.*; + +/* + * @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; + + /** + * The literal string value of this element. + * + * This means that it is a string whose value should always mean the + * same thing. + * + * <h2>Used For</h2> + * <dl> + * <dt>LITERAL</dt> + * <dd>The string this element represents</dd> + * <dt>RULEREF</dt> + * <dd>The name of the rule this element references</dd> + * </dl> + */ + private String literalVal; + + /** + * The starting integer value of this element. + * + * <h2>Used For</h2> + * <dl> + * <dt>RANGE</dt> + * <dd>The inclusive start of the range</dd> + * </dl> + */ + private int start; + + /** + * The starting integer value of this element. + * + * <h2>Used For</h2> + * <dl> + * <dt>RANGE</dt> + * <dd>The inclusive end of the range</dd> + * </dl> + */ + private int end; + + /** + * The name of the variable this element defines. + * + * <h2>Used For</h2> + * <dl> + * <dt>VARDEF</dt> + * <dd>The name of the variable</dd> + * <dt>EXPVARDEF</dt> + * <dd>The name of the variable</dd> + * </dl> + */ + private String varName; + + /** + * The definition of the variable this element defines. + * + * <h2>Used For</h2> + * <dl> + * <dt>VARDEF</dt> + * <dd>The value of the variable</dd> + * <dt>EXPVARDEF</dt> + * <dd>The rule to expand for the value of this variable</dd> + * </dl> + */ + private String varDef; + + /** + * Create a new case element. + * + * @param typ + * The type of this element. + * + * @throws IllegalArgumentException + * If the specified type needs parameters. + */ + public CaseElement(ElementType typ) { + switch (typ) { + case LITERAL: + case RULEREF: + throw new IllegalArgumentException("This type requires a string parameter"); + case RANGE: + throw new IllegalArgumentException("This type requires two integer parameters"); + case VARDEF: + case EXPVARDEF: + throw new IllegalArgumentException("This type requires two string parameters"); + default: + break; + } + + type = typ; + } + + /** + * Create a new case element that has a single string value. + * + * @param typ + * The type of this element. + * + * @param val + * The string value of this element. + * + * @throws IllegalArgumentException + * If the specified type doesn't take a single string parameter. + */ + public CaseElement(ElementType typ, String val) { + switch (typ) { + case LITERAL: + case RULEREF: + break; + case RANGE: + throw new IllegalArgumentException("This type requires two integer parameters"); + case VARDEF: + case EXPVARDEF: + throw new IllegalArgumentException("This type requires two string parameters"); + default: + throw new IllegalArgumentException("This type doesn't have a string parameter"); + } + + type = typ; + + literalVal = val; + } + + /** + * Create a new case element that has two integer values. + * + * @param typ + * The type of this element. + * + * @param first + * The first integer value for this element. + * + * @param second + * The second integer value for this element. + * + * @throws IllegalArgumentException + * If the specified type doesn't take two integer parameters. + */ + public CaseElement(ElementType typ, int first, int second) { + switch (typ) { + case LITERAL: + case RULEREF: + throw new IllegalArgumentException("This type requires a string parameter"); + case RANGE: + break; + case VARDEF: + case EXPVARDEF: + throw new IllegalArgumentException("This type requires two string parameters"); + default: + throw new IllegalArgumentException("This type doesn't have two integer parameters"); + } + + type = typ; + + this.start = first; + this.end = second; + } + + /** + * Create a new case element that has two string values. + * + * @param typ + * The type of this element. + * + * @param name + * The first string value for this element. + * + * @param def + * The second string value for this element. + * + * @throws IllegalArgumentException + * If the specified type doesn't take two string parameters. + */ + public CaseElement(ElementType typ, String name, String def) { + switch (typ) { + case LITERAL: + case RULEREF: + throw new IllegalArgumentException("This type requires a string parameter"); + case RANGE: + throw new IllegalArgumentException("This type requires two integer parameters"); + case VARDEF: + case EXPVARDEF: + break; + default: + throw new IllegalArgumentException("This type doesn't have two string parameters"); + } + + type = typ; + + this.varName = name; + this.varDef = def; + } + + /** + * Get the literal string value for this element. + * + * @return + * The literal string value for this element. + * + * @throws IllegalStateException + * If this type doesn't have a literal string value. + */ + public String getLiteral() { + switch (type) { + case LITERAL: + case RULEREF: + break; + default: + throw new IllegalStateException( + String.format("Type '%s' doesn't have a literal string value")); + } + + return literalVal; + } + + /** + * Get the starting integer value for this element. + * + * @return + * The starting integer value for this element. + * + * @throws IllegalStateException + * If this type doesn't have a starting integer value. + */ + public int getStart() { + switch (type) { + case RANGE: + break; + default: + throw new IllegalStateException( + String.format("Type '%s' doesn't have a starting integer value", type)); + } + + return start; + } + + /** + * Get the ending integer value for this element. + * + * @return + * The ending integer value for this element. + * + * @throws IllegalStateException + * If this type doesn't have a ending integer value. + */ + public int getEnd() { + switch (type) { + case RANGE: + break; + default: + throw new IllegalStateException( + String.format("Type '%s' doesn't have a ending integer value", type)); + } + + return end; + } + + /** + * Get the variable name for this element. + * + * @return + * The variable name of this element. + * + * @throws IllegalStateException + * If the type doesn't have a variable name. + */ + public String getName() { + switch (type) { + case VARDEF: + case EXPVARDEF: + break; + default: + throw new IllegalStateException(String.format("Type '%s' doesn't have a name", type)); + } + + return varName; + } + + /** + * Get the variable definition for this element. + * + * @return + * The variable definition of this element. + * + * @throws IllegalStateException + * If the type doesn't have a variable definition. + */ + public String getDefn() { + switch (type) { + case VARDEF: + case EXPVARDEF: + break; + default: + throw new IllegalStateException(String.format("Type '%s' doesn't have a name", type)); + } + + return varDef; + } + + @Override + public String toString() { + switch (type) { + case LITERAL: + case RULEREF: + return literalVal; + case RANGE: + return String.format("[%d..%d]", start, end); + case VARDEF: + return String.format("{%s:=%s}", varName, varDef); + case EXPVARDEF: + return String.format("{%s=%s}", varName, varDef); + 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 CaseElement(EXPVARDEF, 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 CaseElement(VARDEF, parts[0], parts[1]); + } else if (specialBody.matches("{empty}")) { + /* Literal blank, for empty cases. */ + return new CaseElement(LITERAL, ""); + } 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 CaseElement(RANGE, firstNum, secondNum); + } + + return new CaseElement(RULEREF, csepart); + } else { + return new CaseElement(LITERAL, csepart); + } + } +} |
