FoxCSharpScanner.Mod 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468
  1. MODULE FoxCSharpScanner;
  2. IMPORT Streams, Strings, Diagnostics, Commands, StringPool,
  3. D := Debugging, Basic := FoxBasic, FoxScanner,
  4. KernelLog (* DEBUG *);
  5. CONST
  6. Trace = FALSE;
  7. (* overal scanner limitation *)
  8. MaxIdentifierLength* = FoxScanner.MaxIdentifierLength;
  9. (* parametrization of numeric scanner: *)
  10. MaxHexDigits* = FoxScanner.MaxHexDigits;
  11. MaxHugeHexDigits* = FoxScanner.MaxHugeHexDigits;
  12. MaxRealExponent* = FoxScanner.MaxRealExponent;
  13. MaxLongrealExponent* = FoxScanner.MaxLongrealExponent;
  14. (* scanner constants *)
  15. EOT* = 0X;
  16. LF* = 0AX;
  17. CR* = 0DX;
  18. TAB* = 09X;
  19. TYPE
  20. StringType* = FoxScanner.StringType;
  21. IdentifierType* = FoxScanner.IdentifierType;
  22. IdentifierString* = FoxScanner.IdentifierString;
  23. CONST
  24. (* tokens *)
  25. None*= 0;
  26. (* operators and punctuators *)
  27. Exclamation* = 1; (* ! *)
  28. ExclamationEqual* = 2; (* != *)
  29. Percent* = 3; (* % *)
  30. PercentEqual* = 4; (* %= *)
  31. And* = 5; (* & *)
  32. AndEqual* = 6; (* &= *)
  33. AndAnd* = 7; (* && *)
  34. LeftParenthesis* = 8; (* ( *)
  35. RightParenthesis* = 9; (* ) *)
  36. Times* = 10; (* * *)
  37. TimesEqual* = 11; (* *= *)
  38. Plus* = 12; (* + *)
  39. PlusEqual* = 13; (* += *)
  40. PlusPlus* = 14; (* ++ *)
  41. Comma* = 15; (* , *)
  42. Minus* = 16; (* - *)
  43. MinusEqual* = 17; (* -= *)
  44. MinusMinus* = 18; (* -- *)
  45. Period* = 19; (* . *)
  46. Slash* = 20; (* / *)
  47. SlashEqual* = 21; (* /= *)
  48. Colon* = 22; (* : *)
  49. Semicolon* = 23; (* ; *)
  50. Less* = 24; (* < *)
  51. LessEqual* = 25; (* <= *)
  52. LeftShift* = 26; (* << *)
  53. LeftShiftEqual* = 27; (* <<= *)
  54. Equal* = 28; (* = *)
  55. EqualEqual* = 29; (* == *)
  56. Greater* = 30; (* > *)
  57. GreaterEqual* = 31; (* >= *)
  58. RightShift* = 32; (* >> *)
  59. RightShiftEqual* = 33; (* >>= *)
  60. LeftBracket* = 34; (* [ *)
  61. RightBracket* = 35; (* ] *)
  62. Arrow* = 36; (* ^ *)
  63. ArrowEqual* = 37; (* ^= *)
  64. LeftBrace* = 38; (* { *)
  65. Bar* = 39; (* | *)
  66. BarEqual* = 40; (* |= *)
  67. BarBar* = 41; (* || *)
  68. RightBrace* = 42; (* } *)
  69. Tilde* = 43; (* ~ *)
  70. (* keywords *)
  71. As* = 44;
  72. Base* = 45;
  73. Bool* = 46;
  74. Break* = 47;
  75. Case* = 48;
  76. Char* = 49;
  77. Class* = 50;
  78. Const* = 51;
  79. Default* = 52;
  80. Delegate* = 53;
  81. Do* = 54;
  82. Double* = 55;
  83. Else* = 56;
  84. False* = 57;
  85. Float* = 58;
  86. For* = 59;
  87. If* = 60;
  88. Import* = 61;
  89. Int* = 62;
  90. Internal* = 63;
  91. Is* = 64;
  92. Long* = 65;
  93. Module* = 66;
  94. New* = 67;
  95. Null* = 68;
  96. Object* = 69;
  97. Public* = 70;
  98. Readonly* = 71;
  99. Ref* = 72;
  100. Return* = 73;
  101. Sbyte* = 74;
  102. Short* = 75;
  103. String* = 76;
  104. Struct* = 77;
  105. Switch* = 78;
  106. This* = 79;
  107. True* = 80;
  108. Void* = 81;
  109. While* = 82;
  110. Identifier* = 83;
  111. IntegerLiteral* = 84;
  112. RealLiteral* = 85;
  113. CharacterLiteral* = 86;
  114. StringLiteral* = 87;
  115. Comment*= 88;
  116. (* Active Cells *)
  117. Cell* = 89;
  118. Cellnet* = 90;
  119. In* = 91;
  120. Out* = 92;
  121. Select* = 93;
  122. Question* = 94; (* ? *)
  123. QuestionQuestion* = 95; (* ?? *)
  124. EndOfText*= 96;
  125. (* number types *)
  126. IntNumber*= 1;
  127. LongNumber*= 2;
  128. FloatNumber*= 3;
  129. DoubleNumber*= 4;
  130. SingleQuote = 27X;
  131. DoubleQuote* = 22X;
  132. Backslash = 5CX;
  133. TYPE
  134. (* keywords book keeping *)
  135. Keyword* = FoxScanner.Keyword;
  136. KeywordTable* = FoxScanner.KeywordTable;
  137. TYPE
  138. Token* = LONGINT;
  139. (**
  140. symbol: data structure for the data transfer of
  141. the last read input from the scanner to the parser
  142. **)
  143. Symbol* = RECORD
  144. start*, end*, line-: LONGINT;
  145. token*: Token;
  146. identifier*: IdentifierType;
  147. identifierString*: IdentifierString;
  148. string*: StringType;
  149. stringLength*: LONGINT;
  150. numberType*: LONGINT;
  151. integer*: LONGINT;
  152. hugeint*: HUGEINT;
  153. character*: CHAR;
  154. real*: LONGREAL;
  155. END;
  156. StringMaker* = FoxScanner.StringMaker;
  157. Scanner* = OBJECT
  158. VAR
  159. source-: StringType;
  160. reader: Streams.Reader;
  161. diagnostics: Diagnostics.Diagnostics;
  162. ch: CHAR;
  163. position: LONGINT;
  164. line-: LONGINT;
  165. error-: BOOLEAN;
  166. stringWriter: Streams.Writer;
  167. stringMaker: StringMaker;
  168. (*
  169. source: name of the source code for reference in error outputs
  170. reader: input stream
  171. position: reference position (offset) of the input stream, for error output
  172. diagnostics: error output object
  173. *)
  174. PROCEDURE & InitializeScanner*(
  175. CONST source: ARRAY OF CHAR;
  176. reader: Streams.Reader;
  177. position: LONGINT;
  178. diagnostics: Diagnostics.Diagnostics);
  179. BEGIN
  180. NEW(stringMaker,1024);
  181. stringWriter := stringMaker.GetWriter();
  182. error := FALSE;
  183. NEW(SELF.source, Strings.Length(source)+1);
  184. COPY(source, SELF.source^);
  185. SELF.reader := reader;
  186. SELF.diagnostics := diagnostics;
  187. ch := " ";
  188. IF reader = NIL THEN
  189. ch := EOT
  190. ELSE
  191. GetNextCharacter
  192. END;
  193. IF Trace THEN
  194. D.Str("New scanner ");
  195. D.Ln;
  196. END;
  197. SELF.position := position;
  198. line := 0;
  199. END InitializeScanner;
  200. (** report an error occured during scanning **)
  201. PROCEDURE ErrorS(CONST msg: ARRAY OF CHAR);
  202. BEGIN
  203. IF diagnostics # NIL THEN
  204. diagnostics.Error(source^, position, Diagnostics.Invalid, msg)
  205. END;
  206. error := TRUE;
  207. END ErrorS;
  208. (** report an error occured during scanning **)
  209. PROCEDURE Error(code: INTEGER);
  210. VAR errorMessage: ARRAY 256 OF CHAR;
  211. BEGIN
  212. IF diagnostics # NIL THEN
  213. Basic.GetErrorMessage(code, "", errorMessage);
  214. diagnostics.Error(source^, position, code, errorMessage)
  215. END;
  216. error := TRUE;
  217. END Error;
  218. (** get next character, end of text results in ch = EOT **)
  219. PROCEDURE GetNextCharacter;
  220. BEGIN
  221. reader.Char(ch);
  222. INC(position);
  223. IF ch = LF THEN
  224. INC(line)
  225. END;
  226. END GetNextCharacter;
  227. PROCEDURE IsNewlineCharacter(ch: CHAR): BOOLEAN;
  228. BEGIN
  229. RETURN (ch = 0AX) OR (ch = 0DX);
  230. END IsNewlineCharacter;
  231. (**
  232. CharacterLiteral =
  233. "'" Character "'".
  234. Character =
  235. SingleCharacter |
  236. SimpleEscapeSequence |
  237. HexadecimalEscapeSequence.
  238. SingleCharacter =
  239. any character except ' (27X), \ (5CX), and NewLineCharacter.
  240. SimpleEscapeSequence =
  241. "\'" | '\"' | '\\' | '\0' |
  242. '\a' | '\b' | '\f' | '\n' | '\r' | '\t' | '\v'.
  243. HexadecimalEscapeSequence =
  244. '\x' HexDigit {HexDigit}.
  245. **)
  246. PROCEDURE GetEscapeSequence(VAR esc: CHAR);
  247. VAR i, k, n: LONGINT;
  248. PROCEDURE HexDigit(ch: CHAR; VAR dig: LONGINT): BOOLEAN;
  249. BEGIN
  250. IF (ch >= '0') & (ch <= '9') THEN
  251. dig := ORD(ch) - ORD('0');
  252. RETURN TRUE;
  253. END;
  254. IF (ch >= 'A') & (ch <= 'F') THEN
  255. dig := ORD(ch) - ORD('A') + 10;
  256. RETURN TRUE;
  257. END;
  258. IF (ch >= 'a') & (ch <= 'f') THEN
  259. dig := ORD(ch) - ORD('a') + 10;
  260. RETURN TRUE;
  261. END;
  262. RETURN FALSE;
  263. END HexDigit;
  264. BEGIN
  265. CASE ch OF
  266. SingleQuote, DoubleQuote, Backslash:
  267. esc := ch;
  268. GetNextCharacter
  269. | '0':
  270. esc := 0X;
  271. GetNextCharacter
  272. | 'a':
  273. esc := 07X;
  274. GetNextCharacter
  275. | 'b':
  276. esc := 08X;
  277. GetNextCharacter
  278. | 'f':
  279. esc := 0CX;
  280. GetNextCharacter
  281. | 'n':
  282. esc := 0AX;
  283. GetNextCharacter
  284. | 'r':
  285. esc := 0DX;
  286. GetNextCharacter
  287. | 't':
  288. esc := 09X;
  289. GetNextCharacter
  290. | 'v':
  291. esc := 0BX;
  292. GetNextCharacter
  293. | 'x':
  294. GetNextCharacter;
  295. n := 0;
  296. i := 0;
  297. WHILE (i < 2) & HexDigit(ch, k) DO
  298. n := n * 16 + k;
  299. GetNextCharacter;
  300. INC(i);
  301. END;
  302. IF i = 0 THEN
  303. ErrorS("Illegal hexadecimal escape sequence");
  304. END;
  305. esc := CHR(n);
  306. ELSE
  307. ErrorS("Illegal escape sequence");
  308. esc := 0X; (* arbitrary *)
  309. END;
  310. END GetEscapeSequence;
  311. PROCEDURE GetCharacter(VAR symbol: Symbol);
  312. VAR vch: CHAR;
  313. BEGIN
  314. GetNextCharacter;
  315. IF ch = EOT THEN
  316. ErrorS("Unexpected end of character literal");
  317. symbol.character := 0X;
  318. RETURN;
  319. END;
  320. IF ch = Backslash THEN
  321. GetNextCharacter;
  322. GetEscapeSequence(vch);
  323. ELSIF (ch = SingleQuote) OR IsNewlineCharacter(ch) THEN
  324. ErrorS("Illegal character literal");
  325. vch := 0X;
  326. ELSE
  327. vch := ch;
  328. GetNextCharacter;
  329. END;
  330. IF ch = SingleQuote THEN
  331. GetNextCharacter
  332. ELSE
  333. ErrorS("Illegal character literal")
  334. END;
  335. symbol.character := vch;
  336. symbol.integer := ORD(vch);
  337. END GetCharacter;
  338. (**
  339. StringLiteral =
  340. '"' {StringCharacter} '"'.
  341. StringCharacter =
  342. SingleStringCharacter |
  343. SimpleEscapeSequence |
  344. HexadecimalEscapeSequence.
  345. SingleStringCharacter =
  346. any character except " (22X), \ (5CX), and NewLineCharacter.
  347. **)
  348. PROCEDURE GetString(VAR symbol: Symbol);
  349. VAR vch: CHAR;
  350. BEGIN
  351. stringMaker.Clear;
  352. GetNextCharacter;
  353. LOOP
  354. IF (ch = EOT) THEN
  355. ErrorS("Unexpected end of string literal");
  356. EXIT;
  357. END;
  358. IF IsNewlineCharacter(ch) THEN
  359. ErrorS("Illegal string literal");
  360. EXIT;
  361. END;
  362. IF ch = DoubleQuote THEN
  363. GetNextCharacter;
  364. EXIT;
  365. END;
  366. IF ch = Backslash THEN
  367. GetNextCharacter;
  368. GetEscapeSequence(vch);
  369. ELSE
  370. vch := ch;
  371. GetNextCharacter;
  372. END;
  373. stringWriter.Char(vch);
  374. END;
  375. stringWriter.Char(0X);
  376. stringWriter.Update;
  377. (*
  378. ACHTUNG: Due to the implementation of GetStringCopy
  379. the length of the copied string may be inconsistent
  380. with its contents if the string contains 0X.
  381. This must be fixed in the future.
  382. *)
  383. symbol.string := stringMaker.GetStringCopy(symbol.stringLength);
  384. END GetString;
  385. (**
  386. Identifier =
  387. (Letter | '_') {Letter | Digit | '_'}.
  388. Letter =
  389. 'A' | 'B' | .. | 'Z' | 'a' | 'b' | .. | 'z' .
  390. **)
  391. PROCEDURE GetIdentifier(VAR symbol: Symbol);
  392. VAR i: LONGINT;
  393. BEGIN
  394. i := 0;
  395. REPEAT
  396. symbol.identifierString[i] := ch;
  397. INC(i);
  398. GetNextCharacter
  399. UNTIL reservedCharacter[ORD(ch)] OR (i = MaxIdentifierLength);
  400. IF i = MaxIdentifierLength THEN
  401. Error(Basic.IdentifierTooLong);
  402. DEC(i)
  403. END;
  404. symbol.identifierString[i] := 0X;
  405. StringPool.GetIndex(symbol.identifierString, symbol.identifier);
  406. END GetIdentifier;
  407. (**
  408. Number =
  409. IntegerLiteral |
  410. RealLiteral.
  411. IntegerLiteral =
  412. DecimalIntegerLiteral |
  413. HexadecimalIntegerLiteral.
  414. DecimalIntegerLiteral =
  415. Digit {Digit} [IntegerTypeSuffix].
  416. HexadecimalIntegerLiteral =
  417. ('0X' | '0x') HexDigit {HexDigit} [IntegerTypeSuffix].
  418. IntegerTypeSuffix =
  419. 'L' | 'l'.
  420. RealLiteral =
  421. Digit {Digit} '.' Digit {Digit} [ExponentPart] [RealTypeSuffix] |
  422. '.' Digit {Digit} [ExponentPart] [RealTypeSuffix] |
  423. Digit {Digit} [ExponentPart] [RealTypeSuffix] |
  424. Digit {Digit} [RealTypeSuffix].
  425. ExponentPart =
  426. ('E' | 'e') ['+' | '-'] Digit {Digit}.
  427. RealTypeSuffix =
  428. 'F' | 'f' | 'D' | 'd'.
  429. Digit =
  430. '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'.
  431. HexDigit =
  432. '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
  433. 'A' | 'B' | 'C' | 'D' | 'E' | 'F' |
  434. 'a' | 'b' | 'c' | 'd' | 'e' | 'f'.
  435. **)
  436. PROCEDURE GetNumber(VAR symbol: Symbol; frac: BOOLEAN): Token;
  437. VAR i, nextInt, m, n, d, e, si: LONGINT;
  438. dig: ARRAY 24 OF CHAR;
  439. f: LONGREAL;
  440. hex, neg, long: BOOLEAN;
  441. hugeint, tenh: HUGEINT;
  442. result: LONGINT;
  443. PROCEDURE Append(ch: CHAR);
  444. BEGIN
  445. symbol.identifierString[si] := ch;
  446. INC(si);
  447. END Append;
  448. PROCEDURE Digit(ch: CHAR): LONGINT;
  449. BEGIN
  450. RETURN ORD(ch) - ORD('0')
  451. END Digit;
  452. PROCEDURE HexDigit(ch: CHAR): LONGINT;
  453. BEGIN
  454. IF (ch >= '0') & (ch <= '9') THEN
  455. RETURN ORD(ch) - ORD('0')
  456. END;
  457. IF (ch >= 'A') & (ch <= 'F') THEN
  458. RETURN ORD(ch) - ORD('A') + 10
  459. END;
  460. IF (ch >= 'a') & (ch <= 'f') THEN
  461. RETURN ORD(ch) - ORD('a') + 10
  462. END;
  463. (* cannot happen *)
  464. Error(Basic.NumberIllegalCharacter);
  465. RETURN 0
  466. END HexDigit;
  467. PROCEDURE Ten(e: LONGINT): LONGREAL;
  468. VAR x, p: LONGREAL;
  469. BEGIN
  470. x := 1;
  471. p := 10;
  472. WHILE e > 0 DO
  473. IF ODD(e) THEN
  474. x := x * p
  475. END;
  476. e := e DIV 2;
  477. IF e > 0 THEN
  478. p := p * p
  479. END
  480. END;
  481. RETURN x
  482. END Ten;
  483. BEGIN
  484. (* ch is '.' or Digit *)
  485. si := 0;
  486. hex := FALSE;
  487. IF ~frac & (ch = '0') THEN
  488. Append(ch);
  489. GetNextCharacter;
  490. IF (ch = 'X') OR (ch = 'x') THEN
  491. Append(ch);
  492. GetNextCharacter;
  493. hex := TRUE
  494. END;
  495. END;
  496. i := 0;
  497. m := 0;
  498. n := 0;
  499. d := 0;
  500. long := FALSE;
  501. IF frac THEN
  502. Append('.');
  503. (* fictionary zero mantissa: *)
  504. i := 1;
  505. d := 1;
  506. END;
  507. LOOP (* read mantissa *)
  508. IF ((ch >= '0') & (ch <= '9')) OR
  509. (hex &
  510. (((ch >= 'A') & (ch <= 'F')) OR
  511. ((ch >= 'a') & (ch <= 'f')))) THEN
  512. IF (m > 0) OR (ch # '0') THEN (* ignore leading zeros *)
  513. IF n < LEN(dig) THEN
  514. dig[n] := ch;
  515. INC(n);
  516. END;
  517. INC(m);
  518. END;
  519. Append(ch);
  520. GetNextCharacter;
  521. INC(i)
  522. ELSIF ~hex & (ch = '.') THEN
  523. IF d # 0 THEN
  524. EXIT
  525. END;
  526. Append(ch);
  527. GetNextCharacter;
  528. d := i
  529. ELSE
  530. EXIT
  531. END
  532. END;
  533. IF d = 0 THEN
  534. IF ((ch = 'F') OR (ch = 'f') OR
  535. (ch = 'D') OR (ch = 'd') OR
  536. (ch = 'E') OR (ch = 'e')) THEN
  537. d := i
  538. END;
  539. ELSIF d = i THEN
  540. (* '.' must be followed by a digit *)
  541. Error(Basic.NumberIllegalCharacter)
  542. END;
  543. (* 0 <= n <= m <= i, 0 <= d <= i *)
  544. IF d = 0 THEN (* integer *)
  545. IF (ch = 'L') OR (ch = 'l') THEN
  546. Append(ch);
  547. GetNextCharacter;
  548. long := TRUE
  549. END;
  550. IF n = m THEN
  551. symbol.integer := 0;
  552. symbol.hugeint := 0;
  553. i := 0;
  554. IF hex THEN
  555. IF ~long &
  556. ((n < MaxHexDigits) OR
  557. ((n = MaxHexDigits) & (dig[0] <= '7'))) THEN
  558. WHILE i < n DO
  559. symbol.integer := symbol.integer * 10H + HexDigit(dig[i]);
  560. INC(i)
  561. END;
  562. symbol.numberType := IntNumber;
  563. symbol.hugeint := symbol.integer;
  564. ELSIF n <= MaxHugeHexDigits THEN
  565. hugeint := 0;
  566. IF (n = MaxHugeHexDigits) & (dig[0] > '7') THEN
  567. (* prevent overflow *)
  568. hugeint := -1
  569. END;
  570. WHILE i < n DO
  571. hugeint := hugeint * 10H + HexDigit(dig[i]);
  572. INC(i)
  573. END;
  574. symbol.numberType := LongNumber;
  575. symbol.hugeint := hugeint;
  576. symbol.integer := SHORT(symbol.hugeint);
  577. ELSE
  578. symbol.numberType := LongNumber;
  579. Error(Basic.NumberTooLarge)
  580. END
  581. ELSE (* decimal *)
  582. WHILE (i < n) & ~long DO
  583. d := Digit(dig[i]);
  584. INC(i);
  585. nextInt := symbol.integer * 10 + d;
  586. IF nextInt >= 0 THEN
  587. symbol.integer := nextInt
  588. ELSE (* overflow *)
  589. long := TRUE
  590. END;
  591. END;
  592. IF long THEN
  593. (* restart computation *)
  594. (*
  595. ACHTUNG: Reportedly, Fox has or had certain limitations
  596. working with HUGEINT that affected the original code.
  597. Furthermore, at present Ronin supports HUGEINT as
  598. a mere alias to LONGINT, therefore the following code
  599. is just reserved for the future and long integer
  600. constants are not yet supported.
  601. *)
  602. i := 0;
  603. hugeint := 0;
  604. tenh := 10;
  605. WHILE i < n DO
  606. d := Digit(dig[i]);
  607. INC(i);
  608. hugeint := hugeint * tenh + d;
  609. IF hugeint < 0 THEN
  610. Error(Basic.NumberTooLarge)
  611. END
  612. END;
  613. symbol.numberType := LongNumber;
  614. symbol.hugeint := hugeint;
  615. symbol.integer := SHORT(symbol.hugeint);
  616. ELSE
  617. symbol.numberType := IntNumber;
  618. symbol.hugeint := symbol.integer;
  619. END
  620. END
  621. ELSE
  622. symbol.numberType := LongNumber;
  623. Error(Basic.NumberTooLarge)
  624. END;
  625. result := IntegerLiteral;
  626. ELSE (* fraction *)
  627. IF (ch = 'F') OR (ch = 'f') THEN
  628. Append(ch);
  629. GetNextCharacter;
  630. long := FALSE
  631. ELSIF (ch = 'D') OR (ch = 'd') THEN
  632. Append(ch);
  633. GetNextCharacter;
  634. long := TRUE
  635. ELSE
  636. long := TRUE
  637. END;
  638. f := 0;
  639. e := 0;
  640. WHILE n > 0 DO
  641. (* 0 <= f < 1 *)
  642. DEC(n);
  643. f := (Digit(dig[n]) + f) / 10
  644. END;
  645. IF (ch = 'E') OR (ch = 'e') THEN
  646. Append(ch);
  647. GetNextCharacter;
  648. neg := FALSE;
  649. IF ch = '-' THEN
  650. neg := TRUE;
  651. Append(ch);
  652. GetNextCharacter
  653. ELSIF ch = '+' THEN
  654. Append(ch);
  655. GetNextCharacter
  656. END;
  657. IF (ch >= '0') & (ch <= '9') THEN
  658. REPEAT
  659. n := Digit(ch);
  660. Append(ch);
  661. GetNextCharacter;
  662. IF e <= (MAX(INTEGER) - n) DIV 10 THEN
  663. e := e * 10 + n
  664. ELSE
  665. Error(Basic.NumberTooLarge)
  666. END
  667. UNTIL (ch < '0') OR (ch > '9');
  668. IF neg THEN
  669. e := -e
  670. END
  671. ELSE
  672. Error(Basic.NumberIllegalCharacter)
  673. END
  674. END;
  675. (* decimal point shift *)
  676. DEC(e, i-d-m);
  677. IF long THEN
  678. symbol.numberType := DoubleNumber;
  679. IF (1 - MaxLongrealExponent < e) & (e <= MaxLongrealExponent) THEN
  680. IF e < 0 THEN
  681. symbol.real := f / Ten(-e)
  682. ELSE
  683. symbol.real := f * Ten(e)
  684. END
  685. ELSE
  686. Error(Basic.NumberTooLarge)
  687. END
  688. ELSE
  689. symbol.numberType := FloatNumber;
  690. IF (1- MaxRealExponent < e) & (e <= MaxRealExponent) THEN
  691. IF e < 0 THEN
  692. symbol.real := f / Ten(-e)
  693. ELSE
  694. symbol.real := f * Ten(e)
  695. END
  696. ELSE
  697. Error(Basic.NumberTooLarge)
  698. END
  699. END;
  700. result := RealLiteral;
  701. END;
  702. symbol.identifierString[si] := 0X;
  703. RETURN result;
  704. END GetNumber;
  705. (** read / skip a comment **)
  706. (**
  707. Comment =
  708. SingleLineComment |
  709. DelimitedComment.
  710. SingleLineComment =
  711. '//' {InputCharacter}.
  712. InputCharacter =
  713. any character except a NewLineCharacter.
  714. NewlineCharacter =
  715. Carriage return character (0DX) |
  716. Line feed character (0AX) |
  717. EOT (0X).
  718. DelimitedComment =
  719. '/*' [DelimitedCommentText] Asterisks '/'.
  720. DelimitedCommentText =
  721. DelimitedCommentSection {DelimitedCommentSection}.
  722. DelimitedCommentSection =
  723. NotAsterisk |
  724. Asterisks NotSlash.
  725. Asterisks =
  726. '*' {'*'}.
  727. NotAsterisk =
  728. any character except *.
  729. NotSlash =
  730. any character except /.
  731. **)
  732. PROCEDURE ReadSingleLineComment(VAR symbol: Symbol);
  733. BEGIN
  734. stringMaker.Clear;
  735. WHILE (ch # 0DX) & (ch # 0AX) & (ch # EOT) DO
  736. stringWriter.Char(ch);
  737. GetNextCharacter;
  738. END;
  739. stringWriter.Char(0X);
  740. stringWriter.Update;
  741. symbol.token := Comment;
  742. symbol.string := stringMaker.GetString(symbol.stringLength);
  743. END ReadSingleLineComment;
  744. PROCEDURE ReadDelimitedComment(VAR symbol: Symbol);
  745. VAR done: BOOLEAN;
  746. BEGIN
  747. stringMaker.Clear;
  748. done := FALSE;
  749. WHILE ~done & (ch # EOT) DO
  750. IF ch = '*' THEN
  751. GetNextCharacter;
  752. IF ch = '/' THEN
  753. GetNextCharacter;
  754. done := TRUE;
  755. ELSE
  756. stringWriter.Char('*');
  757. END;
  758. ELSE
  759. stringWriter.Char(ch);
  760. GetNextCharacter;
  761. END;
  762. END;
  763. IF ~done THEN
  764. Error(Basic.CommentNotClosed);
  765. END;
  766. stringWriter.Char(0X);
  767. stringWriter.Update;
  768. symbol.token := Comment;
  769. symbol.string := stringMaker.GetString(symbol.stringLength);
  770. END ReadDelimitedComment;
  771. PROCEDURE SkipBlanks;
  772. BEGIN
  773. WHILE (ch = 20X) OR (ch = 09X) OR (ch = 0BX) OR (ch = 0CX) OR
  774. (ch = 0DX) OR (ch = 0AX) DO
  775. (* ignore C# whitespace characters '\t' (09X), '\v' (0BX), '\f' (0CX)
  776. and newlines '\r' (0DX), '\n' (0AX) *)
  777. IF ch = EOT THEN
  778. IF Trace THEN
  779. D.String("EOT");
  780. D.Ln;
  781. END;
  782. RETURN
  783. ELSE
  784. GetNextCharacter
  785. END
  786. END;
  787. END SkipBlanks;
  788. (** get next symbol **)
  789. PROCEDURE GetNextSymbol*(VAR symbol: Symbol): BOOLEAN;
  790. VAR s, token: LONGINT;
  791. BEGIN
  792. SkipBlanks;
  793. symbol.start := position;
  794. symbol.line := line;
  795. stringMaker.Clear;
  796. (* @@@ *)
  797. (*
  798. KernelLog.String("GetNextSymbol ");
  799. KernelLog.Char(ch);
  800. KernelLog.Ln();
  801. *)
  802. CASE ch OF
  803. EOT:
  804. s := EndOfText
  805. | DoubleQuote:
  806. s := StringLiteral;
  807. GetString(symbol)
  808. | SingleQuote:
  809. s := CharacterLiteral;
  810. GetCharacter(symbol)
  811. | '!':
  812. GetNextCharacter;
  813. IF ch = '=' THEN
  814. GetNextCharacter;
  815. s := ExclamationEqual
  816. ELSE
  817. s := Exclamation
  818. END
  819. | '%':
  820. GetNextCharacter;
  821. IF ch = '=' THEN
  822. GetNextCharacter;
  823. s := PercentEqual
  824. ELSE
  825. s := Percent
  826. END
  827. | '&':
  828. GetNextCharacter;
  829. IF ch = '=' THEN
  830. GetNextCharacter;
  831. s := AndEqual
  832. ELSIF ch = '&' THEN
  833. GetNextCharacter;
  834. s := AndAnd
  835. ELSE
  836. s := And
  837. END
  838. | '(':
  839. s := LeftParenthesis;
  840. GetNextCharacter
  841. | ')':
  842. s := RightParenthesis;
  843. GetNextCharacter
  844. | '*':
  845. GetNextCharacter;
  846. IF ch = '=' THEN
  847. GetNextCharacter;
  848. s := TimesEqual
  849. ELSE
  850. s := Times
  851. END
  852. | '+':
  853. GetNextCharacter;
  854. IF ch = '=' THEN
  855. GetNextCharacter;
  856. s := PlusEqual
  857. ELSIF ch = '+' THEN
  858. GetNextCharacter;
  859. s := PlusPlus
  860. ELSE
  861. s := Plus
  862. END
  863. | ',':
  864. s := Comma;
  865. GetNextCharacter
  866. | '-':
  867. GetNextCharacter;
  868. IF ch = '=' THEN
  869. GetNextCharacter;
  870. s := MinusEqual
  871. ELSIF ch = '-' THEN
  872. GetNextCharacter;
  873. s := MinusMinus
  874. ELSE
  875. s := Minus
  876. END
  877. | '.':
  878. GetNextCharacter;
  879. IF (ch >= '0') & (ch <= '9') THEN
  880. s := GetNumber(symbol, TRUE)
  881. ELSE
  882. s := Period
  883. END
  884. | '/':
  885. GetNextCharacter;
  886. IF ch = '=' THEN
  887. GetNextCharacter;
  888. s := SlashEqual
  889. ELSIF ch = '/' THEN
  890. GetNextCharacter;
  891. ReadSingleLineComment(symbol);
  892. s := Comment
  893. ELSIF ch = '*' THEN
  894. GetNextCharacter;
  895. ReadDelimitedComment(symbol);
  896. s := Comment
  897. ELSE
  898. s := Slash
  899. END
  900. | '0' .. '9':
  901. s := GetNumber(symbol, FALSE)
  902. | ':':
  903. s := Colon;
  904. GetNextCharacter
  905. | ';':
  906. s := Semicolon;
  907. GetNextCharacter
  908. | '<':
  909. GetNextCharacter;
  910. IF ch = '=' THEN
  911. GetNextCharacter;
  912. s := LessEqual
  913. ELSIF ch = '<' THEN
  914. GetNextCharacter;
  915. IF ch = '=' THEN
  916. GetNextCharacter;
  917. s := LeftShiftEqual
  918. ELSE
  919. s := LeftShift
  920. END
  921. ELSE
  922. s := Less
  923. END
  924. | '=':
  925. GetNextCharacter;
  926. IF ch = '=' THEN
  927. GetNextCharacter;
  928. s := EqualEqual
  929. ELSE
  930. s := Equal
  931. END
  932. | '>':
  933. GetNextCharacter;
  934. IF ch = '=' THEN
  935. GetNextCharacter;
  936. s := GreaterEqual
  937. ELSIF ch = '>' THEN
  938. GetNextCharacter;
  939. IF ch = '=' THEN
  940. GetNextCharacter;
  941. s := RightShiftEqual
  942. ELSE
  943. s := RightShift
  944. END
  945. ELSE
  946. s := Greater
  947. END
  948. | '?':
  949. GetNextCharacter;
  950. IF ch = '?' THEN
  951. GetNextCharacter;
  952. s := QuestionQuestion
  953. ELSE
  954. s := Question;
  955. END
  956. | '[':
  957. s := LeftBracket;
  958. GetNextCharacter
  959. | ']':
  960. s := RightBracket;
  961. GetNextCharacter
  962. | '^':
  963. GetNextCharacter;
  964. IF ch = '=' THEN
  965. GetNextCharacter;
  966. s := ArrowEqual
  967. ELSE
  968. s := Arrow
  969. END
  970. | '{':
  971. s := LeftBrace;
  972. GetNextCharacter
  973. | '|':
  974. GetNextCharacter;
  975. IF ch = '=' THEN
  976. GetNextCharacter;
  977. s := BarEqual
  978. ELSIF ch = '|' THEN
  979. GetNextCharacter;
  980. s := BarBar
  981. ELSE
  982. s := Bar
  983. END
  984. | '}':
  985. s := RightBrace;
  986. GetNextCharacter
  987. | '~':
  988. s := Tilde;
  989. GetNextCharacter
  990. | 'A' .. 'Z':
  991. s := Identifier;
  992. GetIdentifier(symbol)
  993. | 'a' .. 'z':
  994. s := Identifier;
  995. GetIdentifier(symbol);
  996. token := keywords.IndexByIdentifier(symbol.identifier);
  997. IF (token >= 0) THEN
  998. s := token
  999. END;
  1000. ELSE
  1001. s := Identifier;
  1002. GetIdentifier(symbol)
  1003. END;
  1004. symbol.token := s;
  1005. symbol.end := position;
  1006. IF Trace THEN
  1007. OutSymbol(D.Log, symbol);
  1008. D.Ln;
  1009. END;
  1010. RETURN ~error
  1011. END GetNextSymbol;
  1012. PROCEDURE ResetError*();
  1013. BEGIN
  1014. error := FALSE
  1015. END ResetError;
  1016. (** set the diagnostics mode of the scanner
  1017. (diagnostics = NIL ==> no report) and reset the error state
  1018. intended for silent symbol peeeking after the end of a module *)
  1019. PROCEDURE ResetErrorDiagnostics*(VAR diagnostics: Diagnostics.Diagnostics);
  1020. VAR b: BOOLEAN;
  1021. d: Diagnostics.Diagnostics;
  1022. BEGIN
  1023. error := FALSE;
  1024. d := SELF.diagnostics;
  1025. SELF.diagnostics := diagnostics;
  1026. diagnostics := d;
  1027. END ResetErrorDiagnostics;
  1028. END Scanner;
  1029. (** return a new scanner on a stream, error output via diagnostics **)
  1030. PROCEDURE NewScanner*(
  1031. CONST source: ARRAY OF CHAR;
  1032. reader: Streams.Reader;
  1033. position: LONGINT;
  1034. diagnostics: Diagnostics.Diagnostics): Scanner;
  1035. VAR s: Scanner;
  1036. BEGIN
  1037. NEW( s, source, reader, position, diagnostics );
  1038. RETURN s;
  1039. END NewScanner;
  1040. VAR
  1041. reservedCharacter: ARRAY 256 OF BOOLEAN;
  1042. tokens-: ARRAY EndOfText+1 OF Keyword;
  1043. keywords: KeywordTable;
  1044. PROCEDURE SymbolToString*(CONST symbol: Symbol; VAR str: ARRAY OF CHAR);
  1045. VAR id: StringPool.Index;
  1046. BEGIN
  1047. CASE symbol.token OF
  1048. Identifier, IntegerLiteral, RealLiteral:
  1049. COPY(symbol.identifierString, str)
  1050. | StringLiteral, Comment:
  1051. ASSERT(LEN(str) >= LEN(symbol.string^));
  1052. COPY(symbol.string^, str);
  1053. ELSE
  1054. GetKeyword(symbol.token, id);
  1055. IF id < 0 THEN
  1056. str[0] := 0X
  1057. ELSE
  1058. StringPool.GetString(id, str) END;
  1059. END;
  1060. END SymbolToString;
  1061. (** debugging output **)
  1062. PROCEDURE OutSymbol*(w: Streams.Writer; CONST symbol: Symbol);
  1063. VAR str: ARRAY 256 OF CHAR;
  1064. i: LONGINT;
  1065. PROCEDURE OutChar(ch: CHAR);
  1066. BEGIN
  1067. IF ((ch >= 20X) & (ch < 7FX)) OR ((ch > 0A0X) & (ch # 0ADX)) THEN
  1068. w.Char(ch);
  1069. ELSE
  1070. w.Char(Backslash);
  1071. w.Char('x');
  1072. w.Hex(ORD(ch), 1);
  1073. END;
  1074. END OutChar;
  1075. BEGIN
  1076. w.Int(symbol.start, 1);
  1077. w.String("-");
  1078. w.Int(symbol.end, 1);
  1079. w.String(":");
  1080. w.String(tokens[symbol.token]);
  1081. IF (symbol.token = IntegerLiteral) OR (symbol.token = RealLiteral) THEN
  1082. CASE symbol.numberType OF
  1083. IntNumber:
  1084. w.String("(int)")
  1085. | LongNumber:
  1086. w.String("(long)")
  1087. | FloatNumber:
  1088. w.String("(float)")
  1089. | DoubleNumber:
  1090. w.String("(double)")
  1091. END;
  1092. ELSIF symbol.token = CharacterLiteral THEN
  1093. w.String(":");
  1094. w.Char("'");
  1095. OutChar(symbol.character);
  1096. w.Char("'");
  1097. ELSIF symbol.token = StringLiteral THEN
  1098. w.String(":");
  1099. w.Char('"');
  1100. i := 0;
  1101. WHILE symbol.string^[i] # 0X DO
  1102. OutChar(symbol.string^[i]);
  1103. INC(i);
  1104. END;
  1105. w.Char('"');
  1106. ELSIF symbol.token = Comment THEN
  1107. w.String("/*");
  1108. w.String(symbol.string^);
  1109. w.String("*/");
  1110. ELSE
  1111. SymbolToString(symbol, str);
  1112. w.String(": ");
  1113. w.String(str);
  1114. END
  1115. END OutSymbol;
  1116. (** reserved characters are the characters that may not occur within an identifier **)
  1117. PROCEDURE InitReservedCharacters;
  1118. VAR i: LONGINT;
  1119. BEGIN
  1120. FOR i := 0 TO LEN(reservedCharacter) - 1 DO
  1121. CASE CHR(i) OF
  1122. | 'a' .. 'z', 'A' .. 'Z':
  1123. reservedCharacter[i] := FALSE;
  1124. | '0'..'9':
  1125. reservedCharacter[i] := FALSE;
  1126. | '_':
  1127. reservedCharacter[i] := FALSE
  1128. ELSE
  1129. reservedCharacter[i] := TRUE
  1130. END;
  1131. END;
  1132. END InitReservedCharacters;
  1133. (* get keyword by token *)
  1134. PROCEDURE GetKeyword*(token: LONGINT; VAR identifier: IdentifierType);
  1135. BEGIN
  1136. keywords.IdentifierByIndex(token, identifier);
  1137. END GetKeyword;
  1138. PROCEDURE InitTokens;
  1139. VAR i: LONGINT;
  1140. BEGIN
  1141. tokens[None] := "None";
  1142. (* operators and punctuators *)
  1143. tokens[Exclamation] := "Exclamation";
  1144. tokens[ExclamationEqual] := "ExclamationEqual";
  1145. tokens[Percent] := "Percent";
  1146. tokens[PercentEqual] := "PercentEqual";
  1147. tokens[And] := "And";
  1148. tokens[AndEqual] := "AndEqual";
  1149. tokens[AndAnd] := "AndAnd";
  1150. tokens[LeftParenthesis] := "LeftParenthesis";
  1151. tokens[RightParenthesis] := "RightParenthesis";
  1152. tokens[Times] := "Times";
  1153. tokens[TimesEqual] := "TimesEqual";
  1154. tokens[Plus] := "Plus";
  1155. tokens[PlusEqual] := "PlusEqual";
  1156. tokens[PlusPlus] := "PlusPlus";
  1157. tokens[Comma] := "Comma";
  1158. tokens[Minus] := "Minus";
  1159. tokens[MinusEqual] := "MinusEqual";
  1160. tokens[MinusMinus] := "MinusMinus";
  1161. tokens[Period] := "Period";
  1162. tokens[Slash] := "Slash";
  1163. tokens[SlashEqual] := "SlashEqual";
  1164. tokens[Colon] := "Colon";
  1165. tokens[Semicolon] := "Semicolon";
  1166. tokens[Less] := "Less";
  1167. tokens[LessEqual] := "LessEqual";
  1168. tokens[LeftShift] := "LeftShift";
  1169. tokens[LeftShiftEqual] := "LeftShiftEqual";
  1170. tokens[Equal] := "Equal";
  1171. tokens[EqualEqual] := "EqualEqual";
  1172. tokens[Greater] := "Greater";
  1173. tokens[GreaterEqual] := "GreaterEqual";
  1174. tokens[RightShift] := "RightShift";
  1175. tokens[RightShiftEqual] := "RightShiftEqual";
  1176. tokens[LeftBracket] := "LeftBracket";
  1177. tokens[RightBracket] := "RightBracket";
  1178. tokens[Arrow] := "Arrow";
  1179. tokens[ArrowEqual] := "ArrowEqual";
  1180. tokens[LeftBrace] := "LeftBrace";
  1181. tokens[Bar] := "Bar";
  1182. tokens[BarEqual] := "BarEqual";
  1183. tokens[BarBar] := "BarBar";
  1184. tokens[RightBrace] := "RightBrace";
  1185. tokens[Tilde] := "Tilde";
  1186. (* keywords *)
  1187. tokens[As] := "As";
  1188. tokens[Base] := "Base";
  1189. tokens[Bool] := "Bool";
  1190. tokens[Break] := "Break";
  1191. tokens[Case] := "Case";
  1192. tokens[Char] := "Char";
  1193. tokens[Class] := "Class";
  1194. tokens[Const] := "Const";
  1195. tokens[Default] := "Default";
  1196. tokens[Delegate] := "Delegate";
  1197. tokens[Do] := "Do";
  1198. tokens[Double] := "Double";
  1199. tokens[Else] := "Else";
  1200. tokens[False] := "False";
  1201. tokens[Float] := "Float";
  1202. tokens[For] := "For";
  1203. tokens[If] := "If";
  1204. tokens[Import] := "Import";
  1205. tokens[Int] := "Int";
  1206. tokens[Internal] := "Internal";
  1207. tokens[Is] := "Is";
  1208. tokens[Long] := "Long";
  1209. tokens[Module] := "Module";
  1210. tokens[New] := "New";
  1211. tokens[Null] := "Null";
  1212. tokens[Object] := "Object";
  1213. tokens[Public] := "Public";
  1214. tokens[Readonly] := "Readonly";
  1215. tokens[Ref] := "Ref";
  1216. tokens[Return] := "Return";
  1217. tokens[Sbyte] := "Sbyte";
  1218. tokens[Short] := "Short";
  1219. tokens[String] := "String";
  1220. tokens[Struct] := "Struct";
  1221. tokens[Switch] := "Switch";
  1222. tokens[This] := "This";
  1223. tokens[True] := "True";
  1224. tokens[Void] := "Void";
  1225. tokens[While] := "While";
  1226. tokens[Identifier] := "Identifier";
  1227. tokens[IntegerLiteral] := "IntegerLiteral";
  1228. tokens[RealLiteral] := "RealLiteral";
  1229. tokens[CharacterLiteral] := "CharacterLiteral";
  1230. tokens[StringLiteral] := "StringLiteral";
  1231. tokens[Comment] := "Comment";
  1232. tokens[EndOfText] := "EndOfText";
  1233. (* Active Cells *)
  1234. tokens[Cell] := "Cell";
  1235. tokens[Cellnet] := "Cellnet";
  1236. tokens[In] := "In";
  1237. tokens[Out] := "Out";
  1238. tokens[Select] := "Select";
  1239. tokens[Question] := "Question";
  1240. tokens[QuestionQuestion] := "QuestionQuestion";
  1241. FOR i := 0 TO EndOfText DO
  1242. ASSERT(tokens[i] # "")
  1243. END;
  1244. END InitTokens;
  1245. (** enter keywords in the list of keywords **)
  1246. PROCEDURE InitKeywords;
  1247. PROCEDURE Enter(CONST name: ARRAY OF CHAR; token: LONGINT);
  1248. BEGIN
  1249. keywords.PutString(name, token);
  1250. Basic.SetErrorExpected(token, name);
  1251. END Enter;
  1252. BEGIN
  1253. NEW(keywords,EndOfText+1);
  1254. (* keywords *)
  1255. Enter("as", As);
  1256. Enter("base", Base);
  1257. Enter("bool", Bool);
  1258. Enter("break", Break);
  1259. Enter("case", Case);
  1260. Enter("char", Char);
  1261. Enter("class", Class);
  1262. Enter("const", Const);
  1263. Enter("default", Default);
  1264. Enter("delegate", Delegate);
  1265. Enter("do", Do);
  1266. Enter("double", Double);
  1267. Enter("else", Else);
  1268. Enter("false", False);
  1269. Enter("float", Float);
  1270. Enter("for", For);
  1271. Enter("if", If);
  1272. Enter("import", Import);
  1273. Enter("int", Int);
  1274. Enter("internal", Internal);
  1275. Enter("is", Is);
  1276. Enter("long", Long);
  1277. Enter("module", Module);
  1278. Enter("new", New);
  1279. Enter("null", Null);
  1280. Enter("object", Object);
  1281. Enter("public", Public);
  1282. Enter("readonly", Readonly);
  1283. Enter("ref", Ref);
  1284. Enter("return", Return);
  1285. Enter("sbyte", Sbyte);
  1286. Enter("short", Short);
  1287. Enter("string", String);
  1288. Enter("struct", Struct);
  1289. Enter("switch", Switch);
  1290. Enter("this", This);
  1291. Enter("true", True);
  1292. Enter("void", Void);
  1293. Enter("while", While);
  1294. (* operators and punctuators *)
  1295. Enter("!", Exclamation);
  1296. Enter("!=", ExclamationEqual);
  1297. Enter("%", Percent);
  1298. Enter("%=", PercentEqual);
  1299. Enter("&", And);
  1300. Enter("&=", AndEqual);
  1301. Enter("&&", AndAnd);
  1302. Enter("(", LeftParenthesis);
  1303. Enter(")", RightParenthesis);
  1304. Enter("*", Times);
  1305. Enter("*=", TimesEqual);
  1306. Enter("+", Plus);
  1307. Enter("+=", PlusEqual);
  1308. Enter("++", PlusPlus);
  1309. Enter(",", Comma);
  1310. Enter("-", Minus);
  1311. Enter("-=", MinusEqual);
  1312. Enter("--", MinusMinus);
  1313. Enter(".", Period);
  1314. Enter("/", Slash);
  1315. Enter("/=", SlashEqual);
  1316. Enter(":", Colon);
  1317. Enter(";", Semicolon);
  1318. Enter("<", Less);
  1319. Enter("<=", LessEqual);
  1320. Enter("<<", LeftShift);
  1321. Enter("<<=", LeftShiftEqual);
  1322. Enter("=", Equal);
  1323. Enter("==", EqualEqual);
  1324. Enter(">", Greater);
  1325. Enter(">=", GreaterEqual);
  1326. Enter(">>", RightShift);
  1327. Enter(">>=", RightShiftEqual);
  1328. Enter("[", LeftBracket);
  1329. Enter("]", RightBracket);
  1330. Enter("^", Arrow);
  1331. Enter("^=", ArrowEqual);
  1332. Enter("{", LeftBrace);
  1333. Enter("|", Bar);
  1334. Enter("}", BarEqual);
  1335. Enter("||", BarBar);
  1336. Enter("}", RightBrace);
  1337. Enter("~", Tilde);
  1338. (* Active Cells *)
  1339. Enter("cell", Cell);
  1340. Enter("cellnet", Cellnet);
  1341. Enter("in", In);
  1342. Enter("out", Out);
  1343. Enter("select", Select);
  1344. Enter("?", Question);
  1345. Enter("??", QuestionQuestion);
  1346. Basic.SetErrorMessage(Identifier, "missing identifier");
  1347. Basic.SetErrorMessage(IntegerLiteral, "missing integer literal");
  1348. Basic.SetErrorMessage(RealLiteral, "missing real literal");
  1349. Basic.SetErrorMessage(CharacterLiteral, "missing character literal");
  1350. Basic.SetErrorMessage(StringLiteral, "missing string literal");
  1351. END InitKeywords;
  1352. (** debugging / reporting **)
  1353. PROCEDURE ReportKeywords*(context: Commands.Context);
  1354. VAR i: LONGINT;
  1355. name: Keyword;
  1356. BEGIN
  1357. FOR i := 0 TO EndOfText DO
  1358. context.out.Int(i, 1);
  1359. context.out.String(": ");
  1360. context.out.Char('"');
  1361. keywords.StringByIndex(i, name);
  1362. context.out.String(name);
  1363. context.out.Char('"');
  1364. context.out.Ln;
  1365. END;
  1366. END ReportKeywords;
  1367. (*
  1368. PROCEDURE TestScanner*(context: Commands.Context);
  1369. VAR filename: ARRAY 256 OF CHAR;
  1370. reader: Streams.Reader;
  1371. scanner: Scanner;
  1372. sym: Symbol;
  1373. BEGIN
  1374. context.arg.SkipWhitespace;
  1375. context.arg.String(filename);
  1376. reader := TextUtilities.GetTextReader(filename);
  1377. scanner := NewScanner(filename, reader, 0, NIL);
  1378. REPEAT
  1379. IF scanner.GetNextSymbol(sym) THEN
  1380. OutSymbol(context.out, sym);
  1381. context.out.Ln;
  1382. END;
  1383. UNTIL scanner.error OR (sym.token = EndOfText)
  1384. END TestScanner;
  1385. *)
  1386. BEGIN
  1387. InitReservedCharacters;
  1388. InitTokens;
  1389. InitKeywords
  1390. END FoxCSharpScanner.