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
than add and sub.

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[1] = '(') then begin
    Factor := Expression;
    if (TokenType <> tokSpecial) or (Token[1] <> ')') 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[1] in ['*','/']) do
    Opr := Token[1];
    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[1] in ['+','-']) do
    Opr := Token[1];
    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