Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from lepl import *
- from operator import add, sub, mul, truediv
- # ast nodes
- class Op(List):
- def __float__(self):
- return self._op(float(self[0]), float(self[1]))
- class Add(Op): _op = add
- class Sub(Op): _op = sub
- class Mul(Op): _op = mul
- class Div(Op): _op = truediv
- class Assign(List): pass
- class AssignMul(List): pass
- class AssignDiv(List): pass
- class AssignAdd(List): pass
- class AssignSub(List): pass
- class Eq(List): pass
- class NEq(List): pass
- class GreaterEqual(List): pass
- class GreaterThan(List): pass
- class LessThan(List): pass
- class LessEqual(List): pass
- class AND(List): pass
- class OR(List): pass
- class Expr(List): pass
- class Args(Node): pass
- class Function(List): pass
- class FuncDefHead(List): pass
- class FuncDefParams(List): pass
- class FuncDef(List): pass
- class Block(List): pass
- class EqMul(List): pass
- class EqDiv(List): pass
- class EqSub(List): pass
- class EqPlus(List): pass
- class LoopHead(List): pass
- class LoopBlock(List): pass
- class UnarySub(List): pass
- class UnaryPlus(List): pass
- class IfBlock(List): pass
- class ElifBlock(List): pass
- class ElseBlock(List): pass
- class OutputCall(List): pass
- class InputCall(List): pass
- #basic tokens
- value = Token(UnsignedReal())
- int_ = Token('[0-9]')[1:,...]
- symbol = Token('[^0-9a-zA-Z \t\r\n]')
- none = Token('No') >> (lambda x: None)
- bool = (Token('T') | Token('F')) >> (lambda x: x == 'T')
- ident = Token("[a-zA-Z][a-zA-Z0-9_ ]*")[1:,...]
- singlequotestr = Token("'[a-zA-Z0-9\.\?:!~@#\$%\^&\*\(\)-_=\+\{\}\[\]\|;\"<>,/ \n\r\t]+'")[1:1,...]
- doublequotestr = Token('"[a-zA-Z0-9\.\?:!~@#\$%\^&\*\(\)-_=\+\{\}\[\]\|;\'<>,/ \n\r\t]+"')[1:1,...]
- #delayed symbols
- group2 = Delayed()
- group3 = Delayed()
- expr = Delayed()
- lexpr = Delayed()
- list_tuple_item = Delayed()
- funccall = Delayed()
- block = Delayed()
- operation = Delayed()
- outcall = Delayed()
- incall = Delayed()
- #simple but non-basic symbols
- float_ = (Optional(symbol('-')) & int_ & symbol('.')[0:1] & int_[0:]) > (lambda x: float("%s" % ''.join(x)))
- number = float_
- comma = ~symbol(',')
- str_ = singlequotestr | doublequotestr #needs stringify function
- item = str_ | number | none | bool | ident
- #comparison symbols
- NEQ = symbol("!") & symbol("=")
- EQ = symbol("=")[2:2,...]
- GT = symbol(">")
- GE = symbol(">") & symbol("=")
- LT = symbol("<")
- LE = symbol("<") & symbol("=")
- #syntactical symbols
- lparens = symbol('(')
- rparens = symbol(')')
- ifsym = symbol('~')
- elsesym = symbol('#')
- lcurly = symbol('{')
- rcurly = symbol('}')
- EOL = symbol(';')
- #assignment operations
- eqMul = symbol('*') & symbol('=') > EqMul
- eqDiv = symbol('/') & symbol('=') > EqDiv
- eqPlus = symbol('+') & symbol('=') > EqPlus
- eqSub = symbol('-') & symbol('=') > EqSub
- equal = symbol('=')
- #unary ops
- unPlus = symbol('+') & symbol('+')
- unSub = symbol('-') & symbol('-')
- operPlus = ident & ~unPlus > UnaryPlus
- operSub = ident & ~unSub > UnarySub
- operation += operPlus | operSub
- #statement operations
- ###################################################################
- # basic handling for mathematical operations
- # first layer, most tightly grouped, is parens, numbers, and items
- parens = ~symbol('(') & group3 & ~symbol(')')
- group1 = parens | item | funccall | operation | outcall | incall
- # second layer, next most tightly grouped, is multiplication
- mul_ = group1 & ~symbol('*') & group2 > Mul
- div_ = group1 & ~symbol('/') & group2 > Div
- group2 += mul_ | div_ | group1
- # third layer, least tightly grouped, is addition
- add_ = group2 & ~symbol('+') & group3 > Add
- sub_ = group2 & ~symbol('-') & group3 > Sub
- group3 += add_ | sub_ | group2
- ####################################################################
- #########################################################################
- #argument list handling
- # handles infinite inner lists/tuples, as well as argument amounts.
- # first one handles lists
- list_ = ~symbol('[') & list_tuple_item[:, comma] & ~symbol(']') > list
- #third is an Or of list, and item
- list_tuple_item += item | group3 | list_ | funccall
- #rename list_tuple_item to arg for shortness
- arg = list_tuple_item >> 'arg'
- #gather a comma-delimited list of arguments
- arg_expr = (arg)[1:, comma] > Args
- ############################################################################
- ####
- #expression handling.
- #Use a series of progressively wider expressions to simplify recursion.
- #Starts with AND/OR expressions
- #then to comparison expressions
- #to equality expressions
- #boolean expressions
- bool_expr = Or(
- lexpr & ~symbol('&') & expr > AND,
- lexpr & ~symbol('?') & expr > OR
- )
- #comparison expressions
- ot_expr = Or(
- bool_expr,
- lexpr & ~GT & expr > GreaterThan,
- lexpr & ~GE & expr > GreaterEqual,
- lexpr & ~LT & expr > LessThan,
- lexpr & ~LE & expr > LessEqual
- )
- #equality expressions
- eq_expr = Or(
- ot_expr,
- lexpr & ~EQ & expr > Eq,
- lexpr & ~NEQ & expr > NEq
- )
- #renames all the sub_expr types to be cond
- cond = eq_expr
- #function calls: func(a, b=10)
- funccall += Or((ident & ~lparens & arg_expr & ~rparens), (ident & ~lparens & ~rparens)) > Function #'function'
- #function definitions: separate the head, the params, and the block.
- funcdef_head = ~symbol('^') & ident > FuncDefHead
- funcdef_params = ~symbol(':') & arg_expr > FuncDefParams
- funcdef = funcdef_head & funcdef_params & block > FuncDef
- #loops:
- # [cond;operation]{}
- # [cond;]{}
- loophead = ~symbol('[') & cond & ~symbol(';') & operation[0:] & ~symbol(']') >LoopHead
- loopblock = loophead & block > LoopBlock
- #if, else if, and else construction
- ifblock = ~ifsym & ~lparens & cond & ~rparens & block > IfBlock
- elseifblock = ~elsesym & ~lparens & cond & ~rparens & block > ElifBlock
- elseblock = ~elsesym & block > ElseBlock
- ifstruct = ifblock & elseifblock[0:] & elseblock[0:]
- #input/output calls
- #@<var containing string with account name>(output)
- #$<var containing string with account name>(interogative to ask for input)
- outcall += ~symbol('@') & ident & ~lparens & (str_ | ident) & ~rparens > OutputCall
- incall += ~symbol('$') & ident & ~lparens & (str_ | ident) & ~rparens > InputCall
- #finally define expr
- expr += Or( cond , funccall , outcall, incall, group3 , operation, number , ident , str_) > Expr
- lexpr += Or( item, operation, group3) > Expr
- #assignment statement
- assgn_mul = ident & ~eqMul & expr & ~EOL > AssignMul
- assgn_div = ident & ~eqDiv & expr & ~EOL > AssignDiv
- assgn_add = ident & ~eqPlus & expr & ~EOL > AssignAdd
- assgn_sub = ident & ~eqSub & expr & ~EOL > AssignSub
- assgn_eq = ident & ~equal & expr & ~EOL > Assign
- assgn_mulb = ident & ~eqMul & expr & ~rcurly > AssignMul
- assgn_divb = ident & ~eqDiv & expr & ~rcurly > AssignDiv
- assgn_addb = ident & ~eqPlus & expr & ~rcurly > AssignAdd
- assgn_subb = ident & ~eqSub & expr & ~rcurly > AssignSub
- assgn_eqb = ident & ~equal & expr & ~rcurly > Assign
- assgn_stmt = Or(assgn_mul, assgn_div, assgn_add, assgn_sub, assgn_eq)
- assgn_stmt_blockend = Or(assgn_mulb, assgn_divb, assgn_addb, assgn_subb, assgn_eqb)
- #generic statement construction
- stmt = operation & ~EOL | assgn_stmt | funccall & ~EOL | funcdef | loopblock | ifstruct | incall & ~EOL | outcall & ~EOL
- stmt_blockend = assgn_stmt_blockend | funccall & ~rcurly | operation & ~rcurly | funcdef | loopblock | ifstruct | incall & ~rcurly | outcall & ~rcurly
- #string of statements
- multi_stmt = stmt[0:]
- block += ~lcurly & multi_stmt & ~rcurly | ~lcurly & multi_stmt & stmt_blockend[1:1] > Block
- #block.config.no_full_first_match()
- #ast = block.parse('{c=0;b=rnd();[c==0;]{a=$slf("Guess a number: ");~(a<b){@slf("Too low")}#(a>b){@slf("Too high!")}#{@slf("Just right.");c=1}}')
- #print List(ast)
- #for i in list(ast):
- # print List(i)
- ##########################################
- #test code
- ##########################################
- if __name__ == '__main__':
- #testing code
- ast = none.parse("No")
- print "None Test: ", ast[0]==None
- ast = bool.parse("T")
- ast2 = bool.parse("F")
- print "Boolean Test: ", ast[0]==True, ast2[0]==False
- ast = ident.parse("abc")
- ast2 = ident.parse("abc6")
- ast3 = ident.parse("a_bc")
- ast4 = ident.parse("a_b6_c")
- print "Ident Test: ", ast[0]=='abc', ast2[0]=='abc6', ast3[0]=='a_bc', ast4[0]=='a_b6_c'
- ast = str_.parse('"testing ut87st8st867.?s"')
- ast2 = str_.parse("'testing ut87st8st867.?s'")
- print "String Test: ", ast[0]=='"testing ut87st8st867.?s"', ast2[0]=="'testing ut87st8st867.?s'"
- ast = number.parse('10')
- ast2 = number.parse('10.0')
- ast3 = number.parse('-10')
- ast4 = number.parse('-10.0 ')
- print "Number Test: ", ast[0]==10.0, ast2[0]==10.0, ast3[0]==-10.0, ast4[0]==-10.0
- ast = item.parse("'test'")
- ast2 = item.parse('-10.0')
- ast3 = item.parse('No')
- ast4 = item.parse('T')
- ast5 = item.parse('abc')
- print "Item Test: ", ast[0]=="'test'", ast2[0]==-10.0, ast3[0]==None, ast4[0]==True, ast5[0]=='abc'
- ast = group3.parse('1+2*(3-4)+5/6+7')
- print "Numerical Evaluation Test: ", float(ast[0])== 1.0+2.0*(3.0-4.0)+5.0/6.0+7.0
- ast = arg_expr.parse("a, b, 10, -10.0, [1, a, b, [[c, d], [[a]]]]")
- #print str(List(ast))
- print "Argument Evaluation Test: ", str(List(ast))=="""List
- `- Args
- +- 'a'
- +- 'b'
- +- 10.0
- +- -10.0
- `- list
- +- 1.0
- +- 'a'
- +- 'b'
- `- list
- +- list
- | +- 'c'
- | `- 'd'
- `- list
- `- list
- `- 'a'"""
- ast = expr.parse("a==b")
- ast2 = expr.parse("a>=b")
- ast3 = expr.parse("a&b")
- ast4 = expr.parse("4+5")
- print "Expression Evaluation Test: ", str(List(ast))=="""List
- `- Expr
- `- Eq
- +- Expr
- | `- 'a'
- `- Expr
- `- 'b'""",
- print str(List(ast2))=="""List
- `- Expr
- `- GreaterEqual
- +- Expr
- | `- 'a'
- `- Expr
- `- 'b'""",
- print str(List(ast3))=="""List
- `- Expr
- `- AND
- +- Expr
- | `- 'a'
- `- Expr
- `- 'b'""",
- print str(List(ast4))=="""List
- `- Expr
- `- Add
- +- 4.0
- `- 5.0"""
- ast = funccall.parse("test(test3(), test4(b), test5(b, c), a)")
- #print str(List(ast))
- print "Function Call Test: ", str(List(ast))=="""List
- `- Function
- +- 'test'
- `- Args
- +- Function
- | `- 'test3'
- +- Function
- | +- 'test4'
- | `- Args
- | `- 'b'
- +- Function
- | +- 'test5'
- | `- Args
- | +- 'b'
- | `- 'c'
- `- 'a'"""
- #test suite for statement
- ast = stmt.parse("a=10;")
- ast3 = stmt.parse("^test: a,b{a=20;b=10}")
- ast2 = stmt.parse("a=func(a, 10, 'hello')+5;")
- #print(List(ast2))
- print "Statement Test: ", str(List(ast))=="""List
- `- Assign
- +- 'a'
- `- Expr
- `- 10.0""",
- print str(List(ast2))=="""List
- `- Assign
- +- 'a'
- `- Expr
- `- Add
- +- Function
- | +- 'func'
- | `- Args
- | +- 'a'
- | +- 10.0
- | `- "'hello'"
- `- 5.0""",
- print str(List(ast3))=="""List
- `- FuncDef
- +- FuncDefHead
- | `- 'test'
- +- FuncDefParams
- | `- Args
- | +- 'a'
- | `- 'b'
- `- Block
- +- Assign
- | +- 'a'
- | `- Expr
- | `- 20.0
- `- Assign
- +- 'b'
- `- Expr
- `- 10.0"""
- #test suite for multi_statement
- ast = multi_stmt.parse("a=10;b=20+c;f=test(a,b);[f<100;f++]{a=func(f)}")
- #print List(ast)
- print "Multiple Statement Test: ", str(List(ast))=="""List
- +- Assign
- | +- 'a'
- | `- Expr
- | `- 10.0
- +- Assign
- | +- 'b'
- | `- Expr
- | `- Add
- | +- 20.0
- | `- 'c'
- +- Assign
- | +- 'f'
- | `- Expr
- | `- Function
- | +- 'test'
- | `- Args
- | +- 'a'
- | `- 'b'
- `- LoopBlock
- +- LoopHead
- | +- LessThan
- | | +- Expr
- | | | `- 'f'
- | | `- Expr
- | | `- 100.0
- | `- UnaryPlus
- | `- 'f'
- `- Block
- `- Assign
- +- 'a'
- `- Expr
- `- Function
- +- 'func'
- `- Args
- `- 'f'"""
- #for i in ast:
- # print List(i)
- #test suite for block
- ast = block.parse("{b=test3(c, b);a=0;test4()}")
- ast2 = block.parse("{a++}")
- #print str(List(ast2))
- print "Block Test: ", str(List(ast))=="""List
- `- Block
- +- Assign
- | +- 'b'
- | `- Expr
- | `- Function
- | +- 'test3'
- | `- Args
- | +- 'c'
- | `- 'b'
- +- Assign
- | +- 'a'
- | `- Expr
- | `- 0.0
- `- Function
- `- 'test4'""",
- print str(List(ast2))=="""List
- `- Block
- `- UnaryPlus
- `- 'a'"""
- ast = operation.parse('a++')
- #print List(ast)
- #for i in list(ast):
- # print List(i)
- print "Unary Operation Test: ", str(List(ast))=="""List
- `- UnaryPlus
- `- 'a'"""
- ast = loopblock.parse("[a<10;a++]{out(a)}")
- #print List(ast)
- print "Loop Test: ", str(List(ast))=="""List
- `- LoopBlock
- +- LoopHead
- | +- LessThan
- | | +- Expr
- | | | `- 'a'
- | | `- Expr
- | | `- 10.0
- | `- UnaryPlus
- | `- 'a'
- `- Block
- `- Function
- +- 'out'
- `- Args
- `- 'a'"""
- ast = ifstruct.parse("~(a<10){out(a)}#(a>10){out(b)}#{out(c)}")
- #print(List(ast))
- print "If Block Test: ", str(List(ast))=="""List
- +- IfBlock
- | +- LessThan
- | | +- Expr
- | | | `- 'a'
- | | `- Expr
- | | `- 10.0
- | `- Block
- | `- Function
- | +- 'out'
- | `- Args
- | `- 'a'
- +- ElifBlock
- | +- GreaterThan
- | | +- Expr
- | | | `- 'a'
- | | `- Expr
- | | `- 10.0
- | `- Block
- | `- Function
- | +- 'out'
- | `- Args
- | `- 'b'
- `- ElseBlock
- `- Block
- `- Function
- +- 'out'
- `- Args
- `- 'c'"""
Advertisement
Add Comment
Please, Sign In to add comment