From e9e0ca7bfe722375e7ccb25d2bafbe395b6c6a59 Mon Sep 17 00:00:00 2001 From: Ben Culkin Date: Tue, 6 Oct 2020 19:16:26 -0400 Subject: Info cleanup --- src/main/java/bjc/rgens/parser/RGrammarParser.java | 666 ++++++++++++--------- 1 file changed, 370 insertions(+), 296 deletions(-) (limited to 'src/main/java/bjc/rgens/parser/RGrammarParser.java') diff --git a/src/main/java/bjc/rgens/parser/RGrammarParser.java b/src/main/java/bjc/rgens/parser/RGrammarParser.java index bfbdb98..b25d036 100755 --- a/src/main/java/bjc/rgens/parser/RGrammarParser.java +++ b/src/main/java/bjc/rgens/parser/RGrammarParser.java @@ -6,7 +6,6 @@ import java.io.StringReader; import java.util.ArrayList; import java.util.List; -import bjc.rgens.parser.RGrammarBuilder.AffixType; import bjc.rgens.parser.elements.CaseElement; import bjc.rgens.parser.elements.ChanceCaseElement; import bjc.rgens.parser.elements.SerialCaseElement; @@ -25,7 +24,7 @@ import bjc.utils.ioutils.blocks.SimpleBlockReader; */ public class RGrammarParser { /** - * Whether we are in debug mode or not. + * Whether we are in debug mode or not. */ public static final boolean DEBUG = false; /** @@ -37,19 +36,21 @@ public class RGrammarParser { * Templates for level-dependent delimiters. */ /* Pragma block delimiter. */ - private static final String TMPL_PRAGMA_BLOCK_DELIM = "\\R\\t{%d}(?!\\t)"; + private static final String TMPL_PRAGMA_BLOCK_DELIM = "\\R\\t{%d}(?!\\t)"; /* Rule declaration block delimiter. */ private static final String TMPL_RULEDECL_BLOCK_DELIM = "\\R\\t\\t{%d}"; /* Where block delimiter. */ - private static final String TMPL_WHERE_BLOCK_DELIM = "\\R\\t{%d}(?:in|end)\\R"; + private static final String TMPL_WHERE_BLOCK_DELIM = "\\R\\t{%d}(?:in|end)\\R"; /* Top-level block delimiter. */ private static final String TMPL_TOPLEVEL_BLOCK_DELIM = "\\R\\t{%d}\\.?\\R"; - private static void doAffixWith(String body, RGrammarBuilder build, int level, AffixType afxType, ITree errs) { + private static void doAffixWith(String body, RGrammarBuilder build, int level, + AffixType afxType, ITree errs) { int idx = body.indexOf(" "); if (idx == -1) { - String fmt = "ERROR: Takes at least two arguments, the name of the rule to affix, then what to affix it with\n\tThis can be more than one token, to get them affixed as a group"; + String fmt + = "ERROR: Takes at least two arguments, the name of the rule to affix, then what to affix it with\n\tThis can be more than one token, to get them affixed as a group"; String msg = String.format(fmt, afxType.toString().toLowerCase()); @@ -67,7 +68,8 @@ public class RGrammarParser { build.affixWith(rName, elms, afxType, errs); } - private static void doAutoVar(List bits, RGrammarBuilder build, int level, boolean isRule, ITree errs) { + private static void doAutoVar(List bits, RGrammarBuilder build, int level, + boolean isRule, ITree errs) { if (bits.size() < 1) { String msg = "Must specify name of variable and definition to autovivify"; @@ -84,7 +86,9 @@ public class RGrammarParser { CaseElement elm = elmList.get(0); if (elmList.size() > 1) { - String msg = String.format("WARN: Ignoring %d additional elements for autovivify: %s", elmList.size(), elmList.subList(1, elmList.size())); + String msg = String.format( + "WARN: Ignoring %d additional elements for autovivify: %s", + elmList.size(), elmList.subList(1, elmList.size())); errs.addChild(msg); @@ -92,7 +96,9 @@ public class RGrammarParser { } if (!(elm instanceof VariableDefCaseElement)) { - String msg = String.format("ERROR: Autovivify expression must be a variable defn. (expr. %s)", elm); + String msg = String.format( + "ERROR: Autovivify expression must be a variable defn. (expr. %s)", + elm); errs.addChild(msg); @@ -100,10 +106,12 @@ public class RGrammarParser { } { - String name = ((VariableDefCaseElement)elm).varName; + String name = ((VariableDefCaseElement) elm).varName; - if (isRule) build.addAutoRlVar(name, elm); - else build.addAutoVar(name, elm); + if (isRule) + build.addAutoRlVar(name, elm); + else + build.addAutoVar(name, elm); } } @@ -111,15 +119,19 @@ public class RGrammarParser { * Read a {@link RGrammar} from an input stream. * * @param is - * The input stream to read from. + * The input stream to read from. + * @param lopts + * The options to use for loading. + * @param errs + * The place to put errors. * - * @return - * The grammar represented by the stream. + * @return The grammar represented by the stream. * * @throws GrammarException - * Thrown if the grammar has a syntax error. + * Thrown if the grammar has a syntax error. */ - public static RGrammar readGrammar(Reader is, LoadOptions lopts, ITree errs) throws GrammarException { + public static RGrammar readGrammar(Reader is, LoadOptions lopts, ITree errs) + throws GrammarException { String dlm = String.format(TMPL_TOPLEVEL_BLOCK_DELIM, 0); try (BlockReader reader = new SimpleBlockReader(dlm, is)) { @@ -129,29 +141,35 @@ public class RGrammarParser { return null; } - RGrammarBuilder build = new RGrammarBuilder(); + RGrammarBuilder build = new RGrammarBuilder(); - for(Block block : reader) { - if(lopts.doTrace) { - String msg = String.format("TRACE: Handling top-level block (%s)\n", block); + for (Block block : reader) { + if (lopts.doTrace) { + String msg = String.format("TRACE: Handling top-level block (%s)\n", + block); - errs.addChild(msg); - } + errs.addChild(msg); + } - String msg = String.format("INFO: Block %d (%d-%d) (offset %d, %d-%d)", block.blockNo, block.startLine, block.endLine, block.lineOffset, block.lineOffset + block.startLine, block.lineOffset + block.endLine); + String msg = String.format("INFO: Block %d (%d-%d) (offset %d, %d-%d)", + block.blockNo, block.startLine, block.endLine, block.lineOffset, + block.lineOffset + block.startLine, + block.lineOffset + block.endLine); - ITree kid = new Tree<>(msg); + ITree kid = new Tree<>(msg); - handleBlock(build, block.contents, 0, block.startLine, lopts, kid); + handleBlock(build, block.contents, 0, block.startLine, lopts, kid); - if (kid.size() > 0) errs.addChild(kid); - } + if (kid.size() > 0) + errs.addChild(kid); + } - if(lopts.doTrace) { - errs.addChild(String.format("TRACE: Ended at line %d ", reader.getBlock().endLine)); - } + if (lopts.doTrace) { + errs.addChild(String.format("TRACE: Ended at line %d ", + reader.getBlock().endLine)); + } - return build.toRGrammar(); + return build.toRGrammar(); } catch (IOException ioex) { String msg = String.format("ERROR: Unknown I/O error: %s", ioex.getMessage()); @@ -161,21 +179,24 @@ public class RGrammarParser { return null; } - /* - * Throughout these, level indicates the nesting level of that construct, - * and lineOffset indicates the total number of lines to adjust the block - * line numbers by. + /* + * Throughout these, level indicates the nesting level of that construct, and + * lineOffset indicates the total number of lines to adjust the block line + * numbers by. */ /* Handles an arbitrary block. */ - private static void handleBlock(RGrammarBuilder build, String block, int level, int lineOffset, LoadOptions lopts, ITree errs) { + private static void handleBlock(RGrammarBuilder build, String block, int level, + int lineOffset, LoadOptions lopts, ITree errs) { /* Discard empty blocks. */ - if (block.equals("") || block.matches("\\R")) return; + if (block.equals("") || block.matches("\\R")) + return; int typeSep = block.indexOf(' '); if (typeSep == -1) { - errs.addChild("ERROR: A block must start with a introducer, followed by a space, then the rest of the block"); + errs.addChild( + "ERROR: A block must start with a introducer, followed by a space, then the rest of the block"); } String blockType = block.substring(0, typeSep).trim(); @@ -187,7 +208,7 @@ public class RGrammarParser { } else if (blockType.equalsIgnoreCase("where")) { handleWhereBlock(block, build, level, lineOffset, lopts, errs); } else if (blockType.startsWith("#")) { - if(lopts.doTrace) { + if (lopts.doTrace) { String msg = String.format("TRACE: Handled comment block (%s)\n", block); errs.addChild(msg); @@ -198,8 +219,8 @@ public class RGrammarParser { * * @TODO 10/11/17 Ben Culkin :GrammarComment * - * Attach these to the grammar somehow so that they - * can be re-output during formatting. + * Attach these to the grammar somehow so that they can be re-output during + * formatting. */ return; } else { @@ -210,14 +231,16 @@ public class RGrammarParser { } /* Handle reading a block of pragmas. */ - private static void handlePragmaBlock(String block, RGrammarBuilder build, int level, int lineOffset, LoadOptions lopts, ITree errs) { + private static void handlePragmaBlock(String block, RGrammarBuilder build, int level, + int lineOffset, LoadOptions lopts, ITree errs) { String dlm = String.format(TMPL_PRAGMA_BLOCK_DELIM, level); - try (BlockReader pragmaReader = new SimpleBlockReader(dlm, new StringReader(block))) { - for(Block pragma : pragmaReader) { + try (BlockReader pragmaReader + = new SimpleBlockReader(dlm, new StringReader(block))) { + for (Block pragma : pragmaReader) { pragma.lineOffset = lineOffset; - if(lopts.doTrace) { + if (lopts.doTrace) { System.err.printf("TRACE: Handled pragma block (%s)\n", pragma); } @@ -226,41 +249,48 @@ public class RGrammarParser { int pragmaSep = pragmaContents.indexOf(' '); if (pragmaSep == -1) { - String msg = "ERROR: A pragma invocation must consist of the word pragma, followed by a space, then the body of the pragma"; + String msg + = "ERROR: A pragma invocation must consist of the word pragma, followed by a space, then the body of the pragma"; errs.addChild(msg); return; } String pragmaLeader = pragmaContents.substring(0, pragmaSep); - String pragmaBody = pragmaContents.substring(pragmaSep + 1); + String pragmaBody = pragmaContents.substring(pragmaSep + 1); if (!pragmaLeader.equalsIgnoreCase("pragma")) { - String msg = String.format("ERROR: Illegal line leader in pragma block: '%s'", pragmaLeader); + String msg = String.format( + "ERROR: Illegal line leader in pragma block: '%s'", + pragmaLeader); errs.addChild(msg); return; } - handlePragma(pragmaBody, build, level, pragma.startLine + lineOffset, lopts, errs); + handlePragma(pragmaBody, build, level, pragma.startLine + lineOffset, + lopts, errs); } } catch (IOException ioex) { - String msg = String.format("ERROR: Unknown I/O error in pragma block: %s", ioex.getMessage()); + String msg = String.format("ERROR: Unknown I/O error in pragma block: %s", + ioex.getMessage()); errs.addChild(msg); } } /* Handle an individual pragma in a block. */ - private static void handlePragma(String pragma, RGrammarBuilder build, int level, int lineOffset, LoadOptions lopts, ITree errs) { + private static void handlePragma(String pragma, RGrammarBuilder build, int level, + int lineOffset, LoadOptions lopts, ITree errs) { int bodySep = pragma.indexOf(' '); - if (bodySep == -1) bodySep = pragma.length(); + if (bodySep == -1) + bodySep = pragma.length(); String pragmaName = pragma.substring(0, bodySep); String pragmaBody = pragma.substring(bodySep + 1); - if(lopts.doTrace) { + if (lopts.doTrace) { String msg = String.format("TRACE: Handled pragma '%s'\n", pragmaName); errs.addChild(msg); @@ -273,242 +303,231 @@ public class RGrammarParser { ITree kid = new Tree<>(fmt); switch (pragmaName) { - case "initial-rule": - { - if (bits.size() != 1) { - kid.addChild("ERROR: Must specify initial rule"); - - break; - } + case "initial-rule": { + if (bits.size() != 1) { + kid.addChild("ERROR: Must specify initial rule"); - build.setInitialRule(bits.get(0), kid); + break; } - break; - case "grammar-name": - { - if (bits.size() != 1) { - kid.addChild("ERROR: Must specify grammar name"); - break; - } + build.setInitialRule(bits.get(0), kid); + } + break; + case "grammar-name": { + if (bits.size() != 1) { + kid.addChild("ERROR: Must specify grammar name"); - build.name = bits.get(0); + break; } + + build.name = bits.get(0); + } break; - case "despace-rule": - { - if (bits.size() < 1) { - kid.addChild("ERROR: Must specify at least one rule to despace"); + case "despace-rule": { + if (bits.size() < 1) { + kid.addChild("ERROR: Must specify at least one rule to despace"); - break; - } + break; + } - for(String bit : bits) { - build.despaceRule(bit, kid, lopts.doTrace); - } + for (String bit : bits) { + build.despaceRule(bit, kid, lopts.doTrace); } + } break; - case "export-rule": - { - if(bits.size() < 1) { - kid.addChild("ERROR: Must specify rules to export"); + case "export-rule": { + if (bits.size() < 1) { + kid.addChild("ERROR: Must specify rules to export"); - break; - } + break; + } - for (String export : bits) { - build.addExport(export); - } + for (String export : bits) { + build.addExport(export); } + } break; - case "recur-limit": - { - if(bits.size() != 2) { - kid.addChild("ERROR: Takes two arguments: the name of the rule to set the limit for, and the new value of the limit"); + case "recur-limit": { + if (bits.size() != 2) { + kid.addChild( + "ERROR: Takes two arguments: the name of the rule to set the limit for, and the new value of the limit"); - break; - } - - if(!bits.get(1).matches("\\A\\d+\\Z")) { - kid.addChild("ERROR: Limit value must be an integer"); + break; + } - break; - } + if (!bits.get(1).matches("\\A\\d+\\Z")) { + kid.addChild("ERROR: Limit value must be an integer"); - build.setRuleRecur(bits.get(0), Integer.parseInt(bits.get(1)), kid); + break; } - break; - case "enable-weight": - { - if(bits.size() != 1) { - kid.addChild("ERROR: Takes one argument: the name of the rule to enable standard weighting for"); - } - build.setWeight(bits.get(0), kid); - } + build.setRuleRecur(bits.get(0), Integer.parseInt(bits.get(1)), kid); + } break; - case "enable-descent": - { - if(bits.size() != 2) { - kid.addChild("ERROR: Takes two arguments: The name of the rule to set to descent mode, and the value of the descent factor"); + case "enable-weight": { + if (bits.size() != 1) { + kid.addChild( + "ERROR: Takes one argument: the name of the rule to enable standard weighting for"); + } - break; - } + build.setWeight(bits.get(0), kid); + } + break; + case "enable-descent": { + if (bits.size() != 2) { + kid.addChild( + "ERROR: Takes two arguments: The name of the rule to set to descent mode, and the value of the descent factor"); - if(!bits.get(1).matches("\\A\\d+\\Z")) { - kid.addChild("ERROR: Factor value must be an integer"); + break; + } - break; - } + if (!bits.get(1).matches("\\A\\d+\\Z")) { + kid.addChild("ERROR: Factor value must be an integer"); - build.setDescent(bits.get(0), Integer.parseInt(bits.get(1)), kid); + break; } + + build.setDescent(bits.get(0), Integer.parseInt(bits.get(1)), kid); + } break; - case "enable-binomial": - { - // @NOTE 9/4/18 - // - // This can be kind of hard to read right off. Is there - // a format to put stuff in that looks better and is - // more readable? - - if(bits.size() != 4) { - kid.addChild("ERROR: Takes four arguments: the name of the rule to set the binomial factors for, and the three binomial parameters (target, bound, trials) (target/bound chance of success)"); - - break; - } + case "enable-binomial": { + // @NOTE 9/4/18 + // + // This can be kind of hard to read right off. Is there + // a format to put stuff in that looks better and is + // more readable? + + if (bits.size() != 4) { + kid.addChild( + "ERROR: Takes four arguments: the name of the rule to set the binomial factors for, and the three binomial parameters (target, bound, trials) (target/bound chance of success)"); + + break; + } - if(!bits.get(1).matches("\\A\\d+\\Z")) { - kid.addChild("ERROR: Target value must be an integer"); + if (!bits.get(1).matches("\\A\\d+\\Z")) { + kid.addChild("ERROR: Target value must be an integer"); - break; - } + break; + } - if(!bits.get(2).matches("\\A\\d+\\Z")) { - kid.addChild("ERROR: Bound value must be an integer"); + if (!bits.get(2).matches("\\A\\d+\\Z")) { + kid.addChild("ERROR: Bound value must be an integer"); - break; - } + break; + } - if(!bits.get(3).matches("\\A\\d+\\Z")) { - kid.addChild("ERROR: Trials value must be an integer"); + if (!bits.get(3).matches("\\A\\d+\\Z")) { + kid.addChild("ERROR: Trials value must be an integer"); - break; - } - - build.setBinomial(bits.get(0), Integer.parseInt(bits.get(1)), Integer.parseInt(bits.get(2)), Integer.parseInt(bits.get(3)), kid); + break; } - break; - case "find-replace-rule": - { - /* - * @NOTE 4/9/18 - * - * Consider if we want to replace this with something more akin - * to the `definer` feature from DiceLang. This will work fine - * in most cases, but there are some cases where you'd want the - * extra power. No examples are apparent at the moment. - */ - if(bits.size() != 3) { - kid.addChild("ERROR: Takes three arguments: the name of the rule to process, then the find/replace pair to apply after the rule has been generated."); - break; - } + build.setBinomial(bits.get(0), Integer.parseInt(bits.get(1)), + Integer.parseInt(bits.get(2)), Integer.parseInt(bits.get(3)), kid); + } + break; + case "find-replace-rule": { + /* + * @NOTE 4/9/18 + * + * Consider if we want to replace this with something more akin to the + * `definer` feature from DiceLang. This will work fine in most cases, but + * there are some cases where you'd want the extra power. No examples are + * apparent at the moment. + */ + if (bits.size() != 3) { + kid.addChild( + "ERROR: Takes three arguments: the name of the rule to process, then the find/replace pair to apply after the rule has been generated."); - build.findReplaceRule(bits.get(0), bits.get(1), bits.get(2), kid); + break; } - break; - case "reject-rule": - { - if(bits.size() != 2) { - kid.addChild("ERROR: Takes two arguments: the name of the rule to process, then the rejection pattern to apply after the rule has been generated."); - break; - } + build.findReplaceRule(bits.get(0), bits.get(1), bits.get(2), kid); + } + break; + case "reject-rule": { + if (bits.size() != 2) { + kid.addChild( + "ERROR: Takes two arguments: the name of the rule to process, then the rejection pattern to apply after the rule has been generated."); - build.rejectRule(bits.get(0), bits.get(1), kid); + break; } + + build.rejectRule(bits.get(0), bits.get(1), kid); + } break; - case "prefix-with": - { - doAffixWith(pragmaBody, build, level, AffixType.PREFIX, kid); - } + case "prefix-with": { + doAffixWith(pragmaBody, build, level, AffixType.PREFIX, kid); + } break; - case "suffix-with": - { - doAffixWith(pragmaBody, build, level, AffixType.SUFFIX, kid); - } + case "suffix-with": { + doAffixWith(pragmaBody, build, level, AffixType.SUFFIX, kid); + } break; - case "circumfix-with": - { - doAffixWith(pragmaBody, build, level, AffixType.CIRCUMFIX, kid); - } + case "circumfix-with": { + doAffixWith(pragmaBody, build, level, AffixType.CIRCUMFIX, kid); + } break; - /* - * @NOTE 9/4/18 - * - * Right now, we ignore additional elements to autovivify. Not - * sure yet if this is the desired behavior. - * - * As I see it, there are a couple of alternatives: - * - * 1) Continue what we're doing. This is simple, but seems - * somewhat inelegant. - * - * 2) Error if more than one is provided. Even simpler, but also - * seems inelegant. - * - * 3) Parse them independantly. Each element is treated as a - * seperate autovar. Seems simple, but may - * cause issues with mixing rule & nonrule - * variables, as well as naming. - * - * 4) Parse them together. Autovars are stored as cases instead - * of case elements. Also simple, but may have - * some odd corner cases, and I can't think of - * any cases where the additional power would - * be useful. - * - * - * - * - * - * - * As an additional aside, we currently error if we provide - * something that isn't a variable definition. This is because - * we pull the name for the auto-vivify variable from the - * element. If we go with option 4 above, the user will have to - * specify a name for the variable, and we should likely add - * some check when the variable is made live that it actually - * created the variable it said it would. - * - */ - case "autovivify": - { - doAutoVar(bits, build, level, false, kid); - } + /* + * @NOTE 9/4/18 + * + * Right now, we ignore additional elements to autovivify. Not sure yet if this + * is the desired behavior. + * + * As I see it, there are a couple of alternatives: + * + * 1) Continue what we're doing. This is simple, but seems somewhat inelegant. + * + * 2) Error if more than one is provided. Even simpler, but also seems + * inelegant. + * + * 3) Parse them independantly. Each element is treated as a seperate autovar. + * Seems simple, but may cause issues with mixing rule & nonrule variables, as + * well as naming. + * + * 4) Parse them together. Autovars are stored as cases instead of case + * elements. Also simple, but may have some odd corner cases, and I can't think + * of any cases where the additional power would be useful. + * + * + * + * + * + * + * As an additional aside, we currently error if we provide something that isn't + * a variable definition. This is because we pull the name for the auto-vivify + * variable from the element. If we go with option 4 above, the user will have + * to specify a name for the variable, and we should likely add some check when + * the variable is made live that it actually created the variable it said it + * would. + * + */ + case "autovivify": { + doAutoVar(bits, build, level, false, kid); + } break; - case "autovivify-rule": - { - doAutoVar(bits, build, level, true, kid); - } + case "autovivify-rule": { + doAutoVar(bits, build, level, true, kid); + } break; - default: - { - String msg = String.format("ERROR: Unknown pragma '%s'", pragmaName); + default: { + String msg = String.format("ERROR: Unknown pragma '%s'", pragmaName); - kid.addChild(msg); - } + kid.addChild(msg); + } } - if (kid.size() > 0) errs.addChild(kid); + if (kid.size() > 0) + errs.addChild(kid); } /* Handle a block of a rule declaration and one or more cases. */ - private static void handleRuleBlock(String ruleBlock, RGrammarBuilder build, int level, int lineOffset, LoadOptions lopts, ITree errs) { + private static void handleRuleBlock(String ruleBlock, RGrammarBuilder build, + int level, int lineOffset, LoadOptions lopts, ITree errs) { String dlm = String.format(TMPL_RULEDECL_BLOCK_DELIM, level); - try (BlockReader ruleReader = new SimpleBlockReader(dlm, new StringReader(ruleBlock))) { + try (BlockReader ruleReader + = new SimpleBlockReader(dlm, new StringReader(ruleBlock))) { ITree kid = new Tree<>(); if (ruleReader.hasNextBlock()) { @@ -518,49 +537,54 @@ public class RGrammarParser { declBlock.lineOffset = lineOffset; String declContents = declBlock.contents; - Rule rl = handleRuleDecl(build, declContents, lineOffset + declBlock.startLine, kid); + Rule rl = handleRuleDecl(build, declContents, + lineOffset + declBlock.startLine, kid); // Error occured during rule processing - if (rl == null) return; + if (rl == null) + return; - for(Block block : ruleReader) { + for (Block block : ruleReader) { /* Ignore comment lines. */ - if(block.contents.trim().startsWith("#")) return; + if (block.contents.trim().startsWith("#")) + return; - handleRuleCase(block.contents, build, rl, block.startLine + lineOffset, kid); + handleRuleCase(block.contents, build, rl, + block.startLine + lineOffset, kid); } } else { /* Rule with a declaration followed by a single case. */ handleRuleDecl(build, ruleBlock, lineOffset, kid); } - if (kid.size() > 0) errs.addChild(kid); + if (kid.size() > 0) + errs.addChild(kid); } catch (IOException ex) { - String msg = String.format("ERROR: Unknown error handling rule block (%s)",ex.getMessage()); + String msg = String.format("ERROR: Unknown error handling rule block (%s)", + ex.getMessage()); errs.addChild(msg); } } /* Handle a rule declaration and its initial case. */ - private static Rule handleRuleDecl(RGrammarBuilder build, String declContents, int lineOffset, ITree errs) { + private static Rule handleRuleDecl(RGrammarBuilder build, String declContents, + int lineOffset, ITree errs) { int declSep = declContents.indexOf("\u2192"); if (declSep == -1) { /* - * @NOTE - * We should maybe remove support for the old - * syntax at some point. + * @NOTE We should maybe remove support for the old syntax at some point. * - * We don't want to do so so as to make inputting grammars easier, - * since that character is not easy to type on a normal keyboard, - * and takes 4 keystrokes in vim as composed to 1 for the normal - * one. + * We don't want to do so so as to make inputting grammars easier, since that + * character is not easy to type on a normal keyboard, and takes 4 keystrokes + * in vim as composed to 1 for the normal one. */ declSep = declContents.indexOf(' '); if (declSep == -1) { - String msg = "A rule must be given at least one case in its declaration, and seperated from that case by \u2192 or ' '"; + String msg + = "A rule must be given at least one case in its declaration, and seperated from that case by \u2192 or ' '"; errs.addChild(msg); @@ -581,7 +605,8 @@ public class RGrammarParser { Rule rul = build.getOrCreateRule(ruleName, errs); - if (rul == null) return null; + if (rul == null) + return null; handleRuleCase(ruleBody, build, rul, lineOffset, errs); @@ -589,7 +614,8 @@ public class RGrammarParser { } /* Handle a single case of a rule. */ - private static void handleRuleCase(String cse, RGrammarBuilder build, Rule rul, int lineOffset, ITree errs) { + private static void handleRuleCase(String cse, RGrammarBuilder build, Rule rul, + int lineOffset, ITree errs) { List elms = new ArrayList<>(); int weights = parseElementString(cse, elms, errs); @@ -598,7 +624,8 @@ public class RGrammarParser { } /* Handle a where block (a block with local rules). */ - private static void handleWhereBlock(String block, RGrammarBuilder build, int level, int lineOffset, LoadOptions lopts, ITree errs) { + private static void handleWhereBlock(String block, RGrammarBuilder build, int level, + int lineOffset, LoadOptions lopts, ITree errs) { int nlIndex = block.indexOf("\\nin"); if (nlIndex == -1) { @@ -611,7 +638,8 @@ public class RGrammarParser { String whereDelim = String.format(TMPL_WHERE_BLOCK_DELIM, level); - try (BlockReader whereReader = new SimpleBlockReader(whereDelim, new StringReader(trimBlock))) { + try (BlockReader whereReader + = new SimpleBlockReader(whereDelim, new StringReader(trimBlock))) { Block whereCtx = whereReader.next(); whereCtx.lineOffset = lineOffset; @@ -619,51 +647,97 @@ public class RGrammarParser { String ctxDelim = String.format(TMPL_TOPLEVEL_BLOCK_DELIM, level + 1); try (BlockReader bodyReader = new SimpleBlockReader(ctxDelim, ctxReader)) { - //@SuppressWarnings("unused") + // @SuppressWarnings("unused") Block whereBody = whereReader.next(); whereBody.lineOffset = lineOffset + whereCtx.startLine; - String msg = String.format("UNIMPLEMENTED WHERE:\n%s\n", whereBody.contents); + String msg + = String.format("UNIMPLEMENTED WHERE:\n%s\n", whereBody.contents); errs.addChild(msg); /** - * @TODO 10/11/17 Ben Culkin :WhereBlocks - * Implement where blocks. + * @TODO 10/11/17 Ben Culkin :WhereBlocks Implement where blocks. * - * A where block has the context evaluated - * in a new context, and the body executed - * in that context. + * A where block has the context evaluated in a new context, and the + * body executed in that context. */ } } catch (IOException ioex) { - //String msg = String.format("Unknown error in where block (%s)", ioex.getMessage()); + // String msg = String.format("Unknown error in where block (%s)", + // ioex.getMessage()); } } + /** + * Parse an element string. + * + * @param cses + * The case string. + * @param elms + * The current list of case elements. + * + * @return The weight of the resulting case. + */ public static int parseElementString(String cses, List elms) { return parseElementString(cses, elms, new Tree<>()); } - public static int parseElementString(String cses, List elms, ITree errs) { + /** + * Parse an element string. + * + * @param cses + * The case string. + * @param elms + * The current list of case elements. + * @param errs + * The place to put errors. + * + * @return The weight of the resulting case. + */ + public static int parseElementString(String cses, List elms, + ITree errs) { /* * @NOTE * - * This is done using String.split because using things like ( - * as groupers breaks certain grammars. Maybe it can be used if - * some sort of way to set which groupers to use is added? + * This is done using String.split because using things like ( as groupers + * breaks certain grammars. Maybe it can be used if some sort of way to set + * which groupers to use is added? * - * List cseList = LevelSplitter.def.levelSplit(cses.trim(), " "); + * List cseList = LevelSplitter.def.levelSplit(cses.trim(), " "); * - * return parseElementString(cseList.toArray(new String[0])); + * return parseElementString(cseList.toArray(new String[0])); */ return parseElementString(cses.split(" "), elms, errs); } + /** + * Parse an element string. + * + * @param cses + * The case elements. + * @param elms + * The current list of case elements. + * + * @return The weight of the resulting case. + */ public static int parseElementString(String[] cses, List elms) { return parseElementString(cses, elms, new Tree<>()); } - public static int parseElementString(String[] cses, List caseParts, ITree errs) { + /** + * Parse an element string. + * + * @param cses + * The case elements. + * @param caseParts + * The current list of case elements. + * @param errs + * The place to put errors. + * + * @return The weight of the resulting case. + */ + public static int parseElementString(String[] cses, List caseParts, + ITree errs) { int weight = 1; int repCount = 1; @@ -681,17 +755,20 @@ public class RGrammarParser { if (partToAdd.equals("")) { /* Ignore empty parts */ continue; - } else if(partToAdd.matches("\\<\\^\\d+\\>")) { + } else if (partToAdd.matches("\\<\\^\\d+\\>")) { /* Set case weights */ weight = Integer.parseInt(partToAdd.substring(2, partToAdd.length() - 1)); - } else if(partToAdd.matches("\\<&\\d+\\>")) { - repCount = Integer.parseInt(partToAdd.substring(2, partToAdd.length() - 1)); - } else if(partToAdd.matches("\\<&\\d+\\.\\.\\d+\\>")) { - serialLower = Integer.parseInt(partToAdd.substring(2, partToAdd.indexOf("."))); - serialUpper = Integer.parseInt(partToAdd.substring(partToAdd.lastIndexOf(".") + 1, partToAdd.length() - 1)); + } else if (partToAdd.matches("\\<&\\d+\\>")) { + repCount = Integer + .parseInt(partToAdd.substring(2, partToAdd.length() - 1)); + } else if (partToAdd.matches("\\<&\\d+\\.\\.\\d+\\>")) { + serialLower = Integer + .parseInt(partToAdd.substring(2, partToAdd.indexOf("."))); + serialUpper = Integer.parseInt(partToAdd.substring( + partToAdd.lastIndexOf(".") + 1, partToAdd.length() - 1)); doSerial = true; - } else if(partToAdd.matches("\\<\\?\\d+\\>")) { + } else if (partToAdd.matches("\\<\\?\\d+\\>")) { chance = Integer.parseInt(partToAdd.substring(2, partToAdd.length() - 1)); doChance = true; @@ -699,64 +776,61 @@ public class RGrammarParser { /* * @NOTE * - * One, am I even using this feature anywhere? - * As far as I can tell, this says to apply the - * current set of case part rules to the - * previous case part. This may be useful in - * certain cases, but none come to mind at the + * One, am I even using this feature anywhere? As far as I can tell, this + * says to apply the current set of case part rules to the previous case + * part. This may be useful in certain cases, but none come to mind at the * moment. * * @PERF * - * For performance reasons, we may want to - * consider setting the chance/serial values as - * a setting on CaseElement, instead of having + * For performance reasons, we may want to consider setting the + * chance/serial values as a setting on CaseElement, instead of having * their own CaseElement type. */ CaseElement elm = caseParts.remove(caseParts.size() - 1); - if(repCount == 0) { + if (repCount == 0) { /* Skip no-reps */ } else { - if(doChance) { + if (doChance) { elm = new ChanceCaseElement(elm, chance); doChance = false; } - if(doSerial) { + if (doSerial) { elm = new SerialCaseElement(elm, serialLower, serialUpper); doSerial = false; } - for(int i = 1; i <= repCount; i++) { + for (int i = 1; i <= repCount; i++) { caseParts.add(elm); } repCount = 1; } - } else if(partToAdd.matches("\\<[^\\>]+\\>")) { + } else if (partToAdd.matches("\\<[^\\>]+\\>")) { throw new GrammarException("Unknown parser meta-rule " + partToAdd); } else { CaseElement elm = CaseElement.createElement(partToAdd); - if(repCount == 0) { + if (repCount == 0) { /* Skip no-reps */ } else { - if(doChance) { + if (doChance) { elm = new ChanceCaseElement(elm, chance); doChance = false; } - if(doSerial) { + if (doSerial) { elm = new SerialCaseElement(elm, serialLower, serialUpper); doSerial = false; } - for(int i = 1; i <= repCount; i++) { + for (int i = 1; i <= repCount; i++) { caseParts.add(elm); } -- cgit v1.2.3