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 yylloc.first_line = yylineno;
00511 yylloc.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
return (c >=
'a' && c <=
'z' ||
00581 c >=
'A' && c <=
'Z' ||
00582 c ==
'$' || c ==
'_');
00583 }
00584
00585
bool Lexer::isDecimalDigit(
unsigned short c)
00586 {
00587
return (c >=
'0' && c <=
'9');
00588 }
00589
00590
bool Lexer::isHexDigit(
unsigned short c)
00591 {
00592
return (c >=
'0' && c <=
'9' ||
00593 c >=
'a' && c <=
'f' ||
00594 c >=
'A' && c <=
'F');
00595 }
00596
00597
bool Lexer::isOctalDigit(
unsigned short c)
00598 {
00599
return (c >=
'0' && c <=
'7');
00600 }
00601
00602
int Lexer::matchPunctuator(
unsigned short c1,
unsigned short c2,
00603
unsigned short c3,
unsigned short c4)
00604 {
00605
if (c1 ==
'>' && c2 ==
'>' && c3 ==
'>' && c4 ==
'=') {
00606 shift(4);
00607
return URSHIFTEQUAL;
00608 }
else if (c1 ==
'=' && c2 ==
'=' && c3 ==
'=') {
00609 shift(3);
00610
return STREQ;
00611 }
else if (c1 ==
'!' && c2 ==
'=' && c3 ==
'=') {
00612 shift(3);
00613
return STRNEQ;
00614 }
else if (c1 ==
'>' && c2 ==
'>' && c3 ==
'>') {
00615 shift(3);
00616
return URSHIFT;
00617 }
else if (c1 ==
'<' && c2 ==
'<' && c3 ==
'=') {
00618 shift(3);
00619
return LSHIFTEQUAL;
00620 }
else if (c1 ==
'>' && c2 ==
'>' && c3 ==
'=') {
00621 shift(3);
00622
return RSHIFTEQUAL;
00623 }
else if (c1 ==
'<' && c2 ==
'=') {
00624 shift(2);
00625
return LE;
00626 }
else if (c1 ==
'>' && c2 ==
'=') {
00627 shift(2);
00628
return GE;
00629 }
else if (c1 ==
'!' && c2 ==
'=') {
00630 shift(2);
00631
return NE;
00632 }
else if (c1 ==
'+' && c2 ==
'+') {
00633 shift(2);
00634
if (terminator)
00635
return AUTOPLUSPLUS;
00636
else
00637
return PLUSPLUS;
00638 }
else if (c1 ==
'-' && c2 ==
'-') {
00639 shift(2);
00640
if (terminator)
00641
return AUTOMINUSMINUS;
00642
else
00643
return MINUSMINUS;
00644 }
else if (c1 ==
'=' && c2 ==
'=') {
00645 shift(2);
00646
return EQEQ;
00647 }
else if (c1 ==
'+' && c2 ==
'=') {
00648 shift(2);
00649
return PLUSEQUAL;
00650 }
else if (c1 ==
'-' && c2 ==
'=') {
00651 shift(2);
00652
return MINUSEQUAL;
00653 }
else if (c1 ==
'*' && c2 ==
'=') {
00654 shift(2);
00655
return MULTEQUAL;
00656 }
else if (c1 ==
'/' && c2 ==
'=') {
00657 shift(2);
00658
return DIVEQUAL;
00659 }
else if (c1 ==
'&' && c2 ==
'=') {
00660 shift(2);
00661
return ANDEQUAL;
00662 }
else if (c1 ==
'^' && c2 ==
'=') {
00663 shift(2);
00664
return XOREQUAL;
00665 }
else if (c1 ==
'%' && c2 ==
'=') {
00666 shift(2);
00667
return MODEQUAL;
00668 }
else if (c1 ==
'|' && c2 ==
'=') {
00669 shift(2);
00670
return OREQUAL;
00671 }
else if (c1 ==
'<' && c2 ==
'<') {
00672 shift(2);
00673
return LSHIFT;
00674 }
else if (c1 ==
'>' && c2 ==
'>') {
00675 shift(2);
00676
return RSHIFT;
00677 }
else if (c1 ==
'&' && c2 ==
'&') {
00678 shift(2);
00679
return AND;
00680 }
else if (c1 ==
'|' && c2 ==
'|') {
00681 shift(2);
00682
return OR;
00683 }
00684
00685
switch(c1) {
00686
case '=':
00687
case '>':
00688
case '<':
00689
case ',':
00690
case '!':
00691
case '~':
00692
case '?':
00693
case ':':
00694
case '.':
00695
case '+':
00696
case '-':
00697
case '*':
00698
case '/':
00699
case '&':
00700
case '|':
00701
case '^':
00702
case '%':
00703
case '(':
00704
case ')':
00705
case '{':
00706
case '}':
00707
case '[':
00708
case ']':
00709
case ';':
00710 shift(1);
00711
return static_cast<int>(c1);
00712
default:
00713
return -1;
00714 }
00715 }
00716
00717
unsigned short Lexer::singleEscape(
unsigned short c)
const
00718
{
00719
switch(c) {
00720
case 'b':
00721
return 0x08;
00722
case 't':
00723
return 0x09;
00724
case 'n':
00725
return 0x0A;
00726
case 'v':
00727
return 0x0B;
00728
case 'f':
00729
return 0x0C;
00730
case 'r':
00731
return 0x0D;
00732
case '"':
00733
return 0x22;
00734
case '\'':
00735
return 0x27;
00736
case '\\':
00737
return 0x5C;
00738
default:
00739
return c;
00740 }
00741 }
00742
00743
unsigned short Lexer::convertOctal(
unsigned short c1,
unsigned short c2,
00744
unsigned short c3)
const
00745
{
00746
return ((c1 -
'0') * 64 + (c2 -
'0') * 8 + c3 -
'0');
00747 }
00748
00749
unsigned char Lexer::convertHex(
unsigned short c)
00750 {
00751
if (c >=
'0' && c <=
'9')
00752
return (c -
'0');
00753
else if (c >=
'a' && c <=
'f')
00754
return (c -
'a' + 10);
00755
else
00756
return (c -
'A' + 10);
00757 }
00758
00759
unsigned char Lexer::convertHex(
unsigned short c1,
unsigned short c2)
00760 {
00761
return ((convertHex(c1) << 4) + convertHex(c2));
00762 }
00763
00764
UChar Lexer::convertUnicode(
unsigned short c1,
unsigned short c2,
00765
unsigned short c3,
unsigned short c4)
00766 {
00767
return UChar((convertHex(c1) << 4) + convertHex(c2),
00768 (convertHex(c3) << 4) + convertHex(c4));
00769 }
00770
00771
void Lexer::record8(
unsigned short c)
00772 {
00773 assert(c <= 0xff);
00774
00775
00776
if (pos8 >= size8 - 1) {
00777
char *tmp =
new char[2 * size8];
00778 memcpy(tmp, buffer8, size8 *
sizeof(
char));
00779
delete [] buffer8;
00780 buffer8 = tmp;
00781 size8 *= 2;
00782 }
00783
00784 buffer8[pos8++] = (
char) c;
00785 }
00786
00787
void Lexer::record16(
UChar c)
00788 {
00789
00790
if (pos16 >= size16 - 1) {
00791
UChar *tmp =
new UChar[2 * size16];
00792 memcpy(tmp, buffer16, size16 *
sizeof(UChar));
00793
delete [] buffer16;
00794 buffer16 = tmp;
00795 size16 *= 2;
00796 }
00797
00798 buffer16[pos16++] = c;
00799 }
00800
00801
bool Lexer::scanRegExp()
00802 {
00803 pos16 = 0;
00804
bool lastWasEscape =
false;
00805
bool inBrackets =
false;
00806
00807
while (1) {
00808
if (current ==
'\r' || current ==
'\n' || current == 0)
00809
return false;
00810
else if (current !=
'/' || lastWasEscape ==
true || inBrackets ==
true)
00811 {
00812
00813
if ( !lastWasEscape ) {
00814
if ( current ==
'[' && !inBrackets )
00815 inBrackets =
true;
00816
if ( current ==
']' && inBrackets )
00817 inBrackets =
false;
00818 }
00819 record16(current);
00820 lastWasEscape =
00821 !lastWasEscape && (current ==
'\\');
00822 }
00823
else {
00824 pattern =
UString(buffer16, pos16);
00825 pos16 = 0;
00826 shift(1);
00827
break;
00828 }
00829 shift(1);
00830 }
00831
00832
while (isIdentLetter(current)) {
00833 record16(current);
00834 shift(1);
00835 }
00836 flags =
UString(buffer16, pos16);
00837
00838
return true;
00839 }
00840
00841
00842
void Lexer::doneParsing()
00843 {
00844
for (
unsigned i = 0; i < numIdentifiers; i++) {
00845
delete identifiers[i];
00846 }
00847 free(identifiers);
00848 identifiers = 0;
00849 numIdentifiers = 0;
00850 identifiersCapacity = 0;
00851
00852
for (
unsigned i = 0; i < numStrings; i++) {
00853
delete strings[i];
00854 }
00855 free(strings);
00856 strings = 0;
00857 numStrings = 0;
00858 stringsCapacity = 0;
00859 }
00860
00861
const int initialCapacity = 64;
00862
const int growthFactor = 2;
00863
00864
Identifier *Lexer::makeIdentifier(
UChar *buffer,
unsigned int pos)
00865 {
00866
if (numIdentifiers == identifiersCapacity) {
00867 identifiersCapacity = (identifiersCapacity == 0) ? initialCapacity : identifiersCapacity *growthFactor;
00868 identifiers = (
KJS::Identifier **)realloc(identifiers,
sizeof(
KJS::Identifier *) * identifiersCapacity);
00869 }
00870
00871
KJS::Identifier *identifier =
new KJS::Identifier(buffer, pos);
00872 identifiers[numIdentifiers++] = identifier;
00873
return identifier;
00874 }
00875
00876
UString *Lexer::makeUString(
UChar *buffer,
unsigned int pos)
00877 {
00878
if (numStrings == stringsCapacity) {
00879 stringsCapacity = (stringsCapacity == 0) ? initialCapacity : stringsCapacity *growthFactor;
00880 strings = (
UString **)realloc(strings,
sizeof(
UString *) * stringsCapacity);
00881 }
00882
00883
UString *string =
new UString(buffer, pos);
00884 strings[numStrings++] = string;
00885
return string;
00886 }