#! /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