[cexpr] Support variable assignment

I might have to add code to block it when necessary, but it's needed for
axis recipe parsing.
This commit is contained in:
Bill Currie 2021-11-12 00:19:58 +09:00
parent 5557bf0b09
commit 6e85377d7a
2 changed files with 18 additions and 7 deletions

View file

@ -166,15 +166,23 @@ STRING \"(\\.|[^"\\])*\"
} }
[+\-*/&|^%]= { [+\-*/&|^%]= {
yylval->op = yytext[0];
return ASX;
} }
"%%=" { "%%=" {
yylval->op = MOD;
return ASX;
} }
"<<=" { "<<=" {
yylval->op = SHL;
return ASX;
} }
">>=" { ">>=" {
yylval->op = SHR;
return ASX;
} }
[!(){}.*/&|^~+\-=\[\];,#%?:] { [!(){}.*/&|^~+\-=\[\];,#%?:] {
@ -182,6 +190,7 @@ STRING \"(\\.|[^"\\])*\"
} }
"%%" { "%%" {
return MOD;
} }
"<<" return SHL; "<<" return SHL;

View file

@ -51,8 +51,8 @@
#include "QF/cexpr.h" #include "QF/cexpr.h"
static void assign_expr (exprval_t *dst, const exprval_t *src, static exprval_t *assign_expr (exprval_t *dst, const exprval_t *src,
exprctx_t *context); exprctx_t *context);
static exprval_t *binary_expr (int op, const exprval_t *a, const exprval_t *b, static exprval_t *binary_expr (int op, const exprval_t *a, const exprval_t *b,
exprctx_t *context); exprctx_t *context);
static exprval_t *field_expr (const exprval_t *a, const exprval_t *b, static exprval_t *field_expr (const exprval_t *a, const exprval_t *b,
@ -138,6 +138,7 @@ uexpr
expr expr
: uexpr : uexpr
| expr '=' expr { $$ = assign_expr ($1, $3, context); }
| expr SHL expr { $$ = binary_expr (SHL, $1, $3, context); } | expr SHL expr { $$ = binary_expr (SHL, $1, $3, context); }
| expr SHR expr { $$ = binary_expr (SHR, $1, $3, context); } | expr SHR expr { $$ = binary_expr (SHR, $1, $3, context); }
| expr '+' expr { $$ = binary_expr ('+', $1, $3, context); } | expr '+' expr { $$ = binary_expr ('+', $1, $3, context); }
@ -184,16 +185,16 @@ arg_expr
%% %%
static void static exprval_t *
assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context) assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context)
{ {
binop_t *binop; binop_t *binop;
if (!src) { if (!dst || !src) {
return; return 0;
} }
if (dst->type == &cexpr_exprval) { if (dst->type == &cexpr_exprval) {
*(exprval_t **) dst->value = (exprval_t *) src; *(exprval_t **) dst->value = (exprval_t *) src;
return; return dst;
} }
binop = cexpr_find_cast (dst->type, src->type); binop = cexpr_find_cast (dst->type, src->type);
if (binop && binop->op) { if (binop && binop->op) {
@ -203,10 +204,11 @@ assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context)
cexpr_error (context, cexpr_error (context,
"type mismatch in expression result: %s = %s", "type mismatch in expression result: %s = %s",
dst->type->name, src->type->name); dst->type->name, src->type->name);
return; return dst;
} }
memcpy (dst->value, src->value, dst->type->size); memcpy (dst->value, src->value, dst->type->size);
} }
return dst;
} }
static exprval_t * static exprval_t *