| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- MODULE prog8;
- (* This program implements a simple interactive calculator *)
- IMPORT IO,Str,Storage;
- TYPE
- TokenType = (number, add, sub, mul, div, LeftParen,
- RightParen, end);
- SyntacticType = (main, exp, term, factor);
- TreeType = POINTER TO TreeRecordType;
- TreeRecordType = RECORD
- CASE kind:TokenType OF
- | number :
- NumberValue : LONGREAL;
- | add,sub,mul,div :
- left : TreeType;
- right : TreeType;
- END;
- END;
- VAR
- c:CHAR;
- token:TokenType;
- TokenNumberValue:LONGREAL;
- PROCEDURE error(s:ARRAY OF CHAR);
- BEGIN
- IO.WrStr(s);
- IO.WrLn;
- HALT;
- END error;
- PROCEDURE readtoken;
- VAR
- s:ARRAY[0..99] OF CHAR;
- i:[0..99];
- done:BOOLEAN;
- oldc:CHAR;
- BEGIN
- LOOP
- oldc := c;
- c := IO.RdChar();
- CASE oldc OF
- | ' ' :
- | '+' : token := add; EXIT;
- | '-' : token := sub; EXIT;
- | '*' : token := mul; EXIT;
- | '/' : token := div; EXIT;
- | '(' : token := LeftParen; EXIT;
- | ')' : token := RightParen; EXIT;
- | CHAR(10),CHAR(13),CHAR(26) : token := end; EXIT;
- | '0'..'9' : (* read a real number *)
- i := 1; s[0] := oldc;
- WHILE (c >= '0') AND (c <= '9') DO
- s[i] := c;
- INC(i);
- c := IO.RdChar();
- END;
- IF c<>'.' THEN (* add decimal point if none in input *)
- s[i] := '.';
- INC(i);
- ELSE
- REPEAT (* read fraction part *)
- s[i] := c;
- INC(i);
- c := IO.RdChar();
- UNTIL (c < '0') OR (c > '9');
- END;
- s[i] := CHAR(0);
- TokenNumberValue := Str.StrToReal(s, done);
- IF NOT done THEN
- error('Bad number?');
- END;
- token := number;
- EXIT;
- ELSE
- error('Bad character');
- END;
- END;
- END readtoken;
- PROCEDURE read(what:SyntacticType):TreeType;
- VAR t,t1:TreeType;
- BEGIN
- CASE what OF
- | factor :
- IF token = LeftParen THEN
- readtoken;
- t := read(exp);
- IF token = RightParen THEN
- readtoken;
- ELSE
- error("Missing ')'");
- END;
- ELSIF token = number THEN
- Storage.ALLOCATE(t, SIZE(t^));
- t^.kind := number;
- t^.NumberValue := TokenNumberValue;
- readtoken;
- ELSE
- error('Missing number?');
- END;
- | term:
- t := read(factor);
- WHILE (token = mul) OR (token = div) DO
- t1 := t;
- Storage.ALLOCATE(t, SIZE(t^));
- t^.kind := token;
- readtoken;
- t^.left := t1;
- t^.right := read(factor);
- END;
- | exp:
- t := read(term);
- WHILE (token = add) OR (token = sub) DO
- t1 := t;
- Storage.ALLOCATE(t, SIZE(t^));
- t^.kind := token;
- readtoken;
- t^.left := t1;
- t^.right := read(term);
- END;
- | main :
- c := IO.RdChar();
- readtoken;
- t := read(exp);
- IF (token <> end) THEN
- error('Missing operator?');
- END;
- END;
- RETURN t;
- END read;
- PROCEDURE eval(t:TreeType):LONGREAL;
- BEGIN
- CASE t^.kind OF
- | number : RETURN t^.NumberValue;
- | add : RETURN eval(t^.left) + eval(t^.right);
- | sub : RETURN eval(t^.left) - eval(t^.right);
- | mul : RETURN eval(t^.left) * eval(t^.right);
- | div : RETURN eval(t^.left) / eval(t^.right);
- END;
- END eval;
- VAR
- t:TreeType;
- result:LONGREAL;
- BEGIN
- LOOP
- IO.WrStr('Enter expression : ');
- t := read(main);
- result := eval(t);
- IO.WrStr(' = ');
- IO.WrLngReal(result, 4, 0);
- IO.WrLn;
- END;
- END prog8.
|