diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-07-23 20:10:44 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-07-23 20:10:44 -0300 |
| commit | 12fd9362751871711fad12fea01f39a38c2f32e8 (patch) | |
| tree | 8e27c8ec74e4a0010bcb186fc0124b0a99299dbc /RGens/src/main/java/bjc/rgens | |
| parent | f9d0cc26c52e462e9d0384cb80e8698af2aecf36 (diff) | |
Simplify parser.
The parser no longer uses a modal builder, so grammar blocks could now
be done in a parallel manner
Diffstat (limited to 'RGens/src/main/java/bjc/rgens')
5 files changed, 50 insertions, 112 deletions
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java index 3606d40..ada1a57 100644 --- a/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java +++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java @@ -281,7 +281,7 @@ public class RGrammar { if (!state.vars.containsKey(var)) { String msg = String.format("No variable '%s' defined", var); - throw new GrammarException(); + throw new GrammarException(msg); } String name = state.vars.get(var); @@ -312,7 +312,7 @@ public class RGrammar { if (!state.vars.containsKey(key)) { String msg = String.format("No variable '%s' defined", key); - throw new GrammarException(); + throw new GrammarException(msg); } state.contents.append(state.vars.get(key)); @@ -339,11 +339,11 @@ public class RGrammar { String msg = String.format("No rule '%s' defined (perhaps you meant %s?)", refersTo, StringUtils.toEnglishList(resArray, false)); - throw new GrammarException(); + throw new GrammarException(msg); } String msg = String.format("No rule '%s' defined", refersTo); - throw new GrammarException(); + throw new GrammarException(msg); } if (refersTo.contains("+")) { @@ -385,7 +385,7 @@ public class RGrammar { throw new GrammarException("The empty string is not a valid rule name"); } else if (!rules.containsKey(initRule)) { String msg = String.format("No rule '%s' local to this grammar defined.", initRule); - throw new GrammarException(); + throw new GrammarException(msg); } initialRule = initRule; @@ -405,7 +405,7 @@ public class RGrammar { if (!rules.containsKey(rname)) { String msg = String.format("No rule '%s' local to this grammar defined", initialRule); - throw new GrammarException(); + throw new GrammarException(msg); } res.add(rules.get(rname)); diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java index b4f9f45..bd8ba84 100644 --- a/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java +++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java @@ -17,10 +17,6 @@ import static bjc.rgens.newparser.RuleCase.CaseType.*; * */ public class RGrammarBuilder { - private IList<CaseElement> currentCase; - - private Rule currRule; - private Map<String, Rule> rules; private Set<String> exportedRules; @@ -34,30 +30,23 @@ public class RGrammarBuilder { rules = new HashMap<>(); exportedRules = new HashSet<>(); - - currentCase = new FunctionalList<>(); } - /** - * Starts a rule with the provided name. - * - * If the rule already exists, it will be opened for adding additional - * cases instead. - * - * @param rName - * The name of the rule currently being built. - * - * @throws IllegalArgumentException - * If the rule name is the empty string. - */ - public void startRule(String rName) { - if (rName == null) { + public Rule getOrCreateRule(String rName) { + if(rName == null) throw new NullPointerException("Rule name must not be null"); - } else if (rName.equals("")) { + else if(rName.equals("")) throw new IllegalArgumentException("The empty string is not a valid rule name"); - } - currRule = new Rule(rName); + if(rules.containsKey(rName)) + return rules.get(rName); + else { + Rule ret = new Rule(rName); + + rules.put(rName, ret); + + return ret; + } } /** @@ -76,70 +65,6 @@ public class RGrammarBuilder { } /** - * Adds a case part to this rule. - * - * <h2>Case part formatting</h2> - * <dl> - * <dt>Rule Reference</dt> - * <dd>Rule references are marked by being surrounded with square - * brackets (the square brackets are part of the rule's name)</dd> - * <dt>Literal Strings</dt> - * <dd>Literal strings are the default case part type.</dd> - * </dl> - * - * @param csepart - */ - public void addCasePart(String csepart) { - CaseElement element = CaseElement.createElement(csepart); - - currentCase.add(element); - } - - /** - * Finalizes editing a rule. - * - * Saves the rule to the rule map. - * - * @throws IllegalStateException - * Must be invoked while a rule is being edited. - */ - public void finishRule() { - if (currRule == null) { - throw new IllegalStateException("Must start a rule before finishing one"); - } - - rules.put(currRule.name, currRule); - } - - /** - * Finishes the current case being edited. - * - * @throws IllegalStateException - * Must be invoked while a rule is being edited. - */ - public void finishCase() { - if (currRule == null) { - throw new IllegalStateException("Must start a rule before finishing a case"); - } - - currRule.addCase(new RuleCase(NORMAL, currentCase)); - - currentCase = new FunctionalList<>(); - } - - /** - * Begins a case for the current rule. - * - * @throws IllegalStateException - * Must be invoked while a rule is being edited. - */ - public void beginCase() { - if (currRule == null) { - throw new IllegalStateException("Must start a rule before adding cases"); - } - } - - /** * Set the initial rule of the grammar. * * @param init diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java index 22e0ca7..0c2e3d9 100644 --- a/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java +++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java @@ -1,5 +1,7 @@ package bjc.rgens.newparser; +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.IList; import bjc.utils.funcutils.TriConsumer; import bjc.utils.ioutils.blocks.Block; import bjc.utils.ioutils.blocks.BlockReader; @@ -17,6 +19,8 @@ import java.util.Map; * */ public class RGrammarParser { + public static final boolean DEBUG = false; + /* * Templates for level-dependent delimiters. */ @@ -101,6 +105,9 @@ public class RGrammarParser { RGrammarBuilder build = new RGrammarBuilder(); reader.forEachBlock((block) -> { + if(DEBUG) + System.err.printf("Handling top-level block (%s)\n", block); + handleBlock(build, block.contents, 0); }); @@ -145,6 +152,8 @@ public class RGrammarParser { } else if (blockType.equalsIgnoreCase("where")) { handleWhereBlock(block, build, level); } else if (blockType.equalsIgnoreCase("#")) { + if(DEBUG) + System.err.printf("Handled comment block (%s)\n", block); /* * Comment block. * @@ -167,6 +176,9 @@ public class RGrammarParser { try (BlockReader pragmaReader = new SimpleBlockReader(dlm, new StringReader(block))) { try { pragmaReader.forEachBlock((pragma) -> { + if(DEBUG) + System.err.printf("Handled pragma block (%s)\n", pragma); + String pragmaContents = pragma.contents; int pragmaSep = pragmaContents.indexOf(' '); @@ -212,13 +224,16 @@ public class RGrammarParser { if (pragmas.containsKey(pragmaName)) { try { + if(DEBUG) + System.err.printf("Handled pragma '%s'\n", pragmaName); + pragmas.get(pragmaName).accept(pragmaBody, build, level); } catch (GrammarException gex) { String msg = String.format("Error in pragma '%s'", pragmaName); throw new GrammarException(msg, gex); } } else { - String msg = String.format("Unknown pragma '%s'", pragmaName) + String msg = String.format("Unknown pragma '%s'", pragmaName); throw new GrammarException(msg); } } @@ -228,8 +243,8 @@ public class RGrammarParser { */ private static void handleRuleBlock(String ruleBlock, RGrammarBuilder build, int level) throws GrammarException { - String msg = String.format(TMPL_RULEDECL_BLOCK_DELIM, level); - try (BlockReader ruleReader = new SimpleBlockReaderformat(msg, new StringReader(ruleBlock)) { + String dlm = String.format(TMPL_RULEDECL_BLOCK_DELIM, level); + try (BlockReader ruleReader = new SimpleBlockReader(dlm, new StringReader(ruleBlock))) { try { if (ruleReader.hasNextBlock()) { /* @@ -239,20 +254,16 @@ public class RGrammarParser { Block declBlock = ruleReader.getBlock(); String declContents = declBlock.contents; - handleRuleDecl(build, declContents); + Rule rl = handleRuleDecl(build, declContents); ruleReader.forEachBlock((block) -> { - handleRuleCase(block.contents, build); + handleRuleCase(block.contents, build, rl); }); - - build.finishRule(); } else { /* * Rule with a declaration followed by a single case. */ handleRuleDecl(build, ruleBlock); - - build.finishRule(); } } catch (GrammarException gex) { String msg = String.format("Error in rule case (%s)", ruleReader.getBlock()); @@ -266,7 +277,7 @@ public class RGrammarParser { /* * Handle a rule declaration and its initial case. */ - private static void handleRuleDecl(RGrammarBuilder build, String declContents) { + private static Rule handleRuleDecl(RGrammarBuilder build, String declContents) { int declSep = declContents.indexOf("\u2192"); if (declSep == -1) { @@ -292,16 +303,18 @@ public class RGrammarParser { throw new GrammarException("The empty string is not a valid rule name"); } - build.startRule(ruleName); + Rule rul = build.getOrCreateRule(ruleName); + + handleRuleCase(ruleBody, build, rul); - handleRuleCase(ruleBody, build); + return rul; } /* * Handle a single case of a rule. */ - private static void handleRuleCase(String cse, RGrammarBuilder build) { - build.beginCase(); + private static void handleRuleCase(String cse, RGrammarBuilder build, Rule rul) { + IList<CaseElement> caseParts = new FunctionalList<>(); for (String csepart : cse.split(" ")) { String partToAdd = csepart.trim(); @@ -312,10 +325,10 @@ public class RGrammarParser { if (partToAdd.equals("")) continue; - build.addCasePart(partToAdd); + caseParts.add(CaseElement.createElement(partToAdd)); } - build.finishCase(); + rul.addCase(new RuleCase(RuleCase.CaseType.NORMAL, caseParts)); } /* diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarSet.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarSet.java index d1cd1c2..4aace76 100644 --- a/RGens/src/main/java/bjc/rgens/newparser/RGrammarSet.java +++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarSet.java @@ -124,7 +124,7 @@ public class RGrammarSet { } else if (exportName.equals("")) { throw new IllegalArgumentException("The empty string is not a valid rule name"); } else if (!exportedRules.containsKey(exportName)) { - String msg = String.format("No export with name '%s' defined", exportName) + String msg = String.format("No export with name '%s' defined", exportName); throw new IllegalArgumentException(msg); } @@ -151,7 +151,7 @@ public class RGrammarSet { } else if (exportName.equals("")) { throw new IllegalArgumentException("The empty string is not a valid rule name"); } else if (!exportedRules.containsKey(exportName)) { - String msg = String.format("No export with name '%s' defined", exportName) + String msg = String.format("No export with name '%s' defined", exportName); throw new IllegalArgumentException(msg); } diff --git a/RGens/src/main/java/bjc/rgens/text/markov/Markov.java b/RGens/src/main/java/bjc/rgens/text/markov/Markov.java index 5b74b8c..b4564c4 100644 --- a/RGens/src/main/java/bjc/rgens/text/markov/Markov.java +++ b/RGens/src/main/java/bjc/rgens/text/markov/Markov.java @@ -1,4 +1,4 @@ -p*ackage bjc.rgens.text.markov; +package bjc.rgens.text.markov; import java.util.Map.Entry; import java.util.*; |
