mirror of
https://github.com/davidhalter/parso.git
synced 2025-12-08 21:54:54 +08:00
Refactor the ambiguity tests a bit, see #70
This commit is contained in:
@@ -141,6 +141,9 @@ class NFAArc(object):
|
|||||||
self.next = next_
|
self.next = next_
|
||||||
self.nonterminal_or_string = nonterminal_or_string
|
self.nonterminal_or_string = nonterminal_or_string
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<%s: %s>' % (self.__class__.__name__, self.nonterminal_or_string)
|
||||||
|
|
||||||
|
|
||||||
class NFAState(object):
|
class NFAState(object):
|
||||||
def __init__(self, from_rule):
|
def __init__(self, from_rule):
|
||||||
|
|||||||
@@ -292,41 +292,22 @@ def test_left_recursion():
|
|||||||
generate_grammar('foo: foo NAME\n', tokenize.PythonTokenTypes)
|
generate_grammar('foo: foo NAME\n', tokenize.PythonTokenTypes)
|
||||||
|
|
||||||
|
|
||||||
def test_ambiguities():
|
@pytest.mark.parametrize(
|
||||||
with pytest.raises(
|
'grammar, error_match', [
|
||||||
ValueError,
|
['foo: bar | baz\nbar: NAME\nbaz: NAME\n',
|
||||||
match=r"foo is ambiguous.*given a TokenType\(NAME\).*bar or baz"
|
r"foo is ambiguous.*given a TokenType\(NAME\).*bar or baz"],
|
||||||
):
|
['''foo: bar | baz\nbar: 'x'\nbaz: "x"\n''',
|
||||||
generate_grammar('foo: bar | baz\nbar: NAME\nbaz: NAME\n', tokenize.PythonTokenTypes)
|
r"foo is ambiguous.*given a ReservedString\(x\).*bar or baz"],
|
||||||
|
['''foo: bar | 'x'\nbar: 'x'\n''',
|
||||||
with pytest.raises(
|
r"foo is ambiguous.*given a ReservedString\(x\).*bar or foo"],
|
||||||
ValueError,
|
# An ambiguity with the second (not the first) child of a production
|
||||||
match=r"foo is ambiguous.*given a ReservedString\(x\).*bar or baz"
|
['outer: "a" [inner] "b" "c"\ninner: "b" "c" [inner]\n',
|
||||||
):
|
r"outer is ambiguous.*given a ReservedString\(b\).*inner or outer"],
|
||||||
generate_grammar('''foo: bar | baz\nbar: 'x'\nbaz: "x"\n''', tokenize.PythonTokenTypes)
|
# An ambiguity hidden by a level of indirection (middle)
|
||||||
|
['outer: "a" [middle] "b" "c"\nmiddle: inner\ninner: "b" "c" [inner]\n',
|
||||||
with pytest.raises(
|
r"outer is ambiguous.*given a ReservedString\(b\).*middle or outer"],
|
||||||
ValueError,
|
]
|
||||||
match=r"foo is ambiguous.*given a ReservedString\(x\).*bar or foo"
|
|
||||||
):
|
|
||||||
generate_grammar('''foo: bar | 'x'\nbar: 'x'\n''', tokenize.PythonTokenTypes)
|
|
||||||
|
|
||||||
# an ambiguity with the second (not the first) child of a production
|
|
||||||
with pytest.raises(
|
|
||||||
ValueError,
|
|
||||||
match=r"outer is ambiguous.*given a ReservedString\(b\).*inner or outer"
|
|
||||||
):
|
|
||||||
generate_grammar(
|
|
||||||
'outer: "a" [inner] "b" "c"\ninner: "b" "c" [inner]\n',
|
|
||||||
tokenize.PythonTokenTypes,
|
|
||||||
)
|
|
||||||
|
|
||||||
# an ambiguity hidden by a level of indirection (middle)
|
|
||||||
with pytest.raises(
|
|
||||||
ValueError,
|
|
||||||
match=r"outer is ambiguous.*given a ReservedString\(b\).*middle or outer"
|
|
||||||
):
|
|
||||||
generate_grammar(
|
|
||||||
'outer: "a" [middle] "b" "c"\nmiddle: inner\ninner: "b" "c" [inner]\n',
|
|
||||||
tokenize.PythonTokenTypes,
|
|
||||||
)
|
)
|
||||||
|
def test_ambiguities(grammar, error_match):
|
||||||
|
with pytest.raises(ValueError, match=error_match):
|
||||||
|
generate_grammar(grammar, tokenize.PythonTokenTypes)
|
||||||
|
|||||||
Reference in New Issue
Block a user