compile2.frm 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. MODULE -->Grammar;
  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 -->Scanner IMPORT lst, src, errors, Error, CharAt;
  8. FROM -->Parser 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. TabSize = 8;
  30. VAR
  31. firstErr, lastErr: Err;
  32. Extra: INTEGER;
  33. PROCEDURE StoreError (nr, line, col: INTEGER; pos: INT32);
  34. (* Store an error message for later printing *)
  35. VAR
  36. nextErr: Err;
  37. BEGIN
  38. ALLOCATE(nextErr, TSIZE(ErrDesc));
  39. nextErr^.nr := nr; nextErr^.line := line; nextErr^.col := col;
  40. nextErr^.next := NIL;
  41. IF firstErr = NIL
  42. THEN firstErr := nextErr
  43. ELSE lastErr^.next := nextErr
  44. END;
  45. lastErr := nextErr;
  46. INC(errors)
  47. END StoreError;
  48. PROCEDURE GetLine (VAR pos: INT32;
  49. VAR line: ARRAY OF CHAR;
  50. VAR eof: BOOLEAN);
  51. (* Read a source line. Return empty line if eof *)
  52. VAR
  53. ch: CHAR;
  54. i: CARDINAL;
  55. BEGIN
  56. i := 0; eof := FALSE; ch := CharAt(pos); INC(pos);
  57. WHILE (ch # CR) & (ch # LF) & (ch # EOF) DO
  58. line[i] := ch; INC(i); ch := CharAt(pos); INC(pos);
  59. END;
  60. eof := (i = 0) & (ch = EOF); line[i] := 0C;
  61. IF ch = CR THEN (* check for MsDos *)
  62. ch := CharAt(pos);
  63. IF ch = LF THEN INC(pos); Extra := 0 END
  64. END
  65. END GetLine;
  66. PROCEDURE WriteLine (line: ARRAY OF CHAR);
  67. VAR
  68. i, col, j: CARDINAL;
  69. BEGIN
  70. col := 1;
  71. i := 0;
  72. WHILE line[i] # 0C DO
  73. IF line[i] = tab
  74. THEN
  75. FOR j := 1 TO TabSize - (col MOD TabSize) + 1 DO
  76. Write(lst, ' '); INC(col);
  77. END
  78. ELSE Write(lst, line[i]); INC(col)
  79. END;
  80. INC(i)
  81. END;
  82. WriteLn(lst);
  83. END WriteLine;
  84. PROCEDURE PrintErr (line: ARRAY OF CHAR; nr, col: INTEGER);
  85. (* Print an error message *)
  86. PROCEDURE Msg (s: ARRAY OF CHAR);
  87. BEGIN
  88. WriteString(lst, s)
  89. END Msg;
  90. PROCEDURE Pointer;
  91. VAR
  92. i: INTEGER;
  93. c, j: CARDINAL;
  94. BEGIN
  95. WriteString(lst, "***** ");
  96. i := 0; c := 1;
  97. WHILE i < col + Extra - 2 DO
  98. IF line[i] = tab
  99. THEN
  100. FOR j := 1 TO TabSize - (c MOD TabSize) + 1 DO
  101. Write(lst, ' '); INC(c);
  102. END
  103. ELSE Write(lst, ' '); INC(c)
  104. END;
  105. INC(i)
  106. END;
  107. WriteString(lst, "^ ")
  108. END Pointer;
  109. BEGIN
  110. Pointer;
  111. CASE nr OF
  112. -->Errors
  113. (* add customized cases here *)
  114. ELSE Msg("Error: "); WriteInt(lst, nr, 0);
  115. END;
  116. WriteLn(lst)
  117. END PrintErr;
  118. PROCEDURE PrintListing;
  119. (* Print a source listing with error messages *)
  120. VAR
  121. nextErr: Err;
  122. eof: BOOLEAN;
  123. lnr, errC: INTEGER;
  124. srcPos: INT32;
  125. line: ARRAY [0 .. 255] OF CHAR;
  126. BEGIN
  127. WriteString(lst, "Listing:");
  128. WriteLn(lst); WriteLn(lst);
  129. srcPos := 0; nextErr := firstErr;
  130. GetLine(srcPos, line, eof); lnr := 1; errC := 0;
  131. WHILE ~ eof DO
  132. WriteInt(lst, lnr, 5); WriteString(lst, " ");
  133. WriteLine(line);
  134. WHILE (nextErr # NIL) & (nextErr^.line = lnr) DO
  135. PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
  136. nextErr := nextErr^.next
  137. END;
  138. GetLine(srcPos, line, eof); INC(lnr);
  139. END;
  140. IF nextErr # NIL THEN
  141. WriteInt(lst, lnr, 5); WriteLn(lst);
  142. WHILE nextErr # NIL DO
  143. PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
  144. nextErr := nextErr^.next
  145. END
  146. END;
  147. WriteLn(lst);
  148. WriteInt(lst, errC, 5); WriteString(lst, " error");
  149. IF errC # 1 THEN Write(lst, "s") END;
  150. WriteLn(lst); WriteLn(lst); WriteLn(lst);
  151. END PrintListing;
  152. BEGIN
  153. firstErr := NIL; Extra := 1;
  154. END ListHandler;
  155. (* --------------------------- main module ------------------------------- *)
  156. PROCEDURE ChangeExtension (oldName, Ext: ARRAY OF CHAR;
  157. VAR newName: ARRAY OF CHAR);
  158. (* Constructs newName as complete file name by appending ext to oldName
  159. Examples: (assume ext = "EXT")
  160. old.any ==> old.EXT
  161. old ==> old.EXT
  162. This is not a file renaming facility, merely a string manipulation
  163. routine. *)
  164. VAR
  165. i, l: CARDINAL;
  166. BEGIN
  167. Strings.Assign(oldName, newName);
  168. i := LENGTH(oldName); l := i;
  169. WHILE (i > 0) & (oldName[i -1] # '.')
  170. & (oldName[i -1] # '\') & (oldName[i -1] # '/') DO
  171. DEC(i)
  172. END;
  173. IF (i > 0) & (oldName[i-1] = '.') THEN
  174. Strings.Delete(newName, i - 1, l + 1 - i)
  175. END;
  176. IF Ext[0] = '.' THEN Strings.Delete(Ext, 0, 1) END;
  177. Strings.Append(".", newName);
  178. Strings.Append(Ext, newName)
  179. END ChangeExtension;
  180. VAR
  181. sourceName, listName: ARRAY [0 .. 255] OF CHAR;
  182. BEGIN
  183. (* check on correct parameter usage *)
  184. FileIO.NextParameter(sourceName);
  185. IF sourceName[0] = 0C THEN
  186. FileIO.WriteString(FileIO.StdOut, "No input file specified");
  187. HALT
  188. END;
  189. (* open the source file - Scanner.src *)
  190. FileIO.Open(src, sourceName, FALSE);
  191. IF ~ FileIO.Okay THEN
  192. FileIO.WriteString(FileIO.StdOut, "Could not open input file");
  193. FileIO.WriteLn(FileIO.StdOut);
  194. HALT
  195. END;
  196. (* open the output file for the source listing - Scanner.lst *)
  197. ChangeExtension(sourceName, ".LST", listName);
  198. FileIO.Open(lst, listName, TRUE);
  199. IF ~ FileIO.Okay THEN
  200. FileIO.WriteString(FileIO.StdOut, "Could not open listing file");
  201. FileIO.WriteLn(FileIO.StdOut);
  202. (* default Scanner.lst to screen *) lst := FileIO.StdOut;
  203. END;
  204. (* install error reporting procedure - Scanner.Error *)
  205. Error := StoreError;
  206. (* instigate the compilation - Parser.Parse *)
  207. FileIO.WriteString(FileIO.StdOut, "Parsing"); FileIO.WriteLn(FileIO.StdOut);
  208. Parse;
  209. (* generate the source listing on lst file *)
  210. PrintListing;
  211. IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
  212. (* examine the outcome *)
  213. IF NOT Successful()
  214. THEN
  215. FileIO.WriteString(FileIO.StdOut, "Incorrect source");
  216. ELSE
  217. FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
  218. (* ++++++++ Add further activities if required ++++++++++ *)
  219. END;
  220. END -->Grammar.