1 #include "ucl.h"
2 #include "lex.h"
3 #include "keyword.h"
4
5 #define CURSOR (Input.cursor)
6 #define LINE (Input.line)
7 #define LINEHEAD (Input.lineHead)
8
9 typedef int (*Scanner)(void);
10
11 static unsigned char *PeekPoint;
12 static union value PeekValue;
13 static struct coord PeekCoord;
14 static Scanner Scanners[256];
15
16 union value TokenValue;
17 struct coord TokenCoord;
18 struct coord PrevCoord;
19 char* TokenStrings[] =
20 {
21 #define TOKEN(k, s) s,
22 #include "token.h"
23 #undef TOKEN
24 };
25
26 /**
27 * Scans preprocessing directive which specify the line number and filename such as:
28 * # line 6 "C:\\Program Files\\Visual Stduio 6\\VC6\\Include\\stdio.h" or
29 * # 6 "/usr/include/stdio.h"
30 * Ignores other preprocessing directive.
31 */
ScanPPLine(void)32 static void ScanPPLine(void)
33 {
34 int line = 0;
35
36 CURSOR++;
37 while (*CURSOR == ' ' || *CURSOR == '\t')
38 {
39 CURSOR++;
40 }
41
42 if (IsDigit(*CURSOR))
43 {
44 goto read_line;
45 }
46 else if (strncmp(CURSOR, "line", 4) == 0)
47 {
48 CURSOR += 4;
49 while (*CURSOR == ' ' || *CURSOR == '\t')
50 {
51 CURSOR++;
52 }
53 read_line:
54 while (IsDigit(*CURSOR))
55 {
56 line = 10 * line + *CURSOR - '0';
57 CURSOR++;
58 }
59 TokenCoord.ppline = line - 1;
60
61 while (*CURSOR == ' ' || *CURSOR == '\t')
62 {
63 CURSOR++;
64 }
65 TokenCoord.filename = ++CURSOR;
66 while (*CURSOR != '"' && *CURSOR != END_OF_FILE && *CURSOR != '\n')
67 {
68 CURSOR++;
69 }
70 TokenCoord.filename = InternName(TokenCoord.filename, (char *)CURSOR - TokenCoord.filename);
71 }
72
73 while (*CURSOR != '\n' && *CURSOR != END_OF_FILE)
74 {
75 CURSOR++;
76 }
77 }
78
SkipWhiteSpace(void)79 static void SkipWhiteSpace(void)
80 {
81 int ch;
82
83 again:
84 ch = *CURSOR;
85 while (ch == '\t' || ch == '\v' || ch == '\f' || ch == ' ' ||
86 ch == '\r' || ch == '\n' || ch == '/' || ch == '#')
87 {
88 switch (ch)
89 {
90 case '\n':
91 TokenCoord.ppline++;
92 LINE++;
93 LINEHEAD = ++CURSOR;
94 break;
95
96 case '#':
97 ScanPPLine();
98 break;
99
100 case '/':
101 if (CURSOR[1] != '/' && CURSOR[1] != '*')
102 return;
103 CURSOR++;
104 if (*CURSOR == '/')
105 {
106 CURSOR++;
107 while (*CURSOR != '\n' && *CURSOR != END_OF_FILE)
108 {
109 CURSOR++;
110 }
111 }
112 else
113 {
114 CURSOR += 2;
115 while (CURSOR[0] != '*' || CURSOR[1] != '/')
116 {
117 if (*CURSOR == '\n')
118 {
119 TokenCoord.ppline++;
120 LINE++;
121 }
122 else if (CURSOR[0] == END_OF_FILE || CURSOR[1] == END_OF_FILE)
123 {
124 Error(&TokenCoord, "Comment is not closed");
125 return;
126 }
127 CURSOR++;
128 }
129 CURSOR += 2;
130 }
131 break;
132
133 default:
134 CURSOR++;
135 break;
136 }
137 ch = *CURSOR;
138 }
139
140 if (ExtraWhiteSpace != NULL)
141 {
142 char *p;
143
144 FOR_EACH_ITEM(char*, p, ExtraWhiteSpace)
145 if (strncmp(CURSOR, p, strlen(p)) == 0)
146 {
147 CURSOR += strlen(p);
148 goto again;
149 }
150 ENDFOR
151 }
152 }
153
ScanEscapeChar(int wide)154 static int ScanEscapeChar(int wide)
155 {
156 int v, overflow;
157
158 CURSOR++;
159 switch (*CURSOR++)
160 {
161 case 'a':
162 return '\a';
163
164 case 'b':
165 return '\b';
166
167 case 'f':
168 return '\f';
169
170 case 'n':
171 return '\n';
172
173 case 'r':
174 return '\r';
175
176 case 't':
177 return '\t';
178
179 case 'v':
180 return '\v';
181
182 case '\'':
183 case '"':
184 case '\\':
185 case '\?':
186 return *(CURSOR - 1);
187
188 case 'x':
189 if (! IsHexDigit(*CURSOR))
190 {
191 Error(&TokenCoord, "Expect hex digit");
192 return 'x';
193 }
194 v = 0;
195 while (IsHexDigit(*CURSOR))
196 {
197 if (v >> (WCharType->size - 4))
198 {
199 overflow = 1;
200 }
201 if (IsDigit(*CURSOR))
202 {
203 v = (v << 4) + *CURSOR - '0';
204 }
205 else
206 {
207 v = (v << 4) + ToUpper(*CURSOR) - 'A' + 10;
208 }
209 CURSOR++;
210 }
211 if (overflow || (! wide && v > 255))
212 {
213 Warning(&TokenCoord, "Hexademical espace sequence overflow");
214 }
215 return v;
216
217 case '0': case '1': case '2': case '3':
218 case '4': case '5': case '6': case '7':
219 v = *(CURSOR - 1) - '0';
220 if (IsOctDigit(*CURSOR))
221 {
222 v = (v << 3) + *CURSOR++ - '0';
223 if (IsOctDigit(*CURSOR))
224 v = (v << 3) + *CURSOR++ - '0';
225 }
226 return v;
227
228 default:
229 Warning(&TokenCoord, "Unrecognized escape sequence:\\%c", *CURSOR);
230 return *CURSOR;
231 }
232 }
233
FindKeyword(char * str,int len)234 static int FindKeyword(char *str, int len)
235 {
236 struct keyword *p = NULL;
237 int index = 0;
238
239 if (*str != '_')
240 index = ToUpper(*str) - 'A' + 1;
241
242 p = keywords[index];
243 while (p->name)
244 {
245 if (p->len == len && strncmp(str, p->name, len) == 0)
246 break;
247 p++;
248 }
249 return p->tok;
250 }
251
ScanIntLiteral(unsigned char * start,int len,int base)252 static int ScanIntLiteral(unsigned char *start, int len, int base)
253 {
254 unsigned char *p = start;
255 unsigned char *end = start + len;
256 unsigned int i[2] = {0, 0};
257 int tok = TK_INTCONST;
258 int d = 0;
259 int carry0 = 0, carry1 = 0;
260 int overflow = 0;
261
262 while (p != end)
263 {
264 if (base == 16)
265 {
266 if ((*p >= 'A' && *p <= 'F') ||
267 (*p >= 'a' && *p <= 'f'))
268 {
269 d = ToUpper(*p) - 'A' + 10;
270 }
271 else
272 {
273 d = *p - '0';
274 }
275 }
276 else
277 {
278 d = *p - '0';
279 }
280
281 switch (base)
282 {
283 case 16:
284 carry0 = HIGH_4BIT(i[0]);
285 carry1 = HIGH_4BIT(i[1]);
286 i[0] = i[0] << 4;
287 i[1] = i[1] << 4;
288 break;
289
290 case 8:
291 carry0 = HIGH_3BIT(i[0]);
292 carry1 = HIGH_3BIT(i[1]);
293 i[0] = i[0] << 3;
294 i[1] = i[1] << 3;
295 break;
296
297 case 10:
298 {
299 unsigned int t1, t2;
300
301 carry0 = HIGH_3BIT(i[0]) + HIGH_1BIT(i[0]);
302 carry1 = HIGH_3BIT(i[1]) + HIGH_1BIT(i[1]);
303 t1 = i[0] << 3;
304 t2 = i[0] << 1;
305 if (t1 > UINT_MAX - t2)
306 {
307 carry0++;
308 }
309 i[0] = t1 + t2;
310 t1 = i[1] << 3;
311 t2 = i[1] << 1;
312 if (t1 > UINT_MAX - t2)
313 {
314 carry1++;
315 }
316 i[1] = t1 + t2;
317 }
318 break;
319 }
320 if (i[0] > UINT_MAX - d)
321 {
322 carry0 += i[0] - (UINT_MAX - d);
323 }
324 if (carry1 || (i[1] > UINT_MAX - carry0))
325 {
326 overflow = 1;
327 }
328 i[0] += d;
329 i[1] += carry0;
330 p++;
331 }
332
333 if (overflow || i[1] != 0)
334 {
335 Warning(&TokenCoord, "Integer literal is too big");
336 }
337
338 TokenValue.i[1] = 0;
339 TokenValue.i[0] = i[0];
340 tok = TK_INTCONST;
341
342 if (*CURSOR == 'U' || *CURSOR == 'u')
343 {
344 CURSOR++;
345 if (tok == TK_INTCONST)
346 {
347 tok = TK_UINTCONST;
348 }
349 else if (tok == TK_LLONGCONST)
350 {
351 tok = TK_ULLONGCONST;
352 }
353 }
354
355 if (*CURSOR == 'L' || *CURSOR == 'l')
356 {
357 CURSOR++;
358 if (tok == TK_INTCONST)
359 {
360 tok = TK_LONGCONST;
361 }
362 else if (tok == TK_UINTCONST)
363 {
364 tok = TK_ULONGCONST;
365 }
366 if (*CURSOR == 'L' || *CURSOR == 'l')
367 {
368 CURSOR++;
369 if (tok < TK_LLONGCONST)
370 {
371 tok = TK_LLONGCONST;
372 }
373 }
374 }
375
376 return tok;
377 }
378
ScanFloatLiteral(unsigned char * start)379 static int ScanFloatLiteral(unsigned char *start)
380 {
381 double d;
382
383 if (*CURSOR == '.')
384 {
385 CURSOR++;
386 while (IsDigit(*CURSOR))
387 {
388 CURSOR++;
389 }
390 }
391 if (*CURSOR == 'e' || *CURSOR == 'E')
392 {
393 CURSOR++;
394 if (*CURSOR == '+' || *CURSOR == '-')
395 {
396 CURSOR++;
397 }
398 if (! IsDigit(*CURSOR))
399 {
400 Error(&TokenCoord, "Expect exponent value");
401 }
402 else
403 {
404 while (IsDigit(*CURSOR))
405 {
406 CURSOR++;
407 }
408 }
409 }
410
411 errno = 0;
412 d = strtod((char *)start, NULL);
413 if (errno == ERANGE)
414 {
415 Warning(&TokenCoord, "Float literal overflow");
416 }
417 TokenValue.d = d;
418 if (*CURSOR == 'f' || *CURSOR == 'F')
419 {
420 CURSOR++;
421 TokenValue.f = (float)d;
422 return TK_FLOATCONST;
423 }
424 else if (*CURSOR == 'L' || *CURSOR == 'l')
425 {
426 CURSOR++;
427 return TK_LDOUBLECONST;
428 }
429 else
430 {
431 return TK_DOUBLECONST;
432 }
433 }
434
ScanNumericLiteral(void)435 static int ScanNumericLiteral(void)
436 {
437 unsigned char *start = CURSOR;
438 int base = 10;
439
440 if (*CURSOR == '.')
441 {
442 return ScanFloatLiteral(start);
443 }
444
445 if (*CURSOR == '0' && (CURSOR[1] == 'x' || CURSOR[1] == 'X'))
446 {
447 CURSOR += 2;
448 start = CURSOR;
449 base = 16;
450 if (! IsHexDigit(*CURSOR))
451 {
452 Error(&TokenCoord, "Expect hex digit");
453 TokenValue.i[0] = 0;
454 return TK_INTCONST;
455 }
456 while (IsHexDigit(*CURSOR))
457 {
458 CURSOR++;
459 }
460 }
461 else if (*CURSOR == '0')
462 {
463 CURSOR++;
464 base = 8;
465 while (IsOctDigit(*CURSOR))
466 {
467 CURSOR++;
468 }
469 }
470 else
471 {
472 CURSOR++;
473 while (IsDigit(*CURSOR))
474 {
475 CURSOR++;
476 }
477 }
478
479 if (base == 16 || (*CURSOR != '.' && *CURSOR != 'e' && *CURSOR != 'E'))
480 {
481 return ScanIntLiteral(start, (int)(CURSOR - start), base);
482 }
483 else
484 {
485 return ScanFloatLiteral(start);
486 }
487 }
488
ScanCharLiteral(void)489 static int ScanCharLiteral(void)
490 {
491 int ch = 0;
492 int count = 0;
493 int wide = 0;
494
495 if (*CURSOR == 'L')
496 {
497 CURSOR++;
498 wide = 1;
499 }
500 CURSOR++;
501 while (*CURSOR != '\'')
502 {
503 if (*CURSOR == '\n' || *CURSOR == END_OF_FILE)
504 break;
505
506 ch = *CURSOR == '\\' ? ScanEscapeChar(wide) : *CURSOR++;
507 count++;
508 }
509
510 if (*CURSOR != '\'')
511 {
512 Error(&TokenCoord, "Expect '");
513 goto end_char;
514 }
515
516 CURSOR++;
517 if (count > 1)
518 {
519 Warning(&TokenCoord, "Two many characters");
520 }
521
522 end_char:
523 TokenValue.i[0] = ch;
524 TokenValue.i[1] = 0;
525
526 return TK_INTCONST;
527 }
528
ScanStringLiteral(void)529 static int ScanStringLiteral(void)
530 {
531 char tmp[512];
532 char *cp = tmp;
533 int *wcp = (int *)tmp;
534 int wide = 0;
535 int len = 0;
536 int maxlen = 512;
537 int ch;
538 String str;
539
540 CALLOC(str);
541
542 if (*CURSOR == 'L')
543 {
544 CURSOR++;
545 wide = 1;
546 maxlen /= sizeof(int);
547 }
548 CURSOR++;
549
550 next_string:
551 while (*CURSOR != '"')
552 {
553 if (*CURSOR == '\n' || *CURSOR == END_OF_FILE)
554 break;
555
556 ch = *CURSOR == '\\' ? ScanEscapeChar(wide) : *CURSOR++;
557 if (wide)
558 {
559 wcp[len] = ch;
560 }
561 else
562 {
563 cp[len] = (char)ch;
564 }
565 len++;
566 if (len >= maxlen)
567 {
568 AppendSTR(str, tmp, len, wide);
569 len = 0;
570 }
571 }
572
573 if (*CURSOR != '"')
574 {
575 Error(&TokenCoord, "Expect \"");
576 goto end_string;
577 }
578
579 CURSOR++;
580 SkipWhiteSpace();
581 if (CURSOR[0] == '"')
582 {
583 if (wide == 1)
584 {
585 Error(&TokenCoord, "String wideness mismatch");
586 }
587 CURSOR++;
588 goto next_string;
589 }
590 else if (CURSOR[0] == 'L' && CURSOR[1] == '"')
591 {
592 if (wide == 0)
593 {
594 Error(&TokenCoord, "String wideness mismatch");
595 }
596 CURSOR += 2;
597 goto next_string;
598 }
599
600 end_string:
601 AppendSTR(str, tmp, len, wide);
602 TokenValue.p = str;
603
604 return wide ? TK_WIDESTRING : TK_STRING;
605 }
606
ScanIdentifier(void)607 static int ScanIdentifier(void)
608 {
609 unsigned char *start = CURSOR;
610 int tok;
611
612 if (*CURSOR == 'L')
613 {
614 if (CURSOR[1] == '\'')
615 {
616 return ScanCharLiteral();
617 }
618 if (CURSOR[1] == '"')
619 {
620 return ScanStringLiteral();
621 }
622 }
623
624 CURSOR++;
625 while (IsLetterOrDigit(*CURSOR))
626 {
627 CURSOR++;
628 }
629
630 tok = FindKeyword((char *)start, (int)(CURSOR - start));
631 if (tok == TK_ID)
632 {
633 TokenValue.p = InternName((char *)start, (int)(CURSOR - start));
634 }
635
636 return tok;
637 }
638
ScanPlus(void)639 static int ScanPlus(void)
640 {
641 CURSOR++;
642 if (*CURSOR == '+')
643 {
644 CURSOR++;
645 return TK_INC;
646 }
647 else if (*CURSOR == '=')
648 {
649 CURSOR++;
650 return TK_ADD_ASSIGN;
651 }
652 else
653 {
654 return TK_ADD;
655 }
656 }
657
ScanMinus(void)658 static int ScanMinus(void)
659 {
660 CURSOR++;
661 if (*CURSOR == '-')
662 {
663 CURSOR++;
664 return TK_DEC;
665 }
666 else if (*CURSOR == '=')
667 {
668 CURSOR++;
669 return TK_SUB_ASSIGN;
670 }
671 else if (*CURSOR == '>')
672 {
673 CURSOR++;
674 return TK_POINTER;
675 }
676 else
677 {
678 return TK_SUB;
679 }
680 }
681
ScanStar(void)682 static int ScanStar(void)
683 {
684 CURSOR++;
685 if (*CURSOR == '=')
686 {
687 CURSOR++;
688 return TK_MUL_ASSIGN;
689 }
690 else
691 {
692 return TK_MUL;
693 }
694 }
695
ScanSlash(void)696 static int ScanSlash(void)
697 {
698 CURSOR++;
699 if (*CURSOR == '=')
700 {
701 CURSOR++;
702 return TK_DIV_ASSIGN;
703 }
704 else
705 {
706 return TK_DIV;
707 }
708 }
709
ScanPercent(void)710 static int ScanPercent(void)
711 {
712 CURSOR++;
713 if (*CURSOR == '=')
714 {
715 CURSOR++;
716 return TK_MOD_ASSIGN;
717 }
718 else
719 {
720 return TK_MOD;
721 }
722 }
723
ScanLess(void)724 static int ScanLess(void)
725 {
726 CURSOR++;
727 if (*CURSOR == '<')
728 {
729 CURSOR++;
730 if (*CURSOR == '=')
731 {
732 CURSOR++;
733 return TK_LSHIFT_ASSIGN;
734 }
735 return TK_LSHIFT;
736 }
737 else if (*CURSOR == '=')
738 {
739 CURSOR++;
740 return TK_LESS_EQ;
741 }
742 else
743 {
744 return TK_LESS;
745 }
746 }
747
ScanGreat(void)748 static int ScanGreat(void)
749 {
750 CURSOR++;
751 if (*CURSOR == '>')
752 {
753 CURSOR++;
754 if (*CURSOR == '=')
755 {
756 CURSOR++;
757 return TK_RSHIFT_ASSIGN;
758 }
759 return TK_RSHIFT;
760 }
761 else if (*CURSOR == '=')
762 {
763 CURSOR++;
764 return TK_GREAT_EQ;
765 }
766 else
767 {
768 return TK_GREAT;
769 }
770 }
771
ScanExclamation(void)772 static int ScanExclamation(void)
773 {
774 CURSOR++;
775 if (*CURSOR == '=')
776 {
777 CURSOR++;
778 return TK_UNEQUAL;
779 }
780 else
781 {
782 return TK_NOT;
783 }
784 }
785
ScanEqual(void)786 static int ScanEqual(void)
787 {
788 CURSOR++;
789 if (*CURSOR == '=')
790 {
791 CURSOR++;
792 return TK_EQUAL;
793 }
794 else
795 {
796 return TK_ASSIGN;
797 }
798 }
799
ScanBar(void)800 static int ScanBar(void)
801 {
802 CURSOR++;
803 if (*CURSOR == '|')
804 {
805 CURSOR++;
806 return TK_OR;
807 }
808 else if (*CURSOR == '=')
809 {
810 CURSOR++;
811 return TK_BITOR_ASSIGN;
812 }
813 else
814 {
815 return TK_BITOR;
816 }
817 }
818
ScanAmpersand(void)819 static int ScanAmpersand(void)
820 {
821 CURSOR++;
822 if (*CURSOR == '&')
823 {
824 CURSOR++;
825 return TK_AND;
826 }
827 else if (*CURSOR == '=')
828 {
829 CURSOR++;
830 return TK_BITAND_ASSIGN;
831 }
832 else
833 {
834 return TK_BITAND;
835 }
836 }
837
ScanCaret(void)838 static int ScanCaret(void)
839 {
840 CURSOR++;
841 if (*CURSOR == '=')
842 {
843 CURSOR++;
844 return TK_BITXOR_ASSIGN;
845 }
846 else
847 {
848 return TK_BITXOR;
849 }
850 }
851
ScanDot(void)852 static int ScanDot(void)
853 {
854 if (IsDigit(CURSOR[1]))
855 {
856 return ScanFloatLiteral(CURSOR);
857 }
858 else if (CURSOR[1] == '.' && CURSOR[2] == '.')
859 {
860 CURSOR += 3;
861 return TK_ELLIPSE;
862 }
863 else
864 {
865 CURSOR++;
866 return TK_DOT;
867 }
868 }
869
870 #define SINGLE_CHAR_SCANNER(t) \
871 static int Scan##t(void) \
872 { \
873 CURSOR++; \
874 return TK_##t; \
875 }
876
877 SINGLE_CHAR_SCANNER(LBRACE)
SINGLE_CHAR_SCANNER(RBRACE)878 SINGLE_CHAR_SCANNER(RBRACE)
879 SINGLE_CHAR_SCANNER(LBRACKET)
880 SINGLE_CHAR_SCANNER(RBRACKET)
881 SINGLE_CHAR_SCANNER(LPAREN)
882 SINGLE_CHAR_SCANNER(RPAREN)
883 SINGLE_CHAR_SCANNER(COMMA)
884 SINGLE_CHAR_SCANNER(SEMICOLON)
885 SINGLE_CHAR_SCANNER(COMP)
886 SINGLE_CHAR_SCANNER(QUESTION)
887 SINGLE_CHAR_SCANNER(COLON)
888
889 static int ScanBadChar(void)
890 {
891 Error(&TokenCoord, "illegal character:\\x%x", *CURSOR);
892 return GetNextToken();
893 }
894
ScanEOF(void)895 static int ScanEOF(void)
896 {
897 return TK_END;
898 }
899
SetupLexer(void)900 void SetupLexer(void)
901 {
902 int i;
903
904 for (i = 0; i < END_OF_FILE + 1; i++)
905 {
906 if (IsLetter(i))
907 {
908 Scanners[i] = ScanIdentifier;
909 }
910 else if (IsDigit(i))
911 {
912 Scanners[i] = ScanNumericLiteral;
913 }
914 else
915 {
916 Scanners[i] = ScanBadChar;
917 }
918 }
919
920 Scanners[END_OF_FILE] = ScanEOF;
921 Scanners['\''] = ScanCharLiteral;
922 Scanners['"'] = ScanStringLiteral;
923 Scanners['+'] = ScanPlus;
924 Scanners['-'] = ScanMinus;
925 Scanners['*'] = ScanStar;
926 Scanners['/'] = ScanSlash;
927 Scanners['%'] = ScanPercent;
928 Scanners['<'] = ScanLess;
929 Scanners['>'] = ScanGreat;
930 Scanners['!'] = ScanExclamation;
931 Scanners['='] = ScanEqual;
932 Scanners['|'] = ScanBar;
933 Scanners['&'] = ScanAmpersand;
934 Scanners['^'] = ScanCaret;
935 Scanners['.'] = ScanDot;
936 Scanners['{'] = ScanLBRACE;
937 Scanners['}'] = ScanRBRACE;
938 Scanners['['] = ScanLBRACKET;
939 Scanners[']'] = ScanRBRACKET;
940 Scanners['('] = ScanLPAREN;
941 Scanners[')'] = ScanRPAREN;
942 Scanners[','] = ScanCOMMA;
943 Scanners[';'] = ScanSEMICOLON;
944 Scanners['~'] = ScanCOMP;
945 Scanners['?'] = ScanQUESTION;
946 Scanners[':'] = ScanCOLON;
947
948 if (ExtraKeywords != NULL)
949 {
950 char *str;
951 struct keyword *p;
952
953 FOR_EACH_ITEM(char*, str, ExtraKeywords)
954 p = keywords_;
955 while (p->name)
956 {
957 if (strcmp(str, p->name) == 0)
958 {
959 p->len = strlen(str);
960 break;
961 }
962 p++;
963 }
964 ENDFOR
965 }
966 }
967
GetNextToken(void)968 int GetNextToken(void)
969 {
970 int tok;
971
972 PrevCoord = TokenCoord;
973 SkipWhiteSpace();
974 TokenCoord.line = LINE;
975 TokenCoord.col = (int)(CURSOR - LINEHEAD + 1);
976
977 tok = (*Scanners[*CURSOR])();
978 return tok;
979 }
980
BeginPeekToken(void)981 void BeginPeekToken(void)
982 {
983 PeekPoint = CURSOR;
984 PeekValue = TokenValue;
985 PeekCoord = TokenCoord;
986 }
987
EndPeekToken(void)988 void EndPeekToken(void)
989 {
990 CURSOR = PeekPoint;
991 TokenValue = PeekValue;
992 TokenCoord = PeekCoord;
993 }
994
995
996