Castle: The best Real-Time/Embedded/HighTech language EVER. Attempt 2
修訂 | dc50c83a774264d3692760f7b6ba24591ff6b160 (tree) |
---|---|
時間 | 2021-12-10 23:53:35 |
作者 | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
Rewriten grammar.py (old: ~1, new~2; symlink to select, for NOW. Need t rewrite test
@@ -1,45 +0,0 @@ | ||
1 | -from arpeggio import Optional, ZeroOrMore, OneOrMore, EOF | |
2 | -from arpeggio import RegExMatch as _ | |
3 | -from arpeggio import ParserPython | |
4 | - | |
5 | -def peg_grammar(): return rules, EOF | |
6 | -def rules(): return OneOrMore(rule) | |
7 | -def rule(): return rule_name, '<-', ordered_choice, ";" | |
8 | -def ordered_choice(): return sequence, ZeroOrMore('|', sequence) | |
9 | -def sequence(): return ZeroOrMore(prefix) | |
10 | -def prefix(): return Optional(['&','!']), suffix | |
11 | -def suffix(): return expression, Optional([ '?' , '*' , '+' , '#' ]) | |
12 | -def expression(): return [ regex_term, str_term, ('(', ordered_choice, ')'), rule_crossref] # OrderedChoice | |
13 | -def rule_crossref(): return rule_name | |
14 | -def rule_name(): return ID | |
15 | -def regex_term(): return [ (RE, re_no_slash, RE), # OrderedChoice | |
16 | - (REs3, str_no_s3, S3), | |
17 | - (REd3, str_no_d3, D3), | |
18 | - (REs1, str_no_s1, S1), | |
19 | - (REd1, str_no_d1, D1) ] | |
20 | -def str_term(): return [ (S3, str_no_s3, S3), # OrderedChoice | |
21 | - (D3, str_no_d3, D3), | |
22 | - (S1, str_no_s1, S1), | |
23 | - (D1, str_no_d1, D1) ] | |
24 | - | |
25 | -def ID(): return _(r"[a-zA-Z_]([a-zA-Z_]|[0-9])*") | |
26 | - | |
27 | -def re_no_slash(): return _(r"((\\/)|[^\/])*") | |
28 | - | |
29 | -def str_no_s1(): return _(r"((\\')|[^'\n])*") # Does NOT match multiline -- note 'multiline=False' is not the same | |
30 | -def str_no_d1(): return _(r'((\\")|[^"\n])*') # idem | |
31 | -def str_no_s3(): return _(r"([^']|('[^'])|(''[^']))*") # ALLOW multiline | |
32 | -def str_no_d3(): return _(r'''([^"]|("[^"])|(""[^"]))*''') # idem | |
33 | - | |
34 | -S1 = "'" | |
35 | -D1 = '"' | |
36 | -S3 = "'''" | |
37 | -D3 = '"""' | |
38 | -RE = '/' | |
39 | -REs1 = _(r"[rR]'") | |
40 | -REd1 = _(r'[rR]"') | |
41 | -REs3 = _(r"[rR]'''") | |
42 | -REd3 = _(r'[rR]"""') | |
43 | - | |
44 | -def comment(): return "//", _(".*\n") | |
45 | - |
@@ -0,0 +1,45 @@ | ||
1 | +from arpeggio import Optional, ZeroOrMore, OneOrMore, EOF | |
2 | +from arpeggio import RegExMatch as _ | |
3 | +from arpeggio import ParserPython | |
4 | + | |
5 | +def peg_grammar(): return rules, EOF | |
6 | +def rules(): return OneOrMore(rule) | |
7 | +def rule(): return rule_name, '<-', ordered_choice, ";" | |
8 | +def ordered_choice(): return sequence, ZeroOrMore('|', sequence) | |
9 | +def sequence(): return ZeroOrMore(prefix) | |
10 | +def prefix(): return Optional(['&','!']), suffix | |
11 | +def suffix(): return expression, Optional([ '?' , '*' , '+' , '#' ]) | |
12 | +def expression(): return [ regex_term, str_term, ('(', ordered_choice, ')'), rule_crossref] # OrderedChoice | |
13 | +def rule_crossref(): return rule_name | |
14 | +def rule_name(): return ID | |
15 | +def regex_term(): return [ (RE, re_no_slash, RE), # OrderedChoice | |
16 | + (REs3, str_no_s3, S3), | |
17 | + (REd3, str_no_d3, D3), | |
18 | + (REs1, str_no_s1, S1), | |
19 | + (REd1, str_no_d1, D1) ] | |
20 | +def str_term(): return [ (S3, str_no_s3, S3), # OrderedChoice | |
21 | + (D3, str_no_d3, D3), | |
22 | + (S1, str_no_s1, S1), | |
23 | + (D1, str_no_d1, D1) ] | |
24 | + | |
25 | +def ID(): return _(r"[a-zA-Z_]([a-zA-Z_]|[0-9])*") | |
26 | + | |
27 | +def re_no_slash(): return _(r"((\\/)|[^\/])*") | |
28 | + | |
29 | +def str_no_s1(): return _(r"((\\')|[^'\n])*") # Does NOT match multiline -- note 'multiline=False' is not the same | |
30 | +def str_no_d1(): return _(r'((\\")|[^"\n])*') # idem | |
31 | +def str_no_s3(): return _(r"([^']|('[^'])|(''[^']))*") # ALLOW multiline | |
32 | +def str_no_d3(): return _(r'''([^"]|("[^"])|(""[^"]))*''') # idem | |
33 | + | |
34 | +S1 = "'" | |
35 | +D1 = '"' | |
36 | +S3 = "'''" | |
37 | +D3 = '"""' | |
38 | +RE = '/' | |
39 | +REs1 = _(r"[rR]'") | |
40 | +REd1 = _(r'[rR]"') | |
41 | +REs3 = _(r"[rR]'''") | |
42 | +REd3 = _(r'[rR]"""') | |
43 | + | |
44 | +def comment(): return "//", _(".*\n") | |
45 | + |
@@ -0,0 +1,48 @@ | ||
1 | +from arpeggio import Optional, ZeroOrMore, OneOrMore, EOF | |
2 | +from arpeggio import RegExMatch as _ | |
3 | +from arpeggio import ParserPython | |
4 | + | |
5 | +def peg_grammar(): return rules, EOF | |
6 | +def rules(): return OneOrMore(rule) | |
7 | +def rule(): return rule_name, '<-', expressions, ";" | |
8 | + | |
9 | +def expressions(): return ( OneOrMore(single_expr), Optional( '|' , expressions ) ) | |
10 | +def single_expr(): return ( [ rule_crossref, term, group, predicate ], Optional([ '?' , '*' , '+' , '#' ])) | |
11 | + | |
12 | + | |
13 | +def term(): return [ str_term, regex_term ] | |
14 | +def group(): return '(', expressions, ')' | |
15 | +def predicate(): return ['&','!'], single_expr | |
16 | + | |
17 | +def str_term(): return [ (S3, str_no_s3, S3), | |
18 | + (D3, str_no_d3, D3), | |
19 | + (S1, str_no_s1, S1), | |
20 | + (D1, str_no_d1, D1) ] | |
21 | +def regex_term(): return [ (RE, re_no_slash, RE), | |
22 | + (REs3, str_no_s3, S3), | |
23 | + (REd3, str_no_d3, D3), | |
24 | + (REs1, str_no_s1, S1), | |
25 | + (REd1, str_no_d1, D1) ] | |
26 | +def rule_name(): return ID | |
27 | +def rule_crossref(): return ID | |
28 | +def ID(): return _(r"[a-zA-Z_]([a-zA-Z_]|[0-9])*") | |
29 | + | |
30 | +def re_no_slash(): return _(r"((\\/)|[^\/])*") | |
31 | +def str_no_s1(): return _(r"((\\')|[^'\n])*") # Does NOT match multiline -- note 'multiline=False' is not the same | |
32 | +def str_no_d1(): return _(r'((\\")|[^"\n])*') # idem | |
33 | +def str_no_s3(): return _(r"([^']|('[^'])|(''[^']))*") # ALLOW multiline | |
34 | +def str_no_d3(): return _(r'''([^"]|("[^"])|(""[^"]))*''') # idem | |
35 | + | |
36 | +S1 = "'" | |
37 | +D1 = '"' | |
38 | +S3 = "'''" | |
39 | +D3 = '"""' | |
40 | +RE = '/' | |
41 | +REs1 = _(r"[rR]'") | |
42 | +REd1 = _(r'[rR]"') | |
43 | +REs3 = _(r"[rR]'''") | |
44 | +REd3 = _(r'[rR]"""') | |
45 | + | |
46 | +def comment(): return "//", _(".*\n") | |
47 | + | |
48 | + |
@@ -37,7 +37,7 @@ | ||
37 | 37 | def test_mix_sub(): parse_sequence(r'/regex/ "string" ( A B ) crossref', pattern=[R,S, (X, X), X]) |
38 | 38 | |
39 | 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]) | |
40 | +def test_sub_sub2(): parse_sequence(r'level0 ( level1_1 (level2a level2b ) level1_2) level0', pattern=[X, [X, [X,X], X], X]) | |
41 | 41 | |
42 | 42 | |
43 | 43 |
@@ -11,10 +11,12 @@ | ||
11 | 11 | with (path_to_current_dir / dir / filename).open() as f: |
12 | 12 | txt = f.read() |
13 | 13 | |
14 | - parser = ParserPython(peg_grammar, comment) | |
14 | + parser = ParserPython(peg_grammar, comment, debug=False) | |
15 | 15 | tree = parser.parse(txt) |
16 | 16 | |
17 | 17 | assert tree.position_end == len(txt) , f"Not parsed whole input; Only: >>{regex[tree.position: tree.position_end]}<<; Not: >>{regex[tree.position_end:]}<<." |
18 | + | |
19 | + print("\nPARSE TREE\n" + tree.tree_str()) | |
18 | 20 | return tree |
19 | 21 | |
20 | 22 | def test_grammar(): parse_file("grammar.peg") |
@@ -1,4 +1,4 @@ | ||
1 | -// This is a fragment from ../examples/My_GrammarParser.Castle | |
1 | +//This is a fragment from ../examples/My_GrammarParser.Castle | |
2 | 2 | |
3 | 3 | peg_grammar <- rule+ ; |
4 | 4 | rule <- rule_name '<-' ordered_choice ';' ; |