FoxCSharpScanner.Mod 46 KB

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