From d581fdc048df3714446f10ec37866a26c5e9ed7a Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Mon, 16 Jul 2012 14:52:52 +0200 Subject: [PATCH] Reading a global def --- lexer.c | 4 +- parser.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 132 insertions(+), 9 deletions(-) diff --git a/lexer.c b/lexer.c index 2c6bcb0..5c98d31 100644 --- a/lexer.c +++ b/lexer.c @@ -579,7 +579,9 @@ int lex_do(lex_file *lex) lex->tok->constval.t = TYPE_VECTOR; } else if (!strcmp(v, "for") || !strcmp(v, "while") || - !strcmp(v, "do")) + !strcmp(v, "do") || + !strcmp(v, "var") || + !strcmp(v, "const")) lex->tok->ttype = TOKEN_KEYWORD; return lex->tok->ttype; diff --git a/parser.c b/parser.c index c753c59..896c729 100644 --- a/parser.c +++ b/parser.c @@ -1,24 +1,136 @@ +#include +#include + #include "gmqcc.h" #include "lexer.h" typedef struct { lex_file *lex; int tok; + + MEM_VECTOR_MAKE(ast_value*, globals); } parser_t; +MEM_VEC_FUNCTIONS(parser_t, ast_value*, globals) + +void parseerror(parser_t *parser, const char *fmt, ...) +{ + va_list ap; + + if (parser) + printf("error %s:%lu: ", parser->lex->tok->ctx.file, (unsigned long)parser->lex->tok->ctx.line); + else + printf("error: "); + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + + printf("\n"); +} + +bool parser_next(parser_t *parser) +{ + /* lex_do kills the previous token */ + parser->tok = lex_do(parser->lex); + if (parser->tok == TOKEN_EOF || parser->tok >= TOKEN_ERROR) + return false; + return true; +} + +/* lift a token out of the parser so it's not destroyed by parser_next */ +token *parser_lift(parser_t *parser) +{ + token *tok = parser->lex->tok; + parser->lex->tok = NULL; + return tok; +} + +#define parser_tokval(p) (p->lex->tok->value) +#define parser_token(p) (p->lex->tok) +#define parser_ctx(p) (p->lex->tok->ctx) + +ast_value* parser_find_global(parser_t *parser, const char *name) +{ + size_t i; + for (i = 0; i < parser->globals_count; ++i) { + if (!strcmp(parser->globals[i]->name, name)) + return parser->globals[i]; + } + return NULL; +} + bool parser_do(parser_t *parser) { + if (parser->tok == TOKEN_TYPENAME) + { + ast_value *var; + int vtype = parser->lex->tok->constval.t; + + /* Declaring a variable */ + if (!parser_next(parser)) + return false; + + if (parser->tok != TOKEN_IDENT) { + parseerror(parser, "expected variable name\n"); + return false; + } + + var = parser_find_global(parser, parser_tokval(parser)); + + if (var) { + parseerror(parser, "global already exists: %s\n", parser_tokval(parser)); + return false; + } + + var = ast_value_new(parser_ctx(parser), parser_tokval(parser), vtype); + if (!parser_t_globals_add(parser, var)) + return false; + + /* Constant assignment */ + if (!parser_next(parser)) + return false; + + if (parser->tok == ';') + return parser_next(parser); + + if (parser->tok != '=') { + parseerror(parser, "expected '=' or ';'"); + return false; + } + + /* '=' found, assign... */ + parseerror(parser, "TODO, const assignment"); + return false; + } + else if (parser->tok == TOKEN_KEYWORD) + { + /* handle 'var' and 'const' */ + return false; + } + else if (parser->tok == '.') + { + /* entity-member declaration */ + return false; + } + else + { + parseerror(parser, "unexpected token: %s", parser->lex->tok->value); + return false; + } return true; } bool parser_compile(const char *filename) { + size_t i; parser_t *parser; parser = (parser_t*)mem_a(sizeof(parser_t)); if (!parser) return false; + MEM_VECTOR_INIT(parser, globals); parser->lex = lex_open(filename); if (!parser->lex) { @@ -26,19 +138,28 @@ bool parser_compile(const char *filename) return false; } - for (parser->tok = lex_do(parser->lex); - parser->tok != TOKEN_EOF && parser->tok < TOKEN_ERROR; - parser->tok = lex_do(parser->lex)) + /* initial lexer/parser state */ + parser->lex->flags.noops = true; + + if (parser_next(parser)) { - if (!parser_do(parser)) { - printf("parse error\n"); - lex_close(parser->lex); - mem_d(parser); - return false; + while (parser->tok != TOKEN_EOF && parser->tok < TOKEN_ERROR) + { + if (!parser_do(parser)) { + printf("parse error\n"); + lex_close(parser->lex); + mem_d(parser); + return false; + } } } lex_close(parser->lex); + for (i = 0; i < parser->globals_count; ++i) { + ast_value_delete(parser->globals[i]); + } + MEM_VECTOR_CLEAR(parser, globals); + mem_d(parser); return true; } -- 2.39.2