diff options
Diffstat (limited to 'ecomp-c/ec.c')
-rw-r--r-- | ecomp-c/ec.c | 112 |
1 files changed, 93 insertions, 19 deletions
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c index 1fc0dd6..5ec97cc 100644 --- a/ecomp-c/ec.c +++ b/ecomp-c/ec.c @@ -17,7 +17,7 @@ enum { }; static int DEBUG_GETCHAR = 0; -static int DEBUG_SCANNER = 0; +static int DEBUG_SCANNER = 1; typedef enum { BINARY_FORMAT_EMUL = 0, @@ -45,6 +45,8 @@ typedef enum { S_else, S_while, S_procedure, + S_function, + S_return, S_div, S_mod, S_not, @@ -88,6 +90,8 @@ static char *symname[S_eof+1] = { "else", "while", "procedure", + "function", + "return", "div", "mod", "not", @@ -405,6 +409,14 @@ static S_Symbol getSym( void ) s = S_ident; } break; + case 'f': + identifier( ); + if( strcmp( ident, "function" ) == 0 ) { + s = S_function; + } else { + s = S_ident; + } + break; case 'i': identifier( ); if( strcmp( ident, "if" ) == 0 ) { @@ -449,6 +461,14 @@ static S_Symbol getSym( void ) s = S_ident; } break; + case 'r': + identifier( ); + if( strcmp( ident, "return" ) == 0 ) { + s = S_return; + } else { + s = S_ident; + } + break; case 'v': identifier( ); if( strcmp( ident, "var" ) == 0 ) { @@ -465,14 +485,12 @@ static S_Symbol getSym( void ) s = S_ident; } break; - case 'f': case 'g': case 'h': case 'j': case 'k': case 'l': case 'q': - case 'r': case 's': case 't': case 'u': @@ -678,10 +696,12 @@ typedef struct Symbol { int offset; /* array type */ int dim; - /* procedure type */ + /* procedure/function type */ char *label; struct Scope *scope; struct Symbol *param; + int is_func; + struct Symbol *return_type; } Symbol; static Symbol *integer_type; @@ -805,6 +825,8 @@ static Symbol *create_symbol( char *name, SymbolClass class ) symbol->type = NULL; symbol->label = NULL; symbol->param = NULL; + symbol->is_func = 0; + symbol->return_type = NULL; return symbol; } @@ -1235,6 +1257,7 @@ static void emit_expression_code( ExpressionNode *node, Scope *scope ) } static ExpressionNode *parseExpression( Scope *scope ); +static void parseParameterList( Scope *scope, ExpressionNodeList *list ); static ExpressionNode *parseFactor( Scope *scope ) { @@ -1292,6 +1315,16 @@ static ExpressionNode *parseFactor( Scope *scope ) node->symbol = symbol; node->actual_type = symbol->type; } + } else if( symbol->class == SYMBOL_CLASS_PROCEDURE_TYPE ) { + sym = getSym( ); + if( !symbol->is_func ) { + Abort( "Expecting function and not procedure" ); + } + /* TODO: parse parameters as in a procedure call + parseProcedureCall + then add result into expression, problem here is + we generate code directly in parseProcedureCall and + not an ADT before, must refactor */ } else { Abort( "'%s' is the name for a type and not a constant or variable as expected", ident ); } @@ -1634,7 +1667,7 @@ static void parseProcedureCall( Scope *scope ) } nof_actual_params = 0; - if( sym == S_lparen ) { + if( sym == S_lparen ) { parseParameterList( scope, &list ); node = list.head; @@ -1726,20 +1759,13 @@ static void parseStatementSequence( Scope *scope ) } while( sym == S_semicolon ) { sym = getSym( ); - if( sym == S_end || sym == S_else ) { + if( sym == S_end || sym == S_else || sym == S_return ) { return; } parseStatement( scope ); } } -static void parseStatementBlock( Scope *scope ) -{ - Expect( S_begin ); - parseStatementSequence( scope ); - Expect( S_end ); -} - /* TODO: implement simple expression and later complex expression */ static ExpressionNode *parseConstExpression( Scope *scope ) { @@ -2171,10 +2197,11 @@ static void parseProcedureDeclaration( Scope *scope ) Symbol *symbol; int size_locals; int size_params = 0; - - Expect( S_procedure ); + S_Symbol proc_sym = sym; + + sym = getSym( ); if( sym != S_ident ) { - Abort( "Expecting name of a procedure after 'procedure'" ); + Abort( "Expecting name of a procedure or function after '%s'", symname[proc_sym] ); } symbol = get_symbol( scope, ident ); @@ -2183,6 +2210,11 @@ static void parseProcedureDeclaration( Scope *scope ) procedure_label = get_scoped_label( scope, ident ); symbol->label = AllocateAndCopyStr( procedure_label ); free( procedure_label ); + if( proc_sym == S_procedure ) { + symbol->is_func = 0; + } else if( proc_sym == S_function ) { + symbol->is_func = 1; + } } else if( symbol->class == SYMBOL_CLASS_PROCEDURE_TYPE ) { /* TODO: check, if parameter lists and return values match */ } @@ -2201,6 +2233,16 @@ static void parseProcedureDeclaration( Scope *scope ) int offset; parseParameterDeclarationList( symbol->scope ); + + if( sym == S_colon ) { + if( symbol->is_func ) { + symbol->return_type = parseType( scope ); + sym = getSym( ); + } else { + Abort( "A procedure cannot have a return type" ); + } + } + if( sym == S_semicolon ) { /* forward declaration */ sym = getSym( ); @@ -2216,6 +2258,10 @@ static void parseProcedureDeclaration( Scope *scope ) while( param != NULL ) { if( param->class == SYMBOL_CLASS_VARIABLE ) { int size = get_size( param ); + if( size < 4 ) { + /* parameters on stack are always 4 bytes */ + size = 4; + } size_params += size; param->offset = offset - size; Emit( "; param %s, offset: %d, size: %d\n", @@ -2269,10 +2315,20 @@ static void parseProcedureDeclaration( Scope *scope ) } param = param->next; } + } + } else if( sym == S_colon ) { + if( symbol->is_func ) { + symbol->return_type = parseType( scope ); + } else { + Abort( "A procedure cannot have a return type" ); } } else { Abort( "Semicolon expected" ); } + + if( symbol->is_func && symbol->return_type == NULL ) { + Abort( "A function must have a return type" ); + } /* procedure body */ if( sym == S_const || sym == S_var || sym == S_begin ) { @@ -2363,7 +2419,23 @@ static void parseProcedureDeclaration( Scope *scope ) /* TODO: assign symbols to relative addresses (base pointer) */ /* TODO: initialize local variables */ - parseStatementBlock( symbol->scope ); + Expect( S_begin ); + parseStatementSequence( symbol->scope ); + if( symbol->is_func ) { + ExpressionNode *node = NULL; + Expect( S_return ); + node = parseExpression( symbol->scope ); + if( sym == S_semicolon ) { + sym = getSym( ); + } + (void)node; + /* TODO: add parsing return with local here, emit code + * for returning function value (what convention are + * we going to apply? stack? register? + */ + } + Expect( S_end ); + /* discard locals, restore base pointer, discard params */ if( size_locals > 0 ) { @@ -2387,7 +2459,7 @@ static void parseProcedureDeclaration( Scope *scope ) static void parseProcedureBlock( Scope *scope ) { - while( sym == S_procedure ) { + while( sym == S_procedure || sym == S_function ) { parseProcedureDeclaration( scope ); } } @@ -2423,7 +2495,9 @@ static void parseModule( Scope *scope ) parseDeclarationBlock( scope ); Emit( "%s:\n", entry_label ); - parseStatementBlock( scope ); + Expect( S_begin ); + parseStatementSequence( scope ); + Expect( S_end ); free( entry_label ); } |