# schyme / schyme / parser.py

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85``` ```from pyparsing import Word,Literal,nums, Group,Optional,OneOrMore import sys import os import s_math ####### Built in functions def bi_add(*args): return sum(args) def bi_subtract(*args): return args[0] - sum(args[1:]) def bi_multiply(*args): ret = 1 for arg in args : ret = ret * arg return ret def bi_divide(*args): ret = args[0] for arg in args[1:] : ret = ret / arg return ret funcs = {"+": bi_add, "-": bi_subtract, "*": bi_multiply, "/": bi_divide} ##### parser helpers def parse_number_list(s,l,t): return (list(float(n) if "." in n else int(n) for n in t)) class TwoOrMore(OneOrMore): """Repetition of one or more of the given expression.""" def parseImpl( self, instring, loc, doActions=True ): loc, tokens = super(TwoOrMore,self).parseImpl(instring,loc,doActions) if len(tokens) < 2 : raise ParseException("At least two tokens required") return loc, tokens ###### Grammar number = Word(nums + "." + nums) | Word("." + nums) | Word(nums) operator = Word("+-*/", max=1) opexp = Literal("(").suppress() + operator + Group(TwoOrMore(number).setParseAction(parse_number_list)) + Literal(")").suppress() op_list = OneOrMore(Group(opexp)) def evaluate(exp): func = funcs[exp[0]] return func(*exp[1]) def parse(program): exps = op_list.parseString(program) return exps def run(filename): fp = os.open(filename, os.O_RDONLY, 0777) program_contents = "" while True: read = os.read(fp,4096) if len(read) == 0: break program_contents += read exps = parse(program_contents) for exp in exps: ret = evaluate(exp) print ret os.close(fp) def entry_point(argv): if len(argv) != 2 : print "usage: %s " % argv[0] return 1 run(argv[1]) return 0 def target(*args): return entry_point, None if __name__ == "__main__": entry_point(sys.argv) ```