From 0ea49dd4a52358f053c9be7138c392b16de05899 Mon Sep 17 00:00:00 2001 From: student Date: Fri, 17 Mar 2017 10:49:27 -0400 Subject: Move things around, and start on new parser. --- RGens/src/main/java/bjc/RGens/.DS_Store | Bin 6148 -> 0 bytes RGens/src/main/java/bjc/RGens/ZadronsPouch.java | 219 ------------- .../src/main/java/bjc/RGens/gui/GrammarStudio.java | 26 -- .../java/bjc/RGens/gui/GrammarStudioFrame.java | 30 -- RGens/src/main/java/bjc/RGens/parser/.DS_Store | Bin 6148 -> 0 bytes .../java/bjc/RGens/parser/GrammarReaderApp.java | 93 ------ .../java/bjc/RGens/parser/GrammarReaderCLI.java | 61 ---- .../bjc/RGens/parser/PragmaErrorException.java | 21 -- .../java/bjc/RGens/parser/RBGrammarReader.java | 319 ------------------- .../main/java/bjc/RGens/parser/ReaderState.java | 306 ------------------ .../main/java/bjc/RGens/server/CLIArgsParser.java | 141 --------- .../main/java/bjc/RGens/server/GrammarServer.java | 346 --------------------- .../java/bjc/RGens/server/GrammarServerEngine.java | 300 ------------------ .../main/java/bjc/RGens/server/ReaderState.java | 181 ----------- .../java/bjc/RGens/server/ServerGrammarReader.java | 326 ------------------- .../main/java/bjc/RGens/text/markov/Markov.java | 189 ----------- .../bjc/RGens/text/markov/StandaloneMarkov.java | 42 --- .../RGens/text/markov/StandaloneTextGenerator.java | 70 ----- .../java/bjc/RGens/text/markov/TextGenerator.java | 69 ---- RGens/src/main/java/bjc/rgens/.DS_Store | Bin 0 -> 6148 bytes RGens/src/main/java/bjc/rgens/ZadronsPouch.java | 219 +++++++++++++ .../src/main/java/bjc/rgens/gui/GrammarStudio.java | 26 ++ .../java/bjc/rgens/gui/GrammarStudioFrame.java | 30 ++ .../main/java/bjc/rgens/newparser/RGrammar.java | 5 + .../java/bjc/rgens/newparser/RGrammarBuilder.java | 7 + .../java/bjc/rgens/newparser/RGrammarParser.java | 110 +++++++ RGens/src/main/java/bjc/rgens/parser/.DS_Store | Bin 0 -> 6148 bytes .../java/bjc/rgens/parser/GrammarReaderApp.java | 93 ++++++ .../java/bjc/rgens/parser/GrammarReaderCLI.java | 61 ++++ .../bjc/rgens/parser/PragmaErrorException.java | 21 ++ .../java/bjc/rgens/parser/RBGrammarReader.java | 319 +++++++++++++++++++ .../main/java/bjc/rgens/parser/ReaderState.java | 306 ++++++++++++++++++ .../main/java/bjc/rgens/server/CLIArgsParser.java | 141 +++++++++ .../main/java/bjc/rgens/server/GrammarServer.java | 346 +++++++++++++++++++++ .../java/bjc/rgens/server/GrammarServerEngine.java | 300 ++++++++++++++++++ .../main/java/bjc/rgens/server/ReaderState.java | 181 +++++++++++ .../java/bjc/rgens/server/ServerGrammarReader.java | 326 +++++++++++++++++++ .../main/java/bjc/rgens/text/markov/Markov.java | 189 +++++++++++ .../bjc/rgens/text/markov/StandaloneMarkov.java | 42 +++ .../rgens/text/markov/StandaloneTextGenerator.java | 70 +++++ .../java/bjc/rgens/text/markov/TextGenerator.java | 69 ++++ 41 files changed, 2861 insertions(+), 2739 deletions(-) delete mode 100644 RGens/src/main/java/bjc/RGens/.DS_Store delete mode 100644 RGens/src/main/java/bjc/RGens/ZadronsPouch.java delete mode 100644 RGens/src/main/java/bjc/RGens/gui/GrammarStudio.java delete mode 100644 RGens/src/main/java/bjc/RGens/gui/GrammarStudioFrame.java delete mode 100644 RGens/src/main/java/bjc/RGens/parser/.DS_Store delete mode 100644 RGens/src/main/java/bjc/RGens/parser/GrammarReaderApp.java delete mode 100644 RGens/src/main/java/bjc/RGens/parser/GrammarReaderCLI.java delete mode 100644 RGens/src/main/java/bjc/RGens/parser/PragmaErrorException.java delete mode 100644 RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java delete mode 100644 RGens/src/main/java/bjc/RGens/parser/ReaderState.java delete mode 100644 RGens/src/main/java/bjc/RGens/server/CLIArgsParser.java delete mode 100644 RGens/src/main/java/bjc/RGens/server/GrammarServer.java delete mode 100644 RGens/src/main/java/bjc/RGens/server/GrammarServerEngine.java delete mode 100644 RGens/src/main/java/bjc/RGens/server/ReaderState.java delete mode 100644 RGens/src/main/java/bjc/RGens/server/ServerGrammarReader.java delete mode 100755 RGens/src/main/java/bjc/RGens/text/markov/Markov.java delete mode 100644 RGens/src/main/java/bjc/RGens/text/markov/StandaloneMarkov.java delete mode 100644 RGens/src/main/java/bjc/RGens/text/markov/StandaloneTextGenerator.java delete mode 100755 RGens/src/main/java/bjc/RGens/text/markov/TextGenerator.java create mode 100644 RGens/src/main/java/bjc/rgens/.DS_Store create mode 100644 RGens/src/main/java/bjc/rgens/ZadronsPouch.java create mode 100644 RGens/src/main/java/bjc/rgens/gui/GrammarStudio.java create mode 100644 RGens/src/main/java/bjc/rgens/gui/GrammarStudioFrame.java create mode 100644 RGens/src/main/java/bjc/rgens/newparser/RGrammar.java create mode 100644 RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java create mode 100644 RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java create mode 100644 RGens/src/main/java/bjc/rgens/parser/.DS_Store create mode 100644 RGens/src/main/java/bjc/rgens/parser/GrammarReaderApp.java create mode 100644 RGens/src/main/java/bjc/rgens/parser/GrammarReaderCLI.java create mode 100644 RGens/src/main/java/bjc/rgens/parser/PragmaErrorException.java create mode 100644 RGens/src/main/java/bjc/rgens/parser/RBGrammarReader.java create mode 100644 RGens/src/main/java/bjc/rgens/parser/ReaderState.java create mode 100644 RGens/src/main/java/bjc/rgens/server/CLIArgsParser.java create mode 100644 RGens/src/main/java/bjc/rgens/server/GrammarServer.java create mode 100644 RGens/src/main/java/bjc/rgens/server/GrammarServerEngine.java create mode 100644 RGens/src/main/java/bjc/rgens/server/ReaderState.java create mode 100644 RGens/src/main/java/bjc/rgens/server/ServerGrammarReader.java create mode 100755 RGens/src/main/java/bjc/rgens/text/markov/Markov.java create mode 100644 RGens/src/main/java/bjc/rgens/text/markov/StandaloneMarkov.java create mode 100644 RGens/src/main/java/bjc/rgens/text/markov/StandaloneTextGenerator.java create mode 100755 RGens/src/main/java/bjc/rgens/text/markov/TextGenerator.java diff --git a/RGens/src/main/java/bjc/RGens/.DS_Store b/RGens/src/main/java/bjc/RGens/.DS_Store deleted file mode 100644 index 918453d..0000000 Binary files a/RGens/src/main/java/bjc/RGens/.DS_Store and /dev/null differ diff --git a/RGens/src/main/java/bjc/RGens/ZadronsPouch.java b/RGens/src/main/java/bjc/RGens/ZadronsPouch.java deleted file mode 100644 index b807945..0000000 --- a/RGens/src/main/java/bjc/RGens/ZadronsPouch.java +++ /dev/null @@ -1,219 +0,0 @@ -package bjc.RGens; - -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.gen.RandomGrammar; - -/** - * Example showing code manipulate of random grammars - * - * @author ben - * - */ -public class ZadronsPouch { - /** - * Main method for running application - * - * @param args - * Unused CLI args - */ - public static void main(String[] args) { - ZadronsPouch zp = new ZadronsPouch(); - - for (int i = 0; i < 100; i++) { - IList ls = zp.grammar.generateListValues("[item]", " "); - - StringBuilder sb = new StringBuilder(); - - ls.forEach(sp -> sb.append(sp)); - - System.out.println(sb.toString().replaceAll("\\s+", " ")); - } - } - - private RandomGrammar grammar; - - /** - * Create a new instance with a grammar - */ - public ZadronsPouch() { - grammar = new RandomGrammar<>(); - - addRule("[item]", - "[egg]", "[glove]", "[crys-sphere]", "[rock]", - "[figurine]", "[vial]", "[mini-weapon]", "[bag]", - "[card]", "[rope]", "[box]", "[wand]"); - - addEggRules(); - addGloveRules(); - addCrysSphereRules(); - addRockRules(); - - addFigurineRules(); - addVialRules(); - addMiniWeaponRules(); - addBagRules(); - - addCardRules(); - addRopeRules(); - addBoxRules(); - addWandRules(); - } - - private void addBagRules() { - addRule("[bag]", - "bag of [bag-type]", "[sack-type] sack", "[purse-type] purse"); - addRule("[bag-type]", - "holding", "tricks", "useful items", - "devouring", "dwarf-kind", "invisible cloth", - "monster summoning"); - addRule("[sack-type]", - "lunch", "recursive"); - addRule("[purse-type]", - "everfull"); - } - - private void addBoxRules() { - addRule("[box]", - "[box-type] box", "cube of [box-type]"); - addRule("[box-type]", - "limited-force", "frost-resisting", "morphing", - "self-destructing", "pandora", "panicking"); - } - - private void addCardRules() { - addRule("[card]", - "card of [card-type]", "[card-type] card"); - addRule("[card-type]", - "fate", "teleporting", "elusive treasure", "spell-storing", - "many-things", "imprisoning", "messaging", "bounty"); - } - - private void addCrysSphereRules() { - addRule("[crys-sphere]", - "[sphere-type] spheres", "[sphere-type] sphere", - "lens of [lens-type]", "[crystal-type] crystal", - "crystal of [crystal-type]", "crystal ball", - "crystal ball of [crys-suffix]"); - addRule("[sphere-type]", - "microphonic", "seeing-eye"); - addRule("[lens-type]", - "detection"); - addRule("[crystal-type]", - "prison", "radar"); - addRule("[crys-suffix]", - "jumping"); - } - - private void addEggRules() { - addRule("[egg]", - "[egg-type] egg"); - addRule("[egg-type]", - "copper", "stone", "golden", - "white", "white/pink", "glass"); - } - - private void addFigurineRules() { - addRule("[figurine]", - "[fig-material] [fig-animal]"); - addRule("[fig-material]", - "golden", "onyx", "serpentine", "ivory", - "marble", "bronze", "jade", "limestone"); - addRule("[fig-animal]", - "lion", "dog", "owl", "goat", - "elephant", "warrior", "palace", "leprechaun"); - } - - private void addGloveRules() { - addRule("[glove]", - "gauntlets of [gauntlet-type]", - "gloves of [glove-type]", - "[glove-type] gloves"); - addRule("[gauntlet-type]", - "dexterity", "power"); - addRule("[glove-type]", - "pushing", "choking", "bigby", "stunning"); - } - - private void addMiniWeaponRules() { - addRule("[mini-weapon]", - "minature [weapon-type]", "small [weapon-type]", - "tiny [weapon-type]", "[sling-type] sling", - "[weapon-type]"); - addRule("[weapon-type]", - "boomerang", "arrow", "net", - "catapult", "hammer", "sword", "club"); - addRule("[sling-type]", - "seeking"); - } - - private void addRockRules() { - addRule("[rock]", - "[pebble-type] pebble", "stone of [stone-type]", - "[stone-type] stone", "brick of [brick-type]", - "[geode-type] geode"); - addRule("[pebble-type]", - "inscribed", "elemental control"); - addRule("[stone-type]", - "good-luck", "weight", - "blind-defense", "metal-clinging"); - addRule("[brick-type]", - "flying"); - addRule("[geode-type]", - "ioun"); - } - - private void addRopeRules() { - addRule("[rope]", - "[rope-type] rope", "rope of [rope-type]", - "ball of [string-type] [string-kind]"); - addRule("[rope-type]", - "trick", "entangling", "climbing", "dancing", - "tripping", "snaring", "levitating", "self-entangling"); - addRule("[string-type]", - "endless"); - addRule("[string-kind]", - "string", "yarn"); - } - - private void addRule(String rule, String... cases) { - IList> cses = new FunctionalList<>(); - - for (String strang : cases) { - cses.add(FunctionalStringTokenizer.fromString(strang).toList(s -> s)); - } - - grammar.makeRule(rule, cses); - } - - private void addVialRules() { - addRule("[vial]", - "vial of [vial-type]", "[vial-type] vial", - "[bottle-type] bottle", "[flask-type] flask"); - addRule("[vial-type]", - "holding", "trapping", - "experience", "unnatural regeneration"); - addRule("[bottle-type]", - "ever-smoking", "wheezing", - "blank potion"); - addRule("[flask-type]", - "iron"); - } - - private void addWandRules() { - addRule("[wand]", - "[wand-type] wand", "wand of [wand-type]", - "canceling [wand-type] wand"); - addRule("[wand-type]", - "magic missile", "[spell-1]", "[spell-2]", - "gusting", "life-detecting", "zadron"); - addRule("[spell-1]", - "frost", "fire", "lightning", "fear", - "illumination", "polymorphing", "conjuration", "paralyzing"); - addRule("[spell-2]", - "[spell2-type] detecting"); - addRule("[spell2-type]", - "magic", "enemy", "secret door/trap"); - } -} diff --git a/RGens/src/main/java/bjc/RGens/gui/GrammarStudio.java b/RGens/src/main/java/bjc/RGens/gui/GrammarStudio.java deleted file mode 100644 index ffc9be8..0000000 --- a/RGens/src/main/java/bjc/RGens/gui/GrammarStudio.java +++ /dev/null @@ -1,26 +0,0 @@ -package bjc.RGens.gui; - -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -public class GrammarStudio { - public static void main(String[] args) { - try { - UIManager.setLookAndFeel( - UIManager.getSystemLookAndFeelClassName()); - } catch (ClassNotFoundException | InstantiationException - | IllegalAccessException - | UnsupportedLookAndFeelException ex) { - System.out.println( - "WARNING: Could not use system look and feel"); - ex.printStackTrace(); - } - - GrammarStudioFrame mainFrame = new GrammarStudioFrame(); - - mainFrame.setDefaultCloseOperation( - GrammarStudioFrame.EXIT_ON_CLOSE); - - mainFrame.setVisible(true); - } -} diff --git a/RGens/src/main/java/bjc/RGens/gui/GrammarStudioFrame.java b/RGens/src/main/java/bjc/RGens/gui/GrammarStudioFrame.java deleted file mode 100644 index f671a87..0000000 --- a/RGens/src/main/java/bjc/RGens/gui/GrammarStudioFrame.java +++ /dev/null @@ -1,30 +0,0 @@ -package bjc.RGens.gui; - -import javax.swing.JDesktopPane; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; - -import bjc.utils.gui.layout.AutosizeLayout; - -public class GrammarStudioFrame extends JFrame { - private static final long serialVersionUID = 1476431892446002428L; - - public GrammarStudioFrame() { - super("Grammar Studio"); - - setLayout(new AutosizeLayout()); - - JDesktopPane mainPane = new JDesktopPane(); - - JMenuBar menuBar = new JMenuBar(); - - JMenu fileMenu = new JMenu("File"); - fileMenu.setMnemonic('m'); - - menuBar.add(fileMenu); - - setJMenuBar(menuBar); - add(mainPane); - } -} diff --git a/RGens/src/main/java/bjc/RGens/parser/.DS_Store b/RGens/src/main/java/bjc/RGens/parser/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/RGens/src/main/java/bjc/RGens/parser/.DS_Store and /dev/null differ diff --git a/RGens/src/main/java/bjc/RGens/parser/GrammarReaderApp.java b/RGens/src/main/java/bjc/RGens/parser/GrammarReaderApp.java deleted file mode 100644 index 6a7eb26..0000000 --- a/RGens/src/main/java/bjc/RGens/parser/GrammarReaderApp.java +++ /dev/null @@ -1,93 +0,0 @@ -package bjc.RGens.parser; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.PrintStream; - -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -import bjc.utils.funcutils.ListUtils; -import bjc.utils.gen.WeightedGrammar; -import bjc.utils.gui.SimpleDialogs; -import bjc.utils.gui.awt.SimpleFileDialog; - -/** - * App that reads a grammar from a file and generates results - * - * @author ben - * - */ -public class GrammarReaderApp { - /** - * Main method of class - * - * @param args - * CLI args - */ - public static void main(String[] args) { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (ClassNotFoundException - | InstantiationException - | IllegalAccessException - | UnsupportedLookAndFeelException e) { - e.printStackTrace(); - System.exit(1); - } - - doSingleFile(); - } - - private static void doSingleFile() { - File gramFile = SimpleFileDialog.getOpenFile(null, "Choose Grammar File", ".gram"); - - WeightedGrammar grammar = null; - - try { - grammar = RBGrammarReader.fromPath(gramFile.toPath()); - } catch (IOException ioex) { - ioex.printStackTrace(); - - System.exit(1); - } - - String initRule = ""; - - if (!grammar.hasInitialRule()) { - grammar.getRuleNames().sort((leftString, rightString) -> { - return leftString.compareTo(rightString); - }); - - initRule = SimpleDialogs.getChoice(null, - "Pick a initial rule", - "Pick a initial rule to generate choices from", - grammar.getRuleNames().toArray(new String[0])); - } else { - initRule = grammar.getInitialRule(); - } - - int count = SimpleDialogs.getWhole(null, - "Enter number of repetitions", - "Enter the number of items to generate from the rule"); - - File outputFile = SimpleFileDialog.getSaveFile(null, "Choose Grammar File"); - - PrintStream outputStream = null; - - try { - outputStream = new PrintStream(outputFile); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - - for (int i = 0; i < count; i++) { - String ruleResult = ListUtils.collapseTokens(grammar.generateListValues(initRule, " ")); - - outputStream.println(ruleResult.replaceAll("\\s+", " ")); - } - - outputStream.close(); - } -} diff --git a/RGens/src/main/java/bjc/RGens/parser/GrammarReaderCLI.java b/RGens/src/main/java/bjc/RGens/parser/GrammarReaderCLI.java deleted file mode 100644 index 8d8a334..0000000 --- a/RGens/src/main/java/bjc/RGens/parser/GrammarReaderCLI.java +++ /dev/null @@ -1,61 +0,0 @@ -package bjc.RGens.parser; - -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Paths; - -import bjc.utils.funcutils.ListUtils; -import bjc.utils.gen.WeightedGrammar; - -/** - * App that reads a grammar from a file and generates results - * - * @author ben - * - */ -public class GrammarReaderCLI { - private static WeightedGrammar grammar = null; - - /** - * Main application method - * - * @param args - * CLI args - */ - public static void main(String[] args) { - if (args.length == 0) { - GrammarReaderApp.main(args); - } else { - String fName = args[0]; - - if (fName.equalsIgnoreCase("--help")) { - System.out.println( - "Usage: java -jar GrammarReader.jar "); - System.exit(0); - } - - String ruleName = args[1]; - - try (FileInputStream fStream = new FileInputStream(fName)) { - grammar = RBGrammarReader.fromPath(Paths.get(fName, "")); - } catch (IOException e) { - e.printStackTrace(); - } - - if (ruleName.equalsIgnoreCase("--list-rules")) { - grammar.getRuleNames().forEach(System.out::println); - - System.exit(0); - } - - int rCount = Integer.parseInt(args[2]); - - for (int i = 0; i < rCount; i++) { - String ruleResult = ListUtils.collapseTokens( - grammar.generateListValues(ruleName, " ")); - - System.out.println(ruleResult.replaceAll("\\s+", " ")); - } - } - } -} diff --git a/RGens/src/main/java/bjc/RGens/parser/PragmaErrorException.java b/RGens/src/main/java/bjc/RGens/parser/PragmaErrorException.java deleted file mode 100644 index afa368b..0000000 --- a/RGens/src/main/java/bjc/RGens/parser/PragmaErrorException.java +++ /dev/null @@ -1,21 +0,0 @@ -package bjc.RGens.parser; - -/** - * Exception for error executing a pragma - * - * @author ben - * - */ -public class PragmaErrorException extends RuntimeException { - private static final long serialVersionUID = 7245421182038076899L; - - /** - * Create a new exception with the given message - * - * @param message - * The message of the exception - */ - public PragmaErrorException(String message) { - super(message); - } -} diff --git a/RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java b/RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java deleted file mode 100644 index eca5f4f..0000000 --- a/RGens/src/main/java/bjc/RGens/parser/RBGrammarReader.java +++ /dev/null @@ -1,319 +0,0 @@ -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; - -/** - * Read a grammar from a stream - * - * @author ben - * - */ -public class RBGrammarReader { - private static RuleBasedConfigReader reader; - - private static Random numgen = new Random(); - - static { - setupReader(); - - initPragmas(); - } - - private static void addSubgrammarPragmas() { - reader.addPragma("new-sub-grammar", (tokenizer, state) -> { - state.startNewSubgrammar(); - }); - - reader.addPragma("load-sub-grammar", RBGrammarReader::loadSubGrammar); - reader.addPragma("save-sub-grammar", RBGrammarReader::saveGrammar); - reader.addPragma("edit-sub-grammar", RBGrammarReader::editSubGrammar); - reader.addPragma("remove-sub-grammar", RBGrammarReader::removeSubGrammar); - - reader.addPragma("edit-parent", (tokenizer, state) -> { - state.editParent(); - }); - - reader.addPragma("promote", RBGrammarReader::promoteGrammar); - reader.addPragma("subordinate", RBGrammarReader::subordinateGrammar); - - } - - private static void debugGrammar(ReaderState state) { - System.out.println("Printing rule names: "); - - for (String currentRule : state.getRuleNames().toIterable()) { - System.out.println("\t" + currentRule); - } - - System.out.println(); - } - - private static void doCase(FunctionalStringTokenizer tokenizer, ReaderState state) { - int ruleProbability = readOptionalProbability(tokenizer, state); - - state.addCase(ruleProbability, tokenizer.toList()); - } - - private static void editSubGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { - String subgrammarName = tokenizer.nextToken(); - - state.editSubgrammar(subgrammarName); - } - - /** - * Read a grammar from a path - * - * @param inputPath - * The path to load the grammar from - * - * @return A grammar read from the stream - * - * @throws IOException - * If something goes wrong during file reading - * - */ - public static WeightedGrammar fromPath(Path inputPath) throws IOException { - ReaderState initialState = new ReaderState(inputPath); - - try (FileInputStream inputStream = new FileInputStream(inputPath.toFile())) { - WeightedGrammar gram = reader.fromStream(inputStream, initialState).getGrammar(); - - IMap> vars = new FunctionalMap<>(); - - Predicate specialPredicate = (strang) -> { - if(strang.matches("\\{\\S+\\}") || strang.matches("\\[\\S+\\}")) { - return true; - } - - return false; - }; - - BiFunction, IList> - specialAction = (strang, gramm) -> { - IList 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 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 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 = gramm.generateGenericValues(actualName.toString(), (s) -> s, " "); - } else { - // @FIXME notify the user they did something wrong - retList.add(strang); - } - } - - return retList; - }; - - gram.configureSpecial(specialPredicate, specialAction); - - return gram; - } catch (IOException ioex) { - throw ioex; - } - } - - private static void importRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - String subgrammarName = tokenizer.nextToken(); - - state.addGrammarAlias(subgrammarName, ruleName); - } - - private static void initialRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String initialRuleName = tokenizer.nextToken(); - - state.setInitialRule(initialRuleName); - } - - private static void initPragmas() { - addSubgrammarPragmas(); - - reader.addPragma("debug", (tokenizer, state) -> { - debugGrammar(state); - }); - - reader.addPragma("uniform", (tokenizer, state) -> { - state.toggleUniformity(); - }); - - reader.addPragma("initial-rule", RBGrammarReader::initialRule); - - reader.addPragma("import-rule", RBGrammarReader::importRule); - - reader.addPragma("remove-rule", RBGrammarReader::removeRule); - - reader.addPragma("prefix-with", RBGrammarReader::prefixRule); - reader.addPragma("suffix-with", RBGrammarReader::suffixRule); - - reader.addPragma("regex-rule", (tokenizer, state) -> { - String ruleName = tokenizer.nextToken(); - - IList 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) { - String subgrammarName = stk.nextToken(); - String subgrammarPath = stk.nextToken(); - - rs.loadSubgrammar(subgrammarName, subgrammarPath); - } - - private static void prefixRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - String prefixToken = tokenizer.nextToken(); - - int additionalProbability = readOptionalProbability(tokenizer, state); - - state.prefixRule(ruleName, prefixToken, additionalProbability); - } - - private static void promoteGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { - String subgrammarName = tokenizer.nextToken(); - String subordinateName = tokenizer.nextToken(); - - state.promoteGrammar(subgrammarName, subordinateName); - } - - private static int readOptionalProbability(FunctionalStringTokenizer tokenizer, ReaderState state) { - if (state.isUniform()) { - return 1; - } - - return Integer.parseInt(tokenizer.nextToken()); - } - - private static void removeRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - - state.deleteRule(ruleName); - } - - private static void removeSubGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { - String subgrammarName = tokenizer.nextToken(); - - state.deleteSubgrammar(subgrammarName); - } - - private static void saveGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { - String subgrammarName = tokenizer.nextToken(); - - state.saveSubgrammar(subgrammarName); - } - - private static void setupReader() { - reader = new RuleBasedConfigReader<>(null, null, null); - - reader.setStartRule((tokenizer, stateTokenPair) -> { - stateTokenPair.doWith((initToken, state) -> { - state.startNewRule(initToken); - - doCase(tokenizer, state); - }); - }); - - reader.setContinueRule((tokenizer, state) -> { - doCase(tokenizer, state); - }); - - reader.setEndRule((tokenizer) -> { - tokenizer.setCurrentRule(null); - }); - } - - private static void subordinateGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { - String grammarName = tokenizer.nextToken(); - - state.subordinateGrammar(grammarName); - } - - private static void suffixRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - String suffixToken = tokenizer.nextToken(); - - int additionalProbability = readOptionalProbability(tokenizer, state); - - state.suffixRule(ruleName, suffixToken, additionalProbability); - } -} diff --git a/RGens/src/main/java/bjc/RGens/parser/ReaderState.java b/RGens/src/main/java/bjc/RGens/parser/ReaderState.java deleted file mode 100644 index 14d7ff8..0000000 --- a/RGens/src/main/java/bjc/RGens/parser/ReaderState.java +++ /dev/null @@ -1,306 +0,0 @@ -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; - -/** - * Represents the internal state of reader - * - * @author ben - * - */ -public class ReaderState { - private WeightedGrammar currentGrammar; - - private Stack> grammarStack; - - private String currentRule; - - private boolean isUniform; - - private Path currentDirectory; - - /** - * Create a new reader state - * - * @param inputPath - * The path to this grammar - */ - public ReaderState(Path inputPath) { - grammarStack = new Stack<>(); - - currentGrammar = new WeightedGrammar<>(); - - // Grammars start out uniform - isUniform = true; - - currentDirectory = inputPath.getParent(); - } - - /** - * Get the rule names for the current grammar - * - * @return The rule names for the current grammar - */ - public IList getRuleNames() { - return currentGrammar.getRuleNames(); - } - - /** - * Check if this reader is currently in uniform mode - * - * @return Whether this grammar is in uniform mode - */ - public boolean isUniform() { - return isUniform; - } - - /** - * Set the current grammar to be the specified one - * - * @param newWorkingGrammar - * The new grammar to use - */ - public void setCurrentGrammar(WeightedGrammar newWorkingGrammar) { - currentGrammar = newWorkingGrammar; - } - - /** - * Set the rule currently being worked on - * - * @param ruleName - * The rule currently being worked on - */ - public void setCurrentRule(String ruleName) { - currentRule = ruleName; - } - - /** - * Set the initial rule of this grammar - * - * @param ruleName - * The initial rule of this grammar - */ - public void setInitialRule(String ruleName) { - currentGrammar.setInitialRule(ruleName); - } - - /** - * Toggle this uniformity setting for this grammar - */ - public void toggleUniformity() { - isUniform = !isUniform; - } - - /** - * Start work on a new sub-grammar of the previous grammar - */ - public void startNewSubgrammar() { - grammarStack.push(currentGrammar); - - currentGrammar = new WeightedGrammar<>(); - } - - /** - * Move to editing the grammar that is the parent of this current one - */ - public void editParent() { - currentGrammar = grammarStack.pop(); - } - - /** - * Add a case to the current grammar - * - * @param ruleProbability - * The probability for this case to occur - * @param ruleParts - * The parts that make up this case - */ - public void addCase(int ruleProbability, IList ruleParts) { - currentGrammar.addCase(currentRule, ruleProbability, ruleParts); - } - - public void addSpecialRule(String ruleName, Supplier> cse) { - currentGrammar.addSpecialRule(ruleName, cse); - } - /** - * Edit a subgrammar of the current grammar - * - * @param subgrammarName - * The name of the subgrammar to edit - */ - public void editSubgrammar(String subgrammarName) { - WeightedGrammar subgrammar = currentGrammar.getSubgrammar(subgrammarName); - - grammarStack.push(currentGrammar); - - currentGrammar = subgrammar; - } - - /** - * Start editing a new rule in the current grammar - * - * @param ruleName - * The name of the new rule to edit - */ - public void startNewRule(String ruleName) { - currentGrammar.addRule(ruleName); - - currentRule = ruleName; - } - - /** - * Convert this package of state into a weighted grammar - * - * @return The grammar represented by this state - */ - public WeightedGrammar getGrammar() { - return currentGrammar; - } - - /** - * Alias a current subgrammar to a new name - * - * @param subgrammarName - * The name of the subgrammar to alias - * @param subgrammarAlias - * The name of the alias for the subgrammar - */ - public void addGrammarAlias(String subgrammarName, String subgrammarAlias) { - currentGrammar.addGrammarAlias(subgrammarName, subgrammarAlias); - } - - /** - * Load a subgrammar into this one. - * - * @param subgrammarName - * The name to assign to the subgrammar - * @param subgrammarPath - * The path to load the subgrammar from - */ - public void loadSubgrammar(String subgrammarName, - String subgrammarPath) { - Path loadPath = currentDirectory.resolve(subgrammarPath); - - try { - WeightedGrammar subgrammar = RBGrammarReader - .fromPath(loadPath); - - currentGrammar.addSubgrammar(subgrammarName, subgrammar); - } catch (IOException ioex) { - PragmaErrorException peex = new PragmaErrorException( - "Couldn't load subgrammar " + subgrammarName + " from " - + subgrammarPath); - - peex.initCause(ioex); - - throw peex; - } - } - - /** - * Prefix a token onto all of the cases for the specified rule - * - * @param ruleName - * The rule to do prefixing on - * @param prefixToken - * The token to prefix onto each case - * @param additionalProbability - * The probability modification of the prefixed cases - */ - public void prefixRule(String ruleName, String prefixToken, - int additionalProbability) { - currentGrammar.prefixRule(ruleName, prefixToken, - additionalProbability); - } - - /** - * Promote the specified subgrammar above the current grammar - * - * @param subgrammarName - * The name of the subgrammar to promote - * @param subordinateName - * The name to bind this grammar to the subgrammar under - */ - public void promoteGrammar(String subgrammarName, - String subordinateName) { - WeightedGrammar subgrammar = currentGrammar - .getSubgrammar(subgrammarName); - - currentGrammar.deleteSubgrammar(subgrammarName); - - subgrammar.addSubgrammar(subordinateName, currentGrammar); - - currentGrammar = subgrammar; - } - - /** - * Delete a rule from the current subgrammar - * - * @param ruleName - * The name of the rule to delete - */ - public void deleteRule(String ruleName) { - currentGrammar.deleteRule(ruleName); - } - - /** - * Delete a subgrammar from the current grammar - * - * @param subgrammarName - * The name of the subgrammar to delete - */ - public void deleteSubgrammar(String subgrammarName) { - currentGrammar.deleteSubgrammar(subgrammarName); - } - - /** - * Save the current grammar as a subgrammar of the previous one - * - * @param subgrammarName - * The name of the subgrammar to save this under - */ - public void saveSubgrammar(String subgrammarName) { - WeightedGrammar newWorkingGrammar = grammarStack.pop(); - - newWorkingGrammar.addSubgrammar(subgrammarName, currentGrammar); - - currentGrammar = newWorkingGrammar; - } - - /** - * Subordinate this grammar as a subgrammar to a new grammar - * - * @param grammarName - * The name for the subgrammar to bind the current grammar - * to - */ - public void subordinateGrammar(String grammarName) { - WeightedGrammar newWorkingGrammar = new WeightedGrammar<>(); - - newWorkingGrammar.addSubgrammar(grammarName, currentGrammar); - - currentGrammar = newWorkingGrammar; - } - - /** - * Suffix a token onto all of the cases for the specified rule - * - * @param ruleName - * The rule to do suffixing on - * @param suffixToken - * The token to suffix onto each case - * @param additionalProbability - * The probability modification of the suffixed cases - */ - public void suffixRule(String ruleName, String suffixToken, - int additionalProbability) { - currentGrammar.suffixRule(ruleName, suffixToken, - additionalProbability); - } -} diff --git a/RGens/src/main/java/bjc/RGens/server/CLIArgsParser.java b/RGens/src/main/java/bjc/RGens/server/CLIArgsParser.java deleted file mode 100644 index a39ce1d..0000000 --- a/RGens/src/main/java/bjc/RGens/server/CLIArgsParser.java +++ /dev/null @@ -1,141 +0,0 @@ -package bjc.RGens.server; - -import java.io.File; - -public class CLIArgsParser { - public static void parseArgs(String[] args, GrammarServerEngine eng) { - boolean didTerminalOp = false; - boolean forceInteractive = false; - - // @TODO report error status - boolean didError = false; - - if(args.length < 0) return; - - if(args.length == 1 && args[0].equals("--help")) { - // @TODO show help - } else { - for(int i = 0; i < args.length; i++) { - String arg = args[i]; - - switch(arg) { - case "-lc": - case "--load-config-file": - String configFileName = args[++i]; - - eng.doLoadConfig(configFileName); - break; - case "-lg": - case "--load-grammar-file": - String grammarFileName = args[++i]; - - File grammarFile = new File(grammarFileName); - - String ruleName = grammarFile.getName(); - ruleName = ruleName.substring(0, ruleName.lastIndexOf('.')); - - if(!args[i+1].startsWith("-")) { - ruleName = args[++i]; - } - - eng.doLoadGrammar(ruleName, grammarFileName); - - break; - case "-ll": - case "--load-long-file": - String longRuleFileName = args[++i]; - - File longRuleFile = new File(longRuleFileName); - - String longRuleName = longRuleFile.getName(); - longRuleName = longRuleName.substring(0, longRuleName.lastIndexOf('.')); - - if(!args[i+1].startsWith("-")) { - longRuleName = args[++i]; - } - - eng.doLoadLongRule(longRuleName, longRuleFileName); - - break; - case "-ge": - case "--generate-exported-rule": - String exportedRuleName = args[++i]; - - if(eng.hasExportedRule(exportedRuleName)) { - eng.doGenerateExportedRule(exportedRuleName); - didTerminalOp = true; - } else { - System.out.printf("Error: No exported rule named %s\n", exportedRuleName); - } - break; - case "-gg": - case "--generate-grammar-rule": - String grammarName = args[++i]; - - if(!eng.hasLoadedGrammar(grammarName)) { - System.out.printf("Error: No grammar named %s\n", grammarName); - } else { - String ruleToGenerate = ""; - - if(!args[i+1].startsWith("-")) { - ruleToGenerate = args[++i]; - } else if(eng.hasInitialRule(grammarName)) { - ruleToGenerate = eng.getInitialRule(grammarName); - } else { - System.out.printf("Error: Grammar %s has no initial rule. A " - + "rule must be provided.",grammarName); - } - - eng.doGenerateGrammar(grammarName, ruleToGenerate); - didTerminalOp = true; - } - break; - case "-st": - case "--stress-test": - String thingToTest = args[++i]; - - // @TODO support testing rules from grammars - // as well as a specified number of times - if(thingToTest.equals("*")) { - eng.doStressTest(10000); - } else { - eng.doStressTest(thingToTest, 1000); - } - - didTerminalOp = true; - - break; - case "-d": - case "--debug": - if(eng.debugMode) { - System.out.println("Warning: debug mode is already on. Use -nd or --no-debug" - + " to turn it off"); - } else { - eng.debugMode = true; - } - break; - case "-nd": - case "--no-debug": - if(!eng.debugMode) { - System.out.println("Warning: debug mode is already off. Use -d or --debug" - + " to turn it on"); - } else { - eng.debugMode = false; - } - break; - case "-i": - case "--interactive": - forceInteractive = true; - break; - default: - System.out.println("Error: Unrecognized argument " + arg); - break; - } - } - } - - if(!forceInteractive && didTerminalOp) { - System.exit(didError ? 1 : 0); - } - } -} diff --git a/RGens/src/main/java/bjc/RGens/server/GrammarServer.java b/RGens/src/main/java/bjc/RGens/server/GrammarServer.java deleted file mode 100644 index 8c438c3..0000000 --- a/RGens/src/main/java/bjc/RGens/server/GrammarServer.java +++ /dev/null @@ -1,346 +0,0 @@ -package bjc.RGens.server; - -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IMap; -import bjc.utils.gen.WeightedGrammar; - -import java.io.File; - -import java.util.Scanner; - -public class GrammarServer { - private Scanner scn; - - private IMap> loadedGrammars; - private IMap> exportedRules; - - private GrammarServerEngine eng; - - public GrammarServer(Scanner scn) { - this.scn = scn; - - this.loadedGrammars = new FunctionalMap<>(); - this.exportedRules = new FunctionalMap<>(); - - eng = new GrammarServerEngine(loadedGrammars, exportedRules); - - ServerGrammarReader.setExportedRules(exportedRules); - } - - public static void main(String[] args) { - System.out.println("GrammarServer 1.0"); - - Scanner scn = new Scanner(System.in); - - GrammarServer serv = new GrammarServer(scn); - - CLIArgsParser.parseArgs(args, serv.eng); - - System.out.print("Enter a command (m for help): "); - - char comm = scn.nextLine().charAt(0); - - while(comm != 'e') { - switch(comm) { - case 'm': - System.out.println("GrammarServer Commands:"); - System.out.println("\tm: Print command help"); - System.out.println("\te: Exit GrammarServer"); - System.out.println("\tl: Load from file"); - System.out.println("\ts: Show information"); - System.out.println("\tg: Generate text"); - break; - case 'g': - serv.generateMode(); - break; - case 's': - serv.showMode(); - break; - case 'l': - serv.loadMode(); - break; - default: - System.out.println("? Unrecognized Command"); - } - - System.out.print("Enter a command (m for help): "); - - comm = scn.nextLine().charAt(0); - } - - System.out.println("GrammarServer exiting"); - } - - - - private void loadMode() { - System.out.println("Entering Load Mode"); - - System.out.print("(Load Mode) Enter a command (m for help): "); - char comm = scn.nextLine().charAt(0); - - while(comm != 'e') { - switch(comm) { - case 'm': - System.out.println("GrammarServer Load Mode Commands"); - System.out.println("\tm: Show command help"); - System.out.println("\te: Exit Load Mode"); - System.out.println("\tg: Load grammar from a file"); - System.out.println("\tl: Load long rule from a file"); - System.out.println("\tc: Load configuration from a file"); - break; - case 'g': - loadGrammar(); - break; - case 'c': - loadConfig(); - break; - case 'l': - loadLongRule(); - break; - default: - System.out.println("? Unrecognized Command"); - } - - System.out.print("(Load Mode) Enter a command (m for help): "); - comm = scn.nextLine().charAt(0); - } - - System.out.println("Exiting Load Mode"); - } - - private void loadGrammar() { - System.out.print("Enter path to load grammar from: "); - - String grammarPath = scn.nextLine().trim(); - - File grammarFile = new File(grammarPath); - - String grammarName = grammarFile.getName().trim(); - - grammarName = grammarName.substring(0, grammarName.lastIndexOf(".")); - - System.out.printf("Enter grammar name or press enter for" - + " the default (%s): ", grammarName); - - String inputName = scn.nextLine(); - - if(!inputName.equals("")) { - grammarName = inputName; - } - - eng.doLoadGrammar(grammarName, grammarPath); - - return; - } - - private void loadLongRule() { - System.out.print("Enter the file to load a long rule from: "); - - String fileName = scn.nextLine().trim(); - File ruleFile = new File(fileName); - - String tempName = ruleFile.getName(); - tempName = tempName.substring(0, tempName.lastIndexOf('.')); - - System.out.printf("Enter the name for the long rule (default %s): ", tempName); - - String ruleName = scn.nextLine().trim(); - - if(ruleName.equals("")) { - ruleName = tempName; - } - - eng.doLoadLongRule(ruleName, fileName); - } - - private void loadConfig() { - System.out.print("Enter the file to load configuration from: "); - - String fileName = scn.nextLine().trim(); - - eng.doLoadConfig(fileName); - } - - private void showMode() { - System.out.println("Entering Show Mode"); - - System.out.print("(Show Mode) Enter a command (m for help): "); - - char comm = scn.nextLine().charAt(0); - - while(comm != 'e') { - switch(comm) { - case 'm': - System.out.println("GrammarServer Show Mode Commands: "); - System.out.println("\tm: Show command help"); - System.out.println("\tl: Show loaded grammars"); - System.out.println("\tr: Show rules from a grammar"); - System.out.println("\tx: Show exported rules"); - System.out.println("\te: Exit Show Mode"); - break; - case 'r': - showGrammarRules(); - break; - case 'x': - eng.doShowExportedRules(); - break; - case 'l': - eng.doShowLoadedGrammars(); - break; - default: - System.out.println("? Unrecognized command"); - break; - } - - System.out.print("(Show Mode) Enter a command (m for help): "); - - comm = scn.nextLine().charAt(0); - } - - - - System.out.println("Exiting Show Mode"); - } - - private void generateMode() { - System.out.println("Entering Generate Mode"); - - System.out.print("(Generate Mode) Enter a command (m for help): "); - - char comm = scn.nextLine().charAt(0); - - while(comm != 'e') { - switch(comm) { - case 'm': - System.out.println("GrammarServer Generate Mode Commands: "); - System.out.println("\tm: Show command help"); - System.out.println("\tx: Generate from exported rules"); - System.out.println("\tr: Generate from a grammar"); - System.out.println("\te: Exit Generate Mode"); - break; - case 'x': - generateExportedRule(); - break; - case 'r': - generateGrammar(); - break; - default: - System.out.println("? Unrecognized command"); - } - - System.out.print("(Generate Mode) Enter a command (m for help): "); - - comm = scn.nextLine().charAt(0); - } - - System.out.println("Exiting Generate Mode"); - } - - private void generateExportedRule() { - System.out.print("Enter the name of the rule to generate" - + " (l to list, enter to cancel): "); - - String ruleName = scn.nextLine().trim(); - - while(true) { - if(ruleName.equals("")) break; - - if(ruleName.equals("l")) { - eng.doShowExportedRules(); - } else if (exportedRules.containsKey(ruleName)) { - eng.doGenerateExportedRule(ruleName); - - System.out.print("Generate again from this rule? (yes/no) (yes by default): "); - - String resp = scn.nextLine().trim(); - - if(resp.equalsIgnoreCase("yes") || resp.equals("")) { - continue; - } - } else { - System.out.println("? Unrecognized external rule"); - } - - System.out.print("Enter the name of the rule to generate" - + " (l to list, enter to cancel): "); - - ruleName = scn.nextLine().trim(); - } - } - - private void generateGrammar() { - System.out.print("Enter the name of the grammar to generate from (l to list, enter to cancel): "); - - String grammarName = scn.nextLine().trim(); - - while(true) { - if(grammarName.equals("")) break; - - if(grammarName.equals("l")) { - eng.doShowLoadedGrammars(); - } else if(loadedGrammars.containsKey(grammarName)) { - WeightedGrammar currentGram = loadedGrammars.get(grammarName); - - System.out.print("Enter the name of the rule to generate" - + " (l to list, enter to cancel): "); - - String ruleName = scn.nextLine().trim(); - - while(true) { - if(ruleName.equals("")) break; - - if(ruleName.equals("l")) { - eng.doShowGrammarRules(grammarName); - } else if (currentGram.hasRule(ruleName)) { - eng.doGenerateGrammar(currentGram, ruleName); - - System.out.print("Generate again from this rule? (yes/no) (yes by default): "); - - String resp = scn.nextLine().trim(); - - if(resp.equalsIgnoreCase("yes") || resp.equals("")) { - continue; - } - } else { - System.out.println("? Unrecognized grammar rule"); - } - - System.out.print("Enter the name of the rule to generate" - + " (l to list, enter to cancel): "); - - ruleName = scn.nextLine().trim(); - } - - } else { - System.out.println("? Unrecognized grammar name"); - } - - System.out.print("Enter the name of the grammar to generate from " - + "(l to list, enter to cancel): "); - - grammarName = scn.nextLine().trim(); - } - } - - private void showGrammarRules() { - System.out.print("Enter the name of the grammar (l to list): "); - String gramName = scn.nextLine().trim(); - - do { - if(gramName.equals("")) break; - - if(gramName.equals("l")) { - eng.doShowLoadedGrammars(); - } else if (loadedGrammars.containsKey(gramName)) { - eng.doShowGrammarRules(gramName); - break; - } else { - System.out.println("? Unrecognized grammar name"); - } - - System.out.print("Enter the name of the grammar (l to list): "); - gramName = scn.nextLine().trim(); - } while(true); - } -} diff --git a/RGens/src/main/java/bjc/RGens/server/GrammarServerEngine.java b/RGens/src/main/java/bjc/RGens/server/GrammarServerEngine.java deleted file mode 100644 index 0fe96d9..0000000 --- a/RGens/src/main/java/bjc/RGens/server/GrammarServerEngine.java +++ /dev/null @@ -1,300 +0,0 @@ -package bjc.RGens.server; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.LinkedList; -import java.util.Queue; -import java.util.Scanner; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcutils.ListUtils; -import bjc.utils.gen.WeightedGrammar; - -public class GrammarServerEngine { - private IMap> loadedGrammars; - private IMap> exportedRules; - - public static boolean debugMode = false; - - public GrammarServerEngine(IMap> loadedGrammars, - IMap> exportedRules) { - this.loadedGrammars = loadedGrammars; - this.exportedRules = exportedRules; - } - - public String getInitialRule(String grammarName) { - return loadedGrammars.get(grammarName).getInitialRule(); - } - - public boolean hasInitialRule(String grammarName) { - return loadedGrammars.get(grammarName).hasInitialRule(); - } - - public boolean hasExportedRule(String ruleName) { - return exportedRules.containsKey(ruleName); - } - - public boolean hasLoadedGrammar(String grammarName) { - return loadedGrammars.containsKey(grammarName); - } - - public void doLoadConfig(String fileName) { - File inputFile = new File(fileName); - - try(FileInputStream inputStream = new FileInputStream(inputFile)) { - try(Scanner fle = new Scanner(inputStream)) { - while(fle.hasNextLine()) { - String line = fle.nextLine().trim(); - - // Handle comments - if(line.equals("") || - line.startsWith("#") || - line.startsWith("//")) { - continue; - } - - // Handle mixed whitespace in input - line = line.replaceAll("\\s+", " "); - - String path; - String name; - - if(line.lastIndexOf(' ') != -1) { - path = line.substring(0, line.lastIndexOf(' ')); - name = line.substring(line.lastIndexOf(' ') + 1, line.length()); - } else { - path = line; - - File pathFile = new File(path); - String pathName = pathFile.getName(); - - if(pathFile.isDirectory()) { - // Load all the files in the directory recursively - Queue entries = new LinkedList<>(); - - for (File entry : pathFile.listFiles()) { - entries.add(entry); - } - - while(!entries.isEmpty()) { - File entry = entries.poll(); - - String entryPath = entry.getName(); - - if(entry.isHidden()) continue; - if(entry.isDirectory()) { - for (File newEntry : entry.listFiles()) { - entries.add(newEntry); - } - - continue; - } - - name = entryPath.substring(0, entryPath.lastIndexOf('.')); - - doLoadGrammarEntry(entry.toString(), name); - } - - continue; - } - - name = pathName.substring(0, pathName.lastIndexOf('.')); - } - - doLoadGrammarEntry(path, name); - } - } - } catch(IOException ioex) { - System.out.printf("? Error reading configuration from file" - + " (reason: %s)\n", ioex.getMessage()); - } - } - - private void doLoadGrammarEntry(String path, String name) { - if(path.endsWith(".gram")) { - doLoadGrammar(name, path); - } else if(path.endsWith(".template")) { - System.out.println("Error: Templates are not supported yet"); - } else if(path.endsWith(".long")) { - doLoadLongRule(name, path); - } else { - System.out.println("Error: Unknown filetype " + - path.substring(path.lastIndexOf("."), path.length())); - } - } - - public void doLoadLongRule(String ruleName, String ruleFile) { - ruleName = "[" + ruleName + "]"; - - if(debugMode) { - System.out.printf("Loading long rule (named %s) from path %s\n", - ruleName, ruleFile); - } - - try (FileInputStream inputStream = new FileInputStream(ruleFile)) { - try (Scanner fle = new Scanner(inputStream)) { - IList> ruleParts = new FunctionalList<>(); - - while(fle.hasNextLine()) { - ruleParts.add(new FunctionalList<>(fle.nextLine().trim().split(" "))); - } - - WeightedGrammar longGram = new WeightedGrammar<>(); - - longGram.addSpecialRule(ruleName, () -> ruleParts.randItem()); - longGram.setInitialRule(ruleName); - - exportedRules.put(ruleName, longGram); - - if(debugMode) { - System.out.printf("Loaded long rule (named %s) from path %s\n", - ruleName, ruleFile); - } - } - } catch (IOException ioex) { - System.out.printf("Error reading long rule (%s)\n", ioex.getMessage()); - } - } - - public void doLoadGrammar(String grammarName, String grammarPath) { - if(debugMode) { - System.out.printf("Loading grammar (named %s) from path %s\n", - grammarName, grammarPath); - } - - try (FileInputStream inputStream = new FileInputStream(grammarPath)) { - WeightedGrammar newGram = - ServerGrammarReader.fromStream(inputStream).merge((gram, exports) -> { - for(String export : exports.toIterable()) { - if(debugMode) { - System.out.printf("\tLoaded exported rule %s from grammar %s\n", - export, grammarName); - - if(exportedRules.containsKey(export)) { - System.out.printf("\tWarning: Exported rule %s from grammar %s" + - " shadows a pre-existing rule\n", export, grammarName); - } - } - - exportedRules.put(export, gram); - } - - return gram; - }); - - loadedGrammars.put(grammarName, newGram); - } catch (IOException ioex) { - System.out.printf("? Error reading grammar from file" - + " (reason: %s)\n", ioex.getMessage()); - } - - if(debugMode) { - System.out.printf("Loaded grammar (named %s) from path %s\n", - grammarName, grammarPath); - } - } - - public void doGenerateExportedRule(String ruleName) { - String ruleResult = ListUtils.collapseTokens( - exportedRules.get(ruleName) - .generateListValues(ruleName, " ")); - - System.out.println("Generated Result: "); - System.out.println("\t" + ruleResult.replaceAll("\\s+", " ")); - } - - public void doGenerateGrammar(String currentGram, String ruleName) { - doGenerateGrammar(loadedGrammars.get(currentGram), ruleName); - } - - public void doGenerateGrammar(WeightedGrammar currentGram, String ruleName) { - String ruleResult = ListUtils.collapseTokens( - currentGram.generateListValues(ruleName, " ")); - - System.out.println("Generated Result: "); - System.out.println("\t" + ruleResult.replaceAll("\\s+", " ")); - } - - public void doShowExportedRules() { - System.out.printf("Currently exported rules (%d total):\n", - exportedRules.getSize()); - - exportedRules.forEachKey(key -> { - System.out.println("\t" + key); - }); - } - - public void doShowGrammarRules(String gramName) { - WeightedGrammar gram = loadedGrammars.get(gramName); - - IList ruleNames = gram.getRuleNames(); - - System.out.printf("Rules for grammar %s (%d total)\n", - gramName, ruleNames.getSize()); - - ruleNames.forEach(rule -> { - System.out.println("\t" + rule); - }); - } - - public void doShowLoadedGrammars() { - System.out.printf("Currently loaded grammars (%d total):\n", - loadedGrammars.getSize()); - - loadedGrammars.forEachKey(key -> { - System.out.println("\t" + key); - }); - } - - public void doStressTest(int count) { - exportedRules.forEachKey(key -> { - doStressTest(key, count); - }); - } - - public void doStressTest(String ruleName, int count) { - doStressTest(exportedRules.get(ruleName), ruleName, count); - } - - public void doStressTest(WeightedGrammar gram, String ruleName, int count) { - if(debugMode) System.out.println("Stress-testing rule " + ruleName); - - IList res = new FunctionalList<>(); - IList foundTags = new FunctionalList<>(); - - boolean foundBroken = false; - - for(int i = 0; i < count; i++) { - res = gram.generateListValues(ruleName, " "); - - for(String tok : res.toIterable()) { - if(tok.matches("\\[\\S+\\]") && !foundTags.contains(tok)) { - System.out.println("\tWarning: Possible un-expanded rule " + tok + " found" - + " in expansion of " + ruleName); - - doFindRule(tok); - - foundBroken = true; - - foundTags.add(tok); - } - } - } - - if(debugMode) { - if(!foundBroken) System.out.printf("Rule %s succesfully passed stress-testing\n", ruleName); - else System.out.printf("Rule %s failed stress-testing\n", ruleName); - } - } - - private void doFindRule(String ruleName) { - loadedGrammars.forEach((gramName, gram) -> { - if(gram.hasRule(ruleName)) { - System.out.printf("\t\tFound rule %s in grammar %s\n", ruleName, gramName); - } - }); - } -} diff --git a/RGens/src/main/java/bjc/RGens/server/ReaderState.java b/RGens/src/main/java/bjc/RGens/server/ReaderState.java deleted file mode 100644 index 3a12ed6..0000000 --- a/RGens/src/main/java/bjc/RGens/server/ReaderState.java +++ /dev/null @@ -1,181 +0,0 @@ -package bjc.RGens.server; - -import java.util.function.Supplier; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.gen.WeightedGrammar; - -/** - * Represents the internal state of reader - * - * @author ben - * - */ -public class ReaderState { - private WeightedGrammar currentGrammar; - private String currentRule; - private boolean isUniform; - - private IList exports; - - /** - * Create a new reader state - */ - public ReaderState() { - currentGrammar = new WeightedGrammar<>(); - - // Grammars start out uniform - isUniform = true; - - exports = new FunctionalList<>(); - } - - public void addExport(String export) { - exports.add(export); - } - - public IList getExports() { - return exports; - } - - /** - * Get the rule names for the current grammar - * - * @return The rule names for the current grammar - */ - public IList getRuleNames() { - return currentGrammar.getRuleNames(); - } - - /** - * Check if this reader is currently in uniform mode - * - * @return Whether this grammar is in uniform mode - */ - public boolean isUniform() { - return isUniform; - } - - /** - * Set the current grammar to be the specified one - * - * @param newWorkingGrammar - * The new grammar to use - */ - public void setCurrentGrammar(WeightedGrammar newWorkingGrammar) { - currentGrammar = newWorkingGrammar; - } - - /** - * Set the rule currently being worked on - * - * @param ruleName - * The rule currently being worked on - */ - public void setCurrentRule(String ruleName) { - currentRule = ruleName; - } - - /** - * Set the initial rule of this grammar - * - * @param ruleName - * The initial rule of this grammar - */ - public void setInitialRule(String ruleName) { - currentGrammar.setInitialRule(ruleName); - } - - /** - * Toggle this uniformity setting for this grammar - */ - public void toggleUniformity() { - isUniform = !isUniform; - } - - /** - * Add a case to the current grammar - * - * @param ruleProbability - * The probability for this case to occur - * @param ruleParts - * The parts that make up this case - */ - public void addCase(int ruleProbability, IList ruleParts) { - currentGrammar.addCase(currentRule, ruleProbability, ruleParts); - } - - /** - * Add a special rule to the grammar - * - * @param ruleName The name of the special rule - * @param cse The special case for the rule - */ - public void addSpecialRule(String ruleName, Supplier> cse) { - currentGrammar.addSpecialRule(ruleName, cse); - } - - /** - * Start editing a new rule in the current grammar - * - * @param ruleName - * The name of the new rule to edit - */ - public void startNewRule(String ruleName) { - currentGrammar.addRule(ruleName); - - currentRule = ruleName; - } - - /** - * Convert this package of state into a weighted grammar - * - * @return The grammar represented by this state - */ - public WeightedGrammar getGrammar() { - return currentGrammar; - } - - /** - * Prefix a token onto all of the cases for the specified rule - * - * @param ruleName - * The rule to do prefixing on - * @param prefixToken - * The token to prefix onto each case - * @param additionalProbability - * The probability modification of the prefixed cases - */ - public void prefixRule(String ruleName, String prefixToken, - int additionalProbability) { - currentGrammar.prefixRule(ruleName, prefixToken, - additionalProbability); - } - - /** - * Delete a rule from the current grammar - * - * @param ruleName - * The name of the rule to delete - */ - public void deleteRule(String ruleName) { - currentGrammar.deleteRule(ruleName); - } - - /** - * Suffix a token onto all of the cases for the specified rule - * - * @param ruleName - * The rule to do suffixing on - * @param suffixToken - * The token to suffix onto each case - * @param additionalProbability - * The probability modification of the suffixed cases - */ - public void suffixRule(String ruleName, String suffixToken, - int additionalProbability) { - currentGrammar.suffixRule(ruleName, suffixToken, - additionalProbability); - } -} diff --git a/RGens/src/main/java/bjc/RGens/server/ServerGrammarReader.java b/RGens/src/main/java/bjc/RGens/server/ServerGrammarReader.java deleted file mode 100644 index da42b36..0000000 --- a/RGens/src/main/java/bjc/RGens/server/ServerGrammarReader.java +++ /dev/null @@ -1,326 +0,0 @@ -package bjc.RGens.server; - -import com.mifmif.common.regex.Generex; - -import java.io.InputStream; -import java.util.Random; -import java.util.function.BiFunction; -import java.util.function.Predicate; - -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; -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; - -/** - * Read a grammar from a stream - * - * @author ben - * - */ -public class ServerGrammarReader { - static { - setupReader(); - - initPragmas(); - } - - private static RuleBasedConfigReader reader; - - private static Random numgen = new Random(); - - private static IMap> exportedRules; - - public static void setExportedRules(IMap> rules) { - exportedRules = rules; - } - - /** - * Read a grammar from a stream - * - * @param inputStream - * The stream to load the grammar from - * - * @return A grammar read from the stream - * - */ - public static IPair, IList> - fromStream(InputStream inputStream) { - ReaderState initialState = new ReaderState(); - - WeightedGrammar gram = reader.fromStream(inputStream, initialState).getGrammar(); - - IMap> vars = new FunctionalMap<>(); - - Predicate specialPredicate = (strang) -> { - if(strang.matches("\\[\\S+\\]")) { - return true; - } - - return false; - }; - - BiFunction, IList> - specialAction = (strang, gramm) -> { - return handleSpecialRule(vars, strang, gramm); - }; - - gram.configureSpecial(specialPredicate, specialAction); - - IList exports = initialState.getExports(); - - if(gram.getInitialRule() != null && !exports.contains(gram.getInitialRule())) { - exports.add(gram.getInitialRule()); - } - - return new Pair<>(gram, exports); - } - - private static void initPragmas() { - reader.addPragma("debug", (tokenizer, state) -> { - debugGrammar(state); - }); - - reader.addPragma("uniform", (tokenizer, state) -> { - state.toggleUniformity(); - }); - - reader.addPragma("initial-rule", ServerGrammarReader::initialRule); - - reader.addPragma("remove-rule", ServerGrammarReader::removeRule); - - reader.addPragma("prefix-with", ServerGrammarReader::prefixRule); - reader.addPragma("suffix-with", ServerGrammarReader::suffixRule); - - reader.addPragma("regex-rule", ServerGrammarReader::handleRegexRule); - - reader.addPragma("range-rule", ServerGrammarReader::handleRangeRule); - - reader.addPragma("export-rule", (tokenizer, state) -> { - String ruleName = tokenizer.nextToken(); - - state.addExport(ruleName); - }); - } - - private static void setupReader() { - reader = new RuleBasedConfigReader<>(null, null, null); - - reader.setStartRule((tokenizer, stateTokenPair) -> { - stateTokenPair.doWith((initToken, state) -> { - state.startNewRule(initToken); - - doCase(tokenizer, state); - }); - }); - - reader.setContinueRule((tokenizer, state) -> { - doCase(tokenizer, state); - }); - - reader.setEndRule((tokenizer) -> { - tokenizer.setCurrentRule(null); - }); - } - - private static void debugGrammar(ReaderState state) { - System.out.println("Printing rule names: "); - - for (String currentRule : state.getRuleNames().toIterable()) { - System.out.println("\t" + currentRule); - } - - System.out.println(); - } - - private static IList handleSpecialRule(IMap> vars, String strang, - WeightedGrammar gramm) { - IList retList = new FunctionalList<>(); - - if(strang.matches("\\[\\[\\S+\\]\\]")) { - if(strang.matches("\\[\\[\\S+:=\\S+\\]\\]")) { - doDefineExpandedVariable(vars, strang, gramm); - } else if(strang.matches("\\[\\[\\S+=\\S+\\]\\]")) { - doDefineVariable(vars, strang); - } else if(strang.matches("\\[\\[\\S+\\]\\]")) { - if(GrammarServerEngine.debugMode) { - if(strang.contains("+")) - System.out.println("Double-triggering no-space rule " + strang); - else - System.out.println("Triggered alternate no-space rule " + strang); - } - - doNoSpaceRule(strang, gramm, retList); - } else if (strang.contains("+")) { - if(GrammarServerEngine.debugMode) - System.out.println("Triggered alternate no-space rule " + strang); - - doNoSpaceRule(strang, gramm, retList); - } else { - // @FIXME notify the user they did something wrong - retList.add(strang); - } - } else { - if(strang.matches("\\[\\$\\S+\\-\\S+\\]")) { - retList = doExpandVariableReference(vars, strang, gramm); - } else if(strang.matches("\\[\\$\\S+\\]")) { - String varName = strang.substring(2, strang.length()); - - retList = vars.get(varName); - } else if (exportedRules.containsKey(strang) && - exportedRules.get(strang) != gramm && - !gramm.hasRule(strang)) { - // Only pick external rules if they are both - // a) in a different grammar - // b) not shadowed in the current grammar - WeightedGrammar exportGram = exportedRules.get(strang); - - retList = exportGram.generateGenericValues(strang, (s) -> s, " "); - } else if (strang.contains("+")) { - doNoSpaceRule(strang, gramm, retList); - } else { - // @FIXME notify the user they did something wrong - retList.add(strang); - } - } - - return retList; - } - - private static void handleRangeRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - - int start = Integer.parseInt(tokenizer.nextToken()); - int end = Integer.parseInt(tokenizer.nextToken()); - - state.addSpecialRule(ruleName, () -> { - int genNum = numgen.nextInt((end - start) + 1) + start; - - return new FunctionalList<>(Integer.toString(genNum)); - }); - } - - private static void handleRegexRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - - IList regx = tokenizer.toList(); - Generex regex = new Generex(ListUtils.collapseTokens(regx)); - - state.addSpecialRule(ruleName, () -> { - return new FunctionalList<>(regex.random().split(" ")); - }); - } - - private static int readOptionalProbability(FunctionalStringTokenizer tokenizer, ReaderState state) { - if (state.isUniform()) { - return 1; - } - - return Integer.parseInt(tokenizer.nextToken()); - } - - private static void initialRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String initialRuleName = tokenizer.nextToken(); - - state.setInitialRule(initialRuleName); - } - - private static void prefixRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - String prefixToken = tokenizer.nextToken(); - - int additionalProbability = readOptionalProbability(tokenizer, state); - - state.prefixRule(ruleName, prefixToken, additionalProbability); - } - - private static void removeRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - - state.deleteRule(ruleName); - } - - private static void suffixRule(FunctionalStringTokenizer tokenizer, ReaderState state) { - String ruleName = tokenizer.nextToken(); - String suffixToken = tokenizer.nextToken(); - - int additionalProbability = readOptionalProbability(tokenizer, state); - - state.suffixRule(ruleName, suffixToken, additionalProbability); - } - - private static void doCase(FunctionalStringTokenizer tokenizer, ReaderState state) { - int ruleProbability = readOptionalProbability(tokenizer, state); - - state.addCase(ruleProbability, tokenizer.toList()); - } - - private static void doDefineExpandedVariable(IMap> vars, String strang, WeightedGrammar gramm) { - String[] varParts = strang.split(":="); - - String varName = varParts[0].substring(2); - String ruleName = varParts[1].substring(0, varParts[1].length() - 2); - - IList varValue = gramm.generateGenericValues( - ruleName, (s) -> s, " "); - - vars.put(varName, varValue); - } - - private static void doDefineVariable(IMap> vars, String strang) { - String[] varParts = strang.split("="); - - String varName = varParts[0].substring(2); - String varValue = varParts[1].substring(0, varParts[1].length() - 2); - - vars.put(varName, new FunctionalList<>(varValue)); - } - - private static IList doExpandVariableReference(IMap> vars, String strang, - WeightedGrammar gramm) { - IList retList; - String[] varParts = strang.substring(1, strang.length()).split("-"); - - StringBuilder actualName = new StringBuilder("["); - - for(String varPart : varParts) { - if(varPart.startsWith("$")) { - IList 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); - - retList = gramm.generateGenericValues(actualName.toString(), (s) -> s, " "); - return retList; - } - - private static void doNoSpaceRule(String strang, WeightedGrammar gramm, IList retList) { - if(!GrammarServerEngine.debugMode) { - IList ruleValue = gramm.generateGenericValues( - strang, (s) -> s.trim(), ""); - - retList.add(ListUtils.collapseTokens(ruleValue)); - } else { - // if(!gramm.hasRule(strang)) - // System.out.println("Warning: Possible unexpanded rule " + strang); - - retList.add(strang); - } - } -} diff --git a/RGens/src/main/java/bjc/RGens/text/markov/Markov.java b/RGens/src/main/java/bjc/RGens/text/markov/Markov.java deleted file mode 100755 index 7509a99..0000000 --- a/RGens/src/main/java/bjc/RGens/text/markov/Markov.java +++ /dev/null @@ -1,189 +0,0 @@ -package bjc.RGens.text.markov; - -import java.util.Map.Entry; -import java.util.*; - -/** - * Represents a k-character substring. Can give a pseudo-random suffix - * character based on probability. - * - * @author Daniel Friedman (Fall 2011) - * - */ -public class Markov { - String substring; - int count = 0; - - TreeMap map; - - /** - * Constructs a Markov object from a given substring. - * - * @param substring - * the given substring. - */ - public Markov(String substring) { - this.substring = substring; - - map = new TreeMap<>(); - - add(); - } - - /** - * Constructs a Markov object from a given substring and suffix - * character. Suffix characters are stored in a TreeMap. - * - * @param substring - * the specified substring. - * @param suffix - * the specified suffix. - */ - public Markov(String substring, Character suffix) { - this.substring = substring; - - map = new TreeMap<>(); - - add(suffix); - } - - /** - * Increments the count of number of times the substring appears in a - * text. - */ - public void add() { - count++; - } - - /** - * Adds a suffix character to the TreeMap. - * - * @param c - * the suffix character to be added. - */ - public void add(char c) { - add(); - - if (map.containsKey(c)) { - int frequency = map.get(c); - map.put(c, frequency + 1); - } else - map.put(c, 1); - } - - /** - * Gives the frequency count of a suffix character; that is, the number - * of times the specified suffix follows the substring in a text. - * - * @param c - * the specified suffix. - * @return the frequency count. - */ - public int getFrequencyCount(char c) { - if (!map.containsKey(c)) { - return -1; - } - - return map.get(c); - } - - /** - * Gives a percentage of frequency count / number of total suffixes. - * - * @param c - * @return the ratio of frequency count of a single character to the - * total number of suffixes - */ - public double getCharFrequency(char c) { - if (getFrequencyCount(c) == -1) { - return -1; - } - - return (double) getFrequencyCount(c) / (double) count; - } - - /** - * Finds whether or not the given suffix is in the TreeMap. - * - * @param c - * the given suffix. - * @return True if the suffix exists in the TreeMap, false otherwise. - */ - public boolean containsChar(char c) { - if (!map.containsKey(c)) { - return false; - } - - return true; - } - - /** - * Gives the number of times this substring occurs in a text. - * - * @return said number of times. - */ - public int count() { - return count; - } - - /** - * Gives the TreeMap. - * - * @return the TreeMap. - */ - public TreeMap getMap() { - return map; - } - - /** - * Using probability, returns a pseudo-random character to follow the - * substring. Character possibilities are added to an ArrayList - * (duplicates allowed), and a random number from 0 to the last index - * in the ArrayList is picked. Since more common suffixes occupy more - * indices in the ArrayList, the probability of getting a more common - * suffix is greater than the probability of getting a less common - * suffix. - * - * @return the pseudo-random suffix. - */ - public char random() { - Character ret = null; - - Set> s = map.entrySet(); - - Iterator> it = s.iterator(); - - ArrayList suffixes = new ArrayList<>(); - - while (it.hasNext()) { - Entry tmp = it.next(); - - for (int i = 0; i < tmp.getValue(); i++) { - suffixes.add(tmp.getKey()); - } - } - - Random rand = new Random(); - int retIndex = rand.nextInt(suffixes.size()); - ret = suffixes.get(retIndex); - return ret; - } - - /** - * Gives a String representation of the Markov object. - * - * @return said String representation. - */ - @Override - public String toString() { - String ret = "Substring: " + substring + ", Count: " + count; - ret += "\n" + "Suffixes and frequency counts: "; - - for (Entry entry : map.entrySet()) { - char key = entry.getKey(); - int value = entry.getValue(); - ret += "\n" + "Suffix: " + key + ", frequency count: " + value; - } - return ret; - } -} diff --git a/RGens/src/main/java/bjc/RGens/text/markov/StandaloneMarkov.java b/RGens/src/main/java/bjc/RGens/text/markov/StandaloneMarkov.java deleted file mode 100644 index c8670d4..0000000 --- a/RGens/src/main/java/bjc/RGens/text/markov/StandaloneMarkov.java +++ /dev/null @@ -1,42 +0,0 @@ -package bjc.RGens.text.markov; - -import java.util.Map; - -public class StandaloneMarkov { - private int k; - - private Map markovHash; - private String firstSub; - - public StandaloneMarkov(int k, Map markovHash, - String firstSub) { - this.k = k; - this.markovHash = markovHash; - this.firstSub = firstSub; - } - - public String generateTextFromMarkov(int M) { - StringBuilder text = new StringBuilder(); - for (int i = k; i < M; i++) { - if (i == k) { - text.append(firstSub); - - if (text.length() > k) - i = text.length(); - } - - String sub = text.substring((i - k), (i)); - Markov tmp = markovHash.get(sub); - - if (tmp != null) { - Character nextChar = tmp.random(); - text.append(nextChar); - } else { - i = k - 1; - } - } - - return text.toString(); - } - -} diff --git a/RGens/src/main/java/bjc/RGens/text/markov/StandaloneTextGenerator.java b/RGens/src/main/java/bjc/RGens/text/markov/StandaloneTextGenerator.java deleted file mode 100644 index 78369d0..0000000 --- a/RGens/src/main/java/bjc/RGens/text/markov/StandaloneTextGenerator.java +++ /dev/null @@ -1,70 +0,0 @@ -package bjc.RGens.text.markov; - -import java.io.IOException; -import java.io.Reader; -import java.util.HashMap; -import java.util.Map; - -public class StandaloneTextGenerator { - - /** - * Build a markov generator from a provided source - * - * @param k - * The markov order to use - * @param reader - * The source to seed the generator from - * @return The markov generator for the provided text - */ - public static StandaloneMarkov generateMarkovMap(int k, - Reader reader) { - Map hash = new HashMap<>(); - - Character next = null; - - try { - next = (char) reader.read(); - } catch (IOException e1) { - System.out - .println("IOException in stepping through the reader"); - e1.printStackTrace(); - System.exit(1); - } - - StringBuilder origFileBuffer = new StringBuilder(); - - while (next != null && Character.isDefined(next)) { - Character.toString(next); - origFileBuffer.append(next); - - try { - next = (char) reader.read(); - } catch (IOException e) { - System.out.println( - "IOException in stepping through the reader"); - e.printStackTrace(); - } - - } - - String origFile = origFileBuffer.toString(); - String firstSub = origFile.substring(0, k); - - for (int i = 0; i < origFile.length() - k; i++) { - String sub = origFile.substring(i, i + k); - Character suffix = origFile.charAt(i + k); - - if (hash.containsKey(sub)) { - Markov marvin = hash.get(sub); - marvin.add(suffix); - hash.put(sub, marvin); - } else { - Markov marvin = new Markov(sub, suffix); - hash.put(sub, marvin); - } - } - - return new StandaloneMarkov(k, hash, firstSub); - } - -} diff --git a/RGens/src/main/java/bjc/RGens/text/markov/TextGenerator.java b/RGens/src/main/java/bjc/RGens/text/markov/TextGenerator.java deleted file mode 100755 index e8f9ea7..0000000 --- a/RGens/src/main/java/bjc/RGens/text/markov/TextGenerator.java +++ /dev/null @@ -1,69 +0,0 @@ -package bjc.RGens.text.markov; - -import java.io.*; - -/** - * Generate text from a markov model of an input text - * - * @author ben - * - */ -public class TextGenerator { - /** - * @param args - * when used with three arguments, the first represents the - * k-order of the Markov objects. The second represents the - * number of characters to print out. The third represents - * the file to be read. - * - * When used with two arguments, the first represents the - * k-order of the Markov objects, and the second represents - * the file to be read. The generated text will be the same - * number of characters as the original file. - */ - public static void main(String[] args) { - int k = 0; - int M = 0; - - String file = ""; - StringBuilder text = new StringBuilder(); - - if (args.length == 3) { - k = Integer.parseInt(args[0]); - M = Integer.parseInt(args[1]); - file = args[2]; - } else if (args.length == 2) { - k = Integer.parseInt(args[0]); - file = args[1]; - } else { - System.out - .println("\n" + "Usage: java TextGenerator k M file"); - System.out.println( - "where k is the markov order, M is the number"); - System.out.println( - "of characters to be printed, and file is the"); - System.out.println( - "name of the file to print from. M may be left out." - + "\n"); - System.exit(1); - } - - StandaloneMarkov markov = null; - - try (FileReader reader = new FileReader(file)) { - markov = StandaloneTextGenerator.generateMarkovMap(k, - reader); - - System.out.println(markov.generateTextFromMarkov(M) - .substring(0, Math.min(M, text.length()))); - } catch (FileNotFoundException e) { - System.out.println("File not found."); - e.printStackTrace(); - System.exit(1); - } catch (IOException ioex) { - System.out.println("IOException"); - ioex.printStackTrace(); - System.exit(1); - } - } -} \ No newline at end of file diff --git a/RGens/src/main/java/bjc/rgens/.DS_Store b/RGens/src/main/java/bjc/rgens/.DS_Store new file mode 100644 index 0000000..918453d Binary files /dev/null and b/RGens/src/main/java/bjc/rgens/.DS_Store differ diff --git a/RGens/src/main/java/bjc/rgens/ZadronsPouch.java b/RGens/src/main/java/bjc/rgens/ZadronsPouch.java new file mode 100644 index 0000000..7160bdd --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/ZadronsPouch.java @@ -0,0 +1,219 @@ +package bjc.rgens; + +import bjc.utils.funcdata.FunctionalStringTokenizer; +import bjc.utils.funcdata.IList; +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.gen.RandomGrammar; + +/** + * Example showing code manipulate of random grammars + * + * @author ben + * + */ +public class ZadronsPouch { + /** + * Main method for running application + * + * @param args + * Unused CLI args + */ + public static void main(String[] args) { + ZadronsPouch zp = new ZadronsPouch(); + + for (int i = 0; i < 100; i++) { + IList ls = zp.grammar.generateListValues("[item]", " "); + + StringBuilder sb = new StringBuilder(); + + ls.forEach(sp -> sb.append(sp)); + + System.out.println(sb.toString().replaceAll("\\s+", " ")); + } + } + + private RandomGrammar grammar; + + /** + * Create a new instance with a grammar + */ + public ZadronsPouch() { + grammar = new RandomGrammar<>(); + + addRule("[item]", + "[egg]", "[glove]", "[crys-sphere]", "[rock]", + "[figurine]", "[vial]", "[mini-weapon]", "[bag]", + "[card]", "[rope]", "[box]", "[wand]"); + + addEggRules(); + addGloveRules(); + addCrysSphereRules(); + addRockRules(); + + addFigurineRules(); + addVialRules(); + addMiniWeaponRules(); + addBagRules(); + + addCardRules(); + addRopeRules(); + addBoxRules(); + addWandRules(); + } + + private void addBagRules() { + addRule("[bag]", + "bag of [bag-type]", "[sack-type] sack", "[purse-type] purse"); + addRule("[bag-type]", + "holding", "tricks", "useful items", + "devouring", "dwarf-kind", "invisible cloth", + "monster summoning"); + addRule("[sack-type]", + "lunch", "recursive"); + addRule("[purse-type]", + "everfull"); + } + + private void addBoxRules() { + addRule("[box]", + "[box-type] box", "cube of [box-type]"); + addRule("[box-type]", + "limited-force", "frost-resisting", "morphing", + "self-destructing", "pandora", "panicking"); + } + + private void addCardRules() { + addRule("[card]", + "card of [card-type]", "[card-type] card"); + addRule("[card-type]", + "fate", "teleporting", "elusive treasure", "spell-storing", + "many-things", "imprisoning", "messaging", "bounty"); + } + + private void addCrysSphereRules() { + addRule("[crys-sphere]", + "[sphere-type] spheres", "[sphere-type] sphere", + "lens of [lens-type]", "[crystal-type] crystal", + "crystal of [crystal-type]", "crystal ball", + "crystal ball of [crys-suffix]"); + addRule("[sphere-type]", + "microphonic", "seeing-eye"); + addRule("[lens-type]", + "detection"); + addRule("[crystal-type]", + "prison", "radar"); + addRule("[crys-suffix]", + "jumping"); + } + + private void addEggRules() { + addRule("[egg]", + "[egg-type] egg"); + addRule("[egg-type]", + "copper", "stone", "golden", + "white", "white/pink", "glass"); + } + + private void addFigurineRules() { + addRule("[figurine]", + "[fig-material] [fig-animal]"); + addRule("[fig-material]", + "golden", "onyx", "serpentine", "ivory", + "marble", "bronze", "jade", "limestone"); + addRule("[fig-animal]", + "lion", "dog", "owl", "goat", + "elephant", "warrior", "palace", "leprechaun"); + } + + private void addGloveRules() { + addRule("[glove]", + "gauntlets of [gauntlet-type]", + "gloves of [glove-type]", + "[glove-type] gloves"); + addRule("[gauntlet-type]", + "dexterity", "power"); + addRule("[glove-type]", + "pushing", "choking", "bigby", "stunning"); + } + + private void addMiniWeaponRules() { + addRule("[mini-weapon]", + "minature [weapon-type]", "small [weapon-type]", + "tiny [weapon-type]", "[sling-type] sling", + "[weapon-type]"); + addRule("[weapon-type]", + "boomerang", "arrow", "net", + "catapult", "hammer", "sword", "club"); + addRule("[sling-type]", + "seeking"); + } + + private void addRockRules() { + addRule("[rock]", + "[pebble-type] pebble", "stone of [stone-type]", + "[stone-type] stone", "brick of [brick-type]", + "[geode-type] geode"); + addRule("[pebble-type]", + "inscribed", "elemental control"); + addRule("[stone-type]", + "good-luck", "weight", + "blind-defense", "metal-clinging"); + addRule("[brick-type]", + "flying"); + addRule("[geode-type]", + "ioun"); + } + + private void addRopeRules() { + addRule("[rope]", + "[rope-type] rope", "rope of [rope-type]", + "ball of [string-type] [string-kind]"); + addRule("[rope-type]", + "trick", "entangling", "climbing", "dancing", + "tripping", "snaring", "levitating", "self-entangling"); + addRule("[string-type]", + "endless"); + addRule("[string-kind]", + "string", "yarn"); + } + + private void addRule(String rule, String... cases) { + IList> cses = new FunctionalList<>(); + + for (String strang : cases) { + cses.add(FunctionalStringTokenizer.fromString(strang).toList(s -> s)); + } + + grammar.makeRule(rule, cses); + } + + private void addVialRules() { + addRule("[vial]", + "vial of [vial-type]", "[vial-type] vial", + "[bottle-type] bottle", "[flask-type] flask"); + addRule("[vial-type]", + "holding", "trapping", + "experience", "unnatural regeneration"); + addRule("[bottle-type]", + "ever-smoking", "wheezing", + "blank potion"); + addRule("[flask-type]", + "iron"); + } + + private void addWandRules() { + addRule("[wand]", + "[wand-type] wand", "wand of [wand-type]", + "canceling [wand-type] wand"); + addRule("[wand-type]", + "magic missile", "[spell-1]", "[spell-2]", + "gusting", "life-detecting", "zadron"); + addRule("[spell-1]", + "frost", "fire", "lightning", "fear", + "illumination", "polymorphing", "conjuration", "paralyzing"); + addRule("[spell-2]", + "[spell2-type] detecting"); + addRule("[spell2-type]", + "magic", "enemy", "secret door/trap"); + } +} diff --git a/RGens/src/main/java/bjc/rgens/gui/GrammarStudio.java b/RGens/src/main/java/bjc/rgens/gui/GrammarStudio.java new file mode 100644 index 0000000..46f0d6e --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/gui/GrammarStudio.java @@ -0,0 +1,26 @@ +package bjc.rgens.gui; + +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class GrammarStudio { + public static void main(String[] args) { + try { + UIManager.setLookAndFeel( + UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException + | UnsupportedLookAndFeelException ex) { + System.out.println( + "WARNING: Could not use system look and feel"); + ex.printStackTrace(); + } + + GrammarStudioFrame mainFrame = new GrammarStudioFrame(); + + mainFrame.setDefaultCloseOperation( + GrammarStudioFrame.EXIT_ON_CLOSE); + + mainFrame.setVisible(true); + } +} diff --git a/RGens/src/main/java/bjc/rgens/gui/GrammarStudioFrame.java b/RGens/src/main/java/bjc/rgens/gui/GrammarStudioFrame.java new file mode 100644 index 0000000..17021fc --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/gui/GrammarStudioFrame.java @@ -0,0 +1,30 @@ +package bjc.rgens.gui; + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; + +import bjc.utils.gui.layout.AutosizeLayout; + +public class GrammarStudioFrame extends JFrame { + private static final long serialVersionUID = 1476431892446002428L; + + public GrammarStudioFrame() { + super("Grammar Studio"); + + setLayout(new AutosizeLayout()); + + JDesktopPane mainPane = new JDesktopPane(); + + JMenuBar menuBar = new JMenuBar(); + + JMenu fileMenu = new JMenu("File"); + fileMenu.setMnemonic('m'); + + menuBar.add(fileMenu); + + setJMenuBar(menuBar); + add(mainPane); + } +} diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java new file mode 100644 index 0000000..9b47bd6 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java @@ -0,0 +1,5 @@ +package bjc.rgens.newparser; + +public class RGrammar { + +} diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java new file mode 100644 index 0000000..3b48a2a --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarBuilder.java @@ -0,0 +1,7 @@ +package bjc.rgens.newparser; + +public class RGrammarBuilder { + public RGrammar toRGrammar() { + return null; + } +} diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java new file mode 100644 index 0000000..d60c6d4 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammarParser.java @@ -0,0 +1,110 @@ +package bjc.rgens.newparser; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.StringReader; +import java.util.Scanner; + +/** + * Reads {@link RGrammar} from a input stream. + * + * @author student + * + */ +public class RGrammarParser { + /** + * The exception thrown when something goes wrong while parsing a grammar. + * + * @author student + * + */ + public static class GrammarException extends Exception { + /* + * Serialization ID. + */ + private static final long serialVersionUID = -7287427479316953668L; + + /** + * Create a new grammar exception with the specified message. + * + * @param msg + * The message for this exception. + */ + public GrammarException(String msg) { + super(msg); + } + + /** + * Create a new grammar exception with the specified message and cause. + * + * @param msg + * The message for this exception. + * + * @param cause + * The cause of this exception. + */ + public GrammarException(String msg, Exception cause) { + super(msg, cause); + } + } + + /** + * Read a {@link RGrammar} from an input stream. + * + * @param is + * The input stream to read from. + * + * @return The grammar represented by the stream. + * + * @throws GrammarException + * Thrown if the grammar has a syntax error. + */ + public RGrammar readGrammar(InputStream is) throws GrammarException { + LineNumberReader lnReader = new LineNumberReader(new InputStreamReader(is)); + + try (Scanner scn = new Scanner(lnReader)) { + scn.useDelimiter("\\n\\.?\\n"); + + RGrammarBuilder build = new RGrammarBuilder(); + + while (scn.hasNext()) { + String block = scn.next(); + + if (block.startsWith("pragma")) { + handlePragmaBlock(block, build); + } else if (block.startsWith("[")) { + handleRuleBlock(block, build); + } else { + throw new GrammarException(String.format("Unknown block: %s", lnReader.getLineNumber(), block)); + } + } + } catch (GrammarException gex) { + throw new GrammarException(String.format("Error at line %d", lnReader.getLineNumber()), gex); + } + + return null; + } + + private void handlePragmaBlock(String block, RGrammarBuilder build) throws GrammarException { + LineNumberReader lnReader = new LineNumberReader(new StringReader(block)); + + try (Scanner deblocker = new Scanner(lnReader)) { + deblocker.useDelimiter("\\n(?!\\t)"); + + while (deblocker.hasNext()) { + String pragma = deblocker.next(); + + if (!pragma.startsWith("pragma")) { + throw new GrammarException(String.format("Illegal line at line %d of pragma block: %s", + lnReader.getLineNumber(), pragma)); + } + } + } + } + + private void handleRuleBlock(String block, RGrammarBuilder build) { + // TODO Auto-generated method stub + + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/.DS_Store b/RGens/src/main/java/bjc/rgens/parser/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/RGens/src/main/java/bjc/rgens/parser/.DS_Store differ diff --git a/RGens/src/main/java/bjc/rgens/parser/GrammarReaderApp.java b/RGens/src/main/java/bjc/rgens/parser/GrammarReaderApp.java new file mode 100644 index 0000000..b3beb81 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/GrammarReaderApp.java @@ -0,0 +1,93 @@ +package bjc.rgens.parser; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintStream; + +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import bjc.utils.funcutils.ListUtils; +import bjc.utils.gen.WeightedGrammar; +import bjc.utils.gui.SimpleDialogs; +import bjc.utils.gui.awt.SimpleFileDialog; + +/** + * App that reads a grammar from a file and generates results + * + * @author ben + * + */ +public class GrammarReaderApp { + /** + * Main method of class + * + * @param args + * CLI args + */ + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException + | InstantiationException + | IllegalAccessException + | UnsupportedLookAndFeelException e) { + e.printStackTrace(); + System.exit(1); + } + + doSingleFile(); + } + + private static void doSingleFile() { + File gramFile = SimpleFileDialog.getOpenFile(null, "Choose Grammar File", ".gram"); + + WeightedGrammar grammar = null; + + try { + grammar = RBGrammarReader.fromPath(gramFile.toPath()); + } catch (IOException ioex) { + ioex.printStackTrace(); + + System.exit(1); + } + + String initRule = ""; + + if (!grammar.hasInitialRule()) { + grammar.getRuleNames().sort((leftString, rightString) -> { + return leftString.compareTo(rightString); + }); + + initRule = SimpleDialogs.getChoice(null, + "Pick a initial rule", + "Pick a initial rule to generate choices from", + grammar.getRuleNames().toArray(new String[0])); + } else { + initRule = grammar.getInitialRule(); + } + + int count = SimpleDialogs.getWhole(null, + "Enter number of repetitions", + "Enter the number of items to generate from the rule"); + + File outputFile = SimpleFileDialog.getSaveFile(null, "Choose Grammar File"); + + PrintStream outputStream = null; + + try { + outputStream = new PrintStream(outputFile); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + for (int i = 0; i < count; i++) { + String ruleResult = ListUtils.collapseTokens(grammar.generateListValues(initRule, " ")); + + outputStream.println(ruleResult.replaceAll("\\s+", " ")); + } + + outputStream.close(); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/GrammarReaderCLI.java b/RGens/src/main/java/bjc/rgens/parser/GrammarReaderCLI.java new file mode 100644 index 0000000..b8eac35 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/GrammarReaderCLI.java @@ -0,0 +1,61 @@ +package bjc.rgens.parser; + +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Paths; + +import bjc.utils.funcutils.ListUtils; +import bjc.utils.gen.WeightedGrammar; + +/** + * App that reads a grammar from a file and generates results + * + * @author ben + * + */ +public class GrammarReaderCLI { + private static WeightedGrammar grammar = null; + + /** + * Main application method + * + * @param args + * CLI args + */ + public static void main(String[] args) { + if (args.length == 0) { + GrammarReaderApp.main(args); + } else { + String fName = args[0]; + + if (fName.equalsIgnoreCase("--help")) { + System.out.println( + "Usage: java -jar GrammarReader.jar "); + System.exit(0); + } + + String ruleName = args[1]; + + try (FileInputStream fStream = new FileInputStream(fName)) { + grammar = RBGrammarReader.fromPath(Paths.get(fName, "")); + } catch (IOException e) { + e.printStackTrace(); + } + + if (ruleName.equalsIgnoreCase("--list-rules")) { + grammar.getRuleNames().forEach(System.out::println); + + System.exit(0); + } + + int rCount = Integer.parseInt(args[2]); + + for (int i = 0; i < rCount; i++) { + String ruleResult = ListUtils.collapseTokens( + grammar.generateListValues(ruleName, " ")); + + System.out.println(ruleResult.replaceAll("\\s+", " ")); + } + } + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/PragmaErrorException.java b/RGens/src/main/java/bjc/rgens/parser/PragmaErrorException.java new file mode 100644 index 0000000..05b71d3 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/PragmaErrorException.java @@ -0,0 +1,21 @@ +package bjc.rgens.parser; + +/** + * Exception for error executing a pragma + * + * @author ben + * + */ +public class PragmaErrorException extends RuntimeException { + private static final long serialVersionUID = 7245421182038076899L; + + /** + * Create a new exception with the given message + * + * @param message + * The message of the exception + */ + public PragmaErrorException(String message) { + super(message); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/RBGrammarReader.java b/RGens/src/main/java/bjc/rgens/parser/RBGrammarReader.java new file mode 100644 index 0000000..7753d25 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/RBGrammarReader.java @@ -0,0 +1,319 @@ +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; + +/** + * Read a grammar from a stream + * + * @author ben + * + */ +public class RBGrammarReader { + private static RuleBasedConfigReader reader; + + private static Random numgen = new Random(); + + static { + setupReader(); + + initPragmas(); + } + + private static void addSubgrammarPragmas() { + reader.addPragma("new-sub-grammar", (tokenizer, state) -> { + state.startNewSubgrammar(); + }); + + reader.addPragma("load-sub-grammar", RBGrammarReader::loadSubGrammar); + reader.addPragma("save-sub-grammar", RBGrammarReader::saveGrammar); + reader.addPragma("edit-sub-grammar", RBGrammarReader::editSubGrammar); + reader.addPragma("remove-sub-grammar", RBGrammarReader::removeSubGrammar); + + reader.addPragma("edit-parent", (tokenizer, state) -> { + state.editParent(); + }); + + reader.addPragma("promote", RBGrammarReader::promoteGrammar); + reader.addPragma("subordinate", RBGrammarReader::subordinateGrammar); + + } + + private static void debugGrammar(ReaderState state) { + System.out.println("Printing rule names: "); + + for (String currentRule : state.getRuleNames().toIterable()) { + System.out.println("\t" + currentRule); + } + + System.out.println(); + } + + private static void doCase(FunctionalStringTokenizer tokenizer, ReaderState state) { + int ruleProbability = readOptionalProbability(tokenizer, state); + + state.addCase(ruleProbability, tokenizer.toList()); + } + + private static void editSubGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { + String subgrammarName = tokenizer.nextToken(); + + state.editSubgrammar(subgrammarName); + } + + /** + * Read a grammar from a path + * + * @param inputPath + * The path to load the grammar from + * + * @return A grammar read from the stream + * + * @throws IOException + * If something goes wrong during file reading + * + */ + public static WeightedGrammar fromPath(Path inputPath) throws IOException { + ReaderState initialState = new ReaderState(inputPath); + + try (FileInputStream inputStream = new FileInputStream(inputPath.toFile())) { + WeightedGrammar gram = reader.fromStream(inputStream, initialState).getGrammar(); + + IMap> vars = new FunctionalMap<>(); + + Predicate specialPredicate = (strang) -> { + if(strang.matches("\\{\\S+\\}") || strang.matches("\\[\\S+\\}")) { + return true; + } + + return false; + }; + + BiFunction, IList> + specialAction = (strang, gramm) -> { + IList 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 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 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 = gramm.generateGenericValues(actualName.toString(), (s) -> s, " "); + } else { + // @FIXME notify the user they did something wrong + retList.add(strang); + } + } + + return retList; + }; + + gram.configureSpecial(specialPredicate, specialAction); + + return gram; + } catch (IOException ioex) { + throw ioex; + } + } + + private static void importRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + String subgrammarName = tokenizer.nextToken(); + + state.addGrammarAlias(subgrammarName, ruleName); + } + + private static void initialRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String initialRuleName = tokenizer.nextToken(); + + state.setInitialRule(initialRuleName); + } + + private static void initPragmas() { + addSubgrammarPragmas(); + + reader.addPragma("debug", (tokenizer, state) -> { + debugGrammar(state); + }); + + reader.addPragma("uniform", (tokenizer, state) -> { + state.toggleUniformity(); + }); + + reader.addPragma("initial-rule", RBGrammarReader::initialRule); + + reader.addPragma("import-rule", RBGrammarReader::importRule); + + reader.addPragma("remove-rule", RBGrammarReader::removeRule); + + reader.addPragma("prefix-with", RBGrammarReader::prefixRule); + reader.addPragma("suffix-with", RBGrammarReader::suffixRule); + + reader.addPragma("regex-rule", (tokenizer, state) -> { + String ruleName = tokenizer.nextToken(); + + IList 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) { + String subgrammarName = stk.nextToken(); + String subgrammarPath = stk.nextToken(); + + rs.loadSubgrammar(subgrammarName, subgrammarPath); + } + + private static void prefixRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + String prefixToken = tokenizer.nextToken(); + + int additionalProbability = readOptionalProbability(tokenizer, state); + + state.prefixRule(ruleName, prefixToken, additionalProbability); + } + + private static void promoteGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { + String subgrammarName = tokenizer.nextToken(); + String subordinateName = tokenizer.nextToken(); + + state.promoteGrammar(subgrammarName, subordinateName); + } + + private static int readOptionalProbability(FunctionalStringTokenizer tokenizer, ReaderState state) { + if (state.isUniform()) { + return 1; + } + + return Integer.parseInt(tokenizer.nextToken()); + } + + private static void removeRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + + state.deleteRule(ruleName); + } + + private static void removeSubGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { + String subgrammarName = tokenizer.nextToken(); + + state.deleteSubgrammar(subgrammarName); + } + + private static void saveGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { + String subgrammarName = tokenizer.nextToken(); + + state.saveSubgrammar(subgrammarName); + } + + private static void setupReader() { + reader = new RuleBasedConfigReader<>(null, null, null); + + reader.setStartRule((tokenizer, stateTokenPair) -> { + stateTokenPair.doWith((initToken, state) -> { + state.startNewRule(initToken); + + doCase(tokenizer, state); + }); + }); + + reader.setContinueRule((tokenizer, state) -> { + doCase(tokenizer, state); + }); + + reader.setEndRule((tokenizer) -> { + tokenizer.setCurrentRule(null); + }); + } + + private static void subordinateGrammar(FunctionalStringTokenizer tokenizer, ReaderState state) { + String grammarName = tokenizer.nextToken(); + + state.subordinateGrammar(grammarName); + } + + private static void suffixRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + String suffixToken = tokenizer.nextToken(); + + int additionalProbability = readOptionalProbability(tokenizer, state); + + state.suffixRule(ruleName, suffixToken, additionalProbability); + } +} diff --git a/RGens/src/main/java/bjc/rgens/parser/ReaderState.java b/RGens/src/main/java/bjc/rgens/parser/ReaderState.java new file mode 100644 index 0000000..89fde25 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/parser/ReaderState.java @@ -0,0 +1,306 @@ +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; + +/** + * Represents the internal state of reader + * + * @author ben + * + */ +public class ReaderState { + private WeightedGrammar currentGrammar; + + private Stack> grammarStack; + + private String currentRule; + + private boolean isUniform; + + private Path currentDirectory; + + /** + * Create a new reader state + * + * @param inputPath + * The path to this grammar + */ + public ReaderState(Path inputPath) { + grammarStack = new Stack<>(); + + currentGrammar = new WeightedGrammar<>(); + + // Grammars start out uniform + isUniform = true; + + currentDirectory = inputPath.getParent(); + } + + /** + * Get the rule names for the current grammar + * + * @return The rule names for the current grammar + */ + public IList getRuleNames() { + return currentGrammar.getRuleNames(); + } + + /** + * Check if this reader is currently in uniform mode + * + * @return Whether this grammar is in uniform mode + */ + public boolean isUniform() { + return isUniform; + } + + /** + * Set the current grammar to be the specified one + * + * @param newWorkingGrammar + * The new grammar to use + */ + public void setCurrentGrammar(WeightedGrammar newWorkingGrammar) { + currentGrammar = newWorkingGrammar; + } + + /** + * Set the rule currently being worked on + * + * @param ruleName + * The rule currently being worked on + */ + public void setCurrentRule(String ruleName) { + currentRule = ruleName; + } + + /** + * Set the initial rule of this grammar + * + * @param ruleName + * The initial rule of this grammar + */ + public void setInitialRule(String ruleName) { + currentGrammar.setInitialRule(ruleName); + } + + /** + * Toggle this uniformity setting for this grammar + */ + public void toggleUniformity() { + isUniform = !isUniform; + } + + /** + * Start work on a new sub-grammar of the previous grammar + */ + public void startNewSubgrammar() { + grammarStack.push(currentGrammar); + + currentGrammar = new WeightedGrammar<>(); + } + + /** + * Move to editing the grammar that is the parent of this current one + */ + public void editParent() { + currentGrammar = grammarStack.pop(); + } + + /** + * Add a case to the current grammar + * + * @param ruleProbability + * The probability for this case to occur + * @param ruleParts + * The parts that make up this case + */ + public void addCase(int ruleProbability, IList ruleParts) { + currentGrammar.addCase(currentRule, ruleProbability, ruleParts); + } + + public void addSpecialRule(String ruleName, Supplier> cse) { + currentGrammar.addSpecialRule(ruleName, cse); + } + /** + * Edit a subgrammar of the current grammar + * + * @param subgrammarName + * The name of the subgrammar to edit + */ + public void editSubgrammar(String subgrammarName) { + WeightedGrammar subgrammar = currentGrammar.getSubgrammar(subgrammarName); + + grammarStack.push(currentGrammar); + + currentGrammar = subgrammar; + } + + /** + * Start editing a new rule in the current grammar + * + * @param ruleName + * The name of the new rule to edit + */ + public void startNewRule(String ruleName) { + currentGrammar.addRule(ruleName); + + currentRule = ruleName; + } + + /** + * Convert this package of state into a weighted grammar + * + * @return The grammar represented by this state + */ + public WeightedGrammar getGrammar() { + return currentGrammar; + } + + /** + * Alias a current subgrammar to a new name + * + * @param subgrammarName + * The name of the subgrammar to alias + * @param subgrammarAlias + * The name of the alias for the subgrammar + */ + public void addGrammarAlias(String subgrammarName, String subgrammarAlias) { + currentGrammar.addGrammarAlias(subgrammarName, subgrammarAlias); + } + + /** + * Load a subgrammar into this one. + * + * @param subgrammarName + * The name to assign to the subgrammar + * @param subgrammarPath + * The path to load the subgrammar from + */ + public void loadSubgrammar(String subgrammarName, + String subgrammarPath) { + Path loadPath = currentDirectory.resolve(subgrammarPath); + + try { + WeightedGrammar subgrammar = RBGrammarReader + .fromPath(loadPath); + + currentGrammar.addSubgrammar(subgrammarName, subgrammar); + } catch (IOException ioex) { + PragmaErrorException peex = new PragmaErrorException( + "Couldn't load subgrammar " + subgrammarName + " from " + + subgrammarPath); + + peex.initCause(ioex); + + throw peex; + } + } + + /** + * Prefix a token onto all of the cases for the specified rule + * + * @param ruleName + * The rule to do prefixing on + * @param prefixToken + * The token to prefix onto each case + * @param additionalProbability + * The probability modification of the prefixed cases + */ + public void prefixRule(String ruleName, String prefixToken, + int additionalProbability) { + currentGrammar.prefixRule(ruleName, prefixToken, + additionalProbability); + } + + /** + * Promote the specified subgrammar above the current grammar + * + * @param subgrammarName + * The name of the subgrammar to promote + * @param subordinateName + * The name to bind this grammar to the subgrammar under + */ + public void promoteGrammar(String subgrammarName, + String subordinateName) { + WeightedGrammar subgrammar = currentGrammar + .getSubgrammar(subgrammarName); + + currentGrammar.deleteSubgrammar(subgrammarName); + + subgrammar.addSubgrammar(subordinateName, currentGrammar); + + currentGrammar = subgrammar; + } + + /** + * Delete a rule from the current subgrammar + * + * @param ruleName + * The name of the rule to delete + */ + public void deleteRule(String ruleName) { + currentGrammar.deleteRule(ruleName); + } + + /** + * Delete a subgrammar from the current grammar + * + * @param subgrammarName + * The name of the subgrammar to delete + */ + public void deleteSubgrammar(String subgrammarName) { + currentGrammar.deleteSubgrammar(subgrammarName); + } + + /** + * Save the current grammar as a subgrammar of the previous one + * + * @param subgrammarName + * The name of the subgrammar to save this under + */ + public void saveSubgrammar(String subgrammarName) { + WeightedGrammar newWorkingGrammar = grammarStack.pop(); + + newWorkingGrammar.addSubgrammar(subgrammarName, currentGrammar); + + currentGrammar = newWorkingGrammar; + } + + /** + * Subordinate this grammar as a subgrammar to a new grammar + * + * @param grammarName + * The name for the subgrammar to bind the current grammar + * to + */ + public void subordinateGrammar(String grammarName) { + WeightedGrammar newWorkingGrammar = new WeightedGrammar<>(); + + newWorkingGrammar.addSubgrammar(grammarName, currentGrammar); + + currentGrammar = newWorkingGrammar; + } + + /** + * Suffix a token onto all of the cases for the specified rule + * + * @param ruleName + * The rule to do suffixing on + * @param suffixToken + * The token to suffix onto each case + * @param additionalProbability + * The probability modification of the suffixed cases + */ + public void suffixRule(String ruleName, String suffixToken, + int additionalProbability) { + currentGrammar.suffixRule(ruleName, suffixToken, + additionalProbability); + } +} diff --git a/RGens/src/main/java/bjc/rgens/server/CLIArgsParser.java b/RGens/src/main/java/bjc/rgens/server/CLIArgsParser.java new file mode 100644 index 0000000..fa0d399 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/server/CLIArgsParser.java @@ -0,0 +1,141 @@ +package bjc.rgens.server; + +import java.io.File; + +public class CLIArgsParser { + public static void parseArgs(String[] args, GrammarServerEngine eng) { + boolean didTerminalOp = false; + boolean forceInteractive = false; + + // @TODO report error status + boolean didError = false; + + if(args.length < 0) return; + + if(args.length == 1 && args[0].equals("--help")) { + // @TODO show help + } else { + for(int i = 0; i < args.length; i++) { + String arg = args[i]; + + switch(arg) { + case "-lc": + case "--load-config-file": + String configFileName = args[++i]; + + eng.doLoadConfig(configFileName); + break; + case "-lg": + case "--load-grammar-file": + String grammarFileName = args[++i]; + + File grammarFile = new File(grammarFileName); + + String ruleName = grammarFile.getName(); + ruleName = ruleName.substring(0, ruleName.lastIndexOf('.')); + + if(!args[i+1].startsWith("-")) { + ruleName = args[++i]; + } + + eng.doLoadGrammar(ruleName, grammarFileName); + + break; + case "-ll": + case "--load-long-file": + String longRuleFileName = args[++i]; + + File longRuleFile = new File(longRuleFileName); + + String longRuleName = longRuleFile.getName(); + longRuleName = longRuleName.substring(0, longRuleName.lastIndexOf('.')); + + if(!args[i+1].startsWith("-")) { + longRuleName = args[++i]; + } + + eng.doLoadLongRule(longRuleName, longRuleFileName); + + break; + case "-ge": + case "--generate-exported-rule": + String exportedRuleName = args[++i]; + + if(eng.hasExportedRule(exportedRuleName)) { + eng.doGenerateExportedRule(exportedRuleName); + didTerminalOp = true; + } else { + System.out.printf("Error: No exported rule named %s\n", exportedRuleName); + } + break; + case "-gg": + case "--generate-grammar-rule": + String grammarName = args[++i]; + + if(!eng.hasLoadedGrammar(grammarName)) { + System.out.printf("Error: No grammar named %s\n", grammarName); + } else { + String ruleToGenerate = ""; + + if(!args[i+1].startsWith("-")) { + ruleToGenerate = args[++i]; + } else if(eng.hasInitialRule(grammarName)) { + ruleToGenerate = eng.getInitialRule(grammarName); + } else { + System.out.printf("Error: Grammar %s has no initial rule. A " + + "rule must be provided.",grammarName); + } + + eng.doGenerateGrammar(grammarName, ruleToGenerate); + didTerminalOp = true; + } + break; + case "-st": + case "--stress-test": + String thingToTest = args[++i]; + + // @TODO support testing rules from grammars + // as well as a specified number of times + if(thingToTest.equals("*")) { + eng.doStressTest(10000); + } else { + eng.doStressTest(thingToTest, 1000); + } + + didTerminalOp = true; + + break; + case "-d": + case "--debug": + if(eng.debugMode) { + System.out.println("Warning: debug mode is already on. Use -nd or --no-debug" + + " to turn it off"); + } else { + eng.debugMode = true; + } + break; + case "-nd": + case "--no-debug": + if(!eng.debugMode) { + System.out.println("Warning: debug mode is already off. Use -d or --debug" + + " to turn it on"); + } else { + eng.debugMode = false; + } + break; + case "-i": + case "--interactive": + forceInteractive = true; + break; + default: + System.out.println("Error: Unrecognized argument " + arg); + break; + } + } + } + + if(!forceInteractive && didTerminalOp) { + System.exit(didError ? 1 : 0); + } + } +} diff --git a/RGens/src/main/java/bjc/rgens/server/GrammarServer.java b/RGens/src/main/java/bjc/rgens/server/GrammarServer.java new file mode 100644 index 0000000..1a47de2 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/server/GrammarServer.java @@ -0,0 +1,346 @@ +package bjc.rgens.server; + +import bjc.utils.funcdata.FunctionalMap; +import bjc.utils.funcdata.IMap; +import bjc.utils.gen.WeightedGrammar; + +import java.io.File; + +import java.util.Scanner; + +public class GrammarServer { + private Scanner scn; + + private IMap> loadedGrammars; + private IMap> exportedRules; + + private GrammarServerEngine eng; + + public GrammarServer(Scanner scn) { + this.scn = scn; + + this.loadedGrammars = new FunctionalMap<>(); + this.exportedRules = new FunctionalMap<>(); + + eng = new GrammarServerEngine(loadedGrammars, exportedRules); + + ServerGrammarReader.setExportedRules(exportedRules); + } + + public static void main(String[] args) { + System.out.println("GrammarServer 1.0"); + + Scanner scn = new Scanner(System.in); + + GrammarServer serv = new GrammarServer(scn); + + CLIArgsParser.parseArgs(args, serv.eng); + + System.out.print("Enter a command (m for help): "); + + char comm = scn.nextLine().charAt(0); + + while(comm != 'e') { + switch(comm) { + case 'm': + System.out.println("GrammarServer Commands:"); + System.out.println("\tm: Print command help"); + System.out.println("\te: Exit GrammarServer"); + System.out.println("\tl: Load from file"); + System.out.println("\ts: Show information"); + System.out.println("\tg: Generate text"); + break; + case 'g': + serv.generateMode(); + break; + case 's': + serv.showMode(); + break; + case 'l': + serv.loadMode(); + break; + default: + System.out.println("? Unrecognized Command"); + } + + System.out.print("Enter a command (m for help): "); + + comm = scn.nextLine().charAt(0); + } + + System.out.println("GrammarServer exiting"); + } + + + + private void loadMode() { + System.out.println("Entering Load Mode"); + + System.out.print("(Load Mode) Enter a command (m for help): "); + char comm = scn.nextLine().charAt(0); + + while(comm != 'e') { + switch(comm) { + case 'm': + System.out.println("GrammarServer Load Mode Commands"); + System.out.println("\tm: Show command help"); + System.out.println("\te: Exit Load Mode"); + System.out.println("\tg: Load grammar from a file"); + System.out.println("\tl: Load long rule from a file"); + System.out.println("\tc: Load configuration from a file"); + break; + case 'g': + loadGrammar(); + break; + case 'c': + loadConfig(); + break; + case 'l': + loadLongRule(); + break; + default: + System.out.println("? Unrecognized Command"); + } + + System.out.print("(Load Mode) Enter a command (m for help): "); + comm = scn.nextLine().charAt(0); + } + + System.out.println("Exiting Load Mode"); + } + + private void loadGrammar() { + System.out.print("Enter path to load grammar from: "); + + String grammarPath = scn.nextLine().trim(); + + File grammarFile = new File(grammarPath); + + String grammarName = grammarFile.getName().trim(); + + grammarName = grammarName.substring(0, grammarName.lastIndexOf(".")); + + System.out.printf("Enter grammar name or press enter for" + + " the default (%s): ", grammarName); + + String inputName = scn.nextLine(); + + if(!inputName.equals("")) { + grammarName = inputName; + } + + eng.doLoadGrammar(grammarName, grammarPath); + + return; + } + + private void loadLongRule() { + System.out.print("Enter the file to load a long rule from: "); + + String fileName = scn.nextLine().trim(); + File ruleFile = new File(fileName); + + String tempName = ruleFile.getName(); + tempName = tempName.substring(0, tempName.lastIndexOf('.')); + + System.out.printf("Enter the name for the long rule (default %s): ", tempName); + + String ruleName = scn.nextLine().trim(); + + if(ruleName.equals("")) { + ruleName = tempName; + } + + eng.doLoadLongRule(ruleName, fileName); + } + + private void loadConfig() { + System.out.print("Enter the file to load configuration from: "); + + String fileName = scn.nextLine().trim(); + + eng.doLoadConfig(fileName); + } + + private void showMode() { + System.out.println("Entering Show Mode"); + + System.out.print("(Show Mode) Enter a command (m for help): "); + + char comm = scn.nextLine().charAt(0); + + while(comm != 'e') { + switch(comm) { + case 'm': + System.out.println("GrammarServer Show Mode Commands: "); + System.out.println("\tm: Show command help"); + System.out.println("\tl: Show loaded grammars"); + System.out.println("\tr: Show rules from a grammar"); + System.out.println("\tx: Show exported rules"); + System.out.println("\te: Exit Show Mode"); + break; + case 'r': + showGrammarRules(); + break; + case 'x': + eng.doShowExportedRules(); + break; + case 'l': + eng.doShowLoadedGrammars(); + break; + default: + System.out.println("? Unrecognized command"); + break; + } + + System.out.print("(Show Mode) Enter a command (m for help): "); + + comm = scn.nextLine().charAt(0); + } + + + + System.out.println("Exiting Show Mode"); + } + + private void generateMode() { + System.out.println("Entering Generate Mode"); + + System.out.print("(Generate Mode) Enter a command (m for help): "); + + char comm = scn.nextLine().charAt(0); + + while(comm != 'e') { + switch(comm) { + case 'm': + System.out.println("GrammarServer Generate Mode Commands: "); + System.out.println("\tm: Show command help"); + System.out.println("\tx: Generate from exported rules"); + System.out.println("\tr: Generate from a grammar"); + System.out.println("\te: Exit Generate Mode"); + break; + case 'x': + generateExportedRule(); + break; + case 'r': + generateGrammar(); + break; + default: + System.out.println("? Unrecognized command"); + } + + System.out.print("(Generate Mode) Enter a command (m for help): "); + + comm = scn.nextLine().charAt(0); + } + + System.out.println("Exiting Generate Mode"); + } + + private void generateExportedRule() { + System.out.print("Enter the name of the rule to generate" + + " (l to list, enter to cancel): "); + + String ruleName = scn.nextLine().trim(); + + while(true) { + if(ruleName.equals("")) break; + + if(ruleName.equals("l")) { + eng.doShowExportedRules(); + } else if (exportedRules.containsKey(ruleName)) { + eng.doGenerateExportedRule(ruleName); + + System.out.print("Generate again from this rule? (yes/no) (yes by default): "); + + String resp = scn.nextLine().trim(); + + if(resp.equalsIgnoreCase("yes") || resp.equals("")) { + continue; + } + } else { + System.out.println("? Unrecognized external rule"); + } + + System.out.print("Enter the name of the rule to generate" + + " (l to list, enter to cancel): "); + + ruleName = scn.nextLine().trim(); + } + } + + private void generateGrammar() { + System.out.print("Enter the name of the grammar to generate from (l to list, enter to cancel): "); + + String grammarName = scn.nextLine().trim(); + + while(true) { + if(grammarName.equals("")) break; + + if(grammarName.equals("l")) { + eng.doShowLoadedGrammars(); + } else if(loadedGrammars.containsKey(grammarName)) { + WeightedGrammar currentGram = loadedGrammars.get(grammarName); + + System.out.print("Enter the name of the rule to generate" + + " (l to list, enter to cancel): "); + + String ruleName = scn.nextLine().trim(); + + while(true) { + if(ruleName.equals("")) break; + + if(ruleName.equals("l")) { + eng.doShowGrammarRules(grammarName); + } else if (currentGram.hasRule(ruleName)) { + eng.doGenerateGrammar(currentGram, ruleName); + + System.out.print("Generate again from this rule? (yes/no) (yes by default): "); + + String resp = scn.nextLine().trim(); + + if(resp.equalsIgnoreCase("yes") || resp.equals("")) { + continue; + } + } else { + System.out.println("? Unrecognized grammar rule"); + } + + System.out.print("Enter the name of the rule to generate" + + " (l to list, enter to cancel): "); + + ruleName = scn.nextLine().trim(); + } + + } else { + System.out.println("? Unrecognized grammar name"); + } + + System.out.print("Enter the name of the grammar to generate from " + + "(l to list, enter to cancel): "); + + grammarName = scn.nextLine().trim(); + } + } + + private void showGrammarRules() { + System.out.print("Enter the name of the grammar (l to list): "); + String gramName = scn.nextLine().trim(); + + do { + if(gramName.equals("")) break; + + if(gramName.equals("l")) { + eng.doShowLoadedGrammars(); + } else if (loadedGrammars.containsKey(gramName)) { + eng.doShowGrammarRules(gramName); + break; + } else { + System.out.println("? Unrecognized grammar name"); + } + + System.out.print("Enter the name of the grammar (l to list): "); + gramName = scn.nextLine().trim(); + } while(true); + } +} diff --git a/RGens/src/main/java/bjc/rgens/server/GrammarServerEngine.java b/RGens/src/main/java/bjc/rgens/server/GrammarServerEngine.java new file mode 100644 index 0000000..2f608ec --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/server/GrammarServerEngine.java @@ -0,0 +1,300 @@ +package bjc.rgens.server; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Scanner; + +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.IList; +import bjc.utils.funcdata.IMap; +import bjc.utils.funcutils.ListUtils; +import bjc.utils.gen.WeightedGrammar; + +public class GrammarServerEngine { + private IMap> loadedGrammars; + private IMap> exportedRules; + + public static boolean debugMode = false; + + public GrammarServerEngine(IMap> loadedGrammars, + IMap> exportedRules) { + this.loadedGrammars = loadedGrammars; + this.exportedRules = exportedRules; + } + + public String getInitialRule(String grammarName) { + return loadedGrammars.get(grammarName).getInitialRule(); + } + + public boolean hasInitialRule(String grammarName) { + return loadedGrammars.get(grammarName).hasInitialRule(); + } + + public boolean hasExportedRule(String ruleName) { + return exportedRules.containsKey(ruleName); + } + + public boolean hasLoadedGrammar(String grammarName) { + return loadedGrammars.containsKey(grammarName); + } + + public void doLoadConfig(String fileName) { + File inputFile = new File(fileName); + + try(FileInputStream inputStream = new FileInputStream(inputFile)) { + try(Scanner fle = new Scanner(inputStream)) { + while(fle.hasNextLine()) { + String line = fle.nextLine().trim(); + + // Handle comments + if(line.equals("") || + line.startsWith("#") || + line.startsWith("//")) { + continue; + } + + // Handle mixed whitespace in input + line = line.replaceAll("\\s+", " "); + + String path; + String name; + + if(line.lastIndexOf(' ') != -1) { + path = line.substring(0, line.lastIndexOf(' ')); + name = line.substring(line.lastIndexOf(' ') + 1, line.length()); + } else { + path = line; + + File pathFile = new File(path); + String pathName = pathFile.getName(); + + if(pathFile.isDirectory()) { + // Load all the files in the directory recursively + Queue entries = new LinkedList<>(); + + for (File entry : pathFile.listFiles()) { + entries.add(entry); + } + + while(!entries.isEmpty()) { + File entry = entries.poll(); + + String entryPath = entry.getName(); + + if(entry.isHidden()) continue; + if(entry.isDirectory()) { + for (File newEntry : entry.listFiles()) { + entries.add(newEntry); + } + + continue; + } + + name = entryPath.substring(0, entryPath.lastIndexOf('.')); + + doLoadGrammarEntry(entry.toString(), name); + } + + continue; + } + + name = pathName.substring(0, pathName.lastIndexOf('.')); + } + + doLoadGrammarEntry(path, name); + } + } + } catch(IOException ioex) { + System.out.printf("? Error reading configuration from file" + + " (reason: %s)\n", ioex.getMessage()); + } + } + + private void doLoadGrammarEntry(String path, String name) { + if(path.endsWith(".gram")) { + doLoadGrammar(name, path); + } else if(path.endsWith(".template")) { + System.out.println("Error: Templates are not supported yet"); + } else if(path.endsWith(".long")) { + doLoadLongRule(name, path); + } else { + System.out.println("Error: Unknown filetype " + + path.substring(path.lastIndexOf("."), path.length())); + } + } + + public void doLoadLongRule(String ruleName, String ruleFile) { + ruleName = "[" + ruleName + "]"; + + if(debugMode) { + System.out.printf("Loading long rule (named %s) from path %s\n", + ruleName, ruleFile); + } + + try (FileInputStream inputStream = new FileInputStream(ruleFile)) { + try (Scanner fle = new Scanner(inputStream)) { + IList> ruleParts = new FunctionalList<>(); + + while(fle.hasNextLine()) { + ruleParts.add(new FunctionalList<>(fle.nextLine().trim().split(" "))); + } + + WeightedGrammar longGram = new WeightedGrammar<>(); + + longGram.addSpecialRule(ruleName, () -> ruleParts.randItem()); + longGram.setInitialRule(ruleName); + + exportedRules.put(ruleName, longGram); + + if(debugMode) { + System.out.printf("Loaded long rule (named %s) from path %s\n", + ruleName, ruleFile); + } + } + } catch (IOException ioex) { + System.out.printf("Error reading long rule (%s)\n", ioex.getMessage()); + } + } + + public void doLoadGrammar(String grammarName, String grammarPath) { + if(debugMode) { + System.out.printf("Loading grammar (named %s) from path %s\n", + grammarName, grammarPath); + } + + try (FileInputStream inputStream = new FileInputStream(grammarPath)) { + WeightedGrammar newGram = + ServerGrammarReader.fromStream(inputStream).merge((gram, exports) -> { + for(String export : exports.toIterable()) { + if(debugMode) { + System.out.printf("\tLoaded exported rule %s from grammar %s\n", + export, grammarName); + + if(exportedRules.containsKey(export)) { + System.out.printf("\tWarning: Exported rule %s from grammar %s" + + " shadows a pre-existing rule\n", export, grammarName); + } + } + + exportedRules.put(export, gram); + } + + return gram; + }); + + loadedGrammars.put(grammarName, newGram); + } catch (IOException ioex) { + System.out.printf("? Error reading grammar from file" + + " (reason: %s)\n", ioex.getMessage()); + } + + if(debugMode) { + System.out.printf("Loaded grammar (named %s) from path %s\n", + grammarName, grammarPath); + } + } + + public void doGenerateExportedRule(String ruleName) { + String ruleResult = ListUtils.collapseTokens( + exportedRules.get(ruleName) + .generateListValues(ruleName, " ")); + + System.out.println("Generated Result: "); + System.out.println("\t" + ruleResult.replaceAll("\\s+", " ")); + } + + public void doGenerateGrammar(String currentGram, String ruleName) { + doGenerateGrammar(loadedGrammars.get(currentGram), ruleName); + } + + public void doGenerateGrammar(WeightedGrammar currentGram, String ruleName) { + String ruleResult = ListUtils.collapseTokens( + currentGram.generateListValues(ruleName, " ")); + + System.out.println("Generated Result: "); + System.out.println("\t" + ruleResult.replaceAll("\\s+", " ")); + } + + public void doShowExportedRules() { + System.out.printf("Currently exported rules (%d total):\n", + exportedRules.getSize()); + + exportedRules.forEachKey(key -> { + System.out.println("\t" + key); + }); + } + + public void doShowGrammarRules(String gramName) { + WeightedGrammar gram = loadedGrammars.get(gramName); + + IList ruleNames = gram.getRuleNames(); + + System.out.printf("Rules for grammar %s (%d total)\n", + gramName, ruleNames.getSize()); + + ruleNames.forEach(rule -> { + System.out.println("\t" + rule); + }); + } + + public void doShowLoadedGrammars() { + System.out.printf("Currently loaded grammars (%d total):\n", + loadedGrammars.getSize()); + + loadedGrammars.forEachKey(key -> { + System.out.println("\t" + key); + }); + } + + public void doStressTest(int count) { + exportedRules.forEachKey(key -> { + doStressTest(key, count); + }); + } + + public void doStressTest(String ruleName, int count) { + doStressTest(exportedRules.get(ruleName), ruleName, count); + } + + public void doStressTest(WeightedGrammar gram, String ruleName, int count) { + if(debugMode) System.out.println("Stress-testing rule " + ruleName); + + IList res = new FunctionalList<>(); + IList foundTags = new FunctionalList<>(); + + boolean foundBroken = false; + + for(int i = 0; i < count; i++) { + res = gram.generateListValues(ruleName, " "); + + for(String tok : res.toIterable()) { + if(tok.matches("\\[\\S+\\]") && !foundTags.contains(tok)) { + System.out.println("\tWarning: Possible un-expanded rule " + tok + " found" + + " in expansion of " + ruleName); + + doFindRule(tok); + + foundBroken = true; + + foundTags.add(tok); + } + } + } + + if(debugMode) { + if(!foundBroken) System.out.printf("Rule %s succesfully passed stress-testing\n", ruleName); + else System.out.printf("Rule %s failed stress-testing\n", ruleName); + } + } + + private void doFindRule(String ruleName) { + loadedGrammars.forEach((gramName, gram) -> { + if(gram.hasRule(ruleName)) { + System.out.printf("\t\tFound rule %s in grammar %s\n", ruleName, gramName); + } + }); + } +} diff --git a/RGens/src/main/java/bjc/rgens/server/ReaderState.java b/RGens/src/main/java/bjc/rgens/server/ReaderState.java new file mode 100644 index 0000000..3f5021e --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/server/ReaderState.java @@ -0,0 +1,181 @@ +package bjc.rgens.server; + +import java.util.function.Supplier; + +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.IList; +import bjc.utils.gen.WeightedGrammar; + +/** + * Represents the internal state of reader + * + * @author ben + * + */ +public class ReaderState { + private WeightedGrammar currentGrammar; + private String currentRule; + private boolean isUniform; + + private IList exports; + + /** + * Create a new reader state + */ + public ReaderState() { + currentGrammar = new WeightedGrammar<>(); + + // Grammars start out uniform + isUniform = true; + + exports = new FunctionalList<>(); + } + + public void addExport(String export) { + exports.add(export); + } + + public IList getExports() { + return exports; + } + + /** + * Get the rule names for the current grammar + * + * @return The rule names for the current grammar + */ + public IList getRuleNames() { + return currentGrammar.getRuleNames(); + } + + /** + * Check if this reader is currently in uniform mode + * + * @return Whether this grammar is in uniform mode + */ + public boolean isUniform() { + return isUniform; + } + + /** + * Set the current grammar to be the specified one + * + * @param newWorkingGrammar + * The new grammar to use + */ + public void setCurrentGrammar(WeightedGrammar newWorkingGrammar) { + currentGrammar = newWorkingGrammar; + } + + /** + * Set the rule currently being worked on + * + * @param ruleName + * The rule currently being worked on + */ + public void setCurrentRule(String ruleName) { + currentRule = ruleName; + } + + /** + * Set the initial rule of this grammar + * + * @param ruleName + * The initial rule of this grammar + */ + public void setInitialRule(String ruleName) { + currentGrammar.setInitialRule(ruleName); + } + + /** + * Toggle this uniformity setting for this grammar + */ + public void toggleUniformity() { + isUniform = !isUniform; + } + + /** + * Add a case to the current grammar + * + * @param ruleProbability + * The probability for this case to occur + * @param ruleParts + * The parts that make up this case + */ + public void addCase(int ruleProbability, IList ruleParts) { + currentGrammar.addCase(currentRule, ruleProbability, ruleParts); + } + + /** + * Add a special rule to the grammar + * + * @param ruleName The name of the special rule + * @param cse The special case for the rule + */ + public void addSpecialRule(String ruleName, Supplier> cse) { + currentGrammar.addSpecialRule(ruleName, cse); + } + + /** + * Start editing a new rule in the current grammar + * + * @param ruleName + * The name of the new rule to edit + */ + public void startNewRule(String ruleName) { + currentGrammar.addRule(ruleName); + + currentRule = ruleName; + } + + /** + * Convert this package of state into a weighted grammar + * + * @return The grammar represented by this state + */ + public WeightedGrammar getGrammar() { + return currentGrammar; + } + + /** + * Prefix a token onto all of the cases for the specified rule + * + * @param ruleName + * The rule to do prefixing on + * @param prefixToken + * The token to prefix onto each case + * @param additionalProbability + * The probability modification of the prefixed cases + */ + public void prefixRule(String ruleName, String prefixToken, + int additionalProbability) { + currentGrammar.prefixRule(ruleName, prefixToken, + additionalProbability); + } + + /** + * Delete a rule from the current grammar + * + * @param ruleName + * The name of the rule to delete + */ + public void deleteRule(String ruleName) { + currentGrammar.deleteRule(ruleName); + } + + /** + * Suffix a token onto all of the cases for the specified rule + * + * @param ruleName + * The rule to do suffixing on + * @param suffixToken + * The token to suffix onto each case + * @param additionalProbability + * The probability modification of the suffixed cases + */ + public void suffixRule(String ruleName, String suffixToken, + int additionalProbability) { + currentGrammar.suffixRule(ruleName, suffixToken, + additionalProbability); + } +} diff --git a/RGens/src/main/java/bjc/rgens/server/ServerGrammarReader.java b/RGens/src/main/java/bjc/rgens/server/ServerGrammarReader.java new file mode 100644 index 0000000..77b1e8b --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/server/ServerGrammarReader.java @@ -0,0 +1,326 @@ +package bjc.rgens.server; + +import com.mifmif.common.regex.Generex; + +import java.io.InputStream; +import java.util.Random; +import java.util.function.BiFunction; +import java.util.function.Predicate; + +import bjc.utils.data.IPair; +import bjc.utils.data.Pair; +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; + +/** + * Read a grammar from a stream + * + * @author ben + * + */ +public class ServerGrammarReader { + static { + setupReader(); + + initPragmas(); + } + + private static RuleBasedConfigReader reader; + + private static Random numgen = new Random(); + + private static IMap> exportedRules; + + public static void setExportedRules(IMap> rules) { + exportedRules = rules; + } + + /** + * Read a grammar from a stream + * + * @param inputStream + * The stream to load the grammar from + * + * @return A grammar read from the stream + * + */ + public static IPair, IList> + fromStream(InputStream inputStream) { + ReaderState initialState = new ReaderState(); + + WeightedGrammar gram = reader.fromStream(inputStream, initialState).getGrammar(); + + IMap> vars = new FunctionalMap<>(); + + Predicate specialPredicate = (strang) -> { + if(strang.matches("\\[\\S+\\]")) { + return true; + } + + return false; + }; + + BiFunction, IList> + specialAction = (strang, gramm) -> { + return handleSpecialRule(vars, strang, gramm); + }; + + gram.configureSpecial(specialPredicate, specialAction); + + IList exports = initialState.getExports(); + + if(gram.getInitialRule() != null && !exports.contains(gram.getInitialRule())) { + exports.add(gram.getInitialRule()); + } + + return new Pair<>(gram, exports); + } + + private static void initPragmas() { + reader.addPragma("debug", (tokenizer, state) -> { + debugGrammar(state); + }); + + reader.addPragma("uniform", (tokenizer, state) -> { + state.toggleUniformity(); + }); + + reader.addPragma("initial-rule", ServerGrammarReader::initialRule); + + reader.addPragma("remove-rule", ServerGrammarReader::removeRule); + + reader.addPragma("prefix-with", ServerGrammarReader::prefixRule); + reader.addPragma("suffix-with", ServerGrammarReader::suffixRule); + + reader.addPragma("regex-rule", ServerGrammarReader::handleRegexRule); + + reader.addPragma("range-rule", ServerGrammarReader::handleRangeRule); + + reader.addPragma("export-rule", (tokenizer, state) -> { + String ruleName = tokenizer.nextToken(); + + state.addExport(ruleName); + }); + } + + private static void setupReader() { + reader = new RuleBasedConfigReader<>(null, null, null); + + reader.setStartRule((tokenizer, stateTokenPair) -> { + stateTokenPair.doWith((initToken, state) -> { + state.startNewRule(initToken); + + doCase(tokenizer, state); + }); + }); + + reader.setContinueRule((tokenizer, state) -> { + doCase(tokenizer, state); + }); + + reader.setEndRule((tokenizer) -> { + tokenizer.setCurrentRule(null); + }); + } + + private static void debugGrammar(ReaderState state) { + System.out.println("Printing rule names: "); + + for (String currentRule : state.getRuleNames().toIterable()) { + System.out.println("\t" + currentRule); + } + + System.out.println(); + } + + private static IList handleSpecialRule(IMap> vars, String strang, + WeightedGrammar gramm) { + IList retList = new FunctionalList<>(); + + if(strang.matches("\\[\\[\\S+\\]\\]")) { + if(strang.matches("\\[\\[\\S+:=\\S+\\]\\]")) { + doDefineExpandedVariable(vars, strang, gramm); + } else if(strang.matches("\\[\\[\\S+=\\S+\\]\\]")) { + doDefineVariable(vars, strang); + } else if(strang.matches("\\[\\[\\S+\\]\\]")) { + if(GrammarServerEngine.debugMode) { + if(strang.contains("+")) + System.out.println("Double-triggering no-space rule " + strang); + else + System.out.println("Triggered alternate no-space rule " + strang); + } + + doNoSpaceRule(strang, gramm, retList); + } else if (strang.contains("+")) { + if(GrammarServerEngine.debugMode) + System.out.println("Triggered alternate no-space rule " + strang); + + doNoSpaceRule(strang, gramm, retList); + } else { + // @FIXME notify the user they did something wrong + retList.add(strang); + } + } else { + if(strang.matches("\\[\\$\\S+\\-\\S+\\]")) { + retList = doExpandVariableReference(vars, strang, gramm); + } else if(strang.matches("\\[\\$\\S+\\]")) { + String varName = strang.substring(2, strang.length()); + + retList = vars.get(varName); + } else if (exportedRules.containsKey(strang) && + exportedRules.get(strang) != gramm && + !gramm.hasRule(strang)) { + // Only pick external rules if they are both + // a) in a different grammar + // b) not shadowed in the current grammar + WeightedGrammar exportGram = exportedRules.get(strang); + + retList = exportGram.generateGenericValues(strang, (s) -> s, " "); + } else if (strang.contains("+")) { + doNoSpaceRule(strang, gramm, retList); + } else { + // @FIXME notify the user they did something wrong + retList.add(strang); + } + } + + return retList; + } + + private static void handleRangeRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + + int start = Integer.parseInt(tokenizer.nextToken()); + int end = Integer.parseInt(tokenizer.nextToken()); + + state.addSpecialRule(ruleName, () -> { + int genNum = numgen.nextInt((end - start) + 1) + start; + + return new FunctionalList<>(Integer.toString(genNum)); + }); + } + + private static void handleRegexRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + + IList regx = tokenizer.toList(); + Generex regex = new Generex(ListUtils.collapseTokens(regx)); + + state.addSpecialRule(ruleName, () -> { + return new FunctionalList<>(regex.random().split(" ")); + }); + } + + private static int readOptionalProbability(FunctionalStringTokenizer tokenizer, ReaderState state) { + if (state.isUniform()) { + return 1; + } + + return Integer.parseInt(tokenizer.nextToken()); + } + + private static void initialRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String initialRuleName = tokenizer.nextToken(); + + state.setInitialRule(initialRuleName); + } + + private static void prefixRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + String prefixToken = tokenizer.nextToken(); + + int additionalProbability = readOptionalProbability(tokenizer, state); + + state.prefixRule(ruleName, prefixToken, additionalProbability); + } + + private static void removeRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + + state.deleteRule(ruleName); + } + + private static void suffixRule(FunctionalStringTokenizer tokenizer, ReaderState state) { + String ruleName = tokenizer.nextToken(); + String suffixToken = tokenizer.nextToken(); + + int additionalProbability = readOptionalProbability(tokenizer, state); + + state.suffixRule(ruleName, suffixToken, additionalProbability); + } + + private static void doCase(FunctionalStringTokenizer tokenizer, ReaderState state) { + int ruleProbability = readOptionalProbability(tokenizer, state); + + state.addCase(ruleProbability, tokenizer.toList()); + } + + private static void doDefineExpandedVariable(IMap> vars, String strang, WeightedGrammar gramm) { + String[] varParts = strang.split(":="); + + String varName = varParts[0].substring(2); + String ruleName = varParts[1].substring(0, varParts[1].length() - 2); + + IList varValue = gramm.generateGenericValues( + ruleName, (s) -> s, " "); + + vars.put(varName, varValue); + } + + private static void doDefineVariable(IMap> vars, String strang) { + String[] varParts = strang.split("="); + + String varName = varParts[0].substring(2); + String varValue = varParts[1].substring(0, varParts[1].length() - 2); + + vars.put(varName, new FunctionalList<>(varValue)); + } + + private static IList doExpandVariableReference(IMap> vars, String strang, + WeightedGrammar gramm) { + IList retList; + String[] varParts = strang.substring(1, strang.length()).split("-"); + + StringBuilder actualName = new StringBuilder("["); + + for(String varPart : varParts) { + if(varPart.startsWith("$")) { + IList 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); + + retList = gramm.generateGenericValues(actualName.toString(), (s) -> s, " "); + return retList; + } + + private static void doNoSpaceRule(String strang, WeightedGrammar gramm, IList retList) { + if(!GrammarServerEngine.debugMode) { + IList ruleValue = gramm.generateGenericValues( + strang, (s) -> s.trim(), ""); + + retList.add(ListUtils.collapseTokens(ruleValue)); + } else { + // if(!gramm.hasRule(strang)) + // System.out.println("Warning: Possible unexpanded rule " + strang); + + retList.add(strang); + } + } +} diff --git a/RGens/src/main/java/bjc/rgens/text/markov/Markov.java b/RGens/src/main/java/bjc/rgens/text/markov/Markov.java new file mode 100755 index 0000000..a07f44e --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/text/markov/Markov.java @@ -0,0 +1,189 @@ +package bjc.rgens.text.markov; + +import java.util.Map.Entry; +import java.util.*; + +/** + * Represents a k-character substring. Can give a pseudo-random suffix + * character based on probability. + * + * @author Daniel Friedman (Fall 2011) + * + */ +public class Markov { + String substring; + int count = 0; + + TreeMap map; + + /** + * Constructs a Markov object from a given substring. + * + * @param substring + * the given substring. + */ + public Markov(String substring) { + this.substring = substring; + + map = new TreeMap<>(); + + add(); + } + + /** + * Constructs a Markov object from a given substring and suffix + * character. Suffix characters are stored in a TreeMap. + * + * @param substring + * the specified substring. + * @param suffix + * the specified suffix. + */ + public Markov(String substring, Character suffix) { + this.substring = substring; + + map = new TreeMap<>(); + + add(suffix); + } + + /** + * Increments the count of number of times the substring appears in a + * text. + */ + public void add() { + count++; + } + + /** + * Adds a suffix character to the TreeMap. + * + * @param c + * the suffix character to be added. + */ + public void add(char c) { + add(); + + if (map.containsKey(c)) { + int frequency = map.get(c); + map.put(c, frequency + 1); + } else + map.put(c, 1); + } + + /** + * Gives the frequency count of a suffix character; that is, the number + * of times the specified suffix follows the substring in a text. + * + * @param c + * the specified suffix. + * @return the frequency count. + */ + public int getFrequencyCount(char c) { + if (!map.containsKey(c)) { + return -1; + } + + return map.get(c); + } + + /** + * Gives a percentage of frequency count / number of total suffixes. + * + * @param c + * @return the ratio of frequency count of a single character to the + * total number of suffixes + */ + public double getCharFrequency(char c) { + if (getFrequencyCount(c) == -1) { + return -1; + } + + return (double) getFrequencyCount(c) / (double) count; + } + + /** + * Finds whether or not the given suffix is in the TreeMap. + * + * @param c + * the given suffix. + * @return True if the suffix exists in the TreeMap, false otherwise. + */ + public boolean containsChar(char c) { + if (!map.containsKey(c)) { + return false; + } + + return true; + } + + /** + * Gives the number of times this substring occurs in a text. + * + * @return said number of times. + */ + public int count() { + return count; + } + + /** + * Gives the TreeMap. + * + * @return the TreeMap. + */ + public TreeMap getMap() { + return map; + } + + /** + * Using probability, returns a pseudo-random character to follow the + * substring. Character possibilities are added to an ArrayList + * (duplicates allowed), and a random number from 0 to the last index + * in the ArrayList is picked. Since more common suffixes occupy more + * indices in the ArrayList, the probability of getting a more common + * suffix is greater than the probability of getting a less common + * suffix. + * + * @return the pseudo-random suffix. + */ + public char random() { + Character ret = null; + + Set> s = map.entrySet(); + + Iterator> it = s.iterator(); + + ArrayList suffixes = new ArrayList<>(); + + while (it.hasNext()) { + Entry tmp = it.next(); + + for (int i = 0; i < tmp.getValue(); i++) { + suffixes.add(tmp.getKey()); + } + } + + Random rand = new Random(); + int retIndex = rand.nextInt(suffixes.size()); + ret = suffixes.get(retIndex); + return ret; + } + + /** + * Gives a String representation of the Markov object. + * + * @return said String representation. + */ + @Override + public String toString() { + String ret = "Substring: " + substring + ", Count: " + count; + ret += "\n" + "Suffixes and frequency counts: "; + + for (Entry entry : map.entrySet()) { + char key = entry.getKey(); + int value = entry.getValue(); + ret += "\n" + "Suffix: " + key + ", frequency count: " + value; + } + return ret; + } +} diff --git a/RGens/src/main/java/bjc/rgens/text/markov/StandaloneMarkov.java b/RGens/src/main/java/bjc/rgens/text/markov/StandaloneMarkov.java new file mode 100644 index 0000000..0edaaa8 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/text/markov/StandaloneMarkov.java @@ -0,0 +1,42 @@ +package bjc.rgens.text.markov; + +import java.util.Map; + +public class StandaloneMarkov { + private int k; + + private Map markovHash; + private String firstSub; + + public StandaloneMarkov(int k, Map markovHash, + String firstSub) { + this.k = k; + this.markovHash = markovHash; + this.firstSub = firstSub; + } + + public String generateTextFromMarkov(int M) { + StringBuilder text = new StringBuilder(); + for (int i = k; i < M; i++) { + if (i == k) { + text.append(firstSub); + + if (text.length() > k) + i = text.length(); + } + + String sub = text.substring((i - k), (i)); + Markov tmp = markovHash.get(sub); + + if (tmp != null) { + Character nextChar = tmp.random(); + text.append(nextChar); + } else { + i = k - 1; + } + } + + return text.toString(); + } + +} diff --git a/RGens/src/main/java/bjc/rgens/text/markov/StandaloneTextGenerator.java b/RGens/src/main/java/bjc/rgens/text/markov/StandaloneTextGenerator.java new file mode 100644 index 0000000..92bc653 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/text/markov/StandaloneTextGenerator.java @@ -0,0 +1,70 @@ +package bjc.rgens.text.markov; + +import java.io.IOException; +import java.io.Reader; +import java.util.HashMap; +import java.util.Map; + +public class StandaloneTextGenerator { + + /** + * Build a markov generator from a provided source + * + * @param k + * The markov order to use + * @param reader + * The source to seed the generator from + * @return The markov generator for the provided text + */ + public static StandaloneMarkov generateMarkovMap(int k, + Reader reader) { + Map hash = new HashMap<>(); + + Character next = null; + + try { + next = (char) reader.read(); + } catch (IOException e1) { + System.out + .println("IOException in stepping through the reader"); + e1.printStackTrace(); + System.exit(1); + } + + StringBuilder origFileBuffer = new StringBuilder(); + + while (next != null && Character.isDefined(next)) { + Character.toString(next); + origFileBuffer.append(next); + + try { + next = (char) reader.read(); + } catch (IOException e) { + System.out.println( + "IOException in stepping through the reader"); + e.printStackTrace(); + } + + } + + String origFile = origFileBuffer.toString(); + String firstSub = origFile.substring(0, k); + + for (int i = 0; i < origFile.length() - k; i++) { + String sub = origFile.substring(i, i + k); + Character suffix = origFile.charAt(i + k); + + if (hash.containsKey(sub)) { + Markov marvin = hash.get(sub); + marvin.add(suffix); + hash.put(sub, marvin); + } else { + Markov marvin = new Markov(sub, suffix); + hash.put(sub, marvin); + } + } + + return new StandaloneMarkov(k, hash, firstSub); + } + +} diff --git a/RGens/src/main/java/bjc/rgens/text/markov/TextGenerator.java b/RGens/src/main/java/bjc/rgens/text/markov/TextGenerator.java new file mode 100755 index 0000000..770acd9 --- /dev/null +++ b/RGens/src/main/java/bjc/rgens/text/markov/TextGenerator.java @@ -0,0 +1,69 @@ +package bjc.rgens.text.markov; + +import java.io.*; + +/** + * Generate text from a markov model of an input text + * + * @author ben + * + */ +public class TextGenerator { + /** + * @param args + * when used with three arguments, the first represents the + * k-order of the Markov objects. The second represents the + * number of characters to print out. The third represents + * the file to be read. + * + * When used with two arguments, the first represents the + * k-order of the Markov objects, and the second represents + * the file to be read. The generated text will be the same + * number of characters as the original file. + */ + public static void main(String[] args) { + int k = 0; + int M = 0; + + String file = ""; + StringBuilder text = new StringBuilder(); + + if (args.length == 3) { + k = Integer.parseInt(args[0]); + M = Integer.parseInt(args[1]); + file = args[2]; + } else if (args.length == 2) { + k = Integer.parseInt(args[0]); + file = args[1]; + } else { + System.out + .println("\n" + "Usage: java TextGenerator k M file"); + System.out.println( + "where k is the markov order, M is the number"); + System.out.println( + "of characters to be printed, and file is the"); + System.out.println( + "name of the file to print from. M may be left out." + + "\n"); + System.exit(1); + } + + StandaloneMarkov markov = null; + + try (FileReader reader = new FileReader(file)) { + markov = StandaloneTextGenerator.generateMarkovMap(k, + reader); + + System.out.println(markov.generateTextFromMarkov(M) + .substring(0, Math.min(M, text.length()))); + } catch (FileNotFoundException e) { + System.out.println("File not found."); + e.printStackTrace(); + System.exit(1); + } catch (IOException ioex) { + System.out.println("IOException"); + ioex.printStackTrace(); + System.exit(1); + } + } +} \ No newline at end of file -- cgit v1.2.3