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

Last change on this file since 13597 was 13203, checked in by darin, 19 years ago

JavaScriptCore:

Reviewed by Anders.

  • kjs/lexer.cpp: (Lexer::lex): Turn off the "yylex: ERROR" message.
  • kjs/regexp.cpp: (KJS::RegExp::RegExp): Remove the code to log errors from PCRE to standard output. I think we should arrange for the error text to be in JavaScript exceptions instead at some point.
  • kxmlcore/Vector.h: Add a check for overflow so that we'll abort if we pass a too-large size rather than allocating a buffer smaller than requested.

WebCore:

Reviewed by Anders.

  • khtml/xsl/xsl_stylesheetimpl.cpp: (WebCore::XSLStyleSheetImpl::parseString): Pass XML_PARSE_NOERROR and XML_PARSE_NOWARNING. We don't want errors and warnings to be logged to stdout or stderr. If we later decide we want the error messages, then we should do the additional work to put them into the web page or the console (along with the JavaScript errors).
  • platform/ArrayImpl.cpp: (WebCore::ArrayImpl::resize): Add a preflight to protect against integer overflow due to large array size. Noticed this while looking into the malloc error message.

WebKit:

Reviewed by Anders.

  • WebView/WebDataSourcePrivate.h:
  • WebView/WebDataSource.m: (-[WebDataSource _setRepresentation:]): Clear the flag that records whether we've sent all the data to the representation or not; need this to prevent telling the same representation both that we've succeeded and then later that we've failed. (-[WebDataSource _setMainDocumentError:]): Don't send an error if representationFinishedLoading is already YES. Set representationFinishedLoading. (-[WebDataSource _finishedLoading]): Set representationFinishedLoading. (-[WebDataSource _setupForReplaceByMIMEType:]): Ditto.

WebKitTools:

Reviewed by Anders.

  • DumpRenderTree/DumpRenderTree.m: (checkedMalloc): Added. (checkedRealloc): Added. (makeLargeMallocFailSilently): Added. (main): Call makeLargeMallocFailSilently.
  • Property svn:eol-style set to native
File size: 21.5 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 Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "lexer.h"
25
26#include <ctype.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#include <assert.h>
31
32#include "value.h"
33#include "object.h"
34#include "types.h"
35#include "interpreter.h"
36#include "nodes.h"
37#include "identifier.h"
38#include "lookup.h"
39#include "internal.h"
40#include <unicode/uchar.h>
41
42static bool isDecimalDigit(unsigned short c);
43
44// we can't specify the namespace in yacc's C output, so do it here
45using namespace KJS;
46
47static Lexer *currLexer = 0;
48
49#ifndef KDE_USE_FINAL
50#include "grammar.h"
51#endif
52
53#include "lexer.lut.h"
54
55extern YYLTYPE kjsyylloc; // global bison variable holding token info
56
57// a bridge for yacc from the C world to C++
58int kjsyylex()
59{
60 return Lexer::curr()->lex();
61}
62
63Lexer::Lexer()
64 : yylineno(1),
65 size8(128), size16(128), restrKeyword(false),
66 eatNextIdentifier(false), stackToken(-1), lastToken(-1), pos(0),
67 code(0), length(0),
68#ifndef KJS_PURE_ECMA
69 bol(true),
70#endif
71 current(0), next1(0), next2(0), next3(0),
72 strings(0), numStrings(0), stringsCapacity(0),
73 identifiers(0), numIdentifiers(0), identifiersCapacity(0)
74{
75 // allocate space for read buffers
76 buffer8 = new char[size8];
77 buffer16 = new KJS::UChar[size16];
78 currLexer = this;
79}
80
81Lexer::~Lexer()
82{
83 doneParsing();
84 delete [] buffer8;
85 delete [] buffer16;
86}
87
88Lexer *Lexer::curr()
89{
90 if (!currLexer) {
91 // create singleton instance
92 currLexer = new Lexer();
93 }
94 return currLexer;
95}
96
97#ifdef KJS_DEBUG_MEM
98void Lexer::globalClear()
99{
100 delete currLexer;
101 currLexer = 0L;
102}
103#endif
104
105void Lexer::setCode(const UString &sourceURL, int startingLineNumber, const KJS::UChar *c, unsigned int len)
106{
107 yylineno = 1 + startingLineNumber;
108 m_sourceURL = sourceURL;
109 restrKeyword = false;
110 delimited = false;
111 eatNextIdentifier = false;
112 stackToken = -1;
113 lastToken = -1;
114 pos = 0;
115 code = c;
116 length = len;
117 skipLF = false;
118 skipCR = false;
119 error = false;
120#ifndef KJS_PURE_ECMA
121 bol = true;
122#endif
123
124 // read first characters
125 shift(4);
126}
127
128void Lexer::shift(unsigned int p)
129{
130 while (p--) {
131 current = next1;
132 next1 = next2;
133 next2 = next3;
134 do {
135 if (pos >= length) {
136 next3 = 0;
137 break;
138 }
139 next3 = code[pos++].uc;
140 } while (u_charType(next3) == U_FORMAT_CHAR);
141 }
142}
143
144// called on each new line
145void Lexer::nextLine()
146{
147 yylineno++;
148#ifndef KJS_PURE_ECMA
149 bol = true;
150#endif
151}
152
153void Lexer::setDone(State s)
154{
155 state = s;
156 done = true;
157}
158
159int Lexer::lex()
160{
161 int token = 0;
162 state = Start;
163 unsigned short stringType = 0; // either single or double quotes
164 pos8 = pos16 = 0;
165 done = false;
166 terminator = false;
167 skipLF = false;
168 skipCR = false;
169
170 // did we push a token on the stack previously ?
171 // (after an automatic semicolon insertion)
172 if (stackToken >= 0) {
173 setDone(Other);
174 token = stackToken;
175 stackToken = 0;
176 }
177
178 while (!done) {
179 if (skipLF && current != '\n') // found \r but not \n afterwards
180 skipLF = false;
181 if (skipCR && current != '\r') // found \n but not \r afterwards
182 skipCR = false;
183 if (skipLF || skipCR) // found \r\n or \n\r -> eat the second one
184 {
185 skipLF = false;
186 skipCR = false;
187 shift(1);
188 }
189 switch (state) {
190 case Start:
191 if (isWhiteSpace()) {
192 // do nothing
193 } else if (current == '/' && next1 == '/') {
194 shift(1);
195 state = InSingleLineComment;
196 } else if (current == '/' && next1 == '*') {
197 shift(1);
198 state = InMultiLineComment;
199 } else if (current == 0) {
200 if (!terminator && !delimited) {
201 // automatic semicolon insertion if program incomplete
202 token = ';';
203 stackToken = 0;
204 setDone(Other);
205 } else
206 setDone(Eof);
207 } else if (isLineTerminator()) {
208 nextLine();
209 terminator = true;
210 if (restrKeyword) {
211 token = ';';
212 setDone(Other);
213 }
214 } else if (current == '"' || current == '\'') {
215 state = InString;
216 stringType = current;
217 } else if (isIdentStart(current)) {
218 record16(current);
219 state = InIdentifierOrKeyword;
220 } else if (current == '\\') {
221 state = InIdentifierUnicodeEscapeStart;
222 } else if (current == '0') {
223 record8(current);
224 state = InNum0;
225 } else if (isDecimalDigit(current)) {
226 record8(current);
227 state = InNum;
228 } else if (current == '.' && isDecimalDigit(next1)) {
229 record8(current);
230 state = InDecimal;
231#ifndef KJS_PURE_ECMA
232 // <!-- marks the beginning of a line comment (for www usage)
233 } else if (current == '<' && next1 == '!' &&
234 next2 == '-' && next3 == '-') {
235 shift(3);
236 state = InSingleLineComment;
237 // same for -->
238 } else if (bol && current == '-' && next1 == '-' && next2 == '>') {
239 shift(2);
240 state = InSingleLineComment;
241#endif
242 } else {
243 token = matchPunctuator(current, next1, next2, next3);
244 if (token != -1) {
245 setDone(Other);
246 } else {
247 // cerr << "encountered unknown character" << endl;
248 setDone(Bad);
249 }
250 }
251 break;
252 case InString:
253 if (current == stringType) {
254 shift(1);
255 setDone(String);
256 } else if (current == 0 || isLineTerminator()) {
257 setDone(Bad);
258 } else if (current == '\\') {
259 state = InEscapeSequence;
260 } else {
261 record16(current);
262 }
263 break;
264 // Escape Sequences inside of strings
265 case InEscapeSequence:
266 if (isOctalDigit(current)) {
267 if (current >= '0' && current <= '3' &&
268 isOctalDigit(next1) && isOctalDigit(next2)) {
269 record16(convertOctal(current, next1, next2));
270 shift(2);
271 state = InString;
272 } else if (isOctalDigit(current) && isOctalDigit(next1)) {
273 record16(convertOctal('0', current, next1));
274 shift(1);
275 state = InString;
276 } else if (isOctalDigit(current)) {
277 record16(convertOctal('0', '0', current));
278 state = InString;
279 } else {
280 setDone(Bad);
281 }
282 } else if (current == 'x')
283 state = InHexEscape;
284 else if (current == 'u')
285 state = InUnicodeEscape;
286 else if (isLineTerminator()) {
287 nextLine();
288 state = InString;
289 } else {
290 record16(singleEscape(current));
291 state = InString;
292 }
293 break;
294 case InHexEscape:
295 if (isHexDigit(current) && isHexDigit(next1)) {
296 state = InString;
297 record16(convertHex(current, next1));
298 shift(1);
299 } else if (current == stringType) {
300 record16('x');
301 shift(1);
302 setDone(String);
303 } else {
304 record16('x');
305 record16(current);
306 state = InString;
307 }
308 break;
309 case InUnicodeEscape:
310 if (isHexDigit(current) && isHexDigit(next1) && isHexDigit(next2) && isHexDigit(next3)) {
311 record16(convertUnicode(current, next1, next2, next3));
312 shift(3);
313 state = InString;
314 } else if (current == stringType) {
315 record16('u');
316 shift(1);
317 setDone(String);
318 } else {
319 setDone(Bad);
320 }
321 break;
322 case InSingleLineComment:
323 if (isLineTerminator()) {
324 nextLine();
325 terminator = true;
326 if (restrKeyword) {
327 token = ';';
328 setDone(Other);
329 } else
330 state = Start;
331 } else if (current == 0) {
332 setDone(Eof);
333 }
334 break;
335 case InMultiLineComment:
336 if (current == 0) {
337 setDone(Bad);
338 } else if (isLineTerminator()) {
339 nextLine();
340 } else if (current == '*' && next1 == '/') {
341 state = Start;
342 shift(1);
343 }
344 break;
345 case InIdentifierOrKeyword:
346 case InIdentifier:
347 if (isIdentPart(current))
348 record16(current);
349 else if (current == '\\')
350 state = InIdentifierUnicodeEscapeStart;
351 else
352 setDone(state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier);
353 break;
354 case InNum0:
355 if (current == 'x' || current == 'X') {
356 record8(current);
357 state = InHex;
358 } else if (current == '.') {
359 record8(current);
360 state = InDecimal;
361 } else if (current == 'e' || current == 'E') {
362 record8(current);
363 state = InExponentIndicator;
364 } else if (isOctalDigit(current)) {
365 record8(current);
366 state = InOctal;
367 } else if (isDecimalDigit(current)) {
368 record8(current);
369 state = InDecimal;
370 } else {
371 setDone(Number);
372 }
373 break;
374 case InHex:
375 if (isHexDigit(current)) {
376 record8(current);
377 } else {
378 setDone(Hex);
379 }
380 break;
381 case InOctal:
382 if (isOctalDigit(current)) {
383 record8(current);
384 }
385 else if (isDecimalDigit(current)) {
386 record8(current);
387 state = InDecimal;
388 } else
389 setDone(Octal);
390 break;
391 case InNum:
392 if (isDecimalDigit(current)) {
393 record8(current);
394 } else if (current == '.') {
395 record8(current);
396 state = InDecimal;
397 } else if (current == 'e' || current == 'E') {
398 record8(current);
399 state = InExponentIndicator;
400 } else
401 setDone(Number);
402 break;
403 case InDecimal:
404 if (isDecimalDigit(current)) {
405 record8(current);
406 } else if (current == 'e' || current == 'E') {
407 record8(current);
408 state = InExponentIndicator;
409 } else
410 setDone(Number);
411 break;
412 case InExponentIndicator:
413 if (current == '+' || current == '-') {
414 record8(current);
415 } else if (isDecimalDigit(current)) {
416 record8(current);
417 state = InExponent;
418 } else
419 setDone(Bad);
420 break;
421 case InExponent:
422 if (isDecimalDigit(current)) {
423 record8(current);
424 } else
425 setDone(Number);
426 break;
427 case InIdentifierUnicodeEscapeStart:
428 if (current == 'u')
429 state = InIdentifierUnicodeEscape;
430 else
431 setDone(Bad);
432 break;
433 case InIdentifierUnicodeEscape:
434 if (isHexDigit(current) && isHexDigit(next1) && isHexDigit(next2) && isHexDigit(next3)) {
435 record16(convertUnicode(current, next1, next2, next3));
436 shift(3);
437 state = InIdentifier;
438 } else {
439 setDone(Bad);
440 }
441 break;
442 default:
443 assert(!"Unhandled state in switch statement");
444 }
445
446 // move on to the next character
447 if (!done)
448 shift(1);
449#ifndef KJS_PURE_ECMA
450 if (state != Start && state != InSingleLineComment)
451 bol = false;
452#endif
453 }
454
455 // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
456 if ((state == Number || state == Octal || state == Hex) && isIdentStart(current))
457 state = Bad;
458
459 // terminate string
460 buffer8[pos8] = '\0';
461
462#ifdef KJS_DEBUG_LEX
463 fprintf(stderr, "line: %d ", lineNo());
464 fprintf(stderr, "yytext (%x): ", buffer8[0]);
465 fprintf(stderr, "%s ", buffer8);
466#endif
467
468 double dval = 0;
469 if (state == Number) {
470 dval = strtod(buffer8, 0L);
471 } else if (state == Hex) { // scan hex numbers
472 const char *p = buffer8 + 2;
473 while (char c = *p++) {
474 dval *= 16;
475 dval += convertHex(c);
476 }
477 state = Number;
478 } else if (state == Octal) { // scan octal number
479 const char *p = buffer8 + 1;
480 while (char c = *p++) {
481 dval *= 8;
482 dval += c - '0';
483 }
484 state = Number;
485 }
486
487#ifdef KJS_DEBUG_LEX
488 switch (state) {
489 case Eof:
490 printf("(EOF)\n");
491 break;
492 case Other:
493 printf("(Other)\n");
494 break;
495 case Identifier:
496 printf("(Identifier)/(Keyword)\n");
497 break;
498 case String:
499 printf("(String)\n");
500 break;
501 case Number:
502 printf("(Number)\n");
503 break;
504 default:
505 printf("(unknown)");
506 }
507#endif
508
509 if (state != Identifier && eatNextIdentifier)
510 eatNextIdentifier = false;
511
512 restrKeyword = false;
513 delimited = false;
514 kjsyylloc.first_line = yylineno; // ???
515 kjsyylloc.last_line = yylineno;
516
517 switch (state) {
518 case Eof:
519 token = 0;
520 break;
521 case Other:
522 if(token == '}' || token == ';') {
523 delimited = true;
524 }
525 break;
526 case IdentifierOrKeyword:
527 if ((token = Lookup::find(&mainTable, buffer16, pos16)) < 0) {
528 case Identifier:
529 // Lookup for keyword failed, means this is an identifier
530 // Apply anonymous-function hack below (eat the identifier)
531 if (eatNextIdentifier) {
532 eatNextIdentifier = false;
533 token = lex();
534 break;
535 }
536 kjsyylval.ident = makeIdentifier(buffer16, pos16);
537 token = IDENT;
538 break;
539 }
540
541 eatNextIdentifier = false;
542 // Hack for "f = function somename() { ... }", too hard to get into the grammar
543 if (token == FUNCTION && lastToken == '=' )
544 eatNextIdentifier = true;
545
546 if (token == CONTINUE || token == BREAK ||
547 token == RETURN || token == THROW)
548 restrKeyword = true;
549 break;
550 case String:
551 kjsyylval.ustr = makeUString(buffer16, pos16);
552 token = STRING;
553 break;
554 case Number:
555 kjsyylval.dval = dval;
556 token = NUMBER;
557 break;
558 case Bad:
559#ifdef KJS_DEBUG_LEX
560 fprintf(stderr, "yylex: ERROR.\n");
561#endif
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
878// FIXME: this completely ignores its parameters, instead using buffer16 and pos16 - wtf?
879Identifier *Lexer::makeIdentifier(KJS::UChar*, unsigned int)
880{
881 if (numIdentifiers == identifiersCapacity) {
882 identifiersCapacity = (identifiersCapacity == 0) ? initialCapacity : identifiersCapacity *growthFactor;
883 identifiers = (KJS::Identifier **)fastRealloc(identifiers, sizeof(KJS::Identifier *) * identifiersCapacity);
884 }
885
886 KJS::Identifier *identifier = new KJS::Identifier(buffer16, pos16);
887 identifiers[numIdentifiers++] = identifier;
888 return identifier;
889}
890
891// FIXME: this completely ignores its parameters, instead using buffer16 and pos16 - wtf?
892UString *Lexer::makeUString(KJS::UChar*, unsigned int)
893{
894 if (numStrings == stringsCapacity) {
895 stringsCapacity = (stringsCapacity == 0) ? initialCapacity : stringsCapacity *growthFactor;
896 strings = (UString **)fastRealloc(strings, sizeof(UString *) * stringsCapacity);
897 }
898
899 UString *string = new UString(buffer16, pos16);
900 strings[numStrings++] = string;
901 return string;
902}
Note: See TracBrowser for help on using the repository browser.