Better parser tests
This commit is contained in:
parent
fa843e86aa
commit
197dfd0089
2 changed files with 71 additions and 41 deletions
|
@ -6,35 +6,13 @@
|
||||||
import typing as t
|
import typing as t
|
||||||
|
|
||||||
from ichor.isa import Opcode
|
from ichor.isa import Opcode
|
||||||
from lark import Lark
|
from lark import Lark, Transformer, v_args, Token
|
||||||
|
|
||||||
|
|
||||||
class Identifier(t.NamedTuple):
|
class Identifier(t.NamedTuple):
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
|
|
||||||
class FunctionSignature(t.NamedTuple):
|
|
||||||
raw: str
|
|
||||||
type_params: list
|
|
||||||
name: str
|
|
||||||
args: list
|
|
||||||
ret: list
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def parse_list(l):
|
|
||||||
return [e for e in l.split(",") if e]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse(cls, raw: str):
|
|
||||||
vars, name, args, ret = raw.split(";")
|
|
||||||
return cls(
|
|
||||||
raw,
|
|
||||||
cls.parse_list(vars),
|
|
||||||
name,
|
|
||||||
cls.parse_list(args),
|
|
||||||
cls.parse_list(ret)
|
|
||||||
)
|
|
||||||
|
|
||||||
GRAMMAR = r"""
|
GRAMMAR = r"""
|
||||||
fun: constraints ";" name ";" arguments ";" ret
|
fun: constraints ";" name ";" arguments ";" ret
|
||||||
|
|
||||||
|
@ -44,7 +22,7 @@ constraints: (constraint ","?)*
|
||||||
constraint: type
|
constraint: type
|
||||||
|
|
||||||
var: constraints ";" name ";" arms
|
var: constraints ";" name ";" arms
|
||||||
arms: (arm ("," arms)?)?
|
arms: (arm ","?)+
|
||||||
arm: name "(" bindings ")"
|
arm: name "(" bindings ")"
|
||||||
|
|
||||||
bindings: (binding ","?)*
|
bindings: (binding ","?)*
|
||||||
|
@ -52,10 +30,37 @@ binding: name ":" type
|
||||||
|
|
||||||
type: NAME
|
type: NAME
|
||||||
name: NAME
|
name: NAME
|
||||||
NAME: /[^;,:⊢]+/
|
NAME: /[^;,:⊢()<>\[\]{}|]+/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
FUNC = Lark(GRAMMAR, start="fun")
|
class FuncT(Transformer):
|
||||||
|
@v_args(inline=True)
|
||||||
|
def fun(self, constraints, name, arguments, ret):
|
||||||
|
return (constraints, name, arguments, ret)
|
||||||
|
|
||||||
|
def constraints(self, args):
|
||||||
|
return (*args,)
|
||||||
|
|
||||||
|
def arguments(self, args):
|
||||||
|
return tuple(args)
|
||||||
|
|
||||||
|
def ret(self, args):
|
||||||
|
return tuple(args)
|
||||||
|
|
||||||
|
@v_args(inline=True)
|
||||||
|
def NAME(self, name: Token):
|
||||||
|
return name.value
|
||||||
|
|
||||||
|
@v_args(inline=True)
|
||||||
|
def name(self, name):
|
||||||
|
return name
|
||||||
|
|
||||||
|
@v_args(inline=True)
|
||||||
|
def type(self, name):
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
FUNC = Lark(GRAMMAR, start="fun", parser='lalr', transformer=FuncT())
|
||||||
|
|
||||||
|
|
||||||
class FunctionRef(t.NamedTuple):
|
class FunctionRef(t.NamedTuple):
|
||||||
|
@ -90,8 +95,36 @@ class Function(t.NamedTuple):
|
||||||
typeconstraints: t.List[t.Any] = []
|
typeconstraints: t.List[t.Any] = []
|
||||||
metadata: dict = {}
|
metadata: dict = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def build(cls, name: str, instructions: t.List[Opcode]):
|
||||||
|
pass
|
||||||
|
|
||||||
VAR = Lark(GRAMMAR, start="var")
|
|
||||||
|
class VarT(FuncT):
|
||||||
|
@v_args(inline=True)
|
||||||
|
def var(self, constraints, name, arms):
|
||||||
|
return (constraints, name, arms)
|
||||||
|
|
||||||
|
@v_args(inline=True)
|
||||||
|
def constraint(self, name):
|
||||||
|
return name
|
||||||
|
|
||||||
|
def arms(self, arms):
|
||||||
|
return tuple(arms)
|
||||||
|
|
||||||
|
def binding(self, binding):
|
||||||
|
return tuple(binding)
|
||||||
|
|
||||||
|
def bindings(self, bindings):
|
||||||
|
return tuple(bindings)
|
||||||
|
|
||||||
|
@v_args(inline=True)
|
||||||
|
def arm(self, name, bindings):
|
||||||
|
return (name, bindings)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VAR = Lark(GRAMMAR, start="var", parser='lalr', transformer=VarT())
|
||||||
|
|
||||||
class Type(t.NamedTuple):
|
class Type(t.NamedTuple):
|
||||||
name: str
|
name: str
|
||||||
|
|
|
@ -5,21 +5,18 @@ from ichor.state import FUNC, VAR
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('sig', [
|
@pytest.mark.parametrize('sig,parse', [
|
||||||
";not;bool;bool",
|
(";not;bool;bool", ((), "not", ("bool",), ("bool",))),
|
||||||
";and;bool,bool;bool",
|
(";and;bool,bool;bool", ((), "and", ("bool", "bool"), ("bool",))),
|
||||||
";or;bool,bool,bool;bool",
|
(";or;bool,bool,bool;bool", ((), "or", ("bool", "bool", "bool"), ("bool",))),
|
||||||
])
|
])
|
||||||
def test_func_parses(sig):
|
def test_func_parses(sig, parse):
|
||||||
assert FUNC.parse(sig)
|
assert FUNC.parse(sig) == parse
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('sig', [
|
@pytest.mark.parametrize('sig,parse', [
|
||||||
";bool;true(),false()",
|
(";bool;true(),false()", ((), "bool", (("true", ()), ("false", ())))),
|
||||||
"A,B;pair;pair(a:A,b:B)",
|
("A,B;pair;pair(a:A,b:B)", (("A", "B"), "pair", (("pair", (("a", "A"), ("b", "B"))),))),
|
||||||
"A,B,C;tripple;tripple(a:A,b:B,c:C)",
|
|
||||||
"A,B,C,D;quad;quad(a:A,b:B,c:C,d:D)",
|
|
||||||
"A,B,C,D,E;quint;quint(a:A,b:B,c:C,d:D,e:E)",
|
|
||||||
])
|
])
|
||||||
def test_var_parses(sig):
|
def test_var_parses(sig, parse):
|
||||||
assert VAR.parse(sig)
|
assert VAR.parse(sig) == parse
|
||||||
|
|
Loading…
Reference in a new issue