FoxCSharpScanner.Mod 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466
  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. IF diagnostics # NIL THEN
  204. diagnostics.Error(source^, position.start, 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.start, 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.start);
  223. IF ch = LF THEN
  224. INC(position.line); position.linepos := position.start;
  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.position := position;
  794. stringMaker.Clear;
  795. (* @@@ *)
  796. (*
  797. KernelLog.String("GetNextSymbol ");
  798. KernelLog.Char(ch);
  799. KernelLog.Ln();
  800. *)
  801. CASE ch OF
  802. EOT:
  803. s := EndOfText
  804. | DoubleQuote:
  805. s := StringLiteral;
  806. GetString(symbol)
  807. | SingleQuote:
  808. s := CharacterLiteral;
  809. GetCharacter(symbol)
  810. | '!':
  811. GetNextCharacter;
  812. IF ch = '=' THEN
  813. GetNextCharacter;
  814. s := ExclamationEqual
  815. ELSE
  816. s := Exclamation
  817. END
  818. | '%':
  819. GetNextCharacter;
  820. IF ch = '=' THEN
  821. GetNextCharacter;
  822. s := PercentEqual
  823. ELSE
  824. s := Percent
  825. END
  826. | '&':
  827. GetNextCharacter;
  828. IF ch = '=' THEN
  829. GetNextCharacter;
  830. s := AndEqual
  831. ELSIF ch = '&' THEN
  832. GetNextCharacter;
  833. s := AndAnd
  834. ELSE
  835. s := And
  836. END
  837. | '(':
  838. s := LeftParenthesis;
  839. GetNextCharacter
  840. | ')':
  841. s := RightParenthesis;
  842. GetNextCharacter
  843. | '*':
  844. GetNextCharacter;
  845. IF ch = '=' THEN
  846. GetNextCharacter;
  847. s := TimesEqual
  848. ELSE
  849. s := Times
  850. END
  851. | '+':
  852. GetNextCharacter;
  853. IF ch = '=' THEN
  854. GetNextCharacter;
  855. s := PlusEqual
  856. ELSIF ch = '+' THEN
  857. GetNextCharacter;
  858. s := PlusPlus
  859. ELSE
  860. s := Plus
  861. END
  862. | ',':
  863. s := Comma;
  864. GetNextCharacter
  865. | '-':
  866. GetNextCharacter;
  867. IF ch = '=' THEN
  868. GetNextCharacter;
  869. s := MinusEqual
  870. ELSIF ch = '-' THEN
  871. GetNextCharacter;
  872. s := MinusMinus
  873. ELSE
  874. s := Minus
  875. END
  876. | '.':
  877. GetNextCharacter;
  878. IF (ch >= '0') & (ch <= '9') THEN
  879. s := GetNumber(symbol, TRUE)
  880. ELSE
  881. s := Period
  882. END
  883. | '/':
  884. GetNextCharacter;
  885. IF ch = '=' THEN
  886. GetNextCharacter;
  887. s := SlashEqual
  888. ELSIF ch = '/' THEN
  889. GetNextCharacter;
  890. ReadSingleLineComment(symbol);
  891. s := Comment
  892. ELSIF ch = '*' THEN
  893. GetNextCharacter;
  894. ReadDelimitedComment(symbol);
  895. s := Comment
  896. ELSE
  897. s := Slash
  898. END
  899. | '0' .. '9':
  900. s := GetNumber(symbol, FALSE)
  901. | ':':
  902. s := Colon;
  903. GetNextCharacter
  904. | ';':
  905. s := Semicolon;
  906. GetNextCharacter
  907. | '<':
  908. GetNextCharacter;
  909. IF ch = '=' THEN
  910. GetNextCharacter;
  911. s := LessEqual
  912. ELSIF ch = '<' THEN
  913. GetNextCharacter;
  914. IF ch = '=' THEN
  915. GetNextCharacter;
  916. s := LeftShiftEqual
  917. ELSE
  918. s := LeftShift
  919. END
  920. ELSE
  921. s := Less
  922. END
  923. | '=':
  924. GetNextCharacter;
  925. IF ch = '=' THEN
  926. GetNextCharacter;
  927. s := EqualEqual
  928. ELSE
  929. s := Equal
  930. END
  931. | '>':
  932. GetNextCharacter;
  933. IF ch = '=' THEN
  934. GetNextCharacter;
  935. s := GreaterEqual
  936. ELSIF ch = '>' THEN
  937. GetNextCharacter;
  938. IF ch = '=' THEN
  939. GetNextCharacter;
  940. s := RightShiftEqual
  941. ELSE
  942. s := RightShift
  943. END
  944. ELSE
  945. s := Greater
  946. END
  947. | '?':
  948. GetNextCharacter;
  949. IF ch = '?' THEN
  950. GetNextCharacter;
  951. s := QuestionQuestion
  952. ELSE
  953. s := Question;
  954. END
  955. | '[':
  956. s := LeftBracket;
  957. GetNextCharacter
  958. | ']':
  959. s := RightBracket;
  960. GetNextCharacter
  961. | '^':
  962. GetNextCharacter;
  963. IF ch = '=' THEN
  964. GetNextCharacter;
  965. s := ArrowEqual
  966. ELSE
  967. s := Arrow
  968. END
  969. | '{':
  970. s := LeftBrace;
  971. GetNextCharacter
  972. | '|':
  973. GetNextCharacter;
  974. IF ch = '=' THEN
  975. GetNextCharacter;
  976. s := BarEqual
  977. ELSIF ch = '|' THEN
  978. GetNextCharacter;
  979. s := BarBar
  980. ELSE
  981. s := Bar
  982. END
  983. | '}':
  984. s := RightBrace;
  985. GetNextCharacter
  986. | '~':
  987. s := Tilde;
  988. GetNextCharacter
  989. | 'A' .. 'Z':
  990. s := Identifier;
  991. GetIdentifier(symbol)
  992. | 'a' .. 'z':
  993. s := Identifier;
  994. GetIdentifier(symbol);
  995. token := keywords.IndexByIdentifier(symbol.identifier);
  996. IF (token >= 0) THEN
  997. s := token
  998. END;
  999. ELSE
  1000. s := Identifier;
  1001. GetIdentifier(symbol)
  1002. END;
  1003. symbol.token := s;
  1004. symbol.position.end := position.start;
  1005. IF Trace THEN
  1006. OutSymbol(D.Log, symbol);
  1007. D.Ln;
  1008. END;
  1009. RETURN ~error
  1010. END GetNextSymbol;
  1011. PROCEDURE ResetError*();
  1012. BEGIN
  1013. error := FALSE
  1014. END ResetError;
  1015. (** set the diagnostics mode of the scanner
  1016. (diagnostics = NIL ==> no report) and reset the error state
  1017. intended for silent symbol peeeking after the end of a module *)
  1018. PROCEDURE ResetErrorDiagnostics*(VAR diagnostics: Diagnostics.Diagnostics);
  1019. VAR b: BOOLEAN;
  1020. d: Diagnostics.Diagnostics;
  1021. BEGIN
  1022. error := FALSE;
  1023. d := SELF.diagnostics;
  1024. SELF.diagnostics := diagnostics;
  1025. diagnostics := d;
  1026. END ResetErrorDiagnostics;
  1027. END Scanner;
  1028. (** return a new scanner on a stream, error output via diagnostics **)
  1029. PROCEDURE NewScanner*(
  1030. CONST source: ARRAY OF CHAR;
  1031. reader: Streams.Reader;
  1032. position: LONGINT;
  1033. diagnostics: Diagnostics.Diagnostics): Scanner;
  1034. VAR s: Scanner;
  1035. BEGIN
  1036. NEW( s, source, reader, position, diagnostics );
  1037. RETURN s;
  1038. END NewScanner;
  1039. VAR
  1040. reservedCharacter: ARRAY 256 OF BOOLEAN;
  1041. tokens-: ARRAY EndOfText+1 OF Keyword;
  1042. keywords: KeywordTable;
  1043. PROCEDURE SymbolToString*(CONST symbol: Symbol; VAR str: ARRAY OF CHAR);
  1044. VAR id: StringPool.Index;
  1045. BEGIN
  1046. CASE symbol.token OF
  1047. Identifier, IntegerLiteral, RealLiteral:
  1048. COPY(symbol.identifierString, str)
  1049. | StringLiteral, Comment:
  1050. ASSERT(LEN(str) >= LEN(symbol.string^));
  1051. COPY(symbol.string^, str);
  1052. ELSE
  1053. GetKeyword(symbol.token, id);
  1054. IF id < 0 THEN
  1055. str[0] := 0X
  1056. ELSE
  1057. StringPool.GetString(id, str) END;
  1058. END;
  1059. END SymbolToString;
  1060. (** debugging output **)
  1061. PROCEDURE OutSymbol*(w: Streams.Writer; CONST symbol: Symbol);
  1062. VAR str: ARRAY 256 OF CHAR;
  1063. i: LONGINT;
  1064. PROCEDURE OutChar(ch: CHAR);
  1065. BEGIN
  1066. IF ((ch >= 20X) & (ch < 7FX)) OR ((ch > 0A0X) & (ch # 0ADX)) THEN
  1067. w.Char(ch);
  1068. ELSE
  1069. w.Char(Backslash);
  1070. w.Char('x');
  1071. w.Hex(ORD(ch), 1);
  1072. END;
  1073. END OutChar;
  1074. BEGIN
  1075. w.Int(symbol.position.start, 1);
  1076. w.String("-");
  1077. w.Int(symbol.position.end, 1);
  1078. w.String(":");
  1079. w.String(tokens[symbol.token]);
  1080. IF (symbol.token = IntegerLiteral) OR (symbol.token = RealLiteral) THEN
  1081. CASE symbol.numberType OF
  1082. IntNumber:
  1083. w.String("(int)")
  1084. | LongNumber:
  1085. w.String("(long)")
  1086. | FloatNumber:
  1087. w.String("(float)")
  1088. | DoubleNumber:
  1089. w.String("(double)")
  1090. END;
  1091. ELSIF symbol.token = CharacterLiteral THEN
  1092. w.String(":");
  1093. w.Char("'");
  1094. OutChar(symbol.character);
  1095. w.Char("'");
  1096. ELSIF symbol.token = StringLiteral THEN
  1097. w.String(":");
  1098. w.Char('"');
  1099. i := 0;
  1100. WHILE symbol.string^[i] # 0X DO
  1101. OutChar(symbol.string^[i]);
  1102. INC(i);
  1103. END;
  1104. w.Char('"');
  1105. ELSIF symbol.token = Comment THEN
  1106. w.String("/*");
  1107. w.String(symbol.string^);
  1108. w.String("*/");
  1109. ELSE
  1110. SymbolToString(symbol, str);
  1111. w.String(": ");
  1112. w.String(str);
  1113. END
  1114. END OutSymbol;
  1115. (** reserved characters are the characters that may not occur within an identifier **)
  1116. PROCEDURE InitReservedCharacters;
  1117. VAR i: LONGINT;
  1118. BEGIN
  1119. FOR i := 0 TO LEN(reservedCharacter) - 1 DO
  1120. CASE CHR(i) OF
  1121. | 'a' .. 'z', 'A' .. 'Z':
  1122. reservedCharacter[i] := FALSE;
  1123. | '0'..'9':
  1124. reservedCharacter[i] := FALSE;
  1125. | '_':
  1126. reservedCharacter[i] := FALSE
  1127. ELSE
  1128. reservedCharacter[i] := TRUE
  1129. END;
  1130. END;
  1131. END InitReservedCharacters;
  1132. (* get keyword by token *)
  1133. PROCEDURE GetKeyword*(token: LONGINT; VAR identifier: IdentifierType);
  1134. BEGIN
  1135. keywords.IdentifierByIndex(token, identifier);
  1136. END GetKeyword;
  1137. PROCEDURE InitTokens;
  1138. VAR i: LONGINT;
  1139. BEGIN
  1140. tokens[None] := "None";
  1141. (* operators and punctuators *)
  1142. tokens[Exclamation] := "Exclamation";
  1143. tokens[ExclamationEqual] := "ExclamationEqual";
  1144. tokens[Percent] := "Percent";
  1145. tokens[PercentEqual] := "PercentEqual";
  1146. tokens[And] := "And";
  1147. tokens[AndEqual] := "AndEqual";
  1148. tokens[AndAnd] := "AndAnd";
  1149. tokens[LeftParenthesis] := "LeftParenthesis";
  1150. tokens[RightParenthesis] := "RightParenthesis";
  1151. tokens[Times] := "Times";
  1152. tokens[TimesEqual] := "TimesEqual";
  1153. tokens[Plus] := "Plus";
  1154. tokens[PlusEqual] := "PlusEqual";
  1155. tokens[PlusPlus] := "PlusPlus";
  1156. tokens[Comma] := "Comma";
  1157. tokens[Minus] := "Minus";
  1158. tokens[MinusEqual] := "MinusEqual";
  1159. tokens[MinusMinus] := "MinusMinus";
  1160. tokens[Period] := "Period";
  1161. tokens[Slash] := "Slash";
  1162. tokens[SlashEqual] := "SlashEqual";
  1163. tokens[Colon] := "Colon";
  1164. tokens[Semicolon] := "Semicolon";
  1165. tokens[Less] := "Less";
  1166. tokens[LessEqual] := "LessEqual";
  1167. tokens[LeftShift] := "LeftShift";
  1168. tokens[LeftShiftEqual] := "LeftShiftEqual";
  1169. tokens[Equal] := "Equal";
  1170. tokens[EqualEqual] := "EqualEqual";
  1171. tokens[Greater] := "Greater";
  1172. tokens[GreaterEqual] := "GreaterEqual";
  1173. tokens[RightShift] := "RightShift";
  1174. tokens[RightShiftEqual] := "RightShiftEqual";
  1175. tokens[LeftBracket] := "LeftBracket";
  1176. tokens[RightBracket] := "RightBracket";
  1177. tokens[Arrow] := "Arrow";
  1178. tokens[ArrowEqual] := "ArrowEqual";
  1179. tokens[LeftBrace] := "LeftBrace";
  1180. tokens[Bar] := "Bar";
  1181. tokens[BarEqual] := "BarEqual";
  1182. tokens[BarBar] := "BarBar";
  1183. tokens[RightBrace] := "RightBrace";
  1184. tokens[Tilde] := "Tilde";
  1185. (* keywords *)
  1186. tokens[As] := "As";
  1187. tokens[Base] := "Base";
  1188. tokens[Bool] := "Bool";
  1189. tokens[Break] := "Break";
  1190. tokens[Case] := "Case";
  1191. tokens[Char] := "Char";
  1192. tokens[Class] := "Class";
  1193. tokens[Const] := "Const";
  1194. tokens[Default] := "Default";
  1195. tokens[Delegate] := "Delegate";
  1196. tokens[Do] := "Do";
  1197. tokens[Double] := "Double";
  1198. tokens[Else] := "Else";
  1199. tokens[False] := "False";
  1200. tokens[Float] := "Float";
  1201. tokens[For] := "For";
  1202. tokens[If] := "If";
  1203. tokens[Import] := "Import";
  1204. tokens[Int] := "Int";
  1205. tokens[Internal] := "Internal";
  1206. tokens[Is] := "Is";
  1207. tokens[Long] := "Long";
  1208. tokens[Module] := "Module";
  1209. tokens[New] := "New";
  1210. tokens[Null] := "Null";
  1211. tokens[Object] := "Object";
  1212. tokens[Public] := "Public";
  1213. tokens[Readonly] := "Readonly";
  1214. tokens[Ref] := "Ref";
  1215. tokens[Return] := "Return";
  1216. tokens[Sbyte] := "Sbyte";
  1217. tokens[Short] := "Short";
  1218. tokens[String] := "String";
  1219. tokens[Struct] := "Struct";
  1220. tokens[Switch] := "Switch";
  1221. tokens[This] := "This";
  1222. tokens[True] := "True";
  1223. tokens[Void] := "Void";
  1224. tokens[While] := "While";
  1225. tokens[Identifier] := "Identifier";
  1226. tokens[IntegerLiteral] := "IntegerLiteral";
  1227. tokens[RealLiteral] := "RealLiteral";
  1228. tokens[CharacterLiteral] := "CharacterLiteral";
  1229. tokens[StringLiteral] := "StringLiteral";
  1230. tokens[Comment] := "Comment";
  1231. tokens[EndOfText] := "EndOfText";
  1232. (* Active Cells *)
  1233. tokens[Cell] := "Cell";
  1234. tokens[Cellnet] := "Cellnet";
  1235. tokens[In] := "In";
  1236. tokens[Out] := "Out";
  1237. tokens[Select] := "Select";
  1238. tokens[Question] := "Question";
  1239. tokens[QuestionQuestion] := "QuestionQuestion";
  1240. FOR i := 0 TO EndOfText DO
  1241. ASSERT(tokens[i] # "")
  1242. END;
  1243. END InitTokens;
  1244. (** enter keywords in the list of keywords **)
  1245. PROCEDURE InitKeywords;
  1246. PROCEDURE Enter(CONST name: ARRAY OF CHAR; token: LONGINT);
  1247. BEGIN
  1248. keywords.PutString(name, token);
  1249. Basic.SetErrorExpected(token, name);
  1250. END Enter;
  1251. BEGIN
  1252. NEW(keywords,EndOfText+1);
  1253. (* keywords *)
  1254. Enter("as", As);
  1255. Enter("base", Base);
  1256. Enter("bool", Bool);
  1257. Enter("break", Break);
  1258. Enter("case", Case);
  1259. Enter("char", Char);
  1260. Enter("class", Class);
  1261. Enter("const", Const);
  1262. Enter("default", Default);
  1263. Enter("delegate", Delegate);
  1264. Enter("do", Do);
  1265. Enter("double", Double);
  1266. Enter("else", Else);
  1267. Enter("false", False);
  1268. Enter("float", Float);
  1269. Enter("for", For);
  1270. Enter("if", If);
  1271. Enter("import", Import);
  1272. Enter("int", Int);
  1273. Enter("internal", Internal);
  1274. Enter("is", Is);
  1275. Enter("long", Long);
  1276. Enter("module", Module);
  1277. Enter("new", New);
  1278. Enter("null", Null);
  1279. Enter("object", Object);
  1280. Enter("public", Public);
  1281. Enter("readonly", Readonly);
  1282. Enter("ref", Ref);
  1283. Enter("return", Return);
  1284. Enter("sbyte", Sbyte);
  1285. Enter("short", Short);
  1286. Enter("string", String);
  1287. Enter("struct", Struct);
  1288. Enter("switch", Switch);
  1289. Enter("this", This);
  1290. Enter("true", True);
  1291. Enter("void", Void);
  1292. Enter("while", While);
  1293. (* operators and punctuators *)
  1294. Enter("!", Exclamation);
  1295. Enter("!=", ExclamationEqual);
  1296. Enter("%", Percent);
  1297. Enter("%=", PercentEqual);
  1298. Enter("&", And);
  1299. Enter("&=", AndEqual);
  1300. Enter("&&", AndAnd);
  1301. Enter("(", LeftParenthesis);
  1302. Enter(")", RightParenthesis);
  1303. Enter("*", Times);
  1304. Enter("*=", TimesEqual);
  1305. Enter("+", Plus);
  1306. Enter("+=", PlusEqual);
  1307. Enter("++", PlusPlus);
  1308. Enter(",", Comma);
  1309. Enter("-", Minus);
  1310. Enter("-=", MinusEqual);
  1311. Enter("--", MinusMinus);
  1312. Enter(".", Period);
  1313. Enter("/", Slash);
  1314. Enter("/=", SlashEqual);
  1315. Enter(":", Colon);
  1316. Enter(";", Semicolon);
  1317. Enter("<", Less);
  1318. Enter("<=", LessEqual);
  1319. Enter("<<", LeftShift);
  1320. Enter("<<=", LeftShiftEqual);
  1321. Enter("=", Equal);
  1322. Enter("==", EqualEqual);
  1323. Enter(">", Greater);
  1324. Enter(">=", GreaterEqual);
  1325. Enter(">>", RightShift);
  1326. Enter(">>=", RightShiftEqual);
  1327. Enter("[", LeftBracket);
  1328. Enter("]", RightBracket);
  1329. Enter("^", Arrow);
  1330. Enter("^=", ArrowEqual);
  1331. Enter("{", LeftBrace);
  1332. Enter("|", Bar);
  1333. Enter("}", BarEqual);
  1334. Enter("||", BarBar);
  1335. Enter("}", RightBrace);
  1336. Enter("~", Tilde);
  1337. (* Active Cells *)
  1338. Enter("cell", Cell);
  1339. Enter("cellnet", Cellnet);
  1340. Enter("in", In);
  1341. Enter("out", Out);
  1342. Enter("select", Select);
  1343. Enter("?", Question);
  1344. Enter("??", QuestionQuestion);
  1345. Basic.SetErrorMessage(Identifier, "missing identifier");
  1346. Basic.SetErrorMessage(IntegerLiteral, "missing integer literal");
  1347. Basic.SetErrorMessage(RealLiteral, "missing real literal");
  1348. Basic.SetErrorMessage(CharacterLiteral, "missing character literal");
  1349. Basic.SetErrorMessage(StringLiteral, "missing string literal");
  1350. END InitKeywords;
  1351. (** debugging / reporting **)
  1352. PROCEDURE ReportKeywords*(context: Commands.Context);
  1353. VAR i: LONGINT;
  1354. name: Keyword;
  1355. BEGIN
  1356. FOR i := 0 TO EndOfText DO
  1357. context.out.Int(i, 1);
  1358. context.out.String(": ");
  1359. context.out.Char('"');
  1360. keywords.StringByIndex(i, name);
  1361. context.out.String(name);
  1362. context.out.Char('"');
  1363. context.out.Ln;
  1364. END;
  1365. END ReportKeywords;
  1366. (*
  1367. PROCEDURE TestScanner*(context: Commands.Context);
  1368. VAR filename: ARRAY 256 OF CHAR;
  1369. reader: Streams.Reader;
  1370. scanner: Scanner;
  1371. sym: Symbol;
  1372. BEGIN
  1373. context.arg.SkipWhitespace;
  1374. context.arg.String(filename);
  1375. reader := TextUtilities.GetTextReader(filename);
  1376. scanner := NewScanner(filename, reader, 0, NIL);
  1377. REPEAT
  1378. IF scanner.GetNextSymbol(sym) THEN
  1379. OutSymbol(context.out, sym);
  1380. context.out.Ln;
  1381. END;
  1382. UNTIL scanner.error OR (sym.token = EndOfText)
  1383. END TestScanner;
  1384. *)
  1385. BEGIN
  1386. InitReservedCharacters;
  1387. InitTokens;
  1388. InitKeywords
  1389. END FoxCSharpScanner.