add some more productions to the transformer
This commit is contained in:
parent
0dff746fc2
commit
5c09d658b9
6 changed files with 105 additions and 17 deletions
46
agast.py
46
agast.py
|
@ -1,11 +1,26 @@
|
|||
from typing import *
|
||||
from lark import Transformer, Tree
|
||||
from lark import Transformer, Tree, Token
|
||||
|
||||
class Interface: pass
|
||||
T = TypeVar("T")
|
||||
|
||||
class Node: pass
|
||||
class Decl:
|
||||
name: str
|
||||
class Iface(Decl):
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
class IfaceField: pass
|
||||
|
||||
class IfaceRef: pass
|
||||
|
||||
class Node(Decl):
|
||||
ifaces: List[IfaceRef]
|
||||
|
||||
class NodeRef: pass
|
||||
class NodeRefByName(NodeRef):
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
def __repr__(self) -> str: return f"NodeRefByName({self.name})"
|
||||
|
||||
|
||||
class Sym: pass
|
||||
class SymRename(Sym):
|
||||
|
@ -42,14 +57,33 @@ class ExprCall(Expr):
|
|||
self.func = func
|
||||
self.args = args
|
||||
def __repr__(self) -> str: return f"{self.func}({self.args})"
|
||||
class ExprName(Expr):
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
def __repr__(self) -> str: return f"{self.name}"
|
||||
|
||||
class Parser(Transformer[List[Decl]]):
|
||||
def program(self, items: List[Decl]) -> List[Decl]: return items
|
||||
|
||||
def iface(self, items: List[Any]) -> Iface:
|
||||
[name, fields] = items
|
||||
return Iface(name)
|
||||
def iface_field(self, items: List[str]) -> IfaceField:
|
||||
[name, ty] = items
|
||||
return IfaceField()
|
||||
|
||||
def node(self, items: List[Any]) -> Node:
|
||||
return Node()
|
||||
|
||||
class Parser(Transformer[None]):
|
||||
def variant(self, items: List[Any]) -> Variant:
|
||||
[prod, equations] = items
|
||||
return Variant(prod, equations)
|
||||
def prod(self, items: List[Sym]) -> List[Sym]: return items
|
||||
|
||||
def sym_rename(self, items: List[Any]) -> Sym: return SymRename(items[0], items[1])
|
||||
|
||||
def node_ref_name(self, items: List[str]) -> NodeRefByName: return NodeRefByName(items[0])
|
||||
|
||||
def expr_dot(self, items: List[Expr]) -> Expr:
|
||||
[left, _, right] = items
|
||||
return ExprDot(left, right)
|
||||
|
@ -62,3 +96,7 @@ class Parser(Transformer[None]):
|
|||
def expr_call(self, items: List[Expr]) -> Expr:
|
||||
[func, _, args, _] = items
|
||||
return ExprMul(func, args)
|
||||
|
||||
def sep_trail(self, items: List[Tree]) -> List[T]:
|
||||
return list(map(lambda it: cast(T, it), items))
|
||||
def ident(self, items: List[Token]) -> str: return cast(str, items[0].value)
|
||||
|
|
17
agtypeck.py
Normal file
17
agtypeck.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from typing import *
|
||||
from agast import *
|
||||
|
||||
def typecheck(program: List[Decl]) -> None:
|
||||
i = 0
|
||||
def gen(name: str = "") -> str:
|
||||
return f"__ag{i:03}{name}"
|
||||
|
||||
# collect a list of name -> iface declarations
|
||||
ifaces: Dict[str, Decl] = dict(
|
||||
map(lambda c: (c.name, c),
|
||||
filter(lambda c: isinstance(c, Iface),
|
||||
program)))
|
||||
print(ifaces)
|
||||
|
||||
for node in filter(lambda c: isinstance(c, Node), program):
|
||||
print(node)
|
21
gen.py
21
gen.py
|
@ -2,23 +2,34 @@ import textwrap
|
|||
import os
|
||||
from lark import Lark
|
||||
|
||||
from agast import Parser, Interface
|
||||
from agast import *
|
||||
from agtypeck import *
|
||||
|
||||
p = Lark(open("grammar.lark").read(), parser="lalr", transformer=Parser())
|
||||
p = Lark(open("grammar.lark").read(), start="program", parser="lalr")
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open("arith.ag") as f:
|
||||
data = f.read()
|
||||
|
||||
t = p.parse(data)
|
||||
print(t)
|
||||
cst = p.parse(data)
|
||||
# print("cst", cst)
|
||||
|
||||
trans = Parser()
|
||||
ast = trans.transform(cst)
|
||||
print("ast", ast)
|
||||
|
||||
typecheck(ast)
|
||||
|
||||
parser_data = ""
|
||||
|
||||
if not os.path.exists("gen"):
|
||||
os.makedirs("gen")
|
||||
with open("gen/arith.py", "w") as f:
|
||||
f.write(textwrap.dedent("""
|
||||
f.write(textwrap.dedent(f"""
|
||||
from typing import Generic, TypeVar
|
||||
from lark import Lark
|
||||
T = TypeVar('T')
|
||||
class Thunk(Generic[T]):
|
||||
pass
|
||||
parser = Lark('''{parser_data}''')
|
||||
"""))
|
||||
|
|
21
grammar.lark
21
grammar.lark
|
@ -1,19 +1,22 @@
|
|||
start: decl*
|
||||
program: decl*
|
||||
|
||||
decl: iface
|
||||
?decl: iface
|
||||
| node
|
||||
|
||||
iface: IFACE IDENT "{" iface_field (COMMA iface_field)? COMMA? "}"
|
||||
iface_field: IDENT COLON IDENT
|
||||
sep_trail{item, punc}: item (punc item)? punc?
|
||||
|
||||
node: NODE IDENT COLON IDENT "{" variant* "}"
|
||||
iface: "iface" ident "{" sep_trail{iface_field, ","} "}"
|
||||
iface_field: ident ":" ident
|
||||
|
||||
node: NODE ident ":" ident "{" variant* "}"
|
||||
variant: prod "=>" "{" equation_* "}"
|
||||
prod: sym*
|
||||
sym: sym_rename
|
||||
| STRING
|
||||
sym_rename: "<" IDENT ":" node_ref ">"
|
||||
node_ref: IDENT
|
||||
sym_rename: "<" ident ":" node_ref ">"
|
||||
node_ref: node_ref_name
|
||||
| STRING
|
||||
node_ref_name: ident
|
||||
equation_: equation SEMI
|
||||
equation: expr EQ expr
|
||||
|
||||
|
@ -21,13 +24,15 @@ expr: expr_dot
|
|||
| expr_add
|
||||
| expr_mul
|
||||
| expr_call
|
||||
| IDENT
|
||||
| expr_name
|
||||
expr_dot: expr DOT expr
|
||||
expr_add: expr ADD expr
|
||||
expr_mul: expr MUL expr
|
||||
expr_call: expr LPAR args RPAR
|
||||
expr_name: ident
|
||||
args: expr (COMMA expr)? COMMA?
|
||||
|
||||
ident: IDENT
|
||||
IDENT: /([a-zA-Z][a-zA-Z0-9_]*)|(_[a-zA-Z0-9_]+)/
|
||||
IFACE: "iface"
|
||||
NODE: "node"
|
||||
|
|
16
run.ps1
Normal file
16
run.ps1
Normal file
|
@ -0,0 +1,16 @@
|
|||
#blessed https://stackoverflow.com/a/52784160
|
||||
|
||||
function Invoke-Call {
|
||||
param (
|
||||
[scriptblock]$ScriptBlock,
|
||||
[string]$ErrorAction = $ErrorActionPreference
|
||||
)
|
||||
& @ScriptBlock
|
||||
if (($lastexitcode -ne 0) -and $ErrorAction -eq "Stop") {
|
||||
exit $lastexitcode
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-Call -ScriptBlock {mypy (get-item *.py) } -ErrorAction Stop
|
||||
Invoke-Call -ScriptBlock {python gen.py } -ErrorAction Stop
|
||||
Invoke-Call -ScriptBlock {mypy (get-item gen/*.py) } -ErrorAction Stop
|
1
watch.ps1
Normal file
1
watch.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
watchexec --shell=powershell -ce py -i gen './run.ps1'
|
Loading…
Reference in a new issue