示例#1
0
    def test_repeated_layouts(self):
        class Block(Node):
            pass

        def space_layout(dispatcher, node, before, after, prev):
            yield SimpleChunk(' ')

        def newline_layout(dispatcher, node, before, after, prev):
            yield SimpleChunk('n')

        dispatcher = Dispatcher(
            definitions={
                'Node': (Space, ),
                'Block': (JoinAttr(Iter(), value=(Newline, )), )
            },
            token_handler=None,  # not actually produced
            layout_handlers={
                Space: space_layout,
                Newline: newline_layout,
                # drop the subsequent space
                (Newline, Space): newline_layout,
            },
            deferrable_handlers={},
        )

        n0 = Block([])
        self.assertEqual('', ''.join(c.text for c in walk(dispatcher, n0)))
        n1 = Block([Node([])] * 1)
        self.assertEqual(' ', ''.join(c.text for c in walk(dispatcher, n1)))
        n2 = Block([Node([])] * 2)
        self.assertEqual(' n', ''.join(c.text for c in walk(dispatcher, n2)))
        n3 = Block([Node([])] * 3)
        self.assertEqual(' nn', ''.join(c.text for c in walk(dispatcher, n3)))
示例#2
0
 def test_deferrable_handler_literal_continuation(self):
     dispatcher = Dispatcher({}, None, {}, {})
     node = Node()
     node.value = '"foo\\\r\nbar"'
     self.assertEqual(
         '"foobar"',
         deferrable_handler_literal_continuation(dispatcher, node))
示例#3
0
    def test_nested_layouts(self):
        def simple_layout_space(dispatcher, node, before, after, prev):
            yield SimpleChunk(' ')

        def nested_layout(dispatcher, node, before, after, prev):
            yield SimpleChunk('?')

        def noop(*a, **kw):
            return
            yield  # pragma: no cover

        dispatcher = Dispatcher(
            definitions={'Node': (
                Space,
                JoinAttr(Iter(), value=(Space, )),
            )},
            token_handler=noop,
            layout_handlers={
                Space: simple_layout_space,
                (Space, Space): noop,
                ((Space, Space), Space): nested_layout,
            },
            deferrable_handlers={},
        )

        n0 = Node([])
        self.assertEqual(' ', ''.join(c.text for c in walk(dispatcher, n0)))
        n1 = Node([n0])
        self.assertEqual('', ''.join(c.text for c in walk(dispatcher, n1)))
        n2 = Node([n1, n0])
        self.assertEqual('?', ''.join(c.text for c in walk(dispatcher, n2)))
示例#4
0
    def test_layout_handler_newline_optional_pretty(self):
        # yes using the lteral <CR><LF> is pretty hilarious, but just to
        # show that this is implemented to support whatever.
        dispatcher = Dispatcher({}, None, {}, {}, newline_str='<CR><LF>')
        newline = [('<CR><LF>', 0, 0, None, None)]

        def run(before, after, prev):
            return list(
                layout_handler_newline_optional_pretty(
                    # node is not used.
                    dispatcher,
                    None,
                    before,
                    after,
                    prev))

        # brand new empty program
        self.assertEqual(run(None, None, None), empty)
        # first line of a program
        self.assertEqual(run(None, 'function', None), empty)
        # previous token produced a newline
        self.assertEqual(run('\n', 'function', None), empty)
        # next token produced a newline
        self.assertEqual(run('}', '\n', None), empty)
        # Previous layout produced a newline
        self.assertEqual(run('}', '  ', '\n'), empty)

        # Previous layout produced a newline, with the custom str
        self.assertEqual(run('}', '  ', '<CR><LF>'), empty)

        # The first layout rule
        self.assertEqual(run(';', 'function', None), newline)
示例#5
0
    def test_space_minimum(self):
        # initialise a barebone dispatcher.
        dispatcher = Dispatcher({}, None, {}, {})

        def run(a, b):
            return list(
                layout_handler_space_minimum(
                    # node and prev are not used.
                    dispatcher,
                    None,
                    a,
                    b,
                    None))

        self.assertEqual(run(None, None), empty)

        # for Assign
        self.assertEqual(run('a', ':'), empty)
        self.assertEqual(run('a', '='), empty)

        # for Unary
        self.assertEqual(run('!', 'a'), empty)
        self.assertEqual(run('f', '1'), space)
        self.assertEqual(run('1', 'f'), space)
        self.assertEqual(run('f', '+'), empty)
        self.assertEqual(run('f', '-'), empty)
        self.assertEqual(run('-', 'f'), empty)
        self.assertEqual(run('+', 'f'), empty)
        self.assertEqual(run('+', '-'), empty)
        self.assertEqual(run('-', '-'), space)
        self.assertEqual(run('+', '+'), space)
        self.assertEqual(run(',', 'y'), empty)
        self.assertEqual(run('1', ','), empty)
示例#6
0
    def walk(self, dispatcher, node):
        """
        Walk through the node with a custom dispatcher for extraction of
        details that are required.
        """

        deferrable_handlers = {
            Declare: self.declare,
            Resolve: self.register_reference,
        }
        layout_handlers = {
            PushScope: self.push_scope,
            PopScope: self.pop_scope,
            PushCatch: self.push_catch,
            # should really be different, but given that the
            # mechanism is within the same tree, the only difference
            # would be sanity check which should have been tested in
            # the first place in the primitives anyway.
            PopCatch: self.pop_scope,
        }

        if not self.shadow_funcname:
            layout_handlers[ResolveFuncName] = self.shadow_reference

        local_dispatcher = Dispatcher(
            definitions=dict(dispatcher),
            token_handler=None,
            layout_handlers=layout_handlers,
            deferrable_handlers=deferrable_handlers,
        )
        return list(walk(local_dispatcher, node))
示例#7
0
    def test_indentation(self):
        # initialise a barebone dispatcher.
        dispatcher = Dispatcher({}, None, {}, {}, indent_str='<TAB>')
        layout = indent()()['layout_handlers']
        newline = ('\n', 0, 0, None, None)
        indent1 = ('<TAB>', None, None, None, None)
        indent2 = ('<TAB><TAB>', None, None, None, None)

        def run(rule, before=None):
            return layout[rule](dispatcher, None, before, None, None)

        self.assertEqual(list(run(Newline)), [newline])
        self.assertIsNone(run(Indent))
        self.assertEqual(list(run(Newline)), [newline, indent1])
        self.assertIsNone(run(Indent))
        self.assertEqual(list(run(Newline)), [newline, indent2])

        self.assertIsNone(run(Dedent))
        self.assertEqual(list(run(Newline)), [newline, indent1])
        self.assertIsNone(run(Dedent))
        self.assertEqual(list(run(Newline)), [newline])

        # negative shouldn't matter
        self.assertIsNone(run(Dedent))
        self.assertEqual(list(run(Newline)), [newline])
        # should move it back on the right track.
        self.assertIsNone(run(Indent))
        self.assertEqual(list(run(Newline)), [newline])

        layout = indent(indent_str='    ')()['layout_handlers']
        self.assertIsNone(run(Indent))
        self.assertEqual(list(run(Newline)),
                         [newline, ('    ', None, None, None, None)])

        self.assertEqual(list(run(OptionalNewline, before='\n')), [])
示例#8
0
    def test_core_structures(self):
        # initialise a barebone dispatcher.
        node = Node()
        dispatcher = Dispatcher({}, None, {}, {})
        self.assertEqual([(
            '{',
            0,
            0,
            None,
            None,
        )], list(layout_handler_openbrace(dispatcher, node, None, None, None)))
        self.assertEqual([(
            '}',
            0,
            0,
            None,
            None,
        )], list(layout_handler_closebrace(dispatcher, node, None, None,
                                           None)))
        self.assertEqual([(
            ';',
            0,
            0,
            None,
            None,
        )], list(layout_handler_semicolon(dispatcher, node, None, None, None)))

        # with token map
        node._token_map = {
            '{': [(0, 1, 1)],
            '}': [(1, 1, 2)],
            ';': [(2, 1, 3)],
        }
        self.assertEqual([(
            '{',
            1,
            1,
            None,
            None,
        )], list(layout_handler_openbrace(dispatcher, node, None, None, None)))
        self.assertEqual([(
            '}',
            1,
            2,
            None,
            None,
        )], list(layout_handler_closebrace(dispatcher, node, None, None,
                                           None)))
        self.assertEqual([(
            ';',
            1,
            3,
            None,
            None,
        )], list(layout_handler_semicolon(dispatcher, node, None, None, None)))
示例#9
0
    def test_space_optional_pretty(self):
        # initialise a barebone dispatcher.
        dispatcher = Dispatcher({}, None, {}, {})

        def run(a, b):
            return list(
                layout_handler_space_optional_pretty(
                    # node and prev are not used.
                    dispatcher,
                    None,
                    a,
                    b,
                    None))

        # also test out the cases where OptionalSpace was defined.
        self.assertEqual(run(None, None), empty)
        self.assertEqual(run('a', None), empty)
        self.assertEqual(run(None, 'a'), empty)
        # for Assign
        self.assertEqual(run('a', ':'), empty)
        self.assertEqual(run('a', '='), space)
        self.assertEqual(run('1', '='), space)

        self.assertEqual(run('a', '+='), space)
        self.assertEqual(run('a', '-='), space)
        self.assertEqual(run('a', '*='), space)
        self.assertEqual(run('a', '/='), space)
        self.assertEqual(run('a', '%='), space)
        self.assertEqual(run('a', '&='), space)
        self.assertEqual(run('a', '^='), space)
        self.assertEqual(run('a', '|='), space)
        self.assertEqual(run('a', '<<='), space)
        self.assertEqual(run('a', '>>='), space)
        self.assertEqual(run('a', '>>>='), space)

        # these rules are not defined, since they typically shouldn't
        # happen and that BinOp rules should use Space.
        self.assertEqual(run('+', 'a'), empty)
        self.assertEqual(run('-', 'a'), empty)
        self.assertEqual(run('*', 'a'), empty)
        self.assertEqual(run('/', 'a'), empty)

        # for Unary
        self.assertEqual(run('!', 'a'), empty)
        self.assertEqual(run('f', '1'), space)
        self.assertEqual(run('1', 'f'), space)
        self.assertEqual(run('f', '++'), empty)
        self.assertEqual(run('f', '--'), empty)
        self.assertEqual(run('--', 'f'), empty)
        self.assertEqual(run('++', 'f'), empty)
        self.assertEqual(run('+', '-'), empty)
        self.assertEqual(run('-', '+'), empty)
        self.assertEqual(run('-', '-'), space)
        self.assertEqual(run('+', '+'), space)
示例#10
0
    def test_bad_definition_rule(self):
        (token_handler, layout_handlers, deferrable_handlers,
         self.declared_vars) = setup_handlers(self)
        with self.assertRaises(TypeError) as e:
            Dispatcher(
                definitions={'Node': (object(), )},
                token_handler=token_handler,
                layout_handlers=layout_handlers,
                deferrable_handlers=deferrable_handlers,
            )

        self.assertIn(
            "definition for 'Node' contain unsupported rule (got:",
            e.exception.args[0],
        )
示例#11
0
 def setup_defaults(self):
     # provide just enough of the everything that is required.
     token_handler, layout_handlers, deferrable_handlers, declared_vars = (
         setup_handlers(self))
     self.dispatcher = Dispatcher(
         definitions={
             'ES5Program': (
                 children_newline,
                 Newline,
             ),
             'VarStatement': (
                 Text(value='var'),
                 Space,
                 children_comma,
                 Text(value=';'),
             ),
             'VarDecl': (
                 Attr(Declare('identifier')),
                 Space,
                 Operator(value='='),
                 Space,
                 Attr('initializer'),
             ),
             'Identifier': (Attr(Resolve()), ),
             'PropIdentifier': (Attr('value'), ),
             'Number': (Attr('value'), ),
             'DotAccessor': (
                 Attr('node'),
                 Text(value='.'),
                 Attr('identifier'),
             ),
             'FunctionCall': (
                 Attr('identifier'),
                 Attr('args'),
             ),
             'Arguments': (
                 Text(value='('),
                 JoinAttr('items', value=(Text(value=','), Space)),
                 Text(value=')'),
             ),
         },
         token_handler=token_handler,
         layout_handlers=layout_handlers,
         deferrable_handlers=deferrable_handlers,
     )
     self.declared_vars = declared_vars
示例#12
0
    def test_join_attr_issue_36(self):
        # JoinAttr defined with parameter `value=None` resulted in
        # infinite recursion due to the walker will assume that no rule
        # is provided, triggering rule lookup which would repeat the
        # work that was done.

        class Block(Node):
            pass

        token_handler, layout_handlers, deferrable_handlers, declared_vars = (
            setup_handlers(self))
        dispatcher = Dispatcher(
            definitions={
                'Block': (JoinAttr(Iter(), value=None), ),
                'Node': (Text(value='', ), ),
            },
            token_handler=token_handler,
            layout_handlers={},
            deferrable_handlers={},
        )

        nodes = Block([Node([])] * 3)
        self.assertEqual(3, len(list(walk(dispatcher, nodes))))
示例#13
0
 def test_clone_definitions(self):
     marker = tuple()
     dispatcher = Dispatcher({'Node': marker}, {}, {}, {})
     self.assertEqual(dict(dispatcher), {'Node': marker})
示例#14
0
 def test_empty(self):
     dispatcher = Dispatcher({}, {}, {}, {})
     self.assertEqual(dict(dispatcher), {})