summaryrefslogtreecommitdiff
path: root/RGens
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2017-02-06 10:26:18 -0500
committerbculkin2442 <bjculkin@mix.wvu.edu>2017-02-06 10:26:18 -0500
commit67edd098d89aa86cac315f4f52343e4f42923b16 (patch)
treecdc2f80ddd3253114f29c43b1be49205312b26d9 /RGens
parent51c30f65f5962823c05cceb75b6a1f20d055abe7 (diff)
Grammar feature extensions
Grammars now have support for several addional features. Namely, the following * Regex-rules: You can define a rule as a regex and it will generate strings that match the regex * Range-rules: You can define a rule that will return a random int from a name * Variables: You can define and reference variables for context dependant statements.
Diffstat (limited to 'RGens')
-rw-r--r--RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java119
-rw-r--r--RGens/src/main/java/bjc/RGens/parser/ReaderState.java4
2 files changed, 122 insertions, 1 deletions
diff --git a/RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java b/RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java
index 84fee01..48e21b1 100644
--- a/RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java
+++ b/RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java
@@ -1,10 +1,20 @@
package bjc.RGens.parser;
+import com.mifmif.common.regex.Generex;
+
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.Random;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
import bjc.utils.funcdata.FunctionalStringTokenizer;
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.IList;
+import bjc.utils.funcdata.IMap;
+import bjc.utils.funcutils.ListUtils;
import bjc.utils.gen.WeightedGrammar;
import bjc.utils.parserutils.RuleBasedConfigReader;
@@ -17,6 +27,8 @@ import bjc.utils.parserutils.RuleBasedConfigReader;
public class RBGrammarReader {
private static RuleBasedConfigReader<ReaderState> reader;
+ private static Random numgen = new Random();
+
static {
setupReader();
@@ -80,7 +92,89 @@ public class RBGrammarReader {
ReaderState initialState = new ReaderState(inputPath);
try (FileInputStream inputStream = new FileInputStream(inputPath.toFile())) {
- return reader.fromStream(inputStream, initialState).getGrammar();
+ WeightedGrammar<String> gram = reader.fromStream(inputStream, initialState).getGrammar();
+
+ IMap<String, IList<String>> vars = new FunctionalMap<>();
+
+ Predicate<String> specialPredicate = (strang) -> {
+ if(strang.matches("\\{\\S+\\}") || strang.matches("\\[\\S+\\}")) {
+ return true;
+ }
+
+ return false;
+ };
+
+ BiFunction<String, WeightedGrammar<String>, IList<String>>
+ specialAction = (strang, gramm) -> {
+ IList<String> retList = new FunctionalList<>();
+
+ if(strang.matches("\\{\\S+\\}")) {
+ if(strang.matches("\\{\\S+:=\\S+\\}")) {
+ String[] varParts = strang.split(":=");
+
+ String varName = varParts[0].substring(1);
+ String ruleName = varParts[1].substring(0, varParts[1].length());
+
+ IList<String> varValue = gramm.generateGenericValues(
+ ruleName, (s) -> s, " ");
+
+ vars.put(varName, varValue);
+ } else if(strang.matches("\\{\\S+=\\S+\\}")) {
+ String[] varParts = strang.split("=");
+
+ String varName = varParts[0].substring(1);
+ String varValue = varParts[1].substring(0, varParts[1].length());
+
+ vars.put(varName, new FunctionalList<>(varValue));
+ } else {
+ // @FIXME notify the user they did something wrong
+ retList.add(strang);
+ }
+ } else {
+ if(strang.matches("\\[\\$\\S+\\]")) {
+ String varName = strang.substring(2, strang.length());
+
+ retList = vars.get(varName);
+ } else if(strang.matches("\\[\\$\\S+\\-\\S+\\]")) {
+ String[] varParts = strang.substring(1, strang.length()).split("-");
+
+ StringBuilder actualName = new StringBuilder("[");
+
+ for(String varPart : varParts) {
+ if(varPart.startsWith("$")) {
+ IList<String> varName = vars.get(varPart.substring(1));
+
+ if(varName.getSize() != 1) {
+ // @FIXME notify the user they did something wrong
+ }
+
+ actualName.append(varName.first() + "-");
+ } else {
+ actualName.append(varPart + "-");
+ }
+ }
+
+ // Trim trailing -
+ actualName.deleteCharAt(actualName.length() - 1);
+ actualName.append("]");
+
+ retList = gram.generateGenericValues(actualName.toString(), (s) -> s, " ");
+ } else {
+ // @FIXME notify the user they did something wrong
+ retList.add(strang);
+ }
+ }
+
+ return retList;
+ };
+
+ Runnable specialReset = () -> {
+ vars.clear();
+ };
+
+ gram.configureSpecial(specialPredicate, specialAction, specialReset);
+
+ return gram;
} catch (IOException ioex) {
throw ioex;
}
@@ -118,6 +212,29 @@ public class RBGrammarReader {
reader.addPragma("prefix-with", RBGrammarReader::prefixRule);
reader.addPragma("suffix-with", RBGrammarReader::suffixRule);
+
+ reader.addPragma("regex-rule", (tokenizer, state) -> {
+ String ruleName = tokenizer.nextToken();
+
+ IList<String> regx = tokenizer.toList();
+ Generex regex = new Generex(ListUtils.collapseTokens(regx));
+
+ state.addSpecialRule(ruleName, () -> {
+ return new FunctionalList<>(regex.random().split(" "));
+ });
+ });
+
+ reader.addPragma("range-rule", (tokenizer, state) -> {
+ String ruleName = tokenizer.nextToken();
+
+ int start = Integer.parseInt(tokenizer.nextToken());
+ int end = Integer.parseInt(tokenizer.nextToken());
+
+ state.addSpecialRule(ruleName, () -> {
+ return new FunctionalList<>(Integer.toString(
+ numgen.nextInt((end - start) + 1) + start));
+ });
+ });
}
private static void loadSubGrammar(FunctionalStringTokenizer stk, ReaderState rs) {
diff --git a/RGens/src/main/java/bjc/RGens/parser/ReaderState.java b/RGens/src/main/java/bjc/RGens/parser/ReaderState.java
index b455844..8e846cf 100644
--- a/RGens/src/main/java/bjc/RGens/parser/ReaderState.java
+++ b/RGens/src/main/java/bjc/RGens/parser/ReaderState.java
@@ -3,6 +3,7 @@ package bjc.RGens.parser;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Stack;
+import java.util.function.Supplier;
import bjc.utils.funcdata.IList;
import bjc.utils.gen.WeightedGrammar;
@@ -124,6 +125,9 @@ public class ReaderState {
currentGrammar.addCase(currentRule, ruleProbability, ruleParts);
}
+ public void addSpecialRule(String ruleName, Supplier<IList<String>> cse) {
+ currentGrammar.addSpecialRule(ruleName, cse);
+ }
/**
* Edit a subgrammar of the current grammar
*