FoxCSharpScanner.Mod 46 KB

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