summaryrefslogtreecommitdiff
path: root/miniany/cc.c
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2021-09-29 20:32:00 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2021-09-29 20:32:00 +0200
commit01ee6d3e1de75a1aa08afd06f4dafe49d099e77e (patch)
treee10eccb9076dfb5b4e7f4a94899496e916288625 /miniany/cc.c
parentc2bc809ca97bdebc8c70dd58a1c282c475a88557 (diff)
downloadcompilertests-01ee6d3e1de75a1aa08afd06f4dafe49d099e77e.tar.gz
compilertests-01ee6d3e1de75a1aa08afd06f4dafe49d099e77e.tar.bz2
cc: work on a working if
Diffstat (limited to 'miniany/cc.c')
-rw-r--r--miniany/cc.c116
1 files changed, 107 insertions, 9 deletions
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 <cond> 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 );