| /* main rpn parser and lexical analysis, part of the RPN calculator */ |
| #include <rational> |
| #include <string> |
| enum token |
| { |
| t_type, /* operator or token type */ |
| Rational: t_value, /* value, if t_type is "Number" */ |
| t_word[20], /* raw string */ |
| } |
| |
| const Number = '0' |
| const EndOfExpr = '#' |
| |
| rpncalc(const string[]) |
| { |
| new index |
| new field[token] |
| for ( ;; ) |
| { |
| field = gettoken(string, index) |
| switch (field[t_type]) |
| { |
| case Number: |
| push field[t_value] |
| case '+': |
| push pop() + pop() |
| case '-': |
| push - pop() + pop() |
| case '*': |
| push pop() * pop() |
| case '/', ':': |
| push 1.0 / pop() * pop() |
| case EndOfExpr: |
| break /* exit "for" loop */ |
| default: |
| printf "Unknown operator '%s'\n", field[t_word] |
| } |
| } |
| |
| printf "Result = %r\n", pop() |
| |
| if (clearstack()) |
| print "Stack not empty\n", red |
| } |
| |
| gettoken(const string[], &index) |
| { |
| /* first get the next "word" from the string */ |
| new word[20] |
| word = strtok(string, index) |
| /* then parse it */ |
| new field[token] |
| field[t_word] = word |
| if (strlen(word) == 0) |
| { |
| field[t_type] = EndOfExpr /* special "stop" symbol */ |
| field[t_value] = 0 |
| } |
| else if ('0' <= word[0] <= '9') |
| { |
| field[t_type] = Number |
| field[t_value] = rationalstr(word) |
| } |
| else |
| { |
| field[t_type] = word[0] |
| field[t_value] = 0 |
| } |
| return field |
| } |
| |