compiler.frm 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. MODULE -->Grammar;
  2. (* Minimal main module for the M2c Modula-2 compiler (Coco/R).
  3. Assumes the FileIO/Storage I/O libraries and the generated
  4. <Grammar>S (scanner) and <Grammar>P (parser) modules. *)
  5. FROM -->Scanner IMPORT lst, src, errors, Error, CharAt;
  6. FROM -->Parser IMPORT Parse, Successful;
  7. IMPORT
  8. Strings, Storage, SYSTEM, FileIO;
  9. TYPE
  10. INT32 = FileIO.INT32 (* 32 bit integers needed *);
  11. MODULE ListHandler;
  12. (* ------------------- Source Listing and Error handler -------------- *)
  13. FROM FileIO IMPORT CR, LF, EOF, WriteString, Write, WriteLn, WriteInt, Long0;
  14. FROM Storage IMPORT ALLOCATE;
  15. FROM SYSTEM IMPORT TSIZE;
  16. IMPORT lst, CharAt, errors, INT32;
  17. EXPORT StoreError, PrintListing;
  18. TYPE
  19. Err = POINTER TO ErrDesc;
  20. ErrDesc = RECORD
  21. nr, line, col: INTEGER;
  22. next: Err
  23. END;
  24. CONST
  25. tab = 11C;
  26. VAR
  27. firstErr, lastErr: Err;
  28. Extra: INTEGER;
  29. PROCEDURE StoreError (nr, line, col: INTEGER; pos: INT32);
  30. (* Store an error message for later printing *)
  31. VAR
  32. nextErr: Err;
  33. BEGIN
  34. ALLOCATE(nextErr, TSIZE(ErrDesc));
  35. nextErr^.nr := nr; nextErr^.line := line; nextErr^.col := col;
  36. nextErr^.next := NIL;
  37. IF firstErr = NIL
  38. THEN firstErr := nextErr
  39. ELSE lastErr^.next := nextErr
  40. END;
  41. lastErr := nextErr;
  42. INC(errors)
  43. END StoreError;
  44. PROCEDURE GetLine (VAR pos: INT32;
  45. VAR line: ARRAY OF CHAR;
  46. VAR eof: BOOLEAN);
  47. (* Read a source line. Return empty line if eof *)
  48. VAR
  49. ch: CHAR;
  50. i: CARDINAL;
  51. BEGIN
  52. i := 0; eof := FALSE; ch := CharAt(pos); INC(pos);
  53. WHILE (ch # CR) & (ch # LF) & (ch # EOF) DO
  54. line[i] := ch; INC(i); ch := CharAt(pos); INC(pos);
  55. END;
  56. eof := (i = 0) & (ch = EOF); line[i] := 0C;
  57. IF ch = CR THEN (* check for MsDos *)
  58. ch := CharAt(pos);
  59. IF ch = LF THEN INC(pos); Extra := 0 END
  60. END
  61. END GetLine;
  62. PROCEDURE PrintErr (line: ARRAY OF CHAR; nr, col: INTEGER);
  63. (* Print an error message *)
  64. PROCEDURE Msg (s: ARRAY OF CHAR);
  65. BEGIN
  66. WriteString(lst, s)
  67. END Msg;
  68. PROCEDURE Pointer;
  69. VAR
  70. i: INTEGER;
  71. BEGIN
  72. WriteString(lst, "***** ");
  73. i := 0;
  74. WHILE i < col + Extra - 2 DO
  75. IF line[i] = tab
  76. THEN Write(lst, tab)
  77. ELSE Write(lst, ' ')
  78. END;
  79. INC(i)
  80. END;
  81. WriteString(lst, "^ ")
  82. END Pointer;
  83. BEGIN
  84. Pointer;
  85. CASE nr OF
  86. -->Errors
  87. (* add customized cases here *)
  88. | 202: Msg("module name mismatch")
  89. ELSE Msg("Error: "); WriteInt(lst, nr, 0);
  90. END;
  91. WriteLn(lst)
  92. END PrintErr;
  93. PROCEDURE PrintListing;
  94. (* Print a source listing with error messages *)
  95. VAR
  96. nextErr: Err;
  97. eof: BOOLEAN;
  98. lnr, errC: INTEGER;
  99. srcPos: INT32;
  100. line: ARRAY [0 .. 255] OF CHAR;
  101. BEGIN
  102. WriteString(lst, "Listing:");
  103. WriteLn(lst); WriteLn(lst);
  104. srcPos := 0; nextErr := firstErr;
  105. GetLine(srcPos, line, eof); lnr := 1; errC := 0;
  106. WHILE ~ eof DO
  107. WriteInt(lst, lnr, 5); WriteString(lst, " ");
  108. WriteString(lst, line); WriteLn(lst);
  109. WHILE (nextErr # NIL) & (nextErr^.line = lnr) DO
  110. PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
  111. nextErr := nextErr^.next
  112. END;
  113. GetLine(srcPos, line, eof); INC(lnr);
  114. END;
  115. IF nextErr # NIL THEN
  116. WriteInt(lst, lnr, 5); WriteLn(lst);
  117. WHILE nextErr # NIL DO
  118. PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
  119. nextErr := nextErr^.next
  120. END
  121. END;
  122. WriteLn(lst);
  123. WriteInt(lst, errC, 5); WriteString(lst, " error");
  124. IF errC # 1 THEN Write(lst, 's') END;
  125. WriteLn(lst); WriteLn(lst); WriteLn(lst);
  126. END PrintListing;
  127. BEGIN
  128. firstErr := NIL; Extra := 1;
  129. END ListHandler;
  130. (* --------------------------- main module ------------------------------- *)
  131. PROCEDURE ChangeExtension (oldName, Ext: ARRAY OF CHAR;
  132. VAR newName: ARRAY OF CHAR);
  133. (* Constructs newName by replacing the extension of oldName with Ext. *)
  134. VAR
  135. i, l: CARDINAL;
  136. BEGIN
  137. Strings.Assign(oldName, newName);
  138. i := LENGTH(oldName); l := i;
  139. WHILE (i > 0) & (oldName[i -1] # '.')
  140. & (oldName[i -1] # '\') & (oldName[i -1] # '/') DO
  141. DEC(i)
  142. END;
  143. IF (i > 0) & (oldName[i-1] = '.') THEN
  144. Strings.Delete(newName, i - 1, l + 1 - i)
  145. END;
  146. IF Ext[0] = '.' THEN Strings.Delete(Ext, 0, 1) END;
  147. Strings.Append(".", newName);
  148. Strings.Append(Ext, newName)
  149. END ChangeExtension;
  150. VAR
  151. sourceName, listName: ARRAY [0 .. 255] OF CHAR;
  152. BEGIN
  153. (* check on correct parameter usage *)
  154. FileIO.NextParameter(sourceName);
  155. IF sourceName[0] = 0C THEN
  156. FileIO.WriteString(FileIO.StdOut, "No input file specified");
  157. HALT
  158. END;
  159. (* open the source file - Scanner.src *)
  160. FileIO.Open(src, sourceName, FALSE);
  161. IF ~ FileIO.Okay THEN
  162. FileIO.WriteString(FileIO.StdOut, "Could not open input file");
  163. FileIO.WriteLn(FileIO.StdOut);
  164. HALT
  165. END;
  166. (* open the output file for the source listing - Scanner.lst *)
  167. ChangeExtension(sourceName, ".LST", listName);
  168. FileIO.Open(lst, listName, TRUE);
  169. IF ~ FileIO.Okay THEN
  170. FileIO.WriteString(FileIO.StdOut, "Could not open listing file");
  171. FileIO.WriteLn(FileIO.StdOut);
  172. (* default Scanner.lst to screen *) lst := FileIO.StdOut;
  173. END;
  174. (* install error reporting procedure - Scanner.Error *)
  175. Error := StoreError;
  176. (* instigate the compilation - Parser.Parse *)
  177. FileIO.WriteString(FileIO.StdOut, "Parsing"); FileIO.WriteLn(FileIO.StdOut);
  178. Parse;
  179. (* generate the source listing on lst file *)
  180. PrintListing;
  181. IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
  182. (* examine the outcome *)
  183. IF NOT Successful()
  184. THEN
  185. FileIO.WriteString(FileIO.StdOut, "Incorrect source");
  186. ELSE
  187. FileIO.WriteString(FileIO.StdOut, "Parsed correctly");
  188. END;
  189. END -->Grammar.