diff --git a/.vscode/settings.json b/.vscode/settings.json index dcb1530..f03cc89 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "python.analysis.typeCheckingMode": "basic", - "python.analysis.autoImportCompletions": true + "python.analysis.autoImportCompletions": true, + "python.pythonPath": "./venv/bin/python" } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4dcaf78 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +okipy \ No newline at end of file diff --git a/setup.sh b/setup.sh index 685be52..0079850 100755 --- a/setup.sh +++ b/setup.sh @@ -3,4 +3,5 @@ set -e cd "$(dirname "$(realpath "$0")")" python3 -m venv venv -source venv/bin/activate \ No newline at end of file +source venv/bin/activate +pip install -r requirements.txt \ No newline at end of file diff --git a/tests/cases.py b/tests/cases.py new file mode 100755 index 0000000..ba88e17 --- /dev/null +++ b/tests/cases.py @@ -0,0 +1,70 @@ +#!/bin/env -S python + +from typing import TypeVar, Any +from os.path import dirname +import sys + +sys.path.append(f"{dirname(__file__)}/../src") +from pyalibert import regex, Parser, just, Declare + + +from okipy.lib import Suite + + +# utils +whitespace = just(" ").or_(just("\n")).repeat() +T = TypeVar("T") +def lexeme(p: Parser[T]) -> Parser[T]: + return p << whitespace + + +suite = Suite("cases") + + +@suite.test() +def case_json(ctx): + # Punctuation + lbrace = lexeme(just("{")) + rbrace = lexeme(just("}")) + lbrack = lexeme(just("[")) + rbrack = lexeme(just("]")) + colon = lexeme(just(":")) + comma = lexeme(just(",")) + # Primitives + true = lexeme(just("true")).set(True) + false = lexeme(just("false")).set(False) + null = lexeme(just("null")).set(None) + number = lexeme(regex(r"-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?")).map(float) + just_part = regex(r'[^"\\]+') + just_esc = just("\\") >> ( just("\\") | just("/") | just('"') | just("b").set("\b") | just("f").set("\f") | just("n").set("\n") | just("r").set("\r") | just("t").set("\t") | regex(r"u[0-9a-fA-F]{4}").map(lambda s: chr(int(s[1:], 16)))) + quoted = lexeme(just('"') >> (just_part | just_esc).repeat().map(lambda l: "".join(l)) << just('"')) + # Data structures + json = Declare[Any]() + object_pair = (quoted << colon) & json.parser() + json_object = lbrace >> object_pair.sep_by(comma).map(dict) << rbrace + array = lbrack >> json.parser().sep_by(comma) << rbrack + # Everything + json.define(quoted | number | json_object | array | true | false | null) + json = json.parser() + # asserts + assert json.parse("1") == 1 + assert json.parse('"1"') == "1" + assert json.parse('["1", 1]') == ["1", 1] + assert json.parse('{"1": 1}') == {"1": 1} + assert json.parse(r"""{ + "int": 1, + "just": "hello", + "a list": [1, 2, 3], + "escapes": "\n \u24D2", + "nested": {"x": "y"}, + "other": [true, false, null] + }""") == { + "int": 1, + "just": "hello", + "a list": [1, 2, 3], + "escapes": "\n ⓒ", + "nested": {"x": "y"}, + "other": [True, False, None], + } + +if __name__ == "__main__": suite.run(sys.argv[1:]) diff --git a/tests/inline.py b/tests/inline.py new file mode 100755 index 0000000..8a5b684 --- /dev/null +++ b/tests/inline.py @@ -0,0 +1,12 @@ +#!/bin/env -S python + +from os.path import dirname +import sys + +from okipy.lib import get_inline_suite + +sys.path.append(f"{dirname(__file__)}/../src") +import pyalibert # executes inline tests + + +if __name__ == "__main__": get_inline_suite().run(sys.argv[1:]) diff --git a/tests/json.py b/tests/json.py deleted file mode 100644 index a08535a..0000000 --- a/tests/json.py +++ /dev/null @@ -1,86 +0,0 @@ -from os.path import dirname -import sys - -sys.path.append(f"{dirname(__file__)}/../src") -from party import regex, Parser, just, FwDeclaration - -from typing import TypeVar, Any - -# Utilities -# whitespace = regex(r"\s*") -whitespace = just(" ").or_else(just("\n")).repeat() - -T = TypeVar("T") - - -def lexeme(p: Parser[T]) -> Parser[T]: - return p << whitespace - - -# Punctuation -lbrace = lexeme(just("{")) -rbrace = lexeme(just("}")) -lbrack = lexeme(just("[")) -rbrack = lexeme(just("]")) -colon = lexeme(just(":")) -comma = lexeme(just(",")) - -# Primitives -true = lexeme(just("true")).value(True) -false = lexeme(just("false")).value(False) -null = lexeme(just("null")).value(None) -number = lexeme(regex(r"-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?")).map(float) -just_part = regex(r'[^"\\]+') -just_esc = just("\\") >> ( - just("\\") - | just("/") - | just('"') - | just("b").value("\b") - | just("f").value("\f") - | just("n").value("\n") - | just("r").value("\r") - | just("t").value("\t") - | regex(r"u[0-9a-fA-F]{4}").map(lambda s: chr(int(s[1:], 16))) -) -quoted = lexeme(just('"') >> (just_part | just_esc).repeat().map(lambda l: "".join(l)) << just('"')) - -# Data structures -json_value = FwDeclaration[Any]() -object_pair = (quoted << colon) & json_value.p() -json_object = lbrace >> object_pair.sep_by(comma).map(dict) << rbrace -array = lbrack >> json_value.p().sep_by(comma) << rbrack - -# Everything -json_value.define(quoted | number | json_object | array | true | false | null) -json_doc = whitespace >> json_value.p() - - -def test(): - assert ( - json_doc.parse( - r""" - { - "int": 1, - "just": "hello", - "a list": [1, 2, 3], - "escapes": "\n \u24D2", - "nested": {"x": "y"}, - "other": [true, false, null] - } -""" - ) - == { - "int": 1, - "just": "hello", - "a list": [1, 2, 3], - "escapes": "\n ⓒ", - "nested": {"x": "y"}, - "other": [True, False, None], - } - ) - - -if __name__ == "__main__": - from sys import stdin - test() - # print(repr(json_doc.parse(stdin.read()))) diff --git a/tests/test.py b/tests/test.py deleted file mode 100755 index 689c89f..0000000 --- a/tests/test.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/env -S python - -from os.path import dirname -import sys - -sys.path.append(f"{dirname(__file__)}/../src") -from party import regex, Parser, just, FwDeclaration, end - - -# input = "abc" -# parser = just("a").or_else(just("b")).or_else(just("c")) -# (parsed1, rest1) = parser.parse_part(input) -# (parsed2, rest2) = parser.parse_part(rest1) -# (parsed3, rest3) = parser.parse_part(rest2) - -# print( -# "parsed1", parsed1, -# "rest1", rest1, -# "parsed2", parsed2, -# "rest2", rest2, -# "parsed3", parsed3, -# "rest3", rest3, -# ) - - -# input = "a" -# parser = just("a").and_then(end()) -# parsed = parser.parse(input) - -# print("parsed", parsed) - - -# input = "...a" -# parser = just(".").repeat() >> just("a") -# parsed = parser.parse(input) - -# print("parsed", parsed) - - -# input = r"{a}" -# parser = just("{") >> just("a") << just("}") -# parsed = parser.parse(input) - -# print("parsed", parsed) - - -# input = r"a,a,a,a" -# parser = just("a").sep_by(just(",")) -# parsed = parser.parse(input) - -# print("parsed", parsed) - - -#td -input = r"{a,a,a,a" -# parser = just("{") >> just("a").sep_by(just(",")) -# parser = just("{").and_then(just("a").sep_by(just(","))) -parser = just("{").and_then(just("a").sep_by(just(","))) -parsed = parser.parse(input) - -print("parsed", parsed) diff --git a/tests/test.sh b/tests/test.sh new file mode 100755 index 0000000..30c8349 --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e +cd "$(dirname "$(realpath "$0")")" + +source ../venv/bin/activate +./inline.py +./cases.py