## Scientif Calculator (Help Needed!!!)

##### Quote
On Fri, 14 Jun 1996, Ricardo Goncalves wrote:
> Hi,
>      I need, to do a program using Turbo Pascal... It's a Scientific
> calculator with the operation +-*/ ^ div and uses parentesis () {} []
> and it's has capabilitys of using Variables ...

>    My _BIG_ problem is to do the procedure, of putting in a Stack in
> pos-fixed way (e.g. A+B       AB+  Pos-fixed)  because the prioraty of
> parentesis and *,/,div,^...

There is no need to build additional data structures during calculation.
The interpreter can use its own (CPU) stack for this purpose.

First, we must build the formal representation of expressions to
understand this task better. (See, f.ex., Object Pascal Language
Specification in techdoc archive of ftp.borland.com - OBJLANG.PDF).

What is expression:

1. expr ::= term { '+' | '-' term }

This means that expression is a term optionally followed by plus or minus
sign and another term (repeated). What is term:

2. term ::= factor { '*' | '/' factor }

This rule itself tells that mul and div operations have higher priority

Finally, the factor may be one of: variable, constant or a nested
expression, e.g. rule 1 enclosed in parentheses.

3. factor ::= variable | constant | '(' expr ')'

Variable identifier is usually defined as a sequence of letters:
['A'..'Z','_'], and the constant is a sequence of digits: ['0'..'9','.'].
You should implement a function that reads incoming character stream and
returns so called tokens.

Now, we go down to lower level of implementation and try to tell the same
things in pseudo-pascal:

{ --- TOKEN EXTRACTION --- }

type
TTokenType = (tokNumber, tokIdent, tokSpecial);
TResult = Integer; { or Real }

var
TokenType: TTokenType;
Token: string;
TokenVal: TResult;

procedure NextToken;
begin
skip whitespace characters: [space, tab, CR, LF, ...]
case NextChar of
digit:
Token := next digits
TokenVal := Val(Token)
TokenType := tokNumber
letter:
Token := next letters
TokenType := tokIdent
[plus, minus, ...]:
Token := CurChar
TokenType := tokSpecial
end;

Following functions are almost in 'true' pascal:

{ --- EXPRESSION ITEM --- }

function Expression: TResult; forward;

function Factor: TResult;
begin
if TokenType = tokNumber then
Factor := TokenVal;
else if TokenType = tokIdent then
Factor := { find this identifier in your symbol table and get its value }
else if (TokenType = tokSpecial) and (Token = '(') then begin
Factor := Expression;
if (TokenType <> tokSpecial) or (Token <> ')') then
Error('")" expected');
end
else Error('Expression syntax');
NextToken;
end;

{ --- TERM --- }

function Term: TResult;
var
V: TResult;
Opr: Char;
begin
V := Factor;
while (TokenType = tokSpecial) and (Token in ['*','/']) do
Opr := Token;
NextToken;
if Opr = '*' then V := V * Factor
else V := V / Factor;
end;
Term := V;
end;

{ --- EXPRESSION --- }

function Expression: TResult;
var
V: TResult;
Opr: Char;
begin
NextToken;
V := Term;
while (TokenType = tokSpecial) and (Token in ['+','-']) do
Opr := Token;
NextToken;
if Opr = '+' then V := V + Factor
else V := V - Factor;
end;
Expression := V;
end;

{ --- *** --- }

That's all. Enjoy =:-)

Hovik Melikian,
always at ho...@jerewan1.yerphi.am