/* * Copyright 2014 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ %{ #include "jscript.h" %} %lex-param { parser_ctx_t *ctx } %parse-param { parser_ctx_t *ctx } %pure-parser %start CCExpr %union { ccval_t ccval; } %token tEQ tEQEQ tNEQ tNEQEQ tLSHIFT tRSHIFT tRRSHIFT tOR tAND tLEQ tGEQ %token tCCValue %type CCUnaryExpression CCLogicalORExpression CCLogicalANDExpression %type CCBitwiseORExpression CCBitwiseXORExpression CCBitwiseANDExpression %type CCEqualityExpression CCRelationalExpression CCShiftExpression CCAdditiveExpression CCMultiplicativeExpression %{ static int cc_parser_error(parser_ctx_t *ctx, const char *str) { if(SUCCEEDED(ctx->hres)) { WARN("%s\n", str); ctx->hres = JS_E_SYNTAX; } return 0; } static int cc_parser_lex(void *lval, parser_ctx_t *ctx) { int r; r = try_parse_ccval(ctx, lval); if(r) return r > 0 ? tCCValue : -1; switch(*ctx->ptr) { case '(': case ')': case '+': case '-': case '*': case '/': case '~': case '%': case '^': return *ctx->ptr++; case '=': if(*++ctx->ptr == '=') { if(*++ctx->ptr == '=') { ctx->ptr++; return tEQEQ; } return tEQ; } break; case '!': if(*++ctx->ptr == '=') { if(*++ctx->ptr == '=') { ctx->ptr++; return tNEQEQ; } return tNEQ; } return '!'; case '<': switch(*++ctx->ptr) { case '<': ctx->ptr++; return tLSHIFT; case '=': ctx->ptr++; return tLEQ; default: return '<'; } case '>': switch(*++ctx->ptr) { case '>': if(*++ctx->ptr == '>') { ctx->ptr++; return tRRSHIFT; } return tRSHIFT; case '=': ctx->ptr++; return tGEQ; default: return '>'; } case '|': if(*++ctx->ptr == '|') { ctx->ptr++; return tOR; } return '|'; case '&': if(*++ctx->ptr == '&') { ctx->ptr++; return tAND; } return '&'; } WARN("Failed to interpret %s\n", debugstr_w(ctx->ptr)); return -1; } %} %% /* FIXME: Implement missing expressions. */ CCExpr : CCUnaryExpression { ctx->ccval = $1; YYACCEPT; } CCUnaryExpression : tCCValue { $$ = $1; } | '(' CCLogicalORExpression ')' { $$ = $2; } | '!' CCUnaryExpression { $$ = ccval_bool(!get_ccbool($2)); }; | '~' CCUnaryExpression { FIXME("'~' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } | '+' CCUnaryExpression { FIXME("'+' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } | '-' CCUnaryExpression { FIXME("'-' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } CCLogicalORExpression : CCLogicalANDExpression { $$ = $1; } | CCLogicalORExpression tOR CCLogicalANDExpression { FIXME("'||' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } CCLogicalANDExpression : CCBitwiseORExpression { $$ = $1; } | CCBitwiseANDExpression tAND CCBitwiseORExpression { FIXME("'&&' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } CCBitwiseORExpression : CCBitwiseXORExpression { $$ = $1; } | CCBitwiseORExpression '|' CCBitwiseXORExpression { FIXME("'|' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } CCBitwiseXORExpression : CCBitwiseANDExpression { $$ = $1; } | CCBitwiseXORExpression '^' CCBitwiseANDExpression { FIXME("'^' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } CCBitwiseANDExpression : CCEqualityExpression { $$ = $1; } | CCBitwiseANDExpression '&' CCEqualityExpression { FIXME("'&' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } CCEqualityExpression : CCRelationalExpression { $$ = $1; } | CCEqualityExpression tEQ CCRelationalExpression { $$ = ccval_bool(get_ccnum($1) == get_ccnum($3)); } | CCEqualityExpression tNEQ CCRelationalExpression { $$ = ccval_bool(get_ccnum($1) != get_ccnum($3)); } | CCEqualityExpression tEQEQ CCRelationalExpression { FIXME("'===' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } | CCEqualityExpression tNEQEQ CCRelationalExpression { FIXME("'!==' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } CCRelationalExpression : CCShiftExpression { $$ = $1; } | CCRelationalExpression '<' CCShiftExpression { $$ = ccval_bool(get_ccnum($1) < get_ccnum($3)); } | CCRelationalExpression tLEQ CCShiftExpression { $$ = ccval_bool(get_ccnum($1) <= get_ccnum($3)); } | CCRelationalExpression '>' CCShiftExpression { $$ = ccval_bool(get_ccnum($1) > get_ccnum($3)); } | CCRelationalExpression tGEQ CCShiftExpression { $$ = ccval_bool(get_ccnum($1) >= get_ccnum($3)); } CCShiftExpression : CCAdditiveExpression { $$ = $1; } | CCShiftExpression tLSHIFT CCAdditiveExpression { FIXME("'<<' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } | CCShiftExpression tRSHIFT CCAdditiveExpression { FIXME("'>>' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } | CCShiftExpression tRRSHIFT CCAdditiveExpression { FIXME("'>>>' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } CCAdditiveExpression : CCMultiplicativeExpression { $$ = $1; } | CCAdditiveExpression '+' CCMultiplicativeExpression { $$ = ccval_num(get_ccnum($1) + get_ccnum($3)); } | CCAdditiveExpression '-' CCMultiplicativeExpression { $$ = ccval_num(get_ccnum($1) - get_ccnum($3)); } CCMultiplicativeExpression : CCUnaryExpression { $$ = $1; } | CCMultiplicativeExpression '*' CCUnaryExpression { $$ = ccval_num(get_ccnum($1) * get_ccnum($3)); } | CCMultiplicativeExpression '/' CCUnaryExpression { $$ = ccval_num(get_ccnum($1) / get_ccnum($3)); } | CCMultiplicativeExpression '%' CCUnaryExpression { FIXME("'%%' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; } %% BOOL parse_cc_expr(parser_ctx_t *ctx) { ctx->hres = S_OK; cc_parser_parse(ctx); return SUCCEEDED(ctx->hres); }