diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2020-05-23 20:36:24 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2020-05-23 20:36:24 +0200 |
commit | 58a041e920116d7f06100a588172b4719e32a40b (patch) | |
tree | 64ace16ad16e3261699e735480153f06c0fae8d8 | |
parent | b35ee46072e2a98de06d722ad8db33306e95944c (diff) | |
download | compilertests-58a041e920116d7f06100a588172b4719e32a40b.tar.gz compilertests-58a041e920116d7f06100a588172b4719e32a40b.tar.bz2 |
added character type
multi-typed values for constants and variables (all symbols)
adapted tests to better output of debug code in assembly
-rw-r--r-- | ecomp-c/ec.c | 237 | ||||
-rw-r--r-- | ecomp-c/minie.ebnf | 1 | ||||
-rw-r--r-- | ecomp-c/test1.e | 5 | ||||
-rw-r--r-- | ecomp-c/tests/boolean_variable.easm | 2 | ||||
-rw-r--r-- | ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm | 2 | ||||
-rw-r--r-- | ecomp-c/tests/const_assignment_from_unknown_constant.easm | 2 | ||||
-rw-r--r-- | ecomp-c/tests/type_check_assignment.easm | 2 | ||||
-rw-r--r-- | ecomp-c/tests/type_check_comparision.easm | 4 | ||||
-rw-r--r-- | ecomp-c/tests/variable_initialization.easm | 2 |
9 files changed, 205 insertions, 52 deletions
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c index 9bd2ca2..65c5fad 100644 --- a/ecomp-c/ec.c +++ b/ecomp-c/ec.c @@ -23,6 +23,7 @@ static int DEBUG_SCANNER = 0; typedef enum { S_ident = 0, S_number, + S_char, S_module, S_begin, S_end, @@ -58,6 +59,7 @@ typedef enum { static char *symname[S_eof+1] = { "ident", "number", + "char", "module", "begin", "end", @@ -98,6 +100,7 @@ static S_Symbol sym; static char ident[MAX_IDENT_LEN+1]; static int num; +static int ch; static void Err( char *s, va_list args ) { @@ -209,6 +212,23 @@ static void number( void ) } } +static void character( void ) +{ + if( look == '\'' ) { + look = getChar( ); + if( isDigit( look ) || isAlpha( look ) ) { + ch = look; + } else { + Abort( "Expecting a character as character literal" ); + } + look = getChar( ); + if( look != '\'' ) { + Abort( "Unterminated character literal" ); + } + look = getChar( ); + } +} + static void identifier( void ) { int n = 0; @@ -406,7 +426,11 @@ static S_Symbol getSym( void ) case 'Y': case 'Z': identifier( ); - s = S_ident; + s = S_ident; + break; + case '\'': + character( ); + s = S_char; break; case ':': look = getChar( ); @@ -548,12 +572,18 @@ typedef struct Symbol { struct Symbol *next; struct Symbol *type; /* constant */ - int value; + int integer_value; + char boolean_value; + int character_value; /* variable */ int initialized; int size; } Symbol; +static Symbol *integer_type; +static Symbol *boolean_type; +static Symbol *character_type; + typedef struct Scope { char *name; int label_no; @@ -676,7 +706,9 @@ typedef struct ExpressionNode { ExpressionNodeType type; S_Symbol op; struct ExpressionNode *left, *right; - int number; + int integer_value; + int boolean_value; + int character_value; Symbol *symbol; Symbol *actual_type; } ExpressionNode; @@ -705,7 +737,21 @@ static void generate_expression_comment( ExpressionNode *node ) { switch( node->type ) { case EXPRESSION_NODE_TYPE_CONST: - Emit( "%d ", node->number ); + if( node->actual_type == integer_type ) { + Emit( "%d ", node->integer_value ); + } else if( node->actual_type == boolean_type ) { + if( node->boolean_value == 0 ) { + Emit( "false " ); + } else if( node->boolean_value == 1 ) { + Emit( "true " ); + } else { + Abort( "Internal representation problem of a boolean (is '%d')", node->boolean_value ); + } + } else if( node->actual_type == character_type ) { + Emit( "'%c' ", node->character_value ); + } else { + Abort( "Unhandled basic type '%s' in assembly comment generation", node->actual_type->name ); + } break; case EXPRESSION_NODE_TYPE_VAR: @@ -780,7 +826,15 @@ static void emit_expression_code( ExpressionNode *node, Scope *scope ) { switch( node->type ) { case EXPRESSION_NODE_TYPE_CONST: - Emit( "mov eax, %d\n", node->number ); + if( node->actual_type == integer_type ) { + Emit( "mov eax, %d\n", node->integer_value ); + } else if( node->actual_type == boolean_type ) { + Emit( "mov eax, %d\n", node->boolean_value ); + } else if( node->actual_type == character_type ) { + Emit( "mov eax, %d\n", node->character_value ); + } else { + Abort( "Missing expression node code generation handling for type '%s'", node->actual_type->name ); + } Emit( "push eax\n" ); break; @@ -920,8 +974,14 @@ static ExpressionNode *parseFactor( void ) if( sym == S_number ) { node = create_expression_node( ); node->type = EXPRESSION_NODE_TYPE_CONST; - node->number = num; - node->actual_type = get_symbol( current_scope, "integer" ); + node->integer_value = num; + node->actual_type = integer_type; + sym = getSym( ); + } else if( sym == S_char ) { + node = create_expression_node( ); + node->type = EXPRESSION_NODE_TYPE_CONST; + node->character_value = ch; + node->actual_type = character_type; sym = getSym( ); } else if( sym == S_ident ) { symbol = get_symbol( current_scope, ident ); @@ -934,8 +994,16 @@ static ExpressionNode *parseFactor( void ) if( symbol->class == SYMBOL_CLASS_CONSTANT ) { node = create_expression_node( ); node->type = EXPRESSION_NODE_TYPE_CONST; - node->number = symbol->value; node->actual_type = symbol->type; + if( node->actual_type == integer_type ) { + node->integer_value = symbol->integer_value; + } else if( node->actual_type == boolean_type ) { + node->boolean_value = symbol->boolean_value; + } else if( node->actual_type == character_type ) { + node->character_value = symbol->character_value; + } else { + Abort( "Unhandled expression assignment from identifier with type '%s'", node->actual_type->name ); + } } if( symbol->class == SYMBOL_CLASS_VARIABLE ) { if( !symbol->initialized ) { @@ -1207,8 +1275,13 @@ static ExpressionNode *parseConstExpression( void ) if( sym == S_number ) { node->type = EXPRESSION_NODE_TYPE_CONST; - node->number = num; - node->actual_type = get_symbol( current_scope, "integer" ); + node->integer_value = num; + node->actual_type = integer_type; + sym = getSym( ); + } else if( sym == S_char ) { + node->type = EXPRESSION_NODE_TYPE_CONST; + node->character_value = ch; + node->actual_type = character_type; sym = getSym( ); } else if( sym == S_ident ) { Symbol *symbol = get_symbol( current_scope, ident ); @@ -1229,6 +1302,74 @@ static ExpressionNode *parseConstExpression( void ) return node; } +static void generate_symbol_comment( char *mode, Symbol *constant ) +{ + Emit( "; %s %s -> %s, ", mode, constant->name, constant->type->name ); + if( constant->type == integer_type ) { + Emit( "%d", constant->integer_value ); + } else if( constant->type == boolean_type ) { + if( constant->boolean_value == 0 ) { + Emit( "false" ); + } else if( constant->boolean_value == 1 ) { + Emit( "true" ); + } else { + Abort( "Wrong internal value '%d' of a boolean when printing constant comment", constant->boolean_value ); + } + } else if( constant->type == character_type ) { + Emit( "'%c'", constant->character_value ); + } else { + Abort( "Unhandled symbol (%s) comment case for type '%s'", mode, constant->type->name ); + } + Emit( "\n" ); +} + +static void generate_constant_comment( Symbol *variable ) +{ + generate_symbol_comment( "CONST", variable ); +} + +static void generate_variable_comment( Symbol *variable ) +{ + generate_symbol_comment( "DECL", variable ); +} + +static void symbol_copy_value( Symbol *from, Symbol *to ) +{ + + if( from->type != to->type ) { + Abort( "type mismatch when copying symbol value (from: '%s', to: '%s')", + from->type->name, to->type->name ); + } + + if( from->type == integer_type ) { + to->integer_value = from->integer_value; + } else if( from->type == boolean_type ) { + to->boolean_value = from->boolean_value; + } else if( from->type == character_type ) { + to->character_value = from->character_value; + } else { + Abort( "Unhandled case for type '%s' when copying value of symbol", from->type->name ); + } +} + +static void symbol_copy_node_value( ExpressionNode *from, Symbol *to ) +{ + if( from->actual_type != to->type ) { + Abort( "type mismatch when copying node to symbol value (from: '%s', to: '%s')", + from->actual_type->name, to->type->name ); + } + + if( from->actual_type == integer_type ) { + to->integer_value = from->integer_value; + } else if( from->actual_type == boolean_type ) { + to->boolean_value = from->boolean_value; + } else if( from->actual_type == character_type ) { + to->character_value = from->character_value; + } else { + Abort( "Unhandled case for type '%s' when copying value of symbol from expression node", from->actual_type->name ); + } +} + static void parseConstDeclaration( void ) { int nof_constants = 0; @@ -1268,19 +1409,23 @@ static void parseConstDeclaration( void ) Abort( "Assigning a constant of type '%s' from an expression of type '%s'", type->name, node->actual_type->name ); } + if( node->type == EXPRESSION_NODE_TYPE_CONST ) { for( i = 0; i < nof_constants; i++ ) { - constant[i]->value = node->number; constant[i]->type = node->actual_type; - Emit( "; CONST %s -> %s, %d\n", constant[i]->name, constant[i]->type->name, constant[i]->value ); + symbol_copy_node_value( node, constant[i] ); } } else if( node->type == EXPRESSION_NODE_TYPE_VAR ) { for( i = 0; i < nof_constants; i++ ) { - constant[i]->value = node->symbol->value; constant[i]->type = node->symbol->type; - Emit( "; CONST %s -> %s, %d\n", constant[i]->name, constant[i]->type->name, constant[i]->value ); + symbol_copy_value( node->symbol, constant[i] ); } } + + for( i = 0; i < nof_constants; i++ ) { + generate_constant_comment( constant[i] ); + } + free_expression_node( node ); } @@ -1339,27 +1484,30 @@ static void parseVariableDeclaration( void ) Abort( "Assigning a variable of type '%s' from an expression of type '%s'", type->name, node->actual_type->name ); } + if( node->type == EXPRESSION_NODE_TYPE_CONST ) { for( i = 0; i < nof_variables; i++ ) { - variable[i]->value = node->number; variable[i]->type = node->actual_type; + symbol_copy_node_value( node, variable[i] ); } } else if( node->type == EXPRESSION_NODE_TYPE_VAR ) { for( i = 0; i < nof_variables; i++ ) { - variable[i]->value = node->symbol->value; variable[i]->type = node->symbol->type; + symbol_copy_value( node->symbol, variable[i] ); } } free_expression_node( node ); } else { for( i = 0; i < nof_variables; i++ ) { - variable[i]->value = 0; + variable[i]->integer_value = 0; + variable[i]->boolean_value = 0; /* false */ + variable[i]->character_value = 0; /* NUL */ variable[i]->type = type; } } for( i = 0; i < nof_variables; i++ ) { - Emit( "; DECL %s -> %s, %d\n", variable[i]->name, variable[i]->type->name, variable[i]->value ); + generate_variable_comment( variable[i] ); } } @@ -1403,24 +1551,24 @@ static void parseModule( void ) static void register_internal_types( Scope *scope ) { - Symbol *type_symbol, *const_symbol; - - type_symbol = insert_symbol( current_scope, "integer", SYMBOL_CLASS_TYPE ); - type_symbol->size = 4; + Symbol *const_symbol; + + integer_type = insert_symbol( current_scope, "integer", SYMBOL_CLASS_TYPE ); + integer_type->size = 4; - type_symbol = insert_symbol( current_scope, "boolean", SYMBOL_CLASS_TYPE ); - type_symbol->size = 1; + boolean_type = insert_symbol( current_scope, "boolean", SYMBOL_CLASS_TYPE ); + boolean_type->size = 1; const_symbol = insert_symbol( current_scope, "false", SYMBOL_CLASS_CONSTANT ); - const_symbol->type = type_symbol; - const_symbol->value = 0; + const_symbol->type = boolean_type; + const_symbol->boolean_value = 0; const_symbol = insert_symbol( current_scope, "true", SYMBOL_CLASS_CONSTANT ); - const_symbol->type = type_symbol; - const_symbol->value = 1; + const_symbol->type = boolean_type; + const_symbol->boolean_value = 1; - type_symbol = insert_symbol( current_scope, "char", SYMBOL_CLASS_TYPE ); - type_symbol->size = 1; + character_type = insert_symbol( current_scope, "character", SYMBOL_CLASS_TYPE ); + character_type->size = 1; } static void init( void ) @@ -1453,20 +1601,21 @@ static void epilogue( void ) symbol = current_scope->symbol; while( symbol != NULL ) { if( symbol->class == SYMBOL_CLASS_VARIABLE ) { - switch( symbol->type->size ) { - case 4: - Emit( "%s: dd $", symbol->name ); - Emit_DD( symbol->value ); - Emit( "\n" ); - break; - case 1: - Emit( "%s: db $", symbol->name ); - Emit_Hexbyte( symbol->value ); - Emit( "\n" ); - break; - default: - Abort( "Unhandled size of type '%s' in variable '%s'", - symbol->type->name, symbol->name ); + if( symbol->type == integer_type ) { + Emit( "%s: dd $", symbol->name ); + Emit_DD( symbol->integer_value ); + Emit( "\n" ); + } else if( symbol->type == boolean_type ) { + Emit( "%s: db $", symbol->name ); + Emit_Hexbyte( symbol->boolean_value ); + Emit( "\n" ); + } else if( symbol->type == character_type ) { + Emit( "%s: db $", symbol->name ); + Emit_Hexbyte( symbol->character_value ); + Emit( "\n" ); + } else { + Abort( "Unhandled variable space reservation and initializiation for type '%s' in variable '%s'", + symbol->type->name, symbol->name ); } } symbol = symbol->next; diff --git a/ecomp-c/minie.ebnf b/ecomp-c/minie.ebnf index be82d9e..a0558b6 100644 --- a/ecomp-c/minie.ebnf +++ b/ecomp-c/minie.ebnf @@ -4,6 +4,7 @@ Letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" Special = "_" . Identifier = Letter { Letter | Digit | Special } . Number = Digit { Digit } . +Character = "'" Digit | Letter "'" . Factor = Number | Identifier | "(" Expression ")" | "not" Factor . Term = Factor { ( "*" | "/" | "mod" | "and" ) Factor } . diff --git a/ecomp-c/test1.e b/ecomp-c/test1.e index 28d2516..5648c9f 100644 --- a/ecomp-c/test1.e +++ b/ecomp-c/test1.e @@ -8,6 +8,7 @@ const // integer constant N, M : integer = 20; O : integer = N; + C : character = 'a'; // boolean constant INIT_STATE : boolean = true; @@ -22,7 +23,7 @@ var d, e, f : integer; flag : boolean; i : integer; - j : char; + j : character := C; begin a := 1; @@ -51,4 +52,6 @@ begin while ( i < 10 ) and not flag do i := i + 1; end; + + j := 'b'; end diff --git a/ecomp-c/tests/boolean_variable.easm b/ecomp-c/tests/boolean_variable.easm index d76a31d..4f9c733 100644 --- a/ecomp-c/tests/boolean_variable.easm +++ b/ecomp-c/tests/boolean_variable.easm @@ -3,7 +3,7 @@ use32 org $1000000 ; DECL a -> integer, 0 ; DECL b -> integer, 0 -; DECL flag -> boolean, 0 +; DECL flag -> boolean, false ; LET a <- 573785173 mov eax, 573785173 push eax diff --git a/ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm b/ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm index 266ad15..f969c36 100644 --- a/ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm +++ b/ecomp-c/tests/const_assignment_from_another_constant_illegal_type.easm @@ -2,4 +2,4 @@ format binary use32 org $1000000 ; CONST N -> integer, 20 -; CONST B -> boolean, 0 +; CONST B -> boolean, false diff --git a/ecomp-c/tests/const_assignment_from_unknown_constant.easm b/ecomp-c/tests/const_assignment_from_unknown_constant.easm index 266ad15..f969c36 100644 --- a/ecomp-c/tests/const_assignment_from_unknown_constant.easm +++ b/ecomp-c/tests/const_assignment_from_unknown_constant.easm @@ -2,4 +2,4 @@ format binary use32 org $1000000 ; CONST N -> integer, 20 -; CONST B -> boolean, 0 +; CONST B -> boolean, false diff --git a/ecomp-c/tests/type_check_assignment.easm b/ecomp-c/tests/type_check_assignment.easm index 73e7972..03888c0 100644 --- a/ecomp-c/tests/type_check_assignment.easm +++ b/ecomp-c/tests/type_check_assignment.easm @@ -2,7 +2,7 @@ format binary use32 org $1000000 ; DECL i -> integer, 0 -; DECL b -> boolean, 0 +; DECL b -> boolean, false ; LET i <- 1 mov eax, 1 push eax diff --git a/ecomp-c/tests/type_check_comparision.easm b/ecomp-c/tests/type_check_comparision.easm index ab28b5b..e8fd0ee 100644 --- a/ecomp-c/tests/type_check_comparision.easm +++ b/ecomp-c/tests/type_check_comparision.easm @@ -2,13 +2,13 @@ format binary use32 org $1000000 ; DECL i -> integer, 0 -; DECL b -> boolean, 0 +; DECL b -> boolean, false ; LET i <- 1 mov eax, 1 push eax pop eax mov [i], eax -; LET b <- 0 +; LET b <- false mov eax, 0 push eax pop eax diff --git a/ecomp-c/tests/variable_initialization.easm b/ecomp-c/tests/variable_initialization.easm index d3aac22..369b049 100644 --- a/ecomp-c/tests/variable_initialization.easm +++ b/ecomp-c/tests/variable_initialization.easm @@ -5,7 +5,7 @@ org $1000000 ; DECL a -> integer, 0 ; DECL b -> integer, 1 ; DECL c -> integer, 0 -; DECL d -> boolean, 1 +; DECL d -> boolean, true ; LET c <- 2 mov eax, 2 push eax |