Castle: The best Real-Time/Embedded/HighTech language EVER. Attempt 2
Révision | 033e1be89b60d1188a6bb7626202094a6470fc36 (tree) |
---|---|
l'heure | 2021-12-24 06:52:42 |
Auteur | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
Trival 'rule' (two IDs) now works
@@ -22,8 +22,9 @@ | ||
22 | 22 | |
23 | 23 | @staticmethod |
24 | 24 | def validate_or_raise(value): |
25 | - if not isinstance(value, (ID, str)): | |
26 | - raise IDError("not a str of ID") | |
25 | + if isinstance(value, ID): return | |
26 | + if not isinstance(value, str): | |
27 | + raise IDError("not a str (or an ID)") | |
27 | 28 | if ID._pattern.fullmatch(value) is None: |
28 | 29 | raise IDError("not a valid pattern") |
29 | 30 |
@@ -51,7 +51,6 @@ | ||
51 | 51 | self.expr = expr |
52 | 52 | |
53 | 53 | |
54 | - | |
55 | 54 | class Grammar(NonTerminal): |
56 | 55 | def __init__(self, *, |
57 | 56 | rules: list[Rule]=None, |
@@ -71,6 +70,10 @@ | ||
71 | 70 | def __init__(self, *, value=None, **kwargs): |
72 | 71 | super().__init__(**kwargs) |
73 | 72 | self.value=value |
73 | + def __len__(self): | |
74 | + return len(self.value) | |
75 | + def __getitem__(self, n): | |
76 | + return self.value[n] | |
74 | 77 | |
75 | 78 | |
76 | 79 | class OrderedChoice(Expression):pass |
@@ -16,8 +16,23 @@ | ||
16 | 16 | |
17 | 17 | def test_rule_crossref(): |
18 | 18 | """The rule's expressions can also refer an ID""" |
19 | - txt="aName" | |
19 | + txt="aRef" | |
20 | 20 | ast = parse(txt, grammar.rule_crossref) |
21 | 21 | assert isinstance(ast, peg.ID), "It should be an ID" |
22 | 22 | assert ast.name == txt |
23 | 23 | |
24 | + | |
25 | +def test_ID_as_single_expr(): | |
26 | + txt="aRef" | |
27 | + ast = parse(txt, grammar.single_expr) | |
28 | + assert isinstance(ast, peg.Expression), "A crossref is also an Expression" | |
29 | + assert len(ast.value) == 1, "An expression with length==1" | |
30 | + assert ast.value[0].name == txt, "The name of the (ID of the) Expression-value is still the same" | |
31 | + | |
32 | +def test_ID_as_expressions(): | |
33 | + txt="aRef" | |
34 | + ast = parse(txt, grammar.expressions) | |
35 | + assert isinstance(ast, peg.Expression), "A crossref is also an Expression" | |
36 | + assert len(ast.value) == 1, "An expression with length==1" | |
37 | + assert ast.value[0].name == txt, "The name of the (ID of the) Expression-value is still the same" | |
38 | + |
@@ -0,0 +1,22 @@ | ||
1 | +import pytest | |
2 | + | |
3 | +import grammar | |
4 | + | |
5 | +import sys; sys.path.append("./../AST/") ; sys.path.append("./../../AST/") | |
6 | +from castle import peg # has the AST clases | |
7 | + | |
8 | +from . import parse | |
9 | + | |
10 | +def test_trivial_rule_with_2IDS(): | |
11 | + """The most simple rule has only two IDs""" | |
12 | + txt="trivial <- cross ;" | |
13 | + ast = parse(txt, grammar.rule) | |
14 | + assert isinstance(ast, peg.Rule), "It should be an ID" | |
15 | + | |
16 | + name, expr = ast.name, ast.expr; | |
17 | + assert isinstance(name, peg.ID) | |
18 | + assert isinstance(expr, peg.Expression), "The expression is an Expression ..." | |
19 | + assert isinstance(expr, peg.Sequence), " .. and a Sequence .." | |
20 | + assert len(expr) ==1, " .. of length==1" | |
21 | + assert name.name == txt.split()[0], "the name of the (ID of ) rule is the first ID" | |
22 | + assert expr[0].name == txt.split()[2], "The single element of the expression is the 2nnd ID, which name os the 3 part of the txt" |
@@ -23,6 +23,9 @@ | ||
23 | 23 | if len(children) == 1: # No optional part |
24 | 24 | ast = peg.Sequence(value=children, parse_tree=node) |
25 | 25 | else: |
26 | - assert NotImplementedError("To Do: visit_single_expr with optional part") | |
26 | + assert NotImplementedError("To Do: visit_single_expr with optional part") # XXX | |
27 | 27 | return ast |
28 | 28 | |
29 | + def visit_rule(self, node, children): # Name '<-' expressions ';' | |
30 | + ast = peg.Rule(name=children[0],expr=children[1], parse_tree=node) | |
31 | + return ast |