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
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)

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(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);

17
gmqcc.h
View file

@ -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? */
};
/*

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 */
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);
}

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);
} 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);
}

186
parse.c
View file

@ -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 "<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.

View 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 */
}
}

View 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;