| // Reverse Polish Notation, rpn.k |
| // © 2001, Michael Piefel <piefel@informatik.hu-berlin.de> |
| |
| // Define which views (ie., different paths) we intent to take |
| // during unparse and rewrite |
| %uview infix postfix; |
| %rview canon calculate; |
| |
| |
| // Simple expressions |
| Plus( exp1, exp2 ) |
| -> [ infix: exp1 "+" exp2 ] |
| [ postfix: exp1 " " exp2 " +" ]; |
| |
| Minus( exp1, exp2 ) |
| -> [ infix: exp1 "-" exp2 ] |
| [ postfix: exp1 " " exp2 " -" ]; |
| |
| // Beware of parentheses in infix representation |
| Mul( exp1, exp2=Plus(*,*) ), |
| Mul( exp1, exp2=Minus(*,*) ) |
| -> [ infix: exp1 "*(" exp2 ")" ]; |
| |
| Mul( exp1=Plus(*,*), exp2 ), |
| Mul( exp1=Minus(*,*), exp2 ) |
| -> [ infix: "(" exp1 ")*" exp2 ]; |
| |
| Mul( exp1=Plus(*,*), exp2=Plus(*,*) ), |
| Mul( exp1=Plus(*,*), exp2=Minus(*,*) ), |
| Mul( exp1=Minus(*,*), exp2=Plus(*,*) ), |
| Mul( exp1=Minus(*,*), exp2=Minus(*,*) ) |
| -> [ infix: "(" exp1 ")*(" exp2 ")" ]; |
| |
| Mul( exp1, exp2 ) |
| -> [ infix: exp1 "*" exp2 ] |
| [ postfix: exp1 " " exp2 " *"]; |
| |
| Div( exp1=Plus(*,*), exp2 ), |
| Div( exp1=Minus(*,*), exp2 ) |
| -> [ infix: "(" exp1 ")/" exp2 ]; |
| |
| Div( exp1, exp2=Plus(*,*) ), |
| Div( exp1, exp2=Minus(*,*) ), |
| Div( exp1, exp2=Mul(*,*) ), |
| Div( exp1, exp2=Div(*,*) ) |
| -> [ infix: exp1 "/(" exp2 ")"]; |
| |
| Div( exp1=Plus(*,*), exp2=Plus(*,*) ), |
| Div( exp1=Plus(*,*), exp2=Minus(*,*) ), |
| Div( exp1=Minus(*,*), exp2=Plus(*,*) ), |
| Div( exp1=Minus(*,*), exp2=Minus(*,*) ) |
| -> [ infix: "(" exp1 ")/(" exp2 ")" ]; |
| |
| Div( exp1, exp2 ) |
| -> [ infix: exp1 "/" exp2 ] |
| [ postfix: exp1 " " exp2 " /" ]; |
| |
| |
| // Calculate all that can be calculated (ie. all where |
| // we have concrete numbers) |
| Plus( Term(Number(a)), Term(Number(b)) ) |
| -> < calculate: Term(Number(plus(a,b)))>; |
| |
| Plus( Term(Number(a)), Plus(Term(Number(b)), rest) ) |
| -> < calculate: Plus(Term(Number(plus(a,b))), rest)>; |
| |
| Plus( Term(Number(a)), Minus(Term(Number(b)), rest) ) |
| -> < calculate: Minus(Term(Number(plus(a,b))), rest)>; |
| |
| Minus( Term(Number(a)), Term(Number(b)) ) |
| -> < calculate: Term(Number(minus(a,b)))>; |
| |
| Minus( Term(Number(a)), Minus(Term(Number(b)), rest) ) |
| -> < calculate: Plus(Term(Number(minus(a,b))), rest)>; |
| |
| Minus( Term(Number(a)), Plus(Term(Number(b)), rest) ) |
| -> < calculate: Minus(Term(Number(minus(a,b))), rest)>; |
| |
| Mul( Term(Number(a)), Term(Number(b)) ) |
| -> < calculate: Term(Number(mul(a,b)))>; |
| |
| Mul( Term(Number(a)), Mul(Term(Number(b)), rest) ) |
| -> < calculate: Mul(Term(Number(mul(a,b))), rest)>; |
| |
| Mul( Term(Number(a)), Div(Term(Number(b)), rest) ) |
| -> < calculate: Div(Term(Number(mul(a,b))), rest)>; |
| |
| Div( Term(Number(a)), Term(Number(b)) ) |
| -> < calculate: Term(Number(divi(a,b)))>; |
| |
| Div( Term(Number(a)), Div(Term(Number(b)), rest) ) |
| -> < calculate: Mul(Term(Number(divi(a,b))), rest)>; |
| |
| Div( Term(Number(a)), Mul(Term(Number(b)), rest) ) |
| -> < calculate: Div(Term(Number(divi(a,b))), rest)>; |
| |
| // Helper functions to actually compute |
| %{ KC_REWRITE |
| inline integer plus(integer a, integer b) { return mkinteger(a->value+b->value); } |
| inline integer minus(integer a, integer b) { return mkinteger(a->value-b->value); } |
| inline integer mul(integer a, integer b) { return mkinteger(a->value*b->value); } |
| inline integer divi(integer a, integer b) { return mkinteger(b->value==0 ? 0 : a->value / b->value); } |
| %} |
| |
| |
| // Rewrite to a canonical form of the expression where operators |
| // are to be put as far to the end as possible |
| Plus( Plus(a, b), c) |
| -> < canon: Plus(a, Plus(b, c))>; |
| |
| Plus( Minus(a, b), c) |
| -> < canon: Plus(c, Minus(a, b))>; |
| |
| Minus( Plus(a, b), c) |
| -> < canon: Plus(a, Minus(b, c))>; |
| |
| Mul( Mul(a, b), c) |
| -> < canon: Mul(a, Mul(b, c))>; |
| |
| Plus( a=Term(Ident(*)), b=Term(Number(*)) ) |
| -> < canon: Plus(b, a)>; |
| |
| Mul( a=Term(Ident(*)), b=Term(Number(*)) ) |
| -> < canon: Mul(b, a)>; |
| |
| Plus( a=Term(Ident(*)), Plus(b=Term(Number(*)), rest) ) |
| -> < canon: Plus(b, Plus(a,rest))>; |
| |
| Mul( a=Term(Ident(*)), Mul(b=Term(Number(*)), rest) ) |
| -> < canon: Mul(b, Mul(a,rest))>; |
| |