Example #1
0
 def test_conflict_first_follow():
     """
     Valid input example but produces a first/follow conflict.
     """
     TestParser._run(**{
         'name': 'First/Follow Conflict',
         'productions': {
             '<S>': [['<A>', 'a', 'b']],
             '<A>': [['a'], []]
         },
         'start': '<S>',
         'terminals': set(['a', 'b']),
         'nonterminals': set(['<S>', '<A>']),
         'first': {
             'a': set(['a']),
             'b': set(['b']),
             '<S>': set(['a']),
             '<A>': set(['a', ContextFreeGrammar.epsilon()])
         },
         'follow': {
             '<S>': set([ContextFreeGrammar.end_of_input()]),
             '<A>': set(['a'])
         },
         'rules': [
             ('<S>', ['<A>', 'a', 'b']),
             ('<A>', ['a']),
             ('<A>', [])
         ],
         'table': [
             [' ', 'a', ContextFreeGrammar.end_of_input(), 'b'],
             ['<S>', set([0]), set([]), set([])],
             ['<A>', set([1, 2]), set([]), set([])]
         ]
     })
Example #2
0
    def _run(**kwargs):
        """
        The 'main' for testing which creates the required object and compares
        the results are what was expected, failing appropriately if they are
        not.
        """
        context_free_grammar = ContextFreeGrammar(kwargs['name'],
                                                  kwargs['productions'],
                                                  kwargs['start'])

        assert context_free_grammar.name == kwargs['name'], \
               'Invalid name produced'

        assert context_free_grammar.start == kwargs['start'], \
               'Invalid start production produced'

        assert context_free_grammar.terminals == kwargs['terminals'], \
               'Invalid terminal set produced'

        assert context_free_grammar.nonterminals == kwargs['nonterminals'], \
              'Invalid nonterminal set produced'

        TestParser._compare_first_sets(kwargs['first'],
                                       context_free_grammar.first)

        TestParser._compare_follow_sets(kwargs['follow'],
                                        context_free_grammar.follow)

        mapping = TestParser._compare_rules(kwargs['rules'],
                                            context_free_grammar.rules)

        TestParser._compare_tables(kwargs['table'],
                                   context_free_grammar.table,
                                   mapping)
Example #3
0
 def test_translate_not_implemented():
     """
     Ensure a NotImplementedError is raised if generation to source language
     is attempted with the base Generator.
     """
     generator = Generator()
     generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
     generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
     generator.generate()
 def test_parser_valid():
     """
     Ensure overwriting the paser property works as expected when given
     proper input as a ContextFreeGrammar.
     """
     parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
     generator = Generator()
     generator.parser = parser
     assert generator.parser is parser, 'Invalid parser set/retrieved'
Example #5
0
 def test_overrides_output_python():
     """
     Make sure the 'Python' generator properly overrides the output method.
     """
     module = __import__('spag.generators.python', fromlist=['Python'])
     generator = getattr(module, 'Python')()
     assert generator, 'constructor failed'
     generator.scanner = RegularGrammar('test', {'foo': 'bar'})
     generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
     assert generator.generate(), 'no result returned'
Example #6
0
 def test_overrides_output(language):
     """
     Make sure the generators properly override the output method.
     """
     module = __import__('spag.generators.' + language.lower(),
                         fromlist=[language.capitalize()])
     generator = getattr(module, language.capitalize())()
     assert generator, 'constructor failed'
     generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
     generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
     assert generator.generate(), 'no result returned'
Example #7
0
    def test_translate_return_empty():
        """
        Ensure a ValueError is raised if a child Generator returns empty data.
        """
        class _EmptyFiles(Generator):
            def _translate(self):
                return dict()

        generator = _EmptyFiles()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #8
0
    def test_translate_return_invalid():
        """
        Ensure a TypeError is raised if a child Generator returns invalid data.
        """
        class _InvalidFiles(Generator):
            def _translate(self):
                return list()

        generator = _InvalidFiles()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #9
0
    def test_translate_requirements():
        """
        Ensure correctly overwriting the abstract method in the child Generator
        works as expected.
        """
        class _OutputRequirements(Generator):
            def _translate(self):
                return {self.filename + '.txt': 'hukarz'}

        generator = _OutputRequirements()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #10
0
    def test_translate_content_empty():
        """
        Ensure a ValueError is raised if a child Generator returns empty file
        contents.
        """
        class _EmptyContent(Generator):
            def _translate(self):
                return {self.filename + '.txt': ''}

        generator = _EmptyContent()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #11
0
    def test_translate_content_invalid():
        """
        Ensure a TypeError is raised if a child Generator returns invalid file
        contents.
        """
        class _InvalidContent(Generator):
            def _translate(self):
                return {self.filename + '.txt': None}

        generator = _InvalidContent()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #12
0
    def test_translate_filename_empty():
        """
        Ensure a ValueError is raised if a child Generator returns an empty
        filename.
        """
        class _EmptyFilename(Generator):
            def _translate(self):
                return {'': 'invalid'}

        generator = _EmptyFilename()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #13
0
    def test_translate_filename_invalid():
        """
        Ensure a TypeError is raised if a child Generator returns an invalid
        filename.
        """
        class _InvalidFilename(Generator):
            def _translate(self):
                return {None: 'invalid'}

        generator = _InvalidFilename()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #14
0
 def test_epsilon_absent():
     """
     Ensure the creation of a simple grammar goes as expected.
     """
     TestParser._run(**{
         'name': 'No Epsilon',
         'productions': {
             '<S>': [['<A>', 'a', '<A>', 'b'], ['<B>', 'b', '<B>', 'a']],
             '<A>': [[]],
             '<B>': [[]]
         },
         'start': '<S>',
         'terminals': set(['a', 'b']),
         'nonterminals': set(['<S>', '<A>', '<B>']),
         'first': {
             'a': set(['a']),
             'b': set(['b']),
             '<S>': set(['a', 'b']),
             '<A>': set([ContextFreeGrammar.epsilon()]),
             '<B>': set([ContextFreeGrammar.epsilon()])
         },
         'follow': {
             '<S>': set([ContextFreeGrammar.end_of_input()]),
             '<A>': set(['b', 'a']),
             '<B>': set(['a', 'b'])
         },
         'rules': [
             ('<S>', ['<A>', 'a', '<A>', 'b']),
             ('<S>', ['<B>', 'b', '<B>', 'a']),
             ('<A>', []),
             ('<B>', [])
         ],
         'table': [
             [' ', ContextFreeGrammar.end_of_input(), 'a', 'b'],
             ['<S>', set([]), set([0]), set([1])],
             ['<A>', set([]), set([2]), set([2])],
             ['<B>', set([]), set([3]), set([3])]
         ]
     })
    def test_translate_not_overridden():
        """
        Ensure a NotImplementedError is raised if a child Generator does not
        override the private _translate(self, filename) method.
        """
        # pylint: disable=abstract-method
        class _GenerateNothing(Generator):
            pass
        # pylint: enable=abstract-method

        generator = _GenerateNothing()
        generator.scanner = RegularGrammar('test', {'foo': 'bar'})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #16
0
class TestGenerator:
    """
    A test suite for testing the base Generator object.
    """
    @staticmethod
    def test_constructor():
        """
        Ensure successful creation of a Generator object.
        """
        generator = Generator()
        assert generator is not None, 'No Generator produced'

    @staticmethod
    @pytest.mark.parametrize('scanner', [
        None,
        RegularGrammar('test', {'foo': ['b', 'a', 'r']}),
        pytest.param('invalid_scanner',
                     marks=pytest.mark.xfail(
                         reason='Scanner not of type RegularGrammar or None.',
                         raises=TypeError,
                     )),
    ])
    def test_scanner(scanner):
        """
        Ensure the Generator object's scanner property behaves as expected.
        """
        generator = Generator()
        generator.scanner = scanner
        assert generator.scanner is scanner, 'Invalid scanner set/retrieved'

    @staticmethod
    def test_scanner_default():
        """
        Ensure default scanner retrieval works as expected upon successful
        creation of a Generator object.
        """
        generator = Generator()
        assert generator.scanner is None, 'Invalid scanner default retrieved'

    @staticmethod
    @pytest.mark.parametrize('parser', [
        None,
        ContextFreeGrammar('test', {'S': [['a']]}, 'S'),
        pytest.param(
            'invalid_parser',
            marks=pytest.mark.xfail(
                reason='Parser not of type ContextFreeGrammar or None.',
                raises=TypeError,
            )),
    ])
    def test_parser(parser):
        """
        Ensure the Generator object's parser property behaves as expected.
        """
        generator = Generator()
        generator.parser = parser
        assert generator.parser is parser, 'Invalid parser set/retrieved'

    @staticmethod
    def test_parser_default():
        """
        Ensure default parser retrieval works as expected upon successful
        creation of a Generator object.
        """
        generator = Generator()
        assert generator.parser is None, 'Invalid parser default retrieved'

    @staticmethod
    @pytest.mark.parametrize('filename', [
        'foobar',
        pytest.param(None,
                     marks=pytest.mark.xfail(
                         reason='Filename not of type string.',
                         raises=TypeError,
                     )),
        pytest.param('',
                     marks=pytest.mark.xfail(
                         reason='Filename must be a non empty string.',
                         raises=ValueError,
                     )),
    ])
    def test_filename(filename):
        """
        Ensure the Generator object's filename property behaves as expected.
        """
        generator = Generator()
        generator.filename = filename
        assert generator.filename == filename, 'Invalid filename set/retrieved'

    @staticmethod
    def test_filename_default():
        """
        Ensure default filename retrieval works as expected upon successful
        creation of a Generator object.
        """
        generator = Generator()
        assert generator.filename == 'out', 'Invalid default filename retrieved'

    @staticmethod
    @pytest.mark.parametrize('encoding', [
        'table',
        'direct',
        pytest.param(None,
                     marks=pytest.mark.xfail(
                         reason='Encoding not of type string.',
                         raises=TypeError,
                     )),
        pytest.param('',
                     marks=pytest.mark.xfail(
                         reason='Encoding must be a non empty string.',
                         raises=ValueError,
                     )),
        pytest.param('foo',
                     marks=pytest.mark.xfail(
                         reason='Encoding value not recognized.',
                         raises=ValueError,
                     )),
    ])
    def test_encoding(encoding):
        """
        Ensure the Generator object's encoding property behaves as expected.
        """
        generator = Generator()
        generator.encoding = encoding
        assert generator.encoding == encoding, 'Invalid encoding set/retrieved'

    @staticmethod
    def test_encoding_default():
        """
        Ensure default encoding retrieval works as expected upon successful
        creation of a Generator object.
        """
        generator = Generator()
        assert generator.encoding == 'direct', 'Invalid default encoding retrieved'

    @staticmethod
    @pytest.mark.parametrize('match', [
        'longest',
        'shortest',
        pytest.param(None,
                     marks=pytest.mark.xfail(
                         reason='Match not of type string.',
                         raises=TypeError,
                     )),
        pytest.param('',
                     marks=pytest.mark.xfail(
                         reason='Match must be a non empty string.',
                         raises=ValueError,
                     )),
        pytest.param('foo',
                     marks=pytest.mark.xfail(
                         reason='Match value not recognized.',
                         raises=ValueError,
                     )),
    ])
    def test_match(match):
        """
        Ensure the Generator object's match property behaves as expected.
        """
        generator = Generator()
        generator.match = match
        assert generator.match == match, 'Invalid matching-strategy set/retrieval'

    @staticmethod
    def test_matching_default():
        """
        Ensure default matching retrieval works as expected upon successful
        creation of a Generator object.
        """
        generator = Generator()
        assert generator.match == 'longest', 'Invalid default match retrieved'

    @staticmethod
    @pytest.mark.xfail(
        reason='Scanner or parser required for generation.',
        raises=ValueError,
    )
    def test_output_no_scanner_parser():
        """
        Ensure a ValueError is raised if generation to source language
        is attempted without a set scanner and parser.
        """
        generator = Generator()
        generator.generate()

    @staticmethod
    @pytest.mark.xfail(
        reason='Output not handled by base Generator.',
        raises=NotImplementedError,
    )
    def test_translate_not_implemented():
        """
        Ensure a NotImplementedError is raised if generation to source language
        is attempted with the base Generator.
        """
        generator = Generator()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()

    @staticmethod
    @pytest.mark.xfail(
        reason='Output not overridden by child Generator.',
        raises=NotImplementedError,
    )
    def test_translate_not_overridden():
        """
        Ensure a NotImplementedError is raised if a child Generator does not
        override the private _translate(self, filename) method.
        """

        # pylint: disable=abstract-method
        class _GenerateNothing(Generator):
            pass

        # pylint: enable=abstract-method

        generator = _GenerateNothing()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()

    @staticmethod
    @pytest.mark.xfail(
        reason='Invalid output type of child Generator.',
        raises=TypeError,
    )
    def test_translate_return_invalid():
        """
        Ensure a TypeError is raised if a child Generator returns invalid data.
        """
        class _InvalidFiles(Generator):
            def _translate(self):
                return list()

        generator = _InvalidFiles()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()

    @staticmethod
    @pytest.mark.xfail(
        reason='Empty output of child Generator.',
        raises=ValueError,
    )
    def test_translate_return_empty():
        """
        Ensure a ValueError is raised if a child Generator returns empty data.
        """
        class _EmptyFiles(Generator):
            def _translate(self):
                return dict()

        generator = _EmptyFiles()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()

    @staticmethod
    @pytest.mark.xfail(
        reason='Invalid filename output of child Generator.',
        raises=TypeError,
    )
    def test_translate_filename_invalid():
        """
        Ensure a TypeError is raised if a child Generator returns an invalid
        filename.
        """
        class _InvalidFilename(Generator):
            def _translate(self):
                return {None: 'invalid'}

        generator = _InvalidFilename()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()

    @staticmethod
    @pytest.mark.xfail(
        reason='Empty filename output of child Generator.',
        raises=ValueError,
    )
    def test_translate_filename_empty():
        """
        Ensure a ValueError is raised if a child Generator returns an empty
        filename.
        """
        class _EmptyFilename(Generator):
            def _translate(self):
                return {'': 'invalid'}

        generator = _EmptyFilename()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()

    @staticmethod
    @pytest.mark.xfail(
        reason='Invalid file contents output of child Generator.',
        raises=TypeError,
    )
    def test_translate_content_invalid():
        """
        Ensure a TypeError is raised if a child Generator returns invalid file
        contents.
        """
        class _InvalidContent(Generator):
            def _translate(self):
                return {self.filename + '.txt': None}

        generator = _InvalidContent()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()

    @staticmethod
    @pytest.mark.xfail(
        reason='Empty file contents output of child Generator.',
        raises=ValueError,
    )
    def test_translate_content_empty():
        """
        Ensure a ValueError is raised if a child Generator returns empty file
        contents.
        """
        class _EmptyContent(Generator):
            def _translate(self):
                return {self.filename + '.txt': ''}

        generator = _EmptyContent()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()

    @staticmethod
    def test_translate_requirements():
        """
        Ensure correctly overwriting the abstract method in the child Generator
        works as expected.
        """
        class _OutputRequirements(Generator):
            def _translate(self):
                return {self.filename + '.txt': 'hukarz'}

        generator = _OutputRequirements()
        generator.scanner = RegularGrammar('test', {'foo': ['b', 'a', 'r']})
        generator.parser = ContextFreeGrammar('test', {'S': [['a']]}, 'S')
        generator.generate()
Example #17
0
 def test_conflict_left_recursion():
     """
     Valid input example but produces some conflicts due to the use of left
     recursion.
     """
     TestParser._run(**{
         'name': 'Left Recursion',
         'productions': {
             '<E>': [['<E>', '<A>', '<T>'], ['<T>']],
             '<A>': [['+'], ['-']],
             '<T>': [['<T>', '<M>', '<F>'], ['<F>']],
             '<M>': [['*']],
             '<F>': [['(', '<E>', ')'], ['id']]
         },
         'start': '<E>',
         'terminals': set(['(', ')', '+', '*', '-', 'id']),
         'nonterminals': set(['<E>', '<A>', '<T>', '<M>', '<F>']),
         'first': {
             '(': set(['(']),
             ')': set([')']),
             '+': set(['+']),
             '-': set(['-']),
             '*': set(['*']),
             'id': set(['id']),
             '<E>': set(['(', 'id']),
             '<A>': set(['+', '-']),
             '<T>': set(['(', 'id']),
             '<M>': set(['*']),
             '<F>': set(['(', 'id'])
         },
         'follow': {
             '<E>': set([ContextFreeGrammar.end_of_input(), '+', '-', ')']),
             '<A>': set(['(', 'id']),
             '<T>': set([ContextFreeGrammar.end_of_input(), '+', '-', '*', ')']),
             '<M>': set(['(', 'id']),
             '<F>': set([ContextFreeGrammar.end_of_input(), '+', '-', '*', ')'])
         },
         'rules': [
             ('<E>', ['<E>', '<A>', '<T>']),
             ('<E>', ['<T>']),
             ('<A>', ['+']),
             ('<A>', ['-']),
             ('<T>', ['<T>', '<M>', '<F>']),
             ('<T>', ['<F>']),
             ('<M>', ['*']),
             ('<F>', ['(', '<E>', ')']),
             ('<F>', ['id'])
         ],
         'table': [
             [' ', ContextFreeGrammar.end_of_input(), 'id', ')', '(', '+', '*', '-'],
             ['<E>', set([]), set([0, 1]), set([]), set([0, 1]), set([]),
              set([]), set([])],
             ['<A>', set([]), set([]), set([]), set([]), set([2]), set([]),
              set([3])],
             ['<M>', set([]), set([]), set([]), set([]), set([]), set([6]),
              set([])],
             ['<T>', set([]), set([4, 5]), set([]), set([4, 5]), set([]),
              set([]), set([])],
             ['<F>', set([]), set([8]), set([]), set([7]), set([]), set([]),
              set([])]
         ]
     })
Example #18
0
 def test_lisp():
     """
     Ensure the creation of the Lisp grammar goes as expected.
     """
     TestParser._run(**{
         'name': 'Lisp',
         'productions': {
             '<expression>': [['<atom>'], ['<pair>']],
             '<pair>': [['(', '<expression>', '.', '<expression>', ')']],
             '<atom>': [
                 ['symbol'],
                 ['character'],
                 ['string'],
                 ['boolean'],
                 ['int'],
                 ['float'],
                 ['nil']
             ]
         },
         'start': '<expression>',
         'terminals': set(['(', '.', ')', 'symbol', 'character', 'string',
                           'boolean', 'int', 'float', 'nil']),
         'nonterminals': set(['<atom>', '<pair>', '<expression>']),
         'first': {
             '(': set(['(']),
             '.': set(['.']),
             ')': set([')']),
             'symbol': set(['symbol']),
             'character': set(['character']),
             'string': set(['string']),
             'boolean': set(['boolean']),
             'int': set(['int']),
             'float': set(['float']),
             'nil': set(['nil']),
             '<atom>': set(['boolean', 'character', 'float', 'int', 'nil',
                            'string', 'symbol']),
             '<pair>': set(['(']),
             '<expression>': set(['(', 'boolean', 'character', 'float',
                                  'int', 'nil', 'string', 'symbol'])
         },
         'follow': {
             '<atom>': set([ContextFreeGrammar.end_of_input(), ')', '.']),
             '<pair>': set([ContextFreeGrammar.end_of_input(), ')', '.']),
             '<expression>': set([ContextFreeGrammar.end_of_input(), ')', '.'])
         },
         'rules': [
             ('<expression>', ['<atom>']),
             ('<expression>', ['<pair>']),
             ('<pair>', ['(', '<expression>', '.', '<expression>', ')']),
             ('<atom>', ['symbol']),
             ('<atom>', ['character']),
             ('<atom>', ['string']),
             ('<atom>', ['boolean']),
             ('<atom>', ['int']),
             ('<atom>', ['float']),
             ('<atom>', ['nil'])
         ],
         'table': [
             [' ', ContextFreeGrammar.end_of_input(), 'symbol', 'character', 'string', 'boolean', 'int',
              'float', 'nil', '(', '.', ')'],
             ['<expression>', set([]), set([0]), set([0]), set([0]),
              set([0]), set([0]), set([0]), set([0]), set([1]), set([]),
              set([])],
             ['<atom>', set([]), set([3]), set([4]), set([5]), set([6]),
              set([7]), set([8]), set([9]), set([]), set([]), set([])],
             ['<pair>', set([]), set([]), set([]), set([]), set([]),
              set([]), set([]), set([]), set([2]), set([]), set([])],
         ]
     })
Example #19
0
 def test_ini():
     """
     Ensure the creation of the INI grammar goes as expected.
     """
     TestParser._run(**{
         'name': 'INI',
         'productions': {
             '<INI>': [['<SECTION>', '<INI>'], []],
             '<SECTION>': [['<HEADER>', '<SETTINGS>']],
             '<HEADER>': [['[', 'string', ']']],
             '<SETTINGS>': [['<KEY>', '<SEP>', '<VALUE>', '<SETTINGS>'], []],
             '<KEY>': [['string']],
             '<SEP>': [[':'], ['=']],
             '<VALUE>': [['string'], ['number'], ['bool']]
         },
         'start': '<INI>',
         'terminals': set(['string', 'number', 'bool', ':', '=', '[', ']']),
         'nonterminals': set(['<INI>', '<SECTION>', '<HEADER>',
                              '<SETTINGS>', '<KEY>', '<SEP>', '<VALUE>']),
         'first': {
             'string': set(['string']),
             'number': set(['number']),
             'bool': set(['bool']),
             ':': set([':']),
             '=': set(['=']),
             '[': set(['[']),
             ']': set([']']),
             '<INI>': set([ContextFreeGrammar.epsilon(), '[']),
             '<SECTION>': set(['[']),
             '<HEADER>': set(['[']),
             '<SETTINGS>': set([ContextFreeGrammar.epsilon(), 'string']),
             '<KEY>': set(['string']),
             '<SEP>': set([':', '=']),
             '<VALUE>': set(['string', 'number', 'bool'])
         },
         'follow': {
             '<INI>': set([ContextFreeGrammar.end_of_input()]),
             '<SECTION>': set([ContextFreeGrammar.end_of_input(), '[']),
             '<HEADER>': set([ContextFreeGrammar.end_of_input(), '[', 'string']),
             '<SETTINGS>': set([ContextFreeGrammar.end_of_input(), '[']),
             '<KEY>': set([':', '=']),
             '<SEP>': set(['string', 'number', 'bool']),
             '<VALUE>': set([ContextFreeGrammar.end_of_input(), '[', 'string'])
         },
         'rules': [
             ('<INI>', ['<SECTION>', '<INI>']),
             ('<INI>', []),
             ('<SECTION>', ['<HEADER>', '<SETTINGS>']),
             ('<HEADER>', ['[', 'string', ']']),
             ('<SETTINGS>', ['<KEY>', '<SEP>', '<VALUE>', '<SETTINGS>']),
             ('<SETTINGS>', []),
             ('<KEY>', ['string']),
             ('<SEP>', [':']),
             ('<SEP>', ['=']),
             ('<VALUE>', ['string']),
             ('<VALUE>', ['number']),
             ('<VALUE>', ['bool'])
         ],
         'table': [[' ', ContextFreeGrammar.end_of_input(), 'bool', 'string', '=', '[', ':', ']', 'number'],
                   ['<VALUE>', set([]), set([11]), set([9]), set([]),
                    set([]), set([]), set([]), set([10])],
                   ['<KEY>', set([]), set([]), set([6]), set([]),
                    set([]), set([]), set([]), set([])],
                   ['<SETTINGS>', set([5]), set([]), set([4]), set([]),
                    set([5]), set([]), set([]), set([])],
                   ['<SECTION>', set([]), set([]), set([]), set([]),
                    set([2]), set([]), set([]), set([])],
                   ['<HEADER>', set([]), set([]), set([]), set([]),
                    set([3]), set([]), set([]), set([])],
                   ['<SEP>', set([]), set([]), set([]), set([8]),
                    set([]), set([7]), set([]), set([])],
                   ['<INI>', set([1]), set([]), set([]), set([]),
                    set([0]), set([]), set([]), set([])],
                  ]
     })
Example #20
0
 def test_epsilon_present():
     """
     Ensure the creation of a simple grammar containing an epsilon goes as
     expected.
     """
     TestParser._run(**{
         'name': 'Epsilon',
         'productions': {
             '<E>': [['<T>', '<E\'>']],
             '<E\'>': [['<A>', '<T>', '<E\'>'], []],
             '<A>': [['+'], ['-']],
             '<T>': [['<F>', '<T\'>']],
             '<T\'>': [['<M>', '<F>', '<T\'>'], []],
             '<M>': [['*']],
             '<F>': [['(', '<E>', ')'], ['id']]
         },
         'start': '<E>',
         'terminals': set(['+', '-', '*', '(', ')', 'id']),
         'nonterminals': set(['<E>', '<E\'>', '<A>', '<T>', '<T\'>', '<M>',
                              '<F>']),
         'first': {
             '+': set(['+']),
             '-': set(['-']),
             '*': set(['*']),
             '(': set(['(']),
             ')': set([')']),
             'id': set(['id']),
             '<E>': set(['(', 'id']),
             '<E\'>': set(['+', '-', ContextFreeGrammar.epsilon()]),
             '<A>': set(['+', '-']),
             '<T>': set(['(', 'id']),
             '<T\'>': set([ContextFreeGrammar.epsilon(), '*']),
             '<M>': set(['*']),
             '<F>': set(['(', 'id'])
         },
         'follow': {
             '<E>': set([ContextFreeGrammar.end_of_input(), ')']),
             '<E\'>': set([ContextFreeGrammar.end_of_input(), ')']),
             '<A>': set(['(', 'id']),
             '<T>': set([')', '+', '-', ContextFreeGrammar.end_of_input()]),
             '<T\'>': set([')', '+', '-', ContextFreeGrammar.end_of_input()]),
             '<M>': set(['(', 'id']),
             '<F>': set([')', '+', '-', '*', ContextFreeGrammar.end_of_input()])
         },
         'rules': [
             ('<E>', ['<T>', '<E\'>']),
             ('<E\'>', ['<A>', '<T>', '<E\'>']),
             ('<E\'>', []),
             ('<A>', ['+']),
             ('<A>', ['-']),
             ('<T>', ['<F>', '<T\'>']),
             ('<T\'>', ['<M>', '<F>', '<T\'>']),
             ('<T\'>', []),
             ('<M>', ['*']),
             ('<F>', ['(', '<E>', ')']),
             ('<F>', ['id'])
         ],
         'table': [
             [' ', ContextFreeGrammar.end_of_input(), 'id', ')', '(', '+', '*', '-'],
             ['<E>', set([]), set([0]), set([]), set([0]), set([]), set([]),
              set([])],
             ['<E\'>', set([2]), set([]), set([2]), set([]), set([1]),
              set([]), set([1])],
             ['<A>', set([]), set([]), set([]), set([]), set([3]), set([]),
              set([4])],
             ['<T>', set([]), set([5]), set([]), set([5]), set([]), set([]),
              set([])],
             ['<T\'>', set([7]), set([]), set([7]), set([]), set([7]),
              set([6]), set([7])],
             ['<M>', set([]), set([]), set([]), set([]), set([]), set([8]),
              set([])],
             ['<F>', set([]), set([10]), set([]), set([9]), set([]),
              set([]), set([])]
         ]
     })
Example #21
0
 def test_json():
     """
     Ensure the creation of the JSON grammar goes as expected.
     """
     TestParser._run(**{
         'name': 'JSON',
         'productions': {
             '<VALUE>': [
                 ['string'],
                 ['number'],
                 ['bool'],
                 ['null'],
                 ['<OBJECT>'],
                 ['<ARRAY>']
             ],
             '<OBJECT>': [['{', '<OBJECT\'>']],
             '<OBJECT\'>': [['}'], ['<MEMBERS>', '}']],
             '<MEMBERS>': [['<PAIR>', '<MEMBERS\'>']],
             '<PAIR>': [['string', ':', '<VALUE>']],
             '<MEMBERS\'>': [[',', '<MEMBERS>'], []],
             '<ARRAY>': [['[', '<ARRAY\'>']],
             '<ARRAY\'>': [[']'], ['<ELEMENTS>', ']']],
             '<ELEMENTS>': [['<VALUE>', '<ELEMENTS\'>']],
             '<ELEMENTS\'>': [[',', '<ELEMENTS>'], []]
         },
         'start': '<VALUE>',
         'terminals': set(['{', '}', ',', '[', ']', ':', 'string', 'number',
                           'bool', 'null']),
         'nonterminals': set(['<VALUE>', '<OBJECT>', '<OBJECT\'>',
                              '<MEMBERS>', '<PAIR>', '<MEMBERS\'>',
                              '<ARRAY>', '<ARRAY\'>', '<ELEMENTS>',
                              '<ELEMENTS\'>']),
         'first': {
             '{': set(['{']),
             '}': set(['}']),
             ',': set([',']),
             '[': set(['[']),
             ']': set([']']),
             ':': set([':']),
             'string': set(['string']),
             'number': set(['number']),
             'bool': set(['bool']),
             'null': set(['null']),
             '<VALUE>': set(['string', 'number', 'bool', 'null', '{', '[']),
             '<OBJECT>': set(['{']),
             '<OBJECT\'>': set(['}', 'string']),
             '<MEMBERS>': set(['string']),
             '<PAIR>': set(['string']),
             '<MEMBERS\'>': set([ContextFreeGrammar.epsilon(), ',']),
             '<ARRAY>': set(['[']),
             '<ARRAY\'>': set([']', 'string', 'number', 'bool', 'null', '{',
                               '[']),
             '<ELEMENTS>': set(['string', 'number', 'bool', 'null', '{',
                                '[']),
             '<ELEMENTS\'>': set([ContextFreeGrammar.epsilon(), ','])
         },
         'follow': {
             '<VALUE>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']),
             '<OBJECT>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']),
             '<OBJECT\'>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']),
             '<MEMBERS>': set(['}']),
             '<PAIR>': set(['}', ',']),
             '<MEMBERS\'>': set(['}']),
             '<ARRAY>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']),
             '<ARRAY\'>': set([ContextFreeGrammar.end_of_input(), ']', '}', ',']),
             '<ELEMENTS>': set([']']),
             '<ELEMENTS\'>': set([']'])
         },
         'rules': [
             ('<VALUE>', ['string']),
             ('<VALUE>', ['number']),
             ('<VALUE>', ['bool']),
             ('<VALUE>', ['null']),
             ('<VALUE>', ['<OBJECT>']),
             ('<VALUE>', ['<ARRAY>']),
             ('<OBJECT>', ['{', '<OBJECT\'>']),
             ('<OBJECT\'>', ['}']),
             ('<OBJECT\'>', ['<MEMBERS>', '}']),
             ('<MEMBERS>', ['<PAIR>', '<MEMBERS\'>']),
             ('<PAIR>', ['string', ':', '<VALUE>']),
             ('<MEMBERS\'>', [',', '<MEMBERS>']),
             ('<MEMBERS\'>', []),
             ('<ARRAY>', ['[', '<ARRAY\'>']),
             ('<ARRAY\'>', [']']),
             ('<ARRAY\'>', ['<ELEMENTS>', ']']),
             ('<ELEMENTS>', ['<VALUE>', '<ELEMENTS\'>']),
             ('<ELEMENTS\'>', [',', '<ELEMENTS>']),
             ('<ELEMENTS\'>', [])
         ],
         'table': [[' ', ContextFreeGrammar.end_of_input(), ':', 'string', ']', 'number', ',', 'bool', '{',
                    'null', '}', '['],
                   ['<PAIR>', set([]), set([]), set([10]), set([]),
                    set([]), set([]), set([]), set([]), set([]),
                    set([]), set([])],
                   ['<VALUE>', set([]), set([]), set([0]), set([]),
                    set([1]), set([]), set([2]), set([4]), set([3]),
                    set([]), set([5])],
                   ['<OBJECT>', set([]), set([]), set([]), set([]),
                    set([]), set([]), set([]), set([6]), set([]),
                    set([]), set([])],
                   ['<ELEMENTS>', set([]), set([]), set([16]), set([]),
                    set([16]), set([]), set([16]), set([16]), set([16]),
                    set([]), set([16])],
                   ['<OBJECT\'>', set([]), set([]), set([8]), set([]),
                    set([]), set([]), set([]), set([]), set([]),
                    set([7]), set([])],
                   ['<MEMBERS\'>', set([]), set([]), set([]), set([]),
                    set([]), set([11]), set([]), set([]), set([]),
                    set([12]), set([])],
                   ['<ARRAY>', set([]), set([]), set([]), set([]),
                    set([]), set([]), set([]), set([]), set([]),
                    set([]), set([13])],
                   ['<MEMBERS>', set([]), set([]), set([9]), set([]),
                    set([]), set([]), set([]), set([]), set([]),
                    set([]), set([])],
                   ['<ELEMENTS\'>', set([]), set([]), set([]), set([18]),
                    set([]), set([17]), set([]), set([]), set([]),
                    set([]), set([])],
                   ["<ARRAY'>", set([]), set([]), set([15]), set([14]),
                    set([15]), set([]), set([15]), set([15]), set([15]),
                    set([]), set([15])]
                  ]
     })
Example #22
0
 def test_simple_language():
     """
     Ensure the creation of a simple langugage grammar goes as expected.
     """
     TestParser._run(**{
         'name': 'Simple language',
         'productions': {
             '<STMT>': [
                 ['if', '<EXPR>', 'then', '<STMT>'],
                 ['while', '<EXPR>', 'do', '<STMT>'],
                 ['<EXPR>']
             ],
             '<EXPR>': [
                 ['<TERM>', '->', 'id'],
                 ['zero?', '<TERM>'],
                 ['not', '<EXPR>'],
                 ['++', 'id'],
                 ['--', 'id']
             ],
             '<TERM>': [['id'], ['constant']],
             '<BLOCK>': [['<STMT>'], ['{', '<STMTS>', '}']],
             '<STMTS>': [['<STMT>', '<STMTS>'], []]
         },
         'start': '<STMTS>',
         'terminals': set(['if', 'then', 'while', 'do', '->', 'zero?',
                           'not', '++', '--', 'id', 'constant', '{', '}']),
         'nonterminals': set(['<STMT>', '<STMTS>', '<BLOCK>', '<TERM>',
                              '<EXPR>']),
         'first': {
             'if': set(['if']),
             'then': set(['then']),
             'while': set(['while']),
             'do': set(['do']),
             '->': set(['->']),
             'zero?': set(['zero?']),
             'not': set(['not']),
             '++': set(['++']),
             '--': set(['--']),
             'id': set(['id']),
             'constant': set(['constant']),
             '{': set(['{']),
             '}': set(['}']),
             '<STMT>': set(['constant', '++', 'zero?', 'while', 'not', '--',
                            'id', 'if']),
             '<STMTS>': set([ContextFreeGrammar.epsilon(), 'constant', '++', 'zero?', 'while', 'not',
                             '--', 'id', 'if']),
             '<BLOCK>': set(['constant', '++', 'zero?', 'while', 'not', '--',
                             '{', 'id', 'if']),
             '<TERM>': set(['constant', 'id']),
             '<EXPR>': set(['++', 'not', 'constant', 'zero?', '--', 'id'])
         },
         'follow': {
             '<STMT>': set([ContextFreeGrammar.end_of_input(), 'constant', '++', 'not', 'while', 'zero?',
                            '--', '}', 'id', 'if']),
             '<STMTS>': set([ContextFreeGrammar.end_of_input(), '}']),
             '<BLOCK>': set([]),
             '<TERM>': set([ContextFreeGrammar.end_of_input(), 'then', 'constant', 'do', 'not', 'id', 'if',
                            '++', '--', 'while', 'zero?', '->', '}']),
             '<EXPR>': set([ContextFreeGrammar.end_of_input(), 'then', 'constant', 'do', '++', '--',
                            'while', 'not', 'zero?', '}', 'id', 'if'])
         },
         'rules': [
             ('<STMT>', ['if', '<EXPR>', 'then', '<STMT>']),
             ('<STMT>', ['while', '<EXPR>', 'do', '<STMT>']),
             ('<STMT>', ['<EXPR>']),
             ('<EXPR>', ['<TERM>', '->', 'id']),
             ('<EXPR>', ['zero?', '<TERM>']),
             ('<EXPR>', ['not', '<EXPR>']),
             ('<EXPR>', ['++', 'id']),
             ('<EXPR>', ['--', 'id']),
             ('<TERM>', ['id']),
             ('<TERM>', ['constant']),
             ('<BLOCK>', ['<STMT>']),
             ('<BLOCK>', ['{', '<STMTS>', '}']),
             ('<STMTS>', ['<STMT>', '<STMTS>']),
             ('<STMTS>', [])
         ],
         'table': [
             [' ', ContextFreeGrammar.end_of_input(), 'then', 'constant', 'do', '++', 'zero?', 'while',
              'not', '--', '{', '->', '}', 'id', 'if'],
             ['<STMT>', set([]), set([]), set([2]), set([]), set([2]),
              set([2]), set([1]), set([2]), set([2]), set([]), set([]),
              set([]), set([2]), set([0])],
             ['<EXPR>', set([]), set([]), set([3]), set([]), set([6]),
              set([4]), set([]), set([5]), set([7]), set([]), set([]),
              set([]), set([3]), set([])],
             ['<BLOCK>', set([]), set([]), set([10]), set([]), set([10]),
              set([10]), set([10]), set([10]), set([10]), set([11]),
              set([]), set([]), set([10]), set([10])],
             ['<STMTS>', set([13]), set([]), set([12]), set([]), set([12]),
              set([12]), set([12]), set([12]), set([12]), set([]), set([]),
              set([13]), set([12]), set([12])],
             ['<TERM>', set([]), set([]), set([9]), set([]), set([]),
              set([]), set([]), set([]), set([]), set([]), set([]), set([]),
              set([8]), set([])]
         ]
     })