Source

schyme / schyme / parser.py

Full commit
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 <filename>" % argv[0]
        return 1
    
    run(argv[1])
    return 0

def target(*args):
    return entry_point, None
    
if __name__ == "__main__":
    entry_point(sys.argv)