From 2e707c4702a06bbe6f44efc732820f6eacce27f9 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 30 Sep 2021 13:39:22 +0200 Subject: cc: added do while --- miniany/REQUIREMENTS | 6 +++++- miniany/cc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- miniany/test1.c | 7 ++++++- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/miniany/REQUIREMENTS b/miniany/REQUIREMENTS index cbee3f2..985def7 100644 --- a/miniany/REQUIREMENTS +++ b/miniany/REQUIREMENTS @@ -126,5 +126,9 @@ TODO: a variable. Knowing the contest would require an AST. - AST should not be the output of whole programs, scoping is maybe better - don't allow non-blocked if/else, just avoid dangling else problems - +- for loops: they simply have a too general and weird semantic in C (missing + semicolon after the last triplet). IMHO a for loop makes sense for SIMD + operations only when we can use a stricter grammar to optimize certain + iterations. + diff --git a/miniany/cc.c b/miniany/cc.c index 6e3f391..cef1af2 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -28,6 +28,7 @@ enum { S_IF, S_ELSE, S_WHILE, + S_DO, S_PUTINT, S_IDENT = 60, S_NUM = 70, @@ -162,11 +163,15 @@ void scanIdent( struct Scanner *scanner ) int keyword( char *ident ) { switch( ident[0] ) { + case 'd': + if( strcmp( ident, "do" ) == 0 ) { + return S_DO; + } + break; + case 'e': if( strcmp( ident, "else" ) == 0 ) { return S_ELSE; - } else { - return 0; } break; @@ -1329,6 +1334,44 @@ void parseWhile( struct Compiler *compiler ) free( label1 ); } +void parseDo( struct Compiler *compiler ) +{ + struct Parser *parser; + struct ASTnode *node; + char *label1; + + parser = compiler->parser; + parserExpect( parser, S_DO, "do" ); + if( compiler->generator->debug ) { + putstring( "; do" ); putnl( ); + } + label1 = genGetLabel( compiler, compiler->parser->global_scope ); + putstring( label1 ); putchar( ':' ); putnl( ); + parseStatementBlock( compiler ); + parserExpect( parser, S_WHILE, "while" ); + parserExpect( parser, S_LPAREN, "(" ); + node = parseExpression( parser, 0 ); + generateFromAST( compiler->generator, node, NOREG ); + putstring( "cmp al, 0" ); putnl( ); + putstring( "jne " ); putstring( label1 ); putnl( ); + genFreeAllRegs( compiler->generator ); + parserExpect( parser, S_RPAREN, ")" ); + parserExpect( parser, S_SEMICOLON, ";" ); + free( label1 ); +} + +/* + + + putstring( "jmp " ); putstring( label2 ); putnl( ); + putstring( label1 ); putchar( ':' ); putnl( ); + if( compiler->generator->debug ) { + putstring( "; fi" ); putnl( ); + } + free( label2 ); + free( label1 ); +} + */ void parseStatement( struct Compiler *compiler ) { struct Parser *parser; @@ -1344,6 +1387,8 @@ void parseStatement( struct Compiler *compiler ) parseIf( compiler ); } else if( parser->token == S_WHILE ) { parseWhile( compiler ); + } else if( parser->token == S_DO ) { + parseDo( compiler ); } else if( parser->token == S_RBRACE || parser->token == S_EOI ) { return; } else { diff --git a/miniany/test1.c b/miniany/test1.c index 4492d4f..4bf86e3 100644 --- a/miniany/test1.c +++ b/miniany/test1.c @@ -26,9 +26,14 @@ putint( 0 ); } } - i = 10; + i = 5; while( i > 0 ) { putint( i ); i = i-1; } + i = 1; + do { + putint( i ); + i = i+1; + } while( i <= 5 ); } -- cgit v1.2.3-54-g00ecf