]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
More parsing stuff (still totally broken)
authorDale Weiler <killfieldengine@gmail.com>
Wed, 11 Apr 2012 23:41:04 +0000 (19:41 -0400)
committerDale Weiler <killfieldengine@gmail.com>
Wed, 11 Apr 2012 23:41:04 +0000 (19:41 -0400)
Makefile
code.c
gmqcc.h
lex.c
main.c
parse.c
test/if.qc
test/types.qc

index 051ea18d088784fdf3a506082e36d3ed1a1e49de..6ce342c00aa64534b0fc94599618fd47815a6d4d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
-CC     = gcc
-CFLAGS = -O3 -Wall
-OBJ    = main.o    \
-         lex.o     \
-         error.o   \
-         parse.o   \
-         typedef.o \
-         util.o    \
-         code.o
+CC      = gcc
+CFLAGS += -Wall
+OBJ     = main.o    \
+          lex.o     \
+          error.o   \
+          parse.o   \
+          typedef.o \
+          util.o    \
+          code.o
 
 %.o: %.c
        $(CC) -c $< -o $@ $(CFLAGS)
diff --git a/code.c b/code.c
index b796b1319937b8a5276cc43263738d18d9eda082..00cf70249384653ca2239cd486477c7e38ecd383 100644 (file)
--- a/code.c
+++ b/code.c
@@ -146,18 +146,29 @@ VECTOR_MAKE(prog_section_field,     code_fields    );
 VECTOR_MAKE(prog_section_function,  code_functions );
 VECTOR_MAKE(int,                    code_globals   );
 VECTOR_MAKE(char,                   code_strings   );
+static uint16_t code_crc16  = 0;
+prog_header     code_header ={0};
 
-/* program header */
-prog_header code_header;
-void code_write() {
-       
-       #if 0
-       /* Add test program */
-       code_strings_add('\0');
-       
-               const char *X;
-               size_t size = sizeof(X);
-               size_t iter = 0;
+void code_init() {
+       /*
+        * The way progs.dat is suppose to work is odd, there needs to be
+        * some null (empty) statements, functions, and 28 globals
+        */
+       prog_section_function  empty_function  = {0,0,0,0,0,0,0,{0}};
+       prog_section_statement empty_statement = {0,{0},{0},{0}};
+       int i;
+       for(i = 0; i < 28; i++)
+               code_globals_add(0);
+               
+       code_strings_add   ('\0');
+       code_functions_add (empty_function);
+       code_statements_add(empty_statement);
+}
+
+void code_test() {
+       const char *X;
+       size_t size = sizeof(X);
+       size_t iter = 0;
        
        #define FOO(Y) \
                X = Y; \
@@ -174,10 +185,6 @@ void code_write() {
        FOO("m_toggle");
        FOO("m_shutdown");
        
-       int i;
-       for (i=0; i<28; i++)
-               code_globals_add(0); /* 28 empty */
-       
        code_globals_add(1);  /* m_init */
        code_globals_add(2);  /* print  */
        code_globals_add(14); /* hello world in string table */
@@ -187,7 +194,6 @@ void code_write() {
        code_defs_add((prog_section_def){.type=TYPE_FUNCTION,.offset=29/*globals[29]*/, .name=8 }); /* print  */
        code_defs_add((prog_section_def){.type=TYPE_STRING,  .offset=30/*globals[30]*/, .name=14}); /*hello_world*/
        
-       code_functions_add((prog_section_function){0,  0, 0, 0, .name=0, 0, 0, {0}}); /* NULL */
        code_functions_add((prog_section_function){1,  0, 0, 0, .name=1, 0, 0, {0}}); /* m_init */
        code_functions_add((prog_section_function){-4, 0, 0, 0, .name=8, 0, 0, {0}}); /* print  */
        code_functions_add((prog_section_function){0,  0, 0, 0, .name=14+13,        0,0, {0}}); /* m_keydown */
@@ -195,10 +201,9 @@ void code_write() {
        code_functions_add((prog_section_function){0,  0, 0, 0, .name=14+13+10+7,   0,0, {0}});
        code_functions_add((prog_section_function){0,  0, 0, 0, .name=14+13+10+7+9, 0,0, {0}});
        
-       code_statements_add((prog_section_statement){0, 0, 0, 0}); /* NULL */
-       code_statements_add((prog_section_statement){INSTR_STORE_F, 30/*30 is hello_world */, OFS_PARM0, 0});
-       code_statements_add((prog_section_statement){INSTR_CALL1,   29/*29 is print       */, 0,         0});
-       code_statements_add((prog_section_statement){INSTR_RETURN,  0,                        0,         0});
+       code_statements_add((prog_section_statement){INSTR_STORE_F, {30}/*30 is hello_world */, {OFS_PARM0}, {0}});
+       code_statements_add((prog_section_statement){INSTR_CALL1,   {29}/*29 is print       */, {0},         {0}});
+       code_statements_add((prog_section_statement){INSTR_RETURN,  {0},                        {0},         {0}});
        
        code_header.version    = 6;
        code_header.crc16      = 0; /* TODO: */
@@ -209,10 +214,13 @@ void code_write() {
        code_header.globals    = (prog_section){code_header.functions.offset  + sizeof(prog_section_function) *code_functions_elements,   code_globals_elements    };
        code_header.strings    = (prog_section){code_header.globals.offset    + sizeof(int)                   *code_globals_elements,     code_strings_elements    };
        code_header.entfield   = 0; /* TODO: */
-       #endif
-
+}
 
-       /* write out everything one SHOT! */
+/* program header */
+void code_write() {
+       code_init();
+       code_test();
+       
        FILE *fp = fopen("program.dat", "wb");
        fwrite(&code_header,         1, sizeof(prog_header), fp);
        fwrite(code_statements_data, 1, sizeof(prog_section_statement)*code_statements_elements, fp);
diff --git a/gmqcc.h b/gmqcc.h
index 853eb3315e581ff7ea81afbf43e3890931468958..e8e3df055fee3c2ea6166f4a907a8bf2ba29a548 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
 //============================ lex.c ================================
 //===================================================================
 struct lex_file {
-       FILE *file;
-       char  peek  [5];
+       FILE *file;        /* file handler */
+       char *name;        /* name of file */
+       char  peek  [5];  
        char  lastok[8192];
        
-       int   line;
-       int   last;
-       int   current;
-       int   length;
-       int   size;
+       
+       int   last;    /* last token                   */
+       int   current; /* current token                */
+       
+       int   length;  /* bytes left to parse          */
+       int   size;    /* never changes (size of file) */
+       int   line;    /* what line are we on?         */
 };
 
 /*
diff --git a/lex.c b/lex.c
index 4e84bcec7f42ccf10eb6f78b2881f82819b6153c..7c8044b8ecd8e8819dfda4c77960d6a2ba1f31d5 100644 (file)
--- a/lex.c
+++ b/lex.c
@@ -48,6 +48,7 @@ struct lex_file *lex_open(FILE *fp) {
        lex->size   = lex->length; /* copy, this is never changed */
        fseek(lex->file, 0, SEEK_SET);
        lex->last = 0;
+       lex->line = 1;
        
        memset(lex->peek, 0, sizeof(lex->peek));
        return lex;
@@ -276,7 +277,7 @@ int lex_token(struct lex_file *file) {
        /* valid identifier */
        if (ch > 0 && (ch == '_' || isalpha(ch))) {
                lex_clear(file);
-               while (ch > 0 && (isalpha(ch) || ch == '_')) {
+               while (ch > 0 && ch != ' ' && ch != '(' && ch != '\n') {
                        lex_addch(ch, file);
                        ch = lex_getsource(file);
                }
diff --git a/main.c b/main.c
index 5b9828832743bc85e2fabc0116374fd8fb10803c..754a165791d3b62d97e2824e00e5ca78e5b2a080 100644 (file)
--- a/main.c
+++ b/main.c
@@ -36,11 +36,13 @@ int main(int argc, char **argv) {
                return error(ERROR_COMPILER, "Source file: %s not found\n", ifile);
        } else {
                struct lex_file *lex = lex_open(fp);
+               lex->name = util_strdup(ifile);
                if (!lex) {
                        fclose(fp);
                        return 0;
                }
                parse_tree(lex);
+               mem_d(lex->name);
                lex_close (lex);
        }
        
diff --git a/parse.c b/parse.c
index af6c6229a1dc246a82796909f4dcb3ed11467c7a..54dd2f0658180db8568b7717c3893c378c00cf88 100644 (file)
--- a/parse.c
+++ b/parse.c
        "." , "<" , ">" , "&" , "|" , 
 #endif
 
-#define STORE(X) {  \
-       printf(X);      \
-       break;          \
+#define STORE(X,C) {  \
+    long f = fill;    \
+    while(f--) {      \
+      putchar(' ');   \
+    }                 \
+    fill C;           \
+       printf(X);        \
+       break;            \
 }
 
 void parse_debug(struct parsenode *tree) {
+       long fill = 0;
        while (tree) {  
                switch (tree->type) {
-                       case PARSE_TYPE_ADD:       STORE("OPERATOR:  ADD    \n");
-                       case PARSE_TYPE_BAND:      STORE("OPERATOR:  BITAND \n");
-                       case PARSE_TYPE_BOR:       STORE("OPERATOR:  BITOR  \n");
-                       case PARSE_TYPE_COMMA:     STORE("OPERATOR:  SEPERATOR\n");
-                       case PARSE_TYPE_DOT:       STORE("OPERATOR:  DOT\n");
-                       case PARSE_TYPE_DIVIDE:    STORE("OPERATOR:  DIVIDE\n");
-                       case PARSE_TYPE_EQUAL:     STORE("OPERATOR:  ASSIGNMENT\n");
+                       case PARSE_TYPE_ADD:       STORE("OPERATOR:  ADD    \n", -=0);
+                       case PARSE_TYPE_BAND:      STORE("OPERATOR:  BITAND \n",-=0);
+                       case PARSE_TYPE_BOR:       STORE("OPERATOR:  BITOR  \n",-=0);
+                       case PARSE_TYPE_COMMA:     STORE("OPERATOR:  SEPERATOR\n",-=0);
+                       case PARSE_TYPE_DOT:       STORE("OPERATOR:  DOT\n",-=0);
+                       case PARSE_TYPE_DIVIDE:    STORE("OPERATOR:  DIVIDE\n",-=0);
+                       case PARSE_TYPE_EQUAL:     STORE("OPERATOR:  ASSIGNMENT\n",-=0);
                        
-                       case PARSE_TYPE_BREAK:     STORE("STATEMENT: BREAK  \n");
-                       case PARSE_TYPE_CONTINUE:  STORE("STATEMENT: CONTINUE\n");
-                       case PARSE_TYPE_GOTO:      STORE("STATEMENT: GOTO\n");
-                       case PARSE_TYPE_RETURN:    STORE("STATEMENT: RETURN\n");
-                       case PARSE_TYPE_DONE:      STORE("STATEMENT: DONE\n");
+                       case PARSE_TYPE_BREAK:     STORE("STATEMENT: BREAK  \n",-=0);
+                       case PARSE_TYPE_CONTINUE:  STORE("STATEMENT: CONTINUE\n",-=0);
+                       case PARSE_TYPE_GOTO:      STORE("STATEMENT: GOTO\n",-=0);
+                       case PARSE_TYPE_RETURN:    STORE("STATEMENT: RETURN\n",-=0);
+                       case PARSE_TYPE_DONE:      STORE("STATEMENT: DONE\n",-=0);
 
-                       case PARSE_TYPE_VOID:      STORE("DECLTYPE:  VOID\n");
-                       case PARSE_TYPE_STRING:    STORE("DECLTYPE:  STRING\n");
-                       case PARSE_TYPE_ELIP:      STORE("DECLTYPE:  VALIST\n");
-                       case PARSE_TYPE_ENTITY:    STORE("DECLTYPE:  ENTITY\n");
-                       case PARSE_TYPE_FLOAT:     STORE("DECLTYPE:  FLOAT\n");
-                       case PARSE_TYPE_VECTOR:    STORE("DECLTYPE:  VECTOR\n");
+                       case PARSE_TYPE_VOID:      STORE("DECLTYPE:  VOID\n",-=0);
+                       case PARSE_TYPE_STRING:    STORE("DECLTYPE:  STRING\n",-=0);
+                       case PARSE_TYPE_ELIP:      STORE("DECLTYPE:  VALIST\n",-=0);
+                       case PARSE_TYPE_ENTITY:    STORE("DECLTYPE:  ENTITY\n",-=0);
+                       case PARSE_TYPE_FLOAT:     STORE("DECLTYPE:  FLOAT\n",-=0);
+                       case PARSE_TYPE_VECTOR:    STORE("DECLTYPE:  VECTOR\n",-=0);
                        
-                       case PARSE_TYPE_GT:        STORE("TEST:      GREATER THAN\n");
-                       case PARSE_TYPE_LT:        STORE("TEST:      LESS THAN\n");
-                       case PARSE_TYPE_GTEQ:      STORE("TEST:      GREATER THAN OR EQUAL\n");
-                       case PARSE_TYPE_LTEQ:      STORE("TEST:      LESS THAN OR EQUAL\n");
-                       case PARSE_TYPE_LNEQ:      STORE("TEST:      NOT EQUAL\n");
-                       case PARSE_TYPE_EQEQ:      STORE("TEST:      EQUAL-EQUAL\n");
+                       case PARSE_TYPE_GT:        STORE("TEST:      GREATER THAN\n",-=0);
+                       case PARSE_TYPE_LT:        STORE("TEST:      LESS THAN\n",-=0);
+                       case PARSE_TYPE_GTEQ:      STORE("TEST:      GREATER THAN OR EQUAL\n",-=0);
+                       case PARSE_TYPE_LTEQ:      STORE("TEST:      LESS THAN OR EQUAL\n",-=0);
+                       case PARSE_TYPE_LNEQ:      STORE("TEST:      NOT EQUAL\n",-=0);
+                       case PARSE_TYPE_EQEQ:      STORE("TEST:      EQUAL-EQUAL\n",-=0);
                        
-                       case PARSE_TYPE_LBS:       STORE("BLOCK:     BEG\n");
-                       case PARSE_TYPE_RBS:       STORE("BLOCK:     END\n");
-                       case PARSE_TYPE_ELSE:      STORE("BLOCK:     ELSE\n");
-                       case PARSE_TYPE_IF:        STORE("BLOCK:     IF\n");
+                       case PARSE_TYPE_LBS:       STORE("BLOCK:     BEG\n",+=4);
+                       case PARSE_TYPE_RBS:       STORE("BLOCK:     END\n",-=4);
+                       case PARSE_TYPE_ELSE:      STORE("BLOCK:     ELSE\n",+=0);
+                       case PARSE_TYPE_IF:        STORE("BLOCK:     IF\n",+=0);
                        
-                       case PARSE_TYPE_LAND:      STORE("LOGICAL:   AND\n");
-                       case PARSE_TYPE_LNOT:      STORE("LOGICAL:   NOT\n");
-                       case PARSE_TYPE_LOR:       STORE("LOGICAL:   OR\n");
+                       case PARSE_TYPE_LAND:      STORE("LOGICAL:   AND\n",-=0);
+                       case PARSE_TYPE_LNOT:      STORE("LOGICAL:   NOT\n",-=0);
+                       case PARSE_TYPE_LOR:       STORE("LOGICAL:   OR\n",-=0);
                        
-                       case PARSE_TYPE_LPARTH:    STORE("PARTH:     BEG\n");
-                       case PARSE_TYPE_RPARTH:    STORE("PARTH:     END\n");
+                       case PARSE_TYPE_LPARTH:    STORE("PARTH:     BEG\n",-=0);
+                       case PARSE_TYPE_RPARTH:    STORE("PARTH:     END\n",-=0);
                        
-                       case PARSE_TYPE_WHILE:     STORE("LOOP:      WHILE\n");
-                       case PARSE_TYPE_FOR:       STORE("LOOP:      FOR\n");
-                       case PARSE_TYPE_DO:        STORE("LOOP:      DO\n");
-                       
-                       //case PARSE_TYPE_IDENT:     STORE("IDENT:     ???\n");
+                       case PARSE_TYPE_WHILE:     STORE("LOOP:      WHILE\n",-=0);
+                       case PARSE_TYPE_FOR:       STORE("LOOP:      FOR\n",-=0);
+                       case PARSE_TYPE_DO:        STORE("LOOP:      DO\n",-=0);
                }
                tree = tree->next;
        }
@@ -181,6 +185,23 @@ void parse_clear(struct parsenode *tree) {
        typedef_clear();
 }
 
+const char *STRING_(char ch) {
+       if (ch == ' ')
+               return "<space>";
+       if (ch == '\n')
+               return "<newline>";
+       if (ch == '\0')
+               return "<null>";
+               
+       return &ch;
+}
+
+#define TOKEN_SKIPWHITE()        \
+       token = lex_token(file);     \
+       while (token == ' ') {       \
+               token = lex_token(file); \
+       }
+
 /*
  * Generates a parse tree out of the lexees generated by the lexer.  This
  * is where the tree is built.  This is where valid check is performed.
@@ -210,9 +231,9 @@ int parse_tree(struct lex_file *file) {
                    token                    != ERROR_PREPRO   && file->length >= 0) {
                switch (token) {
                        case TOKEN_IF:
-                               token = lex_token(file);
+                               TOKEN_SKIPWHITE();
                                if (token != '(')
-                                       error(ERROR_PARSE, "Expected `(` on if statement:\n");
+                                       error(ERROR_PARSE, "%s:%d Expected `(` after `if` for if statement\n", file->name, file->line);
                                PARSE_TREE_ADD(PARSE_TYPE_IF);
                                PARSE_TREE_ADD(PARSE_TYPE_LPARTH);
                                break;
@@ -221,7 +242,6 @@ int parse_tree(struct lex_file *file) {
                                PARSE_TREE_ADD(PARSE_TYPE_ELSE);
                                break;
                        case TOKEN_FOR:
-                               //token = lex_token(file);
                                while ((token == ' ' || token == '\n') && file->length >= 0)
                                        token = lex_token(file);
                                PARSE_TREE_ADD(PARSE_TYPE_FOR);
@@ -267,10 +287,70 @@ int parse_tree(struct lex_file *file) {
                        case TOKEN_BREAK:     PARSE_PERFORM(PARSE_TYPE_BREAK,   {});
                        case TOKEN_GOTO:      PARSE_PERFORM(PARSE_TYPE_GOTO,    {});
                        case TOKEN_VOID:      PARSE_PERFORM(PARSE_TYPE_VOID,    {});
-                       case TOKEN_STRING:    PARSE_PERFORM(PARSE_TYPE_STRING,  {});
-                       case TOKEN_FLOAT:     PARSE_PERFORM(PARSE_TYPE_FLOAT,   {});
-                       case TOKEN_VECTOR:    PARSE_PERFORM(PARSE_TYPE_VECTOR,  {});
-                       case TOKEN_ENTITY:    PARSE_PERFORM(PARSE_TYPE_ENTITY,  {});
+                       
+                       case TOKEN_STRING:    PARSE_TREE_ADD(PARSE_TYPE_STRING);
+                       case TOKEN_VECTOR:    PARSE_TREE_ADD(PARSE_TYPE_VECTOR);
+                       case TOKEN_ENTITY:    PARSE_TREE_ADD(PARSE_TYPE_ENTITY);
+                       case TOKEN_FLOAT:     PARSE_TREE_ADD(PARSE_TYPE_FLOAT);
+                       /* fall into this for all types */
+                       {
+                               char *name = NULL;
+                               TOKEN_SKIPWHITE();
+                               name  = util_strdup(file->lastok);
+                               //token = lex_token  (file);
+                               
+                               /* is it NOT a definition? */
+                               if (token != ';') {
+                                       while (token == ' ')
+                                               token = lex_token(file);
+                                       
+                                       /* it's a function? */
+                                       if (token == '(') {
+                                               /*
+                                                * Now I essentially have to do a ton of parsing for
+                                                * function definition.
+                                                */
+                                               PARSE_TREE_ADD(PARSE_TYPE_LPARTH);
+                                               token = lex_token(file);
+                                               while (token != '\n' && token != ')') {
+                                                       switch (token) {
+                                                               case TOKEN_VOID:    PARSE_TREE_ADD(PARSE_TYPE_VOID);   break;
+                                                               case TOKEN_STRING:  PARSE_TREE_ADD(PARSE_TYPE_STRING); break;
+                                                               case TOKEN_ENTITY:  PARSE_TREE_ADD(PARSE_TYPE_ENTITY); break;
+                                                               case TOKEN_FLOAT:   PARSE_TREE_ADD(PARSE_TYPE_FLOAT);  break;
+                                                               /*
+                                                                * TODO:  Need to parse function pointers:  I have no clue how
+                                                                * I'm actually going to pull that off, it's going to be hard
+                                                                * since you can have a function pointer-pointer-pointer ....
+                                                                */
+                                                       }
+                                               }
+                                               /* just a definition */
+                                               if (token == ')') {
+                                                       /*
+                                                        * I like to put my { on the same line as the ) for
+                                                        * functions, ifs, elses, so we must support that!.
+                                                        */
+                                                       PARSE_TREE_ADD(PARSE_TYPE_RPARTH);
+                                                       token = lex_token(file);
+                                                       token = lex_token(file);
+                                                       if(token == '{')
+                                                               PARSE_TREE_ADD(PARSE_TYPE_LBS);
+                                               }
+                                               else if (token == '\n')
+                                                       error(ERROR_COMPILER, "%s:%d Expecting `;` after function definition %s\n", file->name, file->line, name);
+                                                        
+                                       } else if (token == '=') {
+                                               PARSE_TREE_ADD(PARSE_TYPE_EQUAL);
+                                       } else {
+                                               error(ERROR_COMPILER, "%s:%d Invalid decltype: expected `(` [function], or `=` [constant] for %s\n", file->name, file->line, name);
+                                       } 
+                               } else {
+                                       /* definition */
+                                       printf("FOUND DEFINITION\n");
+                               }
+                               mem_d(name);
+                       }
                                
                        /*
                         * From here down is all language punctuation:  There is no
@@ -281,11 +361,11 @@ int parse_tree(struct lex_file *file) {
                         */
                        case '#':
                                token = lex_token(file); /* skip '#' */
-                               while (isspace(token)) {
-                                       if (token == '\n')
-                                               return error(ERROR_PARSE, "Expected valid preprocessor directive after `#` %s\n");
-                                       token = lex_token(file); /* try again */
-                               }
+                               //while (isspace(token)) {
+                               //      if (token == '\n')
+                               //              return error(ERROR_PARSE, "Expected valid preprocessor directive after `#` %s\n");
+                               //      token = lex_token(file); /* try again */
+                               //}
                                /*
                                 * If we make it here we found a directive, the supported
                                 * directives so far are #include.
index 43d8e79fcc01a605551efd32f9b2066c92fb5e6a..9ef72343bf976cda17a5d65fd154ac5a7f958609 100644 (file)
@@ -1,5 +1,9 @@
-float test_if() {
-       if (1 == 1) {
+float test_1data = 1;
+float test_2data = 2;
+
+float test_if()
+{
+       if (test_1data == test_2data) {
                /* do this code */
        }
 }
index a0234a503c90b1f601725d28df2f49b0c6ab983b..814ce11ee59f5ae538211dfd27c22a2818fb4c7c 100644 (file)
@@ -1,5 +1,5 @@
-float  type_float;
-vector type_vector;
-string type_string;
-entity type_entity;
-void   type_void;
+float  typef;
+vector typev;
+string types;
+entity typee;
+void   typev;