ive been working on a java compiler assignment that is asking to find the First of a grammar. I have it all ready and done. all the work has been done , but i have one problem. my first is producing duplicates. for example part of my output is this
NonTerminal First
P int void
L int void
D int void
Vd int void
Ts int void
Fn int void
Ps int void void
Ps int void void , the 2nd void is a duplicate. how would i go about removing these duplicates? ill paste my main compiler code were everything happens below. i suspect i would have to make a change somewere in the findFirst method, since thats were all the action happens , but im not sure what to do.
package compilerproject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.security.KeyStore.Entry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Compiler {
public static void main(String[] args) {
List<Grammar> gList = getGrammar();
Map<String, List<String>> fList = firstList(gList);
//firstlist returns a hash map LHS and RHS
//save it into fList which is a map of Strings and List so u can use it in findFirst method
printFirstList(fList, gList);
ParserLibrary idList = new ParserLibrary();
}
public static List<String> findFirst(String v, List<Grammar> l)
{
List<String> First = new ArrayList<String>();
for(int i = 0; i < l.size(); i++)
{
if(v.equals(l.get(i).term))
{
String [] s = l.get(i).prod.split(" ");
if(!isNonTerm(s[0]))// is a terminal
{
First.add(s[0]);
}
// if the rhs is a terminal
It would save some troubles using a Set instead of a List. I kept List as return type, but changed the rest.
public static List<String> findFirst(String v, List<Grammar> l) {
Set<String> first = new TreeSet<>();
Set<String> done = new HashSet<>();
done.add(v);
Grammer previous = null;
for (Grammar gr : l) {
if (v.equals(gr.term)) {
String s = gr.prod.split(" ")[0];
if (!isNonTerm(s)) { // is a terminal
first.add(s);
}
// if the rhs is a terminal
if (s.equalsIgnoreCase("empty") && previous != null) {
String[] stemp = previous.prod.split(" ");
if (v.equalsIgnoreCase(stemp[0]) && stemp.length > 1
&& done.add(stemp[1])) {
first.addAll(findFirst(stemp[1], l)); // <--------- Here it happened
}
//if the rhs is empty , then get the previous grammar
//split it.
//find the first of it and ad it to the first list
}
if (!v.equals(s) && isNonTerm(s) && done.add(s)) {
first.addAll(findFirst(s, l));
}
}
previous = gr;
}
return new ArrayList<String>(first);
}
I still do not find the code entirely clear. So maybe with Set
at your disposal, you may find a simpler formulation. To remove the scroll bar I place the open brace on the same line.
To prevent endless recursion I added the set done
which "evidently" is not needed.