summaryrefslogtreecommitdiff
path: root/src/main/java/bjc/rgens/parser/RGrammarParser.java
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2020-11-11 12:29:59 -0400
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2020-11-11 12:29:59 -0400
commit80aa147aedc91356276d4346efb1ea62ea5b06f9 (patch)
treea57c8f2ad3a7e68ba1c0a5a2bea573a8da277ab6 /src/main/java/bjc/rgens/parser/RGrammarParser.java
parentc88c846b75dbc806db19a2e3a907bff21fd0c273 (diff)
parente9e0ca7bfe722375e7ccb25d2bafbe395b6c6a59 (diff)
Merge branch 'master' of https://github.com/bculkin2442/rgens
Diffstat (limited to 'src/main/java/bjc/rgens/parser/RGrammarParser.java')
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/RGrammarParser.java666
1 files changed, 370 insertions, 296 deletions
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<String> errs) {
+ private static void doAffixWith(String body, RGrammarBuilder build, int level,
+ AffixType afxType, ITree<String> 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<String> bits, RGrammarBuilder build, int level, boolean isRule, ITree<String> errs) {
+ private static void doAutoVar(List<String> bits, RGrammarBuilder build, int level,
+ boolean isRule, ITree<String> 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<String> errs) throws GrammarException {
+ public static RGrammar readGrammar(Reader is, LoadOptions lopts, ITree<String> 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<String> kid = new Tree<>(msg);
+ ITree<String> 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<String> errs) {
+ private static void handleBlock(RGrammarBuilder build, String block, int level,
+ int lineOffset, LoadOptions lopts, ITree<String> 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<String> errs) {
+ private static void handlePragmaBlock(String block, RGrammarBuilder build, int level,
+ int lineOffset, LoadOptions lopts, ITree<String> 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<String> errs) {
+ private static void handlePragma(String pragma, RGrammarBuilder build, int level,
+ int lineOffset, LoadOptions lopts, ITree<String> 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<String> 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<String> errs) {
+ private static void handleRuleBlock(String ruleBlock, RGrammarBuilder build,
+ int level, int lineOffset, LoadOptions lopts, ITree<String> 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<String> 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<String> errs) {
+ private static Rule handleRuleDecl(RGrammarBuilder build, String declContents,
+ int lineOffset, ITree<String> 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<String> errs) {
+ private static void handleRuleCase(String cse, RGrammarBuilder build, Rule rul,
+ int lineOffset, ITree<String> errs) {
List<CaseElement> 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<String> errs) {
+ private static void handleWhereBlock(String block, RGrammarBuilder build, int level,
+ int lineOffset, LoadOptions lopts, ITree<String> 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<CaseElement> elms) {
return parseElementString(cses, elms, new Tree<>());
}
- public static int parseElementString(String cses, List<CaseElement> elms, ITree<String> 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<CaseElement> elms,
+ ITree<String> 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<String> cseList = LevelSplitter.def.levelSplit(cses.trim(), " ");
+ * List<String> 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<CaseElement> elms) {
return parseElementString(cses, elms, new Tree<>());
}
- public static int parseElementString(String[] cses, List<CaseElement> caseParts, ITree<String> 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<CaseElement> caseParts,
+ ITree<String> 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);
}