ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

lex.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.