mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-17 09:02:25 +00:00
Handling parenthesis in expressions
This commit is contained in:
parent
45933d2ce9
commit
dcb815a65f
1 changed files with 62 additions and 9 deletions
71
parser.c
71
parser.c
|
@ -182,6 +182,7 @@ static ast_value *parser_parse_type(parser_t *parser, int basetype, bool *isfunc
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
size_t etype; /* 0 = expression, others are operators */
|
size_t etype; /* 0 = expression, others are operators */
|
||||||
|
int paren;
|
||||||
ast_expression *out;
|
ast_expression *out;
|
||||||
ast_value *value; /* need to know if we can assign */
|
ast_value *value; /* need to know if we can assign */
|
||||||
lex_ctx ctx;
|
lex_ctx ctx;
|
||||||
|
@ -200,6 +201,7 @@ static sy_elem syexp(lex_ctx ctx, ast_expression *v) {
|
||||||
e.out = v;
|
e.out = v;
|
||||||
e.value = NULL;
|
e.value = NULL;
|
||||||
e.ctx = ctx;
|
e.ctx = ctx;
|
||||||
|
e.paren = 0;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
static sy_elem syval(lex_ctx ctx, ast_value *v) {
|
static sy_elem syval(lex_ctx ctx, ast_value *v) {
|
||||||
|
@ -208,6 +210,7 @@ static sy_elem syval(lex_ctx ctx, ast_value *v) {
|
||||||
e.out = (ast_expression*)v;
|
e.out = (ast_expression*)v;
|
||||||
e.value = v;
|
e.value = v;
|
||||||
e.ctx = ctx;
|
e.ctx = ctx;
|
||||||
|
e.paren = 0;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +220,17 @@ static sy_elem syop(lex_ctx ctx, const oper_info *op) {
|
||||||
e.out = NULL;
|
e.out = NULL;
|
||||||
e.value = NULL;
|
e.value = NULL;
|
||||||
e.ctx = ctx;
|
e.ctx = ctx;
|
||||||
|
e.paren = 0;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sy_elem syparen(lex_ctx ctx, int p) {
|
||||||
|
sy_elem e;
|
||||||
|
e.etype = 0;
|
||||||
|
e.out = NULL;
|
||||||
|
e.value = NULL;
|
||||||
|
e.ctx = ctx;
|
||||||
|
e.paren = p;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,6 +248,11 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sy->ops[sy->ops_count-1].paren) {
|
||||||
|
parseerror(parser, "unmatched parenthesis");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
op = &operators[sy->ops[sy->ops_count-1].etype - 1];
|
op = &operators[sy->ops[sy->ops_count-1].etype - 1];
|
||||||
ctx = sy->ops[sy->ops_count-1].ctx;
|
ctx = sy->ops[sy->ops_count-1].ctx;
|
||||||
|
|
||||||
|
@ -377,6 +396,7 @@ static ast_expression* parser_expression(parser_t *parser)
|
||||||
{
|
{
|
||||||
if (!wantop)
|
if (!wantop)
|
||||||
{
|
{
|
||||||
|
bool nextwant = true;
|
||||||
if (parser->tok == TOKEN_IDENT)
|
if (parser->tok == TOKEN_IDENT)
|
||||||
{
|
{
|
||||||
/* variable */
|
/* variable */
|
||||||
|
@ -390,7 +410,8 @@ static ast_expression* parser_expression(parser_t *parser)
|
||||||
goto onerr;
|
goto onerr;
|
||||||
}
|
}
|
||||||
printf("Added: %s\n", var->name);
|
printf("Added: %s\n", var->name);
|
||||||
} else if (parser->tok == TOKEN_FLOATCONST) {
|
}
|
||||||
|
else if (parser->tok == TOKEN_FLOATCONST) {
|
||||||
ast_value *val = parser_const_float(parser, (parser_token(parser)->constval.f));
|
ast_value *val = parser_const_float(parser, (parser_token(parser)->constval.f));
|
||||||
if (!val)
|
if (!val)
|
||||||
return false;
|
return false;
|
||||||
|
@ -398,7 +419,8 @@ static ast_expression* parser_expression(parser_t *parser)
|
||||||
parseerror(parser, "out of memory");
|
parseerror(parser, "out of memory");
|
||||||
goto onerr;
|
goto onerr;
|
||||||
}
|
}
|
||||||
} else if (parser->tok == TOKEN_INTCONST) {
|
}
|
||||||
|
else if (parser->tok == TOKEN_INTCONST) {
|
||||||
ast_value *val = parser_const_float(parser, (double)(parser_token(parser)->constval.i));
|
ast_value *val = parser_const_float(parser, (double)(parser_token(parser)->constval.i));
|
||||||
if (!val)
|
if (!val)
|
||||||
return false;
|
return false;
|
||||||
|
@ -407,18 +429,48 @@ static ast_expression* parser_expression(parser_t *parser)
|
||||||
goto onerr;
|
goto onerr;
|
||||||
}
|
}
|
||||||
printf("Added: %i\n", parser_token(parser)->constval.i);
|
printf("Added: %i\n", parser_token(parser)->constval.i);
|
||||||
} else {
|
}
|
||||||
|
else if (parser->tok == '(') {
|
||||||
|
nextwant = false; /* not expecting an operator next */
|
||||||
|
if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), 1))) {
|
||||||
|
parseerror(parser, "out of memory");
|
||||||
|
goto onerr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
/* TODO: prefix operators */
|
/* TODO: prefix operators */
|
||||||
parseerror(parser, "expected statement");
|
parseerror(parser, "expected statement");
|
||||||
goto onerr;
|
goto onerr;
|
||||||
}
|
}
|
||||||
wantop = true;
|
wantop = nextwant;
|
||||||
parser->lex->flags.noops = false;
|
parser->lex->flags.noops = !wantop;
|
||||||
} else {
|
} else {
|
||||||
if (parser->tok != TOKEN_OPERATOR) {
|
if (parser->tok == ')') {
|
||||||
|
/* we do expect an operator next */
|
||||||
|
/* closing an opening paren */
|
||||||
|
printf("Applying closing paren\n");
|
||||||
|
if (!sy.ops_count) {
|
||||||
|
parseerror(parser, "unmatched closing paren");
|
||||||
|
goto onerr;
|
||||||
|
}
|
||||||
|
if (sy.ops[sy.ops_count-1].paren == 1) {
|
||||||
|
parseerror(parser, "empty parenthesis expression");
|
||||||
|
goto onerr;
|
||||||
|
}
|
||||||
|
while (sy.ops_count) {
|
||||||
|
if (sy.ops[sy.ops_count-1].paren == 1) {
|
||||||
|
sy.ops_count--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!parser_sy_pop(parser, &sy))
|
||||||
|
goto onerr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parser->tok != TOKEN_OPERATOR) {
|
||||||
parseerror(parser, "expected operator or end of statement");
|
parseerror(parser, "expected operator or end of statement");
|
||||||
goto onerr;
|
goto onerr;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
/* classify the operator */
|
/* classify the operator */
|
||||||
/* TODO: suffix operators */
|
/* TODO: suffix operators */
|
||||||
const oper_info *op;
|
const oper_info *op;
|
||||||
|
@ -439,7 +491,7 @@ static ast_expression* parser_expression(parser_t *parser)
|
||||||
/* found an operator */
|
/* found an operator */
|
||||||
op = &operators[o];
|
op = &operators[o];
|
||||||
|
|
||||||
if (sy.ops_count)
|
if (sy.ops_count && !sy.ops[sy.ops_count-1].paren)
|
||||||
olast = &operators[sy.ops[sy.ops_count-1].etype-1];
|
olast = &operators[sy.ops[sy.ops_count-1].etype-1];
|
||||||
|
|
||||||
while (olast && (
|
while (olast && (
|
||||||
|
@ -448,7 +500,8 @@ static ast_expression* parser_expression(parser_t *parser)
|
||||||
{
|
{
|
||||||
if (!parser_sy_pop(parser, &sy))
|
if (!parser_sy_pop(parser, &sy))
|
||||||
goto onerr;
|
goto onerr;
|
||||||
olast = sy.ops_count ? (&operators[sy.ops[sy.ops_count-1].etype-1]) : NULL;
|
if (sy.ops_count && !sy.ops[sy.ops_count-1].paren)
|
||||||
|
olast = &operators[sy.ops[sy.ops_count-1].etype-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))
|
if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))
|
||||||
|
|
Loading…
Reference in a new issue