예제 #1
0
def resolve_left_recursion_simple(literals, bad_literals):
    from grammar.models import Literal

    for bt in bad_literals:
        index = literals.index(bt)
        rules_1 = [
            rule[1:] for rule in bt.rules if len(rule) and rule[0] == bt
        ]
        rules_2 = [rule for rule in bt.rules if not len(rule) or rule[0] != bt]
        new_literal = Literal(bt.text + '-prime')
        bt.rules = [rule2 + [new_literal] for rule2 in rules_2]
        new_literal.rules = [rule1 + [new_literal] for rule1 in rules_1] + [[]]
        literals.insert(index + 1, new_literal)
    return literals
예제 #2
0
    def test_success_order(self):
        for filename, expected_parse_tree, grammar_filename in TestParser.test_cases:

            with open(
                    os.path.join(
                        os.path.join(BASE_DIR, 'resources/test/grammar'),
                        grammar_filename)) as grammar_file:
                with open(
                        os.path.join(
                            os.path.join(BASE_DIR, 'resources/test/code'),
                            filename)) as test_file:
                    non_terminals = Literal.parse(grammar_file)
                    all_literals = get_all_literals_from_non_terminals(
                        non_terminals)
                    start, states = create_transition_diagram(non_terminals)
                    parser = Parser(states, start,
                                    Scanner(test_file.read(), all_literals))
                    errors = parser.parse()
                    if errors:
                        print(errors)
                    parse_tree = parser.tree
                    self.assertEqual(parse_tree[0], expected_parse_tree[0],
                                     "Error in " + filename)
                    self.assertListEqual(parse_tree[1], expected_parse_tree[1],
                                         "Error in " + filename)
예제 #3
0
 def setUp(self):
     with open(
             os.path.join(
                 BASE_DIR,
                 'resources/src/predictable_grammar.txt')) as grammar_file:
         non_terminals = Literal.parse(grammar_file)
         self.all_literals = get_all_literals_from_non_terminals(
             non_terminals)
예제 #4
0
 def test_predictability(self):
     with open(
             os.path.join(BASE_DIR, 'resources', 'src',
                          'predictable_grammar.txt')) as grammar_file:
         grammar = Literal.parse(grammar_file)
         first = compute_non_terminals_firsts(grammar)
         self.assertTrue(
             check_predictability(
                 grammar, first,
                 compute_non_terminals_follows(grammar, first)))
예제 #5
0
파일: manage.py 프로젝트: altostratous/ancc
def compile_nc_code(input_string):
    with open(os.path.join(
            BASE_DIR,
            'resources/src/predictable_grammar.txt')) as grammar_file:
        non_terminals = Literal.parse(grammar_file)
        all_literals = get_all_literals_from_non_terminals(non_terminals)
        start, states = create_transition_diagram(non_terminals)
        parser = Parser(states, start, Scanner(input_string, all_literals))
        errors = parser.parse()
        if errors:
            for error in errors:
                print(sys.stderr, error)
            return ''
        return str(parser.program)
예제 #6
0
def factorize(grammar):
    # only works for factorizations shared among all rules of the non terminal
    counter = 0
    new_grammar = copy(grammar)
    for non_terminal in grammar:
        counter += 1
        if len(non_terminal.rules) <= 1:
            continue
        prefix = os.path.commonprefix(non_terminal.rules)
        if len(prefix) > 0:
            new_non_terminal = Literal(
                'rest-of-' + non_terminal.text,
                [rule[len(prefix):] for rule in non_terminal.rules])
            non_terminal.rules = [prefix + [new_non_terminal]]
            new_grammar.insert(counter, new_non_terminal)
            counter += 1
    return new_grammar
예제 #7
0
    def test(self):
        with open(
                os.path.join(
                    BASE_DIR,
                    'resources/src/predictable_grammar.txt')) as grammar_file:
            non_terminals = Literal.parse(grammar_file)
            all_literals = get_all_literals_from_non_terminals(non_terminals)
            start, states = create_transition_diagram(non_terminals)
            os.chdir(os.path.join(BASE_DIR, 'resources/test/executable'))

            for filename in Test.test_cases:

                with open(os.path.join('..', 'code',
                                       filename + '.nc')) as test_file:
                    parser = Parser(states, start,
                                    Scanner(test_file.read(), all_literals))
                    errors = parser.parse()
                    if errors:
                        print(errors)
                        self.fail()
                    else:
                        with open(os.path.join(filename + '.nco'),
                                  mode='w') as output_file:
                            output_file.write(str(parser.program))
                        os.system('cp ' + filename + '.nco output.txt')
                        if platform.system() == 'Darwin':
                            os.system('../../../bin/tester_mac.out > tmptmp')
                        elif platform.system() == 'Linux':
                            os.system('../../../bin/tester_linux.out > tmptmp')
                        else:
                            assert 0, "I don't give a F*** to Windows"
                        if 0 != os.system('diff tmptmp ../output/' + filename +
                                          '.txt'):
                            print(
                                "Integration test {} failed.".format(filename))
                            pprint.pprint(parser.tree)
                            self.fail()
                        self.assertEqual(0, os.system('rm output.txt tmptmp'))
예제 #8
0
    def test_first_follow(self):
        opened_file = open(
            os.path.join(BASE_DIR, 'resources', 'test', 'grammar',
                         'complex.txt'))
        non_terminals = Literal.parse(opened_file)
        literals_map = {}
        for non_terminal in non_terminals:
            literals_map[non_terminal.text] = non_terminal
            for rule in non_terminal.rules:
                for literal in rule:
                    literals_map[literal.text] = literal

        first = compute_non_terminals_firsts(non_terminals)
        follow = compute_non_terminals_follows(non_terminals, first)

        self.assertDictEqual(
            dict(first), {
                literals_map['s']: {literals_map['f']},
                literals_map['s-prime']: {literals_map['f']},
                literals_map['a']: {literals_map['f']},
                literals_map['b']: {()},
                literals_map['c']: {literals_map['f']},
                literals_map['d']: {()},
            })

        self.assertDictEqual(
            follow, {
                literals_map['s']: set(),
                literals_map['s-prime']: {literals_map['EOF']},
                literals_map['a']: {literals_map['f']},
                literals_map['b']: {literals_map['f']},
                literals_map['c']: {literals_map['EOF'], literals_map['f']},
                literals_map['d']: {literals_map['EOF']},
            })

        opened_file.close()
예제 #9
0
    def test_success_order(self):
        for filename, expected_parse_errors, grammar_filename in TestPanicMode.test_cases:

            with open(
                    os.path.join(
                        os.path.join(BASE_DIR, 'resources/test/grammar'),
                        grammar_filename)) as grammar_file:
                with open(
                        os.path.join(
                            os.path.join(BASE_DIR, 'resources/test/code'),
                            filename)) as test_file:
                    non_terminals = Literal.parse(grammar_file)
                    all_literals = get_all_literals_from_non_terminals(
                        non_terminals)
                    start, states = create_transition_diagram(non_terminals)
                    parser = Parser(states, start,
                                    Scanner(test_file.read(), all_literals))
                    errors = parser.parse()
                    print(errors)
                    self.assertEqual(len(expected_parse_errors), len(errors))
                    for error in errors:
                        self.assertIn((error.lookahead_literal.text,
                                       error.non_terminal.text),
                                      expected_parse_errors)
예제 #10
0
파일: manage.py 프로젝트: altostratous/ancc
def generate():
    from grammar.utils import check_left_recursion, resolve_left_recursion_simple, print_to_file, factorize, \
        compute_non_terminals_firsts, requires_factorization, compute_non_terminals_follows

    with open(os.path.join(BASE_DIR, 'resources/src/raw_grammar.txt')) as file:
        new_grammar = current_grammar = Literal.parse(file)

    while True:
        bad_literals = check_left_recursion(current_grammar)
        if not bad_literals:
            break
        new_grammar = resolve_left_recursion_simple(current_grammar,
                                                    bad_literals)
        current_grammar = new_grammar

    print_to_file(
        new_grammar,
        os.path.join(BASE_DIR, 'resources/src/recursion_free_grammar.txt'))
    print("Left recursion resolved.")

    while requires_factorization(current_grammar):
        current_grammar = factorize(current_grammar)
        print("Factorized one time.")
    print_to_file(
        current_grammar,
        os.path.join(BASE_DIR, 'resources/src/partially_factored_grammar.txt'))

    with open(os.path.join(BASE_DIR,
                           'resources/src/predictable_grammar.txt')) as file:
        current_grammar = Literal.parse(file)

    first = OrderedDict(compute_non_terminals_firsts(current_grammar))
    follow = OrderedDict(compute_non_terminals_follows(current_grammar, first))
    print("Computed first and follow sets.")
    check_predictability(current_grammar, first, follow)

    start_state, state_machines = create_transition_diagram(current_grammar)

    with open(path.join(BASE_DIR, 'doc/README.md'), 'w') as doc_file:
        with open(path.join(
                BASE_DIR,
                'resources/src/raw_grammar.txt')) as raw_grammar_file:
            with open(
                    path.join(BASE_DIR,
                              'resources/src/recursion_free_grammar.txt')
            ) as recursion_free_grammar_file:
                with open(
                        path.join(
                            BASE_DIR,
                            'resources/src/partially_factored_grammar.txt')
                ) as partially_factored_grammar_file:
                    with open(
                            path.join(BASE_DIR,
                                      'resources/src/predictable_grammar.txt')
                    ) as predictable_grammar_file:
                        doc_file.writelines([
                            '# ANCC Automatically Generated Documentation\n',
                            '## Raw Grammar\n',
                            '```\n',
                        ])
                        for line in raw_grammar_file:
                            doc_file.write(line)
                        doc_file.writelines([
                            '```\n',
                            '## Recursion Free Grammar\n',
                            '```\n',
                        ])
                        for line in recursion_free_grammar_file:
                            doc_file.write(line)

                        doc_file.writelines([
                            '```\n',
                            '## Partially Factored Grammar\n',
                            '```\n',
                        ])
                        for line in partially_factored_grammar_file:
                            doc_file.write(line)

                        doc_file.writelines([
                            '```\n',
                            '## Predictable Grammar\n',
                            '```\n',
                        ])
                        for line in predictable_grammar_file:
                            doc_file.write(escape(line))

                        doc_file.writelines([
                            '\n',
                            '```\n',
                            '## State Diagram\n',
                            '```\n',
                        ])
                        print_diagram(state_machines, doc_file)

                        doc_file.writelines([
                            '```\n', '## First and Follow\n'
                            '|Non-terminal|First|Follow|\n'
                            '|:----------:|:---:|:----:|\n'
                        ])

                        for non_terminal in sorted(first.keys()):
                            doc_file.writelines([
                                '|{}|{}|{}|\n'.format(
                                    non_terminal.text, ' '.join(
                                        sorted([
                                            'ε'
                                            if literal == () else literal.text
                                            for literal in first[non_terminal]
                                        ])),
                                    ' '.join(
                                        sorted([
                                            'ε'
                                            if literal == () else literal.text
                                            for literal in follow[non_terminal]
                                        ]))),
                            ])