Browse Source

BUGFIX: Fixes a subtle bug in the LALR(1) parser. See the new test for details.

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.5.1
Erez Shinan 7 years ago
parent
commit
64d141e486
2 changed files with 19 additions and 3 deletions
  1. +3
    -3
      lark/parsers/lalr_parser.py
  2. +16
    -0
      tests/test_parser.py

+ 3
- 3
lark/parsers/lalr_parser.py View File

@@ -34,7 +34,7 @@ class Parser(object):


raise UnexpectedToken(token, expected, seq, i) raise UnexpectedToken(token, expected, seq, i)


def reduce(rule, size):
def reduce(rule, size, end=False):
if size: if size:
s = value_stack[-size:] s = value_stack[-size:]
del state_stack[-size:] del state_stack[-size:]
@@ -44,7 +44,7 @@ class Parser(object):


res = self.callbacks[rule](s) res = self.callbacks[rule](s)


if len(state_stack) == 1 and rule.origin == self.analysis.start_symbol:
if end and len(state_stack) == 1 and rule.origin == self.analysis.start_symbol:
return res return res


_action, new_state = get_action(rule.origin) _action, new_state = get_action(rule.origin)
@@ -73,7 +73,7 @@ class Parser(object):
while True: while True:
_action, rule = get_action('$end') _action, rule = get_action('$end')
assert _action == 'reduce' assert _action == 'reduce'
res = reduce(*rule)
res = reduce(*rule, end=True)
if res: if res:
assert state_stack == [self.analysis.init_state_idx] and not value_stack, len(state_stack) assert state_stack == [self.analysis.init_state_idx] and not value_stack, len(state_stack)
return res return res


+ 16
- 0
tests/test_parser.py View File

@@ -584,6 +584,22 @@ def _make_parser_test(LEXER, PARSER):
self.assertEqual(tree.children, ['a', 'A']) self.assertEqual(tree.children, ['a', 'A'])




def test_reduce_cycle(self):
"""Tests an edge-condition in the LALR parser, in which a transition state looks exactly like the end state.
It seems that the correct solution is to explicitely distinguish finalization in the reduce() function.
"""

l = _Lark("""
term: A
| term term

A: "a"

""", start='term')

tree = l.parse("aa")
self.assertEqual(len(tree.children), 2)









Loading…
Cancel
Save