mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-17 09:02:25 +00:00
Starting expression parsing
This commit is contained in:
parent
e8563442a1
commit
5d6767f337
2 changed files with 83 additions and 30 deletions
1
lexer.h
1
lexer.h
|
@ -183,6 +183,7 @@ static const oper_info operators[] = {
|
|||
{ "^=", opid2('^','='), ASSOC_RIGHT, 2, 0 },
|
||||
{ "|=", opid2('|','='), ASSOC_RIGHT, 2, 0 },
|
||||
};
|
||||
const size_t operator_count = (sizeof(operators) / sizeof(operators[0]));
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
112
parser.c
112
parser.c
|
@ -200,51 +200,96 @@ static sy_elem syexp(ast_expression *v) {
|
|||
}
|
||||
static sy_elem syval(ast_value *v) { return syexp((ast_expression*)v); }
|
||||
|
||||
static bool parser_expression(parser_t *parser, ast_block *block)
|
||||
static ast_expression* parser_expression(parser_t *parser)
|
||||
{
|
||||
ast_expression *expr = NULL;
|
||||
shynt sy;
|
||||
bool wantop = false;
|
||||
|
||||
MEM_VECTOR_INIT(&sy, out);
|
||||
MEM_VECTOR_INIT(&sy, ops);
|
||||
|
||||
if (parser->tok == TOKEN_IDENT)
|
||||
while (true)
|
||||
{
|
||||
/* variable */
|
||||
ast_value *var = parser_find_var(parser, parser_tokval(parser));
|
||||
if (!var) {
|
||||
parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
|
||||
goto onerr;
|
||||
}
|
||||
if (!shynt_out_add(&sy, syval(var))) {
|
||||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
} else if (parser->tok == TOKEN_FLOATCONST) {
|
||||
ast_value *val = parser_const_float(parser, (parser_token(parser)->constval.f));
|
||||
if (!val)
|
||||
return false;
|
||||
if (!shynt_out_add(&sy, syval(val))) {
|
||||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
} else if (parser->tok == TOKEN_INTCONST) {
|
||||
ast_value *val = parser_const_float(parser, (double)(parser_token(parser)->constval.i));
|
||||
if (!val)
|
||||
return false;
|
||||
if (!shynt_out_add(&sy, syval(val))) {
|
||||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
if (!wantop)
|
||||
{
|
||||
if (parser->tok == TOKEN_IDENT)
|
||||
{
|
||||
/* variable */
|
||||
ast_value *var = parser_find_var(parser, parser_tokval(parser));
|
||||
if (!var) {
|
||||
parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
|
||||
goto onerr;
|
||||
}
|
||||
if (!shynt_out_add(&sy, syval(var))) {
|
||||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
} else if (parser->tok == TOKEN_FLOATCONST) {
|
||||
ast_value *val = parser_const_float(parser, (parser_token(parser)->constval.f));
|
||||
if (!val)
|
||||
return false;
|
||||
if (!shynt_out_add(&sy, syval(val))) {
|
||||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
} else if (parser->tok == TOKEN_INTCONST) {
|
||||
ast_value *val = parser_const_float(parser, (double)(parser_token(parser)->constval.i));
|
||||
if (!val)
|
||||
return false;
|
||||
if (!shynt_out_add(&sy, syval(val))) {
|
||||
parseerror(parser, "out of memory");
|
||||
goto onerr;
|
||||
}
|
||||
} else {
|
||||
/* TODO: prefix operators */
|
||||
parseerror(parser, "expected statement");
|
||||
goto onerr;
|
||||
}
|
||||
wantop = true;
|
||||
parser->lex->flags.noops = false;
|
||||
if (!parser_next(parser)) {
|
||||
goto onerr;
|
||||
}
|
||||
} else {
|
||||
if (parser->tok != TOKEN_OPERATOR) {
|
||||
parseerror(parser, "expected operator or end of statement");
|
||||
goto onerr;
|
||||
} else {
|
||||
/* classify the operator */
|
||||
/* TODO: suffix operators */
|
||||
size_t o;
|
||||
for (o = 0; o < operator_count; ++o) {
|
||||
if (!(operators[o].flags & OP_PREFIX) &&
|
||||
!(operators[o].flags & OP_SUFFIX) && /* remove this */
|
||||
!strcmp(parser_tokval(parser), operators[o].op))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (o == operator_count) {
|
||||
/* no operator found... must be the end of the statement */
|
||||
break;
|
||||
}
|
||||
}
|
||||
wantop = false;
|
||||
parser->lex->flags.noops = true;
|
||||
if (!parser_next(parser)) {
|
||||
goto onerr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parser->lex->flags.noops = true;
|
||||
MEM_VECTOR_CLEAR(&sy, out);
|
||||
MEM_VECTOR_CLEAR(&sy, ops);
|
||||
return true;
|
||||
return expr;
|
||||
|
||||
onerr:
|
||||
parser->lex->flags.noops = true;
|
||||
MEM_VECTOR_CLEAR(&sy, out);
|
||||
MEM_VECTOR_CLEAR(&sy, ops);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool parser_variable(parser_t *parser, bool global);
|
||||
|
@ -264,7 +309,14 @@ static bool parser_body_do(parser_t *parser, ast_block *block)
|
|||
return false;
|
||||
}
|
||||
else
|
||||
return parser_expression(parser, block);
|
||||
{
|
||||
ast_expression *exp = parser_expression(parser);
|
||||
if (!exp)
|
||||
return false;
|
||||
if (!ast_block_exprs_add(block, exp))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static ast_block* parser_parse_block(parser_t *parser)
|
||||
|
|
Loading…
Reference in a new issue