Castle: The best Real-Time/Embedded/HighTech language EVER. Attempt 2
修订版 | 6f8b684557148ab716952d2a0ba00292b8c9e9eb (tree) |
---|---|
时间 | 2022-02-13 08:33:19 |
作者 | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
REFACTORED TEST (d1)
@@ -0,0 +1,16 @@ | ||
1 | +import logging;logger = logging.getLogger(__name__) | |
2 | +from castle.readers.parser import grammar | |
3 | + | |
4 | +import arpeggio | |
5 | + | |
6 | +def parse(txt, grammer_rule): | |
7 | + logger.debug(f'>>{txt}<<') | |
8 | + | |
9 | + parser = arpeggio.ParserPython(grammer_rule, grammar.comment) | |
10 | + pt = parser.parse(txt) | |
11 | + | |
12 | + #Some basic checks | |
13 | + assert pt.position_end == len(txt) , f"Not parsed whole input; Only: >>{txt[pt.position: pt.position_end]}<<; Not: >>{txt[pt.position_end:]}<<." | |
14 | + | |
15 | + return pt | |
16 | + |
@@ -6,33 +6,35 @@ | ||
6 | 6 | import arpeggio |
7 | 7 | RE, S = arpeggio.RegExMatch, arpeggio.StrMatch # shortcut |
8 | 8 | |
9 | -def parse_regex(txt, pattern=None): | |
10 | - logger.debug(f'>>{txt}<<') | |
11 | - parser = arpeggio.ParserPython(grammar.regex_term, grammar.comment) # DoNot use debug/dot_exporter as it will re-use-same-file | |
12 | - tree = parser.parse(txt) | |
13 | - assert tree.position_end == len(txt) , f"Not parsed whole input; Only: >>{txt[tree.position: tree.position_end]}<<; Not: >>{txt[tree.position_end:]}<<." | |
9 | +from . import parse | |
14 | 10 | |
15 | - assert isinstance(tree.rule, arpeggio.OrderedChoice) and tree.rule_name == "regex_term" | |
16 | - assert len(tree) == 3, "regex_term is an Ordered_Choice of always 3 Terminals" | |
11 | +def verify_regex(txt, pattern=None): | |
12 | + parse_tree = parse(txt, grammar.regex_term) | |
17 | 13 | |
18 | - for e in tree: assert isinstance(e, arpeggio.Terminal) | |
14 | + assert isinstance(parse_tree.rule, arpeggio.OrderedChoice) and parse_tree.rule_name == "regex_term" | |
15 | + assert len(parse_tree) == 3, "regex_term is an Ordered_Choice of always 3 Terminals" | |
16 | + for e in parse_tree: assert isinstance(e, arpeggio.Terminal) | |
17 | + | |
19 | 18 | if pattern: |
20 | - for e,T in zip(tree,pattern): | |
19 | + validate_pattern(parse_tree, pattern=pattern) | |
20 | + | |
21 | +def validate_pattern(parse_tree, pattern): | |
22 | + for e,T in zip(parse_tree,pattern): | |
21 | 23 | if T is not None: assert isinstance(e.rule, T), f"{type(e.rule).__name__} doesn't match {T.__name__}" |
22 | 24 | |
23 | - return tree | |
24 | - | |
25 | -def test_slash_simple(): parse_regex(r"/ABC/", pattern=[S,RE,S]) | |
26 | -def test_slash_slashonly(): parse_regex(r"/\//", pattern=[S,RE,S]) | |
27 | -def test_slash_withslash_r(): parse_regex(r"/ab\/c/", pattern=[S,RE,S]) | |
28 | - | |
29 | -def test_Rs1_simple(): parse_regex(r"R'ABC'", pattern=[RE,RE,S]) | |
30 | -def test_rs2_simple(): parse_regex(r"r'abc'", pattern=[RE,RE,S]) | |
31 | -def test_Rd1_simple(): parse_regex(r'R"ABC"', pattern=[RE,RE,S]) | |
32 | -def test_rd2_simple(): parse_regex(r'r"abc"', pattern=[RE,RE,S]) | |
33 | - | |
34 | -def test_grammar_re_no_slash(): parse_regex(r"/((\\/)|[^\/])*/") | |
35 | -def test_grammar_auto_re_no_slash(): parse_regex("/" + grammar.re_no_slash().to_match +"/") # Same as above (unless grammar changes | |
36 | - | |
37 | 25 | |
38 | 26 | |
27 | +def test_slash_simple(): verify_regex(r"/ABC/", pattern=[S,RE,S]) | |
28 | +def test_slash_slashonly(): verify_regex(r"/\//", pattern=[S,RE,S]) | |
29 | +def test_slash_withslash_r(): verify_regex(r"/ab\/c/", pattern=[S,RE,S]) | |
30 | + | |
31 | +def test_Rs1_simple(): verify_regex(r"R'ABC'", pattern=[RE,RE,S]) | |
32 | +def test_rs2_simple(): verify_regex(r"r'abc'", pattern=[RE,RE,S]) | |
33 | +def test_Rd1_simple(): verify_regex(r'R"ABC"', pattern=[RE,RE,S]) | |
34 | +def test_rd2_simple(): verify_regex(r'r"abc"', pattern=[RE,RE,S]) | |
35 | + | |
36 | +def test_grammar_re_no_slash(): verify_regex(r"/((\\/)|[^\/])*/") | |
37 | +def test_grammar_auto_re_no_slash(): verify_regex("/" + grammar.re_no_slash().to_match +"/") # Same as above (unless grammar changes | |
38 | + | |
39 | + | |
40 | + |
@@ -3,39 +3,36 @@ | ||
3 | 3 | |
4 | 4 | from castle.readers.parser import grammar |
5 | 5 | |
6 | - | |
7 | 6 | import arpeggio |
8 | 7 | RE, S = arpeggio.RegExMatch, arpeggio.StrMatch # shortcut |
9 | 8 | |
9 | +from . import parse | |
10 | 10 | |
11 | -def parse_str(str, pattern=[S, RE, S]): | |
12 | - logger.debug(f'>>{str}<<') | |
13 | - parser = arpeggio.ParserPython(grammar.str_term, grammar.comment) | |
14 | - tree = parser.parse(str) | |
15 | - assert tree.position_end == len(str) , f"Not parsed whole input; Only: >>{str[tree.position: tree.position_end]}<<; Not: >>{str[tree.position_end:]}<<." | |
11 | +def verify_str(txt, pattern=[S, RE, S]): | |
12 | + parse_tree = parse(txt, grammar.str_term) | |
16 | 13 | |
17 | - assert isinstance(tree.rule, arpeggio.OrderedChoice) and tree.rule_name == "str_term" | |
18 | - assert len(tree) == 3, "regex_term is an Ordered_Choice of always 3 Terminals" | |
14 | + assert isinstance(parse_tree.rule, arpeggio.OrderedChoice) and parse_tree.rule_name == "str_term" | |
15 | + assert len(parse_tree) == 3, "regex_term is an Ordered_Choice of always 3 Terminals" | |
16 | + for e in parse_tree: assert isinstance(e, arpeggio.Terminal) | |
19 | 17 | |
20 | - for e in tree: assert isinstance(e, arpeggio.Terminal) | |
21 | 18 | if pattern: |
22 | - for e,T in zip(tree,pattern): | |
19 | + validate_pattern(parse_tree, pattern=pattern) | |
20 | + | |
21 | +def validate_pattern(parse_tree, pattern): | |
22 | + for e,T in zip(parse_tree,pattern): | |
23 | 23 | if T is not None: assert isinstance(e.rule, T), f"{type(e.rule).__name__} doesn't match {T.__name__}" |
24 | 24 | |
25 | 25 | |
26 | - return tree | |
27 | - | |
26 | +def test_s1(): verify_str("'single 1'") | |
27 | +def test_d1(): verify_str('"double 1"') | |
28 | +def test_s3(): verify_str(r"'''single 3 b'''") | |
29 | +def test_d3(): verify_str('"""double 3"""') | |
28 | 30 | |
29 | -def test_s1(): parse_str("'single 1'") | |
30 | -def test_d1(): parse_str('"double 1"') | |
31 | -def test_s3(): parse_str(r"'''single 3 b'''") | |
32 | -def test_d3(): parse_str('"""double 3"""') | |
33 | - | |
34 | -def test_multiline_s(): parse_str("""''' | |
31 | +def test_multiline_s(): verify_str("""''' | |
35 | 32 | line 1 |
36 | 33 | line 2 |
37 | 34 | '''""") |
38 | -def test_multiline_d(): parse_str('''""" | |
35 | +def test_multiline_d(): verify_str('''""" | |
39 | 36 | line 1 |
40 | 37 | line 2 |
41 | 38 | """''') |
@@ -43,12 +40,12 @@ | ||
43 | 40 | def test_multiline_only3(): |
44 | 41 | import arpeggio |
45 | 42 | with pytest.raises(arpeggio.NoMatch): |
46 | - parse_str("""' | |
43 | + verify_str("""' | |
47 | 44 | line 1 |
48 | 45 | line 2 |
49 | 46 | '""") |
50 | 47 | with pytest.raises(arpeggio.NoMatch): |
51 | - parse_str('''" | |
48 | + verify_str('''" | |
52 | 49 | line 1 |
53 | 50 | line 2 |
54 | 51 | "''') |
@@ -9,19 +9,16 @@ | ||
9 | 9 | P = grammar.predicate.__name__ |
10 | 10 | G = grammar.group.__name__ |
11 | 11 | |
12 | +from . import parse | |
13 | + | |
12 | 14 | |
13 | 15 | def validate_expression(txt, pattern): |
14 | 16 | parse_tree = parse_expression(txt) |
15 | 17 | validate_pattern(parse_tree, pattern=pattern) |
16 | 18 | |
17 | 19 | def parse_expression(txt): |
18 | - parser = arpeggio.ParserPython(grammar.expression) | |
19 | - parse_tree = parser.parse(txt) | |
20 | - logger.debug("\nPARSE-TREE\n" + parse_tree.tree_str()+'\n') | |
21 | - | |
22 | - 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:]}<<." | |
20 | + parse_tree = parse(txt, grammar.expression) | |
23 | 21 | assert parse_tree.rule_name == "expression" |
24 | - | |
25 | 22 | return parse_tree |
26 | 23 | |
27 | 24 |
@@ -6,26 +6,25 @@ | ||
6 | 6 | import arpeggio |
7 | 7 | RE, S = arpeggio.RegExMatch, arpeggio.StrMatch # shortcut |
8 | 8 | |
9 | -def parse_rule(txt, pattern=None): | |
10 | - parser = arpeggio.ParserPython(grammar.parse_rule) | |
11 | - tree = parser.parse(txt) | |
12 | - logger.debug(f'\nTREE\n{tree.tree_str()}') | |
9 | +from . import parse | |
13 | 10 | |
14 | - assert tree.position_end == len(txt) , f"Not parsed whole input; Only: >>{txt[tree.position: tree.position_end]}<<; Not: >>{txt[tree.position_end:]}<<." | |
15 | - assert len(tree) == 4, "A rule should have length=4; ..." | |
16 | - assert tree[0].rule_name == "rule_name", " at [0], the name of the rule" | |
17 | - assert str(tree[1]) == '<-', " then a arrow" | |
18 | - assert tree[2].rule_name == "expression", " at [2] an expression" | |
19 | - assert str(tree[3]) == ';', " and the the closing ':'" | |
11 | +def check_rule(txt, pattern=None): | |
12 | + parse_tree = parse(txt, grammar.parse_rule) | |
20 | 13 | |
21 | - return tree | |
14 | + assert len(parse_tree) == 4, "A rule should have length=4; ..." | |
15 | + assert parse_tree[0].rule_name == "rule_name", " at [0], the name of the rule" | |
16 | + assert str(parse_tree[1]) == '<-', " then a arrow" | |
17 | + assert parse_tree[2].rule_name == "expression", " at [2] an expression" | |
18 | + assert str(parse_tree[3]) == ';', " and the the closing ':'" | |
19 | + | |
20 | + return parse_tree | |
22 | 21 | |
23 | 22 | |
24 | -def test_simple(): parse_rule(r"R <- A B C ;") | |
25 | -def test_OC(): parse_rule(r"Alts <- This | That | Or So ;") | |
23 | +def test_simple(): check_rule(r"R <- A B C ;") | |
24 | +def test_OC(): check_rule(r"Alts <- This | That | Or So ;") | |
26 | 25 | |
27 | -def test_rule_rule(): parse_rule(r"""RULE <- RULE_NAME '<-' ORDERED_CHOICE ';' ;""") | |
28 | -def test_expression_rule(): parse_rule(r""" | |
26 | +def test_rule_rule(): check_rule(r"""RULE <- RULE_NAME '<-' ORDERED_CHOICE ';' ;""") | |
27 | +def test_expression_rule(): check_rule(r""" | |
29 | 28 | expression <- regex_term |
30 | 29 | | rule_crossref |
31 | 30 | | '(' ordered_choice ')' |