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