diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2018-05-29 18:02:46 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2018-05-29 18:02:46 -0300 |
| commit | faf3e39fee32226ee72c6d43b2ba8a0f4e4bd837 (patch) | |
| tree | 900bdc5a803c7ac0d616d9ceb09e2293a6bd84ce /src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java | |
| parent | 986870048e06fa0de2dd81d244a78c43cd2aa769 (diff) | |
Refactor case element generation
Case elements are now responsible for generating themselves.
Diffstat (limited to 'src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java')
| -rwxr-xr-x | src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java b/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java index f4d3512..d91bebc 100755 --- a/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java +++ b/src/main/java/bjc/rgens/parser/elements/RuleCaseElement.java @@ -1,7 +1,129 @@ package bjc.rgens.parser.elements; +import bjc.rgens.parser.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class RuleCaseElement extends StringCaseElement { + private static Pattern NAMEVAR_PATTERN = Pattern.compile("\\$(\\w+)"); + public RuleCaseElement(String vl) { super(vl, false); } + + @Override + public void generate(GenerationState state) { + /* + * @NOTE + * + * :VarRefactor + * + * Figure out if this can be refactored in some way. + */ + String refersTo = val; + + GenerationState newState = state.newBuf(); + + if (refersTo.contains("$")) { + /* Parse variables */ + String refBody = refersTo.substring(1, refersTo.length() - 1); + + if (refBody.contains("-")) { + /* Handle dependent rule names. */ + StringBuffer nameBuffer = new StringBuffer(); + + Matcher nameMatcher = NAMEVAR_PATTERN.matcher(refBody); + + while (nameMatcher.find()) { + String var = nameMatcher.group(1); + + if (!state.vars.containsKey(var)) { + String msg = String.format("No variable '%s' defined", var); + throw new GrammarException(msg); + } + + String name = state.vars.get(var); + + if (name.contains(" ")) { + throw new GrammarException("Variables substituted into names cannot contain spaces"); + } else if (name.equals("")) { + throw new GrammarException("Variables substituted into names cannot be empty"); + } + + nameMatcher.appendReplacement(nameBuffer, name); + } + + nameMatcher.appendTail(nameBuffer); + + refersTo = "[" + nameBuffer.toString() + "]"; + } else { + /* Handle string references. */ + if (refBody.equals("$")) { + throw new GrammarException("Cannot refer to unnamed variables"); + } + + String key = refBody.substring(1); + + if (!state.vars.containsKey(key)) { + String msg = String.format("No variable '%s' defined", key); + throw new GrammarException(msg); + } + + state.contents.append(state.vars.get(key)); + + return; + } + } + + if (refersTo.startsWith("[^")) { + refersTo = "[" + refersTo.substring(2); + + RGrammar dst = state.importRules.get(refersTo); + + newState.swapGrammar(dst); + + /* :Postprocessing */ + newState.contents = new StringBuilder(dst.generate(refersTo, state.rnd, state.vars)); + } else if (state.rules.containsKey(refersTo)) { + RuleCase cse = state.rules.get(refersTo).getCase(state.rnd); + + state.gram.generateCase(cse, newState); + } else if (state.importRules.containsKey(refersTo)) { + RGrammar dst = state.importRules.get(refersTo); + + newState.swapGrammar(dst); + + /* :Postprocessing */ + newState.contents = new StringBuilder(dst.generate(refersTo, state.rnd, state.vars)); + } else { + /* + * @TODO 5/29/18 Ben Culkin :RuleSuggesting + * + * Re-get this working again. + */ + /* + if (ruleSearcher != null) { + Set<Match<? extends String>> results = ruleSearcher.search(refersTo, MAX_DISTANCE); + + String[] resArray = results.stream().map(Match::getMatch).toArray((i) -> new String[i]); + + String msg = String.format("No rule '%s' defined (perhaps you meant %s?)", refersTo, + StringUtils.toEnglishList(resArray, false)); + + throw new GrammarException(msg); + } + */ + + String msg = String.format("No rule '%s' defined", refersTo); + throw new GrammarException(msg); + } + + if (refersTo.contains("+")) { + /* Rule names with pluses in them get space-flattened */ + state.contents.append(newState.contents.toString().replaceAll("\\s+", "")); + } else { + state.contents.append(newState.contents.toString()); + } + } } |
