Castle: The best Real-Time/Embedded/HighTech language EVER. Attempt 2
Revision | 7156fb339e3311903043a33ebd30c776a742d3a4 (tree) |
---|---|
Zeit | 2021-12-23 08:20:52 |
Autor | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
Added ID (rule_name & rule_crossref) to AST/vistor
@@ -17,7 +17,7 @@ | ||
17 | 17 | |
18 | 18 | import re |
19 | 19 | |
20 | -class ID(str): | |
20 | +class ID(AST_BASE): | |
21 | 21 | _pattern = re.compile(r'[A-Za-z_][A-Za-z0-9_]*') |
22 | 22 | |
23 | 23 | @staticmethod |
@@ -27,3 +27,8 @@ | ||
27 | 27 | if ID._pattern.fullmatch(value) is None: |
28 | 28 | raise IDError("not a valid pattern") |
29 | 29 | |
30 | + def __init__(self, *, name, **kwargs): | |
31 | + super().__init__(**kwargs) | |
32 | + self.validate_or_raise(name) | |
33 | + self.name=name | |
34 | + |
@@ -1,4 +1,4 @@ | ||
1 | -from ._base import AST_BASE, ID | |
1 | +from ._base import AST_BASE, ID, IDError | |
2 | 2 | |
3 | 3 | class PEG (AST_BASE): # abstract |
4 | 4 | """Base class of all PEG classes""" |
@@ -72,7 +72,7 @@ | ||
72 | 72 | super().__init__(**kwargs) |
73 | 73 | self.value=value |
74 | 74 | |
75 | - | |
75 | + | |
76 | 76 | class OrderedChoice(Expression):pass |
77 | 77 | class Predicate(Expression): pass # abstract |
78 | 78 |
@@ -0,0 +1,10 @@ | ||
1 | +import visitor | |
2 | +import arpeggio | |
3 | + | |
4 | +def parse(txt, rule): | |
5 | + parser = arpeggio.ParserPython(rule) | |
6 | + pt = parser.parse(txt) | |
7 | + assert pt.position_end == len(txt), f"Did not parse all input txt=>>{txt}<<len={len(txt)} ==> parse_tree: >>{pt}<<_end={pt.position_end}" | |
8 | + ast = arpeggio.visit_parse_tree(pt, visitor.PegVisitor()) | |
9 | + assert ast.position == 0 and ast.position_end == len(txt), f"Also the AST (type={type(ast)}) should include all input" | |
10 | + return ast |
@@ -1,20 +1,11 @@ | ||
1 | 1 | import pytest |
2 | 2 | |
3 | 3 | import grammar |
4 | -import visitor | |
5 | -import arpeggio | |
6 | 4 | |
7 | 5 | import sys; sys.path.append("./../AST/") ; sys.path.append("./../../AST/") |
8 | 6 | from castle import peg # has the AST clases |
9 | 7 | |
10 | - | |
11 | -def parse(txt, rule): | |
12 | - parser = arpeggio.ParserPython(rule) | |
13 | - pt = parser.parse(txt) | |
14 | - assert pt.position_end == len(txt), "Did not parse all input" # JTBS | |
15 | - ast = arpeggio.visit_parse_tree(pt, visitor.PegVisitor()) | |
16 | - assert ast.position == 0 and ast.position_end == len(txt), "Also the AST should include all input" | |
17 | - return ast | |
8 | +from . import parse | |
18 | 9 | |
19 | 10 | def test_simple_str(): |
20 | 11 | txt="'a string'" |
@@ -4,16 +4,25 @@ | ||
4 | 4 | from castle import peg # has the AST clases |
5 | 5 | |
6 | 6 | class PegVisitor(arpeggio.PTNodeVisitor): |
7 | + | |
7 | 8 | def visit_str_term(self, node, children): |
8 | 9 | ast = peg.StrTerm(value=node[1], parse_tree=node) |
9 | 10 | return ast |
10 | 11 | def visit_regex_term(self, node, children): |
11 | 12 | ast = peg.RegExpTerm(value=node[1], parse_tree=node) |
12 | 13 | return ast |
14 | + | |
15 | + def visit_rule_name(self, node, children): | |
16 | + ast = peg.ID(name=str(node), parse_tree=node) | |
17 | + return ast | |
18 | + def visit_rule_crossref(self, node, children): | |
19 | + ast = peg.ID(name=str(node), parse_tree=node) | |
20 | + return ast | |
21 | + | |
13 | 22 | def visit_single_expr(self, node, children): # [ rule_crossref, term, group, predicate ] Optional([ '?' , '*' , '+' , '#' ])) |
14 | 23 | if len(children) == 1: # No optional part |
15 | 24 | ast = peg.Sequence(value=children, parse_tree=node) |
16 | 25 | else: |
17 | 26 | assert NotImplementedError("To Do: visit_single_expr with optional part") |
27 | + return ast | |
18 | 28 | |
19 | - return ast |