summaryrefslogtreecommitdiff
path: root/RGens/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'RGens/src/main')
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/RGrammar.java61
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java38
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java32
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/RGrammarSet.java123
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/RGrammarTest.java10
-rw-r--r--RGens/src/main/java/bjc/rgens/newparser/RuleCase.java2
6 files changed, 247 insertions, 19 deletions
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java
index 4adcbe8..35fc356 100644
--- a/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java
+++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java
@@ -1,7 +1,8 @@
package bjc.rgens.newparser;
-import java.util.List;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/**
* Represents a randomized grammar.
@@ -20,7 +21,9 @@ public class RGrammar {
private Map<String, Rule> rules;
- private Map<String, Rule> importRules;
+ private Map<String, RGrammar> importRules;
+
+ private Set<String> exportRules;
private String initialRule;
@@ -40,11 +43,11 @@ public class RGrammar {
* Imported rules are checked for rule definitions after local
* definitions are checked.
*
- * @param importedRules
+ * @param exportedRules
* The set of imported rules to use.
*/
- public void setImportedRules(Map<String, Rule> importedRules) {
- importRules = importedRules;
+ public void setImportedRules(Map<String, RGrammar> exportedRules) {
+ importRules = exportedRules;
}
/**
@@ -116,9 +119,9 @@ public class RGrammar {
generateCase(cse, state);
} else if(importRules.containsKey(elm.getLiteral())) {
- RuleCase cse = importRules.get(elm.getLiteral()).getCase();
+ RGrammar dst = importRules.get(elm.getLiteral());
- generateCase(cse, state);
+ state.contents.append(dst.generate(elm.getLiteral()));
} else {
throw new GrammarException(
String.format("No rule by name '%s' found", elm.getLiteral()));
@@ -149,6 +152,14 @@ public class RGrammar {
* is no initial rule.
*/
public void setInitialRule(String initialRule) {
+ /*
+ * Passing null nulls our initial rule.
+ */
+ if(initialRule == null) {
+ this.initialRule = null;
+ return;
+ }
+
if(initialRule.equals("")) {
throw new GrammarException("The empty string is not a valid rule name");
} else if(!rules.containsKey(initialRule)) {
@@ -158,4 +169,40 @@ public class RGrammar {
this.initialRule = initialRule;
}
+
+ /**
+ * Gets the rules exported by this grammar.
+ *
+ * The initial rule is exported by default if specified.
+ *
+ * @return The rules exported by this grammar.
+ */
+ public Set<Rule> getExportedRules() {
+ Set<Rule> res = new HashSet<>();
+
+ for(String rname : exportRules) {
+ if(!rules.containsKey(rname)) {
+ throw new GrammarException(String
+ .format("No rule named '%s' local to this grammar found", initialRule));
+ }
+
+ res.add(rules.get(rname));
+ }
+
+ if(initialRule != null) {
+ res.add(rules.get(initialRule));
+ }
+
+ return res;
+ }
+
+ /**
+ * Set the rules exported by this grammar.
+ *
+ * @param exportRules
+ * The rules exported by this grammar.
+ */
+ public void setExportedRules(Set<String> exportRules) {
+ this.exportRules = exportRules;
+ }
}
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java
index 7549847..346e588 100644
--- a/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java
+++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java
@@ -4,7 +4,9 @@ import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.IList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import static bjc.rgens.newparser.CaseElement.ElementType.*;
import static bjc.rgens.newparser.RuleCase.CaseType.*;
@@ -16,11 +18,13 @@ import static bjc.rgens.newparser.RuleCase.CaseType.*;
*
*/
public class RGrammarBuilder {
- private Map<String, Rule> rules;
+ private IList<CaseElement> currentCase;
private Rule currRule;
- private IList<CaseElement> currentCase;
+ private Map<String, Rule> rules;
+
+ private Set<String> exportedRules;
private String initialRule;
@@ -30,6 +34,8 @@ public class RGrammarBuilder {
public RGrammarBuilder() {
rules = new HashMap<>();
+ exportedRules = new HashSet<>();
+
currentCase = new FunctionalList<>();
}
@@ -65,6 +71,8 @@ public class RGrammarBuilder {
grammar.setInitialRule(initialRule);
+ grammar.setExportedRules(exportedRules);
+
return grammar;
}
@@ -139,6 +147,10 @@ public class RGrammarBuilder {
*
* @param init
* The initial rule of the grammar.
+ *
+ * @throws IllegalArgumentException
+ * If the rule is either not valid or not defined in the
+ * grammar.
*/
public void setInitialRule(String init) {
if(init == null) {
@@ -151,4 +163,26 @@ public class RGrammarBuilder {
initialRule = init;
}
+
+ /**
+ * Add an exported rule to this grammar.
+ *
+ * @param export
+ * The name of the rule to export.
+ *
+ * @throws IllegalArgumentException
+ * If the rule is either not valid or not defined in the
+ * grammar.
+ */
+ public void addExport(String export) {
+ if(export == null) {
+ throw new NullPointerException("Export name must not be null");
+ } else if(export.equals("")) {
+ throw new NullPointerException("The empty string is not a valid rule name");
+ } else if(!rules.containsKey(export)) {
+ throw new IllegalArgumentException(String.format("No rule named '%s' found", export));
+ }
+
+ exportedRules.add(export);
+ }
}
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java
index b74c5f7..64d7b54 100644
--- a/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java
+++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java
@@ -49,6 +49,14 @@ public class RGrammarParser {
build.setInitialRule(body);
});
+
+ pragmas.put("export-rule", (body, build, level) -> {
+ String[] exports = body.split(" ");
+
+ for(String export : exports) {
+ build.addExport(export);
+ }
+ });
}
/**
@@ -99,6 +107,7 @@ public class RGrammarParser {
*/
if(block.equals("")) return;
if(block.equals("\n")) return;
+ if(block.equals("\r\n")) return;
int typeSep = block.indexOf(' ');
@@ -176,7 +185,11 @@ public class RGrammarParser {
String pragmaBody = pragma.substring(bodySep + 1);
if(pragmas.containsKey(pragmaName)) {
- pragmas.get(pragmaName).accept(pragmaBody, build, level);
+ try {
+ pragmas.get(pragmaName).accept(pragmaBody, build, level);
+ } catch(GrammarException gex) {
+ throw new GrammarException(String.format("Error in '%s' pragma", pragmaName), gex);
+ }
} else {
throw new GrammarException(String.format("Unknown pragma named '%s'", pragmaName));
}
@@ -211,7 +224,7 @@ public class RGrammarParser {
* single case.
*/
handleRuleDecl(build, ruleBlock);
-
+
build.finishRule();
}
} catch(GrammarException gex) {
@@ -231,7 +244,8 @@ public class RGrammarParser {
if(declSep == -1) {
/*
- * The old syntax allowed it to work with just a space.
+ * TODO remove support for the old syntax when all of
+ * the files are converted.
*/
declSep = declContents.indexOf(' ');
@@ -240,9 +254,6 @@ public class RGrammarParser {
"A rule must be given at least one case in its declaration, and"
+ "seperated from that case by \u2192");
}
-
- System.out.println(
- "WARNING: Rule declarations must now be seperated from the initial case by \u2192.");
}
String ruleName = declContents.substring(0, declSep).trim();
@@ -264,7 +275,14 @@ public class RGrammarParser {
build.beginCase();
for(String csepart : cse.split(" ")) {
- build.addCasePart(csepart);
+ String partToAdd = csepart.trim();
+
+ /*
+ * Ignore empty parts
+ */
+ if(partToAdd.equals("")) continue;
+
+ build.addCasePart(partToAdd);
}
build.finishCase();
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarSet.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarSet.java
new file mode 100644
index 0000000..e67e356
--- /dev/null
+++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarSet.java
@@ -0,0 +1,123 @@
+package bjc.rgens.newparser;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Represents a set of grammars that can share rules via exports.
+ *
+ * @author EVE
+ *
+ */
+public class RGrammarSet {
+ private Map<String, RGrammar> grammars;
+
+ private Map<String, RGrammar> exportedRules;
+
+ /**
+ * Create a new set of randomized grammars.
+ */
+ public RGrammarSet() {
+ grammars = new HashMap<>();
+
+ exportedRules = new HashMap<>();
+ }
+
+ /**
+ * Add a grammar to this grammar set.
+ *
+ * @param grammarName
+ * The name of the grammar to add.
+ *
+ * @param gram
+ * The grammar to add.
+ *
+ * @throws IllegalArgumentException
+ * If the grammar name is invalid.
+ */
+ public void addGrammar(String grammarName, RGrammar gram) {
+ if(grammarName == null) {
+ throw new NullPointerException("Grammar name must not be null");
+ } else if(gram == null) {
+ throw new NullPointerException("Grammar must not be null");
+ } else if(grammarName.equals("")) {
+ throw new IllegalArgumentException("The empty string is not a valid grammar name");
+ }
+
+ grammars.put(grammarName, gram);
+
+ for(Rule export : gram.getExportedRules()) {
+ exportedRules.put(export.ruleName, gram);
+ }
+
+ gram.setImportedRules(exportedRules);
+ }
+
+ /**
+ * Get a grammar from this grammar set.
+ *
+ * @param grammarName
+ * The name of the grammar to get.
+ *
+ * @return The grammar with that name.
+ *
+ * @throws IllegalArgumentException
+ * If the grammar name is invalid or not present in this
+ * set.
+ */
+ public RGrammar getGrammar(String grammarName) {
+ if(grammarName == null) {
+ throw new NullPointerException("Grammar name must not be null");
+ } else if(grammarName.equals("")) {
+ throw new IllegalArgumentException("The empty string is not a valid grammar name");
+ } else if(!grammars.containsKey("")) {
+ throw new IllegalArgumentException(
+ String.format("No grammar with name '%s' found", grammarName));
+ }
+
+ return grammars.get(grammarName);
+ }
+
+ /**
+ * Get the grammar a rule was exported from.
+ *
+ * @param exportName
+ * The name of the exported rule.
+ *
+ * @return The grammar the exported rule came from.
+ *
+ * @throws IllegalArgumentException
+ * If the export name is invalid or not present in this
+ * set.
+ */
+ public RGrammar getExportSource(String exportName) {
+ if(exportName == null) {
+ throw new NullPointerException("Export name must not be null");
+ } else if(exportName.equals("")) {
+ throw new IllegalArgumentException("The empty string is not a valid rule name");
+ } else if(!exportedRules.containsKey(exportName)) {
+ throw new IllegalArgumentException(String.format("No export with name '%s' found", exportName));
+ }
+
+ return exportedRules.get(exportName);
+ }
+
+ /**
+ * Get the names of all the grammars in this set.
+ *
+ * @return The names of all the grammars in this set.
+ */
+ public Set<String> getGrammars() {
+ return grammars.keySet();
+ }
+
+ /**
+ * Get the names of all the exported rules in this set.
+ *
+ * @return The names of all the exported rules in this set.
+ */
+ public Set<String> getExportedRules() {
+ return exportedRules.keySet();
+ }
+}
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarTest.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarTest.java
index 483542e..48977e9 100644
--- a/RGens/src/main/java/bjc/rgens/newparser/RGrammarTest.java
+++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarTest.java
@@ -16,12 +16,18 @@ public class RGrammarTest {
* Unused CLI args.
*/
public static void main(String[] args) {
- InputStream stream = RGrammarTest.class.getResourceAsStream("/sample-grammars/insults.gram");
+ InputStream stream = RGrammarTest.class.getResourceAsStream("/sample-grammars/24hr-rpg.gram");
+
+ RGrammarSet grammarSet = new RGrammarSet();
RGrammarParser parse = new RGrammarParser();
RGrammar grammar = parse.readGrammar(stream);
- System.out.println(grammar.generate(null));
+ grammarSet.addGrammar("rpg", grammar);
+
+ for(int i = 0; i < 10; i++) {
+ System.out.println(grammar.generate(null));
+ }
}
}
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RuleCase.java b/RGens/src/main/java/bjc/rgens/newparser/RuleCase.java
index e919cb8..9652273 100644
--- a/RGens/src/main/java/bjc/rgens/newparser/RuleCase.java
+++ b/RGens/src/main/java/bjc/rgens/newparser/RuleCase.java
@@ -18,7 +18,7 @@ public class RuleCase {
/**
* A normal case, composed from a list of elementList.
*/
- NORMAL;
+ NORMAL,
}
/**