diff options
-rw-r--r-- | abdl/__init__.py | 3 | ||||
-rw-r--r-- | abdl/_parser.py | 31 | ||||
-rw-r--r-- | testing/test_abdl.py | 2 | ||||
-rw-r--r-- | testing/test_ops_abdl.py | 34 |
4 files changed, 39 insertions, 31 deletions
diff --git a/abdl/__init__.py b/abdl/__init__.py index d751187..2c6b26a 100644 --- a/abdl/__init__.py +++ b/abdl/__init__.py @@ -137,6 +137,9 @@ from abdl import _parser from abdl import _vm from abdl import exceptions +# backwards compatibility TODO: remove in 3.0.0 +from abdl.exceptions import ValidationError, DeprecationError, PatternError + class Pattern: """A compiled pattern object. diff --git a/abdl/_parser.py b/abdl/_parser.py index c39a45e..3e179a2 100644 --- a/abdl/_parser.py +++ b/abdl/_parser.py @@ -16,7 +16,7 @@ import pyparsing -import abdl.exceptions +from abdl import exceptions from abdl import _vm def _build_syntax(): @@ -27,14 +27,21 @@ def _build_syntax(): skippable = Optional("?", default="") - str_literal = (Combine(Suppress("'") - + (Suppress("%") + ("'" | "%") | Literal("%") + (CharsNotIn("") | StringEnd()).setParseAction(abdl.exceptions.PatternError._str_escape) | CharsNotIn("%'"))[...] - + (Suppress("'") | StringEnd().setParseAction(abdl.exceptions.PatternError._str_end))) + skippable) + escape_char = Literal("%") + str_token = Literal("'") + re_token = Literal("/") + + unexpected_token = CharsNotIn("", exact=1).setParseAction(exceptions.PatternError._unexpected_tok) + unexpected_end = StringEnd().setParseAction(exceptions.PatternError._unexpected_tok) + + str_literal = (Combine(Suppress(str_token) + + (Suppress(escape_char) + (str_token | escape_char) | escape_char + CharsNotIn("", exact=1).setParseAction(exceptions.PatternError._str_escape) | CharsNotIn("%'"))[...] + + (Suppress(str_token) | StringEnd().setParseAction(exceptions.PatternError._str_end))) + skippable) str_literal.setParseAction(lambda toks: [_vm.StringKey(toks)]) - re_literal = (Combine(Suppress("/") - + (Suppress("%") + ("/" | "%") | Literal("%") + (CharsNotIn("") | StringEnd()).setParseAction(abdl.exceptions.PatternError._re_escape) | CharsNotIn("%/"))[...] - + (Suppress("/") | StringEnd().setParseAction(abdl.exceptions.PatternError._re_end))) + skippable) + re_literal = (Combine(Suppress(re_token) + + (Suppress(escape_char) + (re_token | escape_char) | escape_char + CharsNotIn("", exact=1).setParseAction(exceptions.PatternError._re_escape) | CharsNotIn("%/"))[...] + + (Suppress(re_token) | StringEnd().setParseAction(exceptions.PatternError._re_end))) + skippable) re_literal.setParseAction(lambda toks: [_vm.RegexKey(toks)]) arrow = Literal("->") @@ -46,25 +53,23 @@ def _build_syntax(): parameter = (Suppress("$") + skippable + identifier) parameter.setParseAction(lambda toks: [_vm.Param(toks)]) - type_ = (Suppress(":") + skippable + Optional(Suppress("$")) + identifier) + type_ = (Suppress(":") + skippable + Suppress("$") + identifier) type_.setParseAction(lambda toks: [_vm.ApplyPredicate(toks)]) # support for objects-as-keys - keysubtree = (Suppress("[") - + Group(type_[...] + subtree) - + (Suppress("]") | (CharsNotIn("") | StringEnd()).setParseAction(abdl.exceptions.PatternError._unexpected_tok)) + skippable) + keysubtree = (Suppress("[") + Group(type_[...] + subtree) + (Suppress("]") | unexpected_token | unexpected_end) + skippable) keysubtree.setParseAction(lambda toks: [_vm.KeySubtree(toks)]) # represents key matching - switches from "key" to "value" tag = (identifier + Optional(parameter | str_literal | re_literal | keysubtree) | parameter | str_literal | re_literal | keysubtree) + type_[...] + Empty().setParseAction(lambda: [_vm.End()]) # multiple value matching - valuesubtree = (Suppress("(") + Group(subtree) + (Suppress(")") | CharsNotIn("").setParseAction(abdl.exceptions.PatternError._unexpected_tok) | StringEnd().setParseAction(abdl.exceptions.PatternError._unexpected_tok)) + Optional("?", default="")) + valuesubtree = (Suppress("(") + Group(subtree) + (Suppress(")") | unexpected_token | unexpected_end) + Optional("?", default="")) valuesubtree.setParseAction(lambda toks: [_vm.ValueSubtree(toks)]) # arrow and tag, value subtree subtree <<= (arrow + tag)[...] + (valuesubtree + Empty().setParseAction(lambda: [_vm.End()]))[...] - return ((subtree | CharsNotIn("").setParseAction(abdl.exceptions.PatternError._unexpected_tok)) + StringEnd()).parseWithTabs() + return ((subtree | unexpected_token) + StringEnd()).parseWithTabs() BUILT_SYNTAX = _build_syntax() diff --git a/testing/test_abdl.py b/testing/test_abdl.py index f9eedcc..2cea90d 100644 --- a/testing/test_abdl.py +++ b/testing/test_abdl.py @@ -15,7 +15,7 @@ import traceback abdl.DeprecationError.enable_key_match_compat = False # use abdl's _pairs for consistency. -pairs = abdl._pairs +pairs = abdl._vm._pairs # do not put integers, floats, etc here # do not put bytes, they iterate as integers diff --git a/testing/test_ops_abdl.py b/testing/test_ops_abdl.py index 0695e3f..3fba731 100644 --- a/testing/test_ops_abdl.py +++ b/testing/test_ops_abdl.py @@ -19,10 +19,10 @@ class OpHelper: def __enter__(self): self.pos += 1 first = self.pos - assert not isinstance(self.ops[first], abdl._End) - while not isinstance(self.ops[self.pos], abdl._End): + assert not isinstance(self.ops[first], abdl._vm.End) + while not isinstance(self.ops[self.pos], abdl._vm.End): self.pos += 1 - assert isinstance(self.ops[self.pos], abdl._End) + assert isinstance(self.ops[self.pos], abdl._vm.End) return self.ops[first:self.pos] def __exit__(self, exc_type, exc_value, traceback): @@ -35,7 +35,7 @@ def expect_types(seq, *tys): def expect_idents(oph, *idents): for ident in idents: with oph as ops: - expect_types(ops, abdl._Arrow, abdl._Ident) + expect_types(ops, abdl._vm.Arrow, abdl._vm.Ident) assert ops[1].key == ident def test_empty_iterator_pattern(): @@ -50,7 +50,7 @@ def test_four_depths_pattern(): def test_regex_pattern(): oph = OpHelper(abdl.compile("->/.../")) with oph as ops: - expect_types(ops, abdl._Arrow, abdl._RegexKey) + expect_types(ops, abdl._vm.Arrow, abdl._vm.RegexKey) assert ops[1].key == '...' assert ops[1].compiled == re.compile('...') assert ops[1].skippable == False @@ -59,7 +59,7 @@ def test_regex_pattern(): def test_regex_skippable_pattern(): oph = OpHelper(abdl.compile("->/.../?")) with oph as ops: - expect_types(ops, abdl._Arrow, abdl._RegexKey) + expect_types(ops, abdl._vm.Arrow, abdl._vm.RegexKey) assert ops[1].key == '...' assert ops[1].compiled == re.compile('...') assert ops[1].skippable == True @@ -68,7 +68,7 @@ def test_regex_skippable_pattern(): def test_regex_and_bind_pattern(): oph = OpHelper(abdl.compile("->/.../->Y")) with oph as ops: - expect_types(ops, abdl._Arrow, abdl._RegexKey) + expect_types(ops, abdl._vm.Arrow, abdl._vm.RegexKey) assert ops[1].key == '...' assert ops[1].compiled == re.compile('...') assert ops[1].skippable == False @@ -78,7 +78,7 @@ def test_regex_and_bind_pattern(): def test_empty_literal_skippable_and_bind_pattern(): oph = OpHelper(abdl.compile("->''?->Y")) with oph as ops: - expect_types(ops, abdl._Arrow, abdl._StringKey) + expect_types(ops, abdl._vm.Arrow, abdl._vm.StringKey) assert ops[1].key == '' assert ops[1].skippable == True expect_idents(oph, "Y") @@ -88,7 +88,7 @@ def test_type_pattern(): oph = OpHelper(abdl.compile("->X:?$a->Y", defs={'a': (dict, list, set)})) assert oph.pat._defs['a'] == (dict, list, set) with oph as ops: - expect_types(ops, abdl._Arrow, abdl._Ident, abdl._ApplyPredicate) + expect_types(ops, abdl._vm.Arrow, abdl._vm.Ident, abdl._vm.ApplyPredicate) assert ops[1].key == 'X' assert ops[2].key == 'a' assert ops[2].skippable == True @@ -101,7 +101,7 @@ def test_multi_type_pattern(): assert oph.pat._defs['b'] == (dict, set) assert oph.pat._defs['c'] == dict with oph as ops: - expect_types(ops, abdl._Arrow, abdl._Ident, abdl._ApplyPredicate, abdl._ApplyPredicate, abdl._ApplyPredicate) + expect_types(ops, abdl._vm.Arrow, abdl._vm.Ident, abdl._vm.ApplyPredicate, abdl._vm.ApplyPredicate, abdl._vm.ApplyPredicate) assert ops[1].key == 'X' assert ops[2].key == 'a' assert ops[2].skippable == False @@ -116,10 +116,10 @@ def test_key_subtree_pattern(): oph = OpHelper(abdl.compile("->[:?$set->A]->D", defs={'set': set})) assert oph.pat._defs['set'] == set with oph as ops: - expect_types(ops, abdl._Arrow, abdl._KeySubtree) + expect_types(ops, abdl._vm.Arrow, abdl._vm.KeySubtree) oph2 = OpHelper(None, ops=ops[1].key) with oph2 as ops2: - expect_types(ops2, abdl._ApplyPredicate, abdl._Arrow, abdl._Ident) + expect_types(ops2, abdl._vm.ApplyPredicate, abdl._vm.Arrow, abdl._vm.Ident) assert ops2[0].key == 'set' assert ops2[0].skippable == True assert ops2[2].key == 'A' @@ -132,7 +132,7 @@ def test_param_pattern(): assert oph.pat._defs['a'] == '0' expect_idents(oph, "X") with oph as ops: - expect_types(ops, abdl._Arrow, abdl._Param) + expect_types(ops, abdl._vm.Arrow, abdl._vm.Param) assert ops[1].key == 'a' assert ops[1].skippable == False expect_idents(oph, "Z") @@ -141,19 +141,19 @@ def test_param_pattern(): def test_value_subtree_pattern(): oph = OpHelper(abdl.compile("(->foo'foo')(->bar'bar')")) with oph as ops: - expect_types(ops, abdl._ValueSubtree) + expect_types(ops, abdl._vm.ValueSubtree) oph2 = OpHelper(None, ops=ops[0].key) with oph2 as ops2: - expect_types(ops2, abdl._Arrow, abdl._Ident, abdl._StringKey) + expect_types(ops2, abdl._vm.Arrow, abdl._vm.Ident, abdl._vm.StringKey) assert ops2[1].key == 'foo' assert ops2[2].key == 'foo' assert ops2[2].skippable == False oph2.done() with oph as ops: - expect_types(ops, abdl._ValueSubtree) + expect_types(ops, abdl._vm.ValueSubtree) oph2 = OpHelper(None, ops=ops[0].key) with oph2 as ops2: - expect_types(ops2, abdl._Arrow, abdl._Ident, abdl._StringKey) + expect_types(ops2, abdl._vm.Arrow, abdl._vm.Ident, abdl._vm.StringKey) assert ops2[1].key == 'bar' assert ops2[2].key == 'bar' assert ops2[2].skippable == False |