summaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/parse.c b/parse.c
index a48fc6b..378eef3 100644
--- a/parse.c
+++ b/parse.c
@@ -3,7 +3,7 @@
This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-static void parser_create(Parser *p, Identifiers *globals, Tokenizer *t, Allocator *allocr, File *main_file, StrHashTable *included_files);
+static void parser_create(Parser *p, Identifiers *globals, Tokenizer *t, Allocator *allocr, GlobalCtx *gctx);
static Status parse_file(Parser *p, ParsedFile *f);
static Status parse_expr(Parser *p, Expression *e, Token *end);
static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement);
@@ -344,6 +344,18 @@ static inline Identifiers *parser_get_idents(Parser *p) {
return p->block == NULL ? p->globals : &p->block->idents;
}
+static inline bool block_is_at_top_level(Block *b) {
+ for (Block *bb = b; bb; bb = bb->parent)
+ if (bb->kind != BLOCK_NMS)
+ return false;
+ return true;
+}
+
+static inline bool parser_is_at_top_level(Parser *p) {
+ return block_is_at_top_level(p->block);
+}
+
+
#define parser_arr_add_ptr(p, a) arr_adda_ptr(a, p->allocr)
#define parser_arr_add(p, a, x) arr_adda(a, x, p->allocr)
#define parser_arr_set_len(p, a, l) arr_set_lena(a, l, p->allocr)
@@ -2329,6 +2341,8 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
i->flags = 0;
if (t->token->kind == TOKEN_DIRECT) {
i->flags |= IF_STATIC;
+ StatementWithCtx sctx = {s, p->block, p->nms};
+ parser_arr_add(p, p->gctx->static_ifs, sctx);
}
s->kind = STMT_IF;
++t->token;
@@ -2572,11 +2586,12 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
if (!forced) {
size_t filename_len = strlen(filename);
- if (streq(filename, p->main_file->filename)) {
+ if (streq(filename, p->gctx->main_file->filename)) {
err_print(s->where, "Circular #include detected. You can add #force to this #include to force it to be included.");
success = false; goto nms_done;
}
- inc_f = str_hash_table_get(p->included_files, filename, filename_len);
+ StrHashTable *included_files = &p->gctx->included_files;
+ inc_f = str_hash_table_get(included_files, filename, filename_len);
if (inc_f) {
/* has already been included */
if (inc_f->flags & INC_FILE_INCLUDING) {
@@ -2590,7 +2605,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
}
goto nms_done;
} else {
- inc_f = str_hash_table_insert(p->included_files, filename, filename_len);
+ inc_f = str_hash_table_insert(included_files, filename, filename_len);
inc_f->flags |= INC_FILE_INCLUDING;
inc_f->main_nms = p->nms;
}
@@ -2620,7 +2635,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
#endif
Parser parser;
- parser_create(&parser, p->globals, &tokr, p->allocr, p->main_file, p->included_files);
+ parser_create(&parser, p->globals, &tokr, p->allocr, p->gctx);
parser.block = p->block;
parser.nms = p->nms;
ParsedFile parsed_file;
@@ -2672,8 +2687,13 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
}
} break;
case DIRECT_INIT: {
+ if (!parser_is_at_top_level(p)) {
+ tokr_err(t, "#init directives can't be inside a block.");
+ tokr_skip_semicolon(t);
+ return false;
+ }
*was_a_statement = false;
- Initialization *init = parser_arr_add_ptr(p, p->parsed_file->inits);
+ Initialization *init = parser_arr_add_ptr(p, p->gctx->inits);
++t->token;
if (!token_is_kw(t->token, KW_LPAREN)) {
tokr_err(t, "Expected ( after #init.");
@@ -2746,19 +2766,17 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
return true;
}
-static void parser_create(Parser *p, Identifiers *globals, Tokenizer *t, Allocator *allocr, File *main_file, StrHashTable *included_files) {
+static void parser_create(Parser *p, Identifiers *globals, Tokenizer *t, Allocator *allocr, GlobalCtx *gctx) {
p->tokr = t;
p->block = NULL;
p->globals = globals;
p->allocr = allocr;
- p->main_file = main_file;
- p->included_files = included_files;
+ p->gctx = gctx;
}
static Status parse_file(Parser *p, ParsedFile *f) {
Tokenizer *t = p->tokr;
f->stmts = NULL;
- f->inits = NULL;
p->file = t->file;
p->parsed_file = f;
bool ret = true;