diff --git a/src/main/java/code_generation/BasicCodeGenerator.java b/src/main/java/code_generation/BasicCodeGenerator.java index 9234f1b..fa3256d 100644 --- a/src/main/java/code_generation/BasicCodeGenerator.java +++ b/src/main/java/code_generation/BasicCodeGenerator.java @@ -12,9 +12,9 @@ public class BasicCodeGenerator implements CodeGenerator { protected String postGeneration; public BasicCodeGenerator(RuleConvertor ruleConvertor) { - this.ruleConvertor = ruleConvertor.getConversions(); + this.ruleConvertor = ruleConvertor.conversions(); - NullableTuple bookends = ruleConvertor.getBookends(); + NullableTuple bookends = ruleConvertor.bookends(); this.preGeneration = bookends.value1(); this.postGeneration = bookends.value2(); @@ -150,17 +150,16 @@ public int getElementsGenerated() { @Override public String toString() { - String string = ""; + String string = "parseState: "; - string += "parseState: "; if(parseState == null) { string += null; } else { string += parseState.toString(); } - string += "\n"; + string += "\n"; string += "elementsGenerated: " + elementsGenerated; return string; diff --git a/src/main/java/component_construction/builders/CompilerBuilder.java b/src/main/java/component_construction/builders/CompilerBuilder.java index 27c1f70..2a11c63 100644 --- a/src/main/java/component_construction/builders/CompilerBuilder.java +++ b/src/main/java/component_construction/builders/CompilerBuilder.java @@ -174,7 +174,6 @@ private void checkForCompleteBuild() { //Note: Allowing null lexical components if(msgParts.size() == 0) return; //No error - if(msgParts.size() == 1) throw new ParameterError(msgParts.get(0) + " not provided"); String msg = msgParts.get(0); diff --git a/src/main/java/component_construction/builders/grammar_objects/GrammarBuilder.java b/src/main/java/component_construction/builders/grammar_objects/GrammarBuilder.java new file mode 100644 index 0000000..11f655c --- /dev/null +++ b/src/main/java/component_construction/builders/grammar_objects/GrammarBuilder.java @@ -0,0 +1,95 @@ +package component_construction.builders.grammar_objects; + +import java.util.*; +import grammar_objects.*; + +public class GrammarBuilder { + + protected Set tokens = new HashSet<>(); + protected Set nonTerminals = new HashSet<>(); + protected List productionRules = new ArrayList<>(); + protected NonTerminal sentinal; + + /** + * Sets up the sentinal for the grammar being built + * @param sentinal The sentinal non-terminal + * @return This builder for method chaining + */ + public GrammarBuilder setSentinal(NonTerminal sentinal) { + this.sentinal = sentinal; + return this; + } + + /** + * Adds a production rule for the grammar being built + * @param productionRule The production rule + * @return This builder for method chaining + */ + public GrammarBuilder addRule(ProductionRule productionRule) { + addTokens(productionRule); + productionRules.add(productionRule); + return this; + } + + /** + * Adds a production rule for the grammar being built + * @param nonTerminal The NonTerminal for the rule + * @param elements In-order elements for the rule + * @return This builder for method chaining + */ + public GrammarBuilder addRule(NonTerminal nonTerminal, LexicalElement[] elements) { + return addRule(new ProductionRule(nonTerminal, elements)); + } + + /** + * Adds a production rule for the grammar being built + * @param nonTerminalName The name of the NonTerminal for this rule + * @param elements In-order elements for this rule + * @return This builder for method chaining + */ + public GrammarBuilder addRule(String nonTerminalName, LexicalElement[] elements) { + return addRule(new NonTerminal(nonTerminalName), elements); + } + + /** + * Adds a collection of production rules to the grammar being built + * @param rules The collection of rules + * @return This builder for method chaining + */ + public GrammarBuilder addRules(Collection rules) { + for (ProductionRule productionRule : rules) { + addRule(productionRule); + } + + return this; + } + + /** + * Produces the grammar built through this builder + * @return The grammar that was built + */ + public Grammar produceGrammar() { + if (sentinal == null) throw new MissingSentinalException(); + return new Grammar(tokens, nonTerminals, productionRules, sentinal); + } + + + private void addTokens(ProductionRule productionRule) { + nonTerminals.add(productionRule.nonTerminal()); + + for (LexicalElement element : productionRule.productionSequence()) { + if (element instanceof Token) { tokens.add((Token)element); } + else if (element instanceof NonTerminal) { nonTerminals.add((NonTerminal)element); } + } + } + + + public class MissingSentinalException extends RuntimeException { + + public MissingSentinalException() { + super("Sentinal not defined"); + } + + } + +} diff --git a/src/main/java/component_construction/builders/grammar_objects/RuleConvertorBuilder.java b/src/main/java/component_construction/builders/grammar_objects/RuleConvertorBuilder.java new file mode 100644 index 0000000..cb661d8 --- /dev/null +++ b/src/main/java/component_construction/builders/grammar_objects/RuleConvertorBuilder.java @@ -0,0 +1,171 @@ +package component_construction.builders.grammar_objects; + +import java.util.*; +import java.util.Map.Entry; + +import code_generation.Generator; +import grammar_objects.*; +import helper_objects.NullableTuple; + +public class RuleConvertorBuilder { + + protected Grammar grammar; + protected Map conversions = new HashMap<>(); + protected NullableTuple bookends = null; + protected Generator defaultConversion = null; + + public RuleConvertorBuilder(Grammar grammar) { + this.grammar = grammar; + } + + public RuleConvertor produceConvertor() { + if (defaultConversion != null) + populateDefaultConversions(); + + return new RuleConvertor(grammar, conversions, bookends); + } + + /** + * Sets the constant strings which will bookend produced generations + * @param bookends The strings to bookend produced generations + * @return This builder to allow method chaining + */ + public RuleConvertorBuilder setBookends(NullableTuple bookends) { + this.bookends = bookends; + return this; + } + + /** + * Sets the constant strings which will bookend produced generations + * @param startBookend The constant starting string + * @param endBookend The constant ending string + * @return This builder to allow method chaining + */ + public RuleConvertorBuilder setBookends(String startBookend, String endBookend) { + this.bookends = new NullableTuple<>(startBookend, endBookend); + return this; + } + + /** + * Enables default conversions for each grammar rule + * The default conversion will concatenate the generations of each element within each rule + * @return This builder to allow method chaining + */ + public RuleConvertorBuilder enableDefaultConversions() { + this.defaultConversion = (elements) -> Arrays + .stream(elements) + .map((element) -> element.getGeneration().toString()) + .reduce("", (subtotal, current) -> subtotal + current); + + return this; + } + + /** + * Enables default conversions for each grammar rule using the specified generator + * @param defaultGeneratorFunction The default generator to convert each grammar rule with + * @return This builder to allow method chaining + */ + public RuleConvertorBuilder enableDefaultConversions(Generator defaultGeneratorFunction) { + this.defaultConversion = defaultGeneratorFunction; + return this; + } + + /** + * Sets the conversion function for the additional root rule of the grammar + * @param generatorFunction The conversion/generator function to be used + * @return This builder to allow method chaining + */ + public RuleConvertorBuilder setRootConversion(Generator generatorFunction) { + this.conversions.put(RuleConvertor.ROOT_RULE, generatorFunction); + return this; + } + + /** + * Sets the conversion function for the specified grammar rule + * @param rule The grammar rule the conversion will be applied for + * @param generatorFunction The conversion/generator function to be used + * @return This builder to allow method chaining + */ + public RuleConvertorBuilder setConversion(ProductionRule rule, Generator generatorFunction) { + this.conversions.put(rule, generatorFunction); + return this; + } + + /** + * Sets the conversion function for the specified grammar rule + * @param ruleNumber The index of the grammar rule the conversion will be applied for + * @param generatorFunction The conversion/generator function to be used + * @return This builder to allow method chaining + */ + public RuleConvertorBuilder setConversion(int ruleNumber, Generator generatorFunction) { + if(ruleNumber < 0) + throw new RuntimeException("The given rule number must be >= 0"); + + ProductionRule rule = grammar.getRule(ruleNumber); + conversions.put(rule, generatorFunction); + + return this; + } + + /** + * Adds the given conversion functions for the specified grammar rule + * @param conversions A map of grammar rules to generator functions + * @return This builder to allow method chaining + */ + public RuleConvertorBuilder setConversions(Map conversions) { + for (Entry entry : conversions.entrySet()) { + setConversion(entry.getKey(), entry.getValue()); + } + + return this; + } + + /** + * Selects the specified grammar rule + * @param rule The grammar rule + * @return An object for applying options for the selected grammar rule + */ + public RuleOptions rule(ProductionRule rule) { + return new RuleOptions(this, rule); + } + + /** + * Selects the specified grammar rule + * @param ruleNumber The index of the grammar rule + * @return An object for applying options for the selected grammar rule + */ + public RuleOptions rule(int ruleNumber) { + if(ruleNumber < 0) + throw new RuntimeException("The given rule number must be >= 0"); + + ProductionRule rule = grammar.getRule(ruleNumber); + return new RuleOptions(this, rule); + } + + + private void populateDefaultConversions() { + for (ProductionRule productionRule : grammar.productionRules()) { + if (conversions.containsKey(productionRule)) continue; + + conversions.put(productionRule, defaultConversion); + } + } + + + /** + * Options that may be applied for a selected grammar rule + */ + protected record RuleOptions(RuleConvertorBuilder builder, ProductionRule rule) { + + /** + * Sets the conversion for the slected grammar rule + * @param generatorFuction The conversion/generator function to be used + * @return The rule convertor builder + */ + public RuleConvertorBuilder setConversion(Generator generatorFuction) { + builder.conversions.put(rule, generatorFuction); + return builder; + } + + } +} diff --git a/src/main/java/component_construction/factories/grammar/BNFConvertor.java b/src/main/java/component_construction/factories/grammar/BNFConvertor.java index 09216b3..f149bb8 100644 --- a/src/main/java/component_construction/factories/grammar/BNFConvertor.java +++ b/src/main/java/component_construction/factories/grammar/BNFConvertor.java @@ -7,6 +7,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import component_construction.builders.grammar_objects.GrammarBuilder; + /** * A class for converting text written in BNF into Grammar objects * Notes: @@ -45,33 +47,10 @@ public class BNFConvertor implements GrammarFactory { public BNFConvertor(String bnf) { GrammarDetailsHolder detailsHolder = gatherGrammarDetails(bnf); - constructedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - for (Token token : detailsHolder.tokenHolder) { - tokenOrganiser.addToken(token); - } - } - - @Override - protected NonTerminal setUpSentinal() { - return detailsHolder.sentinal; - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - for (NonTerminal nonTerminal : detailsHolder.nonTerminalHolder) { - nonTerminalOrganiser.addNonTerminal(nonTerminal); - } - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - for (ProductionRule rule : detailsHolder.ruleHolder) { - ruleOrganiser.addRule(rule); - } - } - }; + constructedGrammar = new GrammarBuilder() + .setSentinal(detailsHolder.sentinal) + .addRules(detailsHolder.ruleHolder) + .produceGrammar(); } private GrammarDetailsHolder gatherGrammarDetails(String bnf) { diff --git a/src/main/java/grammar_objects/Grammar.java b/src/main/java/grammar_objects/Grammar.java index 109053c..70fe049 100644 --- a/src/main/java/grammar_objects/Grammar.java +++ b/src/main/java/grammar_objects/Grammar.java @@ -2,40 +2,12 @@ import java.util.*; -public abstract class Grammar { - - protected Set tokens = new HashSet<>(); - protected Set nonTerminals = new HashSet<>(); - protected List productionRules = new ArrayList<>(); - protected NonTerminal sentinal; - - public Grammar() { - setUpTokens(new TokenOrganiser()); - sentinal = setUpSentinal(); - setUpNonTerminals(new NonTerminalOrganiser()); - setUpProductionRules(new RuleOrganiser()); - } - - /** - * Sets up the tokens for this grammar. - * @param tokenOrganiser An object which is passed to this method to store created tokens. - */ - protected abstract void setUpTokens(TokenOrganiser tokenOrganiser); - /** - * Sets up the sentinal token for this grammar. - * @return The sentinal token for this grammar. - */ - protected abstract NonTerminal setUpSentinal(); - /** - * Sets up the non-terminals for this grammar. - * @param nonTerminalOrganiser An object which is passed to this method to store created non-terminals. - */ - protected abstract void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser); - /** - * Sets up the production rules for this grammar. - * @param ruleOrganiser An object which is passed to this method to store specified production rules. - */ - protected abstract void setUpProductionRules(RuleOrganiser ruleOrganiser); +public record Grammar( + Set tokens, + Set nonTerminals, + List productionRules, + NonTerminal sentinal +) { public ProductionRule getRule(int index) { return productionRules.get(index); @@ -50,66 +22,6 @@ public GrammarParts getParts() { ); } - - protected class TokenOrganiser { - public TokenOrganiser addToken(Token token) { - tokens.add(token); - return this; - } - - /** - * Adds a token for this Grammar. Note: The name will be converted to an object of type Token. Use addToken(Token) to include Token Subtypes. - * @param tokenName The name of the Token to be added. - * @return This TokenOrganiser, for method chaining. - */ - public TokenOrganiser addToken(String tokenName) { - return addToken(new Token(tokenName)); - } - } - - protected class NonTerminalOrganiser { - public NonTerminalOrganiser addNonTerminal(NonTerminal nonTerminal) { - nonTerminals.add(nonTerminal); - return this; - } - - /** - * Adds a NonTerminal for this Grammar. Note: The name will be converted to an object of type NonTerminal. Use addNonTerminal(NonTerminal) to include NonTerminal Subtypes. - * @param nonTerminalName The name of the NonTerminal to be added. - * @return This NonTerminalOrganiser, for method chaining. - */ - public NonTerminalOrganiser addNonTerminal(String nonTerminalName) { - return addNonTerminal(new NonTerminal(nonTerminalName)); - } - } - - protected class RuleOrganiser { - public RuleOrganiser addRule(ProductionRule productionRule) { - productionRules.add(productionRule); - return this; - } - - /** - * Adds a new ProductionRule for this Grammar. - * @param nonTerminal The NonTerminal for this rule - * @param elements The in-order elements for this rule - * @return This RuleOrganiser, for method chaining. - */ - public RuleOrganiser addRule(NonTerminal nonTerminal, LexicalElement[] elements) { - return addRule(new ProductionRule(nonTerminal, elements)); - } - - /** - * Adds a new ProductionRule for this Grammar. - * @param nonTerminalName The name for the NonTerminal for this rule - * @param elements The in-order elements for this rule - * @return This RuleOrganiser, for method chaining. - */ - public RuleOrganiser addRule(String nonTerminalName, LexicalElement[] elements) { - return addRule(new NonTerminal(nonTerminalName), elements); - } - } - @Override public boolean equals(Object object){ if(!(object instanceof Grammar)) { return false; } diff --git a/src/main/java/grammar_objects/LexicalElement.java b/src/main/java/grammar_objects/LexicalElement.java index 337e5ba..1eb4656 100644 --- a/src/main/java/grammar_objects/LexicalElement.java +++ b/src/main/java/grammar_objects/LexicalElement.java @@ -13,20 +13,18 @@ public String getName() { @Override public boolean equals(Object obj) { - if (!this.getClass().isInstance(obj)) { - return false; - } + if (!this.getClass().isInstance(obj)) { return false; } LexicalElement otherElement = (LexicalElement) obj; - if(name == null) { return otherElement.getName() == null; } + if (name == null) { return otherElement.getName() == null; } return getName().equals(otherElement.getName()); } @Override public int hashCode() { - if(name == null) { return 0; } + if (name == null) { return 0; } return name.hashCode(); } diff --git a/src/main/java/grammar_objects/ProductionRule.java b/src/main/java/grammar_objects/ProductionRule.java index ba22e46..2ead21d 100644 --- a/src/main/java/grammar_objects/ProductionRule.java +++ b/src/main/java/grammar_objects/ProductionRule.java @@ -8,20 +8,21 @@ public LexicalElement getFirstElement() { @Override public boolean equals(Object obj) { - if (!(obj instanceof ProductionRule)) { - return false; - } + if (!(obj instanceof ProductionRule)) { return false; } ProductionRule otherRule = (ProductionRule)obj; - if(nonTerminal == null) { - if(otherRule.nonTerminal() != null) { return false; } + if (nonTerminal == null) { + if (otherRule.nonTerminal() != null) { return false; } } else { - if(!nonTerminal.equals(otherRule.nonTerminal())) { return false; } + if (!nonTerminal.equals(otherRule.nonTerminal())) { return false; } } - if(productionSequence.length != otherRule.productionSequence().length) { return false; } + if (productionSequence == null || otherRule.productionSequence() == null) + return productionSequence == otherRule.productionSequence(); + + if (productionSequence.length != otherRule.productionSequence().length) { return false; } LexicalElement[] otherProductionSequence = otherRule.productionSequence(); for (int i = 0; i < productionSequence.length; i++) { @@ -37,7 +38,7 @@ public boolean equals(Object obj) { public String toString() { String string = ""; - if(nonTerminal == null) { + if (nonTerminal == null) { string += "null"; } else { @@ -47,14 +48,13 @@ public String toString() { string += " := "; for (int i = 0; i < productionSequence.length - 1; i++) { - if(productionSequence[i] == null) { string += "null"; } + if (productionSequence[i] == null) { string += "null"; } string += productionSequence[i].toString() + " "; } - if(productionSequence.length > 0) { + if (productionSequence.length > 0) string += productionSequence[productionSequence.length - 1].toString(); - } string.stripTrailing(); return string; @@ -62,10 +62,15 @@ public String toString() { @Override public int hashCode() { - int hashCode = nonTerminal.hashCode() * 31; + int hashCode = 1; + + if (nonTerminal != null) + hashCode *= nonTerminal.hashCode() * 31; - for (LexicalElement lexicalElement : productionSequence) { - hashCode *= lexicalElement.hashCode(); + if (productionSequence != null) { + for (LexicalElement lexicalElement : productionSequence) { + hashCode *= lexicalElement.hashCode(); + } } return hashCode; diff --git a/src/main/java/grammar_objects/RuleConvertor.java b/src/main/java/grammar_objects/RuleConvertor.java index a81fe16..beece05 100644 --- a/src/main/java/grammar_objects/RuleConvertor.java +++ b/src/main/java/grammar_objects/RuleConvertor.java @@ -3,85 +3,95 @@ import java.util.*; import code_generation.Generator; +import component_construction.ParameterError; import helper_objects.NullableTuple; -public abstract class RuleConvertor { - public static final Integer ROOT_RULE_INDEX = null; - public static final ProductionRule ROOT_RULE = null; - - private Grammar grammar; - private NullableTuple bookends; - private Map conversions = new HashMap<>(); - - public RuleConvertor() { - grammar = setUpGrammar(); - bookends = setUpBookends(); - - if(bookends == null) { - bookends = new NullableTuple("", ""); - } - - setUpRuleConvertors(new RuleOrganiser()); - } +/** + * Defines conversions for the rules within the specified grammar. + */ +public record RuleConvertor( + Grammar grammar, + Map conversions, + NullableTuple bookends +) { + //TODO: Consider if the sentinal token should be listed in the productionSequence + public static final ProductionRule ROOT_RULE = new ProductionRule(null, null); /** - * Set up the grammar for this convertor - * @return The grammar to be used + * Defines conversions for the rules within the specified grammar + * @param grammar The grammar for conversions + * @param conversions The conversions for every grammar rule + * @param bookends Any constant strings which will bookend produced generations. May be null, in which case the Generator will be {@code (elements) -> elements[0].getGeneration() } */ - protected abstract Grammar setUpGrammar(); + public RuleConvertor( + Grammar grammar, + Map conversions, + NullableTuple bookends + ) { + if (grammar == null) throw new ParameterError("A grammar must be defined"); + if (conversions == null) throw new ParameterError("Production rule conversions must be defined"); + + if (bookends == null) + bookends = new NullableTuple("", ""); - /** - * Set up the constant starting and ending strings for conversions - * @return A NullableTuple of the starting string and ending string, may be null in which case the bookends will be taken as ("","") - */ - protected abstract NullableTuple setUpBookends(); + try { + if (!conversions.containsKey(ROOT_RULE)) + conversions.put(ROOT_RULE, (elements) -> elements[0].getGeneration()); + } + catch (NullPointerException e) { + conversions = new HashMap<>(); + conversions.put(ROOT_RULE, (elements) -> elements[0].getGeneration()); + conversions.putAll(conversions); + } - /** - * Sets up code conversions for each production rule, for when the rules are sanctioned - * @param ruleOrganiser A helper object for conversion setup - */ - protected abstract void setUpRuleConvertors(RuleOrganiser ruleOrganiser); + if (conversions.size() < grammar.productionRules().size() + 1) + throw new IncompleteConversionsException(conversions, grammar.productionRules()); - /** - * Gets the start and ending strings for conversions - * @return A tuple of the starting and ending strings - */ - public NullableTuple getBookends() { - return bookends; + this.grammar = grammar; + this.bookends = bookends; + this.conversions = conversions; } /** - * Gets the mapping of production rules to the Generators for their conversions - * @return The conversion map + * Defines conversions for the rules within the specified grammar + * @param grammar The grammar for conversions + * @param conversions The conversions for every grammar rule */ - public Map getConversions() { - return conversions; + public RuleConvertor( + Grammar grammar, + Map conversions + ) { + this(grammar, conversions, null); } - protected class RuleOrganiser { - - /** - * Sets the conversion code to run when the specified rule is sanctioned - * @param ruleNumber The rule index. ROOT_RULE_INDEX, to run code after the final rule is sanctioned (useful for formatting). - * @param generatorFunction The function to be run when the specified rule is sanctioned. - * @return The original organiser object to allof method chaining. - */ - public RuleOrganiser setConversion(Integer ruleNumber, Generator generatorFunction) { - if(ruleNumber < 0 && ruleNumber != ROOT_RULE_INDEX) { - throw new RuntimeException("The given rule number must be >= 0 or ROOT_RULE_INDEX"); + public class IncompleteConversionsException extends RuntimeException { + + protected String message; + + public IncompleteConversionsException(Map conversions, List productionRules) { + List notImplemented = new ArrayList<>(); + + for (ProductionRule productionRule : productionRules) { + if (!conversions.containsKey(productionRule)) + notImplemented.add(productionRule); } - ProductionRule rule = null; + message = "There were no conversions for the following rules:\n"; + + if (!conversions.containsKey(ROOT_RULE)) + message += " ROOT_RULE\n"; - if(ruleNumber != ROOT_RULE_INDEX) { - rule = grammar.getRule(ruleNumber); + for (ProductionRule productionRule : notImplemented) { + message += " " + productionRule.toString() + "\n"; } - conversions.put(rule, generatorFunction); + message = message.strip(); + } - return this; + @Override + public String getMessage() { + return message; } } - } diff --git a/src/main/java/grammars/basic_CLR1/BasicCLR1Grammar.java b/src/main/java/grammars/basic_CLR1/BasicCLR1Grammar.java index 3b9b00d..9dbffd8 100644 --- a/src/main/java/grammars/basic_CLR1/BasicCLR1Grammar.java +++ b/src/main/java/grammars/basic_CLR1/BasicCLR1Grammar.java @@ -1,50 +1,30 @@ package grammars.basic_CLR1; +import component_construction.builders.grammar_objects.GrammarBuilder; import grammar_objects.*; -public class BasicCLR1Grammar extends Grammar { - - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser - .addToken("a") - .addToken("b"); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("S"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser - .addNonTerminal("S") - .addNonTerminal("X"); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser +public class BasicCLR1Grammar { + public static Grammar produce() { + return new GrammarBuilder() + .setSentinal(new NonTerminal("S")) .addRule( new NonTerminal("S"), new LexicalElement[] { new NonTerminal("X"), new NonTerminal("X") }) - .addRule( new NonTerminal("X"), new LexicalElement[] { new Token("a"), new NonTerminal("X") }) - .addRule( new NonTerminal("X"), new LexicalElement[] { new Token("b") - }); + }) + .produceGrammar(); } } diff --git a/src/main/java/grammars/basic_SLR1/BasicSLR1Grammar.java b/src/main/java/grammars/basic_SLR1/BasicSLR1Grammar.java index bb4fd90..bb4cd02 100644 --- a/src/main/java/grammars/basic_SLR1/BasicSLR1Grammar.java +++ b/src/main/java/grammars/basic_SLR1/BasicSLR1Grammar.java @@ -1,5 +1,6 @@ package grammars.basic_SLR1; +import component_construction.builders.grammar_objects.GrammarBuilder; import grammar_objects.*; /** @@ -7,31 +8,11 @@ * A –> aA * A –> b */ -public class BasicSLR1Grammar extends Grammar { - - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser - .addToken("a") - .addToken("b"); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("S"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser - .addNonTerminal("S") - .addNonTerminal("A"); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser +public class BasicSLR1Grammar { + public static Grammar produce() { + return new GrammarBuilder() + .setSentinal(new NonTerminal("S")) .addRule( new NonTerminal("S"), new LexicalElement[] { @@ -51,7 +32,8 @@ protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { new LexicalElement[] { new Token("b") } - ); + ) + .produceGrammar(); } } diff --git a/src/main/java/grammars/basic_identifier/BasicIdentifierGrammar.java b/src/main/java/grammars/basic_identifier/BasicIdentifierGrammar.java index c57bbc7..235c043 100644 --- a/src/main/java/grammars/basic_identifier/BasicIdentifierGrammar.java +++ b/src/main/java/grammars/basic_identifier/BasicIdentifierGrammar.java @@ -1,5 +1,6 @@ package grammars.basic_identifier; +import component_construction.builders.grammar_objects.GrammarBuilder; import grammar_objects.*; /** @@ -8,48 +9,22 @@ * := identifier = + ; * := identifier | number */ -public class BasicIdentifierGrammar extends Grammar { - - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser - .addToken(new Token("=")) - .addToken(new Token("+")) - .addToken(new Token(";")) - .addToken(new Identifier("identifier")) - .addToken(new Literal("number")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("statement list"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser - .addNonTerminal("statement list") - .addNonTerminal("statement") - .addNonTerminal("element"); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser +public class BasicIdentifierGrammar { + public static Grammar produce() { + return new GrammarBuilder() + .setSentinal(new NonTerminal("statement list")) .addRule( new NonTerminal("statement list"), new LexicalElement[] { new NonTerminal("statement") }) - .addRule( new NonTerminal("statement list"), new LexicalElement[] { new NonTerminal("statement list"), new NonTerminal("statement") }) - .addRule( new NonTerminal("statement"), new LexicalElement[] { @@ -60,18 +35,17 @@ protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { new NonTerminal("element"), new Token(";") }) - .addRule( new NonTerminal("element"), new LexicalElement[] { new Identifier("identifier") }) - .addRule( new NonTerminal("element"), new LexicalElement[] { new Literal("number") - }); + }) + .produceGrammar(); } } \ No newline at end of file diff --git a/src/main/java/grammars/basic_identifier/convertors/XToYToX.java b/src/main/java/grammars/basic_identifier/convertors/XToYToX.java index 12bbacc..6e489b5 100644 --- a/src/main/java/grammars/basic_identifier/convertors/XToYToX.java +++ b/src/main/java/grammars/basic_identifier/convertors/XToYToX.java @@ -1,39 +1,37 @@ package grammars.basic_identifier.convertors; +import java.util.*; + import grammar_objects.*; import grammars.basic_identifier.BasicIdentifierGrammar; import helper_objects.NullableTuple; -public class XToYToX extends RuleConvertor { - - @Override - protected Grammar setUpGrammar() { - return new BasicIdentifierGrammar(); - } +public class XToYToX { - @Override - protected NullableTuple setUpBookends() { - return new NullableTuple( - "public class TestGrammar {\n" + - "\tpublic static void main(String[] args) {\n", + public static RuleConvertor produce() { + Grammar grammar = BasicIdentifierGrammar.produce(); + + return new RuleConvertor( + grammar, + new HashMap<>(Map.of( + grammar.getRule(0), (elements) -> { return elements[0].getGeneration(); }, // := + grammar.getRule(1), (elements) -> { return elements[0].getGeneration() + elements[1].getGeneration(); }, // := + grammar.getRule(2), (elements) -> { + return "\t\t" + elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration() + " " + + elements[3].getGeneration() + " " + elements[4].getGeneration() + elements[5].getGeneration() + "\n"; + }, // := identifier = + ; + grammar.getRule(3), (elements) -> { return elements[0].getGeneration(); }, // := identifier + grammar.getRule(4), (elements) -> { return elements[0].getGeneration(); } // := number + )), + new NullableTuple( + "public class TestGrammar {\n" + + "\tpublic static void main(String[] args) {\n", - "\t\tSystem.out.println(x);\n" + - "\t}\n" + - "}" + "\t\tSystem.out.println(x);\n" + + "\t}\n" + + "}" + ) ); } - - @Override - protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { - ruleOrganiser - .setConversion(0, (elements) -> { return elements[0].getGeneration(); }) // := - .setConversion(1, (elements) -> { return elements[0].getGeneration() + elements[1].getGeneration(); }) // := - .setConversion(2, (elements) -> { - return "\t\t" + elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration() + " " + - elements[3].getGeneration() + " " + elements[4].getGeneration() + elements[5].getGeneration() + "\n"; - }) // := identifier = + ; - .setConversion(3, (elements) -> { return elements[0].getGeneration(); }) // := identifier - .setConversion(4, (elements) -> { return elements[0].getGeneration(); }); // := number - } } diff --git a/src/main/java/grammars/basic_identifier/convertors/XToYToXSemantic.java b/src/main/java/grammars/basic_identifier/convertors/XToYToXSemantic.java index 85fce34..a3f6113 100644 --- a/src/main/java/grammars/basic_identifier/convertors/XToYToXSemantic.java +++ b/src/main/java/grammars/basic_identifier/convertors/XToYToXSemantic.java @@ -1,53 +1,51 @@ package grammars.basic_identifier.convertors; +import java.util.*; + import code_generation.*; import grammar_objects.*; import grammars.basic_identifier.BasicIdentifierGrammar; import helper_objects.NullableTuple; import semantic_analysis.TypeChecker; -public class XToYToXSemantic extends RuleConvertor { - - @Override - protected Grammar setUpGrammar() { - return new BasicIdentifierGrammar(); - } - - @Override - protected NullableTuple setUpBookends() { - return new NullableTuple( - "public class TestGrammar {\n" + - "\tpublic static void main(String[] args) {\n", +public class XToYToXSemantic { - "\t\tSystem.out.println(x);\n" + - "\t}\n" + - "}" - ); - } - - @Override - protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { + public static RuleConvertor produce() { TypeChecker typeChecker = new TypeChecker(); - ruleOrganiser - .setConversion(0, (elements) -> { return elements[0].getGeneration(); }) // := - .setConversion(1, (elements) -> { return elements[0].getGeneration() + elements[1].getGeneration(); }) // := - .setConversion(2, (elements) -> { - String identifierType = ""; - - DynamicTokenGeneration identifier = (DynamicTokenGeneration)elements[0]; - if(!typeChecker.isDeclared(identifier)) { - identifierType = "int "; //Note: Only works for "int" in this grammar - typeChecker.declare(identifier); - } - - return "\t\t" + identifierType + elements[0].getGeneration() + " " + - elements[1].getGeneration() + " " + elements[2].getGeneration() + " " + - elements[3].getGeneration() + " " + elements[4].getGeneration() + - elements[5].getGeneration() + "\n"; - }) // := identifier = + ; - .setConversion(3, (elements) -> { return elements[0].getGeneration(); }) // := identifier - .setConversion(4, (elements) -> { return elements[0].getGeneration(); }); // := number + Grammar grammar = BasicIdentifierGrammar.produce(); + + return new RuleConvertor( + grammar, + new HashMap<>(Map.of( + grammar.getRule(0), (elements) -> { return elements[0].getGeneration(); },// := + grammar.getRule(1), (elements) -> { return elements[0].getGeneration() + elements[1].getGeneration(); },// := + grammar.getRule(2), (elements) -> { + String identifierType = ""; + + DynamicTokenGeneration identifier = (DynamicTokenGeneration)elements[0]; + if(!typeChecker.isDeclared(identifier)) { + identifierType = "int "; // Note: Only works for "int" in this grammar + typeChecker.declare(identifier); + } + + return "\t\t" + identifierType + elements[0].getGeneration() + " " + + elements[1].getGeneration() + " " + elements[2].getGeneration() + " " + + elements[3].getGeneration() + " " + elements[4].getGeneration() + + elements[5].getGeneration() + "\n"; + }, // := identifier = + ; + grammar.getRule(3), (elements) -> { return elements[0].getGeneration(); },// := identifier + grammar.getRule(4), (elements) -> { return elements[0].getGeneration(); } // := number + )), + new NullableTuple( + "public class TestGrammar {\n" + + "\tpublic static void main(String[] args) {\n", + + "\t\tSystem.out.println(x);\n" + + "\t}\n" + + "}" + ) + ); } } diff --git a/src/main/java/grammars/integer_comparison/IntegerCompGrammar.java b/src/main/java/grammars/integer_comparison/IntegerCompGrammar.java index da04b35..dd38700 100644 --- a/src/main/java/grammars/integer_comparison/IntegerCompGrammar.java +++ b/src/main/java/grammars/integer_comparison/IntegerCompGrammar.java @@ -1,5 +1,6 @@ package grammars.integer_comparison; +import component_construction.builders.grammar_objects.GrammarBuilder; import grammar_objects.*; // statement_list -> statement_list statement @@ -26,53 +27,10 @@ // expression -> expression - numConstant // expression -> expression * numConstant // expression -> expression / numConstant -public class IntegerCompGrammar extends Grammar { - - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser - .addToken(new Token(";")) - .addToken(new Token("if")) - .addToken(new Token("(")) - .addToken(new Token(")")) - .addToken(new Token("{")) - .addToken(new Token("}")) - .addToken(new Token("else")) - .addToken(new Token(">")) - .addToken(new Token(">=")) - .addToken(new Token("==")) - .addToken(new Token("!=")) - .addToken(new Token("<=")) - .addToken(new Token("=")) - .addToken(new Token("+")) - .addToken(new Token("-")) - .addToken(new Token("*")) - .addToken(new Token("/")) - .addToken(new Identifier("identifier")) - .addToken(new Literal("numConstant")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("statement list"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser - .addNonTerminal("statement list") - .addNonTerminal("statement") - .addNonTerminal("if statement") - .addNonTerminal("condition") - .addNonTerminal("conditional operator") - .addNonTerminal("assignment") - .addNonTerminal("expression"); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser +public class IntegerCompGrammar { + public static Grammar produce() { + return new GrammarBuilder() .addRule( new NonTerminal("statement list"), new LexicalElement[] { @@ -250,7 +208,9 @@ protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { new NonTerminal("expression"), new Token("/"), new Literal("numConstant") - }); + }) + + .produceGrammar(); } } diff --git a/src/main/java/grammars/integer_comparison/convertors/JavaConversion.java b/src/main/java/grammars/integer_comparison/convertors/JavaConversion.java index 5640d48..c063e8f 100644 --- a/src/main/java/grammars/integer_comparison/convertors/JavaConversion.java +++ b/src/main/java/grammars/integer_comparison/convertors/JavaConversion.java @@ -1,58 +1,44 @@ package grammars.integer_comparison.convertors; +import java.util.*; + import code_generation.*; import grammar_objects.*; import grammars.integer_comparison.IntegerCompGrammar; import helper_objects.NullableTuple; import semantic_analysis.TypeChecker; -public class JavaConversion extends RuleConvertor { - - @Override - protected Grammar setUpGrammar() { - return new IntegerCompGrammar(); - } - - @Override - protected NullableTuple setUpBookends() { - return new NullableTuple( - "public class TestGrammar {\n" + - " public static void main(String[] args) {\n", - - " System.out.println(x);\n" + - " }\n" + - "}" - ); - } +public class JavaConversion { - @Override - protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { + public static RuleConvertor produce() { TypeChecker typeChecker = new TypeChecker(); - ruleOrganiser - .setConversion(ROOT_RULE_INDEX, (elements) -> { return " " + elements[0].getGeneration().stripTrailing().replaceAll("\n", "\n ") + "\n"; }) - .setConversion(0, (elements) -> { return elements[0].getGeneration() + elements[1].getGeneration() + "\n"; }) // := - .setConversion(1, (elements) -> { return elements[0].getGeneration() + "\n"; }) // := - .setConversion(2, (elements) -> { return elements[0].getGeneration() + ";"; }) // := ; - .setConversion(3, (elements) -> { return elements[0].getGeneration() + "\n"; }) // := - .setConversion(4, (elements) -> { + Grammar grammar = IntegerCompGrammar.produce(); + + Map convertors = new HashMap<>(); + convertors.put(RuleConvertor.ROOT_RULE, (elements) -> { return " " + elements[0].getGeneration().stripTrailing().replaceAll("\n", "\n ") + "\n"; }); + convertors.put(grammar.getRule(0), (elements) -> { return elements[0].getGeneration() + elements[1].getGeneration() + "\n"; }); // := + convertors.put(grammar.getRule(1), (elements) -> { return elements[0].getGeneration() + "\n"; }); // := + convertors.put(grammar.getRule(2), (elements) -> { return elements[0].getGeneration() + ";"; }); // := ; + convertors.put(grammar.getRule(3), (elements) -> { return elements[0].getGeneration() + "\n"; }); // := + convertors.put(grammar.getRule(4), (elements) -> { String generation = "\nif(" + elements[2].getGeneration() + ") {\n "; generation += elements[5].getGeneration().stripTrailing().replaceAll("\n", "\n "); return generation + "\n}"; - }) // := if() {} - .setConversion(5, (elements) -> { + }); // := if() {} + convertors.put(grammar.getRule(5), (elements) -> { String generation = elements[0].getGeneration() + "\nelse {\n "; generation += elements[3].getGeneration().stripTrailing().replaceAll("\n", "\n "); return generation + "\n}"; - }) // := else {} - .setConversion(6, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := identifier identifier - .setConversion(7, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := identifier numConstant - .setConversion(8, (elements) -> { return elements[0].getGeneration(); }) // := > - .setConversion(9, (elements) -> { return elements[0].getGeneration(); }) // := >= - .setConversion(10, (elements) -> { return elements[0].getGeneration(); }) // := == - .setConversion(11, (elements) -> { return elements[0].getGeneration(); }) // := != - .setConversion(12, (elements) -> { return elements[0].getGeneration(); }) // := <= - .setConversion(13, (elements) -> { + }); // := else {} + convertors.put(grammar.getRule(6), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := identifier identifier + convertors.put(grammar.getRule(7), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := identifier numConstant + convertors.put(grammar.getRule(8), (elements) -> { return elements[0].getGeneration(); }); // := > + convertors.put(grammar.getRule(9), (elements) -> { return elements[0].getGeneration(); }); // := >= + convertors.put(grammar.getRule(10), (elements) -> { return elements[0].getGeneration(); }); // := == + convertors.put(grammar.getRule(11), (elements) -> { return elements[0].getGeneration(); }); // := != + convertors.put(grammar.getRule(12), (elements) -> { return elements[0].getGeneration(); }); // := <= + convertors.put(grammar.getRule(13), (elements) -> { String generation = ""; DynamicTokenGeneration identifier = (DynamicTokenGeneration)elements[0]; @@ -63,17 +49,30 @@ protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { generation += elements[0].getGeneration(); return generation + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); - }) // := identifier = - .setConversion(14, (elements) -> { return elements[0].getGeneration(); }) // := val identifier - .setConversion(15, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := + identifier - .setConversion(16, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := - identifier - .setConversion(17, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := * identifier - .setConversion(18, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := / identifier - .setConversion(19, (elements) -> { return elements[0].getGeneration(); }) // := numConstant - .setConversion(20, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := + numConstant - .setConversion(21, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := - numConstant - .setConversion(22, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) // := * numConstant - .setConversion(23, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := / numConstant + }); // := identifier = + convertors.put(grammar.getRule(14), (elements) -> { return elements[0].getGeneration(); }); // := val identifier + convertors.put(grammar.getRule(15), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := + identifier + convertors.put(grammar.getRule(16), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := - identifier + convertors.put(grammar.getRule(17), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := * identifier + convertors.put(grammar.getRule(18), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := / identifier + convertors.put(grammar.getRule(19), (elements) -> { return elements[0].getGeneration(); }); // := numConstant + convertors.put(grammar.getRule(20), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := + numConstant + convertors.put(grammar.getRule(21), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := - numConstant + convertors.put(grammar.getRule(22), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := * numConstant + convertors.put(grammar.getRule(23), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }); // := / numConstant + + return new RuleConvertor( + grammar, + convertors, + new NullableTuple( + "public class TestGrammar {\n" + + " public static void main(String[] args) {\n", + + " System.out.println(x);\n" + + " }\n" + + "}" + ) + ); } } diff --git a/src/main/java/grammars/self_referential/SelfReferentialGrammar.java b/src/main/java/grammars/self_referential/SelfReferentialGrammar.java index a482b30..e9e3a8e 100644 --- a/src/main/java/grammars/self_referential/SelfReferentialGrammar.java +++ b/src/main/java/grammars/self_referential/SelfReferentialGrammar.java @@ -1,5 +1,6 @@ package grammars.self_referential; +import component_construction.builders.grammar_objects.GrammarBuilder; import grammar_objects.*; /** @@ -8,60 +9,35 @@ * L → l L //Self-referential * L → o */ -public class SelfReferentialGrammar extends Grammar { - - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser - .addToken("h") - .addToken("a") - .addToken("l") - .addToken("o"); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("H"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser - .addNonTerminal("H") - .addNonTerminal("A") - .addNonTerminal("L"); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser +public class SelfReferentialGrammar { + public static Grammar produce() { + return new GrammarBuilder() + .setSentinal(new NonTerminal("H")) .addRule( new NonTerminal("H"), new LexicalElement[] { new Token("h"), new NonTerminal("A") }) - .addRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("L") }) - .addRule( new NonTerminal("L"), new LexicalElement[] { new Token("l"), new NonTerminal("L") }) - .addRule( new NonTerminal("L"), new LexicalElement[] { new Token("o") - }); + }) + .produceGrammar(); } } diff --git a/src/main/java/grammars/small_grammar/SmallGrammar.java b/src/main/java/grammars/small_grammar/SmallGrammar.java index 2078396..996368d 100644 --- a/src/main/java/grammars/small_grammar/SmallGrammar.java +++ b/src/main/java/grammars/small_grammar/SmallGrammar.java @@ -1,5 +1,6 @@ package grammars.small_grammar; +import component_construction.builders.grammar_objects.GrammarBuilder; import grammar_objects.*; /** @@ -9,33 +10,11 @@ * B->0 * B->1 */ -public class SmallGrammar extends Grammar { - - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser - .addToken("0") - .addToken("1") - .addToken("*") - .addToken("+"); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("E"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser - .addNonTerminal("E") - .addNonTerminal("B"); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser +public class SmallGrammar { + public static Grammar produce() { + return new GrammarBuilder() + .setSentinal(new NonTerminal("E")) .addRule( new NonTerminal("E"), new LexicalElement[] { @@ -43,7 +22,6 @@ protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { new Token("+"), new NonTerminal("B") }) - .addRule( new NonTerminal("E"), new LexicalElement[] { @@ -51,24 +29,22 @@ protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { new Token("*"), new NonTerminal("B") }) - .addRule( new NonTerminal("E"), new LexicalElement[] { new NonTerminal("B") }) - .addRule( new NonTerminal("B"), new LexicalElement[] { new Token("0") }) - .addRule( new NonTerminal("B"), new LexicalElement[] { new Token("1") - }); + }) + .produceGrammar(); } } diff --git a/src/main/java/grammars/small_grammar/convertors/COpZtO.java b/src/main/java/grammars/small_grammar/convertors/COpZtO.java index 38063e9..dd19641 100644 --- a/src/main/java/grammars/small_grammar/convertors/COpZtO.java +++ b/src/main/java/grammars/small_grammar/convertors/COpZtO.java @@ -1,37 +1,35 @@ package grammars.small_grammar.convertors; +import java.util.*; + import grammar_objects.*; import grammars.small_grammar.SmallGrammar; import helper_objects.NullableTuple; -public class COpZtO extends RuleConvertor { - - @Override - protected Grammar setUpGrammar() { - return new SmallGrammar(); - } +public class COpZtO { - @Override - protected NullableTuple setUpBookends() { - return new NullableTuple( - "#include \n" + - "\n" + - "main()\n" + - "\tprintf(", + public static RuleConvertor produce() { + Grammar grammar = SmallGrammar.produce(); + + return new RuleConvertor( + grammar, + new HashMap<>(Map.of( + grammar.getRule(0), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E+B + grammar.getRule(1), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E*B + grammar.getRule(2), (elements) -> { return elements[0].getGeneration(); }, //E->B + grammar.getRule(3), (elements) -> { return elements[0].getGeneration(); }, //B->0 + grammar.getRule(4), (elements) -> { return elements[0].getGeneration(); } //B->1 + )), + new NullableTuple( + "#include \n" + + "\n" + + "main()\n" + + "\tprintf(", - ");\n" + - "}" + ");\n" + + "}" + ) ); } - @Override - protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { - ruleOrganiser - .setConversion(0, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E+B - .setConversion(1, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E*B - .setConversion(2, (elements) -> { return elements[0].getGeneration(); }) //E->B - .setConversion(3, (elements) -> { return elements[0].getGeneration(); }) //B->0 - .setConversion(4, (elements) -> { return elements[0].getGeneration(); }); //B->1 - } - } diff --git a/src/main/java/grammars/small_grammar/convertors/EmptyReduce.java b/src/main/java/grammars/small_grammar/convertors/EmptyReduce.java index 491ce8f..2d47372 100644 --- a/src/main/java/grammars/small_grammar/convertors/EmptyReduce.java +++ b/src/main/java/grammars/small_grammar/convertors/EmptyReduce.java @@ -1,37 +1,35 @@ package grammars.small_grammar.convertors; +import java.util.*; + import grammar_objects.*; import grammars.small_grammar.SmallGrammar; import helper_objects.NullableTuple; -public class EmptyReduce extends RuleConvertor { - - @Override - protected Grammar setUpGrammar() { - return new SmallGrammar(); - } +public class EmptyReduce { - @Override - protected NullableTuple setUpBookends() { - return new NullableTuple( - "public class TestGrammar {\n" + - "\tpublic static void main(String[] args) {\n" + - "\t\tSystem.out.println(", + public static RuleConvertor produce() { + Grammar grammar = SmallGrammar.produce(); + + return new RuleConvertor( + grammar, + new HashMap<>(Map.of( + grammar.getRule(0), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E+B + grammar.getRule(1), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E*B + grammar.getRule(2), (elements) -> { return elements[0].getGeneration(); }, //E->B + grammar.getRule(3), (elements) -> { return elements[0].getGeneration(); }, //B->0 + grammar.getRule(4), (elements) -> { return elements[0].getGeneration(); } //B->1 + )), + new NullableTuple( + "public class TestGrammar {\n" + + "\tpublic static void main(String[] args) {\n" + + "\t\tSystem.out.println(", - ");\n" + - "\t}\n" + - "}" + ");\n" + + "\t}\n" + + "}" + ) ); } - - @Override - protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { - ruleOrganiser - .setConversion(0, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E+B - .setConversion(1, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E*B - .setConversion(2, (elements) -> { return elements[0].getGeneration(); }) //E->B - .setConversion(3, (elements) -> { return elements[0].getGeneration(); }) //B->0 - .setConversion(4, (elements) -> { return elements[0].getGeneration(); }); //B->1 - } } diff --git a/src/main/java/grammars/small_grammar/convertors/One.java b/src/main/java/grammars/small_grammar/convertors/One.java index 90e199e..c94057a 100644 --- a/src/main/java/grammars/small_grammar/convertors/One.java +++ b/src/main/java/grammars/small_grammar/convertors/One.java @@ -1,37 +1,35 @@ package grammars.small_grammar.convertors; +import java.util.*; + import grammar_objects.*; import grammars.small_grammar.SmallGrammar; import helper_objects.NullableTuple; -public class One extends RuleConvertor { - - @Override - protected Grammar setUpGrammar() { - return new SmallGrammar(); - } +public class One { - @Override - protected NullableTuple setUpBookends() { - return new NullableTuple( - "public class TestGrammar {\n" + - "\tpublic static void main(String[] args) {\n" + - "\t\tSystem.out.println(", + public static RuleConvertor produce() { + Grammar grammar = SmallGrammar.produce(); + + return new RuleConvertor( + grammar, + new HashMap<>(Map.of( + grammar.getRule(0), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E+B + grammar.getRule(1), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E*B + grammar.getRule(2), (elements) -> { return elements[0].getGeneration(); }, //E->B + grammar.getRule(3), (elements) -> { return elements[0].getGeneration(); }, //B->0 + grammar.getRule(4), (elements) -> { return elements[0].getGeneration(); } //B->1 + )), + new NullableTuple( + "public class TestGrammar {\n" + + "\tpublic static void main(String[] args) {\n" + + "\t\tSystem.out.println(", - ");\n" + - "\t}\n" + - "}" + ");\n" + + "\t}\n" + + "}" + ) ); } - - @Override - protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { - ruleOrganiser - .setConversion(0, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E+B - .setConversion(1, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E*B - .setConversion(2, (elements) -> { return elements[0].getGeneration(); }) //E->B - .setConversion(3, (elements) -> { return elements[0].getGeneration(); }) //B->0 - .setConversion(4, (elements) -> { return elements[0].getGeneration(); }); //B->1 - } } diff --git a/src/main/java/grammars/small_grammar/convertors/OpZtO.java b/src/main/java/grammars/small_grammar/convertors/OpZtO.java index 957a30e..2a5fd34 100644 --- a/src/main/java/grammars/small_grammar/convertors/OpZtO.java +++ b/src/main/java/grammars/small_grammar/convertors/OpZtO.java @@ -1,5 +1,7 @@ package grammars.small_grammar.convertors; +import java.util.*; + import grammar_objects.*; import grammars.small_grammar.SmallGrammar; import helper_objects.NullableTuple; @@ -7,34 +9,30 @@ /** * "1+0*1" */ -public class OpZtO extends RuleConvertor { - - @Override - protected Grammar setUpGrammar() { - return new SmallGrammar(); - } - - @Override - protected NullableTuple setUpBookends() { - return new NullableTuple( - "public class TestGrammar {\n" + - "\tpublic static void main(String[] args) {\n" + - "\t\tSystem.out.println(", +public class OpZtO { + + public static RuleConvertor produce() { + Grammar grammar = SmallGrammar.produce(); + + return new RuleConvertor( + grammar, + new HashMap<>(Map.of( + grammar.getRule(0), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E+B + grammar.getRule(1), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E*B + grammar.getRule(2), (elements) -> { return elements[0].getGeneration(); }, //E->B + grammar.getRule(3), (elements) -> { return elements[0].getGeneration(); }, //B->0 + grammar.getRule(4), (elements) -> { return elements[0].getGeneration(); } //B->1 + )), + new NullableTuple( + "public class TestGrammar {\n" + + "\tpublic static void main(String[] args) {\n" + + "\t\tSystem.out.println(", - ");\n" + - "\t}\n" + - "}" + ");\n" + + "\t}\n" + + "}" + ) ); } - - @Override - protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { - ruleOrganiser - .setConversion(0, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E+B - .setConversion(1, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E*B - .setConversion(2, (elements) -> { return elements[0].getGeneration(); }) //E->B - .setConversion(3, (elements) -> { return elements[0].getGeneration(); }) //B->0 - .setConversion(4, (elements) -> { return elements[0].getGeneration(); }); //B->1 - } } diff --git a/src/main/java/grammars/small_grammar/convertors/OpZtOMissingReduction.java b/src/main/java/grammars/small_grammar/convertors/OpZtOMissingReduction.java index 94d475e..6e5e9b6 100644 --- a/src/main/java/grammars/small_grammar/convertors/OpZtOMissingReduction.java +++ b/src/main/java/grammars/small_grammar/convertors/OpZtOMissingReduction.java @@ -1,37 +1,34 @@ package grammars.small_grammar.convertors; +import java.util.*; + import grammar_objects.*; import grammars.small_grammar.SmallGrammar; import helper_objects.NullableTuple; -public class OpZtOMissingReduction extends RuleConvertor { - - @Override - protected Grammar setUpGrammar() { - return new SmallGrammar(); - } - - @Override - protected NullableTuple setUpBookends() { - return new NullableTuple( - "public class TestGrammar {\n" + - "\tpublic static void main(String[] args) {\n" + - "\t\tSystem.out.println(", +public class OpZtOMissingReduction { + + public static RuleConvertor produce() { + Grammar grammar = SmallGrammar.produce(); + + return new RuleConvertor( + grammar, + new HashMap<>(Map.of( + grammar.getRule(0), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E+B + grammar.getRule(1), (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }, //E->E*B + grammar.getRule(2), (elements) -> { return elements[0].getGeneration(); }, //E->B + grammar.getRule(3), (elements) -> { return elements[0].getGeneration(); }, //B->0 + grammar.getRule(4), (elements) -> { return elements[0].getGeneration(); } //B->1 + )), + new NullableTuple( + "public class TestGrammar {\n" + + "\tpublic static void main(String[] args) {\n" + + "\t\tSystem.out.println(", - ");\n" + - "\t}\n" + - "}" + ");\n" + + "\t}\n" + + "}" + ) ); } - - @Override - protected void setUpRuleConvertors(RuleOrganiser ruleOrganiser) { - ruleOrganiser - .setConversion(0, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E+B - .setConversion(1, (elements) -> { return elements[0].getGeneration() + " " + elements[1].getGeneration() + " " + elements[2].getGeneration(); }) //E->E*B - .setConversion(2, (elements) -> { return elements[0].getGeneration(); }) //E->B - .setConversion(3, (elements) -> { return elements[0].getGeneration(); }) //B->0 - .setConversion(4, (elements) -> { return elements[0].getGeneration(); }); //B->1 - } - } diff --git a/src/test/java/component_construction/CompilerTests.java b/src/test/java/component_construction/CompilerTests.java index 31ffe8a..be9b9f8 100644 --- a/src/test/java/component_construction/CompilerTests.java +++ b/src/test/java/component_construction/CompilerTests.java @@ -24,8 +24,8 @@ public void basicIdentifierCompiler() throws ParseFailedException { new GeneralLexicalAnalyserFactory(), new CLR1ParserFactory(), new BasicCodeGenFactory(), - new BasicIdentifierGrammar(), - new XToYToXSemantic(), + BasicIdentifierGrammar.produce(), + XToYToXSemantic.produce(), new String[] {" ", "\n", "\r", "\t"}, new String[] {"+", "=", ";"}, new String[] {}, diff --git a/src/test/java/component_construction/builders/CompilerBuilderTests.java b/src/test/java/component_construction/builders/CompilerBuilderTests.java index 67a8e2c..f5c0bb7 100644 --- a/src/test/java/component_construction/builders/CompilerBuilderTests.java +++ b/src/test/java/component_construction/builders/CompilerBuilderTests.java @@ -20,14 +20,14 @@ public void basicCompilerBuilder() { new GeneralLexicalAnalyserFactory(), new CLR1ParserFactory(), new BasicCodeGenFactory(), - new BasicIdentifierGrammar(), - new XToYToXSemantic(), + BasicIdentifierGrammar.produce(), + XToYToXSemantic.produce(), new String[] {" "}, new String[] {"+", "=", ";"}, new String[] {}, new DynamicTokenRegex[] { new DynamicTokenRegex("[A-Za-z]+", "identifier"), - new DynamicTokenRegex("[0-9]+|[0-9]+.[0-9]+", "number") //TODO: Using [0-9]+(\\.[0-9]+)? for all tests woud be better + new DynamicTokenRegex("[0-9]+|[0-9]+.[0-9]+", "number") //TODO: Using [0-9]+(\\.[0-9]+)? for all tests would be better } ); @@ -47,8 +47,8 @@ public void nullComponentInputs() { null, new CLR1ParserFactory(), new BasicCodeGenFactory(), - new BasicIdentifierGrammar(), - new XToYToXSemantic(), + BasicIdentifierGrammar.produce(), + XToYToXSemantic.produce(), new String[] {" "}, new String[] {"+", "=", ";"}, new String[] {}, @@ -61,8 +61,8 @@ public void nullComponentInputs() { new GeneralLexicalAnalyserFactory(), null, new BasicCodeGenFactory(), - new BasicIdentifierGrammar(), - new XToYToXSemantic(), + BasicIdentifierGrammar.produce(), + XToYToXSemantic.produce(), new String[] {" "}, new String[] {"+", "=", ";"}, new String[] {}, @@ -75,8 +75,8 @@ public void nullComponentInputs() { new GeneralLexicalAnalyserFactory(), new CLR1ParserFactory(), null, - new BasicIdentifierGrammar(), - new XToYToXSemantic(), + BasicIdentifierGrammar.produce(), + XToYToXSemantic.produce(), new String[] {" "}, new String[] {"+", "=", ";"}, new String[] {}, @@ -90,7 +90,7 @@ public void nullComponentInputs() { new CLR1ParserFactory(), new BasicCodeGenFactory(), null, - new XToYToXSemantic(), + XToYToXSemantic.produce(), new String[] {" "}, new String[] {"+", "=", ";"}, new String[] {}, @@ -103,7 +103,7 @@ public void nullComponentInputs() { new GeneralLexicalAnalyserFactory(), new CLR1ParserFactory(), new BasicCodeGenFactory(), - new BasicIdentifierGrammar(), + BasicIdentifierGrammar.produce(), null, new String[] {" "}, new String[] {"+", "=", ";"}, @@ -129,8 +129,8 @@ public void nullLexicalInputs() { new GeneralLexicalAnalyserFactory(), new CLR1ParserFactory(), new BasicCodeGenFactory(), - new BasicIdentifierGrammar(), - new XToYToXSemantic(), + BasicIdentifierGrammar.produce(), + XToYToXSemantic.produce(), null, null, null, diff --git a/src/test/java/component_construction/builders/grammar_objects/GrammarBuilderTests.java b/src/test/java/component_construction/builders/grammar_objects/GrammarBuilderTests.java new file mode 100644 index 0000000..9494ffa --- /dev/null +++ b/src/test/java/component_construction/builders/grammar_objects/GrammarBuilderTests.java @@ -0,0 +1,78 @@ +package component_construction.builders.grammar_objects; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +import java.util.*; +import grammar_objects.*; +import component_construction.builders.grammar_objects.GrammarBuilder.MissingSentinalException; + +public class GrammarBuilderTests { + + @Test + public void basicTwoRuleGrammar() { + GrammarBuilder builder = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new NonTerminal("B"), + new Token("a") + })) + .addRule(new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + })); + + + Grammar actual = builder.produceGrammar(); + + + Grammar expected = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new NonTerminal("B"), + new Token("a") + }), + new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + }) + ), + new NonTerminal("A") + ); + + assertEquals(expected, actual); + } + + @Test + public void missingSentinal() { + GrammarBuilder builder = new GrammarBuilder() + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new NonTerminal("B"), + new Token("a") + })) + .addRule(new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + })); + + + assertThrows(MissingSentinalException.class, () -> builder.produceGrammar()); + } +} diff --git a/src/test/java/component_construction/builders/grammar_objects/RuleConvertorBuilderTests.java b/src/test/java/component_construction/builders/grammar_objects/RuleConvertorBuilderTests.java new file mode 100644 index 0000000..f7ff5c0 --- /dev/null +++ b/src/test/java/component_construction/builders/grammar_objects/RuleConvertorBuilderTests.java @@ -0,0 +1,162 @@ +package component_construction.builders.grammar_objects; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.*; +import org.junit.jupiter.api.Test; +import code_generation.Generator; +import component_construction.ParameterError; +import grammar_objects.*; +import grammar_objects.RuleConvertor.IncompleteConversionsException; +import helper_objects.NullableTuple; + +public class RuleConvertorBuilderTests { + + @Test + public void standardUsage() { + List rules = List.of( + new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a"), + new NonTerminal("B") + } + ), + new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + } + ) + ); + + Grammar grammar = new GrammarBuilder() + .addRules(rules) + .setSentinal(new NonTerminal("A")) + .produceGrammar(); + + Map conversions = new HashMap<>(); + conversions.put(rules.get(0), (elements) -> "A"); + conversions.put(rules.get(1), (elements) -> "B"); + + NullableTuple bookends = new NullableTuple<>("start", "end"); + + + RuleConvertor actual = new RuleConvertorBuilder(grammar) + .setConversions(conversions) + .setBookends(bookends) + .produceConvertor(); + + + RuleConvertor expected = new RuleConvertor(grammar, conversions, bookends); + + assertEquals(expected, actual); + } + + @Test + public void noGrammar() { + List rules = List.of( + new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a"), + new NonTerminal("B") + } + ), + new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + } + ) + ); + + Map conversions = new HashMap<>(); + conversions.put(rules.get(0), (elements) -> "A"); + conversions.put(rules.get(1), (elements) -> "B"); + + NullableTuple bookends = new NullableTuple<>("start", "end"); + + + assertThrows(ParameterError.class, () ->new RuleConvertorBuilder(null) + .setConversions(conversions) + .setBookends(bookends) + .produceConvertor() + ); + } + + @Test + public void noConversions() { + List rules = List.of( + new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a"), + new NonTerminal("B") + } + ), + new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + } + ) + ); + + Grammar grammar = new GrammarBuilder() + .addRules(rules) + .setSentinal(new NonTerminal("A")) + .produceGrammar(); + + Map conversions = new HashMap<>(); + conversions.put(rules.get(0), (elements) -> "A"); + conversions.put(rules.get(1), (elements) -> "B"); + + NullableTuple bookends = new NullableTuple<>("start", "end"); + + + assertThrows(IncompleteConversionsException.class, () -> new RuleConvertorBuilder(grammar) + .setBookends(bookends) + .produceConvertor() + ); + } + + @Test + public void noBookends() { + List rules = List.of( + new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a"), + new NonTerminal("B") + } + ), + new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + } + ) + ); + + Grammar grammar = new GrammarBuilder() + .addRules(rules) + .setSentinal(new NonTerminal("A")) + .produceGrammar(); + + Map conversions = new HashMap<>(); + conversions.put(rules.get(0), (elements) -> "A"); + conversions.put(rules.get(1), (elements) -> "B"); + + + RuleConvertor actual = new RuleConvertorBuilder(grammar) + .setConversions(conversions) + .produceConvertor(); + + + RuleConvertor expected = new RuleConvertor(grammar, conversions); + + assertEquals(expected, actual); + } + +} diff --git a/src/test/java/component_construction/factories/grammar/BNFConvertorTests.java b/src/test/java/component_construction/factories/grammar/BNFConvertorTests.java index 2a7eddd..bad9b2b 100644 --- a/src/test/java/component_construction/factories/grammar/BNFConvertorTests.java +++ b/src/test/java/component_construction/factories/grammar/BNFConvertorTests.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; +import component_construction.builders.grammar_objects.GrammarBuilder; import component_construction.factories.grammar.BNFConvertor.InvalidEscapeCharacterException; import grammar_objects.*; @@ -13,32 +14,15 @@ public void singleRule() { A -> b """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -55,48 +39,27 @@ public void multipleRules() { C -> d """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("c")); - tokenOrganiser.addToken(new Token("d")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("C")); + )) + .addRule(new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("c") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("B"), - new LexicalElement[] { - new Token("c") - } - )); - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("C"), - new LexicalElement[] { - new Token("d") - } - )); + )) + .addRule(new ProductionRule( + new NonTerminal("C"), + new LexicalElement[] { + new Token("d") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -111,34 +74,16 @@ public void multipleTokens() { A -> a b """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("a"), - new Token("b") - } - )); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a"), + new Token("b") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -153,34 +98,16 @@ public void nonTerminalInRule() { A -> N b """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new NonTerminal("N"), + new Token("b") } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("N")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new NonTerminal("N"), - new Token("b") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -195,34 +122,16 @@ public void taggedTokens() { A -> t:b t:B """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("B")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b"), + new Token("B") } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b"), - new Token("B") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -239,50 +148,28 @@ public void taggedNonTerminals() { B -> d """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("c")); - tokenOrganiser.addToken(new Token("d")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("a")) + .addRule(new ProductionRule( + new NonTerminal("a"), + new LexicalElement[] { + new NonTerminal("b"), + new NonTerminal("B") } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("a"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("a")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("b")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); + )) + .addRule(new ProductionRule( + new NonTerminal("b"), + new LexicalElement[] { + new Token("c") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("a"), - new LexicalElement[] { - new NonTerminal("b"), - new NonTerminal("B") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("b"), - new LexicalElement[] { - new Token("c") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("B"), - new LexicalElement[] { - new Token("d") - } - )); + )) + .addRule(new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("d") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -297,32 +184,15 @@ public void tagAsTokenPrefix() { A -> t:t:b """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("t:b")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("t:b") } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("t:b") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -338,40 +208,21 @@ public void tagAsNonTerminalPrefix() { n:n:B -> c """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("c")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new NonTerminal("n:B"), } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("n:B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new NonTerminal("n:B"), - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("n:B"), - new LexicalElement[] { - new Token("c") - } - )); + )) + .addRule(new ProductionRule( + new NonTerminal("n:B"), + new LexicalElement[] { + new Token("c") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -386,36 +237,17 @@ public void escapedSpaceTokens() { A -> \\ b\\ t:\\ \\\s """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token(" ")); - tokenOrganiser.addToken(new Token("b ")); - tokenOrganiser.addToken(new Token(" ")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token(" "), + new Token("b "), + new Token(" ") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token(" "), - new Token("b "), - new Token(" ") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -432,50 +264,28 @@ public void escapedSpaceNonTerminal() { n:C\\ C -> b """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal(" A"); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal(" A")) + .addRule(new ProductionRule( + new NonTerminal(" A"), + new LexicalElement[] { + new NonTerminal("B "), + new NonTerminal("C C") } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal(" A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B ")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("C C")); + )) + .addRule(new ProductionRule( + new NonTerminal("B "), + new LexicalElement[] { + new Token("a") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal(" A"), - new LexicalElement[] { - new NonTerminal("B "), - new NonTerminal("C C") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("B "), - new LexicalElement[] { - new Token("a") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("C C"), - new LexicalElement[] { - new Token("b") - } - )); + )) + .addRule(new ProductionRule( + new NonTerminal("C C"), + new LexicalElement[] { + new Token("b") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -490,36 +300,17 @@ public void escapedNewlineTokens() { A -> \\\n b\\\n t:\\\n\\\n """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("\n")); - tokenOrganiser.addToken(new Token("b\n")); - tokenOrganiser.addToken(new Token("\n\n")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("\n"), + new Token("b\n"), + new Token("\n\n") } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("\n"), - new Token("b\n"), - new Token("\n\n") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -536,51 +327,28 @@ public void escapedNewlineNonTerminal() { n:C\\\nC -> b """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("\nA"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("\nA")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B\n\n")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("C\nC")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("\nA"), - new LexicalElement[] { - new NonTerminal("B\n\n"), - new NonTerminal("C\nC") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("B\n\n"), - new LexicalElement[] { - new Token("a") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("C\nC"), - new LexicalElement[] { - new Token("b") - } - )); - } - }; - + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("\nA")) + .addRule(new ProductionRule( + new NonTerminal("\nA"), + new LexicalElement[] { + new NonTerminal("B\n\n"), + new NonTerminal("C\nC") + } + )) + .addRule(new ProductionRule( + new NonTerminal("B\n\n"), + new LexicalElement[] { + new Token("a") + } + )) + .addRule(new ProductionRule( + new NonTerminal("C\nC"), + new LexicalElement[] { + new Token("b") + } + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -594,36 +362,17 @@ public void arrowInTokens() { A -> -> t:a-> \\ ->\\\s """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("->")); - tokenOrganiser.addToken(new Token("a->")); - tokenOrganiser.addToken(new Token(" -> ")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("->"), + new Token("a->"), + new Token(" -> ") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("->"), - new Token("a->"), - new Token(" -> ") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -639,43 +388,23 @@ public void arrowInNonTerminals() { n:N-> -> c """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("c")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("->A"); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("->A")) + .addRule(new ProductionRule( + new NonTerminal("->A"), + new LexicalElement[] { + new NonTerminal("N->"), + new NonTerminal("N->"), + new Token("b") } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("->A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("N->")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("->A"), - new LexicalElement[] { - new NonTerminal("N->"), - new NonTerminal("N->"), - new Token("b") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("N->"), - new LexicalElement[] { - new Token("c") - } - )); + )) + .addRule(new ProductionRule( + new NonTerminal("N->"), + new LexicalElement[] { + new Token("c") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -692,53 +421,31 @@ public void emptyTokenUsage() { C -> \\e """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new EmptyToken()); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("C")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new NonTerminal("B"), - new NonTerminal("C"), - new EmptyToken(), - new Token("b"), - new EmptyToken() - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("B"), - new LexicalElement[] { - new EmptyToken() - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("C"), - new LexicalElement[] { - new EmptyToken() - } - )); - } - }; + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new NonTerminal("B"), + new NonTerminal("C"), + new EmptyToken(), + new Token("b"), + new EmptyToken() + } + )) + .addRule(new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new EmptyToken() + } + )) + .addRule(new ProductionRule( + new NonTerminal("C"), + new LexicalElement[] { + new EmptyToken() + } + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -753,32 +460,15 @@ public void escapedSpaceBeforeArrow() { A\\ -> b """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A "); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A ")) + .addRule(new ProductionRule( + new NonTerminal("A "), + new LexicalElement[] { + new Token("b") } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A ")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A "), - new LexicalElement[] { - new Token("b") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -793,40 +483,21 @@ public void singleNonTerminalOr() { A -> b | c """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("c")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("c") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("c") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -841,36 +512,17 @@ public void singleNonTerminalEscapedOr() { A -> b \\| c """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("|")); - tokenOrganiser.addToken(new Token("c")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b"), - new Token("|"), - new Token("c") - } - )); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b"), + new Token("|"), + new Token("c") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -905,40 +557,21 @@ public void singleNonTerminalAlternativesWithoutOr() { A -> c """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("c")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("c") - } - )); + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("c") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -954,40 +587,21 @@ public void singleNonTerminalAlternativesMultiLine() { | c """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("c")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("c") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("c") - } - )); - } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -1005,56 +619,33 @@ public void singleNonTerminalAlternativesMultiLineVariableSpacing() { \t| e """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("c")); - tokenOrganiser.addToken(new Token("d")); - tokenOrganiser.addToken(new Token("e")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("c") } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("d") } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("c") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("d") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("e") - } - )); + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("e") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -1071,48 +662,27 @@ public void singleNonTerminalAlternativesEmptyLine() { | c """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new EmptyToken()); - tokenOrganiser.addToken(new Token("c")); + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new EmptyToken() } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new EmptyToken() - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("c") - } - )); + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("c") } - }; + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); @@ -1127,48 +697,27 @@ public void singleNonTerminalEmptyInlineOr() { A -> b | | c """; - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new EmptyToken()); - tokenOrganiser.addToken(new Token("c")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new EmptyToken() - } - )); - - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("c") - } - )); - } - }; + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") + } + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new EmptyToken() + } + )) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("c") + } + )) + .produceGrammar(); Grammar producedGrammar = new BNFConvertor(bnf).produceGrammar(); diff --git a/src/test/java/grammar_objects/GrammarTests.java b/src/test/java/grammar_objects/GrammarTests.java index 31a8b05..77baa6a 100644 --- a/src/test/java/grammar_objects/GrammarTests.java +++ b/src/test/java/grammar_objects/GrammarTests.java @@ -3,559 +3,422 @@ import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; +import java.util.*; public class GrammarTests { @Test public void fullEquality() { - Grammar grammar1 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + Grammar grammar1 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; - - Grammar grammar2 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + ) + ), + new NonTerminal("A") + ); + + Grammar grammar2 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; + ) + ), + new NonTerminal("A") + ); assertEquals(grammar1, grammar2); } @Test public void lessTokens() { - Grammar grammar1 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + Grammar grammar1 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; - - Grammar grammar2 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + ) + ), + new NonTerminal("A") + ); + + Grammar grammar2 = new Grammar( + Set.of( + new Token("a") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; + ) + ), + new NonTerminal("A") + ); assertNotEquals(grammar1, grammar2); } @Test public void moreTokens() { - Grammar grammar1 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + Grammar grammar1 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; - - Grammar grammar2 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - tokenOrganiser.addToken(new Token("c")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + ) + ), + new NonTerminal("A") + ); + + Grammar grammar2 = new Grammar( + Set.of( + new Token("a"), + new Token("b"), + new Token("c") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; + ) + ), + new NonTerminal("A") + ); assertNotEquals(grammar1, grammar2); } @Test public void lessNonTerminals() { - Grammar grammar1 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + Grammar grammar1 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; - - Grammar grammar2 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + ) + ), + new NonTerminal("A") + ); + + Grammar grammar2 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; + ) + ), + new NonTerminal("A") + ); assertNotEquals(grammar1, grammar2); } @Test public void moreNonTerminals() { - Grammar grammar1 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + Grammar grammar1 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; - - Grammar grammar2 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("C")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + ) + ), + new NonTerminal("A") + ); + + Grammar grammar2 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B"), + new NonTerminal("C") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; + ) + ), + new NonTerminal("A") + ); assertNotEquals(grammar1, grammar2); } @Test public void lessRules() { - Grammar grammar1 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + Grammar grammar1 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; - - Grammar grammar2 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + ) + ), + new NonTerminal("A") + ); + + Grammar grammar2 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - } - }; + ) + ), + new NonTerminal("A") + ); assertNotEquals(grammar1, grammar2); } @Test public void moreRules() { - Grammar grammar1 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + Grammar grammar1 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - } - }; - - Grammar grammar2 = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("a")); - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - nonTerminalOrganiser.addNonTerminal(new NonTerminal("B")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( + ) + ), + new NonTerminal("A") + ); + + Grammar grammar2 = new Grammar( + Set.of( + new Token("a"), + new Token("b") + ), + Set.of( + new NonTerminal("A"), + new NonTerminal("B") + ), + List.of( + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("a"), new NonTerminal("B") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("B"), new LexicalElement[] { new Token("b") } - )); - - ruleOrganiser.addRule(new ProductionRule( + ), + new ProductionRule( new NonTerminal("A"), new LexicalElement[] { new Token("c") } - )); - } - }; + ) + ), + new NonTerminal("A") + ); assertNotEquals(grammar1, grammar2); } + + //TODO: Test with null or empty values } diff --git a/src/test/java/grammar_objects/ProductionRuleTest.java b/src/test/java/grammar_objects/ProductionRuleTest.java new file mode 100644 index 0000000..201c6ee --- /dev/null +++ b/src/test/java/grammar_objects/ProductionRuleTest.java @@ -0,0 +1,101 @@ +package grammar_objects; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class ProductionRuleTest { + + @Test + public void equality() { + ProductionRule original = new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") + }); + + ProductionRule identical = new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") + }); + ProductionRule nullNonTerminal = new ProductionRule( + null, + new LexicalElement[] { + new Token("b") + }); + ProductionRule nullProductionSequence = new ProductionRule( + new NonTerminal("A"), + null + ); + ProductionRule incorrectNonTerminal = new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + }); + ProductionRule incorrectProductionSequence = new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a") + }); + ProductionRule incorrectProductionSequence_usingNonTerminal = new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new NonTerminal("b") + }); + + assertEquals(original, identical); + assertNotEquals(original, nullNonTerminal); + assertNotEquals(original, nullProductionSequence); + assertNotEquals(original, incorrectNonTerminal); + assertNotEquals(original, incorrectProductionSequence); + assertNotEquals(original, incorrectProductionSequence_usingNonTerminal); + } + + @Test + public void reversedEquality() { + ProductionRule original = new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") + }); + + ProductionRule identical = new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") + }); + ProductionRule nullNonTerminal = new ProductionRule( + null, + new LexicalElement[] { + new Token("b") + }); + ProductionRule nullProductionSequence = new ProductionRule( + new NonTerminal("A"), + null + ); + ProductionRule incorrectNonTerminal = new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + }); + ProductionRule incorrectProductionSequence = new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a") + }); + ProductionRule incorrectProductionSequence_usingNonTerminal = new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new NonTerminal("b") + }); + + assertEquals(identical, original); + assertNotEquals(nullNonTerminal, original); + assertNotEquals(nullProductionSequence, original); + assertNotEquals(incorrectNonTerminal, original); + assertNotEquals(incorrectProductionSequence, original); + assertNotEquals(incorrectProductionSequence_usingNonTerminal, original); + } + +} diff --git a/src/test/java/grammar_objects/RuleConvertorTests.java b/src/test/java/grammar_objects/RuleConvertorTests.java new file mode 100644 index 0000000..cf6eed4 --- /dev/null +++ b/src/test/java/grammar_objects/RuleConvertorTests.java @@ -0,0 +1,128 @@ +package grammar_objects; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.*; + +import org.junit.jupiter.api.Test; + +import code_generation.Generator; +import component_construction.builders.grammar_objects.GrammarBuilder; +import grammar_objects.RuleConvertor.IncompleteConversionsException; +import helper_objects.NullableTuple; + +public class RuleConvertorTests { + + @Test + public void normalUsage_defaultRootRule() { + List rules = List.of( + new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a"), + new NonTerminal("B") + } + ), + new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + } + ) + ); + + Grammar grammar = new GrammarBuilder() + .addRules(rules) + .setSentinal(new NonTerminal("A")) + .produceGrammar(); + + Map conversions = new HashMap<>(); + conversions.put(rules.get(0), (elements) -> "A"); + conversions.put(rules.get(1), (elements) -> "B"); + + NullableTuple bookends = new NullableTuple<>("start", "end"); + + + RuleConvertor actual = new RuleConvertor(grammar, conversions, bookends); + + + assertEquals(bookends, actual.bookends()); + assertEquals(conversions, actual.conversions()); + assertEquals(grammar, actual.grammar()); + } + + @Test + public void normalUsage_definedRootRule() { + List rules = List.of( + new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a"), + new NonTerminal("B") + } + ), + new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + } + ) + ); + + Grammar grammar = new GrammarBuilder() + .addRules(rules) + .setSentinal(new NonTerminal("A")) + .produceGrammar(); + + Generator rootConvertor = (elements) -> "ROOT"; + + Map conversions = new HashMap<>(); + conversions.put(RuleConvertor.ROOT_RULE, rootConvertor); + conversions.put(rules.get(0), (elements) -> "A"); + conversions.put(rules.get(1), (elements) -> "B"); + + NullableTuple bookends = new NullableTuple<>("start", "end"); + + + RuleConvertor actual = new RuleConvertor(grammar, conversions, bookends); + + + assertEquals(bookends, actual.bookends()); + assertEquals(conversions, actual.conversions()); + assertEquals(grammar, actual.grammar()); + assertEquals(rootConvertor, actual.conversions().get(RuleConvertor.ROOT_RULE)); + } + + @Test + public void tooFewConversions() { + List rules = List.of( + new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("a"), + new NonTerminal("B") + } + ), + new ProductionRule( + new NonTerminal("B"), + new LexicalElement[] { + new Token("b") + } + ) + ); + + Grammar grammar = new GrammarBuilder() + .addRules(rules) + .setSentinal(new NonTerminal("A")) + .produceGrammar(); + + + Map conversions = new HashMap<>(); + conversions.put(rules.get(0), (elements) -> "A"); + + NullableTuple bookends = new NullableTuple<>("start", "end"); + + + assertThrows(IncompleteConversionsException.class, () -> new RuleConvertor(grammar, conversions, bookends)); + } +} diff --git a/src/test/java/helper_objects/GrammarTests.java b/src/test/java/helper_objects/GrammarTests.java index 44b33fa..75654b4 100644 --- a/src/test/java/helper_objects/GrammarTests.java +++ b/src/test/java/helper_objects/GrammarTests.java @@ -3,65 +3,33 @@ import org.junit.jupiter.api.Test; +import component_construction.builders.grammar_objects.GrammarBuilder; import grammar_objects.*; public class GrammarTests { @Test public void equality() { - Grammar expectedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - } - }; + Grammar expectedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") + } + )) + .produceGrammar(); + + Grammar producedGrammar = new GrammarBuilder() + .setSentinal(new NonTerminal("A")) + .addRule(new ProductionRule( + new NonTerminal("A"), + new LexicalElement[] { + new Token("b") + } + )) + .produceGrammar(); - Grammar producedGrammar = new Grammar() { - @Override - protected void setUpTokens(TokenOrganiser tokenOrganiser) { - tokenOrganiser.addToken(new Token("b")); - } - - @Override - protected NonTerminal setUpSentinal() { - return new NonTerminal("A"); - } - - @Override - protected void setUpNonTerminals(NonTerminalOrganiser nonTerminalOrganiser) { - nonTerminalOrganiser.addNonTerminal(new NonTerminal("A")); - } - - @Override - protected void setUpProductionRules(RuleOrganiser ruleOrganiser) { - ruleOrganiser.addRule(new ProductionRule( - new NonTerminal("A"), - new LexicalElement[] { - new Token("b") - } - )); - } - }; assertEquals(expectedGrammar, producedGrammar); } diff --git a/src/test/java/semantic_analysis/TypeCheckerTests.java b/src/test/java/semantic_analysis/TypeCheckerTests.java index 6248a7e..23c54d5 100644 --- a/src/test/java/semantic_analysis/TypeCheckerTests.java +++ b/src/test/java/semantic_analysis/TypeCheckerTests.java @@ -17,7 +17,7 @@ public void XToYToXGeneration() { String language = "Java"; String sentence = "XToYToXSemantic"; TestGrammar grammar = new BasicIdentifierTestGrammar(GrammarType.LR0); - RuleConvertor ruleConvertor = new XToYToXSemantic(); + RuleConvertor ruleConvertor = XToYToXSemantic.produce(); CodeGenerator codeGenerator = new BasicCodeGenerator(ruleConvertor); ParseState rootParseState = grammar.getParseRoot("XToYToXSemantic"); diff --git a/src/test/java/test_aids/TestGrammar.java b/src/test/java/test_aids/TestGrammar.java index 5ce8f43..766fbc3 100644 --- a/src/test/java/test_aids/TestGrammar.java +++ b/src/test/java/test_aids/TestGrammar.java @@ -7,6 +7,8 @@ import syntax_analysis.parsing.ParseState; import test_aids.test_grammars.UnsupportedSentenceException; +//TODO: Rework to use Grammar builder + public abstract class TestGrammar { //TODO allow implementation of grammar interface for propper testing protected Grammar grammar; diff --git a/src/test/java/test_aids/test_grammars/basic_CLR1/BasicCLR1TestGrammar.java b/src/test/java/test_aids/test_grammars/basic_CLR1/BasicCLR1TestGrammar.java index e7ef971..135e2a7 100644 --- a/src/test/java/test_aids/test_grammars/basic_CLR1/BasicCLR1TestGrammar.java +++ b/src/test/java/test_aids/test_grammars/basic_CLR1/BasicCLR1TestGrammar.java @@ -15,7 +15,7 @@ public BasicCLR1TestGrammar(GrammarType type) { @Override protected Grammar setUpGrammar(GrammarType type) { - return new BasicCLR1Grammar(); + return BasicCLR1Grammar.produce(); } @Override diff --git a/src/test/java/test_aids/test_grammars/basic_SLR1/BasicSLR1TestGrammar.java b/src/test/java/test_aids/test_grammars/basic_SLR1/BasicSLR1TestGrammar.java index 10e0b82..a40bb02 100644 --- a/src/test/java/test_aids/test_grammars/basic_SLR1/BasicSLR1TestGrammar.java +++ b/src/test/java/test_aids/test_grammars/basic_SLR1/BasicSLR1TestGrammar.java @@ -21,7 +21,7 @@ public BasicSLR1TestGrammar(GrammarType type) { @Override protected Grammar setUpGrammar(GrammarType type) { - return new BasicSLR1Grammar(); + return BasicSLR1Grammar.produce(); } @Override diff --git a/src/test/java/test_aids/test_grammars/basic_identifier/BasicIdentifierTestGrammar.java b/src/test/java/test_aids/test_grammars/basic_identifier/BasicIdentifierTestGrammar.java index 137a17f..799ab5d 100644 --- a/src/test/java/test_aids/test_grammars/basic_identifier/BasicIdentifierTestGrammar.java +++ b/src/test/java/test_aids/test_grammars/basic_identifier/BasicIdentifierTestGrammar.java @@ -24,7 +24,7 @@ public BasicIdentifierTestGrammar(GrammarType type) { @Override protected Grammar setUpGrammar(GrammarType type) { - return new BasicIdentifierGrammar(); + return BasicIdentifierGrammar.produce(); } @Override @@ -482,8 +482,8 @@ private ParseState parseTree0() { protected void setUpRuleConvertors(GrammarType type, Map> ruleConvertorMap) { ruleConvertorMap.put("Java", new HashMap<>()); - ruleConvertorMap.get("Java").put("XToYToX", new XToYToX()); - ruleConvertorMap.get("Java").put("XToYToXSemantic", new XToYToXSemantic()); + ruleConvertorMap.get("Java").put("XToYToX", XToYToX.produce()); + ruleConvertorMap.get("Java").put("XToYToXSemantic", XToYToXSemantic.produce()); } @Override diff --git a/src/test/java/test_aids/test_grammars/self_referential/SelfReferentialTestGrammar.java b/src/test/java/test_aids/test_grammars/self_referential/SelfReferentialTestGrammar.java index 785843f..0858295 100644 --- a/src/test/java/test_aids/test_grammars/self_referential/SelfReferentialTestGrammar.java +++ b/src/test/java/test_aids/test_grammars/self_referential/SelfReferentialTestGrammar.java @@ -22,7 +22,7 @@ public SelfReferentialTestGrammar(GrammarType type) { @Override protected Grammar setUpGrammar(GrammarType type) { - return new SelfReferentialGrammar(); + return SelfReferentialGrammar.produce(); } @Override diff --git a/src/test/java/test_aids/test_grammars/small_grammar/SmallTestGrammar.java b/src/test/java/test_aids/test_grammars/small_grammar/SmallTestGrammar.java index d5368ae..66b24f7 100644 --- a/src/test/java/test_aids/test_grammars/small_grammar/SmallTestGrammar.java +++ b/src/test/java/test_aids/test_grammars/small_grammar/SmallTestGrammar.java @@ -25,7 +25,7 @@ public SmallTestGrammar(GrammarType type) { @Override protected Grammar setUpGrammar(GrammarType type) { - return new SmallGrammar(); + return SmallGrammar.produce(); } @Override @@ -384,14 +384,14 @@ private ParseState parseTree3() { protected void setUpRuleConvertors(GrammarType type, Map> ruleConvertorMap) { ruleConvertorMap.put("Java", new HashMap<>()); - ruleConvertorMap.get("Java").put("1+0*1", new OpZtO()); - ruleConvertorMap.get("Java").put("1", new One()); - ruleConvertorMap.get("Java").put("emptyReduce", new EmptyReduce()); - ruleConvertorMap.get("Java").put("1+0*1MissingReduction", new OpZtOMissingReduction()); + ruleConvertorMap.get("Java").put("1+0*1", OpZtO.produce()); + ruleConvertorMap.get("Java").put("1", One.produce()); + ruleConvertorMap.get("Java").put("emptyReduce", EmptyReduce.produce()); + ruleConvertorMap.get("Java").put("1+0*1MissingReduction", OpZtOMissingReduction.produce()); ruleConvertorMap.put("C", new HashMap<>()); - ruleConvertorMap.get("C").put("1+0*1", new COpZtO()); + ruleConvertorMap.get("C").put("1+0*1", COpZtO.produce()); } @Override