]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Reading a global def
authorWolfgang Bumiller <wolfgang.linux@bumiller.com>
Mon, 16 Jul 2012 12:52:52 +0000 (14:52 +0200)
committerWolfgang Bumiller <wolfgang.linux@bumiller.com>
Mon, 16 Jul 2012 12:52:52 +0000 (14:52 +0200)
lexer.c
parser.c

diff --git a/lexer.c b/lexer.c
index 2c6bcb0b9ebc94b3309816fec313ed95af3b6218..5c98d31caedbcf1f95fba984d871686558cc0f5d 100644 (file)
--- 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;
index c753c59aa782325d9755fd195ec837a57d1ecd31..896c729d854c11664f4b0e9a8e9803b28bf28641 100644 (file)
--- a/parser.c
+++ b/parser.c
+#include <stdio.h>
+#include <stdarg.h>
+
 #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;
 }