From: Dale Weiler Date: Wed, 11 Apr 2012 23:41:04 +0000 (-0400) Subject: More parsing stuff (still totally broken) X-Git-Tag: 0.1-rc1~681 X-Git-Url: https://git.xonotic.org/?a=commitdiff_plain;h=e4bc0a2d6a6c35c67f8920c555c3564e6002de84;p=xonotic%2Fgmqcc.git More parsing stuff (still totally broken) --- diff --git a/Makefile b/Makefile index 051ea18..6ce342c 100644 --- 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 b796b13..00cf702 100644 --- 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 853eb33..e8e3df0 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -28,15 +28,18 @@ //============================ 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 4e84bce..7c8044b 100644 --- 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 5b98288..754a165 100644 --- 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 af6c622..54dd2f0 100644 --- a/parse.c +++ b/parse.c @@ -93,59 +93,63 @@ "." , "<" , ">" , "&" , "|" , #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 ""; + if (ch == '\n') + return ""; + if (ch == '\0') + return ""; + + 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. diff --git a/test/if.qc b/test/if.qc index 43d8e79..9ef7234 100644 --- a/test/if.qc +++ b/test/if.qc @@ -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 */ } } diff --git a/test/types.qc b/test/types.qc index a0234a5..814ce11 100644 --- a/test/types.qc +++ b/test/types.qc @@ -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;