From a13f1f396d28c0b900a10bede57f30be3a35003a Mon Sep 17 00:00:00 2001 From: "Benjamin J. Culkin" Date: Sun, 3 Jun 2018 19:27:43 -0300 Subject: Enable multi-prefixing/suffixing You can now provide multiple prefix/suffix elements, and all of the permutations of them will be applied. For example, providing the elements A & B, will yield the following permutations * A * B * A B * B A --- .../java/bjc/rgens/parser/RGrammarBuilder.java | 107 +++++++++++++++++---- 1 file changed, 88 insertions(+), 19 deletions(-) (limited to 'src/main/java/bjc/rgens/parser/RGrammarBuilder.java') diff --git a/src/main/java/bjc/rgens/parser/RGrammarBuilder.java b/src/main/java/bjc/rgens/parser/RGrammarBuilder.java index fc679f1..3aa220a 100755 --- a/src/main/java/bjc/rgens/parser/RGrammarBuilder.java +++ b/src/main/java/bjc/rgens/parser/RGrammarBuilder.java @@ -3,11 +3,16 @@ package bjc.rgens.parser; import bjc.rgens.parser.elements.CaseElement; import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.IList; +import bjc.utils.funcutils.ListUtils; +import bjc.utils.funcutils.SetUtils; import static bjc.rgens.parser.RuleCase.CaseType.*; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.LinkedList; import java.util.Map; import java.util.Set; @@ -136,7 +141,7 @@ public class RGrammarBuilder { * If the rule name is either invalid or not defined by this * grammar, or if the suffix is invalid. */ - public void suffixWith(String ruleName, String suffix) { + public void suffixWith(String ruleName, String... suffixes) { if (ruleName == null) { throw new NullPointerException("Rule name must not be null"); } else if (ruleName.equals("")) { @@ -147,19 +152,27 @@ public class RGrammarBuilder { throw new IllegalArgumentException(msg); } - CaseElement element = CaseElement.createElement(suffix); + Set elements = new HashSet<>(suffixes.length); + for(String suffix : suffixes) { + elements.add(CaseElement.createElement(suffix)); + } + + List> suffixLists = powerList(elements); FunctionalList newCases = new FunctionalList<>(); IList caseList = rules.get(ruleName).getCases(); for (RuleCase ruleCase : caseList) { + for(List suffixList : suffixLists) { FunctionalList newCase = new FunctionalList<>(); for(CaseElement elm : ruleCase.getElements()) { newCase.add(elm); } - newCase.add(element); + for(CaseElement element : suffixList) { + newCase.add(element); + } /* * @NOTE :AffixCasing @@ -168,6 +181,7 @@ public class RGrammarBuilder { * existing case type? */ newCases.add(new NormalRuleCase(newCase)); + } } @@ -189,7 +203,7 @@ public class RGrammarBuilder { * If the rule name is either invalid or not defined by this * grammar, or if the prefix is invalid. */ - public void prefixWith(String ruleName, String prefix) { + public void prefixWith(String ruleName, String... prefixes) { if (ruleName == null) { throw new NullPointerException("Rule name must not be null"); } else if (ruleName.equals("")) { @@ -200,27 +214,36 @@ public class RGrammarBuilder { throw new IllegalArgumentException(msg); } - CaseElement element = CaseElement.createElement(prefix); + Set elements = new HashSet<>(prefixes.length); + for(String prefix : prefixes) { + elements.add(CaseElement.createElement(prefix)); + } + + List> prefixLists = powerList(elements); FunctionalList newCases = new FunctionalList<>(); IList caseList = rules.get(ruleName).getCases(); for (RuleCase ruleCase : caseList) { - FunctionalList newCase = new FunctionalList<>(); - - newCase.add(element); - - for(CaseElement elm : ruleCase.getElements()) { - newCase.add(elm); + for(List prefixList : prefixLists) { + FunctionalList newCase = new FunctionalList<>(); + + for(CaseElement elm: prefixList) { + newCase.add(elm); + } + + for(CaseElement elm : ruleCase.getElements()) { + newCase.add(elm); + } + + /* + * @NOTE :AffixCasing + * + * Is this correct, or should we be mirroring the + * existing case type? + */ + newCases.add(new NormalRuleCase(newCase)); } - - /* - * @NOTE :AffixCasing - * - * Is this correct, or should we be mirroring the - * existing case type? - */ - newCases.add(new NormalRuleCase(newCase)); } @@ -269,6 +292,52 @@ public class RGrammarBuilder { } rules.get(rule).replaceCases(newCaseList); + } + + private static List> powerList(Set elements) { + /* + * Fast-case the most common usage + */ + if(elements.size() == 1) { + List> ret = new LinkedList<>(); + + List curr = new ArrayList<>(elements.size()); + for(T elem : elements) { + curr.add(elem); + } + + ret.add(curr); + + return ret; + } + + Set> powerSet = SetUtils.powerSet(elements); + + List> list = new LinkedList<>(); + + for(Set set : powerSet) { + /* + * Skip empty sets + */ + if(set.size() == 0) continue; + + List stor = new ArrayList<>(set.size()); + + for(T elm : set) { + stor.add(elm); + } + + for(List permute : ListUtils.permuteList(stor)) { + System.err.printf("\tTRACE: generated permute "); + for(T elm : permute) { + System.err.printf("%s ", elm); + } + System.err.println(); + + list.add(permute); + } + } + return list; } } -- cgit v1.2.3