diff --git a/.gitignore b/.gitignore index 791e803..13034c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .mypy_cache +__pycache__ gen/ diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..28551c9 --- /dev/null +++ b/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +lark-parser = "==0.11.3" + +[dev-packages] +mypy = "==0.901" + +[requires] +python_version = "3.9" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..2d28c65 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,81 @@ +{ + "_meta": { + "hash": { + "sha256": "225e01979b7cd88f078f6c030af46ff11f7af0bf8c34a7deeb50be649492cd4d" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.9" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "lark-parser": { + "hashes": [ + "sha256:e29ca814a98bb0f81674617d878e5f611cb993c19ea47f22c80da3569425f9bd" + ], + "index": "pypi", + "version": "==0.11.3" + } + }, + "develop": { + "mypy": { + "hashes": [ + "sha256:053b92ebae901fc7954677949049f70133f2f63e3e83dc100225c26d6a46fe95", + "sha256:08cf1f31029612e1008a9432337ca4b1fbac989ff7c8200e2c9ec42705cd4c7b", + "sha256:18753a8bb9bcf031ff10009852bd48d781798ecbccf45be5449892e6af4e3f9f", + "sha256:1cd241966a35036f936d4739bd71a1c64e15f02bf7d12bb2815cccfb2993a9de", + "sha256:307a6c047596d768c3d689734307e47a91596eb9dbb67cfdf7d1fd9117b27f13", + "sha256:4a622faa3be76114cdce009f8ec173401494cf9e8f22713e7ae75fee9d906ab3", + "sha256:4b54518e399c3f4dc53380d4252c83276b2e60623cfc5274076eb8aae57572ac", + "sha256:5ddd8f4096d5fc2e7d7bb3924ac22758862163ad2c1cdc902c4b85568160e90a", + "sha256:61b10ba18a01d05fc46adbf4f18b0e92178f6b5fd0f45926ffc2a408b5419728", + "sha256:7845ad3a31407bfbd64c76d032c16ab546d282930f747023bf07c17b054bebc5", + "sha256:79beb6741df15395908ecc706b3a593a98804c1d5b5b6bd0c5b03b67c7ac03a0", + "sha256:8183561bfd950e93eeab8379ae5ec65873c856f5b58498d23aa8691f74c86030", + "sha256:91211acf1485a1db0b1261bc5f9ed450cba3c0dfd8da0a6680e94827591e34d7", + "sha256:97be0e8ed116f7f79472a49cf06dd45dd806771142401f684d4f13ee652a63c0", + "sha256:9941b685807b60c58020bb67b3217c9df47820dcd00425f55cdf71f31d3c42d9", + "sha256:a85c6759dcc6a9884131fa06a037bd34352aa3947e7f5d9d5a35652cc3a44bcd", + "sha256:bc61153eb4df769538bb4a6e1045f59c2e6119339690ec719feeacbfc3809e89", + "sha256:bf347c327c48d963bdef5bf365215d3e98b5fddbe5069fc796cec330e8235a20", + "sha256:c86e3f015bfe7958646825d41c0691c6e5a5cd4015e3409b5c29c18a3c712534", + "sha256:c8bc628961cca4335ac7d1f2ed59b7125d9252fe4c78c3d66d30b50162359c99", + "sha256:da914faaa80c25f463913da6db12adba703822a768f452f29f75b40bb4357139", + "sha256:e8577d30daf1b7b6582020f539f76e78ee1ed64a0323b28c8e0333c45db9369f", + "sha256:f208cc967e566698c4e30a1f65843fc88d8da05a8693bac8b975417e0aee9ced" + ], + "index": "pypi", + "version": "==0.901" + }, + "mypy-extensions": { + "hashes": [ + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + ], + "version": "==0.4.3" + }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.10.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497", + "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342", + "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84" + ], + "version": "==3.10.0.0" + } + } +} diff --git a/agast.py b/agast.py new file mode 100644 index 0000000..376ae3a --- /dev/null +++ b/agast.py @@ -0,0 +1,64 @@ +from typing import * +from lark import Transformer, Tree + +class Interface: pass + +class Node: pass + +class NodeRef: pass + +class Sym: pass +class SymRename(Sym): + def __init__(self, name: str, node_ref: NodeRef): + self.name = name + self.node_ref = node_ref + def __repr__(self) -> str: return f"SymRename({self.name} : {self.node_ref})" +class Equation: pass + +class Variant: + def __init__(self, prod: List[Sym], equations: List[Equation]): + self.prod = prod + self.equations = equations + def __repr__(self) -> str: return f"Variant({self.prod}, {self.equations})" + +class Expr: pass +class ExprDot(Expr): + def __init__(self, left: Expr, right: Expr): + self.left = left + self.right = right + def __repr__(self) -> str: return f"{self.left}.{self.right}" +class ExprAdd(Expr): + def __init__(self, left: Expr, right: Expr): + self.left = left + self.right = right + def __repr__(self) -> str: return f"{self.left} + {self.right}" +class ExprMul(Expr): + def __init__(self, left: Expr, right: Expr): + self.left = left + self.right = right + def __repr__(self) -> str: return f"{self.left} * {self.right}" +class ExprCall(Expr): + def __init__(self, func: Expr, args: List[Expr]): + self.func = func + self.args = args + def __repr__(self) -> str: return f"{self.func}({self.args})" + +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 expr_dot(self, items: List[Expr]) -> Expr: + [left, _, right] = items + return ExprDot(left, right) + def expr_add(self, items: List[Expr]) -> Expr: + [left, _, right] = items + return ExprAdd(left, right) + def expr_mul(self, items: List[Expr]) -> Expr: + [left, _, right] = items + return ExprMul(left, right) + def expr_call(self, items: List[Expr]) -> Expr: + [func, _, args, _] = items + return ExprMul(func, args) diff --git a/arith.ag b/arith.ag index 6d4adf7..90867bc 100644 --- a/arith.ag +++ b/arith.ag @@ -1,8 +1,8 @@ -iface Node { +iface HasValue { val: int, } -node Expr : Node { +node Expr : HasValue { "+" => { self.val = l.val + r.val; } diff --git a/gen.py b/gen.py index ac6c0d8..b773ea2 100644 --- a/gen.py +++ b/gen.py @@ -2,7 +2,9 @@ import textwrap import os from lark import Lark -p = Lark(open("grammar.lark").read()) +from agast import Parser, Interface + +p = Lark(open("grammar.lark").read(), parser="lalr", transformer=Parser()) if __name__ == "__main__": with open("arith.ag") as f: diff --git a/grammar.lark b/grammar.lark index 9e2a3bf..338fb44 100644 --- a/grammar.lark +++ b/grammar.lark @@ -6,21 +6,26 @@ decl: iface iface: IFACE IDENT "{" iface_field (COMMA iface_field)? COMMA? "}" iface_field: IDENT COLON IDENT -node: NODE IDENT COLON IDENT "{" node_prod* "}" -node_prod: prod THICCARROW "{" (equation SEMI)* "}" +node: NODE IDENT COLON IDENT "{" variant* "}" +variant: prod "=>" "{" equation_* "}" prod: sym* -sym: IDENT - | LANG IDENT COLON node_ref RANG +sym: sym_rename | STRING +sym_rename: "<" IDENT ":" node_ref ">" node_ref: IDENT | STRING +equation_: equation SEMI equation: expr EQ expr -expr: expr DOT expr - | expr ADD expr - | expr MUL expr - | expr LPAR args RPAR +expr: expr_dot + | expr_add + | expr_mul + | expr_call | IDENT +expr_dot: expr DOT expr +expr_add: expr ADD expr +expr_mul: expr MUL expr +expr_call: expr LPAR args RPAR args: expr (COMMA expr)? COMMA? IDENT: /([a-zA-Z][a-zA-Z0-9_]*)|(_[a-zA-Z0-9_]+)/