Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlex.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2008 Jacek Caban for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include <math.h> 00020 #include <limits.h> 00021 00022 #include "jscript.h" 00023 #include "activscp.h" 00024 #include "objsafe.h" 00025 #include "engine.h" 00026 00027 #include "parser.tab.h" 00028 00029 #include "wine/debug.h" 00030 #include "wine/unicode.h" 00031 00032 WINE_DEFAULT_DEBUG_CHANNEL(jscript); 00033 00034 #define LONGLONG_MAX (((LONGLONG)0x7fffffff<<32)|0xffffffff) 00035 00036 static const WCHAR breakW[] = {'b','r','e','a','k',0}; 00037 static const WCHAR caseW[] = {'c','a','s','e',0}; 00038 static const WCHAR catchW[] = {'c','a','t','c','h',0}; 00039 static const WCHAR continueW[] = {'c','o','n','t','i','n','u','e',0}; 00040 static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0}; 00041 static const WCHAR deleteW[] = {'d','e','l','e','t','e',0}; 00042 static const WCHAR doW[] = {'d','o',0}; 00043 static const WCHAR elseW[] = {'e','l','s','e',0}; 00044 static const WCHAR falseW[] = {'f','a','l','s','e',0}; 00045 static const WCHAR finallyW[] = {'f','i','n','a','l','l','y',0}; 00046 static const WCHAR forW[] = {'f','o','r',0}; 00047 static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0}; 00048 static const WCHAR ifW[] = {'i','f',0}; 00049 static const WCHAR inW[] = {'i','n',0}; 00050 static const WCHAR instanceofW[] = {'i','n','s','t','a','n','c','e','o','f',0}; 00051 static const WCHAR newW[] = {'n','e','w',0}; 00052 static const WCHAR nullW[] = {'n','u','l','l',0}; 00053 static const WCHAR returnW[] = {'r','e','t','u','r','n',0}; 00054 static const WCHAR switchW[] = {'s','w','i','t','c','h',0}; 00055 static const WCHAR thisW[] = {'t','h','i','s',0}; 00056 static const WCHAR throwW[] = {'t','h','r','o','w',0}; 00057 static const WCHAR trueW[] = {'t','r','u','e',0}; 00058 static const WCHAR tryW[] = {'t','r','y',0}; 00059 static const WCHAR typeofW[] = {'t','y','p','e','o','f',0}; 00060 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; 00061 static const WCHAR varW[] = {'v','a','r',0}; 00062 static const WCHAR voidW[] = {'v','o','i','d',0}; 00063 static const WCHAR whileW[] = {'w','h','i','l','e',0}; 00064 static const WCHAR withW[] = {'w','i','t','h',0}; 00065 00066 static const struct { 00067 const WCHAR *word; 00068 int token; 00069 } keywords[] = { 00070 {breakW, kBREAK}, 00071 {caseW, kCASE}, 00072 {catchW, kCATCH}, 00073 {continueW, kCONTINUE}, 00074 {defaultW, kDEFAULT}, 00075 {deleteW, kDELETE}, 00076 {doW, kDO}, 00077 {elseW, kELSE}, 00078 {falseW, kFALSE}, 00079 {finallyW, kFINALLY}, 00080 {forW, kFOR}, 00081 {functionW, kFUNCTION}, 00082 {ifW, kIF}, 00083 {inW, kIN}, 00084 {instanceofW, kINSTANCEOF}, 00085 {newW, kNEW}, 00086 {nullW, kNULL}, 00087 {returnW, kRETURN}, 00088 {switchW, kSWITCH}, 00089 {thisW, kTHIS}, 00090 {throwW, kTHROW}, 00091 {trueW, kTRUE}, 00092 {tryW, kTRY}, 00093 {typeofW, kTYPEOF}, 00094 {varW, kVAR}, 00095 {voidW, kVOID}, 00096 {whileW, kWHILE}, 00097 {withW, kWITH} 00098 }; 00099 00100 static int lex_error(parser_ctx_t *ctx, HRESULT hres) 00101 { 00102 ctx->hres = JSCRIPT_ERROR|hres; 00103 ctx->lexer_error = TRUE; 00104 return -1; 00105 } 00106 00107 /* ECMA-262 3rd Edition 7.6 */ 00108 static BOOL is_identifier_char(WCHAR c) 00109 { 00110 return isalnumW(c) || c == '$' || c == '_' || c == '\\'; 00111 } 00112 00113 static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lval) 00114 { 00115 const WCHAR *p1 = ctx->ptr; 00116 const WCHAR *p2 = word; 00117 00118 while(p1 < ctx->end && *p2) { 00119 if(*p1 != *p2) 00120 return *p1 - *p2; 00121 p1++; 00122 p2++; 00123 } 00124 00125 if(*p2 || (p1 < ctx->end && is_identifier_char(*p1))) 00126 return 1; 00127 00128 *lval = ctx->ptr; 00129 ctx->ptr = p1; 00130 return 0; 00131 } 00132 00133 /* ECMA-262 3rd Edition 7.3 */ 00134 static BOOL is_endline(WCHAR c) 00135 { 00136 return c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029; 00137 } 00138 00139 static int hex_to_int(WCHAR c) 00140 { 00141 if('0' <= c && c <= '9') 00142 return c-'0'; 00143 00144 if('a' <= c && c <= 'f') 00145 return c-'a'+10; 00146 00147 if('A' <= c && c <= 'F') 00148 return c-'A'+10; 00149 00150 return -1; 00151 } 00152 00153 static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval) 00154 { 00155 int min = 0, max = sizeof(keywords)/sizeof(keywords[0])-1, r, i; 00156 00157 while(min <= max) { 00158 i = (min+max)/2; 00159 00160 r = check_keyword(ctx, keywords[i].word, lval); 00161 if(!r) 00162 return keywords[i].token; 00163 00164 if(r > 0) 00165 min = i+1; 00166 else 00167 max = i-1; 00168 } 00169 00170 return 0; 00171 } 00172 00173 static void skip_spaces(parser_ctx_t *ctx) 00174 { 00175 while(ctx->ptr < ctx->end && isspaceW(*ctx->ptr)) { 00176 if(is_endline(*ctx->ptr++)) 00177 ctx->nl = TRUE; 00178 } 00179 } 00180 00181 static BOOL skip_html_comment(parser_ctx_t *ctx) 00182 { 00183 const WCHAR html_commentW[] = {'<','!','-','-',0}; 00184 00185 if(!ctx->is_html || ctx->ptr+3 >= ctx->end || 00186 memcmp(ctx->ptr, html_commentW, sizeof(WCHAR)*4)) 00187 return FALSE; 00188 00189 ctx->nl = TRUE; 00190 while(ctx->ptr < ctx->end && !is_endline(*ctx->ptr++)); 00191 00192 return TRUE; 00193 } 00194 00195 static BOOL skip_comment(parser_ctx_t *ctx) 00196 { 00197 if(ctx->ptr+1 >= ctx->end || *ctx->ptr != '/') 00198 return FALSE; 00199 00200 switch(ctx->ptr[1]) { 00201 case '*': 00202 ctx->ptr += 2; 00203 while(ctx->ptr+1 < ctx->end && (ctx->ptr[0] != '*' || ctx->ptr[1] != '/')) 00204 ctx->ptr++; 00205 00206 if(ctx->ptr[0] == '*' && ctx->ptr[1] == '/') { 00207 ctx->ptr += 2; 00208 }else { 00209 WARN("unexpected end of file (missing end of comment)\n"); 00210 ctx->ptr = ctx->end; 00211 } 00212 break; 00213 case '/': 00214 ctx->ptr += 2; 00215 while(ctx->ptr < ctx->end && !is_endline(*ctx->ptr)) 00216 ctx->ptr++; 00217 break; 00218 default: 00219 return FALSE; 00220 } 00221 00222 return TRUE; 00223 } 00224 00225 static BOOL unescape(WCHAR *str) 00226 { 00227 WCHAR *pd, *p, c; 00228 int i; 00229 00230 pd = p = str; 00231 while(*p) { 00232 if(*p != '\\') { 00233 *pd++ = *p++; 00234 continue; 00235 } 00236 00237 p++; 00238 c = 0; 00239 00240 switch(*p) { 00241 case '\'': 00242 case '\"': 00243 case '\\': 00244 c = *p; 00245 break; 00246 case 'b': 00247 c = '\b'; 00248 break; 00249 case 't': 00250 c = '\t'; 00251 break; 00252 case 'n': 00253 c = '\n'; 00254 break; 00255 case 'v': 00256 c = '\v'; 00257 break; 00258 case 'f': 00259 c = '\f'; 00260 break; 00261 case 'r': 00262 c = '\r'; 00263 break; 00264 case 'x': 00265 i = hex_to_int(*++p); 00266 if(i == -1) 00267 return FALSE; 00268 c = i << 4; 00269 00270 i = hex_to_int(*++p); 00271 if(i == -1) 00272 return FALSE; 00273 c += i; 00274 break; 00275 case 'u': 00276 i = hex_to_int(*++p); 00277 if(i == -1) 00278 return FALSE; 00279 c = i << 12; 00280 00281 i = hex_to_int(*++p); 00282 if(i == -1) 00283 return FALSE; 00284 c += i << 8; 00285 00286 i = hex_to_int(*++p); 00287 if(i == -1) 00288 return FALSE; 00289 c += i << 4; 00290 00291 i = hex_to_int(*++p); 00292 if(i == -1) 00293 return FALSE; 00294 c += i; 00295 break; 00296 default: 00297 if(isdigitW(*p)) { 00298 c = *p++ - '0'; 00299 if(isdigitW(*p)) { 00300 c = c*8 + (*p++ - '0'); 00301 if(isdigitW(*p)) 00302 c = c*8 + (*p++ - '0'); 00303 } 00304 p--; 00305 } 00306 else 00307 c = *p; 00308 } 00309 00310 *pd++ = c; 00311 p++; 00312 } 00313 00314 *pd = 0; 00315 return TRUE; 00316 } 00317 00318 static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret) 00319 { 00320 const WCHAR *ptr = ctx->ptr++; 00321 WCHAR *wstr; 00322 int len; 00323 00324 while(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr)) 00325 ctx->ptr++; 00326 00327 len = ctx->ptr-ptr; 00328 00329 *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR)); 00330 memcpy(wstr, ptr, (len+1)*sizeof(WCHAR)); 00331 wstr[len] = 0; 00332 00333 /* FIXME: unescape */ 00334 return tIdentifier; 00335 } 00336 00337 static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret, WCHAR endch) 00338 { 00339 const WCHAR *ptr = ++ctx->ptr; 00340 WCHAR *wstr; 00341 int len; 00342 00343 while(ctx->ptr < ctx->end && *ctx->ptr != endch) { 00344 if(*ctx->ptr++ == '\\') 00345 ctx->ptr++; 00346 } 00347 00348 if(ctx->ptr == ctx->end) 00349 return lex_error(ctx, IDS_UNTERMINATED_STR); 00350 00351 len = ctx->ptr-ptr; 00352 00353 *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR)); 00354 memcpy(wstr, ptr, (len+1)*sizeof(WCHAR)); 00355 wstr[len] = 0; 00356 00357 ctx->ptr++; 00358 00359 if(!unescape(wstr)) { 00360 WARN("unescape failed\n"); 00361 return lex_error(ctx, E_FAIL); 00362 } 00363 00364 return tStringLiteral; 00365 } 00366 00367 static literal_t *alloc_int_literal(parser_ctx_t *ctx, LONG l) 00368 { 00369 literal_t *ret = parser_alloc(ctx, sizeof(literal_t)); 00370 00371 ret->type = LT_INT; 00372 ret->u.lval = l; 00373 00374 return ret; 00375 } 00376 00377 static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **literal) 00378 { 00379 LONGLONG d, hlp; 00380 int exp = 0; 00381 00382 if(ctx->ptr == ctx->end || (!isdigitW(*ctx->ptr) && 00383 *ctx->ptr!='.' && *ctx->ptr!='e' && *ctx->ptr!='E')) { 00384 ERR("Illegal character\n"); 00385 return 0; 00386 } 00387 00388 d = int_part; 00389 while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { 00390 hlp = d*10 + *(ctx->ptr++) - '0'; 00391 if(d>LONGLONG_MAX/10 || hlp<0) { 00392 exp++; 00393 break; 00394 } 00395 else 00396 d = hlp; 00397 } 00398 while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { 00399 exp++; 00400 ctx->ptr++; 00401 } 00402 00403 if(*ctx->ptr == '.') ctx->ptr++; 00404 00405 while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { 00406 hlp = d*10 + *(ctx->ptr++) - '0'; 00407 if(d>LONGLONG_MAX/10 || hlp<0) 00408 break; 00409 00410 d = hlp; 00411 exp--; 00412 } 00413 while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) 00414 ctx->ptr++; 00415 00416 if(ctx->ptr < ctx->end && (*ctx->ptr == 'e' || *ctx->ptr == 'E')) { 00417 int sign = 1, e = 0; 00418 00419 ctx->ptr++; 00420 if(ctx->ptr < ctx->end) { 00421 if(*ctx->ptr == '+') { 00422 ctx->ptr++; 00423 }else if(*ctx->ptr == '-') { 00424 sign = -1; 00425 ctx->ptr++; 00426 }else if(!isdigitW(*ctx->ptr)) { 00427 WARN("Expected exponent part\n"); 00428 return lex_error(ctx, E_FAIL); 00429 } 00430 } 00431 00432 if(ctx->ptr == ctx->end) { 00433 WARN("unexpected end of file\n"); 00434 return lex_error(ctx, E_FAIL); 00435 } 00436 00437 while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { 00438 if(e > INT_MAX/10 || (e = e*10 + *ctx->ptr++ - '0')<0) 00439 e = INT_MAX; 00440 } 00441 e *= sign; 00442 00443 if(exp<0 && e<0 && e+exp>0) exp = INT_MIN; 00444 else if(exp>0 && e>0 && e+exp<0) exp = INT_MAX; 00445 else exp += e; 00446 } 00447 00448 *literal = parser_alloc(ctx, sizeof(literal_t)); 00449 (*literal)->type = LT_DOUBLE; 00450 (*literal)->u.dval = (double)d*pow(10, exp); 00451 00452 return tNumericLiteral; 00453 } 00454 00455 static int parse_numeric_literal(parser_ctx_t *ctx, literal_t **literal) 00456 { 00457 LONG l, d; 00458 00459 l = *ctx->ptr++ - '0'; 00460 if(ctx->ptr == ctx->end) { 00461 *literal = alloc_int_literal(ctx, l); 00462 return tNumericLiteral; 00463 } 00464 00465 if(!l) { 00466 if(*ctx->ptr == 'x' || *ctx->ptr == 'X') { 00467 if(++ctx->ptr == ctx->end) { 00468 ERR("unexpexted end of file\n"); 00469 return 0; 00470 } 00471 00472 while(ctx->ptr < ctx->end && (d = hex_to_int(*ctx->ptr)) != -1) { 00473 l = l*16 + d; 00474 ctx->ptr++; 00475 } 00476 00477 if(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr)) { 00478 WARN("unexpected identifier char\n"); 00479 return lex_error(ctx, E_FAIL); 00480 } 00481 00482 *literal = alloc_int_literal(ctx, l); 00483 return tNumericLiteral; 00484 } 00485 00486 if(isdigitW(*ctx->ptr) || is_identifier_char(*ctx->ptr)) { 00487 WARN("wrong char after zero\n"); 00488 return lex_error(ctx, E_FAIL); 00489 } 00490 00491 *literal = alloc_int_literal(ctx, 0); 00492 } 00493 00494 while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) 00495 { 00496 d = l*10 + *(ctx->ptr)-'0'; 00497 00498 /* Check for integer overflow */ 00499 if (l > INT_MAX/10 || d < 0) 00500 return parse_double_literal(ctx, l, literal); 00501 00502 l = d; 00503 ctx->ptr++; 00504 } 00505 00506 if(ctx->ptr < ctx->end) { 00507 if(*ctx->ptr == '.' || *ctx->ptr == 'e' || *ctx->ptr == 'E') 00508 return parse_double_literal(ctx, l, literal); 00509 00510 if(is_identifier_char(*ctx->ptr)) { 00511 WARN("unexpected identifier char\n"); 00512 return lex_error(ctx, E_FAIL); 00513 } 00514 } 00515 00516 *literal = alloc_int_literal(ctx, l); 00517 return tNumericLiteral; 00518 } 00519 00520 int parser_lex(void *lval, parser_ctx_t *ctx) 00521 { 00522 int ret; 00523 00524 ctx->nl = ctx->ptr == ctx->begin; 00525 00526 do { 00527 skip_spaces(ctx); 00528 if(ctx->ptr == ctx->end) 00529 return 0; 00530 }while(skip_comment(ctx) || skip_html_comment(ctx)); 00531 00532 if(isalphaW(*ctx->ptr)) { 00533 ret = check_keywords(ctx, lval); 00534 if(ret) 00535 return ret; 00536 00537 return parse_identifier(ctx, lval); 00538 } 00539 00540 if(isdigitW(*ctx->ptr)) 00541 return parse_numeric_literal(ctx, lval); 00542 00543 switch(*ctx->ptr) { 00544 case '{': 00545 case '(': 00546 case ')': 00547 case '[': 00548 case ']': 00549 case ';': 00550 case ',': 00551 case '~': 00552 case '?': 00553 case ':': 00554 return *ctx->ptr++; 00555 00556 case '}': 00557 *(const WCHAR**)lval = ctx->ptr++; 00558 return '}'; 00559 00560 case '.': 00561 if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) 00562 return parse_double_literal(ctx, 0, lval); 00563 return '.'; 00564 00565 case '<': 00566 if(++ctx->ptr == ctx->end) { 00567 *(int*)lval = EXPR_LESS; 00568 return tRelOper; 00569 } 00570 00571 switch(*ctx->ptr) { 00572 case '=': /* <= */ 00573 ctx->ptr++; 00574 *(int*)lval = EXPR_LESSEQ; 00575 return tRelOper; 00576 case '<': /* << */ 00577 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* <<= */ 00578 ctx->ptr++; 00579 *(int*)lval = EXPR_ASSIGNLSHIFT; 00580 return tAssignOper; 00581 } 00582 *(int*)lval = EXPR_LSHIFT; 00583 return tShiftOper; 00584 default: /* < */ 00585 *(int*)lval = EXPR_LESS; 00586 return tRelOper; 00587 } 00588 00589 case '>': 00590 if(++ctx->ptr == ctx->end) { /* > */ 00591 *(int*)lval = EXPR_GREATER; 00592 return tRelOper; 00593 } 00594 00595 switch(*ctx->ptr) { 00596 case '=': /* >= */ 00597 ctx->ptr++; 00598 *(int*)lval = EXPR_GREATEREQ; 00599 return tRelOper; 00600 case '>': /* >> */ 00601 if(++ctx->ptr < ctx->end) { 00602 if(*ctx->ptr == '=') { /* >>= */ 00603 ctx->ptr++; 00604 *(int*)lval = EXPR_ASSIGNRSHIFT; 00605 return tAssignOper; 00606 } 00607 if(*ctx->ptr == '>') { /* >>> */ 00608 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* >>>= */ 00609 ctx->ptr++; 00610 *(int*)lval = EXPR_ASSIGNRRSHIFT; 00611 return tAssignOper; 00612 } 00613 *(int*)lval = EXPR_RRSHIFT; 00614 return tRelOper; 00615 } 00616 } 00617 *(int*)lval = EXPR_RSHIFT; 00618 return tShiftOper; 00619 default: 00620 *(int*)lval = EXPR_GREATER; 00621 return tRelOper; 00622 } 00623 00624 case '+': 00625 ctx->ptr++; 00626 if(ctx->ptr < ctx->end) { 00627 switch(*ctx->ptr) { 00628 case '+': /* ++ */ 00629 ctx->ptr++; 00630 return tINC; 00631 case '=': /* += */ 00632 ctx->ptr++; 00633 *(int*)lval = EXPR_ASSIGNADD; 00634 return tAssignOper; 00635 } 00636 } 00637 return '+'; 00638 00639 case '-': 00640 ctx->ptr++; 00641 if(ctx->ptr < ctx->end) { 00642 switch(*ctx->ptr) { 00643 case '-': /* -- or --> */ 00644 ctx->ptr++; 00645 if(ctx->is_html && ctx->nl && ctx->ptr < ctx->end && *ctx->ptr == '>') { 00646 ctx->ptr++; 00647 return tHTMLCOMMENT; 00648 } 00649 return tDEC; 00650 case '=': /* -= */ 00651 ctx->ptr++; 00652 *(int*)lval = EXPR_ASSIGNSUB; 00653 return tAssignOper; 00654 } 00655 } 00656 return '-'; 00657 00658 case '*': 00659 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* *= */ 00660 ctx->ptr++; 00661 *(int*)lval = EXPR_ASSIGNMUL; 00662 return tAssignOper; 00663 } 00664 return '*'; 00665 00666 case '%': 00667 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* %= */ 00668 ctx->ptr++; 00669 *(int*)lval = EXPR_ASSIGNMOD; 00670 return tAssignOper; 00671 } 00672 return '%'; 00673 00674 case '&': 00675 if(++ctx->ptr < ctx->end) { 00676 switch(*ctx->ptr) { 00677 case '=': /* &= */ 00678 ctx->ptr++; 00679 *(int*)lval = EXPR_ASSIGNAND; 00680 return tAssignOper; 00681 case '&': /* && */ 00682 ctx->ptr++; 00683 return tANDAND; 00684 } 00685 } 00686 return '&'; 00687 00688 case '|': 00689 if(++ctx->ptr < ctx->end) { 00690 switch(*ctx->ptr) { 00691 case '=': /* |= */ 00692 ctx->ptr++; 00693 *(int*)lval = EXPR_ASSIGNOR; 00694 return tAssignOper; 00695 case '|': /* || */ 00696 ctx->ptr++; 00697 return tOROR; 00698 } 00699 } 00700 return '|'; 00701 00702 case '^': 00703 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* ^= */ 00704 ctx->ptr++; 00705 *(int*)lval = EXPR_ASSIGNXOR; 00706 return tAssignOper; 00707 } 00708 return '^'; 00709 00710 case '!': 00711 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* != */ 00712 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* !== */ 00713 ctx->ptr++; 00714 *(int*)lval = EXPR_NOTEQEQ; 00715 return tEqOper; 00716 } 00717 *(int*)lval = EXPR_NOTEQ; 00718 return tEqOper; 00719 } 00720 return '!'; 00721 00722 case '=': 00723 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* == */ 00724 if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* === */ 00725 ctx->ptr++; 00726 *(int*)lval = EXPR_EQEQ; 00727 return tEqOper; 00728 } 00729 *(int*)lval = EXPR_EQ; 00730 return tEqOper; 00731 } 00732 return '='; 00733 00734 case '/': 00735 if(++ctx->ptr < ctx->end) { 00736 if(*ctx->ptr == '=') { /* /= */ 00737 ctx->ptr++; 00738 *(int*)lval = EXPR_ASSIGNDIV; 00739 return kDIVEQ; 00740 } 00741 } 00742 return '/'; 00743 00744 case '\"': 00745 case '\'': 00746 return parse_string_literal(ctx, lval, *ctx->ptr); 00747 00748 case '_': 00749 case '$': 00750 return parse_identifier(ctx, lval); 00751 } 00752 00753 WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr); 00754 return 0; 00755 } 00756 00757 literal_t *parse_regexp(parser_ctx_t *ctx) 00758 { 00759 const WCHAR *re, *flags_ptr; 00760 DWORD re_len, flags; 00761 literal_t *ret; 00762 HRESULT hres; 00763 00764 TRACE("\n"); 00765 00766 while(*ctx->ptr != '/') 00767 ctx->ptr--; 00768 00769 re = ++ctx->ptr; 00770 while(ctx->ptr < ctx->end && *ctx->ptr != '/') { 00771 if(*ctx->ptr++ == '\\' && ctx->ptr < ctx->end) 00772 ctx->ptr++; 00773 } 00774 00775 if(ctx->ptr == ctx->end) { 00776 WARN("unexpected end of file\n"); 00777 return NULL; 00778 } 00779 00780 re_len = ctx->ptr-re; 00781 00782 flags_ptr = ++ctx->ptr; 00783 while(ctx->ptr < ctx->end && isalnumW(*ctx->ptr)) 00784 ctx->ptr++; 00785 00786 hres = parse_regexp_flags(flags_ptr, ctx->ptr-flags_ptr, &flags); 00787 if(FAILED(hres)) 00788 return NULL; 00789 00790 ret = parser_alloc(ctx, sizeof(literal_t)); 00791 ret->type = LT_REGEXP; 00792 ret->u.regexp.str = re; 00793 ret->u.regexp.str_len = re_len; 00794 ret->u.regexp.flags = flags; 00795 return ret; 00796 } Generated on Sat May 26 2012 04:22:53 for ReactOS by
1.7.6.1
|