PROG8.MOD 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. MODULE prog8;
  2. (* This program implements a simple interactive calculator *)
  3. IMPORT IO,Str,Storage;
  4. TYPE
  5. TokenType = (number, add, sub, mul, div, LeftParen,
  6. RightParen, end);
  7. SyntacticType = (main, exp, term, factor);
  8. TreeType = POINTER TO TreeRecordType;
  9. TreeRecordType = RECORD
  10. CASE kind:TokenType OF
  11. | number :
  12. NumberValue : LONGREAL;
  13. | add,sub,mul,div :
  14. left : TreeType;
  15. right : TreeType;
  16. END;
  17. END;
  18. VAR
  19. c:CHAR;
  20. token:TokenType;
  21. TokenNumberValue:LONGREAL;
  22. PROCEDURE error(s:ARRAY OF CHAR);
  23. BEGIN
  24. IO.WrStr(s);
  25. IO.WrLn;
  26. HALT;
  27. END error;
  28. PROCEDURE readtoken;
  29. VAR
  30. s:ARRAY[0..99] OF CHAR;
  31. i:[0..99];
  32. done:BOOLEAN;
  33. oldc:CHAR;
  34. BEGIN
  35. LOOP
  36. oldc := c;
  37. c := IO.RdChar();
  38. CASE oldc OF
  39. | ' ' :
  40. | '+' : token := add; EXIT;
  41. | '-' : token := sub; EXIT;
  42. | '*' : token := mul; EXIT;
  43. | '/' : token := div; EXIT;
  44. | '(' : token := LeftParen; EXIT;
  45. | ')' : token := RightParen; EXIT;
  46. | CHAR(10),CHAR(13),CHAR(26) : token := end; EXIT;
  47. | '0'..'9' : (* read a real number *)
  48. i := 1; s[0] := oldc;
  49. WHILE (c >= '0') AND (c <= '9') DO
  50. s[i] := c;
  51. INC(i);
  52. c := IO.RdChar();
  53. END;
  54. IF c<>'.' THEN (* add decimal point if none in input *)
  55. s[i] := '.';
  56. INC(i);
  57. ELSE
  58. REPEAT (* read fraction part *)
  59. s[i] := c;
  60. INC(i);
  61. c := IO.RdChar();
  62. UNTIL (c < '0') OR (c > '9');
  63. END;
  64. s[i] := CHAR(0);
  65. TokenNumberValue := Str.StrToReal(s, done);
  66. IF NOT done THEN
  67. error('Bad number?');
  68. END;
  69. token := number;
  70. EXIT;
  71. ELSE
  72. error('Bad character');
  73. END;
  74. END;
  75. END readtoken;
  76. PROCEDURE read(what:SyntacticType):TreeType;
  77. VAR t,t1:TreeType;
  78. BEGIN
  79. CASE what OF
  80. | factor :
  81. IF token = LeftParen THEN
  82. readtoken;
  83. t := read(exp);
  84. IF token = RightParen THEN
  85. readtoken;
  86. ELSE
  87. error("Missing ')'");
  88. END;
  89. ELSIF token = number THEN
  90. Storage.ALLOCATE(t, SIZE(t^));
  91. t^.kind := number;
  92. t^.NumberValue := TokenNumberValue;
  93. readtoken;
  94. ELSE
  95. error('Missing number?');
  96. END;
  97. | term:
  98. t := read(factor);
  99. WHILE (token = mul) OR (token = div) DO
  100. t1 := t;
  101. Storage.ALLOCATE(t, SIZE(t^));
  102. t^.kind := token;
  103. readtoken;
  104. t^.left := t1;
  105. t^.right := read(factor);
  106. END;
  107. | exp:
  108. t := read(term);
  109. WHILE (token = add) OR (token = sub) DO
  110. t1 := t;
  111. Storage.ALLOCATE(t, SIZE(t^));
  112. t^.kind := token;
  113. readtoken;
  114. t^.left := t1;
  115. t^.right := read(term);
  116. END;
  117. | main :
  118. c := IO.RdChar();
  119. readtoken;
  120. t := read(exp);
  121. IF (token <> end) THEN
  122. error('Missing operator?');
  123. END;
  124. END;
  125. RETURN t;
  126. END read;
  127. PROCEDURE eval(t:TreeType):LONGREAL;
  128. BEGIN
  129. CASE t^.kind OF
  130. | number : RETURN t^.NumberValue;
  131. | add : RETURN eval(t^.left) + eval(t^.right);
  132. | sub : RETURN eval(t^.left) - eval(t^.right);
  133. | mul : RETURN eval(t^.left) * eval(t^.right);
  134. | div : RETURN eval(t^.left) / eval(t^.right);
  135. END;
  136. END eval;
  137. VAR
  138. t:TreeType;
  139. result:LONGREAL;
  140. BEGIN
  141. LOOP
  142. IO.WrStr('Enter expression : ');
  143. t := read(main);
  144. result := eval(t);
  145. IO.WrStr(' = ');
  146. IO.WrLngReal(result, 4, 0);
  147. IO.WrLn;
  148. END;
  149. END prog8.
  150.