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