Castle: The best Real-Time/Embedded/HighTech language EVER. Attempt 2
Révision | bea0d751eb50f252c484e09867ac7daeaeffe832 (tree) |
---|---|
l'heure | 2021-12-21 07:48:17 |
Auteur | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
Term is ALSO an single_expr and ALSO an expressions. TODO visitor +peg for more complex cases
@@ -22,7 +22,7 @@ | ||
22 | 22 | |
23 | 23 | @staticmethod |
24 | 24 | def validate_or_raise(value): |
25 | - if not isinstance(value, str): | |
25 | + if not isinstance(value, (ID, str)): | |
26 | 26 | raise IDError("not a str of ID") |
27 | 27 | if ID._pattern.fullmatch(value) is None: |
28 | 28 | raise IDError("not a valid pattern") |
@@ -65,7 +65,14 @@ | ||
65 | 65 | |
66 | 66 | class ManyExpression(Expression): pass # abstract |
67 | 67 | class Group(Expression):pass |
68 | -class Sequence(Expression):pass | |
68 | + | |
69 | +class Sequence(Expression): | |
70 | + """A "list of expressions; can be of length=1""" | |
71 | + def __init__(self, *, value=None, **kwargs): | |
72 | + super().__init__(**kwargs) | |
73 | + self.value=value | |
74 | + | |
75 | + | |
69 | 76 | class OrderedChoice(Expression):pass |
70 | 77 | class Predicate(Expression): pass # abstract |
71 | 78 |
@@ -43,7 +43,7 @@ | ||
43 | 43 | assert isinstance(ast, peg.RegExpTerm), "... and a RegExp" |
44 | 44 | assert ast.value == expect, "And the regex-pre/postfix should be removed from the value" |
45 | 45 | |
46 | -def testregex_variants(): | |
46 | +def test_regex_variants(): | |
47 | 47 | regex_variants(txt:="""/a reg.ex/""", expect=txt[1:-1]) # Same a test_regex_RE |
48 | 48 | regex_variants(txt:="""/re_slash/""", expect=txt[1:-1]) |
49 | 49 |
@@ -58,3 +58,19 @@ | ||
58 | 58 | regex_variants(txt:='''r"""re__rstr_d3"""''', expect=txt[4:-3]) |
59 | 59 | |
60 | 60 | |
61 | +def test_term_as_single_expr(): # A term is **ALSO** a single_expr | |
62 | + txt="'a string'" | |
63 | + ast = parse(txt, grammar.single_expr) | |
64 | + assert isinstance(ast, peg.Expression), "A (str)term is also an Expression" | |
65 | + assert len(ast.value) == 1, "An expression with length==1" | |
66 | + assert ast.value[0].value == txt[1:-1], "It's correct value should be without quotes" | |
67 | + | |
68 | +def test_term_as_expressions(): # A term is **ALSO an expressions | |
69 | + txt="'a string'" | |
70 | + ast = parse(txt, grammar.expressions) | |
71 | + # result is same a above | |
72 | + assert isinstance(ast, peg.Expression), "A (str)term is also an Expression" | |
73 | + assert len(ast.value) == 1, "An expression with length==1" | |
74 | + assert ast.value[0].value == txt[1:-1], "It's correct value should be without quotes" | |
75 | + | |
76 | + |
@@ -10,3 +10,10 @@ | ||
10 | 10 | def visit_regex_term(self, node, children): |
11 | 11 | ast = peg.RegExpTerm(value=node[1], parse_tree=node) |
12 | 12 | return ast |
13 | + def visit_single_expr(self, node, children): # [ rule_crossref, term, group, predicate ] Optional([ '?' , '*' , '+' , '#' ])) | |
14 | + if len(children) == 1: # No optional part | |
15 | + ast = peg.Sequence(value=children, parse_tree=node) | |
16 | + else: | |
17 | + assert NotImplementedError("To Do: visit_single_expr with optional part") | |
18 | + | |
19 | + return ast |