package org.simantics.scl.compiler.parser.generator.grammar; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.hash.TIntByteHashMap; import gnu.trove.procedure.TIntIntProcedure; import gnu.trove.procedure.TIntProcedure; import gnu.trove.set.hash.THashSet; import gnu.trove.set.hash.TIntHashSet; import java.util.ArrayList; import java.util.Arrays; import org.simantics.scl.compiler.parser.grammar.Grammar; import org.simantics.scl.compiler.parser.grammar.Production; import org.simantics.scl.compiler.parser.regexp.Namer; import org.simantics.scl.compiler.parser.regexp.automata.DFA; public class AnaGrammar implements Namer { public ArrayList prods = new ArrayList(); public int[] nonterminalPos; public final String[] terminalNames; public final String[] nonterminalNames; public final int[] initialNonterminals; public boolean[] nullable; public int[][] first; public AnaGrammar(Grammar grammar) { initialNonterminals = grammar.initialNonterminals; terminalNames = Arrays.copyOf(grammar.terminalNames, grammar.terminalNames.length+1); terminalNames[terminalNames.length-1] = "EOF"; nonterminalNames = Arrays.copyOf(grammar.nonterminalNames, grammar.nonterminalNames.length+initialNonterminals.length); for(int i=1;i<=initialNonterminals.length;++i) nonterminalNames[nonterminalNames.length-i] = "init$" + i; // Convert grammar ArrayList[] prodMap = new ArrayList[nonterminalNames.length]; for(int i=0;i(); for(Production production : grammar.productions) { Prod prod = new Prod(production.name, ~production.lhs, production.rhs.toAutomaton().determinize().minimize(), production.annotations); prodMap[prod.lhs].add(prod); } // Initial production for(int i=1;i<=initialNonterminals.length;++i) { DFA dfa = new DFA(); int s0 = dfa.newState(); dfa.setInitialState(s0); int s1 = dfa.newState(); dfa.addTransition(s0, initialNonterminals[i-1], s1); int s2 = dfa.newState(); dfa.addTransition(s1, terminalNames.length-1, s2); dfa.setAccepts(s2, true); Prod prod = new Prod("Init", nonterminalNames.length-i, dfa, new TIntByteHashMap()); prodMap[prod.lhs].add(prod); } TIntArrayList pos = new TIntArrayList(); for(int i=0;i[] pendingItems = new ArrayList[nonterminalCount]; final ArrayList stack = new ArrayList(); THashSet handledItems = new THashSet(); for(int i=0;i(); for(int i=0;i "); if(nullable[i]) System.out.print(" NULL"); for(int s : this.first[i]) System.out.print(" " + terminalNames[s]); System.out.println(); }*/ } public static void gclose(TIntHashSet[] sets, TIntHashSet[] graph_) { int[][] graph = new int[graph_.length][]; for(int i=0;i= 0) return terminalNames[symbolId]; else return nonterminalNames[~symbolId]; } private class AlmostAcceptsProc implements TIntIntProcedure { DFA rhs; TIntHashSet visited = new TIntHashSet(); boolean result; public AlmostAcceptsProc(DFA rhs) { this.rhs = rhs; } @Override public boolean execute(int a, int b) { if(a < 0 && nullable[~a]) visit(b); return !result; } public void visit(int position) { if(visited.add(position)) { if(rhs.getAccepts(position)) { result = true; return; } rhs.forEachTransition(position, this); } } } public boolean almostAccepts(DFA rhs, int position) { AlmostAcceptsProc proc = new AlmostAcceptsProc(rhs); proc.visit(position); return proc.result; } }