add grammer assignment from WCC CS 145 Spring 2019.
This commit is contained in:
parent
46f17fac95
commit
8018490bbd
|
@ -0,0 +1,63 @@
|
||||||
|
// Stuart Reges
|
||||||
|
// 3/10/04
|
||||||
|
//
|
||||||
|
// GrammarMain contains a main program that prompts a user for the name of a
|
||||||
|
// grammar file and then gives the user the opportunity to generate random
|
||||||
|
// versions of various elements of the grammar.
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class GrammarMain {
|
||||||
|
public static void main(String[] args) throws FileNotFoundException {
|
||||||
|
Scanner console = new Scanner(System.in);
|
||||||
|
System.out.println("Welcome to the cs145 random sentence generator.");
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
// open grammar file
|
||||||
|
System.out.print("What is the name of the grammar file? ");
|
||||||
|
String fileName = console.nextLine();
|
||||||
|
Scanner input = new Scanner(new File(fileName));
|
||||||
|
|
||||||
|
// read the grammar file and construct the grammar solver
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
while (input.hasNextLine())
|
||||||
|
grammar.add(input.nextLine());
|
||||||
|
GrammarSolver solver =
|
||||||
|
new GrammarSolver(Collections.unmodifiableList(grammar));
|
||||||
|
|
||||||
|
showResults(console, solver);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pre : console open for console reading, solver initialized
|
||||||
|
// post: allows the user to repeatedly pick a grammar element to generate
|
||||||
|
public static void showResults(Scanner console, GrammarSolver solver) {
|
||||||
|
for(;;) {
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Available symbols to generate are:");
|
||||||
|
System.out.println(solver.getSymbols());
|
||||||
|
System.out.print("What do you want generated (return to quit)? ");
|
||||||
|
String target = console.nextLine();
|
||||||
|
if (target.length() == 0)
|
||||||
|
break;
|
||||||
|
if (!solver.grammarContains(target))
|
||||||
|
System.out.println("Illegal symbol");
|
||||||
|
else {
|
||||||
|
System.out.print("How many do you want me to generate? ");
|
||||||
|
if (!console.hasNextInt())
|
||||||
|
System.out.println("that's not an integer");
|
||||||
|
else {
|
||||||
|
int number = console.nextInt();
|
||||||
|
if (number < 0)
|
||||||
|
System.out.println("no negatives allowed");
|
||||||
|
else {
|
||||||
|
String[] answers = solver.generate(target, number);
|
||||||
|
for (int i = 0; i < number; i++)
|
||||||
|
System.out.println(answers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.nextLine(); // to position to next line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Matt Jensen
|
||||||
|
* CS145 - Lab 5
|
||||||
|
* 5/30/19
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class GrammarSolver {
|
||||||
|
|
||||||
|
private Map<String, List<String>> grammarMap;
|
||||||
|
private List<String> grammarList;
|
||||||
|
|
||||||
|
// sets grammar of object.
|
||||||
|
public GrammarSolver(List<String> grammarList) {
|
||||||
|
this.grammarList = grammarList;
|
||||||
|
this.grammarMap = new TreeMap<String, List<String>>();
|
||||||
|
|
||||||
|
// add all lines to grammer.
|
||||||
|
for(String entry : grammarList) {
|
||||||
|
if( this.isValidEntry(entry) ) { // throws exception if illegal.
|
||||||
|
this.addEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Public Methods
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// publicly evaluate grammar
|
||||||
|
public String[] generate(String symbol, int times) {
|
||||||
|
String[] result = new String[times];
|
||||||
|
for( int i = 0; i < result.length; i++) {
|
||||||
|
result[i] = this.generate(symbol);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// map of available grammars.
|
||||||
|
public Map<String, List<String>> getGrammars() {
|
||||||
|
return this.grammarMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// list of grammars.
|
||||||
|
public List<String> getGrammarList() {
|
||||||
|
return this.grammarList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// all the keys/nonterminals of the grammer
|
||||||
|
public String getSymbols() {
|
||||||
|
return this.getGrammars().keySet().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// grammer contains a terminal key.
|
||||||
|
public boolean grammarContains(String key) {
|
||||||
|
return this.getGrammars().keySet().contains(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Private Helper Methods
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// recursively evaluate grammar
|
||||||
|
private String generate(String symbol) {
|
||||||
|
String result = "";
|
||||||
|
Set<String> symbols = this.getGrammars().keySet();
|
||||||
|
|
||||||
|
// base case
|
||||||
|
if(this.grammarContains(symbol) != true ) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String rule = this.getRandomTerminal(symbol);
|
||||||
|
|
||||||
|
// apply the rules
|
||||||
|
for(String subRule : GrammarSolver.splitRule(rule)){
|
||||||
|
if( ! result.isEmpty()) {
|
||||||
|
result += " "; // keeps leading whitespace off.
|
||||||
|
}
|
||||||
|
if( this.grammarContains(subRule) ) { // test if a subrule is a nonterminal.
|
||||||
|
result += this.generate(subRule); // evaluates nonterminal rule and appends it.
|
||||||
|
} else {
|
||||||
|
result += subRule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// add grammar to grammars.
|
||||||
|
private void addEntry(String entry) {
|
||||||
|
String nonterminal = GrammarSolver.nonTerminal(entry);
|
||||||
|
List<String> rules = GrammarSolver.terminals(entry);
|
||||||
|
this.getGrammars().put(nonterminal, rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
// line of a grammar is valid.
|
||||||
|
private boolean isValidEntry(String entry) {
|
||||||
|
// errors if bad colon count
|
||||||
|
int colonCount = entry.length() - entry.replace(":", "").length();
|
||||||
|
if( colonCount != 1) {
|
||||||
|
throw new IllegalArgumentException("does not contain single colon");
|
||||||
|
}
|
||||||
|
|
||||||
|
// errors if duplicate
|
||||||
|
String nonterminal = GrammarSolver.nonTerminal(entry);
|
||||||
|
if( this.getGrammars().keySet().contains(nonterminal) ) {
|
||||||
|
throw new IllegalArgumentException("duplicate non-terminal detected");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// random element of a non-terminal's rules.
|
||||||
|
private String getRandomTerminal(String symbol) {
|
||||||
|
Random random = new Random();
|
||||||
|
List<String> rules = this.getGrammars().get(symbol);
|
||||||
|
int index = random.nextInt(rules.size());
|
||||||
|
return rules.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Static Methods
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// splits a string of rules at the whitespaces.
|
||||||
|
private static String[] splitRule(String rule) {
|
||||||
|
String[] split = rule.split("[ \t]");
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pre: no whitespace.
|
||||||
|
// pre: non-empty.
|
||||||
|
public static String nonTerminal(String entry) {
|
||||||
|
return entry.substring(0, entry.indexOf(':'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// extracts terminals from a string.
|
||||||
|
public static List<String> terminals(String entry) {
|
||||||
|
List<String> rules = new ArrayList<String>();
|
||||||
|
entry = entry.substring(entry.indexOf(':') + 1, entry.length());
|
||||||
|
String[] exploded = entry.split("\\|");
|
||||||
|
for(int i = 0; i < exploded.length; i++) {
|
||||||
|
rules.add(exploded[i]);
|
||||||
|
}
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,206 @@
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import org.junit.Test;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class GrammarTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMixedNonAndTerminals() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:<b> <c>|<b>");
|
||||||
|
grammar.add("<b>:Test");
|
||||||
|
grammar.add("<c>:");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
String[] result = solver.generate("<a>", 1);
|
||||||
|
String[] expected = new String[1];
|
||||||
|
Arrays.fill(expected, "Test");
|
||||||
|
assertArrayEquals(expected, result);
|
||||||
|
}
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testGenerateNonTermDoesntExist() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test|:Other");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
solver.generate("<b>", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testGenerateTimesInvalid() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test|:Other");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
solver.generate("<a>", 0);
|
||||||
|
solver.generate("<a>", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerate() {
|
||||||
|
String[] expected = new String[2];
|
||||||
|
Arrays.fill(expected, "Test");
|
||||||
|
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
|
||||||
|
String[] result = solver.generate("<a>", 2);
|
||||||
|
assertArrayEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleRulePaths() {
|
||||||
|
String[] expected = new String[3];
|
||||||
|
Arrays.fill(expected, "Test Nest");
|
||||||
|
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:<b> <c>");
|
||||||
|
grammar.add("<b>:Test");
|
||||||
|
grammar.add("<c>:Nest");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
|
||||||
|
String[] result = solver.generate("<a>", 3);
|
||||||
|
assertArrayEquals(expected, result);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testMultipleSymbolsAsRules() {
|
||||||
|
String[] expected = new String[3];
|
||||||
|
Arrays.fill(expected, "Nest Nest");
|
||||||
|
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:<b> <c>");
|
||||||
|
grammar.add("<b>:<c>");
|
||||||
|
grammar.add("<c>:Nest");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
|
||||||
|
String[] result = solver.generate("<a>", 3);
|
||||||
|
assertArrayEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenerateNestedTwice() {
|
||||||
|
String[] expected = new String[3];
|
||||||
|
Arrays.fill(expected, "Nest");
|
||||||
|
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:<b>");
|
||||||
|
grammar.add("<b>:<c>");
|
||||||
|
grammar.add("<c>:Nest");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
|
||||||
|
String[] result = solver.generate("<a>", 3);
|
||||||
|
assertArrayEquals(expected, result);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testGenerateNested() {
|
||||||
|
String[] expected = new String[2];
|
||||||
|
Arrays.fill(expected, "Nest");
|
||||||
|
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:<b>");
|
||||||
|
grammar.add("<b>:Nest");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
|
||||||
|
String[] result = solver.generate("<a>", 2);
|
||||||
|
assertArrayEquals(expected, result);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testGrammarListImmutable() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
String expected = grammar.get(0);
|
||||||
|
String actual = solver.getGrammarList().get(0);
|
||||||
|
assertEquals("got back different than instantiation.", expected, actual);
|
||||||
|
assertArrayEquals("different grammars.", grammar.toArray(), solver.getGrammarList().toArray());
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testGrammarListImmutableWithPipe() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test|Other");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
assertArrayEquals("different grammars.", grammar.toArray(), solver.getGrammarList().toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonTerminalExtract() {
|
||||||
|
String entry = "<a>:Test";
|
||||||
|
String expected = "<a>";
|
||||||
|
String actual = GrammarSolver.nonTerminal(entry);
|
||||||
|
assertEquals("failure - extraction failed", expected, actual);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testRuleExtractContent() {
|
||||||
|
String entry = "<a>:Test";
|
||||||
|
List<String> expected = new ArrayList<String>();
|
||||||
|
expected.add("Test");
|
||||||
|
List<String> actual = GrammarSolver.terminals(entry);
|
||||||
|
assertArrayEquals("failure - rule extraction failed", expected.toArray(), actual.toArray());
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testRuleCount() {
|
||||||
|
String entry = "<a>:Test";
|
||||||
|
List<String> expected = new ArrayList<String>();
|
||||||
|
expected.add("Test");
|
||||||
|
List<String> actual = GrammarSolver.terminals(entry);
|
||||||
|
assertEquals("rule count different", expected.size(), actual.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testNoColon() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("test");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testDuplicateGrammar() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test|Other");
|
||||||
|
grammar.add("<a>:Test|Other");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testGrammarContainsSingleColon() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test|:Other");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGrammarContains() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
assertEquals(true, solver.grammarContains("<a>"));
|
||||||
|
assertEquals(false, solver.grammarContains("a"));
|
||||||
|
assertEquals(false, solver.grammarContains("<b>"));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testGrammarContainsCaseInsensitive() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
assertEquals(true, solver.grammarContains("<a>"));
|
||||||
|
assertEquals(false, solver.grammarContains("<A>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSymbols() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<a>:Test");
|
||||||
|
grammar.add("<b>:Test|Other");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
assertEquals("[<a>, <b>]", solver.getSymbols());
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testGetSymbolsSorted() {
|
||||||
|
List<String> grammar = new ArrayList<String>();
|
||||||
|
grammar.add("<C>:Test|Other");
|
||||||
|
grammar.add("<A>:Test");
|
||||||
|
grammar.add("<b>:Test|Other");
|
||||||
|
GrammarSolver solver = new GrammarSolver(grammar);
|
||||||
|
assertEquals("[<A>, <C>, <b>]", solver.getSymbols());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<s>:<np> <vp>
|
||||||
|
<np>:<dp> <adjp> <n>|<pn>
|
||||||
|
<pn>:John|Jane|Sally|Spot|Fred|Elmo
|
||||||
|
<adjp>:<adj>|<adj> <adjp>
|
||||||
|
<adj>:big|fat|green|wonderful|faulty|subliminal|pretentious
|
||||||
|
<dp>:the|a
|
||||||
|
<n>:dog|cat|man|university|father|mother|child|television
|
||||||
|
<vp>:<tv> <np>|<iv>
|
||||||
|
<tv>:hit|honored|kissed|helped
|
||||||
|
<iv>:died|collapsed|laughed|wept
|
|
@ -0,0 +1,5 @@
|
||||||
|
E: T | E OP T
|
||||||
|
T: x | y | 42 | 0 | 1 | 92 | ( E ) | F1 ( E ) | - T | F2 ( E , E )
|
||||||
|
OP: + | - | * | % | /
|
||||||
|
F1: sin | cos| tan |sqrt | abs
|
||||||
|
F2:max |min | pow
|
Binary file not shown.
After Width: | Height: | Size: 339 KiB |
Loading…
Reference in New Issue