This repository was archived by the owner on Mar 30, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRandomPhraseGenerator.java
127 lines (108 loc) · 4.06 KB
/
RandomPhraseGenerator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package comprehensive;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Random;
/**
* This class contains a method for generating random phrases based of a
* formatted input grammar file.
*
* @author Paul Nuffer, and Nils Streedain
* @version April 27, 2021
*/
public class RandomPhraseGenerator {
HashMap<String, ArrayList<String>> nonTerminals;
Random rng;
BufferedReader reader;
/**
* Main method for creating a phrase generator and generating a number of
* phrases based of input arguments. This is for use when calling from terminal
* or using run configurations in Eclipse.
*
* @param args - First argument is the input grammar file, second is the number
* of phrases to generate
*/
public static void main(String[] args) {
// Creates a new phrase generator, parsed from the input file
RandomPhraseGenerator phraseGenerator = new RandomPhraseGenerator(args[0]);
// A StringBuilder is used to allow for efficiently using only one print
StringBuilder output = new StringBuilder();
// Loops once for each phrase that needs to be generated and adds it to a new
// line in the StringBuilder
for (int i = 0; i < Integer.parseInt(args[1]); i++)
output.append(phraseGenerator.generatePhrase() + "\n");
// Single print statement to print the output
System.out.println(output);
}
/**
* Constructor used for creating a new phrase generator object and then parsing
* an input file into that object.
*
* @param filename - Input file to parse
*/
public RandomPhraseGenerator(String filename) {
// Creates a HashMap instance to parse the data into
nonTerminals = new HashMap<>();
rng = new Random();
// Standard try-catch for a FileReader nested in a BufferedReader
try {
// FileReader nested in a BufferedReader is used because it is more efficient
// and is specifically meant for parsing only strings which fits this use case
reader = new BufferedReader(new FileReader(filename));
// curr is used to keep track of the current line being read in the file
String curr;
// Loops over each line in the input file
while ((curr = reader.readLine()) != null) {
// Skips over anything outside a curly bracket
if (curr.equals("{")) {
// Saves the first line after "{" to be used as they key (non-terminal name)
String key = reader.readLine();
// Creates an ArrayList of Strings (Production Rules) to be used as the value
ArrayList<String> prodRules = new ArrayList<>();
// Adds each line after the name to the production rules until "}" is reached
while (!(curr = reader.readLine()).equals("}"))
prodRules.add(curr);
// Adds the given non-terminal definition to the HashMap
nonTerminals.put(key, prodRules);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException f) {
f.printStackTrace();
}
}
}
/**
* Public method to generate a single phrase given a phraseGenerator object of a
* parsed input file.
*
* @return - Generated Phrase
*/
public StringBuilder generatePhrase() {
StringBuilder nonTerminal = new StringBuilder("<start>");
// Increment over the whole string
for (int start = 0; start < nonTerminal.length(); start++) {
// Gets the index of the beginning of the first nonterminal
if (nonTerminal.charAt(start) == '<') {
int end = start + 1;
// Gets the end index for the current nonterminal
while (nonTerminal.charAt(end) != '>')
end++;
// Gets the list of possible productions to replace the nonterminal with
ArrayList<String> possibleResults = nonTerminals.get(nonTerminal.substring(start, end + 1));
// Replaces nonterminal substring with a random production rule from the list
nonTerminal.replace(start, end + 1, possibleResults.get(rng.nextInt(possibleResults.size())));
// Decrements i for when a replaced production rule starts with a non-terminal
start--;
}
}
return nonTerminal;
}
}