From 01ee6d3e1de75a1aa08afd06f4dafe49d099e77e Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Wed, 29 Sep 2021 20:32:00 +0200 Subject: cc: work on a working if --- miniany/cc.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 107 insertions(+), 9 deletions(-) (limited to 'miniany/cc.c') diff --git a/miniany/cc.c b/miniany/cc.c index 01472c9..c814f3d 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -15,6 +15,8 @@ enum { S_SEMICOLON, S_LPAREN, S_RPAREN, + S_LBRACE, + S_RBRACE, S_ASSIGN, S_EQUALS, S_NOT_EQUALS, @@ -22,10 +24,12 @@ enum { S_LESS_OR_EQUALS, S_MORE, S_MORE_OR_EQUALS, - S_INT = 10, + S_INT = 50, + S_IF, + S_ELSE, S_PUTINT, - S_IDENT = 20, - S_NUM = 30, + S_IDENT = 60, + S_NUM = 70, S_EOI = 98, S_ERR = 99 }; @@ -157,8 +161,18 @@ void scanIdent( struct Scanner *scanner ) int keyword( char *ident ) { switch( ident[0] ) { + case 'e': + if( strcmp( ident, "else" ) == 0 ) { + return S_ELSE; + } else { + return 0; + } + break; + case 'i': - if( strcmp( ident, "int" ) == 0 ) { + if( strcmp( ident, "if" ) == 0 ) { + return S_IF; + } else if( strcmp( ident, "int" ) == 0 ) { return S_INT; } else { return 0; @@ -260,6 +274,12 @@ int getToken( struct Scanner *scanner ) case ')': scanner->token = S_RPAREN; break; + case '{': + scanner->token = S_LBRACE; + break; + case '}': + scanner->token = S_RBRACE; + break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': scanNumber( scanner ); @@ -330,6 +350,7 @@ void freeSymbol( struct Symbol *sym ) struct Scope { char *name; struct Symbol *sym; + int labelNo; }; struct Scope *createScope( char *name ) @@ -339,6 +360,7 @@ struct Scope *createScope( char *name ) scope = (struct Scope *)malloc( sizeof( struct Scope ) ); scope->name = strdup( name ); scope->sym = NULL; + scope->labelNo = 0; return scope; } @@ -1132,7 +1154,7 @@ struct ASTnode *parseExpression( struct Parser *parser, int level ) parser->token = getToken( parser->scanner ); right = parseExpression( parser, parserOperatorPrecedence( parser, op ) ); left = createASTbinary( op, left, right ); - if( parser->token == S_EOI || parser->token == S_SEMICOLON ) { + if( parser->token == S_EOI || parser->token == S_SEMICOLON || parser->token == S_RPAREN ) { return left; } op = parserTokenToOperator( parser, parser->token ); @@ -1209,6 +1231,70 @@ void parsePutint( struct Compiler *compiler ) freeASTnode( node ); } +/* TODO c4: forward reference of function */ +void parseStatementBlock( struct Compiler *compiler ); + +char *genGetLabel( struct Compiler *compiler, struct Scope *scope ) +{ + char *label; + char *s; + + label = (char *)malloc( MAX_IDENT_LEN ); + strlcpy( label, "__", MAX_IDENT_LEN ); + strlcat( label, scope->name, MAX_IDENT_LEN ); + strlcat( label, "_", 1 ); + s = (char *)malloc( MAX_IDENT_LEN ); + itoa( scope->labelNo, s, 10 ); + strlcat( label, s, MAX_IDENT_LEN ); + free( (char *)s ); + scope->labelNo++; + + return label; +} + +void parseIf( struct Compiler *compiler ) +{ + struct Parser *parser; + struct ASTnode *node; + char *label1, *label2; + + parser = compiler->parser; + parserExpect( parser, S_IF, "if" ); + parserExpect( parser, S_LPAREN, "(" ); + node = parseExpression( parser, 0 ); + if( compiler->generator->debug ) { + putstring( "; if then" ); putnl( ); + } + generateFromAST( compiler->generator, node, NOREG ); + /* TODO: this should be condensed and optimized for the normal path + * (rare ifs, invert the condition, jmpXX directly */ + putstring( "cmp al, 0" ); putnl( ); + label1 = genGetLabel( compiler, compiler->parser->global_scope ); + putstring( "je " ); putstring( label1 ); putnl( ); + genFreeAllRegs( compiler->generator ); + parserExpect( parser, S_RPAREN, ")" ); + parseStatementBlock( compiler ); + if( parser->token == S_ELSE ) { + label2 = genGetLabel( compiler, compiler->parser->global_scope ); + putstring( "jmp " ); putstring( label2 ); putnl( ); + if( compiler->generator->debug ) { + putstring( "; else" ); putnl( ); + } + putstring( label1 ); putchar( ':' ); putnl( ); + compiler->parser->token = getToken( compiler->parser->scanner ); + parseStatementBlock( compiler ); + putstring( label2 ); putchar( ':' ); putnl( ); + free( label2 ); + } else { + putstring( label1 ); putchar( ':' ); putnl( ); + } + + if( compiler->generator->debug ) { + putstring( "; fi" ); putnl( ); + } + free( label1 ); +} + void parseStatement( struct Compiler *compiler ) { struct Parser *parser; @@ -1220,7 +1306,9 @@ void parseStatement( struct Compiler *compiler ) parseAssignment( compiler ); } else if( parser->token == S_PUTINT ) { parsePutint( compiler ); - } else if( parser->token == S_EOI ) { + } else if( parser->token == S_IF ) { + parseIf( compiler ); + } else if( parser->token == S_RBRACE || parser->token == S_EOI ) { return; } else { scannerPrintErrorHeader( parser->scanner ); @@ -1232,6 +1320,18 @@ void parseStatement( struct Compiler *compiler ) } } +void parseStatementBlock( struct Compiler *compiler ) +{ + struct Parser *parser; + + parser = compiler->parser; + parserExpect( parser, S_LBRACE, "{" ); + while( parser->token != S_RBRACE && parser->token != S_EOI ) { + parseStatement( compiler ); + } + parserExpect( parser, S_RBRACE, "}" ); +} + /* compiler */ struct Compiler *createCompiler( ) @@ -1263,9 +1363,7 @@ int main( int argc, char **argv ) /* compiler->generator->debug = 1; */ genPrologue( compiler ); compiler->parser->token = getToken( compiler->parser->scanner ); - while( compiler->parser->token != S_EOI ) { - parseStatement( compiler ); - } + parseStatementBlock( compiler ); genEpilogue( compiler ); freeCompiler( compiler ); -- cgit v1.2.3-54-g00ecf