From e723b3e74b0b674b17fa0229eb1d6a483e6845d2 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 13 Jul 2019 20:14:52 +0200 Subject: [PATCH] Refactor the ambiguity tests a bit, see #70 --- parso/pgen2/grammar_parser.py | 3 ++ test/test_pgen2.py | 57 ++++++++++++----------------------- 2 files changed, 22 insertions(+), 38 deletions(-) diff --git a/parso/pgen2/grammar_parser.py b/parso/pgen2/grammar_parser.py index 623a455..0be7209 100644 --- a/parso/pgen2/grammar_parser.py +++ b/parso/pgen2/grammar_parser.py @@ -141,6 +141,9 @@ class NFAArc(object): self.next = next_ self.nonterminal_or_string = nonterminal_or_string + def __repr__(self): + return '<%s: %s>' % (self.__class__.__name__, self.nonterminal_or_string) + class NFAState(object): def __init__(self, from_rule): diff --git a/test/test_pgen2.py b/test/test_pgen2.py index 6ec081b..30b0c23 100644 --- a/test/test_pgen2.py +++ b/test/test_pgen2.py @@ -292,41 +292,22 @@ def test_left_recursion(): generate_grammar('foo: foo NAME\n', tokenize.PythonTokenTypes) -def test_ambiguities(): - with pytest.raises( - ValueError, - match=r"foo is ambiguous.*given a TokenType\(NAME\).*bar or baz" - ): - generate_grammar('foo: bar | baz\nbar: NAME\nbaz: NAME\n', tokenize.PythonTokenTypes) - - with pytest.raises( - ValueError, - match=r"foo is ambiguous.*given a ReservedString\(x\).*bar or baz" - ): - generate_grammar('''foo: bar | baz\nbar: 'x'\nbaz: "x"\n''', tokenize.PythonTokenTypes) - - with pytest.raises( - 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, - ) +@pytest.mark.parametrize( + 'grammar, error_match', [ + ['foo: bar | baz\nbar: NAME\nbaz: NAME\n', + r"foo is ambiguous.*given a TokenType\(NAME\).*bar or baz"], + ['''foo: bar | baz\nbar: 'x'\nbaz: "x"\n''', + r"foo is ambiguous.*given a ReservedString\(x\).*bar or baz"], + ['''foo: bar | 'x'\nbar: 'x'\n''', + r"foo is ambiguous.*given a ReservedString\(x\).*bar or foo"], + # An ambiguity with the second (not the first) child of a production + ['outer: "a" [inner] "b" "c"\ninner: "b" "c" [inner]\n', + r"outer is ambiguous.*given a ReservedString\(b\).*inner or outer"], + # An ambiguity hidden by a level of indirection (middle) + ['outer: "a" [middle] "b" "c"\nmiddle: inner\ninner: "b" "c" [inner]\n', + r"outer is ambiguous.*given a ReservedString\(b\).*middle or outer"], + ] +) +def test_ambiguities(grammar, error_match): + with pytest.raises(ValueError, match=error_match): + generate_grammar(grammar, tokenize.PythonTokenTypes)