More parsing stuff (still totally broken)

This commit is contained in:
Dale Weiler 2012-04-11 19:41:04 -04:00
parent e4e6185d5f
commit e4bc0a2d6a
8 changed files with 198 additions and 100 deletions

View file

@ -1,12 +1,12 @@
CC = gcc CC = gcc
CFLAGS = -O3 -Wall CFLAGS += -Wall
OBJ = main.o \ OBJ = main.o \
lex.o \ lex.o \
error.o \ error.o \
parse.o \ parse.o \
typedef.o \ typedef.o \
util.o \ util.o \
code.o code.o
%.o: %.c %.o: %.c
$(CC) -c $< -o $@ $(CFLAGS) $(CC) -c $< -o $@ $(CFLAGS)

54
code.c
View file

@ -146,18 +146,29 @@ VECTOR_MAKE(prog_section_field, code_fields );
VECTOR_MAKE(prog_section_function, code_functions ); VECTOR_MAKE(prog_section_function, code_functions );
VECTOR_MAKE(int, code_globals ); VECTOR_MAKE(int, code_globals );
VECTOR_MAKE(char, code_strings ); VECTOR_MAKE(char, code_strings );
static uint16_t code_crc16 = 0;
prog_header code_header ={0};
/* program header */ void code_init() {
prog_header code_header; /*
void code_write() { * The way progs.dat is suppose to work is odd, there needs to be
* some null (empty) statements, functions, and 28 globals
#if 0 */
/* Add test program */ prog_section_function empty_function = {0,0,0,0,0,0,0,{0}};
code_strings_add('\0'); prog_section_statement empty_statement = {0,{0},{0},{0}};
int i;
const char *X; for(i = 0; i < 28; i++)
size_t size = sizeof(X); code_globals_add(0);
size_t iter = 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) \ #define FOO(Y) \
X = Y; \ X = Y; \
@ -174,10 +185,6 @@ void code_write() {
FOO("m_toggle"); FOO("m_toggle");
FOO("m_shutdown"); 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(1); /* m_init */
code_globals_add(2); /* print */ code_globals_add(2); /* print */
code_globals_add(14); /* hello world in string table */ 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_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_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){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){-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 */ 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, 0,0, {0}});
code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10+7+9, 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_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_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_RETURN, 0, 0, 0});
code_header.version = 6; code_header.version = 6;
code_header.crc16 = 0; /* TODO: */ 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.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.strings = (prog_section){code_header.globals.offset + sizeof(int) *code_globals_elements, code_strings_elements };
code_header.entfield = 0; /* TODO: */ code_header.entfield = 0; /* TODO: */
#endif }
/* program header */
/* write out everything one SHOT! */ void code_write() {
code_init();
code_test();
FILE *fp = fopen("program.dat", "wb"); FILE *fp = fopen("program.dat", "wb");
fwrite(&code_header, 1, sizeof(prog_header), fp); fwrite(&code_header, 1, sizeof(prog_header), fp);
fwrite(code_statements_data, 1, sizeof(prog_section_statement)*code_statements_elements, fp); fwrite(code_statements_data, 1, sizeof(prog_section_statement)*code_statements_elements, fp);

17
gmqcc.h
View file

@ -28,15 +28,18 @@
//============================ lex.c ================================ //============================ lex.c ================================
//=================================================================== //===================================================================
struct lex_file { struct lex_file {
FILE *file; FILE *file; /* file handler */
char peek [5]; char *name; /* name of file */
char peek [5];
char lastok[8192]; char lastok[8192];
int line;
int last; int last; /* last token */
int current; int current; /* current token */
int length;
int size; int length; /* bytes left to parse */
int size; /* never changes (size of file) */
int line; /* what line are we on? */
}; };
/* /*

3
lex.c
View file

@ -48,6 +48,7 @@ struct lex_file *lex_open(FILE *fp) {
lex->size = lex->length; /* copy, this is never changed */ lex->size = lex->length; /* copy, this is never changed */
fseek(lex->file, 0, SEEK_SET); fseek(lex->file, 0, SEEK_SET);
lex->last = 0; lex->last = 0;
lex->line = 1;
memset(lex->peek, 0, sizeof(lex->peek)); memset(lex->peek, 0, sizeof(lex->peek));
return lex; return lex;
@ -276,7 +277,7 @@ int lex_token(struct lex_file *file) {
/* valid identifier */ /* valid identifier */
if (ch > 0 && (ch == '_' || isalpha(ch))) { if (ch > 0 && (ch == '_' || isalpha(ch))) {
lex_clear(file); lex_clear(file);
while (ch > 0 && (isalpha(ch) || ch == '_')) { while (ch > 0 && ch != ' ' && ch != '(' && ch != '\n') {
lex_addch(ch, file); lex_addch(ch, file);
ch = lex_getsource(file); ch = lex_getsource(file);
} }

2
main.c
View file

@ -36,11 +36,13 @@ int main(int argc, char **argv) {
return error(ERROR_COMPILER, "Source file: %s not found\n", ifile); return error(ERROR_COMPILER, "Source file: %s not found\n", ifile);
} else { } else {
struct lex_file *lex = lex_open(fp); struct lex_file *lex = lex_open(fp);
lex->name = util_strdup(ifile);
if (!lex) { if (!lex) {
fclose(fp); fclose(fp);
return 0; return 0;
} }
parse_tree(lex); parse_tree(lex);
mem_d(lex->name);
lex_close (lex); lex_close (lex);
} }

186
parse.c
View file

@ -93,59 +93,63 @@
"." , "<" , ">" , "&" , "|" , "." , "<" , ">" , "&" , "|" ,
#endif #endif
#define STORE(X) { \ #define STORE(X,C) { \
printf(X); \ long f = fill; \
break; \ while(f--) { \
putchar(' '); \
} \
fill C; \
printf(X); \
break; \
} }
void parse_debug(struct parsenode *tree) { void parse_debug(struct parsenode *tree) {
long fill = 0;
while (tree) { while (tree) {
switch (tree->type) { switch (tree->type) {
case PARSE_TYPE_ADD: STORE("OPERATOR: ADD \n"); case PARSE_TYPE_ADD: STORE("OPERATOR: ADD \n", -=0);
case PARSE_TYPE_BAND: STORE("OPERATOR: BITAND \n"); case PARSE_TYPE_BAND: STORE("OPERATOR: BITAND \n",-=0);
case PARSE_TYPE_BOR: STORE("OPERATOR: BITOR \n"); case PARSE_TYPE_BOR: STORE("OPERATOR: BITOR \n",-=0);
case PARSE_TYPE_COMMA: STORE("OPERATOR: SEPERATOR\n"); case PARSE_TYPE_COMMA: STORE("OPERATOR: SEPERATOR\n",-=0);
case PARSE_TYPE_DOT: STORE("OPERATOR: DOT\n"); case PARSE_TYPE_DOT: STORE("OPERATOR: DOT\n",-=0);
case PARSE_TYPE_DIVIDE: STORE("OPERATOR: DIVIDE\n"); case PARSE_TYPE_DIVIDE: STORE("OPERATOR: DIVIDE\n",-=0);
case PARSE_TYPE_EQUAL: STORE("OPERATOR: ASSIGNMENT\n"); case PARSE_TYPE_EQUAL: STORE("OPERATOR: ASSIGNMENT\n",-=0);
case PARSE_TYPE_BREAK: STORE("STATEMENT: BREAK \n"); case PARSE_TYPE_BREAK: STORE("STATEMENT: BREAK \n",-=0);
case PARSE_TYPE_CONTINUE: STORE("STATEMENT: CONTINUE\n"); case PARSE_TYPE_CONTINUE: STORE("STATEMENT: CONTINUE\n",-=0);
case PARSE_TYPE_GOTO: STORE("STATEMENT: GOTO\n"); case PARSE_TYPE_GOTO: STORE("STATEMENT: GOTO\n",-=0);
case PARSE_TYPE_RETURN: STORE("STATEMENT: RETURN\n"); case PARSE_TYPE_RETURN: STORE("STATEMENT: RETURN\n",-=0);
case PARSE_TYPE_DONE: STORE("STATEMENT: DONE\n"); case PARSE_TYPE_DONE: STORE("STATEMENT: DONE\n",-=0);
case PARSE_TYPE_VOID: STORE("DECLTYPE: VOID\n"); case PARSE_TYPE_VOID: STORE("DECLTYPE: VOID\n",-=0);
case PARSE_TYPE_STRING: STORE("DECLTYPE: STRING\n"); case PARSE_TYPE_STRING: STORE("DECLTYPE: STRING\n",-=0);
case PARSE_TYPE_ELIP: STORE("DECLTYPE: VALIST\n"); case PARSE_TYPE_ELIP: STORE("DECLTYPE: VALIST\n",-=0);
case PARSE_TYPE_ENTITY: STORE("DECLTYPE: ENTITY\n"); case PARSE_TYPE_ENTITY: STORE("DECLTYPE: ENTITY\n",-=0);
case PARSE_TYPE_FLOAT: STORE("DECLTYPE: FLOAT\n"); case PARSE_TYPE_FLOAT: STORE("DECLTYPE: FLOAT\n",-=0);
case PARSE_TYPE_VECTOR: STORE("DECLTYPE: VECTOR\n"); case PARSE_TYPE_VECTOR: STORE("DECLTYPE: VECTOR\n",-=0);
case PARSE_TYPE_GT: STORE("TEST: GREATER THAN\n"); case PARSE_TYPE_GT: STORE("TEST: GREATER THAN\n",-=0);
case PARSE_TYPE_LT: STORE("TEST: LESS THAN\n"); case PARSE_TYPE_LT: STORE("TEST: LESS THAN\n",-=0);
case PARSE_TYPE_GTEQ: STORE("TEST: GREATER THAN OR EQUAL\n"); case PARSE_TYPE_GTEQ: STORE("TEST: GREATER THAN OR EQUAL\n",-=0);
case PARSE_TYPE_LTEQ: STORE("TEST: LESS THAN OR EQUAL\n"); case PARSE_TYPE_LTEQ: STORE("TEST: LESS THAN OR EQUAL\n",-=0);
case PARSE_TYPE_LNEQ: STORE("TEST: NOT EQUAL\n"); case PARSE_TYPE_LNEQ: STORE("TEST: NOT EQUAL\n",-=0);
case PARSE_TYPE_EQEQ: STORE("TEST: EQUAL-EQUAL\n"); case PARSE_TYPE_EQEQ: STORE("TEST: EQUAL-EQUAL\n",-=0);
case PARSE_TYPE_LBS: STORE("BLOCK: BEG\n"); case PARSE_TYPE_LBS: STORE("BLOCK: BEG\n",+=4);
case PARSE_TYPE_RBS: STORE("BLOCK: END\n"); case PARSE_TYPE_RBS: STORE("BLOCK: END\n",-=4);
case PARSE_TYPE_ELSE: STORE("BLOCK: ELSE\n"); case PARSE_TYPE_ELSE: STORE("BLOCK: ELSE\n",+=0);
case PARSE_TYPE_IF: STORE("BLOCK: IF\n"); case PARSE_TYPE_IF: STORE("BLOCK: IF\n",+=0);
case PARSE_TYPE_LAND: STORE("LOGICAL: AND\n"); case PARSE_TYPE_LAND: STORE("LOGICAL: AND\n",-=0);
case PARSE_TYPE_LNOT: STORE("LOGICAL: NOT\n"); case PARSE_TYPE_LNOT: STORE("LOGICAL: NOT\n",-=0);
case PARSE_TYPE_LOR: STORE("LOGICAL: OR\n"); case PARSE_TYPE_LOR: STORE("LOGICAL: OR\n",-=0);
case PARSE_TYPE_LPARTH: STORE("PARTH: BEG\n"); case PARSE_TYPE_LPARTH: STORE("PARTH: BEG\n",-=0);
case PARSE_TYPE_RPARTH: STORE("PARTH: END\n"); case PARSE_TYPE_RPARTH: STORE("PARTH: END\n",-=0);
case PARSE_TYPE_WHILE: STORE("LOOP: WHILE\n"); case PARSE_TYPE_WHILE: STORE("LOOP: WHILE\n",-=0);
case PARSE_TYPE_FOR: STORE("LOOP: FOR\n"); case PARSE_TYPE_FOR: STORE("LOOP: FOR\n",-=0);
case PARSE_TYPE_DO: STORE("LOOP: DO\n"); case PARSE_TYPE_DO: STORE("LOOP: DO\n",-=0);
//case PARSE_TYPE_IDENT: STORE("IDENT: ???\n");
} }
tree = tree->next; tree = tree->next;
} }
@ -181,6 +185,23 @@ void parse_clear(struct parsenode *tree) {
typedef_clear(); 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 * 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. * 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) { token != ERROR_PREPRO && file->length >= 0) {
switch (token) { switch (token) {
case TOKEN_IF: case TOKEN_IF:
token = lex_token(file); TOKEN_SKIPWHITE();
if (token != '(') 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_IF);
PARSE_TREE_ADD(PARSE_TYPE_LPARTH); PARSE_TREE_ADD(PARSE_TYPE_LPARTH);
break; break;
@ -221,7 +242,6 @@ int parse_tree(struct lex_file *file) {
PARSE_TREE_ADD(PARSE_TYPE_ELSE); PARSE_TREE_ADD(PARSE_TYPE_ELSE);
break; break;
case TOKEN_FOR: case TOKEN_FOR:
//token = lex_token(file);
while ((token == ' ' || token == '\n') && file->length >= 0) while ((token == ' ' || token == '\n') && file->length >= 0)
token = lex_token(file); token = lex_token(file);
PARSE_TREE_ADD(PARSE_TYPE_FOR); 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_BREAK: PARSE_PERFORM(PARSE_TYPE_BREAK, {});
case TOKEN_GOTO: PARSE_PERFORM(PARSE_TYPE_GOTO, {}); case TOKEN_GOTO: PARSE_PERFORM(PARSE_TYPE_GOTO, {});
case TOKEN_VOID: PARSE_PERFORM(PARSE_TYPE_VOID, {}); 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_STRING: PARSE_TREE_ADD(PARSE_TYPE_STRING);
case TOKEN_VECTOR: PARSE_PERFORM(PARSE_TYPE_VECTOR, {}); case TOKEN_VECTOR: PARSE_TREE_ADD(PARSE_TYPE_VECTOR);
case TOKEN_ENTITY: PARSE_PERFORM(PARSE_TYPE_ENTITY, {}); 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 * From here down is all language punctuation: There is no
@ -281,11 +361,11 @@ int parse_tree(struct lex_file *file) {
*/ */
case '#': case '#':
token = lex_token(file); /* skip '#' */ token = lex_token(file); /* skip '#' */
while (isspace(token)) { //while (isspace(token)) {
if (token == '\n') // if (token == '\n')
return error(ERROR_PARSE, "Expected valid preprocessor directive after `#` %s\n"); // return error(ERROR_PARSE, "Expected valid preprocessor directive after `#` %s\n");
token = lex_token(file); /* try again */ // token = lex_token(file); /* try again */
} //}
/* /*
* If we make it here we found a directive, the supported * If we make it here we found a directive, the supported
* directives so far are #include. * directives so far are #include.

View file

@ -1,5 +1,9 @@
float test_if() { float test_1data = 1;
if (1 == 1) { float test_2data = 2;
float test_if()
{
if (test_1data == test_2data) {
/* do this code */ /* do this code */
} }
} }

View file

@ -1,5 +1,5 @@
float type_float; float typef;
vector type_vector; vector typev;
string type_string; string types;
entity type_entity; entity typee;
void type_void; void typev;