Castle: The best Real-Time/Embedded/HighTech language EVER. Attempt 2
Revision | 614d3d329c7e8456ce094dc8caedec15b973e5ae (tree) |
---|---|
Zeit | 2021-12-11 04:28:40 |
Autor | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
Rewriten grammar.py test_3_sequence is replaced by test_3_expressions
@@ -9,7 +9,6 @@ | ||
9 | 9 | def expressions(): return ( OneOrMore(single_expr), Optional( '|' , expressions ) ) |
10 | 10 | def single_expr(): return ( [ rule_crossref, term, group, predicate ], Optional([ '?' , '*' , '+' , '#' ])) |
11 | 11 | |
12 | - | |
13 | 12 | def term(): return [ str_term, regex_term ] |
14 | 13 | def group(): return '(', expressions, ')' |
15 | 14 | def predicate(): return ['&','!'], single_expr |
@@ -23,6 +22,7 @@ | ||
23 | 22 | (REd3, str_no_d3, D3), |
24 | 23 | (REs1, str_no_s1, S1), |
25 | 24 | (REd1, str_no_d1, D1) ] |
25 | + | |
26 | 26 | def rule_name(): return ID |
27 | 27 | def rule_crossref(): return ID |
28 | 28 | def ID(): return _(r"[a-zA-Z_]([a-zA-Z_]|[0-9])*") |
@@ -0,0 +1,61 @@ | ||
1 | +import pytest | |
2 | +import grammar | |
3 | + | |
4 | +import arpeggio | |
5 | + | |
6 | +R, S, X = grammar.regex_term.__name__, grammar.str_term.__name__, grammar.rule_crossref.__name__ # shortcut in grammar | |
7 | +P = grammar.predicate.__name__ | |
8 | +G = grammar.group.__name__ | |
9 | + | |
10 | +def parse_expressions(txt, pattern=None): | |
11 | + parser = arpeggio.ParserPython(grammar.expressions) | |
12 | + parse_tree = parser.parse(txt) | |
13 | + print("\nPARSE-TREE\n" + parse_tree.tree_str()+'\n') | |
14 | + | |
15 | + assert parse_tree.position_end == len(txt) , f"Not parsed whole input; Only: >>{txt[parse_tree.position: parse_tree.position_end]}<<; Not: >>{txt[parse_tree.position_end:]}<<." | |
16 | + assert parse_tree.rule_name == "expressions" | |
17 | + | |
18 | + if pattern: validate_pattern(parse_tree, pattern=pattern) | |
19 | + | |
20 | + return parse_tree | |
21 | + | |
22 | +def validate_pattern(pt, pattern=None): | |
23 | + print('VVV', pt, type(pt)) | |
24 | + assert len(pt) == len(pattern), f"Not correct number-of-element" | |
25 | + | |
26 | + for p, s in zip(pattern, pt): # E <- S* (| E)? | |
27 | + if p is None: continue | |
28 | + if p == X: | |
29 | + assert s[0].rule_name == p | |
30 | + elif p in (S,R): | |
31 | + assert s[0][0].rule_name == p # S => T => str/regex | |
32 | + elif isinstance(p, tuple): # Group: '(' ... ')' | |
33 | + assert s[0].rule_name == G | |
34 | + print("\nVVV:G\n" + s.tree_str()) | |
35 | + # XXXXX | |
36 | + validate_pattern(s[0][1:-1][0], pattern=p) # G=>E=> | |
37 | + elif p == P: | |
38 | + assert False, "To Do: Predicate" | |
39 | + else: | |
40 | + assert False, "To Do: More" | |
41 | + print('VVV OKE') | |
42 | + | |
43 | + | |
44 | +def test_simple_1(): parse_expressions(r"abc", pattern=[X]) | |
45 | +def test_simple_2(): parse_expressions(r'A Bc', pattern=[X, X]) | |
46 | + | |
47 | +def test_string_1(): parse_expressions(r"'abc'", pattern=[S]) | |
48 | +def test_regexp_1(): parse_expressions(r"/re/", pattern=[R]) | |
49 | + | |
50 | +def test_mix(): parse_expressions(r'/regex/ "string" crossref crossref', pattern=[R,S, X, X]) | |
51 | + | |
52 | +def test_sub(): parse_expressions(r'( A B )', pattern=[(X, X)]) | |
53 | +def test_mix_nosub(): parse_expressions(r'/regex/ "string" ( A B ) crossref', pattern=[R,S, None, X]) | |
54 | +def test_mix_sub(): parse_expressions(r'/regex/ "string" ( A B ) crossref', pattern=[R,S, (X, X), X]) | |
55 | + | |
56 | +def test_sub_sub(): parse_expressions(r'level0 ( level1_1 (level2a level2b ) level1_2) level0', pattern=[X, (X, (X,X), X), X]) | |
57 | + | |
58 | + | |
59 | + | |
60 | + | |
61 | + |
@@ -1,44 +0,0 @@ | ||
1 | -import pytest | |
2 | -from grammar import * | |
3 | - | |
4 | -import arpeggio | |
5 | - | |
6 | -R, S, X = regex_term.__name__, str_term.__name__, rule_crossref.__name__ # shortcut in grammar | |
7 | - | |
8 | -def parse_sequence(txt, pattern=None): | |
9 | - parser = ParserPython(sequence, comment) | |
10 | - tree = parser.parse(txt) | |
11 | - | |
12 | - assert tree.position_end == len(txt) , f"Not parsed whole input; Only: >>{txt[tree.position: tree.position_end]}<<; Not: >>{txt[tree.position_end:]}<<." | |
13 | - assert isinstance(tree.rule, arpeggio.ZeroOrMore) and tree.rule_name == "sequence" | |
14 | - | |
15 | - if pattern: validate_pattern(tree,pattern=pattern) | |
16 | - return tree | |
17 | - | |
18 | -def validate_pattern(tree, pattern=None): | |
19 | - assert len(tree) == len(pattern), f"Not correct number-of-element at sublevel={sub}" | |
20 | - | |
21 | - exs=tree.prefix.suffix.expression | |
22 | - for ex,p in zip(exs, pattern): | |
23 | - if p is not None: | |
24 | - if not isinstance(p, (tuple, list)): | |
25 | - assert ex[0].rule_name == p, f"{ex} doesn't match given {p} sublevel={sub}" | |
26 | - else: | |
27 | - validate_pattern(tree=ex[1][0], pattern=p) | |
28 | - | |
29 | - | |
30 | - | |
31 | -def test_simple_1(): parse_sequence(r"abc", pattern=[X]) | |
32 | -def test_simple_2(): parse_sequence(r'A Bc', pattern=[X, X]) | |
33 | -def test_mix(): parse_sequence(r'/regex/ "string" crossref crossref', pattern=[R,S, X, X]) | |
34 | - | |
35 | -def test_sub(): parse_sequence(r'( A B )', pattern=[(X, X)]) | |
36 | -def test_mix_nosub(): parse_sequence(r'/regex/ "string" ( A B ) crossref', pattern=[R,S, None, X]) | |
37 | -def test_mix_sub(): parse_sequence(r'/regex/ "string" ( A B ) crossref', pattern=[R,S, (X, X), X]) | |
38 | - | |
39 | -def test_sub_sub(): parse_sequence(r'level0 ( level1_1 (level2a level2b ) level1_2) level0', pattern=[X, (X, (X,X), X), X]) | |
40 | -def test_sub_sub2(): parse_sequence(r'level0 ( level1_1 (level2a level2b ) level1_2) level0', pattern=[X, [X, [X,X], X], X]) | |
41 | - | |
42 | - | |
43 | - | |
44 | - |