}
/* returns true if it counts as an error */
-bool parsewarning(parser_t *parser, int warntype, const char *fmt, ...)
+bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char *fmt, ...)
{
va_list ap;
int lvl = LVL_WARNING;
return true;
}
+static bool parser_parse_dowhile(parser_t *parser, ast_block *block, ast_expression **out)
+{
+ ast_loop *aloop;
+ ast_expression *cond, *ontrue;
+
+ lex_ctx ctx = parser_ctx(parser);
+
+ /* skip the 'do' and get the body */
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected loop body");
+ return false;
+ }
+ ontrue = parser_parse_statement_or_block(parser);
+ if (!ontrue)
+ return false;
+
+ /* expect the "while" */
+ if (parser->tok != TOKEN_KEYWORD ||
+ strcmp(parser_tokval(parser), "while"))
+ {
+ parseerror(parser, "expected 'while' and condition");
+ ast_delete(ontrue);
+ return false;
+ }
+
+ /* skip the 'while' and check for opening paren */
+ if (!parser_next(parser) || parser->tok != '(') {
+ parseerror(parser, "expected 'while' condition in parenthesis");
+ ast_delete(ontrue);
+ return false;
+ }
+ /* parse into the expression */
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected 'while' condition after opening paren");
+ ast_delete(ontrue);
+ return false;
+ }
+ /* parse the condition */
+ cond = parser_expression_leave(parser);
+ if (!cond)
+ return false;
+ /* closing paren */
+ if (parser->tok != ')') {
+ parseerror(parser, "expected closing paren after 'while' condition");
+ ast_delete(ontrue);
+ ast_delete(cond);
+ return false;
+ }
+ /* parse on */
+ if (!parser_next(parser) || parser->tok != ';') {
+ parseerror(parser, "expected semicolon after condition");
+ ast_delete(ontrue);
+ ast_delete(cond);
+ return false;
+ }
+
+ if (!parser_next(parser)) {
+ parseerror(parser, "parse error");
+ ast_delete(ontrue);
+ ast_delete(cond);
+ return false;
+ }
+
+ aloop = ast_loop_new(ctx, NULL, NULL, cond, NULL, ontrue);
+ *out = (ast_expression*)aloop;
+ return true;
+}
+
static bool parser_parse_for(parser_t *parser, ast_block *block, ast_expression **out)
{
ast_loop *aloop;
/* parse the condition */
if (parser->tok != ';') {
- printf("going cond!\n");
cond = parser_expression_leave(parser);
if (!cond)
goto onerr;
- printf("going cond!\n");
}
/* move on to incrementor */
parseerror(parser, "cannot declare a variable from here");
return false;
}
+ if (opts_standard == COMPILER_QCC) {
+ if (parsewarning(parser, WARN_EXTENSIONS, "missing 'local' keyword when declaring a local variable"))
+ return false;
+ }
if (!parser_variable(parser, block))
return false;
*out = NULL;
}
else if (parser->tok == TOKEN_KEYWORD)
{
- if (!strcmp(parser_tokval(parser), "return"))
+ if (!strcmp(parser_tokval(parser), "local"))
+ {
+ if (!block) {
+ parseerror(parser, "cannot declare a local variable here");
+ return false;
+ }
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected variable declaration");
+ return false;
+ }
+ if (!parser_variable(parser, block))
+ return false;
+ *out = NULL;
+ return true;
+ }
+ else if (!strcmp(parser_tokval(parser), "return"))
{
ast_expression *exp = NULL;
ast_return *ret = NULL;
{
return parser_parse_while(parser, block, out);
}
+ else if (!strcmp(parser_tokval(parser), "do"))
+ {
+ return parser_parse_dowhile(parser, block, out);
+ }
else if (!strcmp(parser_tokval(parser), "for"))
{
return parser_parse_for(parser, block, out);
}
if (parser->tok == ';')
- return parser_next(parser);
+ return parser_next(parser) || parser->tok == TOKEN_EOF;
else if (opts_standard == COMPILER_QCC)
parseerror(parser, "missing semicolon after function body (mandatory with -std=qcc)");
return true;
}
}
- ir_builder_dump(ir, printf);
+ if (opts_dump)
+ ir_builder_dump(ir, printf);
if (!ir_builder_generate(ir, output)) {
printf("*** failed to generate output file\n");