Search code examples
smalltalkpostfix-notation

Postfix calculation in smalltalk


I have to write a code to evaluate a postfix notation(reverse Polish evaluation) in Smalltalk. I have gone through the documentation and have also implemented a stack. This is the code I have written so far:

Object subclass: #Rpcalc
instanceVariableNames: 'anArray top'
classVariableNames: ''
poolDictionaries: ''
category: nil !

pop:
    | item |
item := anArray at: top.
top := top - 1.
^item!

push: item
 top := top + 1.
 anArray at: top put: item!

setsize: n
  anArray := Array new: n.
  top := 0! 

evaluate:
       | expression aToken op1 op2 operator answer|
   Transcript show: 'Enter Expression' .
   expression :- stdin nextLine.

   | aStack |
   aStack := Array new: 10 .

   aToken := self getNextToken.
       ((aToken key) = 'operand')
       ifTrue: [push : aToken].

        aToken := self getNextToken.
       ((aToken key) = 'operator')
        ifTrue:  [op1 := pop.
           op2 := pop.
           operator := aToken.
   "if(operator := +)"
   "answer := op1 + op2"

I want to know how to tokenize each element in the expression. For e.g., for the expression, 10 3 + 3 7 * - I need to equate it to a token. If its an operand, it should push it into the stack. If an operator, pop the stack twice to get the operands and evaluate the expression. I am totally new to smalltalk, so I am clueless about the syntax.


Solution

  • You did not specify which Smalltalk dialect you are using. In Squeak, you could use the findTokens: method:

    '336 8 4 2 1 + - * /' findTokens: ' '
    ==> an OrderedCollection('336' '8' '4' '2' '1' '+' '-' '*' '/')
    

    Use isDigit to test if a token is a number:

    '336' first isDigit
    ==> true
    '+' first isDigit
    ==> false
    

    To convert from a string to a number you would use asNumber:

    '336' asNumber
    ==> 336
    

    The whole RPN parser/evaluator can easily be implemented with less than 10 lines of code, but obviously that is your homework to do (hint: no need to implement a stack, there is already one).