#!/usr/bin/env python # Infix/prefix/postfix expression conversion import tpg class Op: """ Binary operator """ def __init__(self, op, a, b, prec): self.op = op # operator ("+", "-", "*", "/", "^") self.prec = prec # precedence of the operator self.a, self.b = a, b # operands def infix(self): a = self.a.infix() if self.a.prec < self.prec: a = "(%s)"%a b = self.b.infix() if self.b.prec <= self.prec: b = "(%s)"%b return "%s %s %s"%(a, self.op, b) def prefix(self): a = self.a.prefix() b = self.b.prefix() return "%s %s %s"%(self.op, a, b) def postfix(self): a = self.a.postfix() b = self.b.postfix() return "%s %s %s"%(a, b, self.op) class Atom: """ Atomic expression """ def __init__(self, s): self.a = s self.prec = 99 def infix(self): return self.a def prefix(self): return self.a def postfix(self): return self.a class Func: """ Function expression """ def __init__(self, name, *args): self.name = name self.args = args self.prec = 99 def infix(self): args = [a.infix() for a in self.args] return "%s(%s)"%(self.name, ",".join(args)) def prefix(self): args = [a.prefix() for a in self.args] return "%s %s"%(self.name, " ".join(args)) def postfix(self): args = [a.postfix() for a in self.args] return "%s %s"%(" ".join(args), self.name) # Grammar for arithmetic expressions class ExpressionParser(tpg.Parser): r""" separator space '\s+'; token func1 '\b(sin|cos|tan)\b' ; token func2 '\b(min|max)\b' ; token ident '\w+'; START/ -> EXPR/e '\n' $ t = 'infix' | EXPR_PRE/e '\n' $ t = 'prefix' | EXPR_POST/e '\n' $ t = 'postfix' ; # Infix expressions EXPR/e -> TERM/e ( '[+-]'/op TERM/t $ e=Op(op,e,t,1) )* ; TERM/t -> FACT/t ( '[*/]'/op FACT/f $ t=Op(op,t,f,2) )* ; FACT/f -> ATOM/f ( '\^'/op FACT/e $ f=Op(op,f,e,3) )? ; ATOM/a -> ident/s $ a=Atom(s) | '\(' EXPR/a '\)' | func1/f '\(' EXPR/x '\)' $ a=Func(f,x) | func2/f '\(' EXPR/x ',' EXPR/y '\)' $ a=Func(f,x,y) ; # Prefix expressions EXPR_PRE/e -> ident/s $ e=Atom(s) | '\(' EXPR_PRE/e '\)' | OP/ EXPR_PRE/a EXPR_PRE/b $ e=Op(op,a,b,prec) | func1/f EXPR/x $ e=Func(f,x) | func1/f EXPR/x EXPR/y $ e=Func(f,x,y) ; # Postfix expressions EXPR_POST/e -> ATOM_POST/a SEXPR_POST/e ; ATOM_POST/a -> ident/s $ a=Atom(s) | '\(' EXPR_POST/a '\)' ; SEXPR_POST/e -> EXPR_POST/e2 ( OP/ SEXPR_POST<$Op(op,e,e2,prec)$>/e | func2/f SEXPR_POST<$Func(f, e, e2)$>/e ) | func1/f SEXPR_POST<$Func(f, e)$>/e | ; OP/ -> '[+-]'/op $ prec=1 | '[*/]'/op $ prec=2 | '\^'/op $ prec=3 ; """ parser = ExpressionParser() while 1: e = raw_input(":") if e == "": break try: expr, t = parser(e+"\n") except tpg.Error, e: print e else: print e, "is a", t, "expression" print "\tinfix :", expr.infix() print "\tprefix :", expr.prefix() print "\tpostfix :", expr.postfix()