{ THAI TRAN { I've netmailed you the full-featured version (800 lines!) that will do Functions, exponentiation, factorials, and has all the bells and whistles, but I thought you might want to take a look at a simple version so you can understand the algorithm. This one only works With +, -, *, /, (, and ). I wrote it quickly, so it makes extensive use of global Variables and has no error checking; Use at your own risk. Algorithm to convert infix to postfix (RPN) notation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Parse through the entire expression getting each token (number, arithmetic operator, left or right parenthesis). For each token, if it is: 1. an operand (number) Send it to the RPN calculator 2. a left parenthesis Push it onto the operator stack 3. a right parenthesis Pop operators off stack and send to RPN calculator Until the a left parenthesis is on top of the stack. Pop it also, but don't send it to the calculator. 4. an operator While the stack is not empty, pop operators off the stack and send them to the RPN calculator Until you reach one With a higher precedence than the current operator (Note: a left parenthesis has the least precendence). Then push the current operator onto the stack. This will convert (4+5)*6/(2-3) to 4 5 + 6 * 2 3 - / Algorithm For RPN calculator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Note: this Uses a different stack from the one described above. In RPN, if an operand (a number) is entered, it is just pushed onto the stack. For binary arithmetic operators (+, -, *, /, and ^), the top two operands are popped off the stack, operated on, and the result pushed back onto the stack. if everything has gone correctly, at the end, the answer should be at the top of the stack. Released to Public Domain by Thai Tran (if that matters). } {$X+} Program Expression_Evaluator; Const RPNMax = 10; { I think you only need 4, but just to be safe } OpMax = 25; Type String15 = String[15]; Var Expression : String; RPNStack : Array[1..RPNMax] of Real; { Stack For RPN calculator } RPNTop : Integer; OpStack : Array[1..OpMax] of Char; { Operator stack For conversion } OpTop : Integer; Procedure RPNPush(Num : Real); { Add an operand to the top of the RPN stack } begin if RPNTop < RPNMax then begin Inc(RPNTop); RPNStack[RPNTop] := Num; end else { Put some error handler here } end; Function RPNPop : Real; { Get the operand at the top of the RPN stack } begin if RPNTop > 0 then begin RPNPop := RPNStack[RPNTop]; Dec(RPNTop); end else { Put some error handler here } end; Procedure RPNCalc(Token : String15); { RPN Calculator } Var Temp : Real; Error : Integer; begin Write(Token, ' '); { This just outputs the RPN expression } if (Length(Token) = 1) and (Token[1] in ['+', '-', '*', '/']) then Case Token[1] of { Handle operators } '+' : RPNPush(RPNPop + RPNPop); '-' : RPNPush(-(RPNPop - RPNPop)); '*' : RPNPush(RPNPop * RPNPop); '/' : begin Temp := RPNPop; if Temp <> 0 then RPNPush(RPNPop/Temp) else { Handle divide by 0 error } end; end else begin { Convert String to number and add to stack } Val(Token, Temp, Error); if Error = 0 then RPNPush(Temp) else { Handle error } end; end; Procedure OpPush(Operator : Char); { Add an operator onto top of the stack } begin if OpTop < OpMax then begin Inc(OpTop); OpStack[OpTop] := Operator; end else { Put some error handler here } end; Function OpPop : Char; { Get operator at the top of the stack } begin if OpTop > 0 then begin OpPop := OpStack[OpTop]; Dec(OpTop); end else { Put some error handler here } end; Function Priority(Operator : Char) : Integer; { Return priority of operator } begin Case Operator OF '(' : Priority := 0; '+', '-' : Priority := 1; '*', '/' : Priority := 2; else { More error handling } end; end; Procedure Evaluate(Expr : String); { Guess } Var I : Integer; Token : String15; begin OpTop := 0; { Reset stacks } RPNTop := 0; Token := ''; For I := 1 to Length(Expr) DO if Expr[I] in ['0'..'9'] then begin { Build multi-digit numbers } Token := Token + Expr[I]; if I = Length(Expr) then { Send last one to calculator } RPNCalc(Token); end else if Expr[I] in ['+', '-', '*', '/', '(', ')'] then begin if Token <> '' then begin { Send last built number to calc. } RPNCalc(Token); Token := ''; end; Case Expr[I] OF '(' : OpPush('('); ')' : begin While OpStack[OpTop] <> '(' DO RPNCalc(OpPop); OpPop; { Pop off and ignore the '(' } end; '+', '-', '*', '/' : begin While (OpTop > 0) AND (Priority(Expr[I]) <= Priority(OpStack[OpTop])) DO RPNCalc(OpPop); OpPush(Expr[I]); end; end; { Case } end else; { Handle bad input error } While OpTop > 0 do { Pop off the remaining operators } RPNCalc(OpPop); end; begin Write('Enter expression: '); Readln(Expression); Write('RPN Expression = '); Evaluate(Expression); Writeln; Writeln('Answer = ', RPNPop : 0 : 4); end.