Reverse polish is the notation in which a+b is written a b +. For many purposes reverse Polish is the simplest possible representation of any kind of computation - there is no ambiguity about it at all, as operators appear in the order in which they are applied. In an algorithmic implementation, each operator takes its operands from a stack and replaces them with the result it produces.
Precisely because it is so well adapted to an algorithmic approach, reverse Polish is less well adapted to a purely linguistic approach - the push-down stack is an essentially algorthmic beast.
The language machine does in fact use a push-down stack behind the scenes for operands in purely interpreted implementations, and generally for use by the % operation which is used to capture input symbols in low-level lexical rules. But it was a design decision not to make the operand stack generally visible except as part of the external code api.
So here are rules for a reverse Polish calculator which exploits the ability to 'see' variables in enclosing contexts to enable operators to find their operands - a pure solution, if slightly devious:
.calc() - error output <- eof - ; - result output <- eof - ; - rp x :N '=' <- result 'result: ' N '\n' eom ;
- <- rp ; - x :A f1 :B <- rp - x :B ; - rp x :B f2 :C <- f1 :C ;
'N' <- f1 :(-A); '+' <- f2 :(A + B); '-' <- f2 :(A - B); '*' <- f2 :(A * B); '/' <- f2 :(A / B); '%' <- f2 :(A % B);
'~' <- f2 :(~A); '^' <- f2 :(A ^ B); '&' <- f2 :(A & B); '|' <- f2 :(A | B);
.calc(20L)
[ \t\n] <- - ;
[0-9] % { repeat .[0-9] % } { option '.' % repeat [0-9] % } toNum :N <- x :N;
'0x' .[0-9a-zA-Z] % { repeat .[0-9a-zA-Z] % } { option '.' % repeat [0-9] % } toHex :N <- x :N;
'0b' .[01] % { repeat .[01] % } toBix :N <- x :N;
.calc(30R) - anything <- line - ; eof <- line eof; '\n' <- line;
- line <- error '--- not understood - skipping one line\n' eom; - eom <- output ; - out <- eom - ;
Compile the calculator rules to internal format and wrap them to create shell script (a shebang script) called rpCalc.lm:
[peri@a4 examples]$ make rpCalc.lm
lmn2m -o rpCalc.lm -s $(which lm) rpCalc.lmn chmod +x rpCalc.lm
Try the calculator program:
[peri@p2 examples]$ ./rpCalc.lm 1 27 / 2 + = result: 2.03704 1 27 2 * 39 3 / + / = result: 0.0149254
And finally, here is the lm-diagram output from a single expression:
./rpCalc.lm -W 40 -t D
0 5 N + 2 * =
eof '1'
? eof '1'
.------------000090
| result '1'
|? result '1'
|.-----------000091
|| rp '1'
||? rp '1'
||.----------000092
||| x '1'
|||? x '1'
|||.---------000093
|||| % '0'
|||| repeat '0'
|||| [0-9] '0'
|||| % ' '
||||*
|||| [0-9] ' '
||||? [0-9] ' '
||||- [0-9] ' '
|||| option ' '
|||| '.' ' '
||||? '.' ' '
||||- '.' ' '
|||| toNum ' '
|||| : ' '
|||'---------000093---------- ----------000093-------------.
||| x x |
||| : : |
||| 000093-------------'
||| f1 ' '
|||? f1 ' '
||| f1 '5'
|||? f1 '5'
|||.---------000097
|||| rp '5'
||||? rp '5'
||||.--------000098
||||| x '5'
|||||? x '5'
|||||.-------000099
|||||| % ' '
|||||| repeat ' '
|||||| [0-9] ' '
||||||? [0-9] ' '
||||||- [0-9] ' '
|||||| option ' '
|||||| '.' ' '
||||||? '.' ' '
||||||- '.' ' '
|||||| toNum ' '
|||||| : ' '
|||||'-------000099---------- ----------000099-------------.
||||| x x |
||||| : : |
||||| 000099-------------'
||||| f1 ' '
|||||? f1 ' '
||||| f1 'N'
|||||? f1 'N'
||||| 000103-------------.
||||| f1 f1 |
||||| : : |
||||'--------000098---------- ----------000098------------.|
|||| rp x ||
||||? rp x ??
||||.--------000104 ||
||||| x x ||
||||| : : ||
||||| 000098------------'|
||||| 000103-------------'
||||| f1 ' '
|||||? f1 ' '
||||| f1 '+'
|||||? f1 '+'
|||||.-------000106
|||||| rp '+'
||||||? rp '+'
||||||.------000107
||||||| x '+'
|||||||? x '+'
|||||||- x '+'
|||||| 000107-------------.
|||||| rp rp |
|||||| 000107-------------'
|||||| x '+'
||||||? x '+'
||||||- x '+'
|||||- f1 '+'
|||| 000104-----------.||
|||| rp rp |||
|||| 000104-----------'||
|||| x x ||
|||| : : ||
|||| 000098------------'|
|||| 000103-------------'
|||| f2 ' '
||||? f2 ' '
|||| f2 '+'
||||? f2 '+'
|||| 000109-------------.
|||| f2 f2 |
|||| : : |
|||'---------000097---------- ----------000097------------.|
||| f1 f1 ||
||| : : ||
||'----------000092---------- ----------000092-----------.||
|| rp x |||
||? rp x ???
||.----------000110 |||
||| x x |||
||| : : |||
||| 000092-----------'||
||| 000097------------'|
||| 000109-------------'
||| f1 ' '
|||? f1 ' '
||| f1 '2'
|||? f1 '2'
|||.---------000112
|||| rp '2'
||||? rp '2'
||||.--------000113
||||| x '2'
|||||? x '2'
|||||.-------000114
|||||| % ' '
|||||| repeat ' '
|||||| [0-9] ' '
||||||? [0-9] ' '
||||||- [0-9] ' '
|||||| option ' '
|||||| '.' ' '
||||||? '.' ' '
||||||- '.' ' '
|||||| toNum ' '
|||||| : ' '
|||||'-------000114---------- ----------000114-------------.
||||| x x |
||||| : : |
||||| 000114-------------'
||||| f1 ' '
|||||? f1 ' '
||||| f1 '*'
|||||? f1 '*'
|||||.-------000118
|||||| rp '*'
||||||? rp '*'
||||||.------000119
||||||| x '*'
|||||||? x '*'
|||||||- x '*'
|||||| 000119-------------.
|||||| rp rp |
|||||| 000119-------------'
|||||| x '*'
||||||? x '*'
||||||- x '*'
|||||- f1 '*'
|||| 000113-------------.
|||| rp rp |
|||| 000113-------------'
|||| x '2'
||||? x '2'
||||.--------000120
||||| % ' '
||||| repeat ' '
||||| [0-9] ' '
|||||? [0-9] ' '
|||||- [0-9] ' '
||||| option ' '
||||| '.' ' '
|||||? '.' ' '
|||||- '.' ' '
||||| toNum ' '
||||| : ' '
||||'--------000120---------- ----------000120-------------.
|||| x x |
|||| : : |
|||| 000120-------------'
|||| f2 ' '
||||? f2 ' '
|||| f2 '*'
||||? f2 '*'
|||| 000124-------------.
|||| f2 f2 |
|||| : : |
|||'---------000112---------- ----------000112------------.|
||| f1 f1 ||
||| : : ||
||'----------000110---------- ----------000110-----------.||
|| rp x |||
||? rp x ???
||.----------000125 |||
||| x x |||
||| : : |||
||| 000110-----------'||
||| 000112------------'|
||| 000124-------------'
||| f1 ' '
|||? f1 ' '
||| f1 '='
|||? f1 '='
|||.---------000127
|||| rp '='
||||? rp '='
||||.--------000128
||||| x '='
|||||? x '='
|||||- x '='
|||| 000128-------------.
|||| rp rp |
|||| 000128-------------'
|||| x '='
||||? x '='
||||- x '='
|||- f1 '='
|| 000125----------.|||
|| rp rp ||||
|| 000125----------'|||
|| x x |||
|| : : |||
|| 000110-----------'||
|| 000112------------'|
|| 000124-------------'
|| '=' ' '
||? '=' ' '
|| '=' '='
|'-----------000091---------- ----------000091-------------.
| result result |
| output 'r' |
|? output 'r' ?
|.-----------000130 |
|| eom 'r' |
||? eom 'r' ?
||.----------000131 |
||| out 'r' |
r ||'----------000131 |
|| eom 'e' |
||? eom 'e' ?
||.----------000132 |
||| out 'e' |
e ||'----------000132 |
|| eom 's' |
||? eom 's' ?
||.----------000133 |
||| out 's' |
s ||'----------000133 |
|| eom 'u' |
||? eom 'u' ?
||.----------000134 |
||| out 'u' |
u ||'----------000134 |
|| eom 'l' |
||? eom 'l' ?
||.----------000135 |
||| out 'l' |
l ||'----------000135 |
|| eom 't' |
||? eom 't' ?
||.----------000136 |
||| out 't' |
t ||'----------000136 |
|| eom ':' |
||? eom ':' ?
||.----------000137 |
||| out ':' |
: ||'----------000137 |
|| eom ' ' |
||? eom ' ' ?
||.----------000138 |
||| out ' ' |
||'----------000138 |
|| eom 10 |
||? eom 10 ?
||.----------000139 |
||| out 10 |
10 ||'----------000139 |
|| eom '\n' |
||? eom '\n' ?
||.----------000140 |
||| out '\n' |
||'----------000140 |
|| eom eom |
|'-----------000130---------- ----------000130------------.|
| output output ||
'------------000090 ||
000130------------'|
000091-------------'
eof '\n'
? eof '\n'
eof eof
[peri@p2 examples]$






