Exemple #1
0
    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)
Exemple #2
0
    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)
Exemple #4
0
    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)