aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2023-09-16 02:44:19 +0200
committerHugo Hörnquist <hugo@lysator.liu.se>2023-09-19 07:50:48 +0200
commit0397a11f1a1f1c63f3d983b2ddda08569f1e3acd (patch)
treed867ca45440642d8f1082ebae21590d408a637ba
parentGet parser formatter "working". (diff)
downloadmuppet-strings-0397a11f1a1f1c63f3d983b2ddda08569f1e3acd.tar.gz
muppet-strings-0397a11f1a1f1c63f3d983b2ddda08569f1e3acd.tar.xz
Add more tests.
-rw-r--r--tests/test_parser_combinator.py191
-rw-r--r--tests/test_util.py14
2 files changed, 205 insertions, 0 deletions
diff --git a/tests/test_parser_combinator.py b/tests/test_parser_combinator.py
new file mode 100644
index 0000000..c718b45
--- /dev/null
+++ b/tests/test_parser_combinator.py
@@ -0,0 +1,191 @@
+from muppet.parser_combinator import (
+ MatchLiteral,
+ MatchObject,
+ ParseDirective,
+ ParseError,
+ ParserCombinator,
+ all_,
+ char,
+ complement,
+ count,
+ digit,
+ hexdig,
+ line_comment,
+ many,
+ many1,
+ name,
+ nop,
+ not_,
+ optional,
+ s,
+ tag,
+ ws,
+ delimited,
+ discard,
+ space,
+)
+
+
+def lit(x):
+ return MatchLiteral(matched=x)
+
+
+def test_partial():
+ data = "123 Hello"
+
+ parser = ParserCombinator(data)
+
+ assert [lit("123")] == parser.get(many(digit))
+ assert " Hello" == parser.remaining()
+
+
+def test_char():
+ parser = ParserCombinator("Hello!")
+ assert [lit('H')] == parser.get(char)
+ assert [lit('e')] == parser.get(char)
+ assert "llo!" == parser.remaining()
+
+
+def test_nop():
+ parser = ParserCombinator("Hello!")
+ assert [] == parser.get(nop)
+ assert "Hello!" == parser.remaining()
+
+
+def test_digit():
+ p1 = ParserCombinator("123")
+ assert [lit('1')] == p1.get(digit)
+ p2 = ParserCombinator("Hello")
+ try:
+ p2.get(digit)
+ assert False, "Parser should have failed, but didn't"
+ except ParseError:
+ assert "Hello" == p2.remaining()
+
+
+def test_consume():
+ p = ParserCombinator("Hello")
+ try:
+ p.get([char, digit])
+ assert False, "Parser should have failed, but didn't"
+ except ParseError:
+ assert "ello" == p.remaining()
+
+
+def test_hexdig():
+ pass
+
+
+def test_space():
+ pass
+
+# --------------------------------------------------
+
+
+def test_many():
+ p1 = ParserCombinator("Hello, World!")
+
+ assert [lit("Hello, World!")] == p1.get(many(char))
+
+ p2 = ParserCombinator("")
+ assert [] == p2.get(many(char))
+
+
+def test_many1():
+ p1 = ParserCombinator("Hello, World!")
+
+ assert [lit("Hello, World!")] == p1.get(many1(char))
+
+ p2 = ParserCombinator("")
+ try:
+ p2.get(many1(char))
+ assert False, "Parser should have failed, but didn't"
+ except ParseError:
+ assert True
+
+
+def test_count():
+ p1 = ParserCombinator("ABCDE")
+ assert [lit("A")] == p1.get(count(s("A"), 1, 3))
+
+ p2 = ParserCombinator("AAAAA")
+ assert [lit("AAA")] == p2.get(count(s("A"), 1, 3))
+
+ p3 = ParserCombinator("BBBBB")
+ assert [] == p3.get(count(s("A"), 3))
+
+ p4 = ParserCombinator("AAAAA")
+ assert [lit("AAA")] == p4.get(count(s("A"), 3))
+
+
+def test_optional():
+ p1 = ParserCombinator("ABC")
+ assert [lit("A")] == p1.get(optional(s("A")))
+ assert "BC" == p1.remaining()
+
+ p2 = ParserCombinator("ABC")
+ assert [] == p2.get(optional(s("B")))
+ assert "ABC" == p2.remaining()
+
+
+def test_ws():
+ p1 = ParserCombinator("Hello")
+ assert [] == p1.get(ws)
+
+ p2 = ParserCombinator("\t \n\r Hello")
+ assert [lit("\t \n\r ")] == p2.get(ws)
+
+
+def test_discard():
+ p1 = ParserCombinator("Hello")
+ assert [] == p1.get(discard(s("He")))
+ assert "llo" == p1.remaining()
+
+ p2 = ParserCombinator("Hello!")
+ assert [lit("ll")] == p2.get(discard(s("He")) & s("ll") & discard(s("o")))
+ assert "!" == p2.remaining()
+
+
+def handle_int(xs: list[MatchObject]) -> list[int]:
+ """Convert matched to an integer."""
+ return [int(xs[0].matched)]
+
+
+def test_delimited():
+ number = many(digit) @ handle_int
+
+ p1 = ParserCombinator("1,20,2")
+ assert [1, lit(","), 20, lit(","), 2] == p1.get(delimited(s(","), number))
+
+ p2 = ParserCombinator("1,20,2")
+ assert [1, 20, 2] == p2.get(delimited(discard(s(",")), number))
+
+
+def test_all():
+ p1 = ParserCombinator("123")
+ assert [lit("1")] == p1.get(all_(char, digit))
+
+
+def test_complement_1():
+ p1 = ParserCombinator("Hello, World!")
+ assert [lit("H")] == p1.get(all_(~ space, char))
+
+
+def test_complement_2():
+ p1 = ParserCombinator("Hello, World!")
+ assert [lit("Hello,")] == p1.get(many(all_(~ space, char)))
+
+
+def test_complement():
+ p = ParserCombinator("Hello")
+ assert [lit("He")] == p.get(many(complement("l")))
+
+
+def test_stringifiers():
+ assert "'a'" == str(s("a"))
+ assert "~ 'a'" == repr(~ s("a"))
+ assert "x" == str(name("x", space & space))
+ assert "('a' & 'b')" == str(s('a') & s('b'))
+ assert "('a' | 'b')" == str(s('a') | s('b'))
+ assert "char" == str(char)
+ assert "nop" == str(nop)
diff --git a/tests/test_util.py b/tests/test_util.py
new file mode 100644
index 0000000..f382835
--- /dev/null
+++ b/tests/test_util.py
@@ -0,0 +1,14 @@
+from muppet.util import group_by, concatenate
+
+
+def test_group_by():
+ groups = group_by(lambda x: x % 3, range(10))
+ assert len(groups) == 3
+ assert groups[0] == [0, 3, 6, 9]
+ assert groups[1] == [1, 4, 7]
+ assert groups[2] == [2, 5, 8]
+
+
+def test_concatenate():
+ assert concatenate([[1, 2], [3, 4]]) == [1, 2, 3, 4]
+ assert concatenate([[1, [2]], [3, 4]]) == [1, [2], 3, 4]