source: webkit/trunk/JavaScriptCore/kjs/lexer.cpp@ 11962

Last change on this file since 11962 was 11962, checked in by thatcher, 19 years ago

Removes svn:keywords from all files.

  • Property svn:eol-style set to native
File size: 21.4 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2000 Harri Porten ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <ctype.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#include <assert.h>
32
33#include "value.h"
34#include "object.h"
35#include "types.h"
36#include "interpreter.h"
37#include "nodes.h"
38#include "lexer.h"
39#include "identifier.h"
40#include "lookup.h"
41#include "internal.h"
42#include <unicode/uchar.h>
43
44static bool isDecimalDigit(unsigned short c);
45
46// we can't specify the namespace in yacc's C output, so do it here
47using namespace KJS;
48
49static Lexer *currLexer = 0;
50
51#ifndef KDE_USE_FINAL
52#include "grammar.h"
53#endif
54
55#include "lexer.lut.h"
56
57extern YYLTYPE kjsyylloc; // global bison variable holding token info
58
59// a bridge for yacc from the C world to C++
60int kjsyylex()
61{
62 return Lexer::curr()->lex();
63}
64
65Lexer::Lexer()
66 : yylineno(1),
67 size8(128), size16(128), restrKeyword(false),
68 eatNextIdentifier(false), stackToken(-1), lastToken(-1), pos(0),
69 code(0), length(0),
70#ifndef KJS_PURE_ECMA
71 bol(true),
72#endif
73 current(0), next1(0), next2(0), next3(0),
74 strings(0), numStrings(0), stringsCapacity(0),
75 identifiers(0), numIdentifiers(0), identifiersCapacity(0)
76{
77 // allocate space for read buffers
78 buffer8 = new char[size8];
79 buffer16 = new KJS::UChar[size16];
80 currLexer = this;
81}
82
83Lexer::~Lexer()
84{
85 doneParsing();
86 delete [] buffer8;
87 delete [] buffer16;
88}
89
90Lexer *Lexer::curr()
91{
92 if (!currLexer) {
93 // create singleton instance
94 currLexer = new Lexer();
95 }
96 return currLexer;
97}
98
99#ifdef KJS_DEBUG_MEM
100void Lexer::globalClear()
101{
102 delete currLexer;
103 currLexer = 0L;
104}
105#endif
106
107void Lexer::setCode(const UString &sourceURL, int startingLineNumber, const KJS::UChar *c, unsigned int len)
108{
109 yylineno = 1 + startingLineNumber;
110 m_sourceURL = sourceURL;
111 restrKeyword = false;
112 delimited = false;
113 eatNextIdentifier = false;
114 stackToken = -1;
115 lastToken = -1;
116 pos = 0;
117 code = c;
118 length = len;
119 skipLF = false;
120 skipCR = false;
121 error = false;
122#ifndef KJS_PURE_ECMA
123 bol = true;
124#endif
125
126 // read first characters
127 shift(4);
128}
129
130void Lexer::shift(unsigned int p)
131{
132 while (p--) {
133 current = next1;
134 next1 = next2;
135 next2 = next3;
136 do {
137 if (pos >= length) {
138 next3 = 0;
139 break;
140 }
141 next3 = code[pos++].uc;
142 } while (u_charType(next3) == U_FORMAT_CHAR);
143 }
144}
145
146// called on each new line
147void Lexer::nextLine()
148{
149 yylineno++;
150#ifndef KJS_PURE_ECMA
151 bol = true;
152#endif
153}
154
155void Lexer::setDone(State s)
156{
157 state = s;
158 done = true;
159}
160
161int Lexer::lex()
162{
163 int token = 0;
164 state = Start;
165 unsigned short stringType = 0; // either single or double quotes
166 pos8 = pos16 = 0;
167 done = false;
168 terminator = false;
169 skipLF = false;
170 skipCR = false;
171
172 // did we push a token on the stack previously ?
173 // (after an automatic semicolon insertion)
174 if (stackToken >= 0) {
175 setDone(Other);
176 token = stackToken;
177 stackToken = 0;
178 }
179
180 while (!done) {
181 if (skipLF && current != '\n') // found \r but not \n afterwards
182 skipLF = false;
183 if (skipCR && current != '\r') // found \n but not \r afterwards
184 skipCR = false;
185 if (skipLF || skipCR) // found \r\n or \n\r -> eat the second one
186 {
187 skipLF = false;
188 skipCR = false;
189 shift(1);
190 }
191 switch (state) {
192 case Start:
193 if (isWhiteSpace()) {
194 // do nothing
195 } else if (current == '/' && next1 == '/') {
196 shift(1);
197 state = InSingleLineComment;
198 } else if (current == '/' && next1 == '*') {
199 shift(1);
200 state = InMultiLineComment;
201 } else if (current == 0) {
202 if (!terminator && !delimited) {
203 // automatic semicolon insertion if program incomplete
204 token = ';';
205 stackToken = 0;
206 setDone(Other);
207 } else
208 setDone(Eof);
209 } else if (isLineTerminator()) {
210 nextLine();
211 terminator = true;
212 if (restrKeyword) {
213 token = ';';
214 setDone(Other);
215 }
216 } else if (current == '"' || current == '\'') {
217 state = InString;
218 stringType = current;
219 } else if (isIdentStart(current)) {
220 record16(current);
221 state = InIdentifierOrKeyword;
222 } else if (current == '\\') {
223 state = InIdentifierUnicodeEscapeStart;
224 } else if (current == '0') {
225 record8(current);
226 state = InNum0;
227 } else if (isDecimalDigit(current)) {
228 record8(current);
229 state = InNum;
230 } else if (current == '.' && isDecimalDigit(next1)) {
231 record8(current);
232 state = InDecimal;
233#ifndef KJS_PURE_ECMA
234 // <!-- marks the beginning of a line comment (for www usage)
235 } else if (current == '<' && next1 == '!' &&
236 next2 == '-' && next3 == '-') {
237 shift(3);
238 state = InSingleLineComment;
239 // same for -->
240 } else if (bol && current == '-' && next1 == '-' && next2 == '>') {
241 shift(2);
242 state = InSingleLineComment;
243#endif
244 } else {
245 token = matchPunctuator(current, next1, next2, next3);
246 if (token != -1) {
247 setDone(Other);
248 } else {
249 // cerr << "encountered unknown character" << endl;
250 setDone(Bad);
251 }
252 }
253 break;
254 case InString:
255 if (current == stringType) {
256 shift(1);
257 setDone(String);
258 } else if (current == 0 || isLineTerminator()) {
259 setDone(Bad);
260 } else if (current == '\\') {
261 state = InEscapeSequence;
262 } else {
263 record16(current);
264 }
265 break;
266 // Escape Sequences inside of strings
267 case InEscapeSequence:
268 if (isOctalDigit(current)) {
269 if (current >= '0' && current <= '3' &&
270 isOctalDigit(next1) && isOctalDigit(next2)) {
271 record16(convertOctal(current, next1, next2));
272 shift(2);
273 state = InString;
274 } else if (isOctalDigit(current) && isOctalDigit(next1)) {
275 record16(convertOctal('0', current, next1));
276 shift(1);
277 state = InString;
278 } else if (isOctalDigit(current)) {
279 record16(convertOctal('0', '0', current));
280 state = InString;
281 } else {
282 setDone(Bad);
283 }
284 } else if (current == 'x')
285 state = InHexEscape;
286 else if (current == 'u')
287 state = InUnicodeEscape;
288 else if (isLineTerminator()) {
289 nextLine();
290 state = InString;
291 } else {
292 record16(singleEscape(current));
293 state = InString;
294 }
295 break;
296 case InHexEscape:
297 if (isHexDigit(current) && isHexDigit(next1)) {
298 state = InString;
299 record16(convertHex(current, next1));
300 shift(1);
301 } else if (current == stringType) {
302 record16('x');
303 shift(1);
304 setDone(String);
305 } else {
306 record16('x');
307 record16(current);
308 state = InString;
309 }
310 break;
311 case InUnicodeEscape:
312 if (isHexDigit(current) && isHexDigit(next1) && isHexDigit(next2) && isHexDigit(next3)) {
313 record16(convertUnicode(current, next1, next2, next3));
314 shift(3);
315 state = InString;
316 } else if (current == stringType) {
317 record16('u');
318 shift(1);
319 setDone(String);
320 } else {
321 setDone(Bad);
322 }
323 break;
324 case InSingleLineComment:
325 if (isLineTerminator()) {
326 nextLine();
327 terminator = true;
328 if (restrKeyword) {
329 token = ';';
330 setDone(Other);
331 } else
332 state = Start;
333 } else if (current == 0) {
334 setDone(Eof);
335 }
336 break;
337 case InMultiLineComment:
338 if (current == 0) {
339 setDone(Bad);
340 } else if (isLineTerminator()) {
341 nextLine();
342 } else if (current == '*' && next1 == '/') {
343 state = Start;
344 shift(1);
345 }
346 break;
347 case InIdentifierOrKeyword:
348 case InIdentifier:
349 if (isIdentPart(current))
350 record16(current);
351 else if (current == '\\')
352 state = InIdentifierUnicodeEscapeStart;
353 else
354 setDone(state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier);
355 break;
356 case InNum0:
357 if (current == 'x' || current == 'X') {
358 record8(current);
359 state = InHex;
360 } else if (current == '.') {
361 record8(current);
362 state = InDecimal;
363 } else if (current == 'e' || current == 'E') {
364 record8(current);
365 state = InExponentIndicator;
366 } else if (isOctalDigit(current)) {
367 record8(current);
368 state = InOctal;
369 } else if (isDecimalDigit(current)) {
370 record8(current);
371 state = InDecimal;
372 } else {
373 setDone(Number);
374 }
375 break;
376 case InHex:
377 if (isHexDigit(current)) {
378 record8(current);
379 } else {
380 setDone(Hex);
381 }
382 break;
383 case InOctal:
384 if (isOctalDigit(current)) {
385 record8(current);
386 }
387 else if (isDecimalDigit(current)) {
388 record8(current);
389 state = InDecimal;
390 } else
391 setDone(Octal);
392 break;
393 case InNum:
394 if (isDecimalDigit(current)) {
395 record8(current);
396 } else if (current == '.') {
397 record8(current);
398 state = InDecimal;
399 } else if (current == 'e' || current == 'E') {
400 record8(current);
401 state = InExponentIndicator;
402 } else
403 setDone(Number);
404 break;
405 case InDecimal:
406 if (isDecimalDigit(current)) {
407 record8(current);
408 } else if (current == 'e' || current == 'E') {
409 record8(current);
410 state = InExponentIndicator;
411 } else
412 setDone(Number);
413 break;
414 case InExponentIndicator:
415 if (current == '+' || current == '-') {
416 record8(current);
417 } else if (isDecimalDigit(current)) {
418 record8(current);
419 state = InExponent;
420 } else
421 setDone(Bad);
422 break;
423 case InExponent:
424 if (isDecimalDigit(current)) {
425 record8(current);
426 } else
427 setDone(Number);
428 break;
429 case InIdentifierUnicodeEscapeStart:
430 if (current == 'u')
431 state = InIdentifierUnicodeEscape;
432 else
433 setDone(Bad);
434 break;
435 case InIdentifierUnicodeEscape:
436 if (isHexDigit(current) && isHexDigit(next1) && isHexDigit(next2) && isHexDigit(next3)) {
437 record16(convertUnicode(current, next1, next2, next3));
438 shift(3);
439 state = InIdentifier;
440 } else {
441 setDone(Bad);
442 }
443 break;
444 default:
445 assert(!"Unhandled state in switch statement");
446 }
447
448 // move on to the next character
449 if (!done)
450 shift(1);
451#ifndef KJS_PURE_ECMA
452 if (state != Start && state != InSingleLineComment)
453 bol = false;
454#endif
455 }
456
457 // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
458 if ((state == Number || state == Octal || state == Hex) && isIdentStart(current))
459 state = Bad;
460
461 // terminate string
462 buffer8[pos8] = '\0';
463
464#ifdef KJS_DEBUG_LEX
465 fprintf(stderr, "line: %d ", lineNo());
466 fprintf(stderr, "yytext (%x): ", buffer8[0]);
467 fprintf(stderr, "%s ", buffer8);
468#endif
469
470 double dval = 0;
471 if (state == Number) {
472 dval = strtod(buffer8, 0L);
473 } else if (state == Hex) { // scan hex numbers
474 const char *p = buffer8 + 2;
475 while (char c = *p++) {
476 dval *= 16;
477 dval += convertHex(c);
478 }
479 state = Number;
480 } else if (state == Octal) { // scan octal number
481 const char *p = buffer8 + 1;
482 while (char c = *p++) {
483 dval *= 8;
484 dval += c - '0';
485 }
486 state = Number;
487 }
488
489#ifdef KJS_DEBUG_LEX
490 switch (state) {
491 case Eof:
492 printf("(EOF)\n");
493 break;
494 case Other:
495 printf("(Other)\n");
496 break;
497 case Identifier:
498 printf("(Identifier)/(Keyword)\n");
499 break;
500 case String:
501 printf("(String)\n");
502 break;
503 case Number:
504 printf("(Number)\n");
505 break;
506 default:
507 printf("(unknown)");
508 }
509#endif
510
511 if (state != Identifier && eatNextIdentifier)
512 eatNextIdentifier = false;
513
514 restrKeyword = false;
515 delimited = false;
516 kjsyylloc.first_line = yylineno; // ???
517 kjsyylloc.last_line = yylineno;
518
519 switch (state) {
520 case Eof:
521 token = 0;
522 break;
523 case Other:
524 if(token == '}' || token == ';') {
525 delimited = true;
526 }
527 break;
528 case IdentifierOrKeyword:
529 if ((token = Lookup::find(&mainTable, buffer16, pos16)) < 0) {
530 case Identifier:
531 // Lookup for keyword failed, means this is an identifier
532 // Apply anonymous-function hack below (eat the identifier)
533 if (eatNextIdentifier) {
534 eatNextIdentifier = false;
535 token = lex();
536 break;
537 }
538 kjsyylval.ident = makeIdentifier(buffer16, pos16);
539 token = IDENT;
540 break;
541 }
542
543 eatNextIdentifier = false;
544 // Hack for "f = function somename() { ... }", too hard to get into the grammar
545 if (token == FUNCTION && lastToken == '=' )
546 eatNextIdentifier = true;
547
548 if (token == CONTINUE || token == BREAK ||
549 token == RETURN || token == THROW)
550 restrKeyword = true;
551 break;
552 case String:
553 kjsyylval.ustr = makeUString(buffer16, pos16);
554 token = STRING;
555 break;
556 case Number:
557 kjsyylval.dval = dval;
558 token = NUMBER;
559 break;
560 case Bad:
561 fprintf(stderr, "yylex: ERROR.\n");
562 error = true;
563 return -1;
564 default:
565 assert(!"unhandled numeration value in switch");
566 error = true;
567 return -1;
568 }
569 lastToken = token;
570 return token;
571}
572
573bool Lexer::isWhiteSpace() const
574{
575 return (current == '\t' || current == 0x0b || current == 0x0c || u_charType(current) == U_SPACE_SEPARATOR);
576}
577
578bool Lexer::isLineTerminator()
579{
580 bool cr = (current == '\r');
581 bool lf = (current == '\n');
582 if (cr)
583 skipLF = true;
584 else if (lf)
585 skipCR = true;
586 return cr || lf || current == 0x2028 || current == 0x2029;
587}
588
589bool Lexer::isIdentStart(unsigned short c)
590{
591 return (U_GET_GC_MASK(c) & (U_GC_L_MASK | U_GC_NL_MASK)) || c == '$' || c == '_';
592}
593
594bool Lexer::isIdentPart(unsigned short c)
595{
596 return (U_GET_GC_MASK(c) & (U_GC_L_MASK | U_GC_NL_MASK | U_GC_MN_MASK | U_GC_MC_MASK | U_GC_ND_MASK | U_GC_PC_MASK)) || c == '$' || c == '_';
597}
598
599static bool isDecimalDigit(unsigned short c)
600{
601 return (c >= '0' && c <= '9');
602}
603
604bool Lexer::isHexDigit(unsigned short c)
605{
606 return (c >= '0' && c <= '9' ||
607 c >= 'a' && c <= 'f' ||
608 c >= 'A' && c <= 'F');
609}
610
611bool Lexer::isOctalDigit(unsigned short c) const
612{
613 return (c >= '0' && c <= '7');
614}
615
616int Lexer::matchPunctuator(unsigned short c1, unsigned short c2,
617 unsigned short c3, unsigned short c4)
618{
619 if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
620 shift(4);
621 return URSHIFTEQUAL;
622 } else if (c1 == '=' && c2 == '=' && c3 == '=') {
623 shift(3);
624 return STREQ;
625 } else if (c1 == '!' && c2 == '=' && c3 == '=') {
626 shift(3);
627 return STRNEQ;
628 } else if (c1 == '>' && c2 == '>' && c3 == '>') {
629 shift(3);
630 return URSHIFT;
631 } else if (c1 == '<' && c2 == '<' && c3 == '=') {
632 shift(3);
633 return LSHIFTEQUAL;
634 } else if (c1 == '>' && c2 == '>' && c3 == '=') {
635 shift(3);
636 return RSHIFTEQUAL;
637 } else if (c1 == '<' && c2 == '=') {
638 shift(2);
639 return LE;
640 } else if (c1 == '>' && c2 == '=') {
641 shift(2);
642 return GE;
643 } else if (c1 == '!' && c2 == '=') {
644 shift(2);
645 return NE;
646 } else if (c1 == '+' && c2 == '+') {
647 shift(2);
648 if (terminator)
649 return AUTOPLUSPLUS;
650 else
651 return PLUSPLUS;
652 } else if (c1 == '-' && c2 == '-') {
653 shift(2);
654 if (terminator)
655 return AUTOMINUSMINUS;
656 else
657 return MINUSMINUS;
658 } else if (c1 == '=' && c2 == '=') {
659 shift(2);
660 return EQEQ;
661 } else if (c1 == '+' && c2 == '=') {
662 shift(2);
663 return PLUSEQUAL;
664 } else if (c1 == '-' && c2 == '=') {
665 shift(2);
666 return MINUSEQUAL;
667 } else if (c1 == '*' && c2 == '=') {
668 shift(2);
669 return MULTEQUAL;
670 } else if (c1 == '/' && c2 == '=') {
671 shift(2);
672 return DIVEQUAL;
673 } else if (c1 == '&' && c2 == '=') {
674 shift(2);
675 return ANDEQUAL;
676 } else if (c1 == '^' && c2 == '=') {
677 shift(2);
678 return XOREQUAL;
679 } else if (c1 == '%' && c2 == '=') {
680 shift(2);
681 return MODEQUAL;
682 } else if (c1 == '|' && c2 == '=') {
683 shift(2);
684 return OREQUAL;
685 } else if (c1 == '<' && c2 == '<') {
686 shift(2);
687 return LSHIFT;
688 } else if (c1 == '>' && c2 == '>') {
689 shift(2);
690 return RSHIFT;
691 } else if (c1 == '&' && c2 == '&') {
692 shift(2);
693 return AND;
694 } else if (c1 == '|' && c2 == '|') {
695 shift(2);
696 return OR;
697 }
698
699 switch(c1) {
700 case '=':
701 case '>':
702 case '<':
703 case ',':
704 case '!':
705 case '~':
706 case '?':
707 case ':':
708 case '.':
709 case '+':
710 case '-':
711 case '*':
712 case '/':
713 case '&':
714 case '|':
715 case '^':
716 case '%':
717 case '(':
718 case ')':
719 case '{':
720 case '}':
721 case '[':
722 case ']':
723 case ';':
724 shift(1);
725 return static_cast<int>(c1);
726 default:
727 return -1;
728 }
729}
730
731unsigned short Lexer::singleEscape(unsigned short c) const
732{
733 switch(c) {
734 case 'b':
735 return 0x08;
736 case 't':
737 return 0x09;
738 case 'n':
739 return 0x0A;
740 case 'v':
741 return 0x0B;
742 case 'f':
743 return 0x0C;
744 case 'r':
745 return 0x0D;
746 case '"':
747 return 0x22;
748 case '\'':
749 return 0x27;
750 case '\\':
751 return 0x5C;
752 default:
753 return c;
754 }
755}
756
757unsigned short Lexer::convertOctal(unsigned short c1, unsigned short c2,
758 unsigned short c3) const
759{
760 return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
761}
762
763unsigned char Lexer::convertHex(unsigned short c)
764{
765 if (c >= '0' && c <= '9')
766 return (c - '0');
767 else if (c >= 'a' && c <= 'f')
768 return (c - 'a' + 10);
769 else
770 return (c - 'A' + 10);
771}
772
773unsigned char Lexer::convertHex(unsigned short c1, unsigned short c2)
774{
775 return ((convertHex(c1) << 4) + convertHex(c2));
776}
777
778KJS::UChar Lexer::convertUnicode(unsigned short c1, unsigned short c2,
779 unsigned short c3, unsigned short c4)
780{
781 return KJS::UChar((convertHex(c1) << 4) + convertHex(c2),
782 (convertHex(c3) << 4) + convertHex(c4));
783}
784
785void Lexer::record8(unsigned short c)
786{
787 assert(c <= 0xff);
788
789 // enlarge buffer if full
790 if (pos8 >= size8 - 1) {
791 char *tmp = new char[2 * size8];
792 memcpy(tmp, buffer8, size8 * sizeof(char));
793 delete [] buffer8;
794 buffer8 = tmp;
795 size8 *= 2;
796 }
797
798 buffer8[pos8++] = (char) c;
799}
800
801void Lexer::record16(KJS::UChar c)
802{
803 // enlarge buffer if full
804 if (pos16 >= size16 - 1) {
805 KJS::UChar *tmp = new KJS::UChar[2 * size16];
806 memcpy(tmp, buffer16, size16 * sizeof(KJS::UChar));
807 delete [] buffer16;
808 buffer16 = tmp;
809 size16 *= 2;
810 }
811
812 buffer16[pos16++] = c;
813}
814
815bool Lexer::scanRegExp()
816{
817 pos16 = 0;
818 bool lastWasEscape = false;
819 bool inBrackets = false;
820
821 while (1) {
822 if (isLineTerminator() || current == 0)
823 return false;
824 else if (current != '/' || lastWasEscape == true || inBrackets == true)
825 {
826 // keep track of '[' and ']'
827 if ( !lastWasEscape ) {
828 if ( current == '[' && !inBrackets )
829 inBrackets = true;
830 if ( current == ']' && inBrackets )
831 inBrackets = false;
832 }
833 record16(current);
834 lastWasEscape =
835 !lastWasEscape && (current == '\\');
836 }
837 else { // end of regexp
838 pattern = UString(buffer16, pos16);
839 pos16 = 0;
840 shift(1);
841 break;
842 }
843 shift(1);
844 }
845
846 while (isIdentPart(current)) {
847 record16(current);
848 shift(1);
849 }
850 flags = UString(buffer16, pos16);
851
852 return true;
853}
854
855
856void Lexer::doneParsing()
857{
858 for (unsigned i = 0; i < numIdentifiers; i++) {
859 delete identifiers[i];
860 }
861 fastFree(identifiers);
862 identifiers = 0;
863 numIdentifiers = 0;
864 identifiersCapacity = 0;
865
866 for (unsigned i = 0; i < numStrings; i++) {
867 delete strings[i];
868 }
869 fastFree(strings);
870 strings = 0;
871 numStrings = 0;
872 stringsCapacity = 0;
873}
874
875const int initialCapacity = 64;
876const int growthFactor = 2;
877
878Identifier *Lexer::makeIdentifier(KJS::UChar *buffer, unsigned int pos)
879{
880 if (numIdentifiers == identifiersCapacity) {
881 identifiersCapacity = (identifiersCapacity == 0) ? initialCapacity : identifiersCapacity *growthFactor;
882 identifiers = (KJS::Identifier **)fastRealloc(identifiers, sizeof(KJS::Identifier *) * identifiersCapacity);
883 }
884
885 KJS::Identifier *identifier = new KJS::Identifier(buffer16, pos16);
886 identifiers[numIdentifiers++] = identifier;
887 return identifier;
888}
889
890UString *Lexer::makeUString(KJS::UChar *buffer, unsigned int pos)
891{
892 if (numStrings == stringsCapacity) {
893 stringsCapacity = (stringsCapacity == 0) ? initialCapacity : stringsCapacity *growthFactor;
894 strings = (UString **)fastRealloc(strings, sizeof(UString *) * stringsCapacity);
895 }
896
897 UString *string = new UString(buffer16, pos16);
898 strings[numStrings++] = string;
899 return string;
900}
Note: See TracBrowser for help on using the repository browser.