lupejuares lupejuares - 11 months ago 69
Java Question

java compiler, finding the follow producing duplicates

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.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++)


String [] s = l.get(i).prod.split(" ");

if(!isNonTerm(s[0]))// is a terminal

// if the rhs is a terminal

Answer Source

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<>();

    Grammer previous = null;
    for (Grammar gr : l) {
        if (v.equals(gr.term)) {
            String s =" ")[0];
            if (!isNonTerm(s)) { // is a terminal

            // if the rhs is a terminal 
            if (s.equalsIgnoreCase("empty") && previous != null) {
                String[] stemp =" ");

                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.