2014-09-30 16:51:57 +02:00
|
|
|
/*
|
|
|
|
* 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 }
|
2022-01-21 12:50:25 +01:00
|
|
|
%define api.prefix {cc_parser_}
|
2019-08-18 12:59:06 +02:00
|
|
|
%define api.pure
|
2014-09-30 16:51:57 +02:00
|
|
|
%start CCExpr
|
|
|
|
|
|
|
|
%union {
|
|
|
|
ccval_t ccval;
|
|
|
|
}
|
|
|
|
|
2014-10-02 14:36:29 +02:00
|
|
|
%token tEQ tEQEQ tNEQ tNEQEQ tLSHIFT tRSHIFT tRRSHIFT tOR tAND tLEQ tGEQ
|
2014-09-30 16:51:57 +02:00
|
|
|
%token <ccval> tCCValue
|
|
|
|
|
2014-10-02 14:36:29 +02:00
|
|
|
%type <ccval> CCUnaryExpression CCLogicalORExpression CCLogicalANDExpression
|
|
|
|
%type <ccval> CCBitwiseORExpression CCBitwiseXORExpression CCBitwiseANDExpression
|
|
|
|
%type <ccval> CCEqualityExpression CCRelationalExpression CCShiftExpression CCAdditiveExpression CCMultiplicativeExpression
|
2014-09-30 16:51:57 +02:00
|
|
|
|
|
|
|
%{
|
|
|
|
|
|
|
|
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 '+':
|
2014-10-01 10:45:44 +02:00
|
|
|
case '-':
|
2014-09-30 16:51:57 +02:00
|
|
|
case '*':
|
|
|
|
case '/':
|
2014-10-02 14:36:29 +02:00
|
|
|
case '~':
|
|
|
|
case '%':
|
|
|
|
case '^':
|
2014-09-30 16:51:57 +02:00
|
|
|
return *ctx->ptr++;
|
2014-10-02 14:36:29 +02:00
|
|
|
case '=':
|
|
|
|
if(*++ctx->ptr == '=') {
|
|
|
|
if(*++ctx->ptr == '=') {
|
|
|
|
ctx->ptr++;
|
|
|
|
return tEQEQ;
|
|
|
|
}
|
|
|
|
return tEQ;
|
|
|
|
}
|
|
|
|
break;
|
2014-09-30 16:51:57 +02:00
|
|
|
case '!':
|
|
|
|
if(*++ctx->ptr == '=') {
|
2014-10-02 14:36:29 +02:00
|
|
|
if(*++ctx->ptr == '=') {
|
|
|
|
ctx->ptr++;
|
|
|
|
return tNEQEQ;
|
|
|
|
}
|
2014-09-30 16:51:57 +02:00
|
|
|
return tNEQ;
|
|
|
|
}
|
|
|
|
return '!';
|
2014-10-02 14:36:29 +02:00
|
|
|
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 '&';
|
2014-09-30 16:51:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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; }
|
2014-10-02 14:36:29 +02:00
|
|
|
| '(' CCLogicalORExpression ')' { $$ = $2; }
|
2014-09-30 16:51:57 +02:00
|
|
|
| '!' CCUnaryExpression { $$ = ccval_bool(!get_ccbool($2)); };
|
2014-10-02 14:36:29 +02:00
|
|
|
| '~' 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
|
2020-10-12 22:25:33 +02:00
|
|
|
{ $$ = ccval_bool(get_ccbool($1) && get_ccbool($3)); }
|
2014-10-02 14:36:29 +02:00
|
|
|
|
|
|
|
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; }
|
2014-09-30 16:51:57 +02:00
|
|
|
|
|
|
|
CCEqualityExpression
|
2014-10-02 14:36:29 +02:00
|
|
|
: CCRelationalExpression { $$ = $1; }
|
|
|
|
| CCEqualityExpression tEQ CCRelationalExpression
|
2014-10-02 14:36:35 +02:00
|
|
|
{ $$ = ccval_bool(get_ccnum($1) == get_ccnum($3)); }
|
2014-10-02 14:36:29 +02:00
|
|
|
| CCEqualityExpression tNEQ CCRelationalExpression
|
2014-09-30 16:51:57 +02:00
|
|
|
{ $$ = ccval_bool(get_ccnum($1) != get_ccnum($3)); }
|
2014-10-02 14:36:29 +02:00
|
|
|
| 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
|
2014-10-02 14:36:40 +02:00
|
|
|
{ $$ = ccval_bool(get_ccnum($1) < get_ccnum($3)); }
|
2014-10-02 14:36:29 +02:00
|
|
|
| CCRelationalExpression tLEQ CCShiftExpression
|
2014-10-02 14:36:40 +02:00
|
|
|
{ $$ = ccval_bool(get_ccnum($1) <= get_ccnum($3)); }
|
2014-10-02 14:36:29 +02:00
|
|
|
| CCRelationalExpression '>' CCShiftExpression
|
2014-10-02 14:36:40 +02:00
|
|
|
{ $$ = ccval_bool(get_ccnum($1) > get_ccnum($3)); }
|
2014-10-02 14:36:29 +02:00
|
|
|
| CCRelationalExpression tGEQ CCShiftExpression
|
2014-10-02 14:36:40 +02:00
|
|
|
{ $$ = ccval_bool(get_ccnum($1) >= get_ccnum($3)); }
|
2014-10-02 14:36:29 +02:00
|
|
|
|
|
|
|
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; }
|
2014-09-30 16:51:57 +02:00
|
|
|
|
|
|
|
CCAdditiveExpression
|
|
|
|
: CCMultiplicativeExpression { $$ = $1; }
|
|
|
|
| CCAdditiveExpression '+' CCMultiplicativeExpression
|
|
|
|
{ $$ = ccval_num(get_ccnum($1) + get_ccnum($3)); }
|
2014-10-01 10:45:44 +02:00
|
|
|
| CCAdditiveExpression '-' CCMultiplicativeExpression
|
|
|
|
{ $$ = ccval_num(get_ccnum($1) - get_ccnum($3)); }
|
2014-09-30 16:51:57 +02:00
|
|
|
|
|
|
|
CCMultiplicativeExpression
|
|
|
|
: CCUnaryExpression { $$ = $1; }
|
|
|
|
| CCMultiplicativeExpression '*' CCUnaryExpression
|
|
|
|
{ $$ = ccval_num(get_ccnum($1) * get_ccnum($3)); }
|
|
|
|
| CCMultiplicativeExpression '/' CCUnaryExpression
|
|
|
|
{ $$ = ccval_num(get_ccnum($1) / get_ccnum($3)); }
|
2014-10-02 14:36:29 +02:00
|
|
|
| CCMultiplicativeExpression '%' CCUnaryExpression
|
|
|
|
{ FIXME("'%%' expression not implemented\n"); ctx->hres = E_NOTIMPL; YYABORT; }
|
2014-09-30 16:51:57 +02:00
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
BOOL parse_cc_expr(parser_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
ctx->hres = S_OK;
|
|
|
|
cc_parser_parse(ctx);
|
|
|
|
return SUCCEEDED(ctx->hres);
|
|
|
|
}
|