CPascalS.cp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. (* ==================================================================== *)
  2. (* *)
  3. (* Scanner Module for the Gardens Point Component Pascal Compiler. *)
  4. (* Copyright (c) John Gough 1999, 2000. *)
  5. (* This module was extensively modified from the scanner *)
  6. (* automatically produced by the M2 version of COCO/R, using *)
  7. (* the CPascal.atg grammar used for the JVM version of GPCP. *)
  8. (* *)
  9. (* ==================================================================== *)
  10. MODULE CPascalS;
  11. (* This is a modified version for Mburg --- it computes column positions *)
  12. (* Scanner generated by Coco/R *)
  13. IMPORT
  14. GPCPcopyright,
  15. RTS,
  16. ASCII,
  17. Console,
  18. Tok := CPascalG,
  19. GPBinFiles,
  20. GPTextFiles;
  21. CONST
  22. noSym = Tok.NOSYM; (*error token code*)
  23. (* not only for errors but also for not finished states of scanner analysis *)
  24. eof = 0X;
  25. eofByt = 0;
  26. EOL = 0AX;
  27. BlkSize = 32768;
  28. BlkNmbr = 32;
  29. asciiHT = 9X;
  30. asciiLF = EOL;
  31. CONST
  32. listAlways* = 2; (* listing control constants *)
  33. listErrOnly* = 1;
  34. listNever* = 0;
  35. TYPE
  36. BufBlk = ARRAY BlkSize OF UBYTE;
  37. Buffer = ARRAY BlkNmbr OF POINTER TO BufBlk;
  38. StartTable = ARRAY 256 OF INTEGER;
  39. (* ======================== EXPORTS ========================= *)
  40. TYPE
  41. ErrorHandler* = POINTER TO ABSTRACT RECORD END;
  42. Token* = POINTER TO RECORD
  43. sym* : INTEGER;
  44. lin* : INTEGER;
  45. col* : INTEGER;
  46. pos* : INTEGER;
  47. len* : INTEGER;
  48. dlr* : BOOLEAN;
  49. END;
  50. Span* = POINTER TO RECORD
  51. sLin*, sCol*, eLin*, eCol* : INTEGER
  52. END;
  53. (* ====================== END EXPORTS ======================= *)
  54. VAR
  55. ch: CHAR; (*current input character*)
  56. curLine: INTEGER; (*current input line (may be higher than line)*)
  57. lineStart: INTEGER; (*start position of current line*)
  58. apx: INTEGER; (*length of appendix (CONTEXT phrase)*)
  59. oldEols: INTEGER; (*number of EOLs in a comment*)
  60. bp: INTEGER; (*current position in buf*)
  61. bp0: INTEGER; (*position of current token)*)
  62. LBlkSize: INTEGER; (*BlkSize*)
  63. inputLen: INTEGER; (*source file size*)
  64. buf: Buffer; (*source buffer for low-level access*)
  65. savedBuf: Buffer;
  66. bufSaved: BOOLEAN;
  67. start: StartTable; (*start state for every character*)
  68. nextLine: INTEGER; (*line of lookahead symbol*)
  69. nextCol: INTEGER; (*column of lookahead symbol*)
  70. nextLen: INTEGER; (*length of lookahead symbol*)
  71. nextPos: INTEGER; (*file position of lookahead symbol*)
  72. spaces: INTEGER; (* ############# NEW ############## *)
  73. (* ======================== EXPORTS ========================= *)
  74. VAR
  75. src*: GPBinFiles.FILE; (*source file. To be opened by main *)
  76. lst*: GPTextFiles.FILE; (*list file. To be opened by main *)
  77. line*, col*: INTEGER; (*line and column of current symbol*)
  78. len*: INTEGER; (*length of current symbol*)
  79. pos*: INTEGER; (*file position of current symbol*)
  80. errors*: INTEGER; (*number of detected errors*)
  81. warnings*: INTEGER; (*number of detected warnings*)
  82. prevTok*: Token;
  83. ParseErr*: ErrorHandler;
  84. SemError*: ErrorHandler;
  85. (* ====================== END EXPORTS ======================= *)
  86. (* ======================== EXPORTS ========================= *)
  87. PROCEDURE (s : ErrorHandler)Report*(num : INTEGER;
  88. lin : INTEGER;
  89. col : INTEGER) ,NEW,ABSTRACT;
  90. PROCEDURE (s : ErrorHandler)RepSt1*(num : INTEGER;
  91. IN str : ARRAY OF CHAR;
  92. lin : INTEGER;
  93. col : INTEGER) ,NEW,ABSTRACT;
  94. PROCEDURE (s : ErrorHandler)RepSt2*(num : INTEGER;
  95. IN st1 : ARRAY OF CHAR;
  96. IN st2 : ARRAY OF CHAR;
  97. lin : INTEGER;
  98. col : INTEGER) ,NEW,ABSTRACT;
  99. PROCEDURE (s : Span)SpanSS*(e : Span) : Span,NEW;
  100. VAR res : Span;
  101. BEGIN
  102. IF e = NIL THEN RETURN s;
  103. ELSE
  104. NEW(res);
  105. res.sLin := s.sLin; res.eLin := e.eLin;
  106. res.sCol := s.sCol; res.eCol := e.eCol;
  107. END;
  108. RETURN res;
  109. END SpanSS;
  110. PROCEDURE mkSpanTT*(s, e : Token) : Span;
  111. VAR res : Span;
  112. BEGIN
  113. NEW(res);
  114. res.sLin := s.lin; res.eLin := e.lin;
  115. res.sCol := s.col; res.eCol := e.col + e.len;
  116. RETURN res;
  117. END mkSpanTT;
  118. PROCEDURE mkSpanT*(t : Token) : Span;
  119. VAR res : Span;
  120. BEGIN
  121. NEW(res);
  122. res.sLin := t.lin; res.eLin := t.lin;
  123. res.sCol := t.col; res.eCol := t.col + t.len;
  124. RETURN res;
  125. END mkSpanT;
  126. PROCEDURE Merge*(s, e : Span) : Span;
  127. BEGIN
  128. IF s # NIL THEN RETURN s.SpanSS(e) ELSE RETURN NIL END;
  129. END Merge;
  130. (* ====================== END EXPORTS ======================= *)
  131. PROCEDURE^ get*() : Token;
  132. (* Gets next symbol from source file *)
  133. PROCEDURE^ GetString*(pos: INTEGER; len: INTEGER; OUT name: ARRAY OF CHAR);
  134. (* Retrieves exact string of max length len from position pos in source file *)
  135. PROCEDURE^ charAt*(pos: INTEGER): CHAR;
  136. (* Returns exact character at position pos in source file *)
  137. PROCEDURE^ Reset*;
  138. (* Reads and stores source file internally *)
  139. PROCEDURE^ SkipAndGetLine*(i : INTEGER; (* indent to skip *)
  140. e : INTEGER; (* end file-pos *)
  141. VAR p : INTEGER; (* crnt file-pos *)
  142. OUT l : INTEGER; (* fetched length *)
  143. VAR s : ARRAY OF CHAR); (* output string *)
  144. (* ==================================================================== *)
  145. PROCEDURE (t : Token)DiagToken*(),NEW;
  146. VAR i : INTEGER;
  147. BEGIN
  148. Console.Write("l"); Console.WriteInt(t.lin,1); Console.Write(":");
  149. Console.Write("c"); Console.WriteInt(t.col,1); Console.WriteString(" '");
  150. FOR i := 0 TO t.len - 1 DO Console.Write(charAt(t.pos+i)) END;
  151. Console.Write("'"); Console.WriteLn;
  152. END DiagToken;
  153. PROCEDURE digitAt(pos : INTEGER) : INTEGER;
  154. VAR ch : CHAR;
  155. BEGIN
  156. ch := charAt(pos);
  157. IF (ch >= '0') & (ch <= '9') THEN RETURN ORD(ch) - ORD('0');
  158. ELSE RETURN ORD(ch) + (10 - ORD('A'));
  159. END;
  160. END digitAt;
  161. PROCEDURE getHex*(pos, len : INTEGER) : INTEGER;
  162. VAR ch : CHAR;
  163. ix : INTEGER;
  164. rslt : INTEGER;
  165. BEGIN
  166. rslt := 0;
  167. FOR ix := pos TO pos + len - 1 DO
  168. ch := charAt(ix);
  169. IF (ch >= '0') & (ch <= '9') THEN rslt := rslt * 16 + ORD(ch) - ORD('0');
  170. ELSIF (ch >= 'a') & (ch <= 'f') THEN rslt := rslt * 16 + ORD(ch) + (10 - ORD('a'));
  171. ELSIF (ch >= 'A') & (ch <= 'F') THEN rslt := rslt * 16 + ORD(ch) + (10 - ORD('A'));
  172. ELSE RETURN -237;
  173. END;
  174. END;
  175. RETURN rslt;
  176. END getHex;
  177. PROCEDURE tokToLong*(t : Token) : LONGINT;
  178. VAR long : LONGINT;
  179. last : LONGINT;
  180. indx : INTEGER;
  181. limt : INTEGER;
  182. hexD : INTEGER;
  183. ch : CHAR;
  184. BEGIN [UNCHECKED_ARITHMETIC]
  185. (*
  186. * This code requires special care.
  187. * For the CLR it would be simplest to catch overflows
  188. * in the per-character loop, and put in a rescue clause
  189. * that reported the Error-233. Unfortunately this does
  190. * not work on the JVM, so we have to catch the overflow
  191. * manually by detecting the sum wrapping to negative.
  192. *)
  193. limt := t.pos + t.len - 1;
  194. long := 0;
  195. ch := charAt(limt);
  196. IF (ch = "H") OR (ch = "L") THEN
  197. DEC(limt);
  198. FOR indx := t.pos TO limt DO
  199. hexD := digitAt(indx);
  200. long := long * 16 + hexD;
  201. IF long < 0 THEN SemError.Report(233, t.lin, t.col); RETURN 0 END;
  202. END;
  203. IF ch = "H" THEN
  204. IF RTS.hiInt(long) # 0 THEN
  205. SemError.Report(232, t.lin, t.col); RETURN 0;
  206. ELSE
  207. long := LONG(RTS.loInt(long));
  208. END;
  209. END;
  210. ELSE
  211. FOR indx := t.pos TO limt DO
  212. ch := charAt(indx);
  213. long := long * 10 + (ORD(ch) - ORD('0'));
  214. IF long < 0 THEN SemError.Report(233, t.lin, t.col); RETURN 0 END;
  215. END;
  216. END;
  217. RETURN long;
  218. END tokToLong;
  219. PROCEDURE tokToReal*(t : Token) : REAL;
  220. VAR str : ARRAY 256 OF CHAR;
  221. pOk : BOOLEAN;
  222. num : REAL;
  223. BEGIN
  224. GetString(t.pos, t.len, str);
  225. RTS.StrToRealInvar(str$, num, pOk);
  226. IF ~pOk THEN
  227. SemError.Report(45, t.lin, t.col); RETURN 0.0;
  228. ELSE
  229. RETURN num;
  230. END;
  231. END tokToReal;
  232. PROCEDURE tokToChar*(t : Token) : CHAR;
  233. VAR cOrd : LONGINT;
  234. indx : INTEGER;
  235. limt : INTEGER;
  236. hexD : INTEGER;
  237. ch : CHAR;
  238. BEGIN
  239. limt := t.pos + t.len - 2;
  240. cOrd := 0;
  241. FOR indx := t.pos TO limt DO
  242. hexD := digitAt(indx);
  243. cOrd := cOrd * 16 + hexD;
  244. END;
  245. (* RANGE CHECK HERE *)
  246. RETURN CHR(cOrd);
  247. END tokToChar;
  248. (* ====================== END EXPORTS ======================= *)
  249. PROCEDURE NextCh;
  250. (* Return global variable ch *)
  251. BEGIN
  252. INC(bp); ch := charAt(bp);
  253. IF ch = asciiHT THEN
  254. INC(spaces,8); DEC(spaces,spaces MOD 8);
  255. ELSE
  256. INC(spaces);
  257. END;
  258. IF ch = EOL THEN INC(curLine); lineStart := bp; spaces := 0 END
  259. END NextCh;
  260. (* ==================================================================== *)
  261. PROCEDURE comment (): BOOLEAN;
  262. VAR
  263. level, startLine: INTEGER;
  264. oldLineStart : INTEGER;
  265. oldSpaces : INTEGER;
  266. BEGIN
  267. level := 1; startLine := curLine;
  268. oldLineStart := lineStart; oldSpaces := spaces;
  269. IF (ch = "(") THEN
  270. NextCh;
  271. IF (ch = "*") THEN
  272. NextCh;
  273. LOOP
  274. IF (ch = "*") THEN
  275. NextCh;
  276. IF (ch = ")") THEN
  277. DEC(level); NextCh;
  278. IF level = 0 THEN RETURN TRUE END
  279. END;
  280. ELSIF (ch = "(") THEN
  281. NextCh;
  282. IF (ch = "*") THEN INC(level); NextCh END;
  283. ELSIF ch = eof THEN RETURN FALSE
  284. ELSE NextCh END;
  285. END; (* LOOP *)
  286. ELSE
  287. IF ch = EOL THEN DEC(curLine); lineStart := oldLineStart END;
  288. DEC(bp, 2); NextCh; spaces := oldSpaces; RETURN FALSE
  289. END;
  290. END;
  291. RETURN FALSE;
  292. END comment;
  293. (* ==================================================================== *)
  294. PROCEDURE get() : Token;
  295. VAR
  296. state: INTEGER;
  297. sym : INTEGER;
  298. PROCEDURE equal (IN s: ARRAY OF CHAR): BOOLEAN;
  299. VAR
  300. i: INTEGER;
  301. q: INTEGER;
  302. BEGIN
  303. (* Assert: only called with literals ==> LEN(s$) = LEN(s)-1 *)
  304. IF nextLen # LEN(s)-1 THEN RETURN FALSE END;
  305. i := 1; q := bp0; INC(q);
  306. WHILE i < nextLen DO
  307. IF charAt(q) # s[i] THEN RETURN FALSE END;
  308. INC(i); INC(q)
  309. END;
  310. RETURN TRUE
  311. END equal;
  312. PROCEDURE CheckLiteral(VAR sym : INTEGER);
  313. BEGIN
  314. CASE charAt(bp0) OF
  315. "A": IF equal("ABSTRACT") THEN sym := Tok.ABSTRACTSym;
  316. ELSIF equal("ARRAY") THEN sym := Tok.ARRAYSym;
  317. END
  318. | "B": IF equal("BEGIN") THEN sym := Tok.BEGINSym;
  319. ELSIF equal("BY") THEN sym := Tok.BYSym;
  320. END
  321. | "C": IF equal("CASE") THEN sym := Tok.CASESym;
  322. ELSIF equal("CLOSE") THEN sym := Tok.CLOSESym;
  323. ELSIF equal("CONST") THEN sym := Tok.CONSTSym;
  324. END
  325. | "D": IF equal("DO") THEN sym := Tok.DOSym;
  326. ELSIF equal("DIV") THEN sym := Tok.DIVSym;
  327. ELSIF equal("DIV0") THEN sym := Tok.DIV0Sym;
  328. END
  329. | "E": IF equal("ELSE") THEN sym := Tok.ELSESym;
  330. ELSIF equal("ELSIF") THEN sym := Tok.ELSIFSym;
  331. ELSIF equal("EMPTY") THEN sym := Tok.EMPTYSym;
  332. ELSIF equal("END") THEN sym := Tok.ENDSym;
  333. ELSIF equal("EXIT") THEN sym := Tok.EXITSym;
  334. ELSIF equal("EXTENSIBLE") THEN sym := Tok.EXTENSIBLESym;
  335. ELSIF equal("ENUM") THEN sym := Tok.ENUMSym;
  336. ELSIF equal("EVENT") THEN sym := Tok.EVENTSym;
  337. END
  338. | "F": IF equal("FOR") THEN sym := Tok.FORSym;
  339. END
  340. | "I": IF equal("IF") THEN sym := Tok.IFSym;
  341. ELSIF equal("IMPORT") THEN sym := Tok.IMPORTSym;
  342. ELSIF equal("IN") THEN sym := Tok.INSym;
  343. ELSIF equal("IS") THEN sym := Tok.ISSym;
  344. ELSIF equal("INTERFACE") THEN sym := Tok.INTERFACESym;
  345. END
  346. | "L": IF equal("LIMITED") THEN sym := Tok.LIMITEDSym;
  347. ELSIF equal("LOOP") THEN sym := Tok.LOOPSym;
  348. END
  349. | "M": IF equal("MOD") THEN sym := Tok.MODSym;
  350. ELSIF equal("MODULE") THEN sym := Tok.MODULESym;
  351. END
  352. | "N": IF equal("NEW") THEN sym := Tok.NEWSym;
  353. ELSIF equal("NIL") THEN sym := Tok.NILSym;
  354. END
  355. | "O": IF equal("OF") THEN sym := Tok.OFSym;
  356. ELSIF equal("OR") THEN sym := Tok.ORSym;
  357. ELSIF equal("OUT") THEN sym := Tok.OUTSym;
  358. END
  359. | "P": IF equal("POINTER") THEN sym := Tok.POINTERSym;
  360. ELSIF equal("PROCEDURE") THEN sym := Tok.PROCEDURESym;
  361. END
  362. | "R": IF equal("RECORD") THEN sym := Tok.RECORDSym;
  363. ELSIF equal("REPEAT") THEN sym := Tok.REPEATSym;
  364. ELSIF equal("RETURN") THEN sym := Tok.RETURNSym;
  365. ELSIF equal("RESCUE") THEN sym := Tok.RESCUESym;
  366. ELSIF equal("REM0") THEN sym := Tok.REM0Sym;
  367. END
  368. | "S": IF equal("STATIC") THEN sym := Tok.STATICSym;
  369. END
  370. | "T": IF equal("THEN") THEN sym := Tok.THENSym;
  371. ELSIF equal("TO") THEN sym := Tok.TOSym;
  372. ELSIF equal("TYPE") THEN sym := Tok.TYPESym;
  373. END
  374. | "U": IF equal("UNTIL") THEN sym := Tok.UNTILSym;
  375. END
  376. | "V": IF equal("VAR") THEN sym := Tok.VARSym;
  377. ELSIF equal("VECTOR") THEN sym := Tok.VECTORSym;
  378. END
  379. | "W": IF equal("WHILE") THEN sym := Tok.WHILESym;
  380. ELSIF equal("WITH") THEN sym := Tok.WITHSym;
  381. END
  382. ELSE
  383. END
  384. END CheckLiteral;
  385. PROCEDURE mkToken(kind : INTEGER) : Token;
  386. VAR new : Token;
  387. BEGIN
  388. NEW(new);
  389. IF kind = Tok.idVariant THEN kind := Tok.identSym; new.dlr := TRUE END;
  390. new.sym := kind;
  391. new.lin := nextLine; new.col := nextCol;
  392. new.len := nextLen; new.pos := nextPos;
  393. RETURN new;
  394. END mkToken;
  395. BEGIN (*get*)
  396. WHILE (ch=' ') OR
  397. (ch >= CHR(9)) & (ch <= CHR(10)) OR
  398. (ch = CHR(13)) DO NextCh END;
  399. IF ((ch = "(")) & comment() THEN RETURN get() END;
  400. pos := nextPos; nextPos := bp;
  401. col := nextCol; nextCol := spaces;
  402. line := nextLine; nextLine := curLine;
  403. len := nextLen; nextLen := 0;
  404. apx := 0; state := start[ORD(ch)]; bp0 := bp;
  405. LOOP
  406. NextCh; INC(nextLen);
  407. CASE state OF
  408. (* ---------------------------------- *)
  409. 1: (* start of ordinary identifier *)
  410. IF (ch >= "0") & (ch <= "9") OR
  411. (ch >= "A") & (ch <= "Z") OR
  412. (ch >= "a") & (ch <= "z") OR
  413. (ch >= 0C0X) & (ch <= 0D6X) OR
  414. (ch >= 0D8X) & (ch <= 0F6X) OR
  415. (ch >= 0F8X) & (ch <= 0FFX) OR
  416. (ch = "_") THEN (* skip *)
  417. ELSIF ch = "@" THEN state := 45;
  418. ELSIF ch = "$" THEN state := 46;
  419. ELSE sym := Tok.identSym; CheckLiteral(sym); RETURN mkToken(sym);
  420. END;
  421. (* ---------------------------------- *)
  422. | 44:(* start of ` escaped identifier *)
  423. IF (ch >= "0") & (ch <= "9") OR
  424. (ch >= "A") & (ch <= "Z") OR
  425. (ch >= "a") & (ch <= "z") OR
  426. (ch >= 0C0X) & (ch <= 0D6X) OR
  427. (ch >= 0D8X) & (ch <= 0F6X) OR
  428. (ch >= 0F8X) & (ch <= 0FFX) OR
  429. (ch = "_") THEN (* skip *)
  430. ELSE
  431. SemError.Report(187, nextLine, spaces);
  432. RETURN mkToken(noSym);
  433. END;
  434. (* throw away the escape char *)
  435. INC(nextPos); INC(nextCol); DEC(nextLen);
  436. state := 45;
  437. (* ---------------------------------- *)
  438. | 45:(* rest of ` escaped identifier *)
  439. IF (ch >= "0") & (ch <= "9") OR
  440. (ch >= "A") & (ch <= "Z") OR
  441. (ch >= "a") & (ch <= "z") OR
  442. (ch = "@") OR
  443. (ch = "_") THEN (* skip *)
  444. ELSIF ch = "$" THEN state := 47;
  445. ELSE RETURN mkToken(Tok.idVariant); (* No check for reserved words *)
  446. END;
  447. (* ---------------------------------- *)
  448. | 46:(* check for $ at end of ident. *)
  449. IF (ch >= "0") & (ch <= "9") OR
  450. (ch >= "A") & (ch <= "Z") OR
  451. (ch >= "a") & (ch <= "z") OR
  452. (ch = "_") THEN state := 45; (* embedded "$" *)
  453. ELSE
  454. DEC(bp, 2); DEC(nextLen); NextCh;
  455. sym := Tok.identSym; CheckLiteral(sym); RETURN mkToken(sym);
  456. END;
  457. (* ---------------------------------- *)
  458. | 47:(* check for $ at end of idVar't *)
  459. IF (ch >= "0") & (ch <= "9") OR
  460. (ch >= "A") & (ch <= "Z") OR
  461. (ch >= "a") & (ch <= "z") OR
  462. (ch = "_") THEN state := 45; (* embedded "$" *)
  463. ELSE
  464. DEC(bp, 2); DEC(nextLen); NextCh;
  465. RETURN mkToken(Tok.idVariant); (* No check for reserved words *)
  466. END;
  467. (* ---------------------------------- *)
  468. | 49: (* !" ..." format string *)
  469. IF ch = '"' THEN state := 51;
  470. ELSIF ch = '\' THEN state := 50;
  471. END;
  472. | 50: (* Last char was '\' inside bangStr *)
  473. state := 49;
  474. | 51: RETURN mkToken(Tok.bangStrSym);
  475. (* ---------------------------------- *)
  476. | 2: RETURN mkToken(Tok.integerSym);
  477. | 3: DEC(bp, apx+1); DEC(nextLen, apx);
  478. NextCh; RETURN mkToken(Tok.integerSym);
  479. | 4: IF (ch >= "0") & (ch <= "9") THEN
  480. ELSIF (ch = "E") THEN state := 5;
  481. ELSE RETURN mkToken(Tok.realSym);
  482. END;
  483. | 5: IF (ch >= "0") & (ch <= "9") THEN state := 7;
  484. ELSIF (ch = "+") OR
  485. (ch = "-") THEN state := 6;
  486. ELSE RETURN mkToken(noSym);
  487. END;
  488. | 6: IF (ch >= "0") & (ch <= "9") THEN state := 7;
  489. ELSE RETURN mkToken(noSym);
  490. END;
  491. | 7: IF (ch >= "0") & (ch <= "9") THEN
  492. ELSE RETURN mkToken(Tok.realSym);
  493. END;
  494. | 8: RETURN mkToken(Tok.CharConstantSym);
  495. | 9: IF (ch <= CHR(9)) OR
  496. (ch >= CHR(11)) & (ch <= CHR(12)) OR
  497. (ch >= CHR(14)) & (ch <= "!") OR
  498. (ch >= "#") THEN
  499. ELSIF (ch = '"') THEN state := 10;
  500. ELSE RETURN mkToken(noSym);
  501. END;
  502. | 10: RETURN mkToken(Tok.stringSym);
  503. | 11: IF (ch <= CHR(9)) OR
  504. (ch >= CHR(11)) & (ch <= CHR(12)) OR
  505. (ch >= CHR(14)) & (ch <= "&") OR
  506. (ch>="(") THEN
  507. ELSIF (ch = "'") THEN state := 10;
  508. ELSE RETURN mkToken(noSym);
  509. END;
  510. | 12: IF (ch >= "0") & (ch <= "9") THEN
  511. ELSIF (ch >= "A") & (ch <= "F") THEN state := 13;
  512. ELSIF (ch = "H") OR
  513. (ch = "L") THEN state := 2;
  514. ELSIF (ch = ".") THEN state := 14; INC(apx)
  515. ELSIF (ch = "X") THEN state := 8;
  516. ELSE RETURN mkToken(Tok.integerSym);
  517. END;
  518. | 13: IF (ch >= "0") & (ch <= "9") OR
  519. (ch >= "A") & (ch <= "F") THEN
  520. ELSIF (ch = "H") OR
  521. (ch = "L") THEN state := 2;
  522. ELSIF (ch = "X") THEN state := 8;
  523. ELSE RETURN mkToken(noSym);
  524. END;
  525. | 14: IF (ch >= "0") & (ch <= "9") THEN state := 4; apx := 0
  526. ELSIF (ch = ".") THEN state := 3; INC(apx)
  527. ELSIF (ch = "E") THEN state := 5; apx := 0
  528. ELSE RETURN mkToken(Tok.realSym);
  529. END;
  530. | 15: RETURN mkToken(Tok.starSym);
  531. | 16: RETURN mkToken(Tok.minusSym);
  532. | 17: IF (ch = '"') THEN state := 49;
  533. ELSE RETURN mkToken(Tok.bangSym);
  534. END;
  535. | 18: IF (ch = ".") THEN state := 40;
  536. ELSE RETURN mkToken(Tok.pointSym);
  537. END;
  538. | 19: RETURN mkToken(Tok.equalSym);
  539. | 20: RETURN mkToken(Tok.commaSym);
  540. | 21: RETURN mkToken(Tok.lparenSym);
  541. | 22: RETURN mkToken(Tok.plusSym);
  542. | 23: RETURN mkToken(Tok.rparenSym);
  543. | 24: RETURN mkToken(Tok.semicolonSym);
  544. | 25: IF (ch = "=") THEN state := 41;
  545. ELSE RETURN mkToken(Tok.colonSym);
  546. END;
  547. | 26: RETURN mkToken(Tok.lbrackSym);
  548. | 27: RETURN mkToken(Tok.rbrackSym);
  549. | 28: RETURN mkToken(Tok.uparrowSym);
  550. | 29: RETURN mkToken(Tok.dollarSym);
  551. | 30: RETURN mkToken(Tok.hashSym);
  552. | 31: IF (ch = "=") THEN state := 32;
  553. ELSE RETURN mkToken(Tok.lessSym);
  554. END;
  555. | 32: RETURN mkToken(Tok.lessequalSym);
  556. | 33: IF (ch = "=") THEN state := 34;
  557. ELSE RETURN mkToken(Tok.greaterSym);
  558. END;
  559. | 34: RETURN mkToken(Tok.greaterequalSym);
  560. | 35: RETURN mkToken(Tok.slashSym);
  561. | 36: RETURN mkToken(Tok.andSym);
  562. | 37: RETURN mkToken(Tok.tildeSym);
  563. | 38: RETURN mkToken(Tok.lbraceSym);
  564. | 39: RETURN mkToken(Tok.rbraceSym);
  565. | 40: RETURN mkToken(Tok.pointpointSym);
  566. | 41: RETURN mkToken(Tok.colonequalSym);
  567. | 42: RETURN mkToken(Tok.barSym);
  568. | 43: ch := 0X; DEC(bp); RETURN mkToken(Tok.EOFSYM);
  569. ELSE RETURN mkToken(noSym); (*NextCh already done*)
  570. END
  571. END
  572. END get;
  573. (* ==================================================================== *)
  574. PROCEDURE SkipAndGetLine(i : INTEGER; (* indent to skip *)
  575. e : INTEGER; (* end file-pos *)
  576. VAR p : INTEGER; (* crnt file-pos *)
  577. OUT l : INTEGER; (* fetched length *)
  578. VAR s : ARRAY OF CHAR); (* output string *)
  579. VAR
  580. ch : CHAR;
  581. ix : INTEGER;
  582. sp : INTEGER;
  583. BEGIN
  584. sp := 0;
  585. ch := charAt(p); INC(p);
  586. (* skip i positions if possible *)
  587. WHILE (sp < i) & (ch <= " ") & (p <= e) & (ch # asciiLF) DO
  588. IF ch = asciiHT THEN INC(sp,8); DEC(sp,sp MOD 8) ELSE INC(sp) END;
  589. ch := charAt(p); INC(p);
  590. END;
  591. ix := 0;
  592. WHILE sp > i DO
  593. s[ix] := " "; INC(ix); DEC(sp);
  594. END;
  595. WHILE (p <= e) & (ch # asciiLF) DO
  596. s[ix] := ch; INC(ix);
  597. ch := charAt(p); INC(p);
  598. END;
  599. s[ix] := 0X; l := ix;
  600. END SkipAndGetLine;
  601. (* ==================================================================== *)
  602. PROCEDURE GetString (pos: INTEGER; len: INTEGER; OUT name: ARRAY OF CHAR);
  603. VAR
  604. i: INTEGER;
  605. p: INTEGER;
  606. BEGIN
  607. IF len >= LEN(name) THEN len := LEN(name)-1 END;
  608. p := pos; i := 0;
  609. WHILE i < len DO
  610. name[i] := charAt(p); INC(i); INC(p)
  611. END;
  612. name[len] := 0X;
  613. END GetString;
  614. (* ==================================================================== *)
  615. PROCEDURE charAt (pos: INTEGER): CHAR;
  616. VAR
  617. ch : CHAR;
  618. BEGIN
  619. IF pos >= inputLen THEN RETURN eof END;
  620. ch := buf[pos DIV LBlkSize][pos MOD LBlkSize];
  621. IF ch # eof THEN RETURN ch ELSE RETURN eof END
  622. END charAt;
  623. (* ==================================================================== *)
  624. PROCEDURE Reset;
  625. VAR
  626. len: INTEGER;
  627. i, read: INTEGER;
  628. BEGIN (*assert: src has been opened*)
  629. FOR i := 0 TO BlkNmbr - 1 DO savedBuf[i] := NIL END; bufSaved := FALSE;
  630. i := -1;
  631. inputLen := 0;
  632. REPEAT
  633. INC(i);
  634. (*
  635. * Conserve memory by not deallocating the buffer.
  636. * Reuse for later compilation, expanding if necessary.
  637. *)
  638. IF buf[i] = NIL THEN NEW(buf[i]) END;
  639. read := GPBinFiles.readNBytes(src, buf[i]^, BlkSize);
  640. INC(inputLen, read);
  641. UNTIL read < BlkSize;
  642. GPBinFiles.CloseFile(src);
  643. buf[i][read] := eofByt;
  644. curLine := 1; lineStart := -2; bp := -1;
  645. oldEols := 0; apx := 0; errors := 0; warnings := 0;
  646. spaces := 0; (* # new # *)
  647. NextCh;
  648. END Reset;
  649. PROCEDURE NewReadBuffer*(source : ARRAY OF POINTER TO ARRAY OF CHAR);
  650. VAR count, linIx, chrIx, index : INTEGER;
  651. lineP : POINTER TO ARRAY OF CHAR;
  652. theCh : CHAR;
  653. BEGIN
  654. IF ~bufSaved THEN
  655. count := 0;
  656. WHILE (count < BlkNmbr) & (buf[count] # NIL) DO
  657. savedBuf[count] := buf[count]; INC(count);
  658. END;
  659. END;
  660. bufSaved := TRUE;
  661. NEW(buf[0]);
  662. index := 0;
  663. FOR linIx := 0 TO LEN(source) - 1 DO
  664. lineP := source[linIx];
  665. chrIx := 0;
  666. IF lineP = NIL THEN theCh := 0X ELSE theCh := lineP[0] END;
  667. WHILE theCh # 0X DO
  668. buf[0][index] := USHORT(ORD(theCh)); INC(index); INC(chrIx);
  669. theCh := lineP[chrIx];
  670. END;
  671. buf[0][index] := ORD(ASCII.LF); INC(index);
  672. END;
  673. buf[0][index] := eofByt;
  674. (*
  675. * Initialize the scanner state.
  676. *)
  677. curLine := 1; lineStart := -2; bp := -1;
  678. oldEols := 0; apx := 0;
  679. spaces := 0; (* # new # *)
  680. NextCh;
  681. END NewReadBuffer;
  682. PROCEDURE RestoreFileBuffer*();
  683. VAR count : INTEGER;
  684. BEGIN
  685. count := 0;
  686. WHILE (count < BlkNmbr) & (savedBuf[count] # NIL) DO
  687. buf[count] := savedBuf[count]; INC(count);
  688. END;
  689. END RestoreFileBuffer;
  690. (* ==================================================================== *)
  691. BEGIN
  692. start[ 0] := 43; start[ 1] := 48; start[ 2] := 48; start[ 3] := 48;
  693. start[ 4] := 48; start[ 5] := 48; start[ 6] := 48; start[ 7] := 48;
  694. start[ 8] := 48; start[ 9] := 48; start[ 10] := 48; start[ 11] := 48;
  695. start[ 12] := 48; start[ 13] := 48; start[ 14] := 48; start[ 15] := 48;
  696. start[ 16] := 48; start[ 17] := 48; start[ 18] := 48; start[ 19] := 48;
  697. start[ 20] := 48; start[ 21] := 48; start[ 22] := 48; start[ 23] := 48;
  698. start[ 24] := 48; start[ 25] := 48; start[ 26] := 48; start[ 27] := 48;
  699. start[ 28] := 48; start[ 29] := 48; start[ 30] := 48; start[ 31] := 48;
  700. start[ 32] := 48; start[ 33] := 17; start[ 34] := 9; start[ 35] := 30; (* '!' = 33 => state 17 *)
  701. start[ 36] := 29; start[ 37] := 48; start[ 38] := 36; start[ 39] := 11; (* '%' = 37 => state 48 *)
  702. start[ 40] := 21; start[ 41] := 23; start[ 42] := 15; start[ 43] := 22;
  703. start[ 44] := 20; start[ 45] := 16; start[ 46] := 18; start[ 47] := 35;
  704. start[ 48] := 12; start[ 49] := 12; start[ 50] := 12; start[ 51] := 12;
  705. start[ 52] := 12; start[ 53] := 12; start[ 54] := 12; start[ 55] := 12;
  706. start[ 56] := 12; start[ 57] := 12; start[ 58] := 25; start[ 59] := 24;
  707. start[ 60] := 31; start[ 61] := 19; start[ 62] := 33; start[ 63] := 48;
  708. start[ 64] := 48; start[ 65] := 1; start[ 66] := 1; start[ 67] := 1;
  709. start[ 68] := 1; start[ 69] := 1; start[ 70] := 1; start[ 71] := 1;
  710. start[ 72] := 1; start[ 73] := 1; start[ 74] := 1; start[ 75] := 1;
  711. start[ 76] := 1; start[ 77] := 1; start[ 78] := 1; start[ 79] := 1;
  712. start[ 80] := 1; start[ 81] := 1; start[ 82] := 1; start[ 83] := 1;
  713. start[ 84] := 1; start[ 85] := 1; start[ 86] := 1; start[ 87] := 1;
  714. start[ 88] := 1; start[ 89] := 1; start[ 90] := 1; start[ 91] := 26;
  715. start[ 92] := 48; start[ 93] := 27; start[ 94] := 28;
  716. (* ------------------------------------------- *)
  717. (* Two special-case characters ... "_" and "`" *)
  718. (* ------------------------------------------- *)
  719. start[ 95] := 1; start[ 96] := 44;
  720. (* ------------------------------------------- *)
  721. start[ 97] := 1; start[ 98] := 1; start[ 99] := 1;
  722. start[100] := 1; start[101] := 1; start[102] := 1; start[103] := 1;
  723. start[104] := 1; start[105] := 1; start[106] := 1; start[107] := 1;
  724. start[108] := 1; start[109] := 1; start[110] := 1; start[111] := 1;
  725. start[112] := 1; start[113] := 1; start[114] := 1; start[115] := 1;
  726. start[116] := 1; start[117] := 1; start[118] := 1; start[119] := 1;
  727. start[120] := 1; start[121] := 1; start[122] := 1; start[123] := 38;
  728. start[124] := 42; start[125] := 39; start[126] := 37; start[127] := 48;
  729. start[128] := 48; start[129] := 48; start[130] := 48; start[131] := 48;
  730. start[132] := 48; start[133] := 48; start[134] := 48; start[135] := 48;
  731. start[136] := 48; start[137] := 48; start[138] := 48; start[139] := 48;
  732. start[140] := 48; start[141] := 48; start[142] := 48; start[143] := 48;
  733. start[144] := 48; start[145] := 48; start[148] := 48; start[147] := 48;
  734. start[148] := 48; start[149] := 48; start[150] := 48; start[151] := 48;
  735. start[152] := 48; start[153] := 48; start[154] := 48; start[155] := 48;
  736. start[156] := 48; start[157] := 48; start[158] := 48; start[159] := 48;
  737. start[160] := 48; start[161] := 48; start[162] := 48; start[163] := 48;
  738. start[164] := 48; start[165] := 48; start[166] := 48; start[167] := 48;
  739. start[168] := 48; start[169] := 48; start[170] := 48; start[171] := 48;
  740. start[172] := 48; start[173] := 48; start[174] := 48; start[175] := 48;
  741. start[176] := 48; start[177] := 48; start[178] := 48; start[179] := 48;
  742. start[180] := 48; start[181] := 48; start[182] := 48; start[183] := 48;
  743. start[184] := 48; start[185] := 48; start[186] := 48; start[187] := 48;
  744. start[188] := 48; start[189] := 48; start[190] := 48; start[191] := 48;
  745. (* ------------------------------------------- *)
  746. (* Latin-8 alphabetics start here ... *)
  747. (* ------------------------------------------- *)
  748. start[192] := 1; start[193] := 1; start[194] := 1; start[195] := 1;
  749. start[196] := 1; start[197] := 1; start[198] := 1; start[199] := 1;
  750. start[200] := 1; start[201] := 1; start[202] := 1; start[203] := 1;
  751. start[204] := 1; start[205] := 1; start[206] := 1; start[207] := 1;
  752. start[208] := 1; start[209] := 1; start[210] := 1; start[211] := 1;
  753. start[212] := 1; start[213] := 1; start[214] := 1;
  754. (* odd character out *)
  755. start[215] := 48;
  756. start[216] := 1; start[217] := 1; start[218] := 1; start[219] := 1;
  757. start[220] := 1; start[221] := 1; start[222] := 1; start[223] := 1;
  758. start[224] := 1; start[225] := 1; start[226] := 1; start[227] := 1;
  759. start[228] := 1; start[229] := 1; start[230] := 1; start[231] := 1;
  760. start[232] := 1; start[233] := 1; start[234] := 1; start[235] := 1;
  761. start[236] := 1; start[237] := 1; start[238] := 1; start[239] := 1;
  762. start[240] := 1; start[241] := 1; start[242] := 1; start[243] := 1;
  763. start[244] := 1; start[245] := 1; start[246] := 1;
  764. (* odd character out *)
  765. start[247] := 48;
  766. start[248] := 1; start[249] := 1; start[250] := 1; start[251] := 1;
  767. start[252] := 1; start[253] := 1; start[254] := 1; start[255] := 1;
  768. LBlkSize := BlkSize;
  769. END CPascalS.