home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
dirs
/
oberon_380.lzh
/
Oberon
/
Demos
/
Pute.mod
< prev
next >
Wrap
Text File
|
1990-10-11
|
4KB
|
180 lines
(*------------------------------------------------------------------------
Pute evaluates integer expressions.
Usage: Pute <expr>
with
expr = "(" expr ")" | number | expr op expr.
op = "+" | "-" | "*" | "-" | "DIV" | "MOD".
number = digit {digit} | hexdigit {hexdigit} "H".
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9".
hexdigit = digit | "A" | "B" | "C" | "D" | "E" | "F".
© Copyright 1990 by Fridtjof Siebert. Freely redistributable
------------------------------------------------------------------------*)
MODULE Pute;
(* $OvflChk- $RangeChk- $StackChk- $NilChk- $ReturnChk- $CaseChk- *)
IMPORT io, ol: OberonLib;
CONST
lparen = 0; rparen = 1; times = 2; plus = 3; minus = 4;
div = 5; mod = 6; number = 7; eof = -1;
TYPE String = ARRAY 80 OF CHAR;
VAR
Sym: SHORTINT;
Number: LONGINT;
Char: CHAR;
buffer: POINTER TO String;
index: INTEGER;
Identifier: String;
result: LONGINT;
(*-------------------------------------------------------------------------*)
PROCEDURE ReadChar;
BEGIN
IF index=ol.dosCmdLen THEN Char := 0X;
ELSE Char := CAP(buffer^[index]); INC(index) END;
END ReadChar;
(*-------------------------------------------------------------------------*)
PROCEDURE Error;
BEGIN
io.WriteString("Usage: PUTE <Expression>"); io.WriteLn; HALT(0)
END Error;
(*-------------------------------------------------------------------------*)
PROCEDURE GetSym();
VAR
digit: String; (* used to read constant numbers *)
cnt,i: INTEGER;
n: SHORTINT;
BEGIN
WHILE (Char<=" ") AND (Char>0X) DO ReadChar END;
CASE Char OF
"A".."Z":
cnt := 0;
WHILE (Char>="A") AND (Char<="Z") DO
Identifier[cnt] := Char;
ReadChar;
INC(cnt); IF cnt=80 THEN Error END;
END;
Identifier[cnt] := 0X;
IF Identifier="DIV" THEN Sym := div
ELSIF Identifier="MOD" THEN Sym := mod
ELSE Error END |
"0".."9":
cnt := -1;
WHILE ((Char>="0") AND (Char<="9")) OR ((Char>="A") AND (Char<="Z")) DO
INC(cnt);
IF cnt=80 THEN Error END;
digit[cnt] := Char;
ReadChar;
END;
Number := 0; i := 0;
IF digit[cnt]#"H" THEN
WHILE i<=cnt DO
n := SHORT(ORD(digit[i])-ORD("0"));
CASE n OF 0..9: Number := 10 * Number + n ELSE Error END;
INC(i);
END;
ELSE
WHILE i<cnt DO
n := SHORT(ORD(digit[i])-ORD("0"));
IF n>9 THEN DEC(n,7) END;
CASE n OF 0..15: Number := 16 * Number + n ELSE Error END;
INC(i);
END;
END;
Sym := number;
RETURN |
"(": Sym := lparen |
")": Sym := rparen |
"*": Sym := times |
"+": Sym := plus |
"-": Sym := minus |
"/": Sym := div |
0X : Sym := eof |
ELSE Error END;
ReadChar;
END GetSym;
(*-------------------------------------------------------------------------*)
PROCEDURE Expression(): LONGINT;
VAR
c: LONGINT;
addOperator: SHORTINT;
PROCEDURE Term(): LONGINT;
VAR
d,c: LONGINT;
s: SHORTINT;
PROCEDURE Factor(): LONGINT;
VAR c: LONGINT;
BEGIN
CASE Sym OF number: c := Number; GetSym |
lparen: GetSym; c:=Expression();
IF Sym#rparen THEN Error END;
GetSym |
ELSE Error END;
RETURN c
END Factor;
BEGIN
c := Factor();
LOOP
CASE Sym OF
times,div,mod:
s := Sym;
GetSym; d := Factor();
IF s=times THEN c := c * d;
ELSIF d=0 THEN HALT(0)
ELSIF s=div THEN c := c DIV d;
ELSE c := c MOD d END |
ELSE EXIT END;
END;
RETURN c;
END Term;
BEGIN
addOperator := Sym;
IF (addOperator=plus) OR (addOperator=minus) THEN GetSym END;
c := Term();
IF addOperator=minus THEN c := -c END;
LOOP
CASE Sym OF
plus : GetSym; INC(c,Term()) |
minus: GetSym; DEC(c,Term()) |
ELSE EXIT END;
END;
RETURN c;
END Expression;
BEGIN
IF ol.wbStarted THEN Error END;
buffer := ol.dosCmdBuf;
Char := " "; GetSym;
result := Expression(); IF Sym#eof THEN Error END;
io.WriteInt(result,11); io.WriteString(" = ");
io.WriteHex(result,8); io.Write("H"); io.WriteLn;
END Pute.