summaryrefslogtreecommitdiff
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
parentc88c846b75dbc806db19a2e3a907bff21fd0c273 (diff)
parente9e0ca7bfe722375e7ccb25d2bafbe395b6c6a59 (diff)
Merge branch 'master' of https://github.com/bculkin2442/rgens
-rw-r--r--src/main/java/bjc/rgens/parser/AffixType.java39
-rw-r--r--src/main/java/bjc/rgens/parser/ConfigLoader.java219
-rw-r--r--src/main/java/bjc/rgens/parser/FlatRuleCase.java1
-rw-r--r--src/main/java/bjc/rgens/parser/GenerationState.java139
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/GrammarException.java27
-rw-r--r--src/main/java/bjc/rgens/parser/NormalRuleCase.java1
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/RGrammar.java124
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/RGrammarBuilder.java202
-rw-r--r--src/main/java/bjc/rgens/parser/RGrammarLogging.java55
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/RGrammarParser.java666
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/RGrammarSet.java21
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/RegexRuleCase.java2
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/Rule.java93
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/RuleCase.java26
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/CaseElement.java63
-rw-r--r--src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java21
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java13
-rw-r--r--src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java14
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/RangeCaseElement.java19
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/RuleCaseElement.java70
-rw-r--r--src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java17
-rw-r--r--src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java24
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/StringCaseElement.java21
-rwxr-xr-xsrc/main/java/bjc/rgens/parser/elements/VariableDefCaseElement.java41
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java16
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java15
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java2
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java15
-rw-r--r--src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java70
-rw-r--r--src/main/java/bjc/rgens/parser/templates/LiteralTemplateElement.java5
-rw-r--r--src/main/java/bjc/rgens/parser/templates/TemplateElement.java24
31 files changed, 1456 insertions, 609 deletions
diff --git a/src/main/java/bjc/rgens/parser/AffixType.java b/src/main/java/bjc/rgens/parser/AffixType.java
new file mode 100644
index 0000000..e591a45
--- /dev/null
+++ b/src/main/java/bjc/rgens/parser/AffixType.java
@@ -0,0 +1,39 @@
+package bjc.rgens.parser;
+
+/**
+ * The type of ways to affix rules.
+ * @author Ben Culkin
+ *
+ */
+public enum AffixType {
+ /**
+ * Prefix and suffix the rules.
+ */
+ CIRCUMFIX,
+ /**
+ * Suffix the rules.
+ */
+ SUFFIX,
+ /**
+ * Prefix the rules.
+ */
+ PREFIX;
+
+ /**
+ * Does this affix type perform suffixing?
+ *
+ * @return Whether this affix type performs suffixing.
+ */
+ public boolean isSuffix() {
+ return this != PREFIX;
+ }
+
+ /**
+ * Does this affix type perform prefixing?
+ *
+ * @return Whether this affix type performs prefixing.
+ */
+ public boolean isPrefix() {
+ return this != SUFFIX;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/bjc/rgens/parser/ConfigLoader.java b/src/main/java/bjc/rgens/parser/ConfigLoader.java
index 8daff71..8427726 100644
--- a/src/main/java/bjc/rgens/parser/ConfigLoader.java
+++ b/src/main/java/bjc/rgens/parser/ConfigLoader.java
@@ -40,15 +40,17 @@ public class ConfigLoader {
* Load a grammar set from a configuration file.
*
* @param cfgFile
- * The configuration file to load from.
+ * The configuration file to load from.
+ * @param lopts
+ * Options used during loading.
*
- * @return
- * The grammar set created by the configuration file.
+ * @return The grammar set created by the configuration file.
*
* @throws IOException
- * If something goes wrong during configuration loading.
+ * If something goes wrong during configuration loading.
*/
- public static ConfigSet fromConfigFile(Path cfgFile, LoadOptions lopts) throws IOException {
+ public static ConfigSet fromConfigFile(Path cfgFile, LoadOptions lopts)
+ throws IOException {
String msg = String.format("INFO: Loading config file from path '%s'", cfgFile);
ITree<String> errTree = new Tree<>(msg);
@@ -60,20 +62,22 @@ public class ConfigLoader {
* Load a grammar set from a configuration file.
*
* @param cfgFile
- * The configuration file to load from.
+ * The configuration file to load from.
+ * @param lopts
+ * Options used during loading.
*
* @param errs
- * A place to add errors that occur during loading.
+ * A place to add errors that occur during loading.
*
- * @return
- * The grammar set created by the configuration file.
+ * @return The grammar set created by the configuration file.
*
* @throws IOException
- * If something goes wrong during configuration loading.
+ * If something goes wrong during configuration loading.
*/
- public static ConfigSet fromConfigFile(Path cfgFile, LoadOptions lopts, ITree<String> errs) throws IOException {
+ public static ConfigSet fromConfigFile(Path cfgFile, LoadOptions lopts,
+ ITree<String> errs) throws IOException {
lopts.cfgFile = cfgFile;
- lopts.cfgSet = new ConfigSet();
+ lopts.cfgSet = new ConfigSet();
/* The grammar set we're parsing into. */
lopts.gramSet = lopts.cfgSet.createGSet(lopts.defName);
@@ -81,10 +85,11 @@ public class ConfigLoader {
long startCFGTime = System.nanoTime();
// Get the directory that contains the config file.
- if (lopts.parent == null) lopts.parent = cfgFile.getParent();
+ if (lopts.parent == null)
+ lopts.parent = cfgFile.getParent();
int lno = 0;
- try(Scanner scn = new Scanner(cfgFile)) {
+ try (Scanner scn = new Scanner(cfgFile)) {
while (scn.hasNextLine()) {
// Execute a line from the configuration file.
@@ -99,18 +104,21 @@ public class ConfigLoader {
String ln = scn.nextLine().trim().replaceAll("\\s+", " ");
// Ignore blank/comment lines.
- if (ln.equals("")) continue;
- if (ln.startsWith("#")) continue;
+ if (ln.equals(""))
+ continue;
+ if (ln.startsWith("#"))
+ continue;
// @TODO Ben Culkin 9/21/2019 :LineCont
// We should support some sort of line
// continuation ability, probably using the '\'
// since that what UNIX uses in most places
- ITree<String> header = new Tree<>(String.format("INFO: Processing line %d", lno));
+ ITree<String> header
+ = new Tree<>(String.format("INFO: Processing line %d", lno));
String[] parts = StringUtils.levelSplit(ln, " ").toArray(new String[0]);
- if(parts.length < 1) {
+ if (parts.length < 1) {
// Must specify a line type
//
// @TODO Ben Culkin 9/21/2019 :ErrorLine
@@ -138,12 +146,13 @@ public class ConfigLoader {
} else {
String type = parts[0];
- switch(type) {
- case "load":
+ switch (type) {
+ case "load":
loadConfigLine(parts, lopts, header);
break;
default:
- String fmt = String.format("ERROR: Unknown config line type '%s'", type);
+ String fmt = String.format("ERROR: Unknown config line type '%s'",
+ type);
header.addChild(fmt);
}
@@ -158,7 +167,9 @@ public class ConfigLoader {
long cfgDur = endCFGTime - startCFGTime;
if (lopts.doPerf) {
- String fmt = String.format("PERF: Read config file (%d lines) from path '%s' in %d ns (%f s)", lno, cfgFile, cfgDur, cfgDur / 1000000000.0);
+ String fmt = String.format(
+ "PERF: Read config file (%d lines) from path '%s' in %d ns (%f s)",
+ lno, cfgFile, cfgDur, cfgDur / 1000000000.0);
errs.addChild(fmt);
}
@@ -167,8 +178,9 @@ public class ConfigLoader {
}
// Load a line from a config file.
- private static void loadConfigLine(String[] parts, LoadOptions lopts, ITree<String> errs) throws IOException {
- if(parts.length < 2) {
+ private static void loadConfigLine(String[] parts, LoadOptions lopts,
+ ITree<String> errs) throws IOException {
+ if (parts.length < 2) {
// Must specify the type of config object you wish to
// load.
//
@@ -191,48 +203,50 @@ public class ConfigLoader {
// Perhaps do a thing that auto-picks a plausible name
// for the object based off of the file name we're
// loading from?
- String fmt = String.format("ERROR: Must specify a name for config object of type '%s'", tag);
+ String fmt = String.format(
+ "ERROR: Must specify a name for config object of type '%s'", tag);
errs.addChild(fmt);
return;
}
- String name = parts[2];
-
- switch(tag) {
- case "template":
- loadTemplate(name, parts, lopts, errs);
- break;
- case "subset":
- {
- String fmt = String.format("ERROR: Sub-grammar sets aren't implemented yet");
-
- /*
- * @TODO Ben Culkin 9/8/17 :SubsetGrammar
- * Implement subset grammars.
- */
- errs.addChild(fmt);
- }
- case "gram":
- case "grammar":
- loadGrammar(name, parts, lopts, errs);
- break;
- case "directory":
- loadDirectory(name, parts, lopts, errs);
- break;
- default:
- String fmt = String.format("ERROR: Unrecognized config object type '%s'", tag);
+ String name = parts[2];
- errs.addChild(fmt);
+ switch (tag) {
+ case "template":
+ loadTemplate(name, parts, lopts, errs);
+ break;
+ case "subset": {
+ String fmt = String.format("ERROR: Sub-grammar sets aren't implemented yet");
+
+ /*
+ * @TODO Ben Culkin 9/8/17 :SubsetGrammar Implement subset grammars.
+ */
+ errs.addChild(fmt);
+ }
+ case "gram":
+ case "grammar":
+ loadGrammar(name, parts, lopts, errs);
+ break;
+ case "directory":
+ loadDirectory(name, parts, lopts, errs);
+ break;
+ default:
+ String fmt
+ = String.format("ERROR: Unrecognized config object type '%s'", tag);
+
+ errs.addChild(fmt);
}
}
// Load a 'directory' config object, by recursively attempting to
// auto-load all of the items in the directory as objects
- private static void loadDirectory(String name, String[] parts, LoadOptions lopts, ITree<String> errs) throws IOException {
- if(parts.length < 4) {
- String fmt = String.format("ERROR: Must specify a path to load directory '%s' from", name);
+ private static void loadDirectory(String name, String[] parts, LoadOptions lopts,
+ ITree<String> errs) {
+ if (parts.length < 4) {
+ String fmt = String.format(
+ "ERROR: Must specify a path to load directory '%s' from", name);
errs.addChild(fmt);
@@ -242,12 +256,11 @@ public class ConfigLoader {
Path path = Paths.get(parts[3]);
/*
- * Convert from configuration relative path to
- * absolute path.
+ * Convert from configuration relative path to absolute path.
*/
Path dirPath = lopts.parent.resolve(path.toString());
- if(!Files.isDirectory(dirPath)) {
+ if (!Files.isDirectory(dirPath)) {
String fmt = String.format("ERROR: '%s' is not a valid directory", dirPath);
errs.addChild(fmt);
@@ -255,16 +268,19 @@ public class ConfigLoader {
// Create an iterator over all of the files in the
// provided directory. This will also have the files for
// the sub-directories added to it as well
- QueuedIterator<File> dirItr = new QueuedIterator<>(dirPath.toFile().listFiles());
+ QueuedIterator<File> dirItr
+ = new QueuedIterator<>(dirPath.toFile().listFiles());
- ITree<String> header = new Tree<>(String.format("INFO: Bulk-loading objects from directory '%s'", lopts.parent));
+ ITree<String> header = new Tree<>(String.format(
+ "INFO: Bulk-loading objects from directory '%s'", lopts.parent));
while (dirItr.hasNext()) {
File curFile = dirItr.next();
String fName = curFile.toString();
- ITree<String> kid = new Tree<>(String.format("INFO: Processing object from path '%s'", fName));
+ ITree<String> kid = new Tree<>(
+ String.format("INFO: Processing object from path '%s'", fName));
Path oldPar = lopts.parent;
@@ -290,7 +306,8 @@ public class ConfigLoader {
} else if (fName.endsWith(".class")) {
// These get ignored
} else {
- String fmt = String.format("WARN: Ignoring unknown type of file '%s'");
+ String fmt = String
+ .format("WARN: Ignoring unknown type of file '%s'");
kid.addChild(fmt);
@@ -310,16 +327,17 @@ public class ConfigLoader {
}
// Actually do the work of loading a 'template' object
- private static void doLoadTemplate(Reader rdr, String name, LoadOptions lopts, ITree<String> errs) throws IOException {
+ private static void doLoadTemplate(Reader rdr, String name, LoadOptions lopts,
+ ITree<String> errs) throws IOException {
String actName;
-
+
long startFileTime = System.nanoTime();
GrammarTemplate template = GrammarTemplate.readTemplate(rdr, errs);
template.belongsTo = lopts.cfgSet;
- if(template.name == null) {
- if(name == null) {
+ if (template.name == null) {
+ if (name == null) {
String fmt = String.format("WARN: Using default name for template");
errs.addChild(fmt);
@@ -329,7 +347,9 @@ public class ConfigLoader {
actName = name;
}
- String fmt = String.format("INFO: Naming unnamed template off name '%s' specified in config", actName);
+ String fmt = String.format(
+ "INFO: Naming unnamed template off name '%s' specified in config",
+ actName);
errs.addChild(fmt);
template.name = actName;
@@ -342,7 +362,8 @@ public class ConfigLoader {
long fileTime = endFileTime - startFileTime;
if (lopts.doPerf) {
- String fmt = String.format("PERF: Read template %s in %d ns (%f s)", template.name, fileTime, fileTime / 1000000000.0);
+ String fmt = String.format("PERF: Read template %s in %d ns (%f s)",
+ template.name, fileTime, fileTime / 1000000000.0);
errs.addChild(fmt);
}
@@ -355,17 +376,19 @@ public class ConfigLoader {
*
* Do we need to do this for templates?
*
- * Probably, if only to allow for some better diagnostics when
- * we need them - ben, 9/21/2019
+ * Probably, if only to allow for some better diagnostics when we need them -
+ * ben, 9/21/2019
*/
- //Mark where the template came from.
- //set.loadedFrom.put(template.name, path.toString());
+ // Mark where the template came from.
+ // set.loadedFrom.put(template.name, path.toString());
}
// Load a 'template' type grammar object
- private static void loadTemplate(String name, String[] parts, LoadOptions lopts, ITree<String> errs) throws IOException {
- if(parts.length < 4) {
- String fmt = String.format("ERROR: Must specify a path to load template '%s' from", name);
+ private static void loadTemplate(String name, String[] parts, LoadOptions lopts,
+ ITree<String> errs) throws IOException {
+ if (parts.length < 4) {
+ String fmt = String.format(
+ "ERROR: Must specify a path to load template '%s' from", name);
errs.addChild(fmt);
@@ -375,23 +398,24 @@ public class ConfigLoader {
Path path = Paths.get(parts[3]);
/*
- * Convert from configuration relative path to
- * absolute path.
+ * Convert from configuration relative path to absolute path.
*/
Path convPath = lopts.parent.resolve(path.toString());
- if(!Files.exists(convPath) || Files.isDirectory(convPath)) {
- String fmt = String.format("ERROR: '%s' is not a valid grammar file", convPath);
+ if (!Files.exists(convPath) || Files.isDirectory(convPath)) {
+ String fmt
+ = String.format("ERROR: '%s' is not a valid grammar file", convPath);
errs.addChild(fmt);
} else {
/* Load template file. */
Reader rdr = new FileReader(convPath.toFile());
- String fmt = String.format("INFO: Loading template '%s' from '%s'", name, convPath);
+ String fmt = String.format("INFO: Loading template '%s' from '%s'", name,
+ convPath);
ITree<String> kid = new Tree<>(fmt);
- Path oldPar = lopts.parent;
+ Path oldPar = lopts.parent;
lopts.parent = convPath.getParent();
try {
@@ -405,14 +429,15 @@ public class ConfigLoader {
}
// Actually load a 'grammar' object
- private static void doLoadGrammar(Reader rdr, String name, LoadOptions lopts, ITree<String> errs, Path convPath) throws IOException {
+ private static void doLoadGrammar(Reader rdr, String name, LoadOptions lopts,
+ ITree<String> errs, Path convPath) throws IOException {
String actName;
long startFileTime = System.nanoTime();
RGrammar gram = RGrammarParser.readGrammar(rdr, lopts, errs);
- if(gram.name == null) {
- if(name == null) {
+ if (gram.name == null) {
+ if (name == null) {
errs.addChild("WARN: Using default name for grammar");
actName = "default-name";
@@ -420,7 +445,8 @@ public class ConfigLoader {
actName = name;
}
- //String fmt = String.format("INFO: Naming unnamed grammar off config name '%s'", actName);
+ // String fmt = String.format("INFO: Naming unnamed grammar off config name
+ // '%s'", actName);
gram.name = actName;
}
@@ -432,7 +458,8 @@ public class ConfigLoader {
long fileTime = endFileTime - startFileTime;
if (lopts.doPerf) {
- String fmt = String.format("PERF: Read grammar %s in %d ns (%f s)", gram.name, fileTime, fileTime / 1000000000.0);
+ String fmt = String.format("PERF: Read grammar %s in %d ns (%f s)", gram.name,
+ fileTime, fileTime / 1000000000.0);
errs.addChild(fmt);
}
@@ -441,16 +468,17 @@ public class ConfigLoader {
lopts.gramSet.addGrammar(gram.name, gram);
/*
- * Mark where the grammar came
- * from.
+ * Mark where the grammar came from.
*/
lopts.gramSet.loadedFrom.put(gram.name, convPath.toString());
}
// Load a 'grammar' object
- private static void loadGrammar(String name, String[] parts, LoadOptions lopts, ITree<String> errs) throws IOException {
- if(parts.length < 4) {
- String fmt = String.format("ERROR: Must provide a path to load grammar '%s' from", name);
+ private static void loadGrammar(String name, String[] parts, LoadOptions lopts,
+ ITree<String> errs) {
+ if (parts.length < 4) {
+ String fmt = String
+ .format("ERROR: Must provide a path to load grammar '%s' from", name);
errs.addChild(fmt);
@@ -460,13 +488,13 @@ public class ConfigLoader {
Path path = Paths.get(parts[3]);
/*
- * Convert from configuration relative path to
- * absolute path.
+ * Convert from configuration relative path to absolute path.
*/
Path convPath = lopts.parent.resolve(path.toString());
- if(!Files.exists(convPath) || Files.isDirectory(convPath)) {
- String fmt = String.format("ERROR: '%s' is not a valid grammar file", convPath);
+ if (!Files.exists(convPath) || Files.isDirectory(convPath)) {
+ String fmt
+ = String.format("ERROR: '%s' is not a valid grammar file", convPath);
errs.addChild(fmt);
} else {
@@ -480,7 +508,8 @@ public class ConfigLoader {
Reader rdr = new FileReader(convPath.toFile());
- ITree<String> kid = new Tree<>(String.format("INFO: Loading grammar '%s' from '%s'", name, convPath));
+ ITree<String> kid = new Tree<>(String
+ .format("INFO: Loading grammar '%s' from '%s'", name, convPath));
doLoadGrammar(rdr, name, lopts, kid, convPath);
diff --git a/src/main/java/bjc/rgens/parser/FlatRuleCase.java b/src/main/java/bjc/rgens/parser/FlatRuleCase.java
index 5055810..0cb2626 100644
--- a/src/main/java/bjc/rgens/parser/FlatRuleCase.java
+++ b/src/main/java/bjc/rgens/parser/FlatRuleCase.java
@@ -35,6 +35,7 @@ public class FlatRuleCase extends RuleCase {
*
* @return A flat rule case, with the given elements.
*/
+ @Override
public FlatRuleCase withElements(List<CaseElement> elms) {
return new FlatRuleCase(elms);
}
diff --git a/src/main/java/bjc/rgens/parser/GenerationState.java b/src/main/java/bjc/rgens/parser/GenerationState.java
index 3eab856..65ab4cd 100644
--- a/src/main/java/bjc/rgens/parser/GenerationState.java
+++ b/src/main/java/bjc/rgens/parser/GenerationState.java
@@ -40,22 +40,23 @@ public class GenerationState {
/**
* Create a new generation state.
*
- * The place to write output to.
+ * @param rw
+ * The place to write output to.
*
* @param rand
- * The random number generator to use.
+ * The random number generator to use.
*
* @param vs
- * The normal variables to use.
+ * The normal variables to use.
*
* @param rvs
- * The rule variables to use.
+ * The rule variables to use.
*
* @param gram
- * The grammar we are generating from.
+ * The grammar we are generating from.
*/
- public GenerationState(ReportWriter rw, Random rand, Map<String, String> vs, Map<String, Rule> rvs,
- RGrammar gram) {
+ public GenerationState(ReportWriter rw, Random rand, Map<String, String> vs,
+ Map<String, Rule> rvs, RGrammar gram) {
vars = new MapSet<>();
rlVars = new MapSet<>();
@@ -75,27 +76,24 @@ public class GenerationState {
* Create a new generation state, from a given grammar.
*
* @param gram
- * The grammar to generate from.
+ * The grammar to generate from.
*
- * @return
- * A new generation state, with the provided parameters.
+ * @return A new generation state, with the provided parameters.
*/
public static GenerationState fromGrammar(RGrammar gram) {
return fromGrammar(BASE, gram);
}
/**
- * Create a new generation state, using a provided random generator and
- * grammar.
+ * Create a new generation state, using a provided random generator and grammar.
*
* @param rand
- * The random number generator to use.
+ * The random number generator to use.
*
* @param gram
- * The grammar to generate from.
+ * The grammar to generate from.
*
- * @return
- * A new generation state, with the provided parameters.
+ * @return A new generation state, with the provided parameters.
*/
public static GenerationState fromGrammar(Random rand, RGrammar gram) {
ReportWriter rw = new ReportWriter(new StringWriter());
@@ -106,27 +104,28 @@ public class GenerationState {
/**
* Swap the grammar for the state.
*
- * @param gram
- * The grammar to swap to.
+ * @param gramr
+ * The grammar to swap to.
*/
- public void swapGrammar(RGrammar gram) {
- if (this.gram == gram) return;
+ public void swapGrammar(RGrammar gramr) {
+ if (this.gram == gramr)
+ return;
- this.gram = gram;
+ this.gram = gramr;
- rules = gram.getRules();
+ rules = gramr.getRules();
- importRules = gram.getImportRules();
+ importRules = gramr.getImportRules();
- vars.setCreateMap(gram.name);
- rlVars.setCreateMap(gram.name);
+ vars.setCreateMap(gramr.name);
+ rlVars.setCreateMap(gramr.name);
}
/**
* Create a copy of this generation state, writing into a fresh buffer.
*
* @return A generation state that is a copy of this one, but writes into a
- * fresh buffer.
+ * fresh buffer.
*/
public GenerationState newBuf() {
// @NOTE 9/5/18
@@ -144,28 +143,29 @@ public class GenerationState {
/*
* @TODO 6/5/18 Ben Culkin :ImportRefactor
*
- * Change this so that imports in almost all cases have to specify where
- * they are importing the rule from, so as to make it clear which rules
- * are imported, and which aren't
+ * Change this so that imports in almost all cases have to specify where they
+ * are importing the rule from, so as to make it clear which rules are imported,
+ * and which aren't
*/
/**
* Find an instance of a rule.
*
* @param ruleName
- * The name of the rule to look for.
+ * The name of the rule to look for.
*
* @param allowImports
- * Whether or not to look for imported rules.
+ * Whether or not to look for imported rules.
*
- * @return The rule instance you were looking for, or null if none by that
- * name happen to exist.
+ * @return The rule instance you were looking for, or null if none by that name
+ * happen to exist.
*/
public Rule findRule(String ruleName, boolean allowImports) {
if (rules.containsKey(ruleName)) {
return rules.get(ruleName);
}
- if (allowImports) return findImport(ruleName);
+ if (allowImports)
+ return findImport(ruleName);
return null;
}
@@ -174,10 +174,10 @@ public class GenerationState {
* Find an instance of an imported rule.
*
* @param ruleName
- * The name of the rule to look for.
+ * The name of the rule to look for.
*
- * @return The rule instance you were looking for, or null if none by that
- * name happen to exist.
+ * @return The rule instance you were looking for, or null if none by that name
+ * happen to exist.
*/
public Rule findImport(String ruleName) {
if (importRules.containsKey(ruleName)) {
@@ -191,16 +191,18 @@ public class GenerationState {
* Define a normal variable.
*
* @param name
- * The name to give the variable.
+ * The name to give the variable.
*
* @param val
- * The value to give the variable.
+ * The value to give the variable.
*/
public void defineVar(String name, String val) {
if (vars.containsKey(name))
- warn("Shadowing variable %s with value %s (old value %s)", name, val, vars.get(name));
+ warn("Shadowing variable %s with value %s (old value %s)", name, val,
+ vars.get(name));
else if (gram.autoVars.containsKey(name))
- warn("Shadowing autovariable %s with value %s (defn. %s)", name, val, gram.autoVars.get(name));
+ warn("Shadowing autovariable %s with value %s (defn. %s)", name, val,
+ gram.autoVars.get(name));
vars.put(name, val);
}
@@ -209,14 +211,15 @@ public class GenerationState {
* Define a rule variable.
*
* @param name
- * The name to give the variable.
+ * The name to give the variable.
*
* @param rle
- * The value to give the variable.
+ * The value to give the variable.
*/
public void defineRuleVar(String name, Rule rle) {
if (rlVars.containsKey(name))
- warn("Shadowing rule variable %s with value %s (old value %s)", name, rlVars.get(name), rle);
+ warn("Shadowing rule variable %s with value %s (old value %s)", name,
+ rlVars.get(name), rle);
else if (gram.autoRlVars.containsKey(name))
warn("Shadowing rule autovariable %s with value %s (defn. %s)", name, rle,
gram.autoRlVars.get(name));
@@ -228,19 +231,22 @@ public class GenerationState {
* Find a variable.
*
* @param name
- * The variable to look for.
+ * The variable to look for.
*
* @return The value of the variable.
*
- * @throws GrammarException If the variable isn't found, or if it was an
- * auto-variable that failed to generate succesfully.
+ * @throws GrammarException
+ * If the variable isn't found, or if it was an
+ * auto-variable that failed to generate succesfully.
*/
public String findVar(String name) {
- if (!vars.containsKey(name)) if (gram.autoVars.containsKey(name)) {
- gram.autoVars.get(name).generate(this);
- } else {
- throw new GrammarException(String.format("Variable %s not defined", name));
- }
+ if (!vars.containsKey(name))
+ if (gram.autoVars.containsKey(name)) {
+ gram.autoVars.get(name).generate(this);
+ } else {
+ throw new GrammarException(
+ String.format("Variable %s not defined", name));
+ }
return vars.get(name);
}
@@ -249,25 +255,31 @@ public class GenerationState {
* Find a rule variable.
*
* @param name
- * The variable to look for.
+ * The variable to look for.
*
* @return The value of the variable.
*
- * @throws GrammarException If the variable isn't found, or if it was an
- * auto-variable that failed to generate succesfully.
+ * @throws GrammarException
+ * If the variable isn't found, or if it was an
+ * auto-variable that failed to generate succesfully.
*/
public Rule findRuleVar(String name) {
- if (!rlVars.containsKey(name)) if (gram.autoRlVars.containsKey(name)) {
- gram.autoRlVars.get(name).generate(this);
- } else {
- throw new GrammarException(String.format("Rule variable %s not defined", name));
- }
+ if (!rlVars.containsKey(name))
+ if (gram.autoRlVars.containsKey(name)) {
+ gram.autoRlVars.get(name).generate(this);
+ } else {
+ throw new GrammarException(
+ String.format("Rule variable %s not defined", name));
+ }
return rlVars.get(name);
}
/**
* Append the given string to our output.
+ *
+ * @param strang
+ * The string to append.
*/
public void appendContents(String strang) {
try {
@@ -281,7 +293,7 @@ public class GenerationState {
* Replace the current contents of our output with the given string.
*
* @param strang
- * The string to replace the output with.
+ * The string to replace the output with.
*/
public void setContents(String strang) {
// @NOTE 9/5/18
@@ -312,6 +324,7 @@ public class GenerationState {
/**
* Get our output as a string.
+ * @return The contents of the state.
*/
public String getContents() {
return contents.toString();
@@ -321,10 +334,10 @@ public class GenerationState {
* Execute a find/replace on our output.
*
* @param find
- * The pattern to look for
+ * The pattern to look for
*
* @param replace
- * The string to replace occurances of 'find' with.
+ * The string to replace occurrences of 'find' with.
*/
public void findReplaceContents(String find, String replace) {
setContents(getContents().replaceAll(find, replace));
diff --git a/src/main/java/bjc/rgens/parser/GrammarException.java b/src/main/java/bjc/rgens/parser/GrammarException.java
index 271f717..f7aca2c 100755
--- a/src/main/java/bjc/rgens/parser/GrammarException.java
+++ b/src/main/java/bjc/rgens/parser/GrammarException.java
@@ -1,8 +1,7 @@
package bjc.rgens.parser;
/**
- * The exception thrown when something goes wrong while parsing a
- * grammar.
+ * The exception thrown when something goes wrong while parsing a grammar.
*
* @author student
*/
@@ -16,21 +15,20 @@ public class GrammarException extends RuntimeException {
* Create a new grammar exception with the specified message.
*
* @param msg
- * The message for this exception.
+ * The message for this exception.
*/
public GrammarException(String msg) {
super(msg);
}
/**
- * Create a new grammar exception with the specified message and
- * cause.
+ * Create a new grammar exception with the specified message and cause.
*
* @param msg
- * The message for this exception.
+ * The message for this exception.
*
* @param cause
- * The cause of this exception.
+ * The cause of this exception.
*/
public GrammarException(String msg, Exception cause) {
super(msg, cause);
@@ -40,7 +38,9 @@ public class GrammarException extends RuntimeException {
* Create a new grammar exception with the specified message.
*
* @param msg
- * The message for this exception.
+ * The message for this exception.
+ * @param rootMsg
+ * The root message for this exception
*/
public GrammarException(String msg, String rootMsg) {
super(msg);
@@ -49,14 +49,15 @@ public class GrammarException extends RuntimeException {
}
/**
- * Create a new grammar exception with the specified message and
- * cause.
+ * Create a new grammar exception with the specified message and cause.
*
* @param msg
- * The message for this exception.
+ * The message for this exception.
*
* @param cause
- * The cause of this exception.
+ * The cause of this exception.
+ * @param rootMsg
+ * The root message for this exception.
*/
public GrammarException(String msg, Exception cause, String rootMsg) {
super(msg, cause);
@@ -70,6 +71,6 @@ public class GrammarException extends RuntimeException {
* @return The root cause of this exception.
*/
public String getRootMessage() {
- return rootMessage == null? getMessage() : rootMessage;
+ return rootMessage == null ? getMessage() : rootMessage;
}
}
diff --git a/src/main/java/bjc/rgens/parser/NormalRuleCase.java b/src/main/java/bjc/rgens/parser/NormalRuleCase.java
index 705a118..9663815 100644
--- a/src/main/java/bjc/rgens/parser/NormalRuleCase.java
+++ b/src/main/java/bjc/rgens/parser/NormalRuleCase.java
@@ -39,6 +39,7 @@ public class NormalRuleCase extends RuleCase {
*
* @return A normal rule case with those elements.
*/
+ @Override
public NormalRuleCase withElements(List<CaseElement> elms) {
return new NormalRuleCase(elms);
}
diff --git a/src/main/java/bjc/rgens/parser/RGrammar.java b/src/main/java/bjc/rgens/parser/RGrammar.java
index 4fe1d79..612fcfe 100755
--- a/src/main/java/bjc/rgens/parser/RGrammar.java
+++ b/src/main/java/bjc/rgens/parser/RGrammar.java
@@ -48,6 +48,10 @@ public class RGrammar {
/* The default post-processing rules to apply. */
private static final List<IPair<String, String>> builtinPostprocs;
+
+ /**
+ * Should we use the built-in post-processing procedures?
+ */
public boolean useBuiltinPostprocs = true;
/* The max distance between possible alternate rules. */
@@ -103,24 +107,19 @@ public class RGrammar {
IPair<String, String> collapseDupSpaces = pair("\\s+", " ");
/* Built-in post-processing steps */
- builtinPostprocs = Arrays.asList(
- collapseDupSpaces,
+ builtinPostprocs = Arrays.asList(collapseDupSpaces,
- /*
- * Remove extraneous spaces around punctuation
- * marks, forced by the way the language syntax
- * works.
+ /*
+ * Remove extraneous spaces around punctuation marks, forced by the way
+ * the language syntax works.
*
- * This can be done in grammars, but it is quite
- * tedious to do so.
+ * This can be done in grammars, but it is quite tedious to do so.
*/
-
/* Handle 's */
pair(" 's ", "'s "),
/* Handle opening/closing punctuation. */
- pair("([(\\[]) ", " $1"),
- pair(" ([)\\]'\"])", "$1 "),
+ pair("([(\\[]) ", " $1"), pair(" ([)\\]'\"])", "$1 "),
/* Remove spaces around series of opening/closing punctuation. */
pair("([(\\[])\\s+([(\\[])", "$1$2"),
pair("([)\\]])\\s+([)\\]])", "$1$2"),
@@ -132,20 +131,19 @@ public class RGrammar {
collapseDupSpaces,
/* Replace this once it is no longer needed. */
- pair("\\s(ish|burg|ton|ville|opolis|field|boro|dale)", "$1")
- );
+ pair("\\s(ish|burg|ton|ville|opolis|field|boro|dale)", "$1"));
}
/**
* Create a new randomized grammar using the specified set of rules.
*
* @param ruls
- * The rules to use.
+ * The rules to use.
*/
public RGrammar(Map<String, Rule> ruls) {
rules = ruls;
- for(Rule rl : ruls.values()) {
+ for (Rule rl : ruls.values()) {
rl.belongsTo = this;
}
@@ -159,7 +157,7 @@ public class RGrammar {
* checked.
*
* @param importedRules
- * The set of imported rules to use.
+ * The set of imported rules to use.
*/
public void setImportedRules(Map<String, Rule> importedRules) {
importRules = importedRules;
@@ -169,7 +167,8 @@ public class RGrammar {
* Generates the data structure backing rule suggestions for unknown rules.
*/
public void generateSuggestions() {
- MutableBkTree<String> ruleSuggester = new MutableBkTree<>(new LevenshteinMetric());
+ MutableBkTree<String> ruleSuggester
+ = new MutableBkTree<>(new LevenshteinMetric());
ruleSuggester.addAll(rules.keySet());
ruleSuggester.addAll(importRules.keySet());
@@ -181,8 +180,8 @@ public class RGrammar {
* 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.
+ * The rule to start generating at, or null to use the initial
+ * rule for this grammar.
*
* @return A possible string from the grammar.
*/
@@ -194,16 +193,17 @@ public class RGrammar {
* 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.
+ * The rule to start generating at, or null to use the initial
+ * rule for this grammar.
*
* @param rnd
- * The random number generator to use.
+ * The random number generator to use.
*
* @param vars
- * The set of variables to use.
+ * The set of variables to use.
*
* @param rlVars
- * The set of rule variables to use.
+ * The set of rule variables to use.
*
* @return A possible string from the grammar.
*/
@@ -218,10 +218,13 @@ public class RGrammar {
* 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.
+ * The rule to start generating at, or null to use the initial
+ * rule for this grammar.
*
* @param state
- * The generation state.
+ * The generation state.
+ *
+ * @return The generated string.
*/
public String generate(String startRule, GenerationState state) {
return generate(startRule, state, true);
@@ -231,20 +234,26 @@ public class RGrammar {
* 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.
+ * The rule to start generating at, or null to use the
+ * initial rule for this grammar.
*
* @param doPostprocess
- * Whether or not we should perform post-processing of our output.
+ * Whether or not we should perform post-processing of our
+ * output.
*
* @param state
- * The generation state.
+ * The generation state.
+ *
+ * @return The generated string.
*/
- public String generate(String startRule, GenerationState state, boolean doPostprocess) {
+ public String generate(String startRule, GenerationState state,
+ boolean doPostprocess) {
String fromRule = startRule;
if (startRule == null) {
if (initialRule == null) {
- throw new GrammarException("Must specify a start rule for grammars with no initial rule");
+ throw new GrammarException(
+ "Must specify a start rule for grammars with no initial rule");
}
fromRule = initialRule;
@@ -254,17 +263,20 @@ public class RGrammar {
}
}
- /* We don't search imports for the initial rule, so it will always belong to this grammar. */
+ /*
+ * We don't search imports for the initial rule, so it will always belong to
+ * this grammar.
+ */
Rule rl = state.findRule(fromRule, false);
- if(rl == null)
+ if (rl == null)
throw new GrammarException("Could not find rule " + fromRule);
rl.generate(state);
String body = state.getContents();
- if(doPostprocess) {
+ if (doPostprocess) {
body = postprocessRes(body);
}
@@ -275,26 +287,27 @@ public class RGrammar {
private String postprocessRes(String strang) {
String body = strang;
- if(useBuiltinPostprocs) {
- for(IPair<String, String> par : builtinPostprocs) {
+ if (useBuiltinPostprocs) {
+ for (IPair<String, String> par : builtinPostprocs) {
body = body.replaceAll(par.getLeft(), par.getRight());
}
}
- for(IPair<String, String> par : postprocs) {
+ for (IPair<String, String> par : postprocs) {
body = body.replaceAll(par.getLeft(), par.getRight());
}
return body.trim();
}
+
/**
* Generate a rule case.
*
* @param start
- * The rule case to generate.
+ * The rule case to generate.
*
* @param state
- * The current generation state.
+ * The current generation state.
*/
public void generateCase(RuleCase start, GenerationState state) {
try {
@@ -318,7 +331,8 @@ public class RGrammar {
* Set the initial rule of this grammar.
*
* @param initRule
- * The initial rule of this grammar, or null to say there is no initial rule.
+ * The initial rule of this grammar, or null to say there is no
+ * initial rule.
*/
public void setInitialRule(String initRule) {
setInitialRule(initRule, new Tree<>());
@@ -328,10 +342,11 @@ public class RGrammar {
* Set the initial rule of this grammar.
*
* @param initRule
- * The initial rule of this grammar, or null to say there is no initial rule.
+ * The initial rule of this grammar, or null to say there is no
+ * initial rule.
*
* @param errs
- * The tree to store errors in.
+ * The tree to store errors in.
*/
public void setInitialRule(String initRule, ITree<String> errs) {
/* Passing null, nulls our initial rule. */
@@ -346,7 +361,9 @@ public class RGrammar {
return;
} else if (!rules.containsKey(initRule)) {
- String msg = String.format("ERROR: No rule '%s' local to this grammar (%s) defined.", initRule, name);
+ String msg = String.format(
+ "ERROR: No rule '%s' local to this grammar (%s) defined.", initRule,
+ name);
errs.addChild(msg);
@@ -368,7 +385,8 @@ public class RGrammar {
for (String rname : exportRules) {
if (!rules.containsKey(rname)) {
- String msg = String.format("No rule '%s' local to this grammar (%s) defined for export",
+ String msg = String.format(
+ "No rule '%s' local to this grammar (%s) defined for export",
name, rname);
throw new GrammarException(msg);
@@ -388,7 +406,7 @@ public class RGrammar {
* Set the rules exported by this grammar.
*
* @param exportedRules
- * The rules exported by this grammar.
+ * The rules exported by this grammar.
*/
public void setExportedRules(Set<String> exportedRules) {
exportRules = exportedRules;
@@ -403,12 +421,26 @@ public class RGrammar {
return rules;
}
+ /**
+ * Get the rules imported into this grammar.
+ *
+ * @return The rules imported into this grammar.
+ */
public Map<String, Rule> getImportRules() {
return importRules;
}
- public void setAutoVars(Map<String, CaseElement> aVars, Map<String, CaseElement> aRlVars) {
- autoVars = aVars;
+ /**
+ * Set up the auto-variable sets.
+ *
+ * @param aVars
+ * The auto-variables to use.
+ * @param aRlVars
+ * The rule-auto-variables to use.
+ */
+ public void setAutoVars(Map<String, CaseElement> aVars,
+ Map<String, CaseElement> aRlVars) {
+ autoVars = aVars;
autoRlVars = aRlVars;
}
}
diff --git a/src/main/java/bjc/rgens/parser/RGrammarBuilder.java b/src/main/java/bjc/rgens/parser/RGrammarBuilder.java
index 820cf6b..e7e799e 100755
--- a/src/main/java/bjc/rgens/parser/RGrammarBuilder.java
+++ b/src/main/java/bjc/rgens/parser/RGrammarBuilder.java
@@ -32,7 +32,10 @@ public class RGrammarBuilder {
private Set<String> exportedRules;
/* The current initial rule. */
private String initialRule;
- /* The current grammar name. */
+
+ /**
+ * The current grammar name.
+ */
public String name;
/* Autovivify variables */
@@ -61,7 +64,18 @@ public class RGrammarBuilder {
public Rule getOrCreateRule(String rName) {
return getOrCreateRule(rName, new Tree<>());
}
-
+
+ /**
+ * Get or create a rule by the given name.
+ *
+ * @param rName
+ * The name of the rule.
+ *
+ * @param errs The place to put errors.
+ *
+ * @return
+ * The rule by that name, or a new one if none existed.
+ */
public Rule getOrCreateRule(String rName, ITree<String> errs) {
if(rName == null) {
errs.addChild("ERROR: Rule name must not be null");
@@ -132,6 +146,17 @@ public class RGrammarBuilder {
// FIXME do something if errs has a result.
}
+ /**
+ * Set the initial rule of the grammar.
+ *
+ * @param init
+ * The initial rule of the grammar.
+ *
+ * @param errs The place to put errors.
+ *
+ * @throws IllegalArgumentException
+ * If the rule is either not valid or not defined in the grammar.
+ */
public void setInitialRule(String init, ITree<String> errs) {
if (init == null) {
errs.addChild("init must not be null");
@@ -159,6 +184,17 @@ public class RGrammarBuilder {
addExport(export, new Tree<>());
}
+ /**
+ * Add an exported rule to this grammar.
+ *
+ * @param export
+ * The name of the rule to export.
+ *
+ * @param errs The place to put errors.
+ *
+ * @throws IllegalArgumentException
+ * If the rule is either not valid or not defined in the grammar.
+ */
public void addExport(String export, ITree<String> errs) {
if (export == null) {
errs.addChild("ERROR: Export name must not be null");
@@ -225,24 +261,42 @@ public class RGrammarBuilder {
affixWith(ruleName, prefixes, AffixType.CIRCUMFIX, new Tree<>());
}
- public static enum AffixType {
- CIRCUMFIX,
- SUFFIX,
- PREFIX;
-
- public boolean isSuffix() {
- return this != PREFIX;
- }
-
- public boolean isPrefix() {
- return this != SUFFIX;
- }
- }
-
+ /**
+ * Affix a given case element to every case of a specific rule.
+ *
+ * @param ruleName
+ * The rule to affix.
+ *
+ * @param affixes
+ * The affixes to add.
+ *
+ * @param type The type of affixing to perform.
+ *
+ * @throws IllegalArgumentException
+ * If the rule name is either invalid or not defined by this
+ * grammar, or if the prefix/suffix is invalid.
+ */
public void affixWith(String ruleName, List<CaseElement> affixes, AffixType type) {
affixWith(ruleName, affixes, type, new Tree<>());
}
+ /**
+ * Affix a given case element to every case of a specific rule.
+ *
+ * @param ruleName
+ * The rule to affix.
+ *
+ * @param affixes
+ * The affixes to add.
+ *
+ * @param type The type of affixing to perform.
+ *
+ * @param errs The place to put errors.
+ *
+ * @throws IllegalArgumentException
+ * If the rule name is either invalid or not defined by this
+ * grammar, or if the prefix/suffix is invalid.
+ */
public void affixWith(String ruleName, List<CaseElement> affixes, AffixType type, ITree<String> errs) {
if (ruleName == null) {
errs.addChild("ERROR: Rule name must not be null");
@@ -300,10 +354,22 @@ public class RGrammarBuilder {
}
}
+ /**
+ * Perform despacing on a rule.
+ *
+ * @param ruleName The rule to perform despacing on.
+ */
public void despaceRule(String ruleName) {
despaceRule(ruleName, new Tree<>(), false);
}
-
+
+ /**
+ * Perform despacing on a rule.
+ *
+ * @param ruleName The rule to perform despacing on.
+ * @param errs The place to put errors.
+ * @param doTrace Whether or not to do tracing.
+ */
public void despaceRule(String ruleName, ITree<String> errs, boolean doTrace) {
if (ruleName == null) {
errs.addChild("ERROR: Rule name must not be null");
@@ -338,10 +404,21 @@ public class RGrammarBuilder {
rules.get(ruleName).replaceCases(newCaseList);
}
+ /**
+ * Set the weight for a rule.
+ *
+ * @param ruleName The rule to set the weight for.
+ */
public void setWeight(String ruleName) {
setWeight(ruleName, new Tree<>());
}
+ /**
+ * Set the weight for a rule.
+ *
+ * @param ruleName The rule to set the weight for.
+ * @param errs The place to put errors.
+ */
public void setWeight(String ruleName, ITree<String> errs) {
if (ruleName == null) {
errs.addChild("ERROR: Rule name must not be null");
@@ -362,10 +439,23 @@ public class RGrammarBuilder {
rules.get(ruleName).prob = Rule.ProbType.NORMAL;
}
+ /**
+ * Set the rule recurrence limit.
+ *
+ * @param ruleName The name of the rule.
+ * @param recurLimit The limit of the number of times to recur.
+ */
public void setRuleRecur(String ruleName, int recurLimit) {
setRuleRecur(ruleName, recurLimit, new Tree<>());
}
+ /**
+ * Set the rule recurrence limit.
+ *
+ * @param ruleName The name of the rule.
+ * @param recurLimit The limit of the number of times to recur.
+ * @param errs The place to put errors.
+ */
public void setRuleRecur(String ruleName, int recurLimit, ITree<String> errs) {
if (ruleName == null) {
errs.addChild("ERROR: Rule name must not be null");
@@ -386,10 +476,23 @@ public class RGrammarBuilder {
rules.get(ruleName).recurLimit = recurLimit;
}
+ /**
+ * Set probability descent on the rule.
+ *
+ * @param ruleName The name of the rule.
+ * @param descentFactor The amount to descend by every time.
+ */
public void setDescent(String ruleName, int descentFactor) {
setDescent(ruleName, descentFactor, new Tree<>());
}
+ /**
+ * Set probability descent on the rule.
+ *
+ * @param ruleName The name of the rule.
+ * @param descentFactor The amount to descend by every time.
+ * @param errs Place to put errors.
+ */
public void setDescent(String ruleName, int descentFactor, ITree<String> errs) {
if (ruleName == null) {
errs.addChild("ERROR: Rule name must not be null");
@@ -413,10 +516,27 @@ public class RGrammarBuilder {
rl.descentFactor = descentFactor;
}
+ /**
+ * Set the binomial distribution on a rule.
+ *
+ * @param ruleName The name of the rule.
+ * @param target The target weighting.
+ * @param bound The bound for the distribution.
+ * @param trials The number of trials for the distribution.
+ */
public void setBinomial(String ruleName, int target, int bound, int trials) {
setBinomial(ruleName, target, bound, trials, new Tree<>());
}
+ /**
+ * Set the binomial distribution on a rule.
+ *
+ * @param ruleName The name of the rule.
+ * @param target The target weighting.
+ * @param bound The bound for the distribution.
+ * @param trials The number of trials for the distribution.
+ * @param errs The place to put errors.
+ */
public void setBinomial(String ruleName, int target, int bound, int trials, ITree<String> errs) {
if (ruleName == null) {
errs.addChild("ERROR: Rule name must not be null");
@@ -442,18 +562,43 @@ public class RGrammarBuilder {
rl.trials = trials;
}
- public void addAutoVar(String name, CaseElement elm) {
- autoVars.put(name, elm);
+ /**
+ * Add an auto-variable.
+ *
+ * @param nam The name of the variable to add.
+ * @param elm The definition of the variable.
+ */
+ public void addAutoVar(String nam, CaseElement elm) {
+ autoVars.put(nam, elm);
}
- public void addAutoRlVar(String name, CaseElement elm) {
- autoRlVars.put(name, elm);
+ /**
+ * Add an auto-rule-variable.
+ *
+ * @param nam The name of the rule variable to add.
+ * @param elm The definition of the rule variable.
+ */
+ public void addAutoRlVar(String nam, CaseElement elm) {
+ autoRlVars.put(nam, elm);
}
+ /**
+ * Add a rule rejection.
+ *
+ * @param rule The name of the rule.
+ * @param reject The rejection for the rule.
+ */
public void rejectRule(String rule, String reject) {
rejectRule(rule, reject, new Tree<>());
}
+ /**
+ * Add a rule rejection.
+ *
+ * @param rule The name of the rule.
+ * @param reject The rejection for the rule.
+ * @param errs The place to put errors.
+ */
public void rejectRule(String rule, String reject, ITree<String> errs) {
if (rule == null) {
errs.addChild("ERROR: Rule must not be null");
@@ -480,10 +625,25 @@ public class RGrammarBuilder {
rl.addRejection(reject, errs);
}
+ /**
+ * Add a find/replace to a rule.
+ *
+ * @param rule The name of the rule
+ * @param find The find string.
+ * @param replace The replace string.
+ */
public void findReplaceRule(String rule, String find, String replace) {
findReplaceRule(rule, find, replace, new Tree<>());
}
+ /**
+ * Add a find/replace to a rule.
+ *
+ * @param rule The name of the rule
+ * @param find The find string.
+ * @param replace The replace string.
+ * @param errs The place to put errors.
+ */
public void findReplaceRule(String rule, String find, String replace, ITree<String> errs) {
if (rule == null) {
errs.addChild("ERROR: Rule must not be null");
diff --git a/src/main/java/bjc/rgens/parser/RGrammarLogging.java b/src/main/java/bjc/rgens/parser/RGrammarLogging.java
index 4dba117..dbc36b4 100644
--- a/src/main/java/bjc/rgens/parser/RGrammarLogging.java
+++ b/src/main/java/bjc/rgens/parser/RGrammarLogging.java
@@ -7,14 +7,31 @@ package bjc.rgens.parser;
* @author Ben Culkin
*/
public final class RGrammarLogging {
+ /**
+ * Log a message.
+ * @param msg The message to log.
+ * @param vars The variable for the message.
+ */
public static void log(String msg, Object... vars) {
System.err.printf(msg, vars);
}
-
+
+ /**
+ * Log a message, including a newline.
+ * @param msg The message to log.
+ * @param vars The variable for the message.
+ */
public static void logline(String msg, Object... vars) {
log(msg + "\n", vars);
}
+ /**
+ * Log an error, including an exception stack trace.
+ *
+ * @param ex The exception which caused this error.
+ * @param msg The message to log.
+ * @param vars The variables for the message.
+ */
public static void error(Exception ex, String msg, Object... vars) {
logline("ERROR: " + msg, vars);
@@ -24,26 +41,62 @@ public final class RGrammarLogging {
logline("");
}
+ /**
+ * Log a performance message.
+ *
+ * @param msg The message to log.
+ * @param vars The variable for the message.
+ */
public static void perf(String msg, Object... vars) {
logline("\tPERF: " + msg, vars);
}
+ /**
+ * Log a info message.
+ *
+ * @param msg The message to log.
+ * @param vars The variable for the message.
+ */
public static void info(String msg, Object... vars) {
logline("INFO: " + msg, vars);
}
+ /**
+ * Log a trace message.
+ *
+ * @param msg The message to log.
+ * @param vars The variable for the message.
+ */
public static void trace(String msg, Object... vars) {
logline("\t\tTRACE: " + msg, vars);
}
+ /**
+ * Log a warn message.
+ *
+ * @param msg The message to log.
+ * @param vars The variable for the message.
+ */
public static void warn(String msg, Object... vars) {
logline("WARN: " + msg, vars);
}
+ /**
+ * Log a debug message.
+ *
+ * @param msg The message to log.
+ * @param vars The variable for the message.
+ */
public static void debug(String msg, Object... vars) {
logline("\tDEBUG: " + msg, vars);
}
+ /**
+ * Log a fine message.
+ *
+ * @param msg The message to log.
+ * @param vars The variable for the message.
+ */
public static void fine(String msg, Object... vars) {
logline("\t\tFINE: " + msg, vars);
}
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);
}
diff --git a/src/main/java/bjc/rgens/parser/RGrammarSet.java b/src/main/java/bjc/rgens/parser/RGrammarSet.java
index 05823ec..c87c02a 100755
--- a/src/main/java/bjc/rgens/parser/RGrammarSet.java
+++ b/src/main/java/bjc/rgens/parser/RGrammarSet.java
@@ -14,10 +14,19 @@ import java.util.TreeMap;
* @author EVE
*/
public class RGrammarSet {
+ /**
+ * The name for this grammar set.
+ */
public String name;
+ /**
+ * The config set this grammar set belongs to.
+ */
public ConfigSet belongsTo;
+ /**
+ * The grammar which contains the exports of this grammar set.
+ */
public RGrammar exportGrammar;
/* Contains all the grammars in this set. */
@@ -26,17 +35,21 @@ public class RGrammarSet {
/* Contains all the exported rules from grammars. */
private Map<String, Rule> exportedRules;
- /* Contains which file a grammar was loaded from. */
+ /**
+ * Contains which file a grammar was loaded from.
+ */
public Map<String, String> loadedFrom;
- /* @NOTE These are replaced by the logging setup */
- public static final boolean PERF = true;
-
/** Create a new set of randomized grammars. */
public RGrammarSet() {
this(false);
}
+ /**
+ * Create a new set of randomized grammars.
+ *
+ * @param orderExports Should the exports be ordered?
+ */
public RGrammarSet(boolean orderExports) {
grammars = new HashMap<>();
diff --git a/src/main/java/bjc/rgens/parser/RegexRuleCase.java b/src/main/java/bjc/rgens/parser/RegexRuleCase.java
index e124205..1cffca3 100755
--- a/src/main/java/bjc/rgens/parser/RegexRuleCase.java
+++ b/src/main/java/bjc/rgens/parser/RegexRuleCase.java
@@ -9,12 +9,14 @@ import java.util.List;
*
* Actually implement this
*/
+@SuppressWarnings("javadoc")
public class RegexRuleCase extends RuleCase {
public RegexRuleCase(List<CaseElement> elements) {
super(elements);
}
+ @Override
public void generate(GenerationState state) {
// TODO
}
diff --git a/src/main/java/bjc/rgens/parser/Rule.java b/src/main/java/bjc/rgens/parser/Rule.java
index 59240bb..3ade828 100755
--- a/src/main/java/bjc/rgens/parser/Rule.java
+++ b/src/main/java/bjc/rgens/parser/Rule.java
@@ -21,6 +21,9 @@ import java.util.regex.PatternSyntaxException;
* @author EVE
*/
public class Rule {
+ /**
+ * The grammar this rule belongs to.
+ */
public RGrammar belongsTo;
/** The name of this grammar rule. */
@@ -35,26 +38,60 @@ public class Rule {
* Perhaps this should be split into subclasses along prob type? I'm not
* sure as to whether or not that would be a useful thing to do.
*/
+ /**
+ * Type of probability to use for this rule.
+ *
+ * @author Ben Culkin
+ *
+ */
public static enum ProbType {
+ /**
+ * Normal-type probability.
+ */
NORMAL,
+ /**
+ * Descent-type probability.
+ */
DESCENDING,
+ /**
+ * Binomial-type probability.
+ */
BINOMIAL
}
+ /**
+ * Type of probability to use for this rule.
+ */
public ProbType prob;
// Probability vars
/* Descent vars */
+ /**
+ * Factor for probability to descend by.
+ */
public int descentFactor;
+
/* Binomial vars */
+ /**
+ * Target for the binomial probability.
+ */
public int target;
+ /**
+ * Bound for the binomial probability.
+ */
public int bound;
+ /**
+ * Trials for the binomial probability.
+ */
public int trials;
private List<String> rejectionPreds;
private List<IPair<String, String>> findReplaces;
// @TODO This default should be configurable in some way
+ /**
+ * Number of times this rule can recur.
+ */
public int recurLimit = 5;
private int currentRecur;
@@ -109,6 +146,7 @@ public class Rule {
*
* @param cse
* The case to add.
+ * @param weight The weight for this case.
*/
public void addCase(RuleCase cse, int weight) {
if (cse == null) {
@@ -121,10 +159,21 @@ public class Rule {
cases.addProbability(weight, cse);
}
+ /**
+ * Add a rejection pattern to this rule.
+ *
+ * @param reject The rejection pattern.
+ */
public void addRejection(String reject) {
addRejection(reject, new Tree<>());
}
+ /**
+ * Add a rejection pattern to this rule.
+ *
+ * @param reject The rejection pattern.
+ * @param errs The place to put errors.
+ */
public void addRejection(String reject, ITree<String> errs) {
try {
Pattern.compile(reject);
@@ -135,10 +184,23 @@ public class Rule {
rejectionPreds.add(reject);
}
+ /**
+ * Add a find/replace pattern to this rule.
+ *
+ * @param find The find string.
+ * @param replace The replace string.
+ */
public void addFindReplace(String find, String replace) {
addFindReplace(find, replace, new Tree<>());
}
+ /**
+ * Add a find/replace pattern to this rule.
+ *
+ * @param find The find string.
+ * @param replace The replace string.
+ * @param errs The place to put errors.
+ */
public void addFindReplace(String find, String replace, ITree<String> errs) {
try {
Pattern.compile(find);
@@ -198,13 +260,13 @@ public class Rule {
/**
* Replace the current list of cases with a new one.
*
- * @param cases
+ * @param caseList
* The new list of cases.
*/
- public void replaceCases(IList<IPair<Integer, RuleCase>> cases) {
+ public void replaceCases(IList<IPair<Integer, RuleCase>> caseList) {
this.cases = new WeightedRandom<>();
- for(IPair<Integer, RuleCase> cse : cases) {
+ for(IPair<Integer, RuleCase> cse : caseList) {
RuleCase cs = cse.getRight();
cs.belongsTo = this;
cs.debugName = String.format("%s-%d", name, ++caseCount);
@@ -250,6 +312,11 @@ public class Rule {
return String.format("Rule '%s' with %d cases", name, cases.getValues().getSize());
}
+ /**
+ * Start recurring on this rule.
+ *
+ * @return Whether the recurrence rule has been exceeded.
+ */
public boolean doRecur() {
if(currentRecur > recurLimit) return false;
@@ -258,11 +325,22 @@ public class Rule {
return true;
}
+ /**
+ * End recurring on this rule.
+ */
public void endRecur() {
- if(currentRecur > 0) currentRecur -= 1;
- else throw new IllegalStateException("endRecur without matching doRecur");
+ if(currentRecur > 0) {
+ currentRecur -= 1;
+ } else {
+ throw new IllegalStateException("endRecur without matching doRecur");
+ }
}
+ /**
+ * Get an exhaustive version of this rule.
+ *
+ * @return An exhaustive version of this rule.
+ */
public Rule exhaust() {
Rule rl = new Rule(name);
@@ -292,6 +370,11 @@ public class Rule {
return rl;
}
+ /**
+ * Generate this rule.
+ *
+ * @param state The generation state to use.
+ */
public void generate(GenerationState state) {
state.swapGrammar(belongsTo);
diff --git a/src/main/java/bjc/rgens/parser/RuleCase.java b/src/main/java/bjc/rgens/parser/RuleCase.java
index dacb16e..3cfe81d 100755
--- a/src/main/java/bjc/rgens/parser/RuleCase.java
+++ b/src/main/java/bjc/rgens/parser/RuleCase.java
@@ -15,14 +15,25 @@ import java.util.List;
* @author EVE
*/
public abstract class RuleCase {
+ /**
+ * Debugging name for this case.
+ */
public String debugName;
+ /**
+ * Serial number for this case.
+ */
public final int serial;
-
private static int nextSerial = 0;
+ /**
+ * The rule this case belongs to.
+ */
public Rule belongsTo;
+ /**
+ * The elements that make up this case.
+ */
public List<CaseElement> elementList;
/**
@@ -40,10 +51,23 @@ public abstract class RuleCase {
nextSerial += 1;
}
+ /**
+ * Generate this case.
+ *
+ * @param state The state to use.
+ */
public abstract void generate(GenerationState state);
+ /**
+ * Create a new case with a different set of elements.
+ *
+ * @param elements The elements for this case.
+ *
+ * @return The case with the same settings, but a different set of elements.
+ */
public abstract RuleCase withElements(List<CaseElement> elements);
+ @Override
public String toString() {
if(debugName != null) {
return String.format("Case %s (#%d) of %s", debugName, serial, belongsTo);
diff --git a/src/main/java/bjc/rgens/parser/elements/CaseElement.java b/src/main/java/bjc/rgens/parser/elements/CaseElement.java
index 76b4efe..9fd565d 100755
--- a/src/main/java/bjc/rgens/parser/elements/CaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/CaseElement.java
@@ -40,6 +40,9 @@ public abstract class CaseElement {
/** The type of this element. */
public boolean spacing;
+ /**
+ * Create a new case element.
+ */
protected CaseElement() {
this(true);
}
@@ -47,8 +50,8 @@ public abstract class CaseElement {
/**
* Create a new case element.
*
- * @param typ
- * The type of this element.
+ * @param spacing
+ * Whether or not to allow spacing.
*/
protected CaseElement(boolean spacing) {
this.spacing = spacing;
@@ -58,7 +61,7 @@ public abstract class CaseElement {
* Generate this case element.
*
* @param state
- * The current state of generation.
+ * The current state of generation.
*/
public abstract void generate(GenerationState state);
@@ -66,7 +69,7 @@ public abstract class CaseElement {
* Create a case element from a string.
*
* @param csepart
- * The string to convert.
+ * The string to convert.
*
* @return A case element representing the string.
*/
@@ -85,27 +88,31 @@ public abstract class CaseElement {
String specialBody = csepart.substring(1, csepart.length() - 1);
if (specialBody.matches("\\S+:\\S=\\S+")) {
- String[] parts = LevelSplitter.def.levelSplit(specialBody, "=").toArray(new String[0]);
+ String[] parts = LevelSplitter.def.levelSplit(specialBody, "=")
+ .toArray(new String[0]);
- if(parts.length != 2) {
- throw new GrammarException("Colon variables must have a name and a definition");
+ if (parts.length != 2) {
+ throw new GrammarException(
+ "Colon variables must have a name and a definition");
}
String varName = parts[0];
char op = varName.charAt(varName.length() - 1);
- trace("Colon definition w/ op %d", (int)op);
+ trace("Colon definition w/ op %d", (int) op);
// Remove the colon, plus any tacked on operator
varName = varName.substring(0, varName.length() - 2);
return VariableDefCaseElement.parseVariable(varName, parts[1], op, true);
} else if (specialBody.matches("\\S+:=\\S+")) {
- String[] parts = LevelSplitter.def.levelSplit(specialBody, "=").toArray(new String[0]);
+ String[] parts = LevelSplitter.def.levelSplit(specialBody, "=")
+ .toArray(new String[0]);
- if(parts.length != 2) {
- throw new GrammarException("Colon variables must have a name and a definition");
+ if (parts.length != 2) {
+ throw new GrammarException(
+ "Colon variables must have a name and a definition");
}
String varName = parts[0];
@@ -114,41 +121,49 @@ public abstract class CaseElement {
return VariableDefCaseElement.parseVariable(varName, parts[1], ' ', true);
} else if (specialBody.matches("\\S+=\\S+")) {
- String[] parts = LevelSplitter.def.levelSplit(specialBody, "=").toArray(new String[0]);
- if(parts.length != 2) {
- throw new GrammarException("Variables must have a name and a definition");
+ String[] parts = LevelSplitter.def.levelSplit(specialBody, "=")
+ .toArray(new String[0]);
+ if (parts.length != 2) {
+ throw new GrammarException(
+ "Variables must have a name and a definition");
}
// Non-colon variables can't take an operator
- return VariableDefCaseElement.parseVariable(parts[0], parts[1], (char)0, false);
+ return VariableDefCaseElement.parseVariable(parts[0], parts[1], (char) 0,
+ false);
} 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));
+ throw new IllegalArgumentException(
+ String.format("Unknown special case part '%s'", specialBody));
}
} else if (csepart.matches("\\[\\S+\\]")) {
String rawCase = csepart.substring(1, csepart.length() - 1);
if (rawCase.matches("\\d+\\.{2}\\d+")) {
- int firstNum = Integer.parseInt(rawCase.substring(0, rawCase.indexOf('.')));
- int secondNum = Integer.parseInt(rawCase.substring(rawCase.lastIndexOf('.') + 1));
+ int firstNum
+ = Integer.parseInt(rawCase.substring(0, rawCase.indexOf('.')));
+ int secondNum = Integer
+ .parseInt(rawCase.substring(rawCase.lastIndexOf('.') + 1));
return new RangeCaseElement(firstNum, secondNum);
- } else if(rawCase.contains("||")) {
- String[] elms = LevelSplitter.def.levelSplit(rawCase, "||").toArray(new String[0]);
+ } else if (rawCase.contains("||")) {
+ String[] elms = LevelSplitter.def.levelSplit(rawCase, "||")
+ .toArray(new String[0]);
return new InlineRuleCaseElement(elms);
- } else if(rawCase.contains("|")) {
+ } else if (rawCase.contains("|")) {
throw new GrammarException("Inline rule using | found, they use || now");
- // String[] elms = LevelSplitter.def.levelSplit(rawCase, "|").toArray(new String[0]);
+ // String[] elms = LevelSplitter.def.levelSplit(rawCase, "|").toArray(new
+ // String[0]);
// return new InlineRuleCaseElement(elms);
} else {
return new RuleCaseElement(rawCase);
}
- } else if(csepart.startsWith("%") && !csepart.equals("%")) {
- return new RuleCaseElement(csepart);
+ } else if (csepart.startsWith("%") && !csepart.equals("%")) {
+ return new RuleCaseElement(csepart);
} else {
return new LiteralCaseElement(csepart);
}
diff --git a/src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java b/src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java
index 66fbb96..6f3d889 100644
--- a/src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/InlineRuleCaseElement.java
@@ -13,13 +13,33 @@ import bjc.utils.ioutils.LevelSplitter;
import java.util.ArrayList;
import java.util.List;
+/**
+ * Case element for an inline rule.
+ *
+ * @author Ben Culkin
+ *
+ */
public class InlineRuleCaseElement extends CaseElement {
+ /**
+ * The elements for this case element.
+ */
public final WeightedRandom<CaseElement> elements;
+ /**
+ * Create a new inline rule case element.
+ *
+ * @param parts The parts of this case element.
+ */
public InlineRuleCaseElement(String... parts) {
this(new Tree<>(), parts);
}
+ /**
+ * Create a new inline rule case element.
+ *
+ * @param errs The place to store errors in.
+ * @param parts The parts of this case element.
+ */
public InlineRuleCaseElement(ITree<String> errs, String... parts) {
super(true);
@@ -43,6 +63,7 @@ public class InlineRuleCaseElement extends CaseElement {
}
}
+ @Override
public void generate(GenerationState state) {
elements.generateValue(state.rnd).generate(state);
}
diff --git a/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java
index c5e5c6f..170794e 100755
--- a/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/LitVariableCaseElement.java
@@ -2,11 +2,24 @@ package bjc.rgens.parser.elements;
import bjc.rgens.parser.GenerationState;
+/**
+ * A case element that defines a literal variable.
+ *
+ * @author Ben Culkin
+ *
+ */
public class LitVariableCaseElement extends VariableDefCaseElement {
+ /**
+ * Create a new case element for a literal variable.
+ *
+ * @param name The name for the case element.
+ * @param def The definition for the case element.
+ */
public LitVariableCaseElement(String name, String def) {
super(name, def);
}
+ @Override
public void generate(GenerationState state) {
state.defineVar(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 2621ee6..54c6454 100644
--- a/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/LiteralCaseElement.java
@@ -2,15 +2,29 @@ package bjc.rgens.parser.elements;
import bjc.rgens.parser.GenerationState;
+/**
+ * Case element that appends a literal.
+ * @author Ben Culkin
+ *
+ */
public class LiteralCaseElement extends CaseElement {
+ /**
+ * The value for this element.
+ */
public String val;
+ /**
+ * Create a new case element.
+ *
+ * @param val The value to append.
+ */
public LiteralCaseElement(String val) {
super(true);
this.val = val;
}
+ @Override
public void generate(GenerationState state) {
state.appendContents(val);
}
diff --git a/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java
index bd73f1b..2d3a771 100755
--- a/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/RangeCaseElement.java
@@ -2,10 +2,28 @@ package bjc.rgens.parser.elements;
import bjc.rgens.parser.GenerationState;
+/**
+ * Case element which generates a range of random numbers.
+ *
+ * @author Ben Culkin
+ *
+ */
public class RangeCaseElement extends CaseElement {
+ /**
+ * The beginning point for this range.
+ */
public final int begin;
+
+ /**
+ * The ending point for this range.
+ */
public final int end;
+ /**
+ * Create a new range case element.
+ * @param beg The beginning point for the range.
+ * @param en The ending point for the range.
+ */
public RangeCaseElement(int beg, int en) {
super(true);
@@ -13,6 +31,7 @@ public class RangeCaseElement extends CaseElement {
end = en;
}
+ @Override
public void generate(GenerationState state) {
int val = state.rnd.nextInt(end - begin);
val += begin;
diff --git a/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java
index 1a2cf85..7fe6603 100755
--- a/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java
@@ -8,48 +8,81 @@ import bjc.rgens.parser.RGrammar;
import bjc.rgens.parser.Rule;
import bjc.rgens.parser.elements.vars.VariableElement;
+/**
+ * Case element which references a rule.
+ *
+ * @author Ben Culkin
+ *
+ */
public class RuleCaseElement extends CaseElement {
+ /**
+ * The elements for this rule.
+ */
public List<VariableElement> elements;
+ /**
+ * Create a new case element to reference a rule.
+ *
+ * @param vl
+ * The text of the reference.
+ */
public RuleCaseElement(String vl) {
super(true);
this.elements = VariableElement.parseElementString(vl);
}
+ /**
+ * Create a new case element to reference a rule.
+ *
+ * @param vl
+ * The text of the reference.
+ * @param elements
+ * The elements of the reference.
+ */
public RuleCaseElement(String vl, List<VariableElement> elements) {
super(true);
this.elements = elements;
}
+ @Override
public void generate(GenerationState state) {
GenerationState newState = state.newBuf();
boolean inName = false;
- for(VariableElement elm : elements) {
+ for (VariableElement elm : elements) {
elm.generate(newState);
- if(inName == false) inName = elm.forbidSpaces;
+ if (inName == false)
+ inName = elm.forbidSpaces;
}
String body = newState.getContents();
- if(inName) {
+ if (inName) {
doGenerate(String.format("[%s]", body), state);
} else {
state.appendContents(body);
}
}
+ /**
+ * Do the generation of a rule element.
+ *
+ * @param acName
+ * The name of the rule to generation.
+ * @param state
+ * The generation state.
+ */
protected void doGenerate(String acName, GenerationState state) {
GenerationState newState = state.newBuf();
Rule rl;
String actName = acName;
-
+
if (actName.startsWith("[^")) {
actName = "[" + actName.substring(2);
@@ -58,12 +91,11 @@ public class RuleCaseElement extends CaseElement {
rl = state.findRule(actName, true);
}
- if(rl != null) {
+ if (rl != null) {
RGrammar destGrammar = rl.belongsTo;
newState.swapGrammar(destGrammar);
- /*
- * Don't postprocess the string, we should only do that
- * once.
+ /*
+ * Don't postprocess the string, we should only do that once.
*/
String res = destGrammar.generate(actName, newState, false);
newState.setContents(res);
@@ -74,17 +106,17 @@ public class RuleCaseElement extends CaseElement {
* Re-get this working again.
*/
/*
- if (ruleSearcher != null) {
- Set<Match<? extends String>> results = ruleSearcher.search(actName, 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?)", actName,
- StringUtils.toEnglishList(resArray, false));
-
- throw new GrammarException(msg);
- }
- */
+ * if (ruleSearcher != null) { Set<Match<? extends String>> results =
+ * ruleSearcher.search(actName, 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?)",
+ * actName, StringUtils.toEnglishList(resArray, false));
+ *
+ * throw new GrammarException(msg); }
+ */
String msg = String.format("No rule '%s' defined", actName);
throw new GrammarException(msg);
diff --git a/src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java
index 923b56c..5806e39 100644
--- a/src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/RuleVariableCaseElement.java
@@ -6,15 +6,32 @@ import bjc.rgens.parser.GenerationState;
import bjc.rgens.parser.GrammarException;
import bjc.rgens.parser.Rule;
+/**
+ * Case element which creates a rule variable.
+ *
+ * @author Ben Culkin
+ *
+ */
public class RuleVariableCaseElement extends VariableDefCaseElement {
+ /**
+ * Whether or not this is an exhaustive variable.
+ */
public final boolean exhaust;
+ /**
+ * Create a case element which creates a rule variable.
+ *
+ * @param varName The name of the variable.
+ * @param varDef The definition of the variable.
+ * @param exhaust Whether or not this is an exhaustive variable.
+ */
public RuleVariableCaseElement(String varName, String varDef, boolean exhaust) {
super(varName, varDef);
this.exhaust = exhaust;
}
+ @Override
public void generate(GenerationState state) {
Rule rl = state.findRule(varDef, true);
diff --git a/src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java b/src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java
index 195ba4f..3d15e8c 100644
--- a/src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/SerialCaseElement.java
@@ -2,12 +2,35 @@ package bjc.rgens.parser.elements;
import bjc.rgens.parser.GenerationState;
+/**
+ * Case element which is generated one or more times.
+ *
+ * @author Ben Culkin
+ *
+ */
public class SerialCaseElement extends CaseElement {
+ /**
+ * The case element to repeat.
+ */
public final CaseElement rep;
+ /**
+ * The lower bound of times to repeat.
+ */
public final int lower;
+
+ /**
+ * The upper bound of times to repeat.
+ */
public final int upper;
+ /**
+ * Create a new repeating case element.
+ *
+ * @param rep The case element to repeat.
+ * @param lower The lower bound of times to repeat.
+ * @param upper The upper bound of times to repeat.
+ */
public SerialCaseElement(CaseElement rep, int lower, int upper) {
super(rep.spacing);
@@ -17,6 +40,7 @@ public class SerialCaseElement extends CaseElement {
this.upper = upper;
}
+ @Override
public void generate(GenerationState state) {
int num = state.rnd.nextInt(upper - lower) + lower;
diff --git a/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java b/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java
index 00441c0..2aa720d 100755
--- a/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/StringCaseElement.java
@@ -1,11 +1,26 @@
package bjc.rgens.parser.elements;
+/**
+ * Case element which writes a string.
+ *
+ * @author Ben Culkin
+ *
+ */
public abstract class StringCaseElement extends CaseElement {
+ /**
+ * String written by this element.
+ */
public final String val;
-
+
+ /**
+ * Create a new string inserting case element.
+ *
+ * @param vl
+ * The string to insert.
+ */
protected StringCaseElement(String vl) {
super(true);
-
+
val = vl;
}
@@ -33,7 +48,7 @@ public abstract class StringCaseElement extends CaseElement {
return false;
return true;
}
-
+
@Override
public String toString() {
return val;
diff --git a/src/main/java/bjc/rgens/parser/elements/VariableDefCaseElement.java b/src/main/java/bjc/rgens/parser/elements/VariableDefCaseElement.java
index 37a12b6..23659c7 100755
--- a/src/main/java/bjc/rgens/parser/elements/VariableDefCaseElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/VariableDefCaseElement.java
@@ -2,6 +2,12 @@ package bjc.rgens.parser.elements;
import bjc.rgens.parser.GrammarException;
+/**
+ * Variable defining case element.
+ *
+ * @author Ben Culkin
+ *
+ */
public abstract class VariableDefCaseElement extends CaseElement {
/**
* The name of the variable this element defines.
@@ -13,6 +19,14 @@ public abstract class VariableDefCaseElement extends CaseElement {
*/
public final String varDef;
+ /**
+ * Create a variable defining case element.
+ *
+ * @param name
+ * The name of the variable.
+ * @param def
+ * The definition of the variable.
+ */
public VariableDefCaseElement(String name, String def) {
super(false);
@@ -51,16 +65,33 @@ public abstract class VariableDefCaseElement extends CaseElement {
return true;
}
- public static CaseElement parseVariable(String varName, String varDef, char op, boolean colon) {
- if(varName.startsWith("$")) {
+ /**
+ * Parse a variable reference.
+ *
+ * @param varName
+ * The variable name.
+ * @param varDef
+ * The variable definition.
+ * @param op
+ * Unused as of yet.
+ * @param colon
+ * Whether the colon was present in the declaration.
+ *
+ * @return A case element which declares the variable.
+ */
+ public static CaseElement parseVariable(String varName, String varDef, char op,
+ boolean colon) {
+ if (varName.startsWith("$")) {
// Handle normal/expanding variable definitions
- if(colon) return new ExpVariableCaseElement(varName.substring(1), varDef);
+ if (colon)
+ return new ExpVariableCaseElement(varName.substring(1), varDef);
return new LitVariableCaseElement(varName.substring(1), varDef);
- } else if(varName.startsWith("@")) {
+ } else if (varName.startsWith("@")) {
return new RuleVariableCaseElement(varName.substring(1), varDef, colon);
} else {
- throw new GrammarException("Unrecognized declaration sigil " + varName.charAt(0));
+ throw new GrammarException(
+ "Unrecognized declaration sigil " + varName.charAt(0));
}
}
}
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java
index e7415f5..595397b 100644
--- a/src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/vars/LiteralVariableElement.java
@@ -2,15 +2,31 @@ package bjc.rgens.parser.elements.vars;
import bjc.rgens.parser.GenerationState;
+/**
+ * Case element which references a literal variable.
+ *
+ * @author Ben Culkin
+ *
+ */
public class LiteralVariableElement extends VariableElement {
+ /**
+ * The name for the variable.
+ */
public String val;
+ /**
+ * Create a case element which references a literal variable.
+ *
+ * @param forbidSpaces Whether to forbid spaces in the result.
+ * @param val The name of the literal variable.
+ */
public LiteralVariableElement(boolean forbidSpaces, String val) {
super(forbidSpaces);
this.val = val;
}
+ @Override
public void generate(GenerationState state) {
state.appendContents(val);
}
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java
index e81e9f8..4001b93 100644
--- a/src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/vars/RRefVariableElement.java
@@ -4,15 +4,30 @@ import bjc.rgens.parser.GenerationState;
import bjc.rgens.parser.GrammarException;
import bjc.rgens.parser.Rule;
+/**
+ * Rule reference variable element.
+ * @author Ben Culkin
+ *
+ */
public class RRefVariableElement extends VariableElement {
+ /**
+ * The name of the rule to reference.
+ */
public String value;
+ /**
+ * Create a new rule-reference variable element.
+ *
+ * @param forbidSpaces Whether to forbid spaces or not.
+ * @param val The rule to reference.
+ */
public RRefVariableElement(boolean forbidSpaces, String val) {
super(forbidSpaces);
value = val;
}
+ @Override
public void generate(GenerationState state) {
Rule rl = state.findRule(value, true);
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java
index c753dfe..efd9007 100644
--- a/src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/vars/TRefVariableElement.java
@@ -7,6 +7,7 @@ import bjc.rgens.parser.GenerationState;
*
* finish when template vars are implemented.
*/
+@SuppressWarnings("javadoc")
public class TRefVariableElement extends VariableElement {
public String value;
@@ -16,6 +17,7 @@ public class TRefVariableElement extends VariableElement {
value = val;
}
+ @Override
public void generate(GenerationState state) {
/*
if(!state.rlVars.containsKey(val)) {
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java
index e65d876..cdead80 100644
--- a/src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/vars/VRefVariableElement.java
@@ -3,15 +3,30 @@ package bjc.rgens.parser.elements.vars;
import bjc.rgens.parser.GenerationState;
import bjc.rgens.parser.GrammarException;
+/**
+ * Variable reference variable element.
+ *
+ * @author Ben Culkin
+ *
+ */
public class VRefVariableElement extends VariableElement {
+ /**
+ * The name of the variable to element.
+ */
public final String nam;
+ /**
+ * Create a new variable referencing variable element.
+ * @param forbidSpaces Whether or not to forbid spaces in the element.
+ * @param nam The name of the variable.
+ */
public VRefVariableElement(boolean forbidSpaces, String nam) {
super(forbidSpaces);
this.nam = nam;
}
+ @Override
public void generate(GenerationState state) {
String strang = state.findVar(nam);
diff --git a/src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java b/src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java
index eb36af8..c73e249 100644
--- a/src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java
+++ b/src/main/java/bjc/rgens/parser/elements/vars/VariableElement.java
@@ -7,30 +7,73 @@ import bjc.rgens.parser.GenerationState;
import bjc.rgens.parser.GrammarException;
import bjc.utils.ioutils.LevelSplitter;
+/**
+ * Case element which references a variable.
+ *
+ * @author Ben Culkin
+ *
+ */
public abstract class VariableElement {
+ /**
+ * Whether or not to forbid spaces in this element.
+ */
public boolean forbidSpaces;
+ /**
+ * Create a new variable element.
+ *
+ * @param forbidSpacing
+ * Whether spacing should be forbidden in this element.
+ */
protected VariableElement(boolean forbidSpacing) {
forbidSpaces = forbidSpacing;
}
+ /**
+ * Generate this element.
+ *
+ * @param state
+ * The state of generation.
+ */
public abstract void generate(GenerationState state);
+ /**
+ * Parse a variable element from a string.
+ *
+ * @param varElm
+ * The string to parse.
+ *
+ * @return The variable elements which make up the string.
+ */
public static List<VariableElement> parseElementString(String varElm) {
boolean forbidSpaces = LevelSplitter.def.levelContains(varElm, "-", "+");
String[] parts;
- if(forbidSpaces) {
- parts = LevelSplitter.def.levelSplit(varElm, true, "-", "+").toArray(new String[0]);
+ if (forbidSpaces) {
+ parts = LevelSplitter.def.levelSplit(varElm, true, "-", "+")
+ .toArray(new String[0]);
} else {
- parts = new String[] { varElm };
+ parts = new String[] {
+ varElm
+ };
}
return parseElementString(forbidSpaces, parts);
}
- public static List<VariableElement> parseElementString(boolean forbidSpaces, String... parts) {
+ /**
+ * Parse a string of variable elements.
+ *
+ * @param forbidSpaces
+ * Whether or not to forbid spacing in this variable.
+ * @param parts
+ * The parts to parse into variable elements.
+ *
+ * @return The variable elements from the string.
+ */
+ public static List<VariableElement> parseElementString(boolean forbidSpaces,
+ String... parts) {
List<VariableElement> elms = new ArrayList<>(parts.length);
VariableElement prevElement = null;
@@ -44,23 +87,26 @@ public abstract class VariableElement {
VariableElement elm = null;
- if(part.startsWith("$")) {
+ if (part.startsWith("$")) {
elm = new VRefVariableElement(forbidSpaces, part.substring(1));
} else if (part.startsWith("@")) {
- if(forbidSpaces)
- throw new GrammarException("Arrays references aren't allowed in rule names");
+ if (forbidSpaces)
+ throw new GrammarException(
+ "Arrays references aren't allowed in rule names");
elm = new ARefVariableElement(part.substring(1));
} else if (part.startsWith("%")) {
- elm = new RRefVariableElement(forbidSpaces, String.format("[%s]", part.substring(1)));
+ elm = new RRefVariableElement(forbidSpaces,
+ String.format("[%s]", part.substring(1)));
} else if (part.startsWith("/")) {
throw new GrammarException("Template variables aren't implemented yet");
} else {
- if(prevElement != null && prevElement instanceof LiteralVariableElement) {
+ if (prevElement != null
+ && prevElement instanceof LiteralVariableElement) {
/* Aggregate chain literals together */
- ((LiteralVariableElement)prevElement).val += part;
+ ((LiteralVariableElement) prevElement).val += part;
} else {
- if(part.contains(" ")) {
+ if (part.contains(" ")) {
elm = new LiteralVariableElement(false, part);
} else {
elm = new LiteralVariableElement(true, part);
@@ -68,7 +114,7 @@ public abstract class VariableElement {
}
}
- if(elm != null) {
+ if (elm != null) {
elms.add(elm);
prevElement = elm;
diff --git a/src/main/java/bjc/rgens/parser/templates/LiteralTemplateElement.java b/src/main/java/bjc/rgens/parser/templates/LiteralTemplateElement.java
index 6fa69f1..6bd8b9f 100644
--- a/src/main/java/bjc/rgens/parser/templates/LiteralTemplateElement.java
+++ b/src/main/java/bjc/rgens/parser/templates/LiteralTemplateElement.java
@@ -19,7 +19,10 @@ public class LiteralTemplateElement extends TemplateElement {
* Create a new literal template element.
*
* @param val
- * The string to insert.
+ * The string to insert.
+ *
+ * @param errs
+ * The place to put errors.
*/
public LiteralTemplateElement(String val, ITree<String> errs) {
super(true);
diff --git a/src/main/java/bjc/rgens/parser/templates/TemplateElement.java b/src/main/java/bjc/rgens/parser/templates/TemplateElement.java
index 2d0724b..effd964 100644
--- a/src/main/java/bjc/rgens/parser/templates/TemplateElement.java
+++ b/src/main/java/bjc/rgens/parser/templates/TemplateElement.java
@@ -2,14 +2,38 @@ package bjc.rgens.parser.templates;
import bjc.rgens.parser.GenerationState;
+/**
+ * Abstract element of a template.
+ *
+ * @author Ben Culkin
+ *
+ */
public abstract class TemplateElement {
+ /**
+ * Whether or not to handle spacing.
+ */
public boolean spacing;
+ /**
+ * The template this element belongs to.
+ */
public GrammarTemplate belongsTo;
+ /**
+ * Create a new template element.
+ *
+ * @param spacing
+ * Whether or not to handle spacing.
+ */
protected TemplateElement(boolean spacing) {
this.spacing = spacing;
}
+ /**
+ * Generate this template element.
+ *
+ * @param state
+ * The state for the generation.
+ */
public abstract void generate(GenerationState state);
}