/* main rpn parser and lexical analysis, part of the RPN calculator */ #include #include 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 }