diff options
| author | bjculkin <bjculkin@mix.wvu.edu> | 2017-03-21 14:04:17 -0400 |
|---|---|---|
| committer | bjculkin <bjculkin@mix.wvu.edu> | 2017-03-21 14:04:17 -0400 |
| commit | e279644fc59f46916c20b0b4f941fd37b4f07675 (patch) | |
| tree | 7782b229f6482039ad0739079807294c14928085 /RGens/src/main/java/bjc/rgens/newparser/RGrammar.java | |
| parent | ba7e0a2c1efe4203f766f3192b8852c3bb7d3369 (diff) | |
Finish basic implementation
This finishes a basic implementation. It now handles literal strings and
rule references, allowing it to handle basic grammars.
Diffstat (limited to 'RGens/src/main/java/bjc/rgens/newparser/RGrammar.java')
| -rw-r--r-- | RGens/src/main/java/bjc/rgens/newparser/RGrammar.java | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java b/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java index 64385e9..4adcbe8 100644 --- a/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java +++ b/RGens/src/main/java/bjc/rgens/newparser/RGrammar.java @@ -1,5 +1,8 @@ package bjc.rgens.newparser; +import java.util.List; +import java.util.Map; + /** * Represents a randomized grammar. * @@ -7,5 +10,152 @@ package bjc.rgens.newparser; * */ public class RGrammar { + private static class GenerationState { + public StringBuilder contents; + + public GenerationState(StringBuilder contents) { + this.contents = contents; + } + } + + private Map<String, Rule> rules; + + private Map<String, Rule> importRules; + + private String initialRule; + + /** + * Create a new randomized grammar using the specified set of rules. + * + * @param rules + * The rules to use. + */ + public RGrammar(Map<String, Rule> rules) { + this.rules = rules; + } + + /** + * Sets the imported rules to use. + * + * Imported rules are checked for rule definitions after local + * definitions are checked. + * + * @param importedRules + * The set of imported rules to use. + */ + public void setImportedRules(Map<String, Rule> importedRules) { + importRules = importedRules; + } + + /** + * Generate a string from this grammar, starting from the specified + * rule. + * + * @param startRule + * The rule to start generating at, or null to use the + * initial rule for this grammar. + * + * @return A possible string from the grammar. + */ + public String generate(String startRule) { + String fromRule = startRule; + + if(startRule == null) { + if(initialRule == null) { + throw new GrammarException( + "Must specify a start rule for grammars with no initial rule"); + } else { + fromRule = initialRule; + } + } else { + if(startRule.equals("")) { + throw new GrammarException("The empty string is not a valid rule name"); + } + } + + RuleCase start = rules.get(fromRule).getCase(); + + StringBuilder contents = new StringBuilder(); + + generateCase(start, new GenerationState(contents)); + + return contents.toString(); + } + + /* + * Generate a rule case. + */ + private void generateCase(RuleCase start, GenerationState state) { + try { + switch(start.type) { + case NORMAL: + for(CaseElement elm : start.getElements()) { + generateElement(elm, state); + } + break; + default: + throw new GrammarException(String.format("Unknown case type '%s'", start.type)); + } + } catch(GrammarException gex) { + throw new GrammarException(String.format("Error in generating case (%s)", start), gex); + } + } + + /* + * Generate a case element. + */ + private void generateElement(CaseElement elm, GenerationState state) { + try { + switch(elm.type) { + case LITERAL: + state.contents.append(elm.getLiteral() + " "); + break; + case RULEREF: + if(rules.containsKey(elm.getLiteral())) { + RuleCase cse = rules.get(elm.getLiteral()).getCase(); + + generateCase(cse, state); + } else if(importRules.containsKey(elm.getLiteral())) { + RuleCase cse = importRules.get(elm.getLiteral()).getCase(); + + generateCase(cse, state); + } else { + throw new GrammarException( + String.format("No rule by name '%s' found", elm.getLiteral())); + } + break; + default: + throw new GrammarException(String.format("Unknown element type '%s'", elm.type)); + } + } catch(GrammarException gex) { + throw new GrammarException(String.format("Error in generating case element (%s)", elm), gex); + } + } + + /** + * Get the initial rule of this grammar. + * + * @return The initial rule of this grammar. + */ + public String getInitialRule() { + return initialRule; + } + + /** + * Set the initial rule of this grammar. + * + * @param initialRule + * The initial rule of this grammar, or null to say there + * is no initial rule. + */ + public void setInitialRule(String initialRule) { + if(initialRule.equals("")) { + throw new GrammarException("The empty string is not a valid rule name"); + } else if(!rules.containsKey(initialRule)) { + throw new GrammarException( + String.format("No rule named '%s' local to this grammar found.", initialRule)); + } + this.initialRule = initialRule; + } } |
