28 | * 29 | *36 | * 37 | * Symbol is inferred as nonterminal by first uppercase char. "->" designates 38 | * definition, "|" designates alternation, and newlines designate termination. 39 | * Use "EPSILON" to represent an empty string. Place spaces between things you 40 | * don't want to read as one symbol: ( A ) != (A). 41 | * 42 | * @author Ira Korshunova 43 | * 44 | */ 45 | 46 | public class Parser { 47 | 48 | /** Terminal symbol of grammar which represents empty string */ 49 | public static Terminal epsilon = new Terminal(0, "EPSILON"); 50 | 51 | /** Terminal symbol which represents end of program */ 52 | public static Terminal endOfProgram = new Terminal(-1, "ENDOFPROGRAM"); 53 | 54 | /** Start symbol of the grammar */ 55 | private NonTerminal startSymbol; 56 | 57 | /** List of rules in the grammar without alternations */ 58 | private List30 | * Goal -> A 31 | * A -> ( A ) | Two 32 | * Two -> a 33 | *34 | * 35 | *
248 | * 249 | *258 | * 259 | * 260 | * @param s 261 | * terminal or nonterminal symbol of grammar 262 | */ 263 | private void first(Symbol s) { 264 | Set250 | * 1. If X is terminal, then FIRST(X) is {X}. 251 | * 2. If X -> EPSILON is production, then add EPSILON to FIRST(X). 252 | * 3. If X is nonterminal and X -> Y1 Y2 ... Yk is a production, 253 | * then place a (terminal) in FIRST(X) if for some i a is in FIRST(Yi), and Y1, ... ,Yi-1 -> EPSILON. 254 | * If EPSILON is in FIRST(Yj) for all j = 1, 2, ... , k, then add EPSILON to FIRST(X). 255 | *256 | * 257 | *