Pascal.mod 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. MODULE Pascal;
  2. (* This is an example of a rudimentary main module for use with COCO/R.
  3. It assumes the FileIO/Storage I/O libraries (as supplied with this
  4. project) are available.
  5. The auxiliary modules <Grammar>S (scanner) and <Grammar>P (parser)
  6. are assumed to have been constructed with COCO/R compiler generator. *)
  7. FROM PascalS IMPORT lst, src, errors, Error, CharAt;
  8. FROM PascalP IMPORT Parse, Successful;
  9. IMPORT
  10. Strings, Storage, SYSTEM, FileIO;
  11. (* and any others needed *)
  12. TYPE
  13. INT32 = FileIO.INT32 (* 32 bit integers needed *);
  14. MODULE ListHandler;
  15. (* ------------------- Source Listing and Error handler -------------- *)
  16. FROM FileIO IMPORT CR, LF, EOF, WriteString, Write, WriteLn, WriteInt, Long0;
  17. FROM Storage IMPORT ALLOCATE;
  18. FROM SYSTEM IMPORT TSIZE;
  19. IMPORT lst, CharAt, errors, INT32;
  20. EXPORT StoreError, PrintListing;
  21. TYPE
  22. Err = POINTER TO ErrDesc;
  23. ErrDesc = RECORD
  24. nr, line, col: INTEGER;
  25. next: Err
  26. END;
  27. CONST
  28. tab = 11C;
  29. VAR
  30. firstErr, lastErr: Err;
  31. Extra: INTEGER;
  32. PROCEDURE StoreError (nr, line, col: INTEGER; pos: INT32);
  33. (* Store an error message for later printing *)
  34. VAR
  35. nextErr: Err;
  36. BEGIN
  37. ALLOCATE(nextErr, TSIZE(ErrDesc));
  38. nextErr^.nr := nr; nextErr^.line := line; nextErr^.col := col;
  39. nextErr^.next := NIL;
  40. IF firstErr = NIL
  41. THEN firstErr := nextErr
  42. ELSE lastErr^.next := nextErr
  43. END;
  44. lastErr := nextErr;
  45. INC(errors)
  46. END StoreError;
  47. PROCEDURE GetLine (VAR pos: INT32;
  48. VAR line: ARRAY OF CHAR;
  49. VAR eof: BOOLEAN);
  50. (* Read a source line. Return empty line if eof *)
  51. VAR
  52. ch: CHAR;
  53. i: CARDINAL;
  54. BEGIN
  55. i := 0; eof := FALSE; ch := CharAt(pos); INC(pos);
  56. WHILE (ch # CR) & (ch # LF) & (ch # EOF) DO
  57. line[i] := ch; INC(i); ch := CharAt(pos); INC(pos);
  58. END;
  59. eof := (i = 0) & (ch = EOF); line[i] := 0C;
  60. IF ch = CR THEN (* check for MsDos *)
  61. ch := CharAt(pos);
  62. IF ch = LF THEN INC(pos); Extra := 0 END
  63. END
  64. END GetLine;
  65. PROCEDURE PrintErr (line: ARRAY OF CHAR; nr, col: INTEGER);
  66. (* Print an error message *)
  67. PROCEDURE Msg (s: ARRAY OF CHAR);
  68. BEGIN
  69. WriteString(lst, s)
  70. END Msg;
  71. PROCEDURE Pointer;
  72. VAR
  73. i: INTEGER;
  74. BEGIN
  75. WriteString(lst, "***** ");
  76. i := 0;
  77. WHILE i < col + Extra - 2 DO
  78. IF line[i] = tab
  79. THEN Write(lst, tab)
  80. ELSE Write(lst, ' ')
  81. END;
  82. INC(i)
  83. END;
  84. WriteString(lst, "^ ")
  85. END Pointer;
  86. BEGIN
  87. Pointer;
  88. CASE nr OF
  89. 0: Msg("EOF expected")
  90. | 1: Msg("identifier expected")
  91. | 2: Msg("integer expected")
  92. | 3: Msg("real expected")
  93. | 4: Msg("string expected")
  94. | 5: Msg("'PROGRAM' expected")
  95. | 6: Msg("';' expected")
  96. | 7: Msg("'.' expected")
  97. | 8: Msg("'(' expected")
  98. | 9: Msg("')' expected")
  99. | 10: Msg("'LABEL' expected")
  100. | 11: Msg("',' expected")
  101. | 12: Msg("'CONST' expected")
  102. | 13: Msg("'=' expected")
  103. | 14: Msg("'+' expected")
  104. | 15: Msg("'-' expected")
  105. | 16: Msg("'TYPE' expected")
  106. | 17: Msg("'PACKED' expected")
  107. | 18: Msg("'^' expected")
  108. | 19: Msg("'..' expected")
  109. | 20: Msg("'ARRAY' expected")
  110. | 21: Msg("'[' expected")
  111. | 22: Msg("']' expected")
  112. | 23: Msg("'OF' expected")
  113. | 24: Msg("'RECORD' expected")
  114. | 25: Msg("'END' expected")
  115. | 26: Msg("'SET' expected")
  116. | 27: Msg("'FILE' expected")
  117. | 28: Msg("':' expected")
  118. | 29: Msg("'CASE' expected")
  119. | 30: Msg("'VAR' expected")
  120. | 31: Msg("'PROCEDURE' expected")
  121. | 32: Msg("'FUNCTION' expected")
  122. | 33: Msg("'FORWARD' expected")
  123. | 34: Msg("'BEGIN' expected")
  124. | 35: Msg("':=' expected")
  125. | 36: Msg("'GOTO' expected")
  126. | 37: Msg("'WHILE' expected")
  127. | 38: Msg("'DO' expected")
  128. | 39: Msg("'REPEAT' expected")
  129. | 40: Msg("'UNTIL' expected")
  130. | 41: Msg("'IF' expected")
  131. | 42: Msg("'THEN' expected")
  132. | 43: Msg("'ELSE' expected")
  133. | 44: Msg("'FOR' expected")
  134. | 45: Msg("'TO' expected")
  135. | 46: Msg("'DOWNTO' expected")
  136. | 47: Msg("'WITH' expected")
  137. | 48: Msg("'<' expected")
  138. | 49: Msg("'>' expected")
  139. | 50: Msg("'<=' expected")
  140. | 51: Msg("'>=' expected")
  141. | 52: Msg("'<>' expected")
  142. | 53: Msg("'IN' expected")
  143. | 54: Msg("'OR' expected")
  144. | 55: Msg("'*' expected")
  145. | 56: Msg("'/' expected")
  146. | 57: Msg("'DIV' expected")
  147. | 58: Msg("'MOD' expected")
  148. | 59: Msg("'AND' expected")
  149. | 60: Msg("'NOT' expected")
  150. | 61: Msg("'NIL' expected")
  151. | 62: Msg("not expected")
  152. | 63: Msg("invalid UnsignedLiteral")
  153. | 64: Msg("invalid MulOp")
  154. | 65: Msg("invalid Factor")
  155. | 66: Msg("invalid AddOp")
  156. | 67: Msg("invalid RelOp")
  157. | 68: Msg("invalid SimpleExpression")
  158. | 69: Msg("invalid ForStatement")
  159. | 70: Msg("invalid AssignmentOrCall")
  160. | 71: Msg("invalid ParamType")
  161. | 72: Msg("invalid FormalSection")
  162. | 73: Msg("invalid Body")
  163. | 74: Msg("invalid StructType")
  164. | 75: Msg("invalid SimpleType")
  165. | 76: Msg("invalid Type")
  166. | 77: Msg("invalid UnsignedNumber")
  167. | 78: Msg("invalid Constant")
  168. | 79: Msg("invalid Constant")
  169. | 80: Msg("invalid ProcDeclarations")
  170. (* add customized cases here *)
  171. ELSE Msg("Error: "); WriteInt(lst, nr, 0);
  172. END;
  173. WriteLn(lst)
  174. END PrintErr;
  175. PROCEDURE PrintListing;
  176. (* Print a source listing with error messages *)
  177. VAR
  178. nextErr: Err;
  179. eof: BOOLEAN;
  180. lnr, errC: INTEGER;
  181. srcPos: INT32;
  182. line: ARRAY [0 .. 255] OF CHAR;
  183. BEGIN
  184. WriteString(lst, "Listing:");
  185. WriteLn(lst); WriteLn(lst);
  186. srcPos := 0; nextErr := firstErr;
  187. GetLine(srcPos, line, eof); lnr := 1; errC := 0;
  188. WHILE ~ eof DO
  189. WriteInt(lst, lnr, 5); WriteString(lst, " ");
  190. WriteString(lst, line); WriteLn(lst);
  191. WHILE (nextErr # NIL) & (nextErr^.line = lnr) DO
  192. PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
  193. nextErr := nextErr^.next
  194. END;
  195. GetLine(srcPos, line, eof); INC(lnr);
  196. END;
  197. IF nextErr # NIL THEN
  198. WriteInt(lst, lnr, 5); WriteLn(lst);
  199. WHILE nextErr # NIL DO
  200. PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
  201. nextErr := nextErr^.next
  202. END
  203. END;
  204. WriteLn(lst);
  205. WriteInt(lst, errC, 5); WriteString(lst, " error");
  206. IF errC # 1 THEN Write(lst, 's') END;
  207. WriteLn(lst); WriteLn(lst); WriteLn(lst);
  208. END PrintListing;
  209. BEGIN
  210. firstErr := NIL; Extra := 1;
  211. END ListHandler;
  212. (* --------------------------- main module ------------------------------- *)
  213. PROCEDURE ChangeExtension (oldName, Ext: ARRAY OF CHAR;
  214. VAR newName: ARRAY OF CHAR);
  215. (* Constructs newName as complete file name by appending ext to oldName
  216. Examples: (assume ext = "EXT")
  217. old.any ==> old.EXT
  218. old ==> old.EXT
  219. This is not a file renaming facility, merely a string manipulation
  220. routine. *)
  221. VAR
  222. i, l: CARDINAL;
  223. BEGIN
  224. Strings.Assign(oldName, newName);
  225. i := LENGTH(oldName); l := i;
  226. WHILE (i > 0) & (oldName[i -1] # '.')
  227. & (oldName[i -1] # '\') & (oldName[i -1] # '/') DO
  228. DEC(i)
  229. END;
  230. IF (i > 0) & (oldName[i-1] = '.') THEN
  231. Strings.Delete(newName, i - 1, l + 1 - i)
  232. END;
  233. IF Ext[0] = '.' THEN Strings.Delete(Ext, 0, 1) END;
  234. Strings.Append(".", newName);
  235. Strings.Append(Ext, newName)
  236. END ChangeExtension;
  237. VAR
  238. sourceName, listName: ARRAY [0 .. 255] OF CHAR;
  239. BEGIN
  240. (* check on correct parameter usage *)
  241. FileIO.NextParameter(sourceName);
  242. IF sourceName[0] = 0C THEN
  243. FileIO.WriteString(FileIO.StdOut, "No input file specified");
  244. HALT
  245. END;
  246. (* open the source file - Scanner.src *)
  247. FileIO.Open(src, sourceName, FALSE);
  248. IF ~ FileIO.Okay THEN
  249. FileIO.WriteString(FileIO.StdOut, "Could not open input file");
  250. FileIO.WriteLn(FileIO.StdOut);
  251. HALT
  252. END;
  253. (* open the output file for the source listing - Scanner.lst *)
  254. ChangeExtension(sourceName, ".LST", listName);
  255. FileIO.Open(lst, listName, TRUE);
  256. IF ~ FileIO.Okay THEN
  257. FileIO.WriteString(FileIO.StdOut, "Could not open listing file");
  258. FileIO.WriteLn(FileIO.StdOut);
  259. (* default Scanner.lst to screen *) lst := FileIO.StdOut;
  260. END;
  261. (* install error reporting procedure - Scanner.Error *)
  262. Error := StoreError;
  263. (* instigate the compilation - Parser.Parse *)
  264. FileIO.WriteString(FileIO.StdOut, "Parsing"); FileIO.WriteLn(FileIO.StdOut);
  265. Parse;
  266. (* generate the source listing on lst file *)
  267. PrintListing;
  268. IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
  269. (* examine the outcome *)
  270. IF NOT Successful()
  271. THEN
  272. FileIO.WriteString(FileIO.StdOut, "Incorrect source");
  273. ELSE
  274. FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
  275. (* ++++++++ Add further activities if required ++++++++++ *)
  276. END;
  277. END Pascal.