def test_conception(self): statement = NonTerminal("Statement") expression = NonTerminal("Expression") semicolon = Terminal(CHARACTER, ";") plus = Terminal(CHARACTER, "+") minus = Terminal(CHARACTER, "-") production = Productions( {statement: [[expression, semicolon]], expression: [[plus], [minus]]} ) production.set_start_symbol(statement) fs = FirstSet(production) fs.compute() print(fs.first_set)
def compute(self): if self.first_set is None: fs = FirstSet(self.production) fs.compute() self.first_set = fs.first_set self.first_set_mapping = fs.first_set_mapping if self.follow_set is None: fs = FollowSet(self.production, self.first_set) fs.compute() self.follow_set = fs.follow_set for lhs_symbol in self.production: productions = self.production[lhs_symbol] for production_index, production in enumerate(productions): symbol_set = self.first_set_mapping[lhs_symbol][ production_index] self.first_plus_set_mapping.setdefault(lhs_symbol, {}) self.first_plus_set_mapping[lhs_symbol].setdefault( production_index, set()) first_plus_set = self.first_plus_set_mapping[lhs_symbol][ production_index] if symbol_set.include_epsilon: first_plus_set.update(symbol_set.remove_epsilon()) first_plus_set.update(self.follow_set[lhs_symbol]) else: first_plus_set.update(symbol_set) self.first_plus_set.setdefault(lhs_symbol, {}) for symbol in first_plus_set: if symbol in self.first_plus_set[lhs_symbol]: msg = "Lookahead {} index {} already exists in {}" raise ValueError( msg.format( symbol, production_index, self.first_plus_set[lhs_symbol], )) self.first_plus_set[lhs_symbol][symbol] = production_index
def test_real(self): """ Goal -> Expr ; Expr -> Term ExprTwo ; ExprTwo -> '+' Term ExprTwo | '-' Term ExprTwo | ϵ ; Term -> Factor TermTwo ; TermTwo -> '*' Factor TermTwo | '/' Factor TermTwo | ϵ ; Factor -> '(' Expr ')' | 'num' | 'name' ; """ """ Extended Backus-Naur form: Goal -> Expr Expr -> Term ExprTwo ExprTwo -> + Term ExprTwo | - Term ExprTwo | EPSILON Term -> Factor TermTwo TermTwo -> * Factor TermTwo | / Factor TermTwo | EPSILON Factor -> ( Expr ) | num | name """ goal = NonTerminal("Goal") expr = NonTerminal("Expr") expr_two = NonTerminal("ExprTwo") term = NonTerminal("Term") term_two = NonTerminal("TermTwo") factor = NonTerminal("Factor") epsilon = Epsilon() name = Terminal(CHARACTER, "name") num = Terminal(CHARACTER, "num") plus = Terminal(CHARACTER, "+") minus = Terminal(CHARACTER, "-") div = Terminal(CHARACTER, "/") asteroid = Terminal(CHARACTER, "*") open_parenthesis = Terminal(CHARACTER, "(") close_parenthesis = Terminal(CHARACTER, ")") eof = EOF() production = Productions( { goal: [[expr]], expr: [[term, expr_two]], expr_two: [[plus, term, expr_two], [minus, term, expr_two], [epsilon]], term: [[factor, term_two]], term_two: [ [asteroid, factor, term_two], [div, factor, term_two], [epsilon], ], factor: [[open_parenthesis, expr, close_parenthesis], [num], [name]], } ) production.set_start_symbol(goal) fs = FirstSet(production) fs.compute() first_set = fs.first_set fs = FollowSet(production, first_set) fs.compute() real_result = fs.follow_set expect_result = { NonTerminal("Goal"): {EOF()}, NonTerminal("Expr"): {Terminal(CHARACTER, ")"), EOF()}, NonTerminal("ExprTwo"): {Terminal(CHARACTER, ")"), EOF()}, NonTerminal("Term"): { EOF(), Terminal(CHARACTER, "+"), Terminal(CHARACTER, "-"), Terminal(CHARACTER, ")"), }, NonTerminal("TermTwo"): { EOF(), Terminal(CHARACTER, "+"), Terminal(CHARACTER, "-"), Terminal(CHARACTER, ")"), }, NonTerminal("Factor"): { EOF(), Terminal(CHARACTER, "+"), Terminal(CHARACTER, "-"), Terminal(CHARACTER, "/"), Terminal(CHARACTER, "*"), Terminal(CHARACTER, ")"), }, } self.assertEqual(real_result, expect_result)
def test_real(self): """ Goal -> Expr ; Expr -> Term ExprTwo ; ExprTwo -> '+' Term ExprTwo | '-' Term ExprTwo | ϵ ; Term -> Factor TermTwo ; TermTwo -> '*' Factor TermTwo | '/' Factor TermTwo | ϵ ; Factor -> '(' Expr ')' | 'num' | 'name' ; """ """ Extended Backus-Naur form: Goal -> Expr Expr -> Term ExprTwo ExprTwo -> + Term ExprTwo | - Term ExprTwo | EPSILON Term -> Factor TermTwo TermTwo -> * Factor TermTwo | / Factor TermTwo | EPSILON Factor -> ( Expr ) | num | name """ goal = NonTerminal("Goal") expr = NonTerminal("Expr") expr_two = NonTerminal("ExprTwo") term = NonTerminal("Term") term_two = NonTerminal("TermTwo") factor = NonTerminal("Factor") epsilon = Epsilon() name = Terminal(CHARACTER, "name") num = Terminal(CHARACTER, "num") plus = Terminal(CHARACTER, "+") minus = Terminal(CHARACTER, "-") div = Terminal(CHARACTER, "/") asteroid = Terminal(CHARACTER, "*") open_parenthesis = Terminal(CHARACTER, "(") close_parenthesis = Terminal(CHARACTER, ")") eof = EOF() production = Productions( { goal: [[expr]], expr: [[term, term_two]], expr_two: [[plus, term, expr_two], [minus, term, expr_two], [epsilon]], term: [[factor, term_two]], term_two: [ [asteroid, factor, term_two], [div, factor, term_two], [epsilon], ], factor: [[open_parenthesis, expr, close_parenthesis], [num], [name]], } ) production.set_start_symbol(goal) fs = FirstSet(production) fs.compute() real_result = fs.first_set expect_result = { eof: SymbolSet({eof}), plus: SymbolSet({plus}), minus: SymbolSet({minus}), epsilon: SymbolSet({epsilon}), asteroid: SymbolSet({asteroid}), div: SymbolSet({div}), open_parenthesis: SymbolSet({open_parenthesis}), close_parenthesis: SymbolSet({close_parenthesis}), num: SymbolSet({num}), name: SymbolSet({name}), expr_two: SymbolSet({plus, minus, epsilon}), term_two: SymbolSet({asteroid, div, epsilon}), factor: SymbolSet({open_parenthesis, num, name}), term: SymbolSet({open_parenthesis, num, name}), expr: SymbolSet({open_parenthesis, num, name}), goal: SymbolSet({open_parenthesis, num, name}), } # pprint.pprint(real_result) self.maxDiff = None self.assertEqual(real_result, expect_result)