compiler.frm 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. MODULE -->Grammar;
  2. (* This is an example of a rudimentary main module for use with COCO/R.
  3. It assumes ISO I/O libraries are available.
  4. The auxiliary modules <Grammar>S (scanner) and <Grammar>P (parser)
  5. are assumed to have been constructed with COCO/R compiler generator. *)
  6. FROM -->Scanner IMPORT lst, src, errors, Error, CharAt;
  7. FROM -->Parser IMPORT Parse, Successful;
  8. IMPORT
  9. ProgramArgs, Strings,
  10. SYSTEM, Storage, TextIO, WholeIO, StdChans, SeqFile, ChanConsts, IOChan;
  11. (* and any others needed *)
  12. TYPE
  13. INT32 = INTEGER (* 32 bit integers needed *);
  14. MODULE ListHandler;
  15. (* ------------------- Source Listing and Error handler -------------- *)
  16. IMPORT WholeIO, TextIO, Storage, SYSTEM;
  17. IMPORT lst, CharAt, errors, INT32;
  18. EXPORT StoreError, PrintListing;
  19. CONST
  20. CR = 15C;
  21. LF = 12C;
  22. EOF = 0C;
  23. TYPE
  24. Err = POINTER TO ErrDesc;
  25. ErrDesc = RECORD
  26. nr, line, col: INTEGER;
  27. next: Err
  28. END;
  29. CONST
  30. tab = 11C;
  31. VAR
  32. firstErr, lastErr: Err;
  33. Extra: INTEGER;
  34. PROCEDURE StoreError (nr, line, col: INTEGER; pos: INT32);
  35. (* Store an error message for later printing *)
  36. VAR
  37. nextErr: Err;
  38. BEGIN
  39. Storage.ALLOCATE(nextErr, SYSTEM.TSIZE(ErrDesc));
  40. nextErr^.nr := nr; nextErr^.line := line; nextErr^.col := col;
  41. nextErr^.next := NIL;
  42. IF firstErr = NIL
  43. THEN firstErr := nextErr
  44. ELSE lastErr^.next := nextErr
  45. END;
  46. lastErr := nextErr;
  47. INC(errors)
  48. END StoreError;
  49. PROCEDURE GetLine (VAR pos: INT32;
  50. VAR line: ARRAY OF CHAR;
  51. VAR eof: BOOLEAN);
  52. (* Read a source line. Return empty line if eof *)
  53. VAR
  54. ch: CHAR;
  55. i: CARDINAL;
  56. BEGIN
  57. i := 0; eof := FALSE; ch := CharAt(pos); INC(pos);
  58. WHILE (ch # CR) & (ch # LF) & (ch # EOF) DO
  59. line[i] := ch; INC(i); ch := CharAt(pos); INC(pos);
  60. END;
  61. eof := (i = 0) & (ch = EOF); line[i] := 0C;
  62. IF ch = CR THEN (* check for MsDos *)
  63. ch := CharAt(pos);
  64. IF ch = LF THEN INC(pos); Extra := 0 END
  65. END
  66. END GetLine;
  67. PROCEDURE PrintErr (line: ARRAY OF CHAR; nr, col: INTEGER);
  68. (* Print an error message *)
  69. PROCEDURE Msg (s: ARRAY OF CHAR);
  70. BEGIN
  71. TextIO.WriteString(lst, s)
  72. END Msg;
  73. PROCEDURE Pointer;
  74. VAR
  75. i: INTEGER;
  76. BEGIN
  77. TextIO.WriteString(lst, "***** ");
  78. i := 0;
  79. WHILE i < col + Extra - 2 DO
  80. IF line[i] = tab
  81. THEN TextIO.WriteChar(lst, tab)
  82. ELSE TextIO.WriteChar(lst, ' ')
  83. END;
  84. INC(i)
  85. END;
  86. TextIO.WriteString(lst, "^ ")
  87. END Pointer;
  88. BEGIN
  89. Pointer;
  90. CASE nr OF
  91. -->Errors
  92. (* add customized cases here *)
  93. ELSE Msg("Error: "); WholeIO.WriteInt(lst, nr, 0);
  94. END;
  95. TextIO.WriteLn(lst)
  96. END PrintErr;
  97. PROCEDURE PrintListing;
  98. (* Print a source listing with error messages *)
  99. VAR
  100. nextErr: Err;
  101. eof: BOOLEAN;
  102. lnr, errC: INTEGER;
  103. srcPos: INT32;
  104. line: ARRAY [0 .. 255] OF CHAR;
  105. BEGIN
  106. TextIO.WriteString(lst, "Listing:");
  107. TextIO.WriteLn(lst); TextIO.WriteLn(lst);
  108. srcPos := 0; nextErr := firstErr;
  109. GetLine(srcPos, line, eof); lnr := 1; errC := 0;
  110. WHILE ~ eof DO
  111. WholeIO.WriteInt(lst, lnr, 5); TextIO.WriteString(lst, " ");
  112. TextIO.WriteString(lst, line); TextIO.WriteLn(lst);
  113. WHILE (nextErr # NIL) & (nextErr^.line = lnr) DO
  114. PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
  115. nextErr := nextErr^.next
  116. END;
  117. GetLine(srcPos, line, eof); INC(lnr);
  118. END;
  119. IF nextErr # NIL THEN
  120. WholeIO.WriteInt(lst, lnr, 5); TextIO.WriteLn(lst);
  121. WHILE nextErr # NIL DO
  122. PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
  123. nextErr := nextErr^.next
  124. END
  125. END;
  126. TextIO.WriteLn(lst);
  127. WholeIO.WriteInt(lst, errC, 5); TextIO.WriteString(lst, " error");
  128. IF errC # 1 THEN TextIO.WriteChar(lst, "s") END;
  129. TextIO.WriteLn(lst); TextIO.WriteLn(lst); TextIO.WriteLn(lst);
  130. END PrintListing;
  131. BEGIN
  132. firstErr := NIL; Extra := 1;
  133. END ListHandler;
  134. (* --------------------------- main module ------------------------------- *)
  135. PROCEDURE ChangeExtension (oldName, Ext: ARRAY OF CHAR;
  136. VAR newName: ARRAY OF CHAR);
  137. (* Constructs newName as complete file name by appending ext to oldName
  138. Examples: (assume ext = "EXT")
  139. old.any ==> old.EXT
  140. old ==> old.EXT
  141. This is not a file renaming facility, merely a string manipulation
  142. routine. *)
  143. VAR
  144. i, l: CARDINAL;
  145. BEGIN
  146. Strings.Assign(oldName, newName);
  147. i := LENGTH(oldName); l := i;
  148. WHILE (i > 0) & (oldName[i -1] # '.')
  149. & (oldName[i -1] # '\') & (oldName[i -1] # '/') DO
  150. DEC(i)
  151. END;
  152. IF (i > 0) & (oldName[i-1] = '.') THEN
  153. Strings.Delete(newName, i - 1, l + 1 - i)
  154. END;
  155. IF Ext[0] = '.' THEN Strings.Delete(Ext, 0, 1) END;
  156. Strings.Append(".", newName);
  157. Strings.Append(Ext, newName)
  158. END ChangeExtension;
  159. VAR
  160. sourceName, listName: ARRAY [0 .. 255] OF CHAR;
  161. StdOut: IOChan.ChanId;
  162. res: ChanConsts.OpenResults;
  163. BEGIN
  164. StdOut := StdChans.StdOutChan();
  165. (* check on correct parameter usage *)
  166. (* you may need ProgramArgs.NextArg(); to skip program name *)
  167. IF ProgramArgs.IsArgPresent()
  168. THEN
  169. TextIO.ReadToken(ProgramArgs.ArgChan(), sourceName);
  170. ELSE
  171. TextIO.WriteString(StdOut, "No input file specified");
  172. HALT
  173. END;
  174. (* open the source file - Scanner.src *)
  175. SeqFile.OpenRead(src, sourceName, SeqFile.raw + SeqFile.old + SeqFile.read, res);
  176. IF res # SeqFile.opened THEN
  177. TextIO.WriteString(StdOut, "Could not open input file");
  178. TextIO.WriteLn(StdOut);
  179. HALT
  180. END;
  181. (* open the output file for the source listing - Scanner.lst *)
  182. ChangeExtension(sourceName, ".LST", listName);
  183. SeqFile.OpenWrite(lst, listName, SeqFile.write + SeqFile.old, res);
  184. IF res # SeqFile.opened THEN
  185. TextIO.WriteString(StdOut, "Could not open listing file");
  186. TextIO.WriteLn(StdOut);
  187. (* default Scanner.lst to screen *) lst := StdOut;
  188. END;
  189. (* install error reporting procedure - Scanner.Error *)
  190. Error := StoreError;
  191. (* instigate the compilation - Parser.Parse *)
  192. TextIO.WriteString(StdOut, "Parsing"); TextIO.WriteLn(StdOut);
  193. Parse;
  194. (* generate the source listing on lst file *)
  195. PrintListing;
  196. IF lst # StdOut THEN SeqFile.Close(lst) END;
  197. (* examine the outcome *)
  198. IF NOT Successful()
  199. THEN
  200. TextIO.WriteString(StdOut, "Incorrect source");
  201. ELSE
  202. TextIO.WriteString(StdOut, "Parsed correctly");
  203. (* ++++++++ Add further activities if required ++++++++++ *)
  204. END;
  205. END -->Grammar.