~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/jscript/lex.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Copyright 2008 Jacek Caban for CodeWeavers
  3  *
  4  * This library is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2.1 of the License, or (at your option) any later version.
  8  *
  9  * This library is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with this library; if not, write to the Free Software
 16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 17  */
 18 
 19 #include <math.h>
 20 #include <limits.h>
 21 
 22 #include "jscript.h"
 23 #include "activscp.h"
 24 #include "objsafe.h"
 25 #include "engine.h"
 26 
 27 #include "parser.tab.h"
 28 
 29 #include "wine/debug.h"
 30 #include "wine/unicode.h"
 31 
 32 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
 33 
 34 #define LONGLONG_MAX (((LONGLONG)0x7fffffff<<32)|0xffffffff)
 35 
 36 static const WCHAR breakW[] = {'b','r','e','a','k',0};
 37 static const WCHAR caseW[] = {'c','a','s','e',0};
 38 static const WCHAR catchW[] = {'c','a','t','c','h',0};
 39 static const WCHAR continueW[] = {'c','o','n','t','i','n','u','e',0};
 40 static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0};
 41 static const WCHAR deleteW[] = {'d','e','l','e','t','e',0};
 42 static const WCHAR doW[] = {'d','o',0};
 43 static const WCHAR elseW[] = {'e','l','s','e',0};
 44 static const WCHAR falseW[] = {'f','a','l','s','e',0};
 45 static const WCHAR finallyW[] = {'f','i','n','a','l','l','y',0};
 46 static const WCHAR forW[] = {'f','o','r',0};
 47 static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0};
 48 static const WCHAR ifW[] = {'i','f',0};
 49 static const WCHAR inW[] = {'i','n',0};
 50 static const WCHAR instanceofW[] = {'i','n','s','t','a','n','c','e','o','f',0};
 51 static const WCHAR newW[] = {'n','e','w',0};
 52 static const WCHAR nullW[] = {'n','u','l','l',0};
 53 static const WCHAR returnW[] = {'r','e','t','u','r','n',0};
 54 static const WCHAR switchW[] = {'s','w','i','t','c','h',0};
 55 static const WCHAR thisW[] = {'t','h','i','s',0};
 56 static const WCHAR throwW[] = {'t','h','r','o','w',0};
 57 static const WCHAR trueW[] = {'t','r','u','e',0};
 58 static const WCHAR tryW[] = {'t','r','y',0};
 59 static const WCHAR typeofW[] = {'t','y','p','e','o','f',0};
 60 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
 61 static const WCHAR varW[] = {'v','a','r',0};
 62 static const WCHAR voidW[] = {'v','o','i','d',0};
 63 static const WCHAR whileW[] = {'w','h','i','l','e',0};
 64 static const WCHAR withW[] = {'w','i','t','h',0};
 65 
 66 static const struct {
 67     const WCHAR *word;
 68     int token;
 69 } keywords[] = {
 70     {breakW,       kBREAK},
 71     {caseW,        kCASE},
 72     {catchW,       kCATCH},
 73     {continueW,    kCONTINUE},
 74     {defaultW,     kDEFAULT},
 75     {deleteW,      kDELETE},
 76     {doW,          kDO},
 77     {elseW,        kELSE},
 78     {falseW,       kFALSE},
 79     {finallyW,     kFINALLY},
 80     {forW,         kFOR},
 81     {functionW,    kFUNCTION},
 82     {ifW,          kIF},
 83     {inW,          kIN},
 84     {instanceofW,  kINSTANCEOF},
 85     {newW,         kNEW},
 86     {nullW,        kNULL},
 87     {returnW,      kRETURN},
 88     {switchW,      kSWITCH},
 89     {thisW,        kTHIS},
 90     {throwW,       kTHROW},
 91     {trueW,        kTRUE},
 92     {tryW,         kTRY},
 93     {typeofW,      kTYPEOF},
 94     {undefinedW,   kUNDEFINED},
 95     {varW,         kVAR},
 96     {voidW,        kVOID},
 97     {whileW,       kWHILE},
 98     {withW,        kWITH}
 99 };
100 
101 static int lex_error(parser_ctx_t *ctx, HRESULT hres)
102 {
103     ctx->hres = JSCRIPT_ERROR|hres;
104     ctx->lexer_error = TRUE;
105     return -1;
106 }
107 
108 /* ECMA-262 3rd Edition    7.6 */
109 static BOOL is_identifier_char(WCHAR c)
110 {
111     return isalnumW(c) || c == '$' || c == '_' || c == '\\';
112 }
113 
114 static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lval)
115 {
116     const WCHAR *p1 = ctx->ptr;
117     const WCHAR *p2 = word;
118 
119     while(p1 < ctx->end && *p2) {
120         if(*p1 != *p2)
121             return *p1 - *p2;
122         p1++;
123         p2++;
124     }
125 
126     if(*p2 || (p1 < ctx->end && is_identifier_char(*p1)))
127         return 1;
128 
129     *lval = ctx->ptr;
130     ctx->ptr = p1;
131     return 0;
132 }
133 
134 /* ECMA-262 3rd Edition    7.3 */
135 static BOOL is_endline(WCHAR c)
136 {
137     return c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029;
138 }
139 
140 static int hex_to_int(WCHAR c)
141 {
142     if('' <= c && c <= '9')
143         return c-'';
144 
145     if('a' <= c && c <= 'f')
146         return c-'a'+10;
147 
148     if('A' <= c && c <= 'F')
149         return c-'A'+10;
150 
151     return -1;
152 }
153 
154 static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval)
155 {
156     int min = 0, max = sizeof(keywords)/sizeof(keywords[0])-1, r, i;
157 
158     while(min <= max) {
159         i = (min+max)/2;
160 
161         r = check_keyword(ctx, keywords[i].word, lval);
162         if(!r)
163             return keywords[i].token;
164 
165         if(r > 0)
166             min = i+1;
167         else
168             max = i-1;
169     }
170 
171     return 0;
172 }
173 
174 static void skip_spaces(parser_ctx_t *ctx)
175 {
176     while(ctx->ptr < ctx->end && isspaceW(*ctx->ptr)) {
177         if(is_endline(*ctx->ptr++))
178             ctx->nl = TRUE;
179     }
180 }
181 
182 static BOOL skip_html_comment(parser_ctx_t *ctx)
183 {
184     const WCHAR html_commentW[] = {'<','!','-','-',0};
185 
186     if(!ctx->is_html || ctx->ptr+3 >= ctx->end ||
187         memcmp(ctx->ptr, html_commentW, sizeof(WCHAR)*4))
188         return FALSE;
189 
190     ctx->nl = TRUE;
191     while(ctx->ptr < ctx->end && !is_endline(*ctx->ptr++));
192 
193     return TRUE;
194 }
195 
196 static BOOL skip_comment(parser_ctx_t *ctx)
197 {
198     if(ctx->ptr+1 >= ctx->end || *ctx->ptr != '/')
199         return FALSE;
200 
201     switch(ctx->ptr[1]) {
202     case '*':
203         ctx->ptr += 2;
204         while(ctx->ptr+1 < ctx->end && (ctx->ptr[0] != '*' || ctx->ptr[1] != '/'))
205             ctx->ptr++;
206 
207         if(ctx->ptr[0] == '*' && ctx->ptr[1] == '/') {
208             ctx->ptr += 2;
209         }else {
210             WARN("unexpected end of file (missing end of comment)\n");
211             ctx->ptr = ctx->end;
212         }
213         break;
214     case '/':
215         ctx->ptr += 2;
216         while(ctx->ptr < ctx->end && !is_endline(*ctx->ptr))
217             ctx->ptr++;
218         break;
219     default:
220         return FALSE;
221     }
222 
223     return TRUE;
224 }
225 
226 static BOOL unescape(WCHAR *str)
227 {
228     WCHAR *pd, *p, c;
229     int i;
230 
231     pd = p = str;
232     while(*p) {
233         if(*p != '\\') {
234             *pd++ = *p++;
235             continue;
236         }
237 
238         p++;
239         c = 0;
240 
241         switch(*p) {
242         case '\'':
243         case '\"':
244         case '\\':
245             c = *p;
246             break;
247         case 'b':
248             c = '\b';
249             break;
250         case 't':
251             c = '\t';
252             break;
253         case 'n':
254             c = '\n';
255             break;
256         case 'v':
257             c = '\v';
258             break;
259         case 'f':
260             c = '\f';
261             break;
262         case 'r':
263             c = '\r';
264             break;
265         case 'x':
266             i = hex_to_int(*++p);
267             if(i == -1)
268                 return FALSE;
269             c = i << 4;
270 
271             i = hex_to_int(*++p);
272             if(i == -1)
273                 return FALSE;
274             c += i;
275             break;
276         case 'u':
277             i = hex_to_int(*++p);
278             if(i == -1)
279                 return FALSE;
280             c = i << 12;
281 
282             i = hex_to_int(*++p);
283             if(i == -1)
284                 return FALSE;
285             c += i << 8;
286 
287             i = hex_to_int(*++p);
288             if(i == -1)
289                 return FALSE;
290             c += i << 4;
291 
292             i = hex_to_int(*++p);
293             if(i == -1)
294                 return FALSE;
295             c += i;
296             break;
297         default:
298             if(isdigitW(*p)) {
299                 c = *p++ - '';
300                 if(isdigitW(*p)) {
301                     c = c*8 + (*p++ - '');
302                     if(isdigitW(*p))
303                         c = c*8 + (*p++ - '');
304                 }
305                 p--;
306             }
307             else
308                 c = *p;
309         }
310 
311         *pd++ = c;
312         p++;
313     }
314 
315     *pd = 0;
316     return TRUE;
317 }
318 
319 static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret)
320 {
321     const WCHAR *ptr = ctx->ptr++;
322     WCHAR *wstr;
323     int len;
324 
325     while(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr))
326         ctx->ptr++;
327 
328     len = ctx->ptr-ptr;
329 
330     *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR));
331     memcpy(wstr, ptr, (len+1)*sizeof(WCHAR));
332     wstr[len] = 0;
333 
334     /* FIXME: unescape */
335     return tIdentifier;
336 }
337 
338 static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret, WCHAR endch)
339 {
340     const WCHAR *ptr = ++ctx->ptr;
341     WCHAR *wstr;
342     int len;
343 
344     while(ctx->ptr < ctx->end && *ctx->ptr != endch) {
345         if(*ctx->ptr++ == '\\')
346             ctx->ptr++;
347     }
348 
349     if(ctx->ptr == ctx->end)
350         return lex_error(ctx, IDS_UNTERMINATED_STR);
351 
352     len = ctx->ptr-ptr;
353 
354     *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR));
355     memcpy(wstr, ptr, (len+1)*sizeof(WCHAR));
356     wstr[len] = 0;
357 
358     ctx->ptr++;
359 
360     if(!unescape(wstr)) {
361         WARN("unescape failed\n");
362         return lex_error(ctx, E_FAIL);
363     }
364 
365     return tStringLiteral;
366 }
367 
368 static literal_t *alloc_int_literal(parser_ctx_t *ctx, LONG l)
369 {
370     literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
371 
372     ret->type = LT_INT;
373     ret->u.lval = l;
374 
375     return ret;
376 }
377 
378 static int parse_double_literal(parser_ctx_t *ctx, LONG int_part, literal_t **literal)
379 {
380     LONGLONG d, hlp;
381     int exp = 0;
382 
383     if(ctx->ptr == ctx->end || (!isdigitW(*ctx->ptr) &&
384         *ctx->ptr!='.' && *ctx->ptr!='e' && *ctx->ptr!='E')) {
385         ERR("Illegal character\n");
386         return 0;
387     }
388 
389     d = int_part;
390     while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
391         hlp = d*10 + *(ctx->ptr++) - '';
392         if(d>LONGLONG_MAX/10 || hlp<0) {
393             exp++;
394             break;
395         }
396         else
397             d = hlp;
398     }
399     while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
400         exp++;
401         ctx->ptr++;
402     }
403 
404     if(*ctx->ptr == '.') ctx->ptr++;
405 
406     while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
407         hlp = d*10 + *(ctx->ptr++) - '';
408         if(d>LONGLONG_MAX/10 || hlp<0)
409             break;
410 
411         d = hlp;
412         exp--;
413     }
414     while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
415         ctx->ptr++;
416 
417     if(ctx->ptr < ctx->end && (*ctx->ptr == 'e' || *ctx->ptr == 'E')) {
418         int sign = 1, e = 0;
419 
420         ctx->ptr++;
421         if(ctx->ptr < ctx->end) {
422             if(*ctx->ptr == '+') {
423                 ctx->ptr++;
424             }else if(*ctx->ptr == '-') {
425                 sign = -1;
426                 ctx->ptr++;
427             }else if(!isdigitW(*ctx->ptr)) {
428                 WARN("Expected exponent part\n");
429                 return lex_error(ctx, E_FAIL);
430             }
431         }
432 
433         if(ctx->ptr == ctx->end) {
434             WARN("unexpected end of file\n");
435             return lex_error(ctx, E_FAIL);
436         }
437 
438         while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) {
439             if(e > INT_MAX/10 || (e = e*10 + *ctx->ptr++ - '')<0)
440                 e = INT_MAX;
441         }
442         e *= sign;
443 
444         if(exp<0 && e<0 && e+exp>0) exp = INT_MIN;
445         else if(exp>0 && e>0 && e+exp<0) exp = INT_MAX;
446         else exp += e;
447     }
448 
449     *literal = parser_alloc(ctx, sizeof(literal_t));
450     (*literal)->type = LT_DOUBLE;
451     (*literal)->u.dval = (double)d*pow(10, exp);
452 
453     return tNumericLiteral;
454 }
455 
456 static int parse_numeric_literal(parser_ctx_t *ctx, literal_t **literal)
457 {
458     LONG l, d;
459 
460     l = *ctx->ptr++ - '';
461     if(ctx->ptr == ctx->end) {
462         *literal = alloc_int_literal(ctx, l);
463         return tNumericLiteral;
464     }
465 
466     if(!l) {
467         if(*ctx->ptr == 'x' || *ctx->ptr == 'X') {
468             if(++ctx->ptr == ctx->end) {
469                 ERR("unexpexted end of file\n");
470                 return 0;
471             }
472 
473             while(ctx->ptr < ctx->end && (d = hex_to_int(*ctx->ptr)) != -1) {
474                 l = l*16 + d;
475                 ctx->ptr++;
476             }
477 
478             if(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr)) {
479                 WARN("unexpected identifier char\n");
480                 return lex_error(ctx, E_FAIL);
481             }
482 
483             *literal = alloc_int_literal(ctx, l);
484             return tNumericLiteral;
485         }
486 
487         if(isdigitW(*ctx->ptr) || is_identifier_char(*ctx->ptr)) {
488             WARN("wrong char after zero\n");
489             return lex_error(ctx, E_FAIL);
490         }
491 
492         *literal = alloc_int_literal(ctx, 0);
493     }
494 
495     while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
496     {
497         d = l*10 + *(ctx->ptr)-'';
498 
499         /* Check for integer overflow */
500         if (l > INT_MAX/10 || d < 0)
501             return parse_double_literal(ctx, l, literal);
502 
503         l = d;
504         ctx->ptr++;
505     }
506 
507     if(ctx->ptr < ctx->end) {
508         if(*ctx->ptr == '.' || *ctx->ptr == 'e' || *ctx->ptr == 'E')
509             return parse_double_literal(ctx, l, literal);
510 
511         if(is_identifier_char(*ctx->ptr)) {
512             WARN("unexpected identifier char\n");
513             return lex_error(ctx, E_FAIL);
514         }
515     }
516 
517     *literal = alloc_int_literal(ctx, l);
518     return tNumericLiteral;
519 }
520 
521 int parser_lex(void *lval, parser_ctx_t *ctx)
522 {
523     int ret;
524 
525     ctx->nl = ctx->ptr == ctx->begin;
526 
527     do {
528         skip_spaces(ctx);
529         if(ctx->ptr == ctx->end)
530             return 0;
531     }while(skip_comment(ctx) || skip_html_comment(ctx));
532 
533     if(isalphaW(*ctx->ptr)) {
534         ret = check_keywords(ctx, lval);
535         if(ret)
536             return ret;
537 
538         return parse_identifier(ctx, lval);
539     }
540 
541     if(isdigitW(*ctx->ptr))
542         return parse_numeric_literal(ctx, lval);
543 
544     switch(*ctx->ptr) {
545     case '{':
546     case '(':
547     case ')':
548     case '[':
549     case ']':
550     case ';':
551     case ',':
552     case '~':
553     case '?':
554     case ':':
555         return *ctx->ptr++;
556 
557     case '}':
558         *(const WCHAR**)lval = ctx->ptr++;
559         return '}';
560 
561     case '.':
562         if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr))
563             return parse_double_literal(ctx, 0, lval);
564         return '.';
565 
566     case '<':
567         if(++ctx->ptr == ctx->end) {
568             *(int*)lval = EXPR_LESS;
569             return tRelOper;
570         }
571 
572         switch(*ctx->ptr) {
573         case '=':  /* <= */
574             ctx->ptr++;
575             *(int*)lval = EXPR_LESSEQ;
576             return tRelOper;
577         case '<':  /* << */
578             if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* <<= */
579                 ctx->ptr++;
580                 *(int*)lval = EXPR_ASSIGNLSHIFT;
581                 return tAssignOper;
582             }
583             *(int*)lval = EXPR_LSHIFT;
584             return tShiftOper;
585         default: /* < */
586             *(int*)lval = EXPR_LESS;
587             return tRelOper;
588         }
589 
590     case '>':
591         if(++ctx->ptr == ctx->end) { /* > */
592             *(int*)lval = EXPR_GREATER;
593             return tRelOper;
594         }
595 
596         switch(*ctx->ptr) {
597         case '=':  /* >= */
598             ctx->ptr++;
599             *(int*)lval = EXPR_GREATEREQ;
600             return tRelOper;
601         case '>':  /* >> */
602             if(++ctx->ptr < ctx->end) {
603                 if(*ctx->ptr == '=') {  /* >>= */
604                     ctx->ptr++;
605                     *(int*)lval = EXPR_ASSIGNRSHIFT;
606                     return tAssignOper;
607                 }
608                 if(*ctx->ptr == '>') {  /* >>> */
609                     if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* >>>= */
610                         ctx->ptr++;
611                         *(int*)lval = EXPR_ASSIGNRRSHIFT;
612                         return tAssignOper;
613                     }
614                     *(int*)lval = EXPR_RRSHIFT;
615                     return tRelOper;
616                 }
617             }
618             *(int*)lval = EXPR_RSHIFT;
619             return tShiftOper;
620         default:
621             *(int*)lval = EXPR_GREATER;
622             return tRelOper;
623         }
624 
625     case '+':
626         ctx->ptr++;
627         if(ctx->ptr < ctx->end) {
628             switch(*ctx->ptr) {
629             case '+':  /* ++ */
630                 ctx->ptr++;
631                 return tINC;
632             case '=':  /* += */
633                 ctx->ptr++;
634                 *(int*)lval = EXPR_ASSIGNADD;
635                 return tAssignOper;
636             }
637         }
638         return '+';
639 
640     case '-':
641         ctx->ptr++;
642         if(ctx->ptr < ctx->end) {
643             switch(*ctx->ptr) {
644             case '-':  /* -- or --> */
645                 ctx->ptr++;
646                 if(ctx->is_html && ctx->nl && ctx->ptr < ctx->end && *ctx->ptr == '>') {
647                     ctx->ptr++;
648                     return tHTMLCOMMENT;
649                 }
650                 return tDEC;
651             case '=':  /* -= */
652                 ctx->ptr++;
653                 *(int*)lval = EXPR_ASSIGNSUB;
654                 return tAssignOper;
655             }
656         }
657         return '-';
658 
659     case '*':
660         if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* *= */
661             ctx->ptr++;
662             *(int*)lval = EXPR_ASSIGNMUL;
663             return tAssignOper;
664         }
665         return '*';
666 
667     case '%':
668         if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* %= */
669             ctx->ptr++;
670             *(int*)lval = EXPR_ASSIGNMOD;
671             return tAssignOper;
672         }
673         return '%';
674 
675     case '&':
676         if(++ctx->ptr < ctx->end) {
677             switch(*ctx->ptr) {
678             case '=':  /* &= */
679                 ctx->ptr++;
680                 *(int*)lval = EXPR_ASSIGNAND;
681                 return tAssignOper;
682             case '&':  /* && */
683                 ctx->ptr++;
684                 return tANDAND;
685             }
686         }
687         return '&';
688 
689     case '|':
690         if(++ctx->ptr < ctx->end) {
691             switch(*ctx->ptr) {
692             case '=':  /* |= */
693                 ctx->ptr++;
694                 *(int*)lval = EXPR_ASSIGNOR;
695                 return tAssignOper;
696             case '|':  /* || */
697                 ctx->ptr++;
698                 return tOROR;
699             }
700         }
701         return '|';
702 
703     case '^':
704         if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* ^= */
705             ctx->ptr++;
706             *(int*)lval = EXPR_ASSIGNXOR;
707             return tAssignOper;
708         }
709         return '^';
710 
711     case '!':
712         if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* != */
713             if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* !== */
714                 ctx->ptr++;
715                 *(int*)lval = EXPR_NOTEQEQ;
716                 return tEqOper;
717             }
718             *(int*)lval = EXPR_NOTEQ;
719             return tEqOper;
720         }
721         return '!';
722 
723     case '=':
724         if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* == */
725             if(++ctx->ptr < ctx->end && *ctx->ptr == '=') {  /* === */
726                 ctx->ptr++;
727                 *(int*)lval = EXPR_EQEQ;
728                 return tEqOper;
729             }
730             *(int*)lval = EXPR_EQ;
731             return tEqOper;
732         }
733         return '=';
734 
735     case '/':
736         if(++ctx->ptr < ctx->end) {
737             if(*ctx->ptr == '=') {  /* /= */
738                 ctx->ptr++;
739                 *(int*)lval = EXPR_ASSIGNDIV;
740                 return kDIVEQ;
741             }
742         }
743         return '/';
744 
745     case '\"':
746     case '\'':
747         return parse_string_literal(ctx, lval, *ctx->ptr);
748 
749     case '_':
750     case '$':
751         return parse_identifier(ctx, lval);
752     }
753 
754     WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr);
755     return 0;
756 }
757 
758 literal_t *parse_regexp(parser_ctx_t *ctx)
759 {
760     const WCHAR *re, *flags_ptr;
761     DWORD re_len, flags;
762     literal_t *ret;
763     HRESULT hres;
764 
765     TRACE("\n");
766 
767     while(*ctx->ptr != '/')
768         ctx->ptr--;
769 
770     re = ++ctx->ptr;
771     while(ctx->ptr < ctx->end && *ctx->ptr != '/') {
772         if(*ctx->ptr++ == '\\' && ctx->ptr < ctx->end)
773             ctx->ptr++;
774     }
775 
776     if(ctx->ptr == ctx->end) {
777         WARN("unexpected end of file\n");
778         return NULL;
779     }
780 
781     re_len = ctx->ptr-re;
782 
783     flags_ptr = ++ctx->ptr;
784     while(ctx->ptr < ctx->end && isalnumW(*ctx->ptr))
785         ctx->ptr++;
786 
787     hres = parse_regexp_flags(flags_ptr, ctx->ptr-flags_ptr, &flags);
788     if(FAILED(hres))
789         return NULL;
790 
791     ret = parser_alloc(ctx, sizeof(literal_t));
792     ret->type = LT_REGEXP;
793     ret->u.regexp.str = re;
794     ret->u.regexp.str_len = re_len;
795     ret->u.regexp.flags = flags;
796     return ret;
797 }
798 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.