All pastes #472714 Raw Edit

Something

public text v1 · immutable
·published 2007-05-05 19:36 UTC
rendered paste body
#! /usr/bin/python

next_token_buffer = []

def token(fd):
    global next_token_buffer
    if next_token_buffer:
        x = next_token_buffer.pop(0)
        return x
    c = fd.read(1)
    while c.isspace():
        c = fd.read(1)
    if c in "+-*/^(),;{}":
        return c
    elif c.isdigit():
        buf = []
        while c.isdigit():
            buf.append(c)
            c = fd.read(1)
        if not c.isspace():
            next_token_buffer.append(c)
        return int("".join(buf))
    elif c.isalpha():
        if c == "D":
            return c
        buf = []
        while c.isalpha():
            buf.append(c)
            c = fd.read(1)
        if not c.isspace():
            next_token_buffer.append(c)
        return ["function", "".join(buf)]
    else:
        return None



def value(t):
    if isinstance(t, int):
        return float(t)
    else:
        if t[0] == "+":
            return value(t[1]) + value(t[2])
        elif t[0] == "-":
            return value(t[1]) - value(t[2])
        elif t[0] == "*":
            return value(t[1]) * value(t[2])
        elif t[0] == "/":
            return value(t[1]) / value(t[2])
        elif t[0] == "^":
            return value(t[1]) ** value(t[2])
        else:
            raise "Operation not known"

prec = {"+":1, "-":1, "*":2, "/":2, "^":3}
left_assoc = "+-*/"
right_assoc = "^"

def parse(fd):
    out = []
    x = parse2(fd)
    while x != None:
        if x:
            out.append( x + " [p]Sf z0<f Lf Zd>f" )
        x = parse2(fd)
    return " ".join(out)


def parse2(fd, in_block=False):
    opers = []
    out = []

    quit_eof = True
    t = token(fd)
    while t:
        if isinstance(t, int):
            out.append(t)
        elif t[0] == "function":
            next = token(fd)
            if next == "(":
                opers.append(t)
            else:
                out.append("l%s" % t[1])
            next_token_buffer.append(next)
        elif t == "D":
            out.append(parse_function(fd))
        elif t == ";":
            if not in_block:
                quit_eof = False
                break
        elif t == "{":
            out.append(parse2(fd, True))
        elif t == "}":
            if not in_block:
                raise "Syntax error", "not in {"
            quit_eof = False
            break
        elif t in "+-*/^":
            while opers and opers[-1] != "("  and ((t in left_assoc and prec[t] <= prec[opers[-1]]) or (t in right_assoc and prec[t] < prec[opers[-1]])):
                out.append(opers.pop())
            opers.append(t)
        elif t == ",":
            while opers[-1] != "(":
                if not opers:
                    raise "Syntax error: mismatched parens"
                out.append(opers.pop())
        elif t == "(":
            opers.append(t)
        elif t == ")":
            op = opers.pop()
            while op != "(":
                out.append(op)
                if not opers:
                    raise "Syntax error: mismatched parens"
                op = opers.pop()
            try:
                if opers[-1][0] == "function":
                    if opers[-1][1] == "print":
                        out.append("p Zd>r")
                        opers.pop()
                    else:
                        out.append("l%sx" % opers.pop()[1])
            except:
                pass
                
        t = token(fd)

    while opers:
        if opers[-1] == "(":
            raise "Syntax error: mismatched parens"
        try:
            if opers[-1][0] == "function":
                if opers[-1][1] == "print":
                    out.append("p Zd>r")
                    opers.pop()
                else:
                    out.append("l%sx" % opers.pop()[1])
            else:
                raise "get me out"
        except:
            out.append(opers.pop())
    if quit_eof and not out:
        return None
    
    return " ".join(str(i) for i in out)
                
def parse_function(fd):
    name = token(fd)[1]
    if token(fd) != "(":
        raise "Syntax error: no"

    args = []
    t = token(fd)
    while t != ")":
        args.append(t[1])
        t = token(fd)
        if t == ")":
            break
        if t != ",":
            raise "Syntax error: no"
        t = token(fd)

    body = parse2(fd)
    out = ["["]
    args.reverse()
    for arg in args:
        out.append("S%s" % arg)
    out.append(body)
    for arg in args:
        out.append("L%s Zd>r" % arg)
    out.append("] s%s" % name)
    return "".join(out)


if __name__ == "__main__":
    from cStringIO import StringIO
    import sys
    x = StringIO("".join(sys.argv[1:]))
    y = parse(x)
    print y