Skip to content

Commit

Permalink
Merge pull request #110 from stanislaw/stanislaw/more_tests
Browse files Browse the repository at this point in the history
tests/test_parsing_expressions: more specific assert statements
  • Loading branch information
igordejanovic committed Apr 7, 2023
2 parents 299e6cc + d0ee7f1 commit 7523102
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 34 deletions.
2 changes: 1 addition & 1 deletion arpeggio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ def _parse(self, parser):

class UnorderedGroup(Repetition):
"""
Will try to match all of the parsing expression in any order.
Will try to match all the parsing expressions in any order.
"""
def _parse(self, parser):
results = []
Expand Down
205 changes: 172 additions & 33 deletions arpeggio/tests/test_parsing_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,20 @@ def grammar():
assert str(parsed) == "c | "
assert repr(parsed) == "[ 'c' [0], EOF [1] ]"

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("ab")
assert (
"Expected EOF at position (1, 2) => 'a*b'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("bb")
assert (
"Expected EOF at position (1, 2) => 'b*b'."
) == str(e.value)


def test_unordered_group():

def grammar():
return UnorderedGroup("a", "b", "c"), EOF

Expand All @@ -61,14 +66,25 @@ def grammar():
assert str(parsed) == "b | a | c | "
assert repr(parsed) == "[ 'b' [0], 'a' [2], 'c' [4], EOF [5] ]"

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a b a c")
assert (
"Expected 'c' at position (1, 5) => 'a b *a c'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a c")
assert (
"Expected 'b' at position (1, 4) => 'a c*'."
) == str(e.value)

# FIXME: This test looks strange. The expectation would rather be:
# Expected 'a' or 'c' at position (1, 3)
with pytest.raises(NoMatch):
parser.parse("b b a c")
assert (
"Expected 'b' at position (1, 4) => 'b b* a c'."
) == str(e.value)


def test_unordered_group_with_separator():
Expand All @@ -84,23 +100,41 @@ def grammar():
assert repr(parsed) == \
"[ 'b' [0], ',' [1], 'a' [3], ',' [5], 'c' [7], EOF [8] ]"

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a, b, a, c")
assert (
"Expected 'c' at position (1, 7) => 'a, b, *a, c'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a, c")
assert (
"Expected ',' or 'b' at position (1, 5) => 'a, c*'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("b, b, a, c")
assert (
"Expected 'a' or 'c' at position (1, 4) => 'b, *b, a, c'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse(",a, b, c")
assert (
"Expected 'a' or 'b' or 'c' at position (1, 1) => '*,a, b, c'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a, b, c,")
assert (
"Expected EOF at position (1, 8) => 'a, b, c*,'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a, ,b, c")
assert (
"Expected 'b' or 'c' at position (1, 4) => 'a, *,b, c'."
) == str(e.value)


def test_unordered_group_with_optionals():
Expand All @@ -119,11 +153,17 @@ def grammar():
parsed = parser.parse("a c")
assert str(parsed) == "a | c | "

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a b c b")
assert (
"Expected EOF at position (1, 7) => 'a b c *b'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a b ")
assert (
"Expected 'c' at position (1, 5) => 'a b *'."
) == str(e.value)


def test_unordered_group_with_optionals_and_separator():
Expand All @@ -142,20 +182,38 @@ def grammar():
parsed = parser.parse("a, c")
assert parsed

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a, b, c, b")
assert (
"Expected EOF at position (1, 8) => 'a, b, c*, b'."
) == str(e.value)

# FIXME: This looks strange. Shouldn't this expect ',' (and also 'c')?
with pytest.raises(NoMatch):
parser.parse("a, b ")
assert (
"Expected EOF at position (1, 8) => 'a, b *'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a, c, ")
assert (
"Expected 'b' at position (1, 7) => 'a, c, *'."
) == str(e.value)

# FIXME: This looks strange. Shouldn't be ',' at position 6?
with pytest.raises(NoMatch):
parser.parse("a, b c ")
assert (
"Expected 'b' at position (1, 7) => 'a, b c* '."
) == str(e.value)

# FIXME: Should the separators work before the unordered group?
with pytest.raises(NoMatch):
parser.parse(",a, c ")
assert (
"Expected 'b' at position (1, 7) => ',a, c *'."
) == str(e.value)


def test_zero_or_more():
Expand All @@ -176,8 +234,11 @@ def grammar():
assert str(parsed) == ""
assert repr(parsed) == "[ EOF [0] ]"

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("bbb")
assert (
"Expected 'a' or EOF at position (1, 1) => '*bbb'."
) == str(e.value)


def test_zero_or_more_with_separator():
Expand All @@ -201,17 +262,33 @@ def grammar():
assert str(parsed) == ""
assert repr(parsed) == "[ EOF [0] ]"

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("aa a")
assert (
"Expected ',' or EOF at position (1, 2) => 'a*a a'."
) == str(e.value)

# FIXME: This looks strange. Can separator be before the first element?
with pytest.raises(NoMatch):
parser.parse(",a,a ,a")
assert (
"Expected ',' or EOF at position (1, 2) => ',*a,a ,a'."
) == str(e.value)

# FIXME: The position looks strange.
# Should this be 'a' or 'EOF' at the position of the last comma?
with pytest.raises(NoMatch):
parser.parse("a,a ,a,")
assert (
"Expected ',' or EOF at position (1, 2) => 'a*,a ,a,'."
) == str(e.value)

# FIXME: Shouldn't this be 'a' or 'EOF' at (1, 1)?
with pytest.raises(NoMatch):
parser.parse("bbb")
assert (
"Expected ',' or EOF at position (1, 2) => 'b*bb'."
) == str(e.value)


def test_zero_or_more_with_optional_separator():
Expand All @@ -237,14 +314,23 @@ def grammar():

parser.parse("aa a")

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse(",a,a ,a")
assert (
"Expected 'a' or EOF at position (1, 1) => '*,a,a ,a'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a,a ,a,")
assert (
"Expected 'a' at position (1, 8) => 'a,a ,a,*'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("bbb")
assert (
"Expected 'a' or EOF at position (1, 1) => '*bbb'."
) == str(e.value)


def test_one_or_more():
Expand All @@ -262,11 +348,17 @@ def grammar():

parser.parse("ab")

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("")
assert (
"Expected 'a' at position (1, 1) => '*'."
) == str(e.value)

with pytest.raises(NoMatch):
parser.parse("b")
assert (
"Expected 'a' at position (1, 1) => '*b'."
) == str(e.value)


def test_one_or_more_with_separator():
Expand All @@ -285,20 +377,37 @@ def grammar():

parser.parse("a b")

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("")
assert (
"Expected 'a' at position (1, 1) => '*'."
) == str(e.value)

with pytest.raises(NoMatch):
parser.parse("b")
assert (
"Expected 'a' at position (1, 1) => '*b'."
) == str(e.value)

# FIXME: Should it be like this? Or ',' at (1, 2)?
with pytest.raises(NoMatch):
parser.parse("a a b")
assert (
"Expected 'a' at position (1, 1) => '*a a b'."
) == str(e.value)

# FIXME: Should it be like this? Or ',' at (1, 2)?
with pytest.raises(NoMatch):
parser.parse("a a, b")
assert (
"Expected 'a' at position (1, 1) => '*a a, b'."
) == str(e.value)

with pytest.raises(NoMatch):
parser.parse(", a, a b")
assert (
"Expected 'a' at position (1, 1) => '*, a, a b'."
) == str(e.value)


def test_one_or_more_with_optional_separator():
Expand All @@ -317,17 +426,29 @@ def grammar():

parser.parse("a b")

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("")
assert (
"Expected 'a' at position (1, 1) => '*'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("b")
assert (
"Expected 'a' at position (1, 1) => '*b'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("a a, b")
assert (
"Expected 'a' at position (1, 6) => 'a a, *b'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse(", a, a b")
assert (
"Expected 'a' at position (1, 1) => '*, a, a b'."
) == str(e.value)


def test_optional():
Expand All @@ -347,11 +468,17 @@ def grammar():
assert str(parsed) == "b | "
assert repr(parsed) == "[ 'b' [0], EOF [1] ]"

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("aab")
assert (
"Expected 'b' at position (1, 2) => 'a*ab'."
) == str(e.value)

with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("")
assert (
"Expected 'a' or 'b' at position (1, 1) => '*'."
) == str(e.value)


# Syntax predicates
Expand All @@ -368,12 +495,18 @@ def grammar():
assert repr(parsed) == "[ 'a' [0], 'b' [1], EOF [2] ]"

# 'And' will try to match 'b' and fail so 'c' will never get matched
with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("ac")
assert (
"Expected 'b' at position (1, 2) => 'a*c'."
) == str(e.value)

# 'And' will not consume 'b' from the input so second 'b' will never match
with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("abb")
assert (
"Expected EOF at position (1, 3) => 'ab*b'."
) == str(e.value)


def test_not():
Expand All @@ -388,10 +521,16 @@ def grammar():
assert str(parsed) == "a | c | "
assert repr(parsed) == "[ 'a' [0], 'c' [1], EOF [2] ]"

# Not will will fail on 'b'
with pytest.raises(NoMatch):
# Not will fail on 'b'
with pytest.raises(NoMatch) as e:
parser.parse("ab")
assert (
"Not expected input at position (1, 2) => 'a*b'."
) == str(e.value)

# And will not consume 'c' from the input so 'b' will never match
with pytest.raises(NoMatch):
with pytest.raises(NoMatch) as e:
parser.parse("acb")
assert (
"Expected EOF at position (1, 3) => 'ac*b'."
) == str(e.value)

0 comments on commit 7523102

Please sign in to comment.