static int next_token(parser_ctx_t *ctx, void *lval) { do { skip_spaces(ctx); if(ctx->ptr == ctx->end) return tEOF; }while(skip_comment(ctx) || skip_html_comment(ctx)); if(isalphaW(*ctx->ptr)) { int ret = check_keywords(ctx, lval); if(ret) return ret; return parse_identifier(ctx, lval); } if(isdigitW(*ctx->ptr)) return parse_numeric_literal(ctx, lval); switch(*ctx->ptr) { case '{': case '(': case ')': case '[': case ']': case ';': case ',': case '~': case '?': case ':': return *ctx->ptr++; case '}': *(const WCHAR**)lval = ctx->ptr++; return '}'; case '.': if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) return parse_double_literal(ctx, 0, lval); return '.'; case '<': if(++ctx->ptr == ctx->end) { *(int*)lval = EXPR_LESS; return tRelOper; } switch(*ctx->ptr) { case '=': /* <= */ ctx->ptr++; *(int*)lval = EXPR_LESSEQ; return tRelOper; case '<': /* << */ if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* <<= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNLSHIFT; return tAssignOper; } *(int*)lval = EXPR_LSHIFT; return tShiftOper; default: /* < */ *(int*)lval = EXPR_LESS; return tRelOper; } case '>': if(++ctx->ptr == ctx->end) { /* > */ *(int*)lval = EXPR_GREATER; return tRelOper; } switch(*ctx->ptr) { case '=': /* >= */ ctx->ptr++; *(int*)lval = EXPR_GREATEREQ; return tRelOper; case '>': /* >> */ if(++ctx->ptr < ctx->end) { if(*ctx->ptr == '=') { /* >>= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNRSHIFT; return tAssignOper; } if(*ctx->ptr == '>') { /* >>> */ if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* >>>= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNRRSHIFT; return tAssignOper; } *(int*)lval = EXPR_RRSHIFT; return tRelOper; } } *(int*)lval = EXPR_RSHIFT; return tShiftOper; default: *(int*)lval = EXPR_GREATER; return tRelOper; } case '+': ctx->ptr++; if(ctx->ptr < ctx->end) { switch(*ctx->ptr) { case '+': /* ++ */ ctx->ptr++; return tINC; case '=': /* += */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNADD; return tAssignOper; } } return '+'; case '-': ctx->ptr++; if(ctx->ptr < ctx->end) { switch(*ctx->ptr) { case '-': /* -- or --> */ ctx->ptr++; if(ctx->is_html && ctx->nl && ctx->ptr < ctx->end && *ctx->ptr == '>') { ctx->ptr++; return tHTMLCOMMENT; } return tDEC; case '=': /* -= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNSUB; return tAssignOper; } } return '-'; case '*': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* *= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNMUL; return tAssignOper; } return '*'; case '%': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* %= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNMOD; return tAssignOper; } return '%'; case '&': if(++ctx->ptr < ctx->end) { switch(*ctx->ptr) { case '=': /* &= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNAND; return tAssignOper; case '&': /* && */ ctx->ptr++; return tANDAND; } } return '&'; case '|': if(++ctx->ptr < ctx->end) { switch(*ctx->ptr) { case '=': /* |= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNOR; return tAssignOper; case '|': /* || */ ctx->ptr++; return tOROR; } } return '|'; case '^': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* ^= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNXOR; return tAssignOper; } return '^'; case '!': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* != */ if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* !== */ ctx->ptr++; *(int*)lval = EXPR_NOTEQEQ; return tEqOper; } *(int*)lval = EXPR_NOTEQ; return tEqOper; } return '!'; case '=': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* == */ if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* === */ ctx->ptr++; *(int*)lval = EXPR_EQEQ; return tEqOper; } *(int*)lval = EXPR_EQ; return tEqOper; } return '='; case '/': if(++ctx->ptr < ctx->end) { if(*ctx->ptr == '=') { /* /= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNDIV; return kDIVEQ; } } return '/'; case '\"': case '\'': return parse_string_literal(ctx, lval, *ctx->ptr); case '_': case '$': return parse_identifier(ctx, lval); case '@': return '@'; } WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr); return 0; }
static BOOL parse_numeric_literal(parser_ctx_t *ctx, double *ret) { LONG l, d; l = *ctx->ptr++ - '0'; if(!l) { if(*ctx->ptr == 'x' || *ctx->ptr == 'X') { if(++ctx->ptr == ctx->end) { ERR("unexpected end of file\n"); return FALSE; } while(ctx->ptr < ctx->end && (d = hex_to_int(*ctx->ptr)) != -1) { l = l*16 + d; ctx->ptr++; } if(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr)) { WARN("unexpected identifier char\n"); lex_error(ctx, JS_E_MISSING_SEMICOLON); return FALSE; } *ret = l; return TRUE; } if(isdigitW(*ctx->ptr)) { unsigned base = 8; const WCHAR *ptr; double val = 0; for(ptr = ctx->ptr; ptr < ctx->end && isdigitW(*ptr); ptr++) { if(*ptr > '7') { base = 10; break; } } do { val = val*base + *ctx->ptr-'0'; }while(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr)); /* FIXME: Do we need it here? */ if(ctx->ptr < ctx->end && (is_identifier_char(*ctx->ptr) || *ctx->ptr == '.')) { WARN("wrong char after octal literal: '%c'\n", *ctx->ptr); lex_error(ctx, JS_E_MISSING_SEMICOLON); return FALSE; } *ret = val; return TRUE; } if(is_identifier_char(*ctx->ptr)) { WARN("wrong char after zero\n"); lex_error(ctx, JS_E_MISSING_SEMICOLON); return FALSE; } } return parse_double_literal(ctx, l, ret); }
static int parse_numeric_literal(parser_ctx_t *ctx, literal_t **literal) { LONG l, d; l = *ctx->ptr++ - '0'; if(ctx->ptr == ctx->end) { *literal = new_int_literal(ctx, l); return tNumericLiteral; } if(!l) { if(*ctx->ptr == 'x' || *ctx->ptr == 'X') { if(++ctx->ptr == ctx->end) { ERR("unexpected end of file\n"); return 0; } while(ctx->ptr < ctx->end && (d = hex_to_int(*ctx->ptr)) != -1) { l = l*16 + d; ctx->ptr++; } if(ctx->ptr < ctx->end && is_identifier_char(*ctx->ptr)) { WARN("unexpected identifier char\n"); return lex_error(ctx, E_FAIL); } *literal = new_int_literal(ctx, l); return tNumericLiteral; } if(isdigitW(*ctx->ptr) || is_identifier_char(*ctx->ptr)) { WARN("wrong char after zero\n"); return lex_error(ctx, E_FAIL); } *literal = new_int_literal(ctx, 0); } while(ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { d = l*10 + *(ctx->ptr)-'0'; /* Check for integer overflow */ if (l > INT_MAX/10 || d < 0) return parse_double_literal(ctx, l, literal); l = d; ctx->ptr++; } if(ctx->ptr < ctx->end) { if(*ctx->ptr == '.' || *ctx->ptr == 'e' || *ctx->ptr == 'E') return parse_double_literal(ctx, l, literal); if(is_identifier_char(*ctx->ptr)) { WARN("unexpected identifier char\n"); return lex_error(ctx, E_FAIL); } } *literal = new_int_literal(ctx, l); return tNumericLiteral; }