testing all of this in python
This commit is contained in:
177
boring/parse.py
Normal file
177
boring/parse.py
Normal file
@@ -0,0 +1,177 @@
|
||||
import sys
|
||||
import enum
|
||||
from typing import Union
|
||||
from dataclasses import dataclass, field
|
||||
from lark import Lark, Transformer
|
||||
|
||||
|
||||
@dataclass
|
||||
class Identifier:
|
||||
name: str
|
||||
|
||||
|
||||
class Operator(enum.Enum):
|
||||
mult = "mult"
|
||||
div = "div"
|
||||
plus = "plus"
|
||||
minus = "minus"
|
||||
|
||||
|
||||
@dataclass
|
||||
class LiteralInt:
|
||||
value: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class FunctionCall:
|
||||
name: Identifier
|
||||
arguments: list['Expression'] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Operation:
|
||||
left: 'Expression'
|
||||
op: Operator
|
||||
right: 'Expression'
|
||||
|
||||
|
||||
@dataclass
|
||||
class Expression:
|
||||
expression: Union[LiteralInt,FunctionCall,Identifier,Operation,'Expression']
|
||||
|
||||
|
||||
@dataclass
|
||||
class Block:
|
||||
expression: Expression
|
||||
|
||||
|
||||
@dataclass
|
||||
class VariableDeclaration:
|
||||
name: Identifier
|
||||
|
||||
|
||||
@dataclass
|
||||
class Function:
|
||||
name: Identifier
|
||||
arguments: list[VariableDeclaration]
|
||||
block: Block
|
||||
|
||||
|
||||
@dataclass
|
||||
class Module:
|
||||
functions: Function
|
||||
|
||||
|
||||
|
||||
boring_grammar = r"""
|
||||
plus : "+"
|
||||
minus : "-"
|
||||
mult : "*"
|
||||
div : "/"
|
||||
|
||||
literal_int: SIGNED_NUMBER
|
||||
identifier : NAME
|
||||
function_call : identifier "(" [expression ("," expression)*] ")"
|
||||
|
||||
add_expression : expression plus factor
|
||||
sub_expression : expression minus factor
|
||||
mult_expression : expression mult term
|
||||
div_expression : expression div term
|
||||
|
||||
expression : add_expression
|
||||
| sub_expression
|
||||
| factor
|
||||
|
||||
factor : mult_expression
|
||||
| div_expression
|
||||
| term
|
||||
|
||||
term : literal_int
|
||||
| identifier
|
||||
| function_call
|
||||
| "(" expression ")"
|
||||
|
||||
block : "{" expression "}"
|
||||
|
||||
variable_declaration : identifier
|
||||
|
||||
function : "fn" identifier "(" [variable_declaration ("," variable_declaration)*] ")" block
|
||||
|
||||
module : (function)*
|
||||
|
||||
%import common.CNAME -> NAME
|
||||
%import common.SIGNED_NUMBER
|
||||
%import common.WS
|
||||
%ignore WS
|
||||
"""
|
||||
|
||||
class TreeToBoring(Transformer):
|
||||
def plus(self, p):
|
||||
return Operator.plus
|
||||
|
||||
def minus(self, m):
|
||||
return Operator.minus
|
||||
|
||||
def mult(self, m):
|
||||
return Operator.mult
|
||||
|
||||
def div(self, d):
|
||||
return Operator.div
|
||||
|
||||
def literal_int(self, n):
|
||||
(n,) = n
|
||||
return LiteralInt(value=int(n))
|
||||
|
||||
def identifier(self, i):
|
||||
(i,) = i
|
||||
return Identifier(name=str(i))
|
||||
|
||||
def function_call(self, call):
|
||||
return FunctionCall(name=call[0], arguments=call[1:])
|
||||
|
||||
def add_expression(self, ae):
|
||||
return Operation(left=ae[0], op=ae[1], right=ae[2])
|
||||
|
||||
def sub_expression(self, se):
|
||||
return Operation(left=se[0], op=se[1], right=se[2])
|
||||
|
||||
def mult_expression(self, se):
|
||||
return Operation(left=se[0], op=se[1], right=se[2])
|
||||
|
||||
def div_expression(self, se):
|
||||
return Operation(left=se[0], op=se[1], right=se[2])
|
||||
|
||||
def expression(self, exp):
|
||||
(exp,) = exp
|
||||
return Expression(expression=exp)
|
||||
|
||||
def factor(self, factor):
|
||||
(factor,) = factor
|
||||
return Expression(factor)
|
||||
|
||||
def term(self, term):
|
||||
(term,) = term
|
||||
return Expression(term)
|
||||
|
||||
def block(self, block):
|
||||
(block,) = block
|
||||
return Block(expression=block)
|
||||
|
||||
def variable_declaration(self, identifier):
|
||||
(identifier,) = identifier
|
||||
return VariableDeclaration(name=identifier)
|
||||
|
||||
def function(self, function):
|
||||
return Function(name=function[0], arguments=function[1:-1], block=function[-1])
|
||||
|
||||
def module(self, functions):
|
||||
return Module(functions=functions)
|
||||
|
||||
|
||||
boring_parser = Lark(boring_grammar, start='module', lexer='standard')
|
||||
|
||||
if __name__ == '__main__':
|
||||
with open(sys.argv[1]) as f:
|
||||
tree = boring_parser.parse(f.read())
|
||||
print(tree)
|
||||
print(TreeToBoring().transform(tree))
|
||||
Reference in New Issue
Block a user