00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <ctype.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <assert.h>
00032
00033 #include "value.h"
00034 #include "object.h"
00035 #include "types.h"
00036 #include "interpreter.h"
00037 #include "nodes.h"
00038 #include "lexer.h"
00039 #include "identifier.h"
00040 #include "lookup.h"
00041 #include "internal.h"
00042
00043
00044 using namespace KJS;
00045
00046 static Lexer *currLexer = 0;
00047
00048 #ifndef KDE_USE_FINAL
00049 #include "grammar.h"
00050 #endif
00051
00052 #include "lexer.lut.h"
00053
00054 extern YYLTYPE yylloc;
00055
00056
00057 int kjsyylex()
00058 {
00059 return Lexer::curr()->lex();
00060 }
00061
00062 Lexer::Lexer()
00063 : yylineno(1),
00064 size8(128), size16(128), restrKeyword(false),
00065 eatNextIdentifier(false), stackToken(-1), lastToken(-1), pos(0),
00066 code(0), length(0),
00067 #ifndef KJS_PURE_ECMA
00068 bol(true),
00069 #endif
00070 current(0), next1(0), next2(0), next3(0),
00071 strings(0), numStrings(0), stringsCapacity(0),
00072 identifiers(0), numIdentifiers(0), identifiersCapacity(0)
00073 {
00074
00075 buffer8 = new char[size8];
00076 buffer16 = new UChar[size16];
00077 currLexer = this;
00078 }
00079
00080 Lexer::~Lexer()
00081 {
00082 delete [] buffer8;
00083 delete [] buffer16;
00084 }
00085
00086 Lexer *Lexer::curr()
00087 {
00088 if (!currLexer) {
00089
00090 currLexer = new Lexer();
00091 }
00092 return currLexer;
00093 }
00094
00095 #ifdef KJS_DEBUG_MEM
00096 void Lexer::globalClear()
00097 {
00098 delete currLexer;
00099 currLexer = 0L;
00100 }
00101 #endif
00102
00103 void Lexer::setCode(const UChar *c, unsigned int len)
00104 {
00105 yylineno = 1;
00106 restrKeyword = false;
00107 delimited = false;
00108 eatNextIdentifier = false;
00109 stackToken = -1;
00110 lastToken = -1;
00111 foundBad = false;
00112 pos = 0;
00113 code = c;
00114 length = len;
00115 skipLF = false;
00116 skipCR = false;
00117 #ifndef KJS_PURE_ECMA
00118 bol = true;
00119 #endif
00120
00121
00122 current = (length > 0) ? code[0].uc : 0;
00123 next1 = (length > 1) ? code[1].uc : 0;
00124 next2 = (length > 2) ? code[2].uc : 0;
00125 next3 = (length > 3) ? code[3].uc : 0;
00126 }
00127
00128 void Lexer::shift(unsigned int p)
00129 {
00130 while (p--) {
00131 pos++;
00132 current = next1;
00133 next1 = next2;
00134 next2 = next3;
00135 next3 = (pos + 3 < length) ? code[pos+3].uc : 0;
00136 }
00137 }
00138
00139
00140 void Lexer::nextLine()
00141 {
00142 yylineno++;
00143 #ifndef KJS_PURE_ECMA
00144 bol = true;
00145 #endif
00146 }
00147
00148 void Lexer::setDone(State s)
00149 {
00150 state = s;
00151 done = true;
00152 }
00153
00154 int Lexer::lex()
00155 {
00156 int token = 0;
00157 state = Start;
00158 unsigned short stringType = 0;
00159 pos8 = pos16 = 0;
00160 done = false;
00161 terminator = false;
00162 skipLF = false;
00163 skipCR = false;
00164
00165
00166
00167 if (stackToken >= 0) {
00168 setDone(Other);
00169 token = stackToken;
00170 stackToken = 0;
00171 }
00172
00173 while (!done) {
00174 if (skipLF && current != '\n')
00175 skipLF = false;
00176 if (skipCR && current != '\r')
00177 skipCR = false;
00178 if (skipLF || skipCR)
00179 {
00180 skipLF = false;
00181 skipCR = false;
00182 shift(1);
00183 }
00184
00185 bool cr = (current == '\r');
00186 bool lf = (current == '\n');
00187 if (cr)
00188 skipLF = true;
00189 else if (lf)
00190 skipCR = true;
00191 bool isLineTerminator = cr || lf;
00192
00193 switch (state) {
00194 case Start:
00195 if (isWhiteSpace(current)) {
00196
00197 } else if (current == '/' && next1 == '/') {
00198 shift(1);
00199 state = InSingleLineComment;
00200 } else if (current == '/' && next1 == '*') {
00201 shift(1);
00202 state = InMultiLineComment;
00203 } else if (current == 0) {
00204 if (!terminator && !delimited) {
00205
00206 token = ';';
00207 stackToken = 0;
00208 setDone(Other);
00209 } else
00210 setDone(Eof);
00211 } else if (isLineTerminator) {
00212 nextLine();
00213 terminator = true;
00214 if (restrKeyword) {
00215 token = ';';
00216 setDone(Other);
00217 }
00218 } else if (current == '"' || current == '\'') {
00219 state = InString;
00220 stringType = current;
00221 } else if (isIdentLetter(current)) {
00222 record16(current);
00223 state = InIdentifier;
00224 } else if (current == '0') {
00225 record8(current);
00226 state = InNum0;
00227 } else if (isDecimalDigit(current)) {
00228 record8(current);
00229 state = InNum;
00230 } else if (current == '.' && isDecimalDigit(next1)) {
00231 record8(current);
00232 state = InDecimal;
00233 #ifndef KJS_PURE_ECMA
00234
00235 } else if (current == '<' && next1 == '!' &&
00236 next2 == '-' && next3 == '-') {
00237 shift(3);
00238 state = InSingleLineComment;
00239
00240 } else if (bol && current == '-' && next1 == '-' && next2 == '>') {
00241 shift(2);
00242 state = InSingleLineComment;
00243 #endif
00244 } else {
00245 token = matchPunctuator(current, next1, next2, next3);
00246 if (token != -1) {
00247 setDone(Other);
00248 } else {
00249
00250 setDone(Bad);
00251 }
00252 }
00253 break;
00254 case InString:
00255 if (current == stringType) {
00256 shift(1);
00257 setDone(String);
00258 } else if (current == 0 || isLineTerminator) {
00259 setDone(Bad);
00260 } else if (current == '\\') {
00261 state = InEscapeSequence;
00262 } else {
00263 record16(current);
00264 }
00265 break;
00266
00267 case InEscapeSequence:
00268 if (isOctalDigit(current)) {
00269 if (current >= '0' && current <= '3' &&
00270 isOctalDigit(next1) && isOctalDigit(next2)) {
00271 record16(convertOctal(current, next1, next2));
00272 shift(2);
00273 state = InString;
00274 } else if (isOctalDigit(current) && isOctalDigit(next1)) {
00275 record16(convertOctal('0', current, next1));
00276 shift(1);
00277 state = InString;
00278 } else if (isOctalDigit(current)) {
00279 record16(convertOctal('0', '0', current));
00280 state = InString;
00281 } else {
00282 setDone(Bad);
00283 }
00284 } else if (current == 'x')
00285 state = InHexEscape;
00286 else if (current == 'u')
00287 state = InUnicodeEscape;
00288 else {
00289 if (isLineTerminator)
00290 nextLine();
00291 record16(singleEscape(current));
00292 state = InString;
00293 }
00294 break;
00295 case InHexEscape:
00296 if (isHexDigit(current) && isHexDigit(next1)) {
00297 state = InString;
00298 record16(convertHex(current, next1));
00299 shift(1);
00300 } else if (current == stringType) {
00301 record16('x');
00302 shift(1);
00303 setDone(String);
00304 } else {
00305 record16('x');
00306 record16(current);
00307 state = InString;
00308 }
00309 break;
00310 case InUnicodeEscape:
00311 if (isHexDigit(current) && isHexDigit(next1) &&
00312 isHexDigit(next2) && isHexDigit(next3)) {
00313 record16(convertUnicode(current, next1, next2, next3));
00314 shift(3);
00315 state = InString;
00316 } else if (current == stringType) {
00317 record16('u');
00318 shift(1);
00319 setDone(String);
00320 } else {
00321 setDone(Bad);
00322 }
00323 break;
00324 case InSingleLineComment:
00325 if (isLineTerminator) {
00326 nextLine();
00327 terminator = true;
00328 if (restrKeyword) {
00329 token = ';';
00330 setDone(Other);
00331 } else
00332 state = Start;
00333 } else if (current == 0) {
00334 setDone(Eof);
00335 }
00336 break;
00337 case InMultiLineComment:
00338 if (current == 0) {
00339 setDone(Bad);
00340 } else if (isLineTerminator) {
00341 nextLine();
00342 } else if (current == '*' && next1 == '/') {
00343 state = Start;
00344 shift(1);
00345 }
00346 break;
00347 case InIdentifier:
00348 if (isIdentLetter(current) || isDecimalDigit(current)) {
00349 record16(current);
00350 break;
00351 }
00352 setDone(Identifier);
00353 break;
00354 case InNum0:
00355 if (current == 'x' || current == 'X') {
00356 record8(current);
00357 state = InHex;
00358 } else if (current == '.') {
00359 record8(current);
00360 state = InDecimal;
00361 } else if (current == 'e' || current == 'E') {
00362 record8(current);
00363 state = InExponentIndicator;
00364 } else if (isOctalDigit(current)) {
00365 record8(current);
00366 state = InOctal;
00367 } else if (isDecimalDigit(current)) {
00368 record8(current);
00369 state = InDecimal;
00370 } else {
00371 setDone(Number);
00372 }
00373 break;
00374 case InHex:
00375 if (isHexDigit(current)) {
00376 record8(current);
00377 } else {
00378 setDone(Hex);
00379 }
00380 break;
00381 case InOctal:
00382 if (isOctalDigit(current)) {
00383 record8(current);
00384 }
00385 else if (isDecimalDigit(current)) {
00386 record8(current);
00387 state = InDecimal;
00388 } else
00389 setDone(Octal);
00390 break;
00391 case InNum:
00392 if (isDecimalDigit(current)) {
00393 record8(current);
00394 } else if (current == '.') {
00395 record8(current);
00396 state = InDecimal;
00397 } else if (current == 'e' || current == 'E') {
00398 record8(current);
00399 state = InExponentIndicator;
00400 } else
00401 setDone(Number);
00402 break;
00403 case InDecimal:
00404 if (isDecimalDigit(current)) {
00405 record8(current);
00406 } else if (current == 'e' || current == 'E') {
00407 record8(current);
00408 state = InExponentIndicator;
00409 } else
00410 setDone(Number);
00411 break;
00412 case InExponentIndicator:
00413 if (current == '+' || current == '-') {
00414 record8(current);
00415 } else if (isDecimalDigit(current)) {
00416 record8(current);
00417 state = InExponent;
00418 } else
00419 setDone(Bad);
00420 break;
00421 case InExponent:
00422 if (isDecimalDigit(current)) {
00423 record8(current);
00424 } else
00425 setDone(Number);
00426 break;
00427 default:
00428 assert(!"Unhandled state in switch statement");
00429 }
00430
00431
00432 if (!done)
00433 shift(1);
00434 #ifndef KJS_PURE_ECMA
00435 if (state != Start && state != InSingleLineComment)
00436 bol = false;
00437 #endif
00438 }
00439
00440
00441 if ((state == Number || state == Octal || state == Hex)
00442 && isIdentLetter(current))
00443 state = Bad;
00444
00445
00446 buffer8[pos8] = '\0';
00447
00448 #ifdef KJS_DEBUG_LEX
00449 fprintf(stderr, "line: %d ", lineNo());
00450 fprintf(stderr, "yytext (%x): ", buffer8[0]);
00451 fprintf(stderr, "%s ", buffer8);
00452 #endif
00453
00454 long double dval = 0;
00455 if (state == Number) {
00456 dval = strtod(buffer8, 0L);
00457 } else if (state == Hex) {
00458 dval = 0;
00459 if (buffer8[0] == '0' && (buffer8[1] == 'x' || buffer8[1] == 'X')) {
00460 for (const char *p = buffer8+2; *p; p++) {
00461 if (!isHexDigit(*p)) {
00462 dval = 0;
00463 break;
00464 }
00465 dval = dval * 16 + convertHex(*p);
00466 }
00467 }
00468 state = Number;
00469 } else if (state == Octal) {
00470 dval = 0;
00471 if (buffer8[0] == '0') {
00472 for (const char *p = buffer8+1; *p; p++) {
00473 if (*p < '0' || *p > '7') {
00474 dval = 0;
00475 break;
00476 }
00477 dval = dval * 8 + *p - '0';
00478 }
00479 }
00480 state = Number;
00481 }
00482
00483 #ifdef KJS_DEBUG_LEX
00484 switch (state) {
00485 case Eof:
00486 printf("(EOF)\n");
00487 break;
00488 case Other:
00489 printf("(Other)\n");
00490 break;
00491 case Identifier:
00492 printf("(Identifier)/(Keyword)\n");
00493 break;
00494 case String:
00495 printf("(String)\n");
00496 break;
00497 case Number:
00498 printf("(Number)\n");
00499 break;
00500 default:
00501 printf("(unknown)");
00502 }
00503 #endif
00504
00505 if (state != Identifier && eatNextIdentifier)
00506 eatNextIdentifier = false;
00507
00508 restrKeyword = false;
00509 delimited = false;
00510 kjsyylloc.first_line = yylineno;
00511 kjsyylloc.last_line = yylineno;
00512
00513 switch (state) {
00514 case Eof:
00515 token = 0;
00516 break;
00517 case Other:
00518 if(token == '}' || token == ';') {
00519 delimited = true;
00520 }
00521 break;
00522 case Identifier:
00523 if ((token = Lookup::find(&mainTable, buffer16, pos16)) < 0) {
00524
00525
00526 if (eatNextIdentifier) {
00527 eatNextIdentifier = false;
00528 #ifdef KJS_VERBOSE
00529 UString debugstr(buffer16, pos16); fprintf(stderr,"Anonymous function hack: eating identifier %s\n",debugstr.ascii());
00530 #endif
00531 token = lex();
00532 break;
00533 }
00534
00535 kjsyylval.ident = makeIdentifier(buffer16, pos16);
00536 token = IDENT;
00537 break;
00538 }
00539
00540 eatNextIdentifier = false;
00541
00542
00543
00544 if ( token == FUNCTION &&
00545 ( lastToken == '=' || lastToken == ',' || lastToken == '(' ) )
00546 eatNextIdentifier = true;
00547
00548 if (token == CONTINUE || token == BREAK ||
00549 token == RETURN || token == THROW)
00550 restrKeyword = true;
00551 break;
00552 case String:
00553 kjsyylval.ustr = makeUString(buffer16, pos16);
00554 token = STRING;
00555 break;
00556 case Number:
00557 kjsyylval.dval = dval;
00558 token = NUMBER;
00559 break;
00560 case Bad:
00561 foundBad = true;
00562 return -1;
00563 default:
00564 assert(!"unhandled numeration value in switch");
00565 return -1;
00566 }
00567 lastToken = token;
00568 return token;
00569 }
00570
00571 bool Lexer::isWhiteSpace(unsigned short c)
00572 {
00573 return (c == ' ' || c == '\t' ||
00574 c == 0x0b || c == 0x0c || c == 0xa0);
00575 }
00576
00577 bool Lexer::isIdentLetter(unsigned short c)
00578 {
00579
00580
00581
00582
00583
00584 return (c >= 'a' && c <= 'z' ||
00585 c >= 'A' && c <= 'Z' ||
00586
00587 c >= 0x00c0 && c <= 0x00d6 ||
00588
00589 c >= 0x00d8 && c <= 0x00f6 ||
00590
00591 c >= 0x00f8 && c <= 0x02af ||
00592
00593 c >= 0x0388 && c <= 0x1ffc ||
00594 c == '$' || c == '_');
00595
00596 }
00597
00598 bool Lexer::isDecimalDigit(unsigned short c)
00599 {
00600 return (c >= '0' && c <= '9');
00601 }
00602
00603 bool Lexer::isHexDigit(unsigned short c)
00604 {
00605 return (c >= '0' && c <= '9' ||
00606 c >= 'a' && c <= 'f' ||
00607 c >= 'A' && c <= 'F');
00608 }
00609
00610 bool Lexer::isOctalDigit(unsigned short c)
00611 {
00612 return (c >= '0' && c <= '7');
00613 }
00614
00615 int Lexer::matchPunctuator(unsigned short c1, unsigned short c2,
00616 unsigned short c3, unsigned short c4)
00617 {
00618 if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
00619 shift(4);
00620 return URSHIFTEQUAL;
00621 } else if (c1 == '=' && c2 == '=' && c3 == '=') {
00622 shift(3);
00623 return STREQ;
00624 } else if (c1 == '!' && c2 == '=' && c3 == '=') {
00625 shift(3);
00626 return STRNEQ;
00627 } else if (c1 == '>' && c2 == '>' && c3 == '>') {
00628 shift(3);
00629 return URSHIFT;
00630 } else if (c1 == '<' && c2 == '<' && c3 == '=') {
00631 shift(3);
00632 return LSHIFTEQUAL;
00633 } else if (c1 == '>' && c2 == '>' && c3 == '=') {
00634 shift(3);
00635 return RSHIFTEQUAL;
00636 } else if (c1 == '<' && c2 == '=') {
00637 shift(2);
00638 return LE;
00639 } else if (c1 == '>' && c2 == '=') {
00640 shift(2);
00641 return GE;
00642 } else if (c1 == '!' && c2 == '=') {
00643 shift(2);
00644 return NE;
00645 } else if (c1 == '+' && c2 == '+') {
00646 shift(2);
00647 if (terminator)
00648 return AUTOPLUSPLUS;
00649 else
00650 return PLUSPLUS;
00651 } else if (c1 == '-' && c2 == '-') {
00652 shift(2);
00653 if (terminator)
00654 return AUTOMINUSMINUS;
00655 else
00656 return MINUSMINUS;
00657 } else if (c1 == '=' && c2 == '=') {
00658 shift(2);
00659 return EQEQ;
00660 } else if (c1 == '+' && c2 == '=') {
00661 shift(2);
00662 return PLUSEQUAL;
00663 } else if (c1 == '-' && c2 == '=') {
00664 shift(2);
00665 return MINUSEQUAL;
00666 } else if (c1 == '*' && c2 == '=') {
00667 shift(2);
00668 return MULTEQUAL;
00669 } else if (c1 == '/' && c2 == '=') {
00670 shift(2);
00671 return DIVEQUAL;
00672 } else if (c1 == '&' && c2 == '=') {
00673 shift(2);
00674 return ANDEQUAL;
00675 } else if (c1 == '^' && c2 == '=') {
00676 shift(2);
00677 return XOREQUAL;
00678 } else if (c1 == '%' && c2 == '=') {
00679 shift(2);
00680 return MODEQUAL;
00681 } else if (c1 == '|' && c2 == '=') {
00682 shift(2);
00683 return OREQUAL;
00684 } else if (c1 == '<' && c2 == '<') {
00685 shift(2);
00686 return LSHIFT;
00687 } else if (c1 == '>' && c2 == '>') {
00688 shift(2);
00689 return RSHIFT;
00690 } else if (c1 == '&' && c2 == '&') {
00691 shift(2);
00692 return AND;
00693 } else if (c1 == '|' && c2 == '|') {
00694 shift(2);
00695 return OR;
00696 }
00697
00698 switch(c1) {
00699 case '=':
00700 case '>':
00701 case '<':
00702 case ',':
00703 case '!':
00704 case '~':
00705 case '?':
00706 case ':':
00707 case '.':
00708 case '+':
00709 case '-':
00710 case '*':
00711 case '/':
00712 case '&':
00713 case '|':
00714 case '^':
00715 case '%':
00716 case '(':
00717 case ')':
00718 case '{':
00719 case '}':
00720 case '[':
00721 case ']':
00722 case ';':
00723 shift(1);
00724 return static_cast<int>(c1);
00725 default:
00726 return -1;
00727 }
00728 }
00729
00730 unsigned short Lexer::singleEscape(unsigned short c) const
00731 {
00732 switch(c) {
00733 case 'b':
00734 return 0x08;
00735 case 't':
00736 return 0x09;
00737 case 'n':
00738 return 0x0A;
00739 case 'v':
00740 return 0x0B;
00741 case 'f':
00742 return 0x0C;
00743 case 'r':
00744 return 0x0D;
00745 case '"':
00746 return 0x22;
00747 case '\'':
00748 return 0x27;
00749 case '\\':
00750 return 0x5C;
00751 default:
00752 return c;
00753 }
00754 }
00755
00756 unsigned short Lexer::convertOctal(unsigned short c1, unsigned short c2,
00757 unsigned short c3) const
00758 {
00759 return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
00760 }
00761
00762 unsigned char Lexer::convertHex(unsigned short c)
00763 {
00764 if (c >= '0' && c <= '9')
00765 return (c - '0');
00766 else if (c >= 'a' && c <= 'f')
00767 return (c - 'a' + 10);
00768 else
00769 return (c - 'A' + 10);
00770 }
00771
00772 unsigned char Lexer::convertHex(unsigned short c1, unsigned short c2)
00773 {
00774 return ((convertHex(c1) << 4) + convertHex(c2));
00775 }
00776
00777 UChar Lexer::convertUnicode(unsigned short c1, unsigned short c2,
00778 unsigned short c3, unsigned short c4)
00779 {
00780 return UChar((convertHex(c1) << 4) + convertHex(c2),
00781 (convertHex(c3) << 4) + convertHex(c4));
00782 }
00783
00784 void Lexer::record8(unsigned short c)
00785 {
00786 assert(c <= 0xff);
00787
00788
00789 if (pos8 >= size8 - 1) {
00790 char *tmp = new char[2 * size8];
00791 memcpy(tmp, buffer8, size8 * sizeof(char));
00792 delete [] buffer8;
00793 buffer8 = tmp;
00794 size8 *= 2;
00795 }
00796
00797 buffer8[pos8++] = (char) c;
00798 }
00799
00800 void Lexer::record16(UChar c)
00801 {
00802
00803 if (pos16 >= size16 - 1) {
00804 UChar *tmp = new UChar[2 * size16];
00805 memcpy(tmp, buffer16, size16 * sizeof(UChar));
00806 delete [] buffer16;
00807 buffer16 = tmp;
00808 size16 *= 2;
00809 }
00810
00811 buffer16[pos16++] = c;
00812 }
00813
00814 bool Lexer::scanRegExp()
00815 {
00816 pos16 = 0;
00817 bool lastWasEscape = false;
00818 bool inBrackets = false;
00819
00820 while (1) {
00821 if (current == '\r' || current == '\n' || current == 0)
00822 return false;
00823 else if (current != '/' || lastWasEscape == true || inBrackets == true)
00824 {
00825
00826 if ( !lastWasEscape ) {
00827 if ( current == '[' && !inBrackets )
00828 inBrackets = true;
00829 if ( current == ']' && inBrackets )
00830 inBrackets = false;
00831 }
00832 record16(current);
00833 lastWasEscape =
00834 !lastWasEscape && (current == '\\');
00835 }
00836 else {
00837 pattern = UString(buffer16, pos16);
00838 pos16 = 0;
00839 shift(1);
00840 break;
00841 }
00842 shift(1);
00843 }
00844
00845 while (isIdentLetter(current)) {
00846 record16(current);
00847 shift(1);
00848 }
00849 flags = UString(buffer16, pos16);
00850
00851 return true;
00852 }
00853
00854
00855 void Lexer::doneParsing()
00856 {
00857 for (unsigned i = 0; i < numIdentifiers; i++) {
00858 delete identifiers[i];
00859 }
00860 free(identifiers);
00861 identifiers = 0;
00862 numIdentifiers = 0;
00863 identifiersCapacity = 0;
00864
00865 for (unsigned i = 0; i < numStrings; i++) {
00866 delete strings[i];
00867 }
00868 free(strings);
00869 strings = 0;
00870 numStrings = 0;
00871 stringsCapacity = 0;
00872 }
00873
00874 const int initialCapacity = 64;
00875 const int growthFactor = 2;
00876
00877 Identifier *Lexer::makeIdentifier(UChar *buffer, unsigned int pos)
00878 {
00879 if (numIdentifiers == identifiersCapacity) {
00880 identifiersCapacity = (identifiersCapacity == 0) ? initialCapacity : identifiersCapacity *growthFactor;
00881 identifiers = (KJS::Identifier **)realloc(identifiers, sizeof(KJS::Identifier *) * identifiersCapacity);
00882 }
00883
00884 KJS::Identifier *identifier = new KJS::Identifier(buffer, pos);
00885 identifiers[numIdentifiers++] = identifier;
00886 return identifier;
00887 }
00888
00889 UString *Lexer::makeUString(UChar *buffer, unsigned int pos)
00890 {
00891 if (numStrings == stringsCapacity) {
00892 stringsCapacity = (stringsCapacity == 0) ? initialCapacity : stringsCapacity *growthFactor;
00893 strings = (UString **)realloc(strings, sizeof(UString *) * stringsCapacity);
00894 }
00895
00896 UString *string = new UString(buffer, pos);
00897 strings[numStrings++] = string;
00898 return string;
00899 }