blob: 18c1cb1c38e3eea8d1543fc37ec35edd659e94da [file] [log] [blame]
/*
* 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"
#include "engine.h"
#include "parser.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
%}
%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 <ccval> tCCValue
%type <ccval> CCUnaryExpression CCLogicalORExpression CCLogicalANDExpression
%type <ccval> CCBitwiseORExpression CCBitwiseXORExpression CCBitwiseANDExpression
%type <ccval> 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);
}