shunt sy;
bool wantop = false;
+ /* count the parens because an if starts with one, so the
+ * end of a condition is an unmatched closing paren
+ */
+ int parens = 0;
+
MEM_VECTOR_INIT(&sy, out);
MEM_VECTOR_INIT(&sy, ops);
}
}
else if (parser->tok == '(') {
+ ++parens;
nextwant = false; /* not expecting an operator next */
if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), 1, 0))) {
parseerror(parser, "out of memory");
}
}
else if (parser->tok == ')') {
+ --parens;
+ if (parens < 0)
+ break;
/* allowed for function calls */
if (!parser_close_paren(parser, &sy, true))
goto onerr;
parser->lex->flags.noops = !wantop;
} else {
if (parser->tok == '(') {
+ ++parens;
/* we expected an operator, this is the function-call operator */
if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), 'f', sy.out_count-1))) {
parseerror(parser, "out of memory");
}
}
else if (parser->tok == ')') {
+ --parens;
+ if (parens < 0)
+ break;
/* we do expect an operator next */
/* closing an opening paren */
if (!parser_close_paren(parser, &sy, false))
break;
}
}
- if (!parser_next(parser)) {
+ if (parens >= 0 && !parser_next(parser)) {
parseerror(parser, "Unexpected end of file");
goto onerr;
}
static bool parser_variable(parser_t *parser, ast_block *localblock);
static ast_block* parser_parse_block(parser_t *parser);
+static ast_expression* parser_parse_statement_or_block(parser_t *parser);
static bool parser_parse_statement(parser_t *parser, ast_block *block, ast_expression **out)
{
if (parser->tok == TOKEN_TYPENAME)
}
return true;
}
+ else if (!strcmp(parser_tokval(parser), "if"))
+ {
+ ast_ifthen *ifthen;
+ ast_expression *cond, *ontrue, *onfalse = NULL;
+
+ lex_ctx ctx = parser_ctx(parser);
+
+ /* skip the 'if' and check for opening paren */
+ if (!parser_next(parser) || parser->tok != '(') {
+ parseerror(parser, "expected 'if' condition in parenthesis");
+ return false;
+ }
+ /* parse into the expression */
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected 'if' condition after opening paren");
+ return false;
+ }
+ /* parse the condition */
+ cond = parser_expression(parser);
+ if (!cond)
+ return false;
+ /* closing paren */
+ if (parser->tok != ')') {
+ parseerror(parser, "expected closing paren after 'if' condition");
+ ast_delete(cond);
+ return false;
+ }
+ /* parse into the 'then' branch */
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected statement for on-true branch of 'if'");
+ ast_delete(cond);
+ return false;
+ }
+ ontrue = parser_parse_statement_or_block(parser);
+ if (!ontrue) {
+ ast_delete(cond);
+ return false;
+ }
+ /* check for an else */
+ if (!strcmp(parser_tokval(parser), "else")) {
+ /* parse into the 'else' branch */
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected on-false branch after 'else'");
+ ast_delete(ontrue);
+ ast_delete(cond);
+ return false;
+ }
+ onfalse = parser_parse_statement_or_block(parser);
+ if (!onfalse) {
+ ast_delete(ontrue);
+ ast_delete(cond);
+ return false;
+ }
+ }
+
+ ifthen = ast_ifthen_new(ctx, cond, ontrue, onfalse);
+ *out = (ast_expression*)ifthen;
+ return true;
+ }
parseerror(parser, "Unexpected keyword");
return false;
}