From faf3e39fee32226ee72c6d43b2ba8a0f4e4bd837 Mon Sep 17 00:00:00 2001 From: "Benjamin J. Culkin" Date: Tue, 29 May 2018 18:02:46 -0300 Subject: Refactor case element generation Case elements are now responsible for generating themselves. --- .../java/bjc/rgens/parser/GenerationState.java | 71 +++++++ src/main/java/bjc/rgens/parser/RGrammar.java | 231 ++++----------------- .../java/bjc/rgens/parser/RGrammarBuilder.java | 16 +- src/main/java/bjc/rgens/parser/RGrammarParser.java | 1 + .../bjc/rgens/parser/elements/CaseElement.java | 56 +++-- .../parser/elements/ExpVariableCaseElement.java | 38 ++++ .../parser/elements/LitVariableCaseElement.java | 6 + .../rgens/parser/elements/LiteralCaseElement.java | 7 + .../rgens/parser/elements/RangeCaseElement.java | 9 + .../bjc/rgens/parser/elements/RuleCaseElement.java | 122 +++++++++++ .../rgens/parser/elements/StringCaseElement.java | 2 +- .../rgens/parser/elements/VariableCaseElement.java | 2 +- 12 files changed, 344 insertions(+), 217 deletions(-) create mode 100644 src/main/java/bjc/rgens/parser/GenerationState.java diff --git a/src/main/java/bjc/rgens/parser/GenerationState.java b/src/main/java/bjc/rgens/parser/GenerationState.java new file mode 100644 index 0000000..7ab55bf --- /dev/null +++ b/src/main/java/bjc/rgens/parser/GenerationState.java @@ -0,0 +1,71 @@ +package bjc.rgens.parser; + +import java.util.Map; +import java.util.Random; + +/* + * The current state during generation. + * + */ +public class GenerationState { + /** The current string. */ + public StringBuilder contents; + /** The RNG. */ + public Random rnd; + + /* + * @NOTE + * + * Once the planned refactor for importing rules happens, this will need + * to be changed. + */ + /** The current grammar. */ + public RGrammar gram; + /** The rules of the grammar. */ + public Map rules; + /** The rules imported from other grammars. */ + public Map importRules; + + /* + * @NOTE + * + * For planned features, this will need to be refactored. + */ + /** The current set of variables. */ + public Map vars; + + /** + * Create a new generation state. + * + * @param cont + * The string being generated. + * + * @param rand + * The RNG to use. + * + * @param vs + * The variables to use. + */ + public GenerationState(StringBuilder cont, Random rand, Map vs, RGrammar gram) { + contents = cont; + rnd = rand; + vars = vs; + + this.gram = gram; + + this.rules = gram.getRules(); + this.importRules = gram.getImportRules(); + } + + public void swapGrammar(RGrammar gram) { + this.gram = gram; + + rules = gram.getRules(); + + importRules = gram.getImportRules(); + } + + public GenerationState newBuf() { + return new GenerationState(new StringBuilder(), rnd, vars, gram); + } +} diff --git a/src/main/java/bjc/rgens/parser/RGrammar.java b/src/main/java/bjc/rgens/parser/RGrammar.java index 38f38c8..9d17171 100755 --- a/src/main/java/bjc/rgens/parser/RGrammar.java +++ b/src/main/java/bjc/rgens/parser/RGrammar.java @@ -48,35 +48,6 @@ public class RGrammar { } } - /* The current state during generation. */ - private static class GenerationState { - /* The current string. */ - public StringBuilder contents; - /* The RNG. */ - public Random rnd; - - /* The current set of variables. */ - public Map vars; - - /** - * Create a new generation state. - * - * @param cont - * The string being generated. - * - * @param rand - * The RNG to use. - * - * @param vs - * The variables to use. - */ - public GenerationState(StringBuilder cont, Random rand, Map vs) { - contents = cont; - rnd = rand; - vars = vs; - } - } - /* The pattern for matching the name of a variable. */ private static Pattern NAMEVAR_PATTERN = Pattern.compile("\\$(\\w+)"); @@ -156,6 +127,20 @@ public class RGrammar { * @return A possible string from the grammar. */ public String generate(String startRule, Random rnd, Map vars) { + return generate(startRule, new GenerationState(new StringBuilder(), rnd, vars, this)); + } + + /** + * Generate a string from this grammar, starting from the specified rule. + * + * @param startRule + * The rule to start generating at, or null to use the initial rule + * for this grammar. + * + * @param state + * The generation state. + */ + public String generate(String startRule, GenerationState state) { String fromRule = startRule; if (startRule == null) { @@ -170,13 +155,19 @@ public class RGrammar { } } - RuleCase start = rules.get(fromRule).getCase(rnd); + RuleCase start = rules.get(fromRule).getCase(state.rnd); - StringBuilder contents = new StringBuilder(); + generateCase(start, state); - generateCase(start, new GenerationState(contents, rnd, vars)); + /* + * @NOTE + * + * :Postprocessing + * + * Do we want to perform this post-processing here, or elsewhere? + */ + String body = state.contents.toString(); - String body = contents.toString(); /* * Collapse duplicate spaces. */ @@ -211,16 +202,24 @@ public class RGrammar { body = body.replaceAll("\\s+", " "); /* - * @TODO 11/01/17 Ben Culkin :RegexRule Replace this once it is no longer - * needed. + * @TODO 11/01/17 Ben Culkin :RegexRule + * + * Replace this once it is no longer needed. */ body = body.replaceAll("\\s(ish|burg|ton|ville|opolis|field|boro|dale)", "$1"); return body; } - /* Generate a rule case. */ - private void generateCase(RuleCase start, GenerationState state) { + /** + * Generate a rule case. + * + * @param start + * The rule case to generate. + * @param state + * The current generation state. + */ + public void generateCase(RuleCase start, GenerationState state) { try { switch (start.type) { case NORMAL: @@ -250,165 +249,13 @@ public class RGrammar { /* Generate a case element. */ private void generateElement(CaseElement elm, GenerationState state) { try { - switch (elm.type) { - case LITERAL: { - LiteralCaseElement lit = (LiteralCaseElement)elm; - - state.contents.append(lit.val); - break; - } - case RULEREF: { - RuleCaseElement rle = (RuleCaseElement)elm; - - generateRuleReference(rle, state); - break; - } - case RANGE: { - RangeCaseElement rang = (RangeCaseElement)elm; - - int val = state.rnd.nextInt(rang.end - rang.begin); - val += rang.begin; - - state.contents.append(val); - break; - } - case VARDEF: - generateVarDef(((VariableCaseElement)elm).varName, ((VariableCaseElement)elm).varDef, state); - break; - case EXPVARDEF: - generateExpVarDef(((VariableCaseElement)elm).varName, ((VariableCaseElement)elm).varDef, state); - break; - default: - String msg = String.format("Unknown element type '%s'", elm.type); - throw new GrammarException(msg); - } + elm.generate(state); } catch (GrammarException gex) { String msg = String.format("Error in generating case element (%s)", elm); throw new GrammarException(msg, gex); } } - /* Generate a expanding variable definition. */ - private void generateExpVarDef(String name, String defn, GenerationState state) { - GenerationState newState = new GenerationState(new StringBuilder(), state.rnd, state.vars); - - if (rules.containsKey(defn)) { - RuleCase destCase = rules.get(defn).getCase(); - - generateCase(destCase, newState); - } else if (importRules.containsKey(defn)) { - RGrammar destGrammar = importRules.get(defn); - String res = destGrammar.generate(defn, state.rnd, state.vars); - - newState.contents.append(res); - } else { - String msg = String.format("No rule '%s' defined", defn); - throw new GrammarException(msg); - } - - state.vars.put(name, newState.contents.toString()); - } - - /* Generate a variable definition. */ - private static void generateVarDef(String name, String defn, GenerationState state) { - state.vars.put(name, defn); - } - - /* Generate a rule reference. */ - private void generateRuleReference(RuleCaseElement elm, GenerationState state) { - String refersTo = elm.val; - - GenerationState newState = new GenerationState(new StringBuilder(), state.rnd, state.vars); - - if (refersTo.contains("$")) { - /* Parse variables */ - String refBody = refersTo.substring(1, refersTo.length() - 1); - - if (refBody.contains("-")) { - /* Handle dependent rule names. */ - StringBuffer nameBuffer = new StringBuffer(); - - Matcher nameMatcher = NAMEVAR_PATTERN.matcher(refBody); - - while (nameMatcher.find()) { - String var = nameMatcher.group(1); - - if (!state.vars.containsKey(var)) { - String msg = String.format("No variable '%s' defined", var); - throw new GrammarException(msg); - } - - String name = state.vars.get(var); - - if (name.contains(" ")) { - throw new GrammarException("Variables substituted into names cannot contain spaces"); - } else if (name.equals("")) { - throw new GrammarException("Variables substituted into names cannot be empty"); - } - - nameMatcher.appendReplacement(nameBuffer, name); - } - - nameMatcher.appendTail(nameBuffer); - - refersTo = "[" + nameBuffer.toString() + "]"; - } else { - /* Handle string references. */ - if (refBody.equals("$")) { - throw new GrammarException("Cannot refer to unnamed variables"); - } - - String key = refBody.substring(1); - - if (!state.vars.containsKey(key)) { - String msg = String.format("No variable '%s' defined", key); - throw new GrammarException(msg); - } - - state.contents.append(state.vars.get(key)); - - return; - } - } - - if (refersTo.startsWith("[^")) { - refersTo = "[" + refersTo.substring(2); - - RGrammar dst = importRules.get(refersTo); - - newState.contents.append(dst.generate(refersTo, state.rnd, state.vars)); - } else if (rules.containsKey(refersTo)) { - RuleCase cse = rules.get(refersTo).getCase(state.rnd); - - generateCase(cse, newState); - } else if (importRules.containsKey(refersTo)) { - RGrammar dst = importRules.get(refersTo); - - newState.contents.append(dst.generate(refersTo, state.rnd, state.vars)); - } else { - if (ruleSearcher != null) { - Set> results = ruleSearcher.search(refersTo, MAX_DISTANCE); - - String[] resArray = results.stream().map(Match::getMatch).toArray((i) -> new String[i]); - - String msg = String.format("No rule '%s' defined (perhaps you meant %s?)", refersTo, - StringUtils.toEnglishList(resArray, false)); - - throw new GrammarException(msg); - } - - String msg = String.format("No rule '%s' defined", refersTo); - throw new GrammarException(msg); - } - - if (refersTo.contains("+")) { - /* Rule names with pluses in them get space-flattened */ - state.contents.append(newState.contents.toString().replaceAll("\\s+", "")); - } else { - state.contents.append(newState.contents.toString()); - } - } - /** * Get the initial rule of this grammar. * @@ -488,4 +335,8 @@ public class RGrammar { public Map getRules() { return rules; } + + public Map getImportRules() { + return importRules; + } } diff --git a/src/main/java/bjc/rgens/parser/RGrammarBuilder.java b/src/main/java/bjc/rgens/parser/RGrammarBuilder.java index 284d1a2..f34a418 100755 --- a/src/main/java/bjc/rgens/parser/RGrammarBuilder.java +++ b/src/main/java/bjc/rgens/parser/RGrammarBuilder.java @@ -66,8 +66,20 @@ public class RGrammarBuilder { public RGrammar toRGrammar() { RGrammar grammar = new RGrammar(rules); + if(initialRule != null) { + if(!rules.containsKey(initialRule)) { + throw new GrammarException(String.format("Rule '%s' doesn't exist\n", initialRule)); + } + } + grammar.setInitialRule(initialRule); + for(String export : exportedRules) { + if(!rules.containsKey(export)) { + throw new GrammarException(String.format("Rule '%s' doesn't exist\n", export)); + } + } + grammar.setExportedRules(exportedRules); return grammar; @@ -87,8 +99,6 @@ public class RGrammarBuilder { throw new NullPointerException("init must not be null"); } else if (init.equals("")) { throw new IllegalArgumentException("The empty string is not a valid rule name"); - } else if (!rules.containsKey(init)) { - throw new IllegalArgumentException(String.format("The rule '%s' doesn't exist", init)); } initialRule = init; @@ -108,8 +118,6 @@ public class RGrammarBuilder { throw new NullPointerException("Export name must not be null"); } else if (export.equals("")) { throw new NullPointerException("The empty string is not a valid rule name"); - } else if(!rules.containsKey(export)) { - throw new IllegalArgumentException(String.format("The rule '%s' doesn't exist", rules)); } exportedRules.add(export); diff --git a/src/main/java/bjc/rgens/parser/RGrammarParser.java b/src/main/java/bjc/rgens/parser/RGrammarParser.java index 3a357b1..506256d 100755 --- a/src/main/java/bjc/rgens/parser/RGrammarParser.java +++ b/src/main/java/bjc/rgens/parser/RGrammarParser.java @@ -182,6 +182,7 @@ public class RGrammarParser { * Comment block. * * @TODO 10/11/17 Ben Culkin :GrammarComment + * * Attach these to the grammar somehow so that they * can be re-output during formatting. */ diff --git a/src/main/java/bjc/rgens/parser/elements/CaseElement.java b/src/main/java/bjc/rgens/parser/elements/CaseElement.java index d74ab52..522de7a 100755 --- a/src/main/java/bjc/rgens/parser/elements/CaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/CaseElement.java @@ -1,17 +1,14 @@ package bjc.rgens.parser.elements; +import bjc.rgens.parser.GenerationState; 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 { +public abstract class CaseElement { /** * The possible types of an element. * @@ -34,8 +31,6 @@ public class CaseElement { } /* 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. */ @@ -53,12 +48,17 @@ public class CaseElement { @Override public String toString() { - switch (type) { - default: - return String.format("Unknown type '%s'", type); - } + return String.format("Unknown type '%s'", type); } + /** + * Generate this case element. + * + * @param state + * The current state of generation. + */ + public abstract void generate(GenerationState state); + /** * Create a case element from a string. * @@ -72,8 +72,11 @@ public class CaseElement { throw new NullPointerException("Case part cannot be null"); } - if (csepart.matches(SPECIAL_CASELEM)) { - /* Handle special cases. */ + if (csepart.matches("\\{[^}]+\\}")) { + /* + * Handle special cases. + * + */ String specialBody = csepart.substring(1, csepart.length() - 1); System.out.printf("\t\tTRACE: special body is '%s'\n", specialBody); @@ -88,6 +91,12 @@ public 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]); } else if (specialBody.matches("\\S+=\\S+")) { /* Handle regular variable definitions. */ @@ -100,23 +109,28 @@ public class CaseElement { } return new LitVariableCaseElement(parts[0], parts[1]); - } else if (specialBody.matches("{empty}")) { + } 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); + } else if (csepart.matches("\\[[^\\]]+\\]")) { + String rawCase = csepart.substring(1, csepart.length() - 1); - int firstNum = Integer.parseInt(rawRange.substring(0, rawRange.indexOf('.'))); - int secondNum = Integer.parseInt(rawRange.substring(rawRange.lastIndexOf('.') + 1)); + if (rawCase.matches("\\d+\\.\\.\\d+")) { + int firstNum = Integer.parseInt(rawCase.substring(0, rawCase.indexOf('.'))); + int secondNum = Integer.parseInt(rawCase.substring(rawCase.lastIndexOf('.') + 1)); return new RangeCaseElement(firstNum, secondNum); } + /* + * @NOTE + * + * Once the rule element execution has been refactored, + * pass rawCase instead. + */ return new RuleCaseElement(csepart); } else { return new LiteralCaseElement(csepart); @@ -144,4 +158,4 @@ public class CaseElement { return false; return true; } -} \ No newline at end of file +} diff --git a/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java index 30925e2..8598fbd 100755 --- a/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/ExpVariableCaseElement.java @@ -1,7 +1,45 @@ package bjc.rgens.parser.elements; +import bjc.rgens.parser.GenerationState; +import bjc.rgens.parser.GrammarException; +import bjc.rgens.parser.RGrammar; +import bjc.rgens.parser.RuleCase; + public class ExpVariableCaseElement extends VariableCaseElement { public ExpVariableCaseElement(String name, String def) { super(name, def, true); } + + @Override + public void generate(GenerationState state) { + GenerationState newState = state.newBuf(); + + if (state.rules.containsKey(varDef)) { + RuleCase destCase = state.rules.get(varDef).getCase(); + + state.gram.generateCase(destCase, newState); + } else if (state.importRules.containsKey(varDef)) { + RGrammar destGrammar = state.importRules.get(varDef); + + 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. + */ + newState.contents = new StringBuilder(res); + } else { + String msg = String.format("No rule '%s' defined", varDef); + throw new GrammarException(msg); + } + + state.vars.put(varName, newState.contents.toString()); + + } } diff --git a/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java index 11035b1..91b8a2b 100755 --- a/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java @@ -1,7 +1,13 @@ package bjc.rgens.parser.elements; +import bjc.rgens.parser.GenerationState; + public class LitVariableCaseElement extends VariableCaseElement { public LitVariableCaseElement(String name, String def) { super(name, def, false); } + + public void generate(GenerationState state) { + state.vars.put(varName, varDef); + } } diff --git a/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java b/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java index d96a32d..18c3482 100755 --- a/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java @@ -1,7 +1,14 @@ package bjc.rgens.parser.elements; +import bjc.rgens.parser.GenerationState; + public class LiteralCaseElement extends StringCaseElement { public LiteralCaseElement(String vl) { super(vl, true); } + + @Override + public void generate(GenerationState state) { + state.contents.append(val); + } } diff --git a/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java index d98bc61..7cebde9 100755 --- a/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java @@ -1,5 +1,7 @@ package bjc.rgens.parser.elements; +import bjc.rgens.parser.GenerationState; + public class RangeCaseElement extends CaseElement { public final int begin; public final int end; @@ -11,6 +13,13 @@ public class RangeCaseElement extends CaseElement { end = en; } + public void generate(GenerationState state) { + int val = state.rnd.nextInt(end - begin); + val += begin; + + state.contents.append(val); + } + @Override public int hashCode() { final int prime = 31; diff --git a/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java index f4d3512..d91bebc 100755 --- a/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java @@ -1,7 +1,129 @@ package bjc.rgens.parser.elements; +import bjc.rgens.parser.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class RuleCaseElement extends StringCaseElement { + private static Pattern NAMEVAR_PATTERN = Pattern.compile("\\$(\\w+)"); + public RuleCaseElement(String vl) { super(vl, false); } + + @Override + public void generate(GenerationState state) { + /* + * @NOTE + * + * :VarRefactor + * + * Figure out if this can be refactored in some way. + */ + String refersTo = val; + + GenerationState newState = state.newBuf(); + + if (refersTo.contains("$")) { + /* Parse variables */ + String refBody = refersTo.substring(1, refersTo.length() - 1); + + if (refBody.contains("-")) { + /* Handle dependent rule names. */ + StringBuffer nameBuffer = new StringBuffer(); + + Matcher nameMatcher = NAMEVAR_PATTERN.matcher(refBody); + + while (nameMatcher.find()) { + String var = nameMatcher.group(1); + + if (!state.vars.containsKey(var)) { + String msg = String.format("No variable '%s' defined", var); + throw new GrammarException(msg); + } + + String name = state.vars.get(var); + + if (name.contains(" ")) { + throw new GrammarException("Variables substituted into names cannot contain spaces"); + } else if (name.equals("")) { + throw new GrammarException("Variables substituted into names cannot be empty"); + } + + nameMatcher.appendReplacement(nameBuffer, name); + } + + nameMatcher.appendTail(nameBuffer); + + refersTo = "[" + nameBuffer.toString() + "]"; + } else { + /* Handle string references. */ + if (refBody.equals("$")) { + throw new GrammarException("Cannot refer to unnamed variables"); + } + + String key = refBody.substring(1); + + if (!state.vars.containsKey(key)) { + String msg = String.format("No variable '%s' defined", key); + throw new GrammarException(msg); + } + + state.contents.append(state.vars.get(key)); + + return; + } + } + + if (refersTo.startsWith("[^")) { + refersTo = "[" + refersTo.substring(2); + + RGrammar dst = state.importRules.get(refersTo); + + newState.swapGrammar(dst); + + /* :Postprocessing */ + newState.contents = new StringBuilder(dst.generate(refersTo, state.rnd, state.vars)); + } else if (state.rules.containsKey(refersTo)) { + RuleCase cse = state.rules.get(refersTo).getCase(state.rnd); + + state.gram.generateCase(cse, newState); + } else if (state.importRules.containsKey(refersTo)) { + RGrammar dst = state.importRules.get(refersTo); + + newState.swapGrammar(dst); + + /* :Postprocessing */ + newState.contents = new StringBuilder(dst.generate(refersTo, state.rnd, state.vars)); + } else { + /* + * @TODO 5/29/18 Ben Culkin :RuleSuggesting + * + * Re-get this working again. + */ + /* + if (ruleSearcher != null) { + Set> results = ruleSearcher.search(refersTo, MAX_DISTANCE); + + String[] resArray = results.stream().map(Match::getMatch).toArray((i) -> new String[i]); + + String msg = String.format("No rule '%s' defined (perhaps you meant %s?)", refersTo, + StringUtils.toEnglishList(resArray, false)); + + throw new GrammarException(msg); + } + */ + + String msg = String.format("No rule '%s' defined", refersTo); + throw new GrammarException(msg); + } + + if (refersTo.contains("+")) { + /* Rule names with pluses in them get space-flattened */ + state.contents.append(newState.contents.toString().replaceAll("\\s+", "")); + } else { + state.contents.append(newState.contents.toString()); + } + } } diff --git a/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java b/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java index 0e64fd3..61ad48a 100755 --- a/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java @@ -1,6 +1,6 @@ package bjc.rgens.parser.elements; -public class StringCaseElement extends CaseElement { +public abstract class StringCaseElement extends CaseElement { public final String val; protected StringCaseElement(String vl, boolean isLiteral) { diff --git a/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java index 920445a..3e691d9 100755 --- a/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/VariableCaseElement.java @@ -1,6 +1,6 @@ package bjc.rgens.parser.elements; -public class VariableCaseElement extends CaseElement { +public abstract class VariableCaseElement extends CaseElement { /** * The name of the variable this element defines. */ -- cgit v1.2.3