72 lines
1.7 KiB
C++
72 lines
1.7 KiB
C++
/* 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
|
|
}
|