© Copyright 2005 Peri Hankey - documentation license Gnu FDL - code license Gnu GPL - validate HTML
SourceForge.net Logo reverse Polish calculator

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]$
home