RPN(3)                User Contributed Perl Documentation               RPN(3)



PPaarrssee--RRPPNN ((VV 22..xxxx)) -- IInnttrroodduuccttiioonn
         Parse::RPN - Is a minimalist RPN parser/processor (a little like FORTH)

SSYYNNOOPPSSIISS
         use Parse::RPN;
         $result=rpn(string ...);
         @results=rpn(string ...);

         $error=rpn_error();

         string... is a list of RPN operator and value separated by a coma
         in scalar mode RPN return the result of the calculation (If the stack contain more then one element,
         you receive a warning and the top value on the stack)
         in array mode, you receive the content of the stack after evaluation

DDEESSCCRRIIPPTTIIOONN
         rpn() receive in entry a scalar of one or more elements coma separated
         and evaluate as an RPN (Reverse Polish Notation) command.
         The function split all elements and put in the stack.
         The operator are case sensitive.
         The operator are detect as is, if they are alone in the element of the stack.
         Extra space before or after are allowed
         (e.g "3,4,ADD" here ADD is an opeartor but it is not the case in "3,4,ADD 1")
         If element is not part of the predefined operator (dictionary), the element is push as a litteral.
         If you would like to put a string which is part of the dictionary, put it between quote or double-quote
         (e.g "3,4,'ADD'" here ADD is a literal and the evaluation reurn ADD and a warning because the stack is not empty)
         If the string contain a coma, you need also to quote or double-quote the string.
         (be care to close your quoted or double-quoted string)

         The evaluation follow the rule of RPN or FORTH or POSTCRIPT or pockect calcutor HP.
         Look on web for documentation about the use of RPN notation.

         I use this module in a application where the final user need to create an maintain
         a configuration file with the possibility to do calculation on variable returned from application.

         The idea of this module is comming from Math::RPN of Owen DeLong, owen@delong.com that I used for more then a year
         before some of my customer would like more ...
         I correct a bug (interversion of > and >=), add the STRING function, pattern search and some STACK functions.

         rpn_error() return the last error from the evaluation (illegal division by 0, error from the PERL function execution...)
         each time that rpn() is call the rpn_error() is reinitianised.

MMAATTHHEEMMAATTIICC ooppeerraattoorrss
       .

       aa bb ++

             return the result of 'a' + 'b'

       aa bb --

             return the result of 'a' - 'b'

       aa bb **

             return the result of 'a' * 'b'

       aa bb //

             return the result of 'a' / 'b'
             if b =0 return '' (to prevent exception raise)

       aa bb ****

             return the result of 'a' ** 'b'  (exponant)

       aa 11++

             return the result of 'a' +1

       aa 11--

             return the result of 'a' -1

       aa 22--

             return the result of 'a' -2

       aa 22++

             return the result of 'a' +2

       aa bb MMOODD

             return the result of 'a' % 'b'

       aa AABBSS

             return the result of  abs 'a'

       aa IINNTT

             return the result of INT 'a'

       aa ++--

             return the result negate value of 'a' (- 'a' )

       aa RREEMMAAIINN

             return the result of 'a' - int 'a' (fractional part of 'a' )

       aa SSIINN

             return the result of sin 'a'  ('a' in RADIAN)

       aa CCOOSS

             return the result of cos 'a'  ('a' in RADIAN)

       aa TTAANN

             return the result of tan 'a'  ('a' in RADIAN)

       aa CCTTAANN

             return the result of cotan 'a'  ('a' in RADIAN)

       aa LLNN

             return the result of ln 'a'
             if = 0 return '' (to prevent exception raise)

       aa EEXXPP

             return the result of 'e' ** 'a'

       PPII

             return the value of PI (3.14159265358979)

rreellaattiioonnaall ooppeerraattoorrss
       .

       aa bb <<

             return the result of 'a' < 'b'  ( BOOLEAN value )

       aa bb <<==

             return the result of 'a' <= 'b'  ( BOOLEAN value )

       aa bb >>

             return the result of 'a' > 'b'  ( BOOLEAN value )

       aa bb >>==

             return the result of 'a' >= 'b'  ( BOOLEAN value )

       aa bb ====

             return the result of 'a' == 'b'  ( BOOLEAN value ) 1 if a == b else 0

       aa bb <<==>>

             return the result of 'a' <=> 'b'  ( BOOLEAN value  ) -1 if a < b ,0 if a == b, 1 if a > b

       aa bb !!==

             return the result of 'a' != 'b'  ( BOOLEAN value ) 0 if a == b else 1

       aa bb OORR==

             return the result of 'a' || 'b'  ( BOOLEAN value ) 0 if a == b else 1

LLOOGGIICCAALL ooppeerraattoorrss
       aa bb OORR

             return the 1 one of the 2 argument are not equal to 0

       aa bb AANNDD

             return the 0 one of the 2 argument are equal to 0

       aa bb XXOORR

             return the 0 if the  2 argument are equal

       aa NNOOTT

             return the 0 if the argument is not eqauk to 0
             return the 1 if the argument is  eqauk to 0

       aa TTRRUUEE

             return the 1 if the top of stack is !=0 and if stack not empty

       aa FFAALLSSEE

             return the 0 if the top of stack is !=0

MMIISSCC ooppeerraattoorrss
       aa bb >>>>

             bitwise shift to the right
             shift the bits in a to the left of b level

       aa bb <<<<

             bitwise shift to the left
             shift the bits in a to the left of b level

       aa bb MMIINN

             return the result smallest of the 2 arguments

       aa bb MMAAXX

             return the result greatest of the 2 arguments

       TTIICCKK

             return the current time in ticks

       aa LLTTIIMMEE

             return the localtime coresponding to the ticks value 'a'
             the format is 'sec' 'min' 'hour' 'day_in_the_month' 'month' 'year' 'day_in_week' 'day_year' 'dayloight_saving'
             'year' is the elapsed year since 1900
             'month' start to 0
             The format is the same as localtime() in perl

       aa GGTTIIMMEE

             return the gmtime coresponding to the ticks value 'a'
             the format is 'sec' 'min' 'hour' 'day_in_the_month' 'month' 'year' 'day_in_week' 'day_year' 'dayloight_saving'
             'year' is the elapsed year since 1900
             'month' start to 0
             The format is the same as gmtime() in perl

       aa HHLLTTIIMMEE

             return the localtime coresponding to the ticks value 'a' in a human readable format

       aa HHGGTTIIMMEE

             return the gmtime coresponding to the ticks value 'a' in a human readable format

       RRAANNDD

             return a random value in the range [0,1[

       aa LLRRAANNDD

             return a random value in the range [0,'a'[

       aa SSPPAACCEE

             return the number 'a' formated with space each 3 digits

       aa DDOOTT

             return the number 'a' formated with . (dot) each 3 digits

       aa NNOORRMM

             return the number 'a' normalize by slice of 1000 with extra power value "K", "M", "G", "T", "P" (or nothing if lower than 1000)

       aa NNOORRMM22

             return the number 'a' normalize by slice of 1024 with extra power value "K", "M", "G", "T", "P" (or nothing if lower than 1024)

       aa OOCCTT

             return the decimal value for the HEX, BINARY or OCTAL value 'a'
             OCTAL is like  '0nn' where n is in the range of 0-7
             BINARY is like '0bnnn...'   where n is in the range of 0-1
             HEX is like '0xnnn' where n is in the range of 0-9A-F
             if no specific format convert as an hexadecimal by default

SSTTRRIINNGG ooppeerraattoorrss
       .

       aa bb EEQQ

             return the result of 'a' EQ 'b'  ( BOOLEAN value )

       aa bb NNEE

             return the result of 'a' NE 'b'  ( BOOLEAN value )

       aa bb LLTT

             return the result of 'a' LT 'b'  ( BOOLEAN value )

       aa bb GGTT

             return the result of 'a' GT 'b'  ( BOOLEAN value )

       aa bb LLEE

             return the result of 'a' LE 'b'  ( BOOLEAN value )

       aa bb GGEE

             return the result of 'a' GE 'b'  ( BOOLEAN value )

       aa bb CCMMPP

             return the result of 'a' CMP 'b'  ( BOOLEAN value )

       aa LLEENN

             return the length of 'a' EQ 'b'

       aa bb CCAATT

             return the concatenation 'a' and 'b'

       aa bb RREEPP

             return the result of 'a' x 'b'  duplicate 'a' by the number of 'x'

       aa RREEVV

             return the reverse of 'a' EQ 'b'

       aa bb cc SSUUBBSSTTRR

             return the substring of 'c' starting at 'b' with the length of 'a'

       aa UUCC

             return 'a' in uppercase

       aa LLCC

             return 'a' in lowercase

       aa UUCCFFIIRRSSTT

             return 'a' with the first letter in uppercase

       aa LLCCFFIIRRSSTT

             return 'a' with the first letter in lowercase

       aa bb SSPPLLIITT

             return all splitted item of 'a' by the separator 'b'
             'b' is a REGEX
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry
             !!! if the split match on the beginning of string,
             SPLIT return the matched value WITHOUT the empty string of the beginning

       aa bb SSPPLLIITTII

             return all splitted item of 'a' by the separator 'b'
             'b' is a REGEX case insensitive
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry
             !!! if the split match on the beginning of string,
             SPLIT return the matched value WITHOUT the empty string of the beginning

       aa bb PPAATT

             return one or more occurance of 'b' in 'a'
             'b' is a REGEX
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry

       aa bb PPAATTII

             return one or more occurance of 'b' in 'a'
             'b' is a REGEX case insensitive
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry

       aa bb TTPPAATT

             test if the pattern 'b' is in 'a'
             'b' is a REGEX
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry

       aa bb TTPPAATTII

             test if the pattern 'b' is in 'a'
             'b' is a REGEX
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry

       aa bb cc SSPPAATT

             substitute the pattern 'b' by the pattern 'a'  in 'c'
             'b' and 'c' are a REGEX
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry

       aa bb cc SSPPAATTGG

             substitute the pattern 'b' by the pattern 'a'  in 'c' as many time as possible (g flag in REGEX)
             'b' and 'c' are a REGEX
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry

       aa bb cc SSPPAATTII

             substitute the pattern 'b' by the pattern 'a'  in 'c'case insensitive (i flag in REGEX)
             'b' and 'c' are a REGEX
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry

       aa bb cc SSPPAATTGGII

             substitute the pattern 'b' by the pattern 'a'  in 'c' as many time as possible (g flag in REGEX)
             and case insensitive (1 flag in REGEX)
             'b' and 'c' are a REGEX
             !!! becare, if you need to use : as a regex, you need to backslash to prevent overlap with new dictionary entry

       aa ...... zz PPRRIINNTTFF

            use the format 'z' to print the value(s) on the stack
            7,3,/,10,3,/,%d %f,PRINTF -> 2 3.333333
            see printf in perl

       aa bb PPAACCKK

             pack the value 'a' with the format 'b'
             2004,06,08,a4 a2 a2,PACK -> 20040608
             see pack in perl

       aa bb UUNNPPAACCKK

             unpack the value 'a' with the format 'b'
             20040608,a4 a2 a2,PACK -> 2004,06,08
             see unpack in perl

SSTTAACCKK ooppeerraattoorrss
       .

       aa bb SSWWAAPP

               return 'b' 'a'

       aa bb OOVVEERR

               return 'a' 'b' 'a'

       aa DDUUPP

               return 'a' 'a'

       aa bb DDDDUUPP

               return 'a' 'b' 'a' 'b'

       aa bb cc RROOTT

               return 'b' 'c' 'a'

       aa bb cc RRRROOTT

               return 'c' 'a' 'b'

       DDEEPPTTHH

               return the number of elements on the stack

       aa bb PPOOPP

               remove the last element on the stack

       aa ...... zz PPOOPPNN

               remove the 'z' last element(s) from the stack

       aa bb cc dd ee ff RROOLLLL

               rotate the stack on 'f' element
               a,b,c,d,e,4,ROLL -> a c d e b
               if n= 3 = ROT

       aa PPIICCKK

               copy element from depth 'a' to the stack

       aa GGEETT

               get (remove) element from depth 'a'

       aa bb PPUUTT

               put element 'a' at the level 'b' of the stack
               if 'b' gretaer than the stack put at first place
               if 'b' < 0 start to the reverse order of the stack

       aa bb DDEELL

               delete 'b' element on the stack from level 'a'
               'a' and 'b' is get in absolute value

       aa FFIINNDD

               get the level of stack containing the value 'a'

       aa SSEEAARRCCHH

               get the level of stack containing the REGEX 'a'

       aa SSEEAARRCCHHII

               get the level of stack containing the REGEX 'a' (cas insensitive)

       aa KKEEEEPP

               delete all element on the stack except the level 'a'
               if 'a' is deeper then stack, keep the stack untouched

DDIICCTTIIOONNAARRYY aanndd VVAARRSS ooppeerraattoorrss
       .

       WWOORRDDSS

               return as one stack element the list of WORD in DICT separated by a |

       VVAARRSS

               return as one stack element the list of VARS  separated by a |

       IINNCC

               incremente (+ 1) the value of the variable on the statck

       DDEECC

               decremente (- 1) the value of the variable on the statck

       VVAARRIIAABBLLEE xxxxxx

              deckare the variable 'xxx' (reserve memory)

       xxxx vvaarr11 !!

               set the value xx to the variable var1

       vvaarr11 @@

               reyrn the value of the variable var1

       ::xxxxxx  nnaammee11 ;;

               create a new entry in the dictionary whith name name1 and store the progam xxx

       :: xxxxxx yyyyyy nnaammee11 PPEERRLL

               execute the PERL code
               with parameter(s) xxx yyy
               !!! be care if the perl code need to use a coma (,)
               you need to enclose the line inside double quote
               if you need double quote in code use qq{ ... }

       :: xxxxxx nnaammee11 PPEERRLLFFUUNNCC

               execute the PERL function name1 with the parameter xxx
               the default name space is "main::"
               It is possible tu use a specific name space
               the paramter are "stringified"
               e.g. ':,5,filename,save,PERLFUNC'
               call the function save("filename", 5);

       aa >>RR

               put 'a' on the return stack

       RR>>

              remove first element from the return stack and copy on the normal stack

       RRLL

              return the depth of the return stack

       RR@@

              copy return stack ion normal stack

LLOOOOPP aanndd DDEECCIISSIIOONN ooppeerraattoorrss
       .

       aa IIFF xxxxxx TTHHEENN

               test the element on top of stack
                       if ==0 execute 'xxx' block

               The loop is executed always one time

       aa IIFF zzzzzz EELLSSEE xxxxxx TTHHEENN

               test the element on top of stack
                       if ==0 execute 'xxx' block
                       if != 0 execute 'zzz' block

               The loop is executed always one time

       BBEEGGIINN xxxxxx WWHHIILLEE zzzzzz RREEPPEEAATT

               execute 'xxx' block
               test the element on top of stack
                       if ==0 execute 'zzz' block and branch again at 'BEGIN'
                       if != 0 end the loop

               The loop is executed always one time

       eenndd ssttaarrtt DDOO,,bblloocckk,,LLOOOOPP

               process 'block' with iterator from value 'start' untill 'end' value,with increment of 1;
               The iterator variable is the second value on the stack (start argument)

       eenndd ssttaarrtt iinnccrreemmeenntt DDOO,,bblloocckk,,LLOOOOPP

               process 'block' with iterator from value 'start' untill 'end' value,with increment of 'increment'
               This allow rational or negative value
               The iterator variable is the second value on the stack (start argument)

       _r_p_n___e_r_r_o_r_(_)

               function which return the debug info from the calculation (like a division by 0)

       rrppnn__sseeppaarraattoorr(( ''sseepp'' ))

               function to set a specific separator for the returned stack (default = space)
               This is useful when the result of rpn() is use inside another rpn() call

OOPPEERRAATTOORRSS
            The operators get value from the stack and push the result on top
            In the following explanation, the stack is represented as a pair of brackets ()
            and each elements by a pair of square barcket []
            The left part is the state before evalutation
            and the right part is the state of the stack after evaluation

               Arithmetic operators
               ---------------------
                   +                   ([a][b])                ([a+b])
                   -                   ([a][b])                ([a-b])
                   *                   ([a][b])                ([a*b])
                   /                   ([a][b])                ([a/b])         Becare if division by null return a blank value
                   **                  ([a][b])                ([a**b])
                   1+                  ([a])                   ([a+1])
                   1-                  ([a])                   ([a-1])
                   2+                  ([a])                   ([a+2])
                   2-                  ([a])                   ([a-2])
                   MOD                 ([a][b])                ([a%b])
                   ABS                 ([a])                   ([ABS a])
                   INT                 ([a])                   ([INT a])
                   +-                  ([a])                   ([-a])
                   REMAIN              ([a])                   ([a- INT a])

               Rationnal operators
               -------------------
                   SIN                 ([a])                   ([SIN a])       Unit in radian
                   COS                 ([a])                   ([COS a])       Unit in radian
                   TAN                 ([a])                   ([TAN a])       Unit in radian
                   CTAN                ([a])                   ([CTAN a])      Unit in radian
                   LN                  ([a])                   ([LOG a])
                   EXP                 ([a])                   ([EXP a])
                   PI                                          ([3.14159265358979])

               Relational operator
               ----------------
                   <                   ([a][b])                ([1]) if [a]<[b] else ([0])
                   <=                  ([a][b])                ([1]) if [a]<=[b] else ([0])
                   >                   ([a][b])                ([1]) if [a]>[b] else ([0])
                   >=                  ([a][b])                ([1]) if [a]>=[b] else ([0])
                   ==                  ([a][b])                ([1]) if [a]==[b] else ([0])
                   <=>                 ([a][b])                ([-1]) if [a]>[b],([1]) if [a]<[b], ([0])if [a]==[b]
                   !=                  ([a][b])                ([0]) if [a]==[b] else ([1])
                   TRUE                ([a])                   Return 1 if [a]>0 and exist
                   FALSE               ([a])                   Return 0 if [a]>0

               Logical operator
               ----------------

                   OR                  ([a][b])                ([1]) if [a] or [b] >0
                   AND                 ([a][b])                ([1]) if [a] and [b] >0
                   XOR                 ([a][b])                ([1]) if [a] and [b] are >0 or ==0
                   NOT                 ([a])                   Return 0 if [a]>0, Return 1 if[a]==0,

               Other operator
               ----------------

                   >>                  ([a][b])                shift to the right the bits from [a] of [b] rank
                   <<                  ([a][b])                shift to the left the bits from [a] of [b] rank
                   MIN                 ([a][b])                ([a]) if  [a]<[b] else ([b])
                   MAX                 ([a][b])                ([a]) if  [a]>[b] else ([b])
                   TICK                ()                      ([time]) time in ticks
                   LTIME               ([a])                   ([min][hour][day_in_the_month][month][year][day_in_week][day_year][daylight_saving]
                                                               localtime of [a] like PERL
                   GTIME               ([a])                   ([min][hour][day_in_the_month][month][year][day_in_week][day_year][daylight_saving]
                                                               ([a]) gmtime of [a] like PERL
                   HLTIME              ([a])                   ([a]) localtime human readeable
                   HGTIME              ([a])                   gmtime human readeable
                   RAND                ()                      ([rand]) a random numder between 0 and 1
                   LRAND               ([a])                   ([rand]) a random numder between 0 and [a]
                   SPACE               ([a])                   Return [a] with space between each 3 digits
                   DOT                 ([a])                   Return [a] with dot (.) between each 3 digits
                   NORM                ([a])                   Return [a] normalized by 1000 (K,M,G = 1000 * unit)
                   NORM2               ([a])                   Return [a] normalized by 1000 (K,M,G = 1024 * unit)
                   OCT                 (|a|)                   Return the DECIMAL value from HEX,OCTAL or BINARY value |a| (see oct from perl)

               String operators
               ----------------
                   EQ                  ([a][b])                ([1]) if [a] eq [b] else ([0])
                   NE                  ([a][b])                ([1]) if [a] ne [b] else ([0])
                   LT                  ([a][b])                ([1]) if [a] lt [b] else ([0])
                   GT                  ([a][b])                ([1]) if [a] gt [b] else ([0])
                   LE                  ([a][b])                ([1]) if [a] le [b] else ([0])
                   GE                  ([a][b])                ([1]) if [a] ge [b] else ([0])
                   CMP                 ([a][b])                ([-1]) if [a] gt [b],([1]) if [a] lt [b], ([0])if [a] eq [b]
                   LEN                 ([a])                   ([LENGTH a])
                   CAT                 ([a][b])                ([ab])  String concatenation
                   REP                 ([a][b])                ([a x b]) repeat [b] time the motif [a]
                   REV                 ([a])                   ([REVERSE a])
                   SUBSTR              ([a][b][c])             ([SUBSTR [a], [b], [c]) get substring of [a] starting from [b] untill [c]
                   UC                  ([a])                   ([UC a])
                   LC                  ([a])                   ([LC a])
                   UCFIRST             ([a])                   ([UCFIRST a])
                   LCFIRST             ([a])                   ([LCFIRST a])
                   PAT                 ([a][b])                ([r1]...) use the pattern [b] on the string [a] and return result
                                                               if more then one result like $1, $2 ... return all the results
                   PATI                ([a][b])                ([r1]...) use the pattern CASE INSENSITIVE [b] on the string [a] and return result
                                                               if more then one result like $1, $2 ... return all the results
                   TPAT                ([a][b])                ([r]) use the pattern [b] on the string [a] and return 1 if pattern macth
                                                               otherwise return 0
                   TPATI               ([a][b])                ([r]) use the pattern CASE INSENSITIVE [b] on the string [a] and return 1 if pattern macth
                                                               otherwise return 0
                   SPLIT               ([a][b])                split ([a]) using the pattern ([b]) and return all elements on stack
                   SPLITI                                      split ([a]) using the pattern CASE INSENSITIVE  ([b])) and return all elements on stack
                   SPAT                ([a][b][c])             Do a pattern subsititution following this rule I<[c] =~s/[a]/[b]/>
                   SPATG               ([a][b][c])             Do a pattern subsititution following this rule I<[c] =~s/[a]/[b]/g>
                   SPATI               ([a][b][c])             Do a pattern subsititution following this rule I<[c] =~s/[a]/[b]/i>
                                                               (case insensitive)
                   SPATGI              ([a][b][c])             Do a pattern subsititution following this rule I<[c] =~s/[a]/[b]/gi>
                                                               (case insensitive)
                   PRINTF              ([a][b]...[x])          use the format present in [a] to print the value [b] to [x]
                                                               the format is the same as (s)printf
                   PACK                ([a][b]...[x])          Do an unpack on variable [b] to [x] using format [b]
                   UNPACK              ([a][b])                Do an unpack on variable [b] using format [a]

                Stack operators
                ---------------

                   SWAP                ([a][b])                ([b][a])
                   OVER                ([a][b])                ([a][b][a])
                   DUP                 ([a])                   ([a][a])
                   DDUP                ([a][b])                ([a][b][a][b])
                   ROT                 ([a][b][c])             ([b][c][a])
                   RROT                ([a][b][c])             ([c][a][b])
                   DEPTH               ([r1]...)               ([re1]...[nbr]) Return the number of elements in the statck
                   POP                 ([a][b])                ([a])
                   POPN                ([a][b][c]...[x])       ([l]...[x]) remove [b] element from the stack (starting at [c])
                   DEL                 ([a][b][c][d]...[x])    ([c]...[n][m]...[x]) delete [b] elements from element number [a]
                   SWAP2               ([a][b][c])             ([a][c][b])
                   ROLL                ([a][b][c][d][e][n])    ([a][c][d][e][b]) rotate the [n] element of the stack (here [n]=4)
                                                               if  [n] =3 it is equivalent to ROT
                   PICK                ([a][b][c][d][e][n])    ([a][b][c][d][e][b]) copy element from depth [n] on top
                   GET                 ([a][b][c][d][e][n])    ([a][b][c][d][e][b]) get element from depth [n] and put on top
                   PUT                 ([a][b][c][d][v][n])    ([a][v][b][c][d]) put element [v] at level [n] (here [n]=3)
                   DEL                 ([a][b])                delete [b] element on the stack from lebvel [a]
                                                               [a] and [b] is get in absolute value
                   FIND                ([a])                   get the level of stack containing [a]
                   SEARCH              ([a])                   get the level of stack containing the REGEX [a]
                   SEARCHI             ([a])                   get the level of stack containing the REGEX [a] ( case insensitive )

                   KEEP                ([a][b][c][d][e][n])    remove all elements of the stack except the element at deepth |n|

                Dictionary operators
                --------------------

                   WORDS               ()                      ([a])return as one stack element the list of WORD in DICT separated by a |
                   VARS                ()                      ([a])return as one stack element the list of VARIABLE in VAR separated by a |
                   INC                 ([a])                   () increment (+1) the value of variable [a]
                   DEC                 ([a])                   () decrement (-1) the value of variable [a]
                   VARIABLE            ([a])                   () create a entry in VAR for the variable [a]
                   !                   ([a][b])                store the value [a] in the variable [b]
                   @                   ([a])                   ([a]) return the value of the variable [a]
                   : xxx yyy ;                                 create a new word (sub) into the dictionary with the xxx "code" with name yyy
                   : xxx yyy PERLFUNC                          execute the PERL function yyy with parameter(s) yyy
                                                               the default name space is "main::"
                                                               It is possible tu use a specific name space
                   : xxx yyy PERL                              execute the PERL code xxx ; yyy

                Return Stack operators
                ----------------------

                  >R                   ([a])                   put ^a$ on the return stack
                  R>                   ()                      remove first element from the return stack and copy on the normal
                  RL                   ()                      return the depth of the return stack
                  R@                   ()                      copy return stack ion normal stack

               LOOP and DECISION operators
               ---------------------------

                [a] IF [..xxx] THEN                            Test the element on top of stack
                                                                 if ==0, execute 'xxx' block
                                                               The loop is executed always one time

                [a] IF [...zzz...] ELSE [..xxx...] THEN        Test the element on top of stack
                                                                 if ==0, execute 'xxx' block
                                                                 if != 0 execute 'zzz' block
                                                               The loop is executed always one time

                BEGIN xxx WHILE zzz REPEAT                     Execute 'xxx' block
                                                               Test the element on top of stack
                                                                 if ==0 execute 'zzz' block and branch again to BEGIN
                                                                 if != 0 end the loop
                                                               The loop is executed always one time

               [a] [b] DO [...xxx...] LOOP     ([a][b])        process block [...xxx...] with iterator from value [b] untill [a] value,
                                                               with increment of 1;
                                                               The iterator variable is '_I_' (read only and scoop only the DO ... LOOP block)

               [a] [b] DO [...xxx...] [c] LOOP ([a][b])        rocess block [...xxx...] with iterator from value [b] untill [a] value,
                                                               with increment of [c];
                                                               The iterator variable is '_I_' (read only and scoop only the DO ... LOOP block)

EEXXAAMMPPLLEESS
               use Parse::RPN;

               $test ="3,5,+";
               $ret = rpn($test);  # $ret = 8

               $test = "Hello World,len,3,+";
               $ret = rpn($test);  # $ret = 14

               $test = "'Hello,World',len,3,+";
               $ret = rpn($test);  # $ret = 14

               $test = "'Hello,World,len,3,+";
               ---------^-----------^-
               $ret = rpn($test);  # $ret = 8 with a warning because the stack is not empty ([Hello] [8])
                                   # be care to close your quoted string

               $test = "'Hello,world',',',pat,',',eq,'Contain a coma','Without a coma',if";
               $ret = rpn($test);  # $ret = "Contain a coma"

               $test = "'Hello world',',',pat,',',eq,'Contain a coma','Without a coma',if";
               $ret = rpn($test);  # $ret = "Without a coma"

               $test = "3,10,/,5,+,82,*,%b,PRINTF";
               $ret = rpn($test);  # $ret = "110110010"

               $test = "3,10,/,5,+,82,*,%016b,PRINTF";
               $ret = rpn($test);  # $ret = "0000000110110010"

               $test = "55,N,pack,B32,unpack,^0+(?=\d), ,spat,'+',ds";
               $ret = rpn($test);  # $ret = 110111

               $test = "7,3,/,10,3,/,%d %f,PRINTF";
               @ret = rpn($test); # @ret = 2 3.333333

               $test = "VARIABLE,a,0,a,!,##,b,BEGIN,bbbb,a,INC,a,@,4,<,WHILE,####,a,@,****,REPEAT";
               @ret =rpn($test); # @ret = ## b bbbb #### 1 **** bbbb #### 2 **** bbbb #### 3 **** bbbb

               $test = "VARIABLE,a,0,a,!,z,0,5,-1,DO,a,INC,6,1,2,DO,A,_I_,+LOOP,#,+LOOP,##,a,@";
               @ret =rpn($test); # @ret = z A 3 A 5 A 7 # A 3 A 5 A 7 # A 3 A 5 A 7 # A 3 A 5 A 7 # A 3 A 5 A 7 # A 3 A 5 A 7 # ## 6

               $test = "1,2,3,4,5,6,7,8,9,3,KEEP";
               ret =rpn($test); # @ret = 7

               $test = "1,2,3,4,5,6,7,8,9,30,KEEP";
               ret =rpn($test); # @ret = 1,2,3,4,5,6,7,8,9

               sub Test {
                  my $a  = shift;
                  my $b = shift;
                  my $c = $a/$b;
                  print "a=$a\tb=$b\ttotal=$c\n";
                  return $c;
               }
               $test = ":,5,6,Test,PERLFUNC";
               @ret =rpn($test); # call the function "Test" from the main package (the caller) with parameter 5,6 and return result (in @ret)

               $test = ":,05,11,01,0,0,0,Time::Local::timelocal,PERLFUNC";
               @ret =rpn($test); # @ret = 1133391600

               $test = "1,2,3,+,:, my $b=7, "open LOG , qq{ >/tmp/log }",print LOG time,,PERL";
               @ret =rpn($test); # @ret = 1,5
               and the file /tmp/log contain a line with the tick time.

               $test = "11,55,*,5,2,401,+,:,my $b=,SWAP,CAT, "open LOG , qq{ >/tmp/log }",print LOG $b.qq{ \n },PERL"
               @ret =rpn($test); # @ret =1 2 3 1 (the latest 1 is the succes result return)
               and the file /tmp/log contain a line with 403 + a cariage return

               The small tool 'RPN.pl' provide an easy interface to test quickly an RPN.
               This include two test functions named 'save' and 'restore'
               Try RPN.pl to get a minimal help.
               Take a look to the minimalistic code, and put RPN.pl in your path.

               Sample of use:
               RPN.pl -r '1,2,3,:,123,100,+,7,*,test,save,PERLFUNC'
               save in file '/tmp/test' the value '1561' (whithout CR/LF) and return 1 2 3 1

AAUUTTHHOORR
               Fabrice Dulaunoy <fabrice@dulaunoy.com>
               It is a full rewrite from the version 1.xx to allow DICTIONNARY use
               and STRUCTURE control
               Thanks to the module Math::RPN from  Owen DeLong, <owen@delong.com>
               for the idea of using RPN in a config file

SSEEEE AALLSSOO
               Math-RPN from  Owen DeLong, <owen@delong.com>

TTOODDOO
               Error processing, stack underflow...

CCRREEDDIITTSS
               Thank's to Stefan Moser <sm@open.ch> for the idea
               to call a perl function from the rpn()

LLIICCEENNSSEE
               Under the GNU GPL2

               This program is free software; you can redistribute it and/or modify it
               under the terms of the GNU General Public
               License as published by the Free Software Foundation; either version 2
               of the License, or (at your option) any later version.

               This program is distributed in the hope that it will be useful,
               but WITHOUT ANY WARRANTY;  without even the implied warranty of
               MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
               See the GNU General Public License for more details.

               You should have received a copy of the GNU General Public License
               along with this program; if not, write to the
               Free Software Foundation, Inc., 59 Temple Place,
               Suite 330, Boston, MA 02111-1307 USA

               Parse::RPN   Copyright (C) 2004 DULAUNOY Fabrice
               Parse::RPN comes with ABSOLUTELY NO WARRANTY;
               for details See: L<http://www.gnu.org/licenses/gpl.html>
               This is free software, and you are welcome to redistribute
               it under certain conditions;



perl v5.8.8                       2006-03-13                            RPN(3)
