From c2bc809ca97bdebc8c70dd58a1c282c475a88557 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 27 Sep 2021 19:34:16 +0200 Subject: cc: added boolean expressions --- miniany/cc.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 155 insertions(+), 3 deletions(-) (limited to 'miniany/cc.c') diff --git a/miniany/cc.c b/miniany/cc.c index 6f4f0a8..01472c9 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -13,7 +13,15 @@ enum { S_STAR, S_SLASH, S_SEMICOLON, + S_LPAREN, + S_RPAREN, + S_ASSIGN, S_EQUALS, + S_NOT_EQUALS, + S_LESS, + S_LESS_OR_EQUALS, + S_MORE, + S_MORE_OR_EQUALS, S_INT = 10, S_PUTINT, S_IDENT = 20, @@ -214,7 +222,43 @@ int getToken( struct Scanner *scanner ) scanner->token = S_SEMICOLON; break; case '=': - scanner->token = S_EQUALS; + c = getChar( scanner ); + if( c == '=' ) { + scanner->token = S_EQUALS; + } else { + pushBack( scanner ); + scanner->token = S_ASSIGN; + } + break; + case '!': + c = getChar( scanner ); + if( c == '=' ) { + scanner->token = S_NOT_EQUALS; + } else { + pushBack( scanner ); + } + break; + case '<': + c = getChar( scanner ); + if( c == '=' ) { + scanner->token = S_LESS_OR_EQUALS; + } else { + scanner->token = S_LESS; + } + break; + case '>': + c = getChar( scanner ); + if( c == '=' ) { + scanner->token = S_MORE_OR_EQUALS; + } else { + scanner->token = S_MORE; + } + break; + case '(': + scanner->token = S_LPAREN; + break; + case ')': + scanner->token = S_RPAREN; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': @@ -351,6 +395,12 @@ enum { A_MULTIPLY, A_DIVIDE, A_ASSIGN, + A_EQUALS, + A_NOT_EQUALS, + A_LESS, + A_LESS_OR_EQUALS, + A_MORE, + A_MORE_OR_EQUALS, A_ERR = 99 }; @@ -480,6 +530,32 @@ void putreg( struct Generator *generator, int reg ) putstring( generator->regName[reg] ); } +void putlow8reg( struct Generator *generator, int reg ) +{ + switch( reg ) { + case EAX: + putstring( "al" ); + break; + case EBX: + putstring( "bl" ); + break; + case ECX: + putstring( "cl" ); + break; + case EDX: + putstring( "dl" ); + break; + default: + scannerPrintErrorHeader( generator->scanner ); + putstring( "error using low 8-bit subreguster of reguster '" ); + putstring( generator->regName[reg] ); + putstring( "'" ); + putnl( ); + exit( EXIT_FAILURE ); + } +} + + void genAddGlob( struct Generator *generator, char *ident ) { putstring( ident ); @@ -747,6 +823,26 @@ int genDiv( struct Generator *generator, int leftreg, int rightreg ) return reg; } +int genCompare( char *op, struct Generator *generator, int leftreg, int rightreg ) +{ + putstring( "cmp " ); + putreg( generator, leftreg ); + putstring( ", " ); + putreg( generator, rightreg ); + putnl( ); + putstring( op ); + putchar( ' ' ); + putlow8reg( generator, leftreg ); + putnl( ); + putstring( "and " ); + putreg( generator, leftreg ); + putstring( ", $FF" ); + putnl( ); + genFreeReg( generator, rightreg ); + + return leftreg; +} + int generateFromAST( struct Generator *generator, struct ASTnode *node, int inreg ) { int leftreg, rightreg, reg; @@ -785,6 +881,24 @@ int generateFromAST( struct Generator *generator, struct ASTnode *node, int inre case A_ASSIGN: reg = inreg; break; + case A_EQUALS: + reg = genCompare( "sete", generator, leftreg, rightreg ); + break; + case A_NOT_EQUALS: + reg = genCompare( "setne", generator, leftreg, rightreg ); + break; + case A_LESS_OR_EQUALS: + reg = genCompare( "setle", generator, leftreg, rightreg ); + break; + case A_LESS: + reg = genCompare( "setl", generator, leftreg, rightreg ); + break; + case A_MORE: + reg = genCompare( "setg", generator, leftreg, rightreg ); + break; + case A_MORE_OR_EQUALS: + reg = genCompare( "setge", generator, leftreg, rightreg ); + break; default: putint( node->op ); putstring( "?" ); @@ -897,6 +1011,30 @@ int parserTokenToOperator( struct Parser *parser, int token ) case S_MINUS: op = A_SUBTRACT; break; + + case S_EQUALS: + op = A_EQUALS; + break; + + case S_NOT_EQUALS: + op = A_NOT_EQUALS; + break; + + case S_LESS: + op = A_LESS; + break; + + case S_LESS_OR_EQUALS: + op = A_LESS_OR_EQUALS; + break; + + case S_MORE: + op = A_MORE; + break; + + case S_MORE_OR_EQUALS: + op = A_MORE_OR_EQUALS; + break; default: scannerPrintErrorHeader( parser->scanner ); @@ -915,6 +1053,18 @@ int parserOperatorPrecedence( struct Parser *parser, int operator ) precedence = 0; switch( operator ) { + case A_LESS: + case A_LESS_OR_EQUALS: + case A_MORE: + case A_MORE_OR_EQUALS: + precedence = 4; + break; + + case A_EQUALS: + case A_NOT_EQUALS: + precedence = 3; + break; + case A_MULTIPLY: case A_DIVIDE: precedence = 2; @@ -973,7 +1123,7 @@ struct ASTnode *parseExpression( struct Parser *parser, int level ) } parser->token = getToken( parser->scanner ); - if( parser->token == S_EOI || parser->token == S_SEMICOLON ) { + if( parser->token == S_EOI || parser->token == S_SEMICOLON || parser->token == S_RPAREN ) { return left; } @@ -1032,7 +1182,7 @@ void parseAssignment( struct Compiler *compiler ) exit( EXIT_FAILURE ); } right = createASTleafSym( A_LVIDENT, sym ); - parserExpect( parser, S_EQUALS, "=" ); + parserExpect( parser, S_ASSIGN, "=" ); left = parseExpression( parser, 0 ); parserExpect( parser, S_SEMICOLON, ";" ); @@ -1049,7 +1199,9 @@ void parsePutint( struct Compiler *compiler ) parser = compiler->parser; parserExpect( parser, S_PUTINT, "putint" ); + parserExpect( parser, S_LPAREN, "(" ); node = parseExpression( parser, 0 ); + parserExpect( parser, S_RPAREN, ")" ); parserExpect( parser, S_SEMICOLON, ";" ); generateFromAST( compiler->generator, node, NOREG ); putstring( "call putint" ); putnl( ); -- cgit v1.2.3-54-g00ecf