static void parser_addglobal(parser_t *parser, const std::string &name, ast_expression *e);
static bool parse_typedef(parser_t *parser);
static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring);
-static ast_block* parse_block(parser_t *parser);
static bool parse_block_into(parser_t *parser, ast_block *block);
static bool parse_statement_or_block(parser_t *parser, ast_expression **out);
static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases);
{
size_t i, hash;
ast_expression *e;
- ast_expression *p;
hash = util_hthash(parser->htglobals, name);
*isparam = false;
- p = parser_find_param(parser, name);
- if (p) {
- *isparam = true;
- return p;
- }
for (i = parser->variables.size(); i > upto;) {
--i;
if ( (e = (ast_expression*)util_htgeth(parser->variables[i], name, hash)) )
return e;
}
- return NULL;
+ *isparam = true;
+ return parser_find_param(parser, name);
}
static ast_expression* parser_find_local(parser_t *parser, const std::string &name, size_t upto, bool *isparam) {
{
bool dummy;
ast_expression *v;
- v = parser_find_local(parser, name, 0, &dummy);
+ v = parser_find_local(parser, name, PARSER_HT_LOCALS, &dummy);
if (!v) v = parser_find_global(parser, name);
return v;
}
const oper_info *op;
lex_ctx_t ctx;
ast_expression *out = nullptr;
- ast_expression *exprs[3];
+ ast_expression *exprs[3] = { 0, 0, 0 };
ast_block *blocks[3];
ast_binstore *asbinstore;
size_t i, assignop, addop, subop;
static bool parser_close_call(parser_t *parser, shunt *sy)
{
+ if (!parser->function)
+ {
+ parseerror(parser, "cannot call functions from global scope");
+ return false;
+ }
+
/* was a function call */
ast_expression *fun;
ast_value *funval = nullptr;
{ "noreturn", AST_FLAG_NORETURN },
{ "inline", AST_FLAG_INLINE },
{ "eraseable", AST_FLAG_ERASEABLE },
+ { "noerase", AST_FLAG_NOERASE },
{ "accumulate", AST_FLAG_ACCUMULATE },
{ "last", AST_FLAG_FINAL_DECL }
};
if (i != GMQCC_ARRAY_COUNT(attributes))
goto leave;
-
if (!strcmp(parser_tokval(parser), "noref")) {
had_noref = true;
if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
}
else if (parser->tok == '{')
{
- ast_block *inner;
- inner = parse_block(parser);
- if (!inner)
- return false;
- *out = inner;
- return true;
+ return parse_statement_or_block(parser, out);
}
else if (parser->tok == ':')
{
return retval && !!block;
}
-static ast_block* parse_block(parser_t *parser)
-{
- ast_block *block;
- block = new ast_block(parser_ctx(parser));
- if (!block)
- return nullptr;
- if (!parse_block_into(parser, block)) {
- delete block;
- return nullptr;
- }
- return block;
-}
-
static bool parse_statement_or_block(parser_t *parser, ast_expression **out)
{
+ bool result = true;
+ std::unique_ptr<ast_block> block(new ast_block(parser_ctx(parser)));
if (parser->tok == '{') {
- *out = parse_block(parser);
- return !!*out;
+ if (!parse_block_into(parser, block.get())) {
+ return false;
+ }
+ } else {
+ parser_enterblock(parser);
+
+ ast_expression* expression = nullptr;
+ if (!parse_statement(parser, block.get(), &expression, false)) {
+ result = false;
+ }
+
+ if (expression && !block->addExpr(expression)) {
+ result = false;
+ }
+
+ if (!parser_leaveblock(parser)) {
+ return false;
+ }
}
- return parse_statement(parser, nullptr, out, false);
+
+ if (result) {
+ *out = block.release();
+ return true;
+ }
+
+ return false;
}
static bool create_vector_members(ast_value *var, ast_member **me)
enderrfn:
(void)!parser_leaveblock(parser);
- parser->functions.pop_back();
+
delete func;
+
+ // Remove |func| from |parser->functions|. It may not actually be at the
+ // back of the vector for accumulated functions.
+ for (auto it = parser->functions.begin(); it != parser->functions.end(); it++) {
+ if (*it == func) {
+ parser->functions.erase(it, it + 1);
+ break;
+ }
+ }
+
var->m_constval.vfunc = nullptr;
enderr:
}
if ( (old = parser_find_var(parser, typevar->m_name)) ) {
- parseerror(parser, "cannot define a type with the same name as a variable: %s\n"
+ parseerror(parser, "cannot define a type with the same name as a variable:\n"
" -> `%s` has been declared here: %s:%i",
typevar->m_name, old->m_context.file, old->m_context.line);
delete typevar;
* store the vstring back to var for alias and
* deprecation messages.
*/
- if (var->m_flags & AST_FLAG_DEPRECATED ||
- var->m_flags & AST_FLAG_ALIAS)
+ if (var->m_flags & AST_FLAG_DEPRECATED || var->m_flags & AST_FLAG_ALIAS)
var->m_desc = vstring;
if (parser_find_global(parser, var->m_name) && var->m_flags & AST_FLAG_ALIAS) {