diff --git a/06-c-syntax-analyzer/err2.c b/06-c-syntax-analyzer/err2.c new file mode 100644 index 0000000..62e1ac2 --- /dev/null +++ b/06-c-syntax-analyzer/err2.c @@ -0,0 +1,18 @@ +int a = 3; +char g_c = (char) 3; + +void main() { + + switch (a) { + case 1: + g_c = 'z'; + case 2: + g_c = 's'; + case 3: + a = 2; + default: + a++; + } + + int x , y = 2; +} \ No newline at end of file diff --git a/06-c-syntax-analyzer/err3.c b/06-c-syntax-analyzer/err3.c new file mode 100644 index 0000000..65257bc --- /dev/null +++ b/06-c-syntax-analyzer/err3.c @@ -0,0 +1,20 @@ +int func1(int pr); +void func2(); +char func3(); + +void main(){ + int i = 16; + char c; + char str[i+1]; + + char *s = "string"; + + int a = func1(); + c = func2(); // return type unmatched + func3(); +} +int func1() {return 1;} +void func2() {} +char func3() { + return 's'; +} \ No newline at end of file diff --git a/06-c-syntax-analyzer/err4.c b/06-c-syntax-analyzer/err4.c new file mode 100644 index 0000000..67d662a --- /dev/null +++ b/06-c-syntax-analyzer/err4.c @@ -0,0 +1,24 @@ +int global; +char global_c; + +int func(); + +int main () { + + int a1 = 1; + enum ss { s, f , sk} ff; + struct df { + int a; + int c; + char i; + } *st; + + a2 = (int) func(); // undefined var + st->b = 1; // undefined field + gobal_c = (char)1; // typo + return 0; +} + +int func(){ + return 3; +} \ No newline at end of file diff --git a/06-c-syntax-analyzer/err5.c b/06-c-syntax-analyzer/err5.c new file mode 100644 index 0000000..8c31e1e --- /dev/null +++ b/06-c-syntax-analyzer/err5.c @@ -0,0 +1,11 @@ +int main () { + struct ss { + int a; + int b; + } a; + + struct ss { + int a; + char c; + } t; +} \ No newline at end of file diff --git a/06-c-syntax-analyzer/err6.c b/06-c-syntax-analyzer/err6.c new file mode 100644 index 0000000..243eb7a --- /dev/null +++ b/06-c-syntax-analyzer/err6.c @@ -0,0 +1,10 @@ +int func1(); +char func2(int a); + +int main(void){ + return 1; +} + +char func1() { + return '2'; +} \ No newline at end of file diff --git a/06-c-syntax-analyzer/err7.c b/06-c-syntax-analyzer/err7.c new file mode 100644 index 0000000..c5ad893 --- /dev/null +++ b/06-c-syntax-analyzer/err7.c @@ -0,0 +1,6 @@ +int func(int, char); +int main(void) +{ + int a; + +} \ No newline at end of file diff --git a/06-c-syntax-analyzer/main.c b/06-c-syntax-analyzer/main.c index 4c4ff44..46b1052 100644 --- a/06-c-syntax-analyzer/main.c +++ b/06-c-syntax-analyzer/main.c @@ -17,4 +17,4 @@ void main(int argc, char *argv[]){ } print_ast(root); exit(0); -} \ No newline at end of file +} diff --git a/06-c-syntax-analyzer/test2.c b/06-c-syntax-analyzer/test2.c index 62e1ac2..3d871d7 100644 --- a/06-c-syntax-analyzer/test2.c +++ b/06-c-syntax-analyzer/test2.c @@ -2,6 +2,7 @@ int a = 3; char g_c = (char) 3; void main() { + int x , y = 2; switch (a) { case 1: @@ -14,5 +15,4 @@ void main() { a++; } - int x , y = 2; } \ No newline at end of file diff --git a/06-c-syntax-analyzer/test4.c b/06-c-syntax-analyzer/test4.c index 9b04d36..269d211 100644 --- a/06-c-syntax-analyzer/test4.c +++ b/06-c-syntax-analyzer/test4.c @@ -11,10 +11,10 @@ int main () { int a; int c; char i; - } st; + } *st; a1 = (int) func(); - st.a = 1; + st->a = 1; global_c = (char)1; return 0; } diff --git a/07-c-semantic-analyzer/Makefile b/07-c-semantic-analyzer/Makefile new file mode 100644 index 0000000..e205c92 --- /dev/null +++ b/07-c-semantic-analyzer/Makefile @@ -0,0 +1,9 @@ +a.out: yacc lex + gcc -g y.tab.c lex.yy.c sem_print.c func.c sem_func.c main.c -w +yacc: yacc.y + yacc -d yacc.y +lex: lex.l + lex lex.l + +make clean: + rm a.out \ No newline at end of file diff --git a/07-c-semantic-analyzer/lex.l b/07-c-semantic-analyzer/lex.l index b755de0..d138b8a 100644 --- a/07-c-semantic-analyzer/lex.l +++ b/07-c-semantic-analyzer/lex.l @@ -73,9 +73,9 @@ while { return(WHILE_SYM); } "\=" { return(ASSIGN); } {digit}+ { yylval = atoi(yytext); return(INTEGER_CONSTANT); } -{digit}+\.{digit}+ { yylval = (YYSTYPE)makeString(yytext); return(FLOAT_CONSTANT); } +{digit}+\.{digit}+ { yylval = makeString(yytext); return(FLOAT_CONSTANT); } {letter}({letter}|{digit})* { return(checkIdentifier(yytext)); } -\"([^"\n]|\\["\n])*\" { yylval = (YYSTYPE)makeString(yytext); return(STRING_LITERAL); } +\"([^"\n]|\\["\n])*\" { yylval = makeString(yytext); return(STRING_LITERAL); } \'([^'\n]|\'\')\' { yylval = *(yytext+1); return(CHARACTER_CONSTANT); } "//"[^\n]* { } diff --git a/07-c-semantic-analyzer/lex.yy.c b/07-c-semantic-analyzer/lex.yy.c index 52c8768..e3eedf5 100644 --- a/07-c-semantic-analyzer/lex.yy.c +++ b/07-c-semantic-analyzer/lex.yy.c @@ -162,27 +162,8 @@ extern FILE *yyin, *yyout; #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 - /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires - * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE yylex. - * One obvious solution it to make yy_act a global. I tried that, and saw - * a 5% performance hit in a non-yylineno scanner, because yy_act is - * normally declared as a register variable-- so it is not worth it. - */ - #define YY_LESS_LINENO(n) \ - do { \ - int yyl;\ - for ( yyl = n; yyl < yyleng; ++yyl )\ - if ( yytext[yyl] == '\n' )\ - --yylineno;\ - }while(0) - #define YY_LINENO_REWIND_TO(dst) \ - do {\ - const char *p;\ - for ( p = yy_cp-1; p >= (dst); --p)\ - if ( *p == '\n' )\ - --yylineno;\ - }while(0) + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ @@ -347,11 +328,14 @@ FILE *yyin = NULL, *yyout = NULL; typedef int yy_state_type; -#define YY_FLEX_LEX_COMPAT extern int yylineno; int yylineno = 1; -extern char yytext[]; +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext static yy_state_type yy_get_previous_state ( void ); static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); @@ -366,9 +350,6 @@ static void yynoreturn yy_fatal_error ( const char* msg ); yyleng = (int) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ - if ( yyleng >= YYLMAX ) \ - YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \ - yy_flex_strncpy( yytext, (yytext_ptr), yyleng + 1 ); \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 57 #define YY_END_OF_BUFFER 58 @@ -535,13 +516,6 @@ static const flex_int16_t yy_chk[213] = 140, 140 } ; -/* Table of booleans, true if rule could match eol. */ -static const flex_int32_t yy_rule_can_match_eol[58] = - { 0, -0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, }; - static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; @@ -555,12 +529,7 @@ int yy_flex_debug = 0; #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET -#ifndef YYLMAX -#define YYLMAX 8192 -#endif - -char yytext[YYLMAX]; -char *yytext_ptr; +char *yytext; #line 1 "lex.l" #line 8 "lex.l" #define YYSTYPE_IS_DECLARED 1 @@ -575,8 +544,8 @@ extern A_ID *current_id; char *makeString(); int checkIdentifier(); -#line 579 "lex.yy.c" -#line 580 "lex.yy.c" +#line 548 "lex.yy.c" +#line 549 "lex.yy.c" #define INITIAL 0 @@ -795,7 +764,7 @@ YY_DECL { #line 22 "lex.l" -#line 799 "lex.yy.c" +#line 768 "lex.yy.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -841,16 +810,6 @@ YY_DECL YY_DO_BEFORE_ACTION; - if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) - { - int yyl; - for ( yyl = 0; yyl < yyleng; ++yyl ) - if ( yytext[yyl] == '\n' ) - - yylineno++; -; - } - do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) @@ -1121,7 +1080,7 @@ YY_RULE_SETUP case 52: YY_RULE_SETUP #line 76 "lex.l" -{ yylval = (YYSTYPE)makeString(yytext); return(FLOAT_CONSTANT); } +{ yylval = makeString(yytext); return(FLOAT_CONSTANT); } YY_BREAK case 53: YY_RULE_SETUP @@ -1132,7 +1091,7 @@ case 54: /* rule 54 can match eol */ YY_RULE_SETUP #line 78 "lex.l" -{ yylval = (YYSTYPE)makeString(yytext); return(STRING_LITERAL); } +{ yylval = makeString(yytext); return(STRING_LITERAL); } YY_BREAK case 55: YY_RULE_SETUP @@ -1149,7 +1108,7 @@ YY_RULE_SETUP #line 82 "lex.l" ECHO; YY_BREAK -#line 1153 "lex.yy.c" +#line 1112 "lex.yy.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1517,10 +1476,6 @@ static int yy_get_next_buffer (void) *--yy_cp = (char) c; - if ( c == '\n' ){ - --yylineno; - } - (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; @@ -1598,11 +1553,6 @@ static int yy_get_next_buffer (void) *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); - if ( c == '\n' ) - - yylineno++; -; - return c; } #endif /* ifndef YY_NO_INPUT */ @@ -2069,9 +2019,6 @@ static int yy_init_globals (void) * This function is called from yylex_destroy(), so don't allocate here. */ - /* We do not touch yylineno unless the option is enabled. */ - yylineno = 1; - (yy_buffer_stack) = NULL; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; diff --git a/07-c-semantic-analyzer/main.c b/07-c-semantic-analyzer/main.c index 96b9755..2bf50ff 100644 --- a/07-c-semantic-analyzer/main.c +++ b/07-c-semantic-analyzer/main.c @@ -1,13 +1,14 @@ #include #include #include "type.h" +#include "sem_func.h" extern int syntax_err; extern int semantic_err; extern A_NODE *root; void initialize(); -void print_ast(); // semantic +void print_sem_ast(); // semantic int main(){ initialize(); @@ -15,5 +16,5 @@ int main(){ if (syntax_err) exit(1); semantic_analysis(root); if (semantic_err) exit(1); - print_ast(root); + print_sem_ast(root); } diff --git a/07-c-semantic-analyzer/print.c b/07-c-semantic-analyzer/print.c deleted file mode 100644 index 2bf6660..0000000 --- a/07-c-semantic-analyzer/print.c +++ /dev/null @@ -1,351 +0,0 @@ -#include "type.h" - -char * node_name[] = { - "N_NULL", - "N_PROGRAM", - "N_EXP_IDENT", - "N_EXP_INT_CONST", - "N_EXP_FLOAT_CONST", - "N_EXP_CHAR_CONST", - "N_EXP_STRING_LITERAL", - "N_EXP_ARRAY", - "N_EXP_FUNCTION_CALL", - "N_EXP_STRUCT", - "N_EXP_ARROW", - "N_EXP_POST_INC", - "N_EXP_POST_DEC", - "N_EXP_PRE_INC", - "N_EXP_PRE_DEC", - "N_EXP_AMP", - "N_EXP_STAR", - "N_EXP_NOT", - "N_EXP_PLUS", - "N_EXP_MINUS", - "N_EXP_SIZE_EXP", - "N_EXP_SIZE_TYPE", - "N_EXP_CAST", - "N_EXP_MUL", - "N_EXP_DIV", - "N_EXP_MOD", - "N_EXP_ADD", - "N_EXP_SUB", - "N_EXP_LSS", - "N_EXP_GTR", - "N_EXP_LEQ", - "N_EXP_GEQ", - "N_EXP_NEQ", - "N_EXP_EQL", - "N_EXP_AND", - "N_EXP_OR", - "N_EXP_ASSIGN", - "N_ARG_LIST", - "N_ARG_LIST_NIL", - "N_STMT_LABEL_CASE", - "N_STMT_LABEL_DEFAULT", - "N_STMT_COMPOUND", - "N_STMT_EMPTY", - "N_STMT_EXPRESSION", - "N_STMT_IF", - "N_STMT_IF_ELSE", - "N_STMT_SWITCH", - "N_STMT_WHILE", - "N_STMT_DO", - "N_STMT_FOR", - "N_STMT_RETURN", - "N_STMT_CONTINUE", - "N_STMT_BREAK", - "N_FOR_EXP", - "N_STMT_LIST", - "N_STMT_LIST_NIL", - "N_INIT_LIST", - "N_INIT_LIST_ONE", - "N_INIT_LIST_NIL" -}; - -void print_ast(A_NODE *); -void prt_program(A_NODE *, int); -void prt_initializer(A_NODE *, int); -void prt_arg_expr_list(A_NODE *, int); -void prt_statement(A_NODE *, int); -void prt_statement_list(A_NODE *, int); -void prt_for_expression(A_NODE *, int); -void prt_expression(A_NODE *, int); -void prt_A_TYPE(A_TYPE *, int); -void prt_A_ID_LIST(A_ID *, int); -void prt_A_ID(A_ID *, int); -void prt_A_ID_NAME(A_ID *, int); -void prt_STRING(char *, int); -void prt_integer(int, int); -void print_node(A_NODE *,int); -void print_space(int); - -extern A_TYPE *int_type, *float_type, *char_type, *void_type, *string_type; - -void print_node(A_NODE *node, int s) -{ - print_space(s); - printf("%s (%x,%d)\n", node_name[node->name],node->type,node->value); -} -void print_space(int s) -{ - int i; - for(i=1; i<=s; i++) printf("| "); -} -void print_ast(A_NODE *node) -{ - printf("======= syntax tree ==========\n"); - prt_program(node,0); -} -void prt_program(A_NODE *node, int s) -{ - print_node(node,s); - switch(node->name) { case N_PROGRAM: - prt_A_ID_LIST(node->clink, s+1); - break; default : - printf("****syntax tree error******"); - } -} -void prt_initializer(A_NODE *node, int s) -{ - print_node(node,s); - switch(node->name) { case N_INIT_LIST: - prt_initializer(node->llink, s+1); - prt_initializer(node->rlink, s+1); - break; case N_INIT_LIST_ONE: - prt_expression(node->clink, s+1); - break; case N_INIT_LIST_NIL: - break; default : - printf("****syntax tree error******"); - } -} -void prt_expression(A_NODE *node, int s) -{ - print_node(node,s); - switch(node->name) { case N_EXP_IDENT : - prt_A_ID_NAME(node->clink, s+1); - break; case N_EXP_INT_CONST : - prt_integer(node->clink, s+1); - break; case N_EXP_FLOAT_CONST : - prt_STRING(node->clink, s+1); - break; case N_EXP_CHAR_CONST : - prt_integer(node->clink, s+1); - break; case N_EXP_STRING_LITERAL : - prt_STRING(node->clink, s+1); - break; case N_EXP_ARRAY : - prt_expression(node->llink, s+1); - prt_expression(node->rlink, s+1); - break; case N_EXP_FUNCTION_CALL : - prt_expression(node->llink, s+1); - prt_arg_expr_list(node->rlink, s+1); - break; case N_EXP_STRUCT : - case N_EXP_ARROW : - prt_expression(node->llink, s+1); - prt_STRING(node->rlink, s+1); - break; case N_EXP_POST_INC : case N_EXP_POST_DEC : case N_EXP_PRE_INC : case N_EXP_PRE_DEC : case N_EXP_AMP : case N_EXP_STAR : case N_EXP_NOT : case N_EXP_PLUS : case N_EXP_MINUS : case N_EXP_SIZE_EXP : - prt_expression(node->clink, s+1); break; case N_EXP_SIZE_TYPE : - prt_A_TYPE(node->clink, s+1); break; case N_EXP_CAST : - prt_A_TYPE(node->llink, s+1); - prt_expression(node->rlink, s+1); break; case N_EXP_MUL : case N_EXP_DIV : case N_EXP_MOD : case N_EXP_ADD : case N_EXP_SUB : - case N_EXP_LSS : case N_EXP_GTR : - case N_EXP_LEQ : case N_EXP_GEQ : case N_EXP_NEQ : case N_EXP_EQL : case N_EXP_AND : case N_EXP_OR : case N_EXP_ASSIGN : - prt_expression(node->llink, s+1); - prt_expression(node->rlink, s+1); break; default : - printf("****syntax tree error******"); - } -} -void prt_arg_expr_list(A_NODE *node, int s) -{ - print_node(node,s); - switch(node->name) { case N_ARG_LIST : - prt_expression(node->llink, s+1); - prt_arg_expr_list(node->rlink, s+1); - break; case N_ARG_LIST_NIL : - break; default : - printf("****syntax tree error******"); - } -} -void prt_statement(A_NODE *node, int s) -{ - print_node(node,s); - switch(node->name) { case N_STMT_LABEL_CASE : - prt_expression(node->llink, s+1); - prt_statement(node->rlink, s+1); - break; case N_STMT_LABEL_DEFAULT : - prt_statement(node->clink, s+1); - break; case N_STMT_COMPOUND: - if(node->llink) - prt_A_ID_LIST(node->llink, s+1); - prt_statement_list(node->rlink, s+1); - break; case N_STMT_EMPTY: - break; case N_STMT_EXPRESSION: - prt_expression(node->clink, s+1); - break; case N_STMT_IF_ELSE: - prt_expression(node->llink, s+1); - prt_statement(node->clink, s+1); - prt_statement(node->rlink, s+1); - break; case N_STMT_IF: case N_STMT_SWITCH: - prt_expression(node->llink, s+1); - prt_statement(node->rlink, s+1); - break; case N_STMT_WHILE: - prt_expression(node->llink, s+1); - prt_statement(node->rlink, s+1); - break; case N_STMT_DO: - prt_statement(node->llink, s+1); - prt_expression(node->rlink, s+1); - break; - case N_STMT_FOR: - prt_for_expression(node->llink, s+1); - prt_statement(node->rlink, s+1); - break; case N_STMT_CONTINUE: - break; case N_STMT_BREAK: - break; case N_STMT_RETURN: - if(node->clink) - prt_expression(node->clink, s+1); - break; default : - printf("****syntax tree error******"); - } -} -void prt_statement_list(A_NODE *node, int s) -{ - print_node(node,s); - switch(node->name) { - case N_STMT_LIST: - prt_statement(node->llink, s+1); - prt_statement_list(node->rlink, s+1); - break; - case N_STMT_LIST_NIL: - break; - default : - printf("****syntax tree error******"); - } -} -void prt_for_expression(A_NODE *node, int s) -{ - print_node(node,s); - switch(node->name) { - case N_FOR_EXP : - if(node->llink) - prt_expression(node->llink, s+1); - if(node->clink) - prt_expression(node->clink, s+1); - if(node->rlink) - prt_expression(node->rlink, s+1); - break; default : - printf("****syntax tree error******"); - } -} -void prt_integer(int a, int s) -{ - print_space(s); - printf("%d\n", a); -} -void prt_STRING(char *str, int s) { - print_space(s); - printf("%s\n", str); -} - -char *type_kind_name[]={"NULL","ENUM","ARRAY","STRUCT","UNION","FUNC","POINTER","VOID"}; - -void prt_A_TYPE(A_TYPE *t, int s) -{ - print_space(s); - if (t==int_type) - printf("(int)\n"); - else if (t==float_type) - printf("(float)\n"); - else if (t==char_type) - printf("(char %d)\n",t->size); - else if (t==void_type) - printf("(void)"); - else if (t->kind==T_NULL) - printf("(null)"); - else if (t->prt) - printf("(DONE:%x)\n",t); - else - switch (t->kind) { - case T_ENUM: - t->prt=TRUE; - printf("ENUM\n"); - print_space(s); printf("| ENUMERATORS\n"); - prt_A_ID_LIST(t->field,s+2); - break; - case T_POINTER: - t->prt=TRUE; - printf("POINTER\n"); - print_space(s); printf("| ELEMENT_TYPE\n"); - prt_A_TYPE(t->element_type,s+2); - break; - case T_ARRAY: - t->prt=TRUE; - printf("ARRAY\n"); - print_space(s); printf("| INDEX\n"); - if (t->expr) - prt_expression(t->expr,s+2); - else - print_space(s+2); printf("(none)\n"); - print_space(s); printf("| ELEMENT_TYPE\n"); - prt_A_TYPE(t->element_type,s+2); - break; - case T_STRUCT: - t->prt=TRUE; - printf("STRUCT\n"); - print_space(s); printf("| FIELD\n"); - prt_A_ID_LIST(t->field,s+2); - break; - case T_UNION: - t->prt=TRUE; - printf("UNION\n"); - print_space(s); printf("| FIELD\n"); - prt_A_ID_LIST(t->field,s+2); - break; - case T_FUNC: - t->prt=TRUE; - printf("FUNCTION\n"); - print_space(s); printf("| PARAMETER\n"); - prt_A_ID_LIST(t->field,s+2); - print_space(s); printf("| TYPE\n"); - prt_A_TYPE(t->element_type,s+2); - if (t->expr) { - print_space(s); printf("| BODY\n"); - prt_statement(t->expr,s+2); - } - } -} -void prt_A_ID_LIST(A_ID *id, int s) -{ - while (id) { - prt_A_ID(id,s); - id=id->link; - } -} - - -char *id_kind_name[]={"NULL","VAR","FUNC","PARM","FIELD","TYPE","ENUM", - "STRUCT","ENUM_LITERAL"}; -char *spec_name[]={"NULL","AUTO","STATIC","TYPEDEF"}; - - -void prt_A_ID_NAME(A_ID *id, int s) -{ - print_space(s); - printf("(ID=\"%s\") TYPE:%x KIND:%s SPEC=%s LEV=%d VAL=%d ADDR=%d \n", - id->name, id->type, id_kind_name[id->kind], spec_name[id->specifier], id->level, id->value, id->address); -} -void prt_A_ID(A_ID *id, int s) -{ - print_space(s); - printf("(ID=\"%s\") TYPE:%x KIND:%s SPEC=%s LEV=%d VAL=%d ADDR=%d \n", - id->name, id->type, id_kind_name[id->kind], spec_name[id->specifier], id->level, id->value, id->address); - if (id->type) { - print_space(s); - printf("| TYPE\n"); - prt_A_TYPE(id->type,s+2);} - if (id->init) { - print_space(s); - printf("| INIT\n"); - if (id->kind==ID_ENUM_LITERAL) - prt_expression(id->init,s+2); - else - prt_initializer(id->init,s+2); - } -} \ No newline at end of file diff --git a/07-c-semantic-analyzer/sem_func.c b/07-c-semantic-analyzer/sem_func.c new file mode 100644 index 0000000..8baa88f --- /dev/null +++ b/07-c-semantic-analyzer/sem_func.c @@ -0,0 +1,1324 @@ +#include "type.h" +#include "sem_func.h" + +extern A_TYPE *int_type, *float_type, *char_type, *string_type, *void_type; + +int global_address = 12; +int semantic_err = 0; +A_LITERAL literal_table[LIT_MAX]; +int literal_no = 0; +int literal_size = 0; + +double atof(); + +void semantic_analysis(A_NODE *node) { + sem_program(node); + set_literal_address(node); +} + +void set_literal_address(A_NODE *node) { + int i; + for (i=1;i<=literal_no; i++) + literal_table[i].addr += node->value; + node->value+=literal_size; +} + +void sem_program(A_NODE *node) { // 원시 프로그램에서 선언된 전역 변수 크기 계산 + int i; + switch(node->name) { + case N_PROGRAM : + i = sem_declaration_list(node->clink, 12); + node->value = global_address; + break; + default : + semantic_error(90, node->line); + break; + } +} + +int put_literal(A_LITERAL lit, int ll) { + float ff; + if (literal_no >= LIT_MAX) + semantic_error(93, ll); + else + literal_no++; + literal_table[literal_no] = lit; + literal_table[literal_no].addr = literal_size; + if (lit.type->kind == T_ENUM) + literal_size += 4; + else if (isStringType(lit.type)) + literal_size += strlen(lit.value.s) + 1; + if (literal_size % 4) + literal_size = literal_size/4 * 4 + 4; + return(literal_no); +} + +A_TYPE *sem_expression(A_NODE *node) { +// 수식 분석, 필요한 경우 변환 +// 수식의 타입 계산하여 node에 저장하고 리턴 + A_TYPE *result=NIL, *t, *t1, *t2; + A_ID *id; + A_LITERAL lit = {0}; + int i; + BOOLEAN lvalue=FALSE; + switch(node->name) { + case N_EXP_IDENT : + id=node->clink; + switch (id->kind) { + case ID_VAR: + case ID_PARM: + result=id->type; + if (!isArrayType(result)) + lvalue = TRUE; + break; + case ID_FUNC: + result = id->type; + break; + case ID_ENUM_LITERAL: + result = int_type; + break; + default: + semantic_error(38, node->line, id->name); + break; + } + break; + case N_EXP_INT_CONST : + result = int_type; + break; + case N_EXP_FLOAT_CONST : + lit.type = float_type; + // lit.value.s = node->clink; + lit.value.f = atof(node->clink); + node->clink = put_literal(lit, node->line); // index of literal table + result = float_type; + break; + case N_EXP_CHAR_CONST : + result = char_type; + break; + case N_EXP_STRING_LITERAL : + lit.type = string_type; + lit.value.s = node->clink; + node->clink = put_literal(lit,node->line); // index of literal table + result = string_type; + break; + case N_EXP_ARRAY : + t1 = sem_expression(node->llink); + t2 = sem_expression(node->rlink); + // usual binary conversion + t = convertUsualBinaryConversion(node); + t1 = node->llink->type; + t2 = node->rlink->type; + if (isPointerOrArrayType_sem(t1)) + result = t1->element_type; + else + semantic_error(32,node->line); + if (!isIntegralType(t2)) + semantic_error(29,node->line); + if (!isArrayType(result)) + lvalue=TRUE; + break; + case N_EXP_STRUCT : + t = sem_expression(node->llink); + id = getStructFieldIdentifier(t,node->rlink); + if (id) { + result = id->type; + if (node->llink->value && !isArrayType(result)) + lvalue = TRUE; + } + else + semantic_error(37, node->line); + node->rlink = id; + break; + case N_EXP_ARROW: + t = sem_expression(node->llink); + id = getPointerFieldIdentifier(t,node->rlink); + if (id) { + result = id->type; + if (!isArrayType(result)) + lvalue = TRUE; + } + else + semantic_error(37,node->line); + node->rlink = id; + break; + case N_EXP_FUNCTION_CALL : + t = sem_expression(node->llink); + // usual unary conversion + node->llink = convertUsualUnaryConversion(node->llink); + t = node->llink->type; + if (isPointerType(t) && isFunctionType(t->element_type)) { + sem_arg_expr_list(node->rlink,t->element_type->field); + result = t->element_type->element_type; + } + else + semantic_error(21,node->line); + break; + case N_EXP_POST_INC : + case N_EXP_POST_DEC : + result = sem_expression(node->clink); + // usual binary conversion between the expression and 1 + if(!isScalarType(result)) + semantic_error(27,node->line); + // check if modifiable lvalue + if (!isModifiableLvalue(node->clink)) + semantic_error(60,node->line); + break; + case N_EXP_CAST : + result = node->llink; + i = sem_A_TYPE(result); + t = sem_expression(node->rlink); + // check allowable casting conversion + if (!isAllowableCastingConversion(result,t)) + semantic_error(58,node->line); + break; + case N_EXP_SIZE_TYPE : + t = node->clink; + i = sem_A_TYPE(t); + // check if incomplete array, function, void + if (isArrayType(t) && t->size == 0 || isFunctionType(t) || isVoidType(t)) + semantic_error(39,node->line); + else + node->clink = i; + result = int_type; + break; + case N_EXP_SIZE_EXP : + t=sem_expression(node->clink); + // check if incomplete array, function + if ((node->clink->name != N_EXP_IDENT || + ((A_ID*)node->clink->clink)->kind != ID_PARM) && + (isArrayType(t) && t->size == 0 || isFunctionType(t))) + semantic_error(39, node->line); + else + node->clink = t->size; + result = int_type; + break; + case N_EXP_PLUS : + case N_EXP_MINUS : + t = sem_expression(node->clink); + if (isArithmeticType(t)) { + node->clink = convertUsualUnaryConversion(node->clink); + result = node->clink->type; + } + else + semantic_error(13,node->line); + break; + case N_EXP_NOT : + t = sem_expression(node->clink); + if (isScalarType(t)) { + node->clink = convertUsualUnaryConversion(node->clink); + result = node->clink->type; + } + else + semantic_error(27, node->line); + break; + case N_EXP_AMP : + t = sem_expression(node->clink); + if (node->clink->value == TRUE || isFunctionType(t)) { + result = setTypeElementType(makeType(T_POINTER),t); + result->size = 4; + } + else + semantic_error(60, node->line); + break; + case N_EXP_STAR : + t = sem_expression(node->clink); + node->clink = convertUsualUnaryConversion(node->clink); + if (isPointerType(t)) { + result = t->element_type; + // lvalue if points to an object + if (isStructOrUnionType(result) || isScalarType(result)) + lvalue = TRUE; + } + else + semantic_error(31, node->line); + break; + case N_EXP_PRE_INC : + case N_EXP_PRE_DEC : + result = sem_expression(node->clink); + // usual binary conversion between the expression and 1 + if (!isScalarType(result)) + semantic_error(27, node->line); + // check if modifiable lvalue + if (!isModifiableLvalue(node->clink)) + semantic_error(60, node->line); + break; + case N_EXP_MUL : + case N_EXP_DIV : + t1 = sem_expression(node->llink); + t2 = sem_expression(node->rlink); + if (isArithmeticType(t1) && isArithmeticType(t2)) + result = convertUsualBinaryConversion(node); + else + semantic_error(28, node->line); + break; + case N_EXP_MOD : + t1 = sem_expression(node->llink); + t2 = sem_expression(node->rlink); + if (isIntegralType(t1) && isIntegralType(t2)) + result = convertUsualBinaryConversion(node); + else + semantic_error(29, node->line); + result = int_type; + break; + case N_EXP_ADD : + t1 = sem_expression(node->llink); + t2 = sem_expression(node->rlink); + if (isArithmeticType(t1) && isArithmeticType(t2)) + result = convertUsualBinaryConversion(node); + else if (isPointerType(t1) && isIntegralType(t2)) + result = t1; + else if (isIntegralType(t1) && isPointerType(t2)) + result = t2; + else + semantic_error(24,node->line); + break; + case N_EXP_SUB : + t1 = sem_expression(node->llink); + t2 = sem_expression(node->rlink); + if (isArithmeticType(t1) && isArithmeticType(t2)) + result = convertUsualBinaryConversion(node); + else if (isPointerType(t1) && isIntegralType(t2)) + result = t1; + else if (isCompatiblePointerType(t1, t2)) + result = t1; + else + semantic_error(24,node->line); + break; + case N_EXP_LSS : + case N_EXP_GTR : + case N_EXP_LEQ : + case N_EXP_GEQ : + t1=sem_expression(node->llink); + t2=sem_expression(node->rlink); + if (isArithmeticType(t1) && isArithmeticType(t2)) + result = convertUsualBinaryConversion(node); + else if (!isCompatiblePointerType(t1,t2)) + semantic_error(40, node->line); + result = int_type; + break; + case N_EXP_NEQ : + case N_EXP_EQL : + t1 = sem_expression(node->llink); + t2 = sem_expression(node->rlink); + if (isArithmeticType(t1) && isArithmeticType(t2)) + result = convertUsualBinaryConversion(node); + else if (!isCompatiblePointerType(t1, t2) && + (!isPointerType(t1) || isConstantZeroExp(node->rlink)) && + (!isPointerType(t2) || isConstantZeroExp(node->rlink))) + semantic_error(40, node->line); + result = int_type; + break; + case N_EXP_AND : + case N_EXP_OR : + t=sem_expression(node->llink); + if(!isScalarType(t)) + node->llink = convertUsualUnaryConversion(node->llink); + else + semantic_error(27, node->line); + t = sem_expression(node->rlink); + if(!isScalarType(t)) + node->rlink = convertUsualUnaryConversion(node->rlink); + else + semantic_error(27, node->line); + result = int_type; + break; + case N_EXP_ASSIGN : + result = sem_expression(node->llink); + // check modifiable lvalue + if(!isModifiableLvalue(node->llink)) + semantic_error(60, node->line); + t = sem_expression(node->rlink); + if(isAllowableAssignmentConversion(result, t, node->rlink)) { + if(isArithmeticType(result) && isArithmeticType(t)) + node->rlink = convertUsualAssignmentConversion(result, node->rlink); + } + else + semantic_error(58, node->line); + break; + default : + semantic_error(90, node->line); + break; + } + node->type = result; + node->value = lvalue; + return (result); +} + +// check argument-expression-list in function call expression +void sem_arg_expr_list(A_NODE *node, A_ID *id) +{ + A_TYPE *t; + A_ID *a; + int arg_size = 0; + switch(node->name) { + case N_ARG_LIST : + if (id == 0) + semantic_error(34, node->line); + else { + if (id->type) { + t = sem_expression(node->llink); + node->llink = convertUsualUnaryConversion(node->llink); + if (isAllowableCastingConversion(id->type, node->llink->type)) + node->llink = convertCastingConversion(node->llink, id->type); + else + semantic_error(59, node->line); + sem_arg_expr_list(node->rlink, id->link); + } + else { // DOTDOT parameter : no conversion + t = sem_expression(node->llink); + sem_arg_expr_list(node->rlink, id); + } + arg_size = node->llink->type->size + node->rlink->value; + } + break; + case N_ARG_LIST_NIL : + if (id && id->type) // check if '...' argument + semantic_error(35, node->line); + break; + default : + semantic_error(90, node->line); + break; + } + if (arg_size % 4) + arg_size = arg_size/4 * 4 + 4; + node->value = arg_size; +} + +BOOLEAN isModifiableLvalue(A_NODE *node) +{ + if (node->value == FALSE || isFunctionType(node->type)) + return FALSE; + else + return TRUE; +} + +// check statement and return local variable size +int sem_statement(A_NODE *node, int addr, A_TYPE *ret, BOOLEAN sw, BOOLEAN brk, BOOLEAN cnt) +{ // 명령문 분석 + // 복합문의 경우 명령문들에 나타난 지역 변수들의 크기를 계산/리턴 + int local_size = 0, i; + A_LITERAL lit; + A_TYPE *t; + switch(node->name) { + case N_STMT_LABEL_CASE : + if (sw == FALSE) // case statement is not in 'switch' + semantic_error(71, node->line); + lit = getTypeAndValueOfExpression(node->llink); + if (isIntegralType(lit.type)) + node->llink = lit.value.i; + else + semantic_error(51, node->line); + local_size = sem_statement(node->rlink, addr, ret, sw, brk, cnt); + break; + case N_STMT_LABEL_DEFAULT : + if (sw == FALSE) + semantic_error(72, node->line); + local_size = sem_statement(node->clink, addr, ret, sw, brk, cnt); + break; + case N_STMT_COMPOUND: + if(node->llink) + local_size = sem_declaration_list(node->llink, addr); + local_size += sem_statement_list(node->rlink, local_size + addr, ret, sw, brk, cnt); + break; + case N_STMT_EMPTY: + break; + case N_STMT_EXPRESSION: + t = sem_expression(node->clink); + break; + case N_STMT_IF: + t = sem_expression(node->llink); + if (isScalarType(t)) + node->llink = convertScalarToInteger(node->llink); + else + semantic_error(50, node->line); + local_size = sem_statement(node->rlink, addr, ret, FALSE, brk, cnt); + break; + case N_STMT_IF_ELSE: + t = sem_expression(node->llink); + if (isScalarType(t)) + node->llink = convertScalarToInteger(node->llink); + else + semantic_error(50, node->line); + local_size = sem_statement(node->clink, addr, ret, FALSE, brk, cnt); + i = sem_statement(node->rlink, addr, ret, FALSE, brk, cnt); + if (local_size < i) + local_size = i; + break; + case N_STMT_SWITCH: + t = sem_expression(node->llink); + if (!isIntegralType(t)) + semantic_error(50, node->line); + local_size = sem_statement(node->rlink, addr, ret, TRUE, TRUE, cnt); + case N_STMT_WHILE: + t = sem_expression(node->llink); + if (isScalarType(t)) + node->llink = convertScalarToInteger(node->llink); + else + semantic_error(50,node->line); + local_size = sem_statement(node->rlink, addr, ret, FALSE, TRUE, TRUE); + break; + case N_STMT_DO: + local_size = sem_statement(node->llink, addr, ret, FALSE, TRUE, TRUE); + t = sem_expression(node->rlink); + if (isScalarType(t)) + node->rlink = convertScalarToInteger(node->rlink); + else + semantic_error(50, node->line); + break; + case N_STMT_FOR: + sem_for_expression(node->llink); + local_size = sem_statement(node->rlink, addr, ret, FALSE, TRUE, TRUE); + break; + case N_STMT_CONTINUE: + if (cnt == FALSE) + semantic_error(74, node->line); + break; + case N_STMT_BREAK: + if (brk == FALSE) + semantic_error(73, node->line); + break; + case N_STMT_RETURN: + if(node->clink){ + t = sem_expression(node->clink); + if (isAllowableCastingConversion(ret, t)) + node->clink = convertCastingConversion(node->clink, ret); + else + semantic_error(57, node->line); + } + break; + default: + semantic_error(90, node->line); + break; + } + node->value = local_size; + return(local_size); +} + +void sem_for_expression(A_NODE *node) { + A_TYPE *t; + switch (node->name) { + case N_FOR_EXP : + if(node->llink) + t = sem_expression(node->llink); + if(node->clink) { + t = sem_expression(node->clink); + if (isScalarType(t)) + node->clink = convertScalarToInteger(node->clink); + else + semantic_error(49, node->line); + } + if(node->rlink) + t = sem_expression(node->rlink); + break; + default : + semantic_error(90, node->line); + break; + } +} + +// check statement-list and return local variable size +int sem_statement_list(A_NODE *node, int addr, A_TYPE *ret, BOOLEAN sw, BOOLEAN brk, BOOLEAN cnt) +{ // 명령문들 분석 + int size, i; + switch(node->name) { + case N_STMT_LIST: + size = sem_statement(node->llink, addr, ret, sw, brk, cnt); + i=sem_statement_list(node->rlink, addr, ret, sw, brk, cnt); + if(size < i) + size = i; + break; + case N_STMT_LIST_NIL: + size = 0; + break; + default : + semantic_error(90, node->line); + break; + } + node->value = size; + return(size); +} + +// check type and return its size (size of incomplete type is 0) +int sem_A_TYPE(A_TYPE *t) +{ // 타입 테이블 분석, 타입의 크기 계산 및 저장 + A_ID *id; + A_TYPE *tt; + A_LITERAL lit; + int result = 0, i; + + if (t->check) + return(t->size); + t->check = 1; + + switch (t->kind) { + case T_NULL: + semantic_error(80, t->line); + break; + case T_ENUM: + i = 0; + id = t->field; + while (id) { // enumerators + if (id->init){ + lit = getTypeAndValueOfExpression(id->init); + if (!isIntType(lit.type)) + semantic_error(81, id->line); + i = lit.value.i; + } + id->init = i++; + id = id->link; + } + result = 4; + break; + case T_ARRAY: + if (t->expr){ + lit = getTypeAndValueOfExpression(t->expr); + if (!isIntType(lit.type) || lit.value.i <= 0) { + semantic_error(82, t->line); + t->expr = 0; + } else + t->expr = lit.value.i; + } + i = sem_A_TYPE(t->element_type) * (int)t->expr; + if (isVoidType(t->element_type) || isFunctionType(t->element_type)) + semantic_error(83, t->line); + else + result = i; + break; + case T_STRUCT: + id = t->field; + while (id) { + result += sem_declaration(id,result); + id = id->link; + } + break; + case T_UNION: + id = t->field; + while (id) { + i = sem_declaration(id,0); + if (i > result) + result = i; + id = id->link; + } + break; + case T_FUNC: + tt = t->element_type; + i = sem_A_TYPE(tt); + if (isArrayType(tt) || isFunctionType(tt)) // check return type + semantic_error(85, t->line); + i = sem_declaration_list(t->field, 12) + 12; // parameter type & size + if (t->expr) { + i = i + sem_statement(t->expr, i, t->element_type, FALSE, FALSE, FALSE); + t->local_var_size = i; + break; + } + t->local_var_size = i; + break; + case T_POINTER: + i = sem_A_TYPE(t->element_type); + result = 4; + break; + case T_VOID: + break; + default: + semantic_error(90, t->line); + break; + } + t->size = result; + return(result); // 타입의 크기 리턴 +} + +// set variable address in declaration-list, and return its total variable size +int sem_declaration_list(A_ID *id, int addr) +{ + int i = addr; + while (id) { + addr += sem_declaration(id, addr); + id = id->link; + } + return(addr - i); +} + +// check declaration (identifier), set address, and return its size +int sem_declaration(A_ID *id,int addr) +{ // 선언문에 나타난 각 지역변수의 주소 설정, 크기 계산, 크기값 리턴 + A_TYPE *t; + int size = 0,i; + A_LITERAL lit; + + switch (id->kind) { + case ID_VAR: + i = sem_A_TYPE(id->type); + + // check empty array + if (isArrayType(id->type) && id->type->expr == NIL) + semantic_error(86, id->line); + if (i % 4) + i = i/4 * 4 + 4; + if (id->specifier == S_STATIC) + id->level = 0; + if (id->level == 0) // if global scope + { + id->address = global_address; + global_address += i; + } + else { + id->address = addr; + size = i; + } + break; + case ID_FIELD: + i = sem_A_TYPE(id->type); + if (isFunctionType(id->type) || isVoidType(id->type)) + semantic_error(84, id->line); + if (i % 4) + i = i/4 * 4 + 4; + id->address = addr; + size = i; + break; + case ID_FUNC: + i = sem_A_TYPE(id->type); + break; + case ID_PARM: + if (id->type) + { + size = sem_A_TYPE(id->type); + // usual unary conversion of parm type + if (id->type == char_type) + id->type = int_type; + else if (isArrayType(id->type)){ + id->type->kind = T_POINTER; + id->type->size = 4; + } + else if (isFunctionType(id->type)) { + t = makeType(T_POINTER); + t->element_type = id->type; + t->size = 4; + id->type = t; + } + size = id->type->size; + if (size % 4) + size = size/4 * 4 + 4; + id->address = addr; + } + break; + case ID_TYPE: + i = sem_A_TYPE(id->type); + break; + default: + semantic_error(89, id->line, id->name); + break; + } + return (size); +} + +A_ID *getStructFieldIdentifier(A_TYPE *t, char *s) { + A_ID *id = NIL; + if (isStructOrUnionType(t)) { + id = t->field; + while (id) { + if (strcmp(id->name, s)==0) + break; + id = id->link; + } + return(id); + } +} + +A_ID *getPointerFieldIdentifier(A_TYPE *t, char *s) { + A_ID *id = NIL; + if (t && t->kind == T_POINTER) { + t = t->element_type; + if (isStructOrUnionType(t)){ + id = t->field; + while (id) { + if (strcmp(id->name,s)==0) + break; + id = id->link; + } + } + } +} +BOOLEAN isSameParameterType(A_ID *a, A_ID *b) { + while (a) { + if (b == NIL || isNotSameType(a->type, b->type)) + return (FALSE); + a = a->link; + b = b->link; + } + if (b) + return (FALSE); + else + return (TRUE); +} + +BOOLEAN isCompatibleType(A_TYPE *t1, A_TYPE *t2) { + if (isArrayType(t1) && isArrayType(t2)) + if (t1->size == 0 || t2->size == 0 || t1->size == t2->size) + return(isCompatibleType(t1->element_type, t2->element_type)); + else + return(FALSE); + else if (isFunctionType(t1) && isFunctionType(t2)) + if (isSameParameterType(t1->field, t2->field)) + return(isCompatibleType(t1->element_type, t2->element_type)); + else + return (FALSE); + else if (isPointerType(t1) && isPointerType(t2)) + return(isCompatibleType(t1->element_type, t2->element_type)); + else + return(t1 == t2); +} + +BOOLEAN isConstantZeroExp(A_NODE *node) { + if (node->name == N_EXP_INT_CONST && node->clink == 0) + return (TRUE); + else + return (FALSE); +} + +BOOLEAN isCompatiblePointerType(A_TYPE *t1, A_TYPE *t2) { + if (isPointerType(t1) && isPointerType(t2)) + return(isCompatibleType(t1->element_type, t2->element_type)); + else + return(FALSE); +} + +A_NODE *convertScalarToInteger(A_NODE *node) { + if (isFloatType(node->type)) { + semantic_warning(16, node->line); + node=makeNode(N_EXP_CAST, int_type, NIL, node); + } + node->type = int_type; + return(node); +} + +A_NODE *convertUsualAssignmentConversion(A_TYPE *t1, A_NODE *node) +{ + A_TYPE *t2; + t2 = node->type; + if (!isCompatibleType(t1, t2)) { + semantic_warning(11, node->line); + node = makeNode(N_EXP_CAST, t1, NIL, node); + node->type = t1; + } + return (node); +} + +A_NODE *convertUsualUnaryConversion(A_NODE *node) { + A_TYPE *t; + t = node->type; + if (t == char_type) { + t = int_type; + node = makeNode(N_EXP_CAST, t, NIL, node); + node->type = t; + } + else if (isArrayType(t)){ + t = setTypeElementType(makeType(T_POINTER), t->element_type); + t->size = 4; + node = makeNode(N_EXP_CAST, t, NIL, node); + node->type = t; + } + else if (isFunctionType(t)){ + t = setTypeElementType(makeType(T_POINTER), t); + t->size = 4; + node = makeNode(N_EXP_AMP, NIL, node, NIL); + node->type = t; + } + return (node); +} + +A_TYPE *convertUsualBinaryConversion(A_NODE *node) { + A_TYPE *t1, *t2, *result = NIL; + t1 = node->llink->type; + t2 = node->rlink->type; + if(isFloatType(t1) && !isFloatType(t2)) { + semantic_warning(14, node->line); + node->rlink = makeNode(N_EXP_CAST, t1, NIL, node->rlink); + node->rlink->type = t1; + result = t1; + } + else if(!isFloatType(t1) && isFloatType(t2)) { + semantic_warning(14, node->line); + node->llink = makeNode(N_EXP_CAST, t2, NIL, node->llink); + node->llink->type = t2; + result = t2; + } + else if (t1 == t2) + result = t1; + else + result = int_type; + return (result); +} + +A_NODE *convertCastingConversion(A_NODE *node, A_TYPE *t1) { + A_TYPE *t2; + t2 = node->type; + if (!isCompatibleType(t1, t2)) { + semantic_warning(12, node->line); + node = makeNode(N_EXP_CAST,t1,NIL,node); + node->type = t1; + } + return (node); +} + +BOOLEAN isAllowableAssignmentConversion(A_TYPE *t1, A_TYPE *t2, A_NODE *node) // t1 <--- t2 +{ + if (isArithmeticType(t1) && isArithmeticType(t2)) + return (TRUE); + else if (isStructOrUnionType(t1) && isCompatibleType(t1, t2)) + return (TRUE); + else if (isPointerType(t1) && (isConstantZeroExp(node) || isCompatiblePointerType(t1, t2))) + return (TRUE); + else + return (FALSE); +} + +BOOLEAN isAllowableCastingConversion(A_TYPE *t1, A_TYPE *t2) // t1 <--- t2 +{ + if (isAnyIntegerType(t1) && + (isAnyIntegerType(t2) || isFloatType(t2) || isPointerType(t2))) + return (TRUE); + else if (isFloatType(t1) && isArithmeticType(t2)) + return (TRUE); + else if (isPointerType(t1) && (isAnyIntegerType(t2) || isPointerType(t2))) + return (TRUE); + else if (isVoidType(t1)) + return (TRUE); + else + return (FALSE); +} + +BOOLEAN isFloatType(A_TYPE *t) { + if (t == float_type) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isArithmeticType(A_TYPE *t) { + if (t && t->kind == T_ENUM) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isScalarType(A_TYPE *t) { + if (t && ((t->kind == T_ENUM) || (t->kind == T_POINTER))) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isAnyIntegerType(A_TYPE *t) { + if ( t && (t == int_type || t == char_type)) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isIntegralType(A_TYPE *t) { + if ( t && t->kind == T_ENUM && t != float_type) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isFunctionType(A_TYPE *t) { + if (t && t->kind == T_FUNC) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isStructOrUnionType(A_TYPE *t) +{ + if (t && (t->kind == T_STRUCT || t->kind == T_UNION)) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isPointerType(A_TYPE *t) { + if (t && t->kind == T_POINTER) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isPointerOrArrayType_sem(A_TYPE *t) { + if (t && (t->kind == T_POINTER || t->kind == T_ARRAY)) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isIntType(A_TYPE *t) { + if (t && t == int_type) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isVoidType(A_TYPE *t) { + if (t && t == void_type) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isArrayType(A_TYPE *t) { + if (t && t->kind == T_ARRAY) + return(TRUE); + else + return(FALSE); +} +BOOLEAN isStringType(A_TYPE *t) { + if (t && (t->kind == T_POINTER||t->kind==T_ARRAY) && + t->element_type == char_type) + return(TRUE); + else + return(FALSE); +} + +// convert literal type +A_LITERAL checkTypeAndConvertLiteral(A_LITERAL result, A_TYPE *t, int ll) { + if (result.type == int_type && t == int_type || + result.type == char_type && t == char_type || + result.type == float_type && t == float_type ) ; + else if (result.type==int_type && t==float_type){ + result.type=float_type; + result.value.f=result.value.i; + } + else if (result.type==int_type && t==char_type){ + result.type=char_type; + result.value.c=result.value.i; + } + else if (result.type==float_type && t==int_type){ + result.type=int_type; + result.value.i=result.value.f; + } + else if (result.type==char_type && t == int_type){ + result.type = int_type; + result.value.i = result.value.c; + } + else + semantic_error(41, ll); + return (result); +} + +A_LITERAL getTypeAndValueOfExpression(A_NODE *node) { + A_TYPE *t; + A_ID *id; + A_LITERAL result, r; + result.type = NIL; + switch(node->name) { + case N_EXP_IDENT : + id = node->clink; + if (id->kind != ID_ENUM_LITERAL) + semantic_error(19, node->line, id->name); + else { + result.type = int_type; + result.value.i = id->init; + } + break; + case N_EXP_INT_CONST : + result.type = int_type; + result.value.i = (int)node->clink; + break; + case N_EXP_CHAR_CONST : + result.type = char_type; + result.value.c = (char)node->clink; + break; + case N_EXP_FLOAT_CONST : + result.type = float_type; + result.value.f = atof(node->clink); + break; + case N_EXP_STRING_LITERAL : + case N_EXP_ARRAY : + case N_EXP_FUNCTION_CALL : + case N_EXP_STRUCT : + case N_EXP_ARROW : + case N_EXP_POST_INC : + case N_EXP_PRE_INC : + case N_EXP_POST_DEC : + case N_EXP_PRE_DEC : + case N_EXP_AMP : + case N_EXP_STAR : + case N_EXP_NOT : + semantic_error(18, node->line); + break; + case N_EXP_MINUS : + result = getTypeAndValueOfExpression(node->clink); + if (result.type == int_type) + result.value.i = -result.value.i; + else if (result.type == float_type) + result.value.f = -result.value.f; + else + semantic_error(18, node->line); + break; + case N_EXP_SIZE_EXP : + t = sem_expression(node->clink); + result.type = int_type; + result.value.i = t->size; + break; + case N_EXP_SIZE_TYPE : + result.type = int_type; + result.value.i = sem_A_TYPE(node->clink); + break; + case N_EXP_CAST : + result = getTypeAndValueOfExpression(node->rlink); + result = checkTypeAndConvertLiteral(result, (A_TYPE*)node->llink, node->line); + break; + case N_EXP_MUL : + result = getTypeAndValueOfExpression(node->llink); + r = getTypeAndValueOfExpression(node->rlink); + if (result.type == int_type && r.type == int_type){ + result.type = int_type; + result.value.i = result.value.i * r.value.i; + } + else if (result.type == int_type && r.type == float_type){ + result.type = float_type; + result.value.f = result.value.i * r.value.f; + } + else if (result.type == float_type && r.type == int_type){ + result.type = float_type; + result.value.f = result.value.f * r.value.i; + } + else if (result.type == float_type && r.type == float_type){ + result.type = float_type; + result.value.f = result.value.f * r.value.f; + } + else + semantic_error(18, node->line); + break; + case N_EXP_DIV : + result = getTypeAndValueOfExpression(node->llink); + r = getTypeAndValueOfExpression(node->rlink); + if (result.type == int_type && r.type == int_type){ + result.type = int_type; + result.value.i = result.value.i / r.value.i; + } + else if (result.type == int_type && r.type == float_type){ + result.type = float_type; + result.value.f = result.value.i / r.value.f; + } + else if (result.type == float_type && r.type == int_type){ + result.type = float_type; + result.value.f = result.value.f / r.value.i; + } + else if (result.type == float_type && r.type == float_type){ + result.type = float_type; + result.value.f = result.value.f / r.value.f; + } + else + semantic_error(18, node->line); + break; + case N_EXP_MOD : + result = getTypeAndValueOfExpression(node->llink); + r = getTypeAndValueOfExpression(node->rlink); + if (result.type == int_type && r.type == int_type) + result.value.i = result.value.i % r.value.i; + else + semantic_error(18, node->line); + break; + case N_EXP_ADD : + result = getTypeAndValueOfExpression(node->llink); + r = getTypeAndValueOfExpression(node->rlink); + if (result.type == int_type && r.type == int_type){ + result.type = int_type; + result.value.i = result.value.i + r.value.i;} + else if (result.type == int_type && r.type == float_type){ + result.type = float_type; + result.value.f = result.value.i + r.value.f; + } + else if (result.type == float_type && r.type == int_type){ + result.type = float_type; + result.value.f = result.value.f + r.value.i; + } + else if (result.type == float_type && r.type == float_type){ + result.type = float_type; + result.value.f = result.value.f + r.value.f; + } + else + semantic_error(18, node->line); + break; + case N_EXP_SUB : + result = getTypeAndValueOfExpression(node->llink); + r = getTypeAndValueOfExpression(node->rlink); + if (result.type == int_type && r.type == int_type){ + result.type = int_type; + result.value.i = result.value.i - r.value.i; + } + else if (result.type == int_type && r.type == float_type){ + result.type = float_type; + result.value.f = result.value.i - r.value.f; + } + else if (result.type == float_type && r.type == int_type){ + result.type = float_type; + result.value.f = result.value.f - r.value.i; + } + else if (result.type == float_type && r.type == float_type){ + result.type = float_type; + result.value.f = result.value.f - r.value.f; + } + else + semantic_error(18, node->line); + break; + case N_EXP_LSS : + case N_EXP_GTR : + case N_EXP_LEQ : + case N_EXP_GEQ : + case N_EXP_NEQ : + case N_EXP_EQL : + case N_EXP_AND : + case N_EXP_OR : + case N_EXP_ASSIGN : + semantic_error(18, node->line); + break; + default : + semantic_error(90, node->line); + break; + } + return (result); +} + +void semantic_error(int i, int ll, char *s) +{ + semantic_err++; + printf("*** semantic error at line %d: ", ll); + + switch (i) { + case 13: + printf("arith type expr required in unary operation\n"); + break; + case 18: + printf("illegal constant expression \n"); + break; + case 19: + printf("illegal identifier %s in constant expression\n", s); + break; + case 21: + printf("illegal type in function call expression\n"); + break; + case 24: + printf("incompatible type in additive expression\n"); + break; + case 27: + printf("scalar type expr required in expression\n"); + break; + case 28: + printf("arith type expression required in binary operation\n"); + break; + case 29: + printf("integral type expression required in expression\n"); + break; + case 31: + printf("pointer type expr required in pointer operation\n"); + break; + case 32: + printf("array type required in array expression\n"); + break; + case 34: + printf("too many arguments in function call\n"); + break; + case 35: + printf("too few arguments in function call\n"); + break; + case 37: + printf("illegal struct field identifier in struct reference expr\n"); + break; + case 38: + printf("illegal kind of identifier %s in expression\n"); + break; + case 39: + printf("illegal type size in sizeof operation\n"); + break; + case 40: + printf("illegal expression type in relational operation\n"); + break; + case 41: + printf("incompatible type in literal\n"); + break; + + // errors in statement + case 49: + printf("scalar type expr required in middle of for-expr\n"); + break; + case 50: + printf("integral type expression required in statement\n"); + break; + case 51: + printf("illegal expression type in case label\n"); + break; + case 57: + printf("not permitted type conversion in return expression\n"); + break; + case 58: + printf("not permitted type casting in expression\n"); + break; + case 59: + printf("not permitted type conversion in argument\n"); + break; + case 60: + printf("expression is not an lvalue \n"); + break; + case 71: + printf("case label not within a switch statement \n"); + break; + case 72: + printf("default label not within a switch statement \n"); + break; + case 73: + printf("break statement not within loop or switch stmt\n"); + break; + case 74: + printf("continue statement not within a loop \n"); + break; + // errors in type & declarator + case 80: + printf("undefined type\n"); + break; + case 81: + printf("integer type expression required in enumerator\n"); + break; + case 82: + printf("illegal array size or type\n"); + break; + case 83: + printf("illegal element type of array declarator\n"); + break; + case 84: + printf("illegal type in struct or union field\n"); + break; + case 85: + printf("invalid function return type\n"); + break; + case 86: + printf("illegal array size or empty array \n"); + break; + case 89: + printf("unknown identifier kind: %s\n", s); + break; + // misc errors + case 90: + printf("fatal compiler error in parse result\n"); + break; + case 93: + printf("too many literals in source program \n"); + break; + default: + printf("unknown \n"); + break; + } +} + +void semantic_warning(int i, int ll) +{ + printf("--- warning at line %d:", ll); + switch (i) + { + case 11: + printf("incompatible types in assignment expression\n"); + break; + case 12: + printf("incompatible types in argument or return expr\n"); + break; + case 14: + printf("incompatible types in binary expression\n"); + break; + case 16: + printf("integer type expression is required\n"); + break; + default: + printf("unknown\n"); + break; + } +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/sem_func.h b/07-c-semantic-analyzer/sem_func.h new file mode 100644 index 0000000..5f6b9ec --- /dev/null +++ b/07-c-semantic-analyzer/sem_func.h @@ -0,0 +1,55 @@ +#ifndef _SEM_FUNC_H_ +#define _SEM_FUNC_H_ + +#define LIT_MAX 100 + +void semantic_analysis(A_NODE *); +void set_literal_address(A_NODE *); +int put_literal(A_LITERAL, int); +void sem_program(A_NODE *); +A_TYPE*sem_expression(A_NODE *); +int sem_statement(A_NODE *, int, A_TYPE *, BOOLEAN, BOOLEAN, BOOLEAN); +int sem_statement_list(A_NODE *, int, A_TYPE *, BOOLEAN, BOOLEAN, BOOLEAN); +void sem_for_expression(A_NODE *); +int sem_A_TYPE(A_TYPE *) ; +int sem_declaration_list(A_ID *id, int addr); +int sem_declaration(A_ID *,int); +void sem_arg_expr_list(A_NODE *, A_ID *); +A_ID *getStructFieldIdentifier(A_TYPE *, char *); +A_ID *getPointerFieldIdentifier(A_TYPE *, char *); +A_NODE *convertScalarToInteger(A_NODE *); +A_NODE *convertUsualAssignmentConversion(A_TYPE *, A_NODE *); +A_NODE *convertUsualUnaryConversion(A_NODE *); +A_TYPE *convertUsualBinaryConversion(A_NODE *); +A_NODE *convertCastingConversion(A_NODE *,A_TYPE *); +BOOLEAN isAllowableAssignmentConversion(A_TYPE *, A_TYPE *, A_NODE *); +BOOLEAN isAllowableCastingConversion(A_TYPE *, A_TYPE *); +BOOLEAN isModifiableLvalue(A_NODE *); +BOOLEAN isConstantZeroExp(A_NODE *); +BOOLEAN isSameParameterType(A_ID *, A_ID *); +BOOLEAN isNotSameType(A_TYPE *, A_TYPE *); +BOOLEAN isCompatibleType(A_TYPE *, A_TYPE *); +BOOLEAN isCompatiblePointerType(A_TYPE *, A_TYPE *); +BOOLEAN isIntType(A_TYPE *); +BOOLEAN isFloatType(A_TYPE *); +BOOLEAN isArithmeticType(A_TYPE *); +BOOLEAN isAnyIntegerType(A_TYPE *); +BOOLEAN isIntegralType(A_TYPE *); +BOOLEAN isStructOrUnionType(A_TYPE *); +BOOLEAN isFunctionType(A_TYPE *); +BOOLEAN isScalarType(A_TYPE *); +BOOLEAN isPointerType(A_TYPE *); +BOOLEAN isPointerOrArrayType_sem(A_TYPE *); +BOOLEAN isArrayType(A_TYPE *); +BOOLEAN isStringType(A_TYPE *); +BOOLEAN isVoidType(A_TYPE *); +A_LITERAL checkTypeAndConvertLiteral(A_LITERAL,A_TYPE*, int); +A_LITERAL getTypeAndValueOfExpression(A_NODE *); +A_TYPE *setTypeElementType(A_TYPE *, A_TYPE *); +A_TYPE *makeType(T_KIND); +void setTypeSize(A_TYPE *, int); +void semantic_warning(int, int); +void semantic_error(); +A_NODE *makeNode(NODE_NAME, A_NODE *, A_NODE *, A_NODE*); + +#endif \ No newline at end of file diff --git a/07-c-semantic-analyzer/sem_print.c b/07-c-semantic-analyzer/sem_print.c new file mode 100644 index 0000000..101010a --- /dev/null +++ b/07-c-semantic-analyzer/sem_print.c @@ -0,0 +1,415 @@ +#include "type.h" + +char * node_name[] = { + "N_NULL", + "N_PROGRAM", + "N_EXP_IDENT", + "N_EXP_INT_CONST", + "N_EXP_FLOAT_CONST", + "N_EXP_CHAR_CONST", + "N_EXP_STRING_LITERAL", + "N_EXP_ARRAY", + "N_EXP_FUNCTION_CALL", + "N_EXP_STRUCT", + "N_EXP_ARROW", + "N_EXP_POST_INC", + "N_EXP_POST_DEC", + "N_EXP_PRE_INC", + "N_EXP_PRE_DEC", + "N_EXP_AMP", + "N_EXP_STAR", + "N_EXP_NOT", + "N_EXP_PLUS", + "N_EXP_MINUS", + "N_EXP_SIZE_EXP", + "N_EXP_SIZE_TYPE", + "N_EXP_CAST", + "N_EXP_MUL", + "N_EXP_DIV", + "N_EXP_MOD", + "N_EXP_ADD", + "N_EXP_SUB", + "N_EXP_LSS", + "N_EXP_GTR", + "N_EXP_LEQ", + "N_EXP_GEQ", + "N_EXP_NEQ", + "N_EXP_EQL", + "N_EXP_AND", + "N_EXP_OR", + "N_EXP_ASSIGN", + "N_ARG_LIST", + "N_ARG_LIST_NIL", + "N_STMT_LABEL_CASE", + "N_STMT_LABEL_DEFAULT", + "N_STMT_COMPOUND", + "N_STMT_EMPTY", + "N_STMT_EXPRESSION", + "N_STMT_IF", + "N_STMT_IF_ELSE", + "N_STMT_SWITCH", + "N_STMT_WHILE", + "N_STMT_DO", + "N_STMT_FOR", + "N_STMT_RETURN", + "N_STMT_CONTINUE", + "N_STMT_BREAK", + "N_FOR_EXP", + "N_STMT_LIST", + "N_STMT_LIST_NIL", + "N_INIT_LIST", + "N_INIT_LIST_ONE", + "N_INIT_LIST_NIL" +}; +char *id_kind_name[]={"NULL","VAR","FUNC","PARM","FIELD","TYPE","ENUM", + "STRUCT","ENUM_LITERAL"}; +char *spec_name[]={"NULL","AUTO","STATIC","TYPEDEF"}; + +void print_sem_ast(A_NODE *); +void prt_sem_program(A_NODE *, int); +void prt_sem_initializer(A_NODE *, int); +void prt_sem_arg_expr_list(A_NODE *, int); +void prt_sem_statement(A_NODE *, int); +void prt_sem_statement_list(A_NODE *, int); +void prt_sem_for_expression(A_NODE *, int); +void prt_sem_expression(A_NODE *, int); +void prt_sem_A_TYPE(A_TYPE *, int); +void prt_sem_A_ID_LIST(A_ID *, int); +void prt_sem_A_ID(A_ID *, int); +void prt_sem_A_ID_NAME(A_ID *, int); +void prt_sem_LITERAL(int, int); +void prt_sem_integer(int, int); +void print_node(A_NODE *,int); +void print_space(int); + +extern A_TYPE *int_type, *float_type, *char_type, *void_type, *string_type; +extern A_LITERAL literal_table[]; + +void print_node(A_NODE *node, int s) +{ + print_space(s); + printf("%s (%x,%d)\n", node_name[node->name],node->type,node->value); +} +void print_space(int s) +{ + int i; + for(i=1; i<=s; i++) printf("| "); +} +void print_sem_ast(A_NODE *node) +{ + printf("======= semantic tree ==========\n"); + prt_sem_program(node,0); +} +void prt_sem_program(A_NODE *node, int s) +{ + print_node(node,s); + switch(node->name) { + case N_PROGRAM: + prt_sem_A_ID_LIST(node->clink, s+1); + break; + default : + printf("****syntax tree error******"); + } +} +void prt_sem_initializer(A_NODE *node, int s) +{ + print_node(node,s); + switch(node->name) { + case N_INIT_LIST: + prt_sem_initializer(node->llink, s+1); + prt_sem_initializer(node->rlink, s+1); + break; + case N_INIT_LIST_ONE: + prt_sem_expression(node->clink, s+1); + break; + case N_INIT_LIST_NIL: + break; + default : + printf("****syntax tree error******"); + } +} +void prt_sem_expression(A_NODE *node, int s) +{ + print_node(node,s); + switch(node->name) { + case N_EXP_IDENT : + prt_sem_A_ID_NAME(node->clink, s+1); + break; + case N_EXP_INT_CONST : + prt_sem_integer(node->clink, s+1); + break; + case N_EXP_FLOAT_CONST : + prt_sem_LITERAL(node->clink, s+1); + break; + case N_EXP_CHAR_CONST : + prt_sem_integer(node->clink, s+1); + break; + case N_EXP_STRING_LITERAL : + prt_sem_LITERAL(node->clink, s+1); + break; + case N_EXP_ARRAY : + prt_sem_expression(node->llink, s+1); + prt_sem_expression(node->rlink, s+1); + break; + case N_EXP_FUNCTION_CALL : + prt_sem_expression(node->llink, s+1); + prt_sem_arg_expr_list(node->rlink, s+1); + break; + case N_EXP_STRUCT: + case N_EXP_ARROW : + prt_sem_expression(node->llink, s+1); + prt_sem_A_ID_NAME(node->rlink, s+1); + break; + case N_EXP_POST_INC : + case N_EXP_POST_DEC : + case N_EXP_PRE_INC : + case N_EXP_PRE_DEC : + case N_EXP_AMP : + case N_EXP_STAR : + case N_EXP_NOT : + case N_EXP_PLUS : + case N_EXP_MINUS : + prt_sem_expression(node->clink, s+1); + break; + case N_EXP_SIZE_EXP : + case N_EXP_SIZE_TYPE : + prt_sem_integer(node->clink, s+1); + break; + case N_EXP_CAST : + prt_sem_A_TYPE(node->llink, s+1); + prt_sem_expression(node->rlink, s+1); + break; + case N_EXP_MUL : + case N_EXP_DIV : + case N_EXP_MOD : + case N_EXP_ADD : + case N_EXP_SUB : + case N_EXP_LSS : + case N_EXP_GTR : + case N_EXP_LEQ : + case N_EXP_GEQ : + case N_EXP_NEQ : + case N_EXP_EQL : + case N_EXP_AND : + case N_EXP_OR : + case N_EXP_ASSIGN : + prt_sem_expression(node->llink, s+1); + prt_sem_expression(node->rlink, s+1); + break; + default : + printf("****syntax tree error******"); + } +} +void prt_sem_arg_expr_list(A_NODE *node, int s) +{ + print_node(node,s); + switch(node->name) { + case N_ARG_LIST : + prt_sem_expression(node->llink, s+1); + prt_sem_arg_expr_list(node->rlink, s+1); + break; + case N_ARG_LIST_NIL : + break; + default : + printf("****syntax tree error******"); + } +} +void prt_sem_statement(A_NODE *node, int s) +{ + print_node(node,s); + switch(node->name) { + case N_STMT_LABEL_CASE : + prt_sem_integer(node->llink, s+1); + prt_sem_statement(node->rlink, s+1); + break; + case N_STMT_LABEL_DEFAULT : + prt_sem_statement(node->clink, s+1); + break; + case N_STMT_COMPOUND: + if(node->llink) + prt_sem_A_ID_LIST(node->llink, s+1); + prt_sem_statement_list(node->rlink, s+1); + break; + case N_STMT_EMPTY: + break; + case N_STMT_EXPRESSION: + prt_sem_expression(node->clink, s+1); + break; + case N_STMT_IF_ELSE: + prt_sem_expression(node->llink, s+1); + prt_sem_statement(node->clink, s+1); + prt_sem_statement(node->rlink, s+1); + break; + case N_STMT_IF: + case N_STMT_SWITCH: + case N_STMT_WHILE: + prt_sem_expression(node->llink, s+1); + prt_sem_statement(node->rlink, s+1); + break; + case N_STMT_DO: + prt_sem_statement(node->llink, s+1); + prt_sem_expression(node->rlink, s+1); + break; + case N_STMT_FOR: + prt_sem_for_expression(node->llink, s+1); + prt_sem_statement(node->rlink, s+1); + break; + case N_STMT_CONTINUE: + break; + case N_STMT_BREAK: + break; + case N_STMT_RETURN: + if(node->clink) + prt_sem_expression(node->clink, s+1); + break; + default : + printf("****syntax tree error******"); + } +} +void prt_sem_statement_list(A_NODE *node, int s) +{ + print_node(node,s); + switch(node->name) { + case N_STMT_LIST: + prt_sem_statement(node->llink, s+1); + prt_sem_statement_list(node->rlink, s+1); + break; + case N_STMT_LIST_NIL: + break; + default : + printf("****syntax tree error******"); + } +} +void prt_sem_for_expression(A_NODE *node, int s) +{ + print_node(node,s); + switch(node->name) { + case N_FOR_EXP : + if(node->llink) + prt_sem_expression(node->llink, s+1); + if(node->clink) + prt_sem_expression(node->clink, s+1); + if(node->rlink) + prt_sem_expression(node->rlink, s+1); + break; + default : + printf("****syntax tree error******"); + } +} +void prt_sem_integer(int a, int s) +{ + print_space(s); + printf("INT=%d\n", a); +} + +void prt_sem_LITERAL(int lit, int s) +{ + print_space(s); + // printf("LITERAL: "); + // if (str) printf("%s\n", str); + // else printf("\n"); + if (literal_table[lit].type == int_type) + printf("%d\n", literal_table[lit].value.i); + if (literal_table[lit].type == float_type) + printf("%f\n", literal_table[lit].value.f); + else if (literal_table[lit].type == string_type) + printf("%s\n", literal_table[lit].value.s); +} + +char *type_kind_name[]={"NULL","ENUM","ARRAY","STRUCT","UNION","FUNC","POINTER","VOID"}; + +void prt_sem_A_TYPE(A_TYPE *t, int s) +{ + print_space(s); + if (t==int_type) + printf("(int)\n"); + else if (t==float_type) + printf("(float)\n"); + else if (t==char_type) + printf("(char %d)\n",t->size); + else if (t==void_type) + printf("(void)\n"); + else if (t->kind==T_NULL) + printf("(null)\n"); + else if (t->prt) + printf("(DONE:%x)\n",t); + else + switch (t->kind) { + case T_ENUM: + t->prt=FALSE; + printf("ENUM\n"); + print_space(s); printf("| ENUMERATORS\n"); + prt_sem_A_ID_LIST(t->field,s+2); + break; + case T_POINTER: + t->prt=FALSE; + printf("POINTER\n"); + print_space(s); printf("| ELEMENT_TYPE\n"); + prt_sem_A_TYPE(t->element_type,s+2); + break; + case T_ARRAY: + t->prt=FALSE; + printf("ARRAY\n"); + print_space(s); printf("| INDEX\n"); + prt_sem_integer(t->expr, s+2); + print_space(s); printf("| ELEMENT_TYPE\n"); + prt_sem_A_TYPE(t->element_type,s+2); + break; + case T_STRUCT: + t->prt=FALSE; + printf("STRUCT\n"); + print_space(s); printf("| FIELD\n"); + prt_sem_A_ID_LIST(t->field,s+2); + break; + case T_UNION: + t->prt=FALSE; + printf("UNION\n"); + print_space(s); printf("| FIELD\n"); + prt_sem_A_ID_LIST(t->field,s+2); + break; + case T_FUNC: + t->prt=FALSE; + printf("FUNCTION\n"); + print_space(s); printf("| PARAMETER\n"); + prt_sem_A_ID_LIST(t->field,s+2); + print_space(s); printf("| TYPE\n"); + prt_sem_A_TYPE(t->element_type,s+2); + if (t->expr) { + print_space(s); printf("| BODY\n"); + prt_sem_statement(t->expr,s+2); + } + } +} +void prt_sem_A_ID_LIST(A_ID *id, int s) +{ + while (id) { + prt_sem_A_ID(id,s); + id=id->link; + } +} + + +void prt_sem_A_ID_NAME(A_ID *id, int s) +{ + print_space(s); + printf("(ID=\"%s\") TYPE:%x KIND:%s SPEC=%s LEV=%d VAL=%d ADDR=%d \n", + id->name, id->type, id_kind_name[id->kind], spec_name[id->specifier], id->level, id->value, id->address); +} +void prt_sem_A_ID(A_ID *id, int s) +{ + print_space(s); + printf("(ID=\"%s\") TYPE:%x KIND:%s SPEC=%s LEV=%d VAL=%d ADDR=%d \n", + id->name, id->type, id_kind_name[id->kind], spec_name[id->specifier], id->level, id->value, id->address); + if (id->type) { + print_space(s); + printf("| TYPE\n"); + prt_sem_A_TYPE(id->type,s+2);} + if (id->init) { + print_space(s); + printf("| INIT\n"); + if (id->kind==ID_ENUM_LITERAL) + prt_sem_integer(id->init,s+2); + else + prt_sem_initializer(id->init,s+2); + } +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err13.c b/07-c-semantic-analyzer/test/err13.c new file mode 100644 index 0000000..b3da46e --- /dev/null +++ b/07-c-semantic-analyzer/test/err13.c @@ -0,0 +1,8 @@ +struct s { + int a; +} mystruct; + +void main() { + int result; + result = -mystruct; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err18.c b/07-c-semantic-analyzer/test/err18.c new file mode 100644 index 0000000..3295384 --- /dev/null +++ b/07-c-semantic-analyzer/test/err18.c @@ -0,0 +1,7 @@ +int func() { + return 10; +} + +void main() { + int arr[func()]; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err19.c b/07-c-semantic-analyzer/test/err19.c new file mode 100644 index 0000000..5a94d98 --- /dev/null +++ b/07-c-semantic-analyzer/test/err19.c @@ -0,0 +1,4 @@ +void main() { + int size = 10; + int arr[size]; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err21.c b/07-c-semantic-analyzer/test/err21.c new file mode 100644 index 0000000..1a4830b --- /dev/null +++ b/07-c-semantic-analyzer/test/err21.c @@ -0,0 +1,4 @@ +void main() { + int i = 10; + i(); +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err24.c b/07-c-semantic-analyzer/test/err24.c new file mode 100644 index 0000000..f3f2759 --- /dev/null +++ b/07-c-semantic-analyzer/test/err24.c @@ -0,0 +1,8 @@ +struct s { + int a; +} mystruct; + +void main() { + int i = 10; + i = i + mystruct; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err27.c b/07-c-semantic-analyzer/test/err27.c new file mode 100644 index 0000000..08f557d --- /dev/null +++ b/07-c-semantic-analyzer/test/err27.c @@ -0,0 +1,8 @@ +struct S { + int a; +}; + +void main() { + struct S s; + !s; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err28.c b/07-c-semantic-analyzer/test/err28.c new file mode 100644 index 0000000..3823c98 --- /dev/null +++ b/07-c-semantic-analyzer/test/err28.c @@ -0,0 +1,5 @@ +void main() { + int *p; + int i = 10; + p * i; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err29.c b/07-c-semantic-analyzer/test/err29.c new file mode 100644 index 0000000..266495a --- /dev/null +++ b/07-c-semantic-analyzer/test/err29.c @@ -0,0 +1,5 @@ +void main() { + float f = 3.14; + int i = 2; + f % i; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err31.c b/07-c-semantic-analyzer/test/err31.c new file mode 100644 index 0000000..d29f2d0 --- /dev/null +++ b/07-c-semantic-analyzer/test/err31.c @@ -0,0 +1,4 @@ +void main() { + int i = 10; + *i; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err32.c b/07-c-semantic-analyzer/test/err32.c new file mode 100644 index 0000000..1f69fbb --- /dev/null +++ b/07-c-semantic-analyzer/test/err32.c @@ -0,0 +1,4 @@ +void main() { + int i = 10; + i[0]; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err34.c b/07-c-semantic-analyzer/test/err34.c new file mode 100644 index 0000000..1e85c0c --- /dev/null +++ b/07-c-semantic-analyzer/test/err34.c @@ -0,0 +1,7 @@ +int func(int a) { + return a; +} + +void main() { + func(1, 2); +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err35.c b/07-c-semantic-analyzer/test/err35.c new file mode 100644 index 0000000..a87d8a1 --- /dev/null +++ b/07-c-semantic-analyzer/test/err35.c @@ -0,0 +1,7 @@ +int func(int a, int b) { + return a + b; +} + +void main() { + func(1); +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err37.c b/07-c-semantic-analyzer/test/err37.c new file mode 100644 index 0000000..9b318e0 --- /dev/null +++ b/07-c-semantic-analyzer/test/err37.c @@ -0,0 +1,8 @@ +struct S { + int a; +}; + +void main() { + struct S s; + s.b; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err39.c b/07-c-semantic-analyzer/test/err39.c new file mode 100644 index 0000000..2a00e01 --- /dev/null +++ b/07-c-semantic-analyzer/test/err39.c @@ -0,0 +1,5 @@ +void func() { } + +void main() { + sizeof(func); +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err40.c b/07-c-semantic-analyzer/test/err40.c new file mode 100644 index 0000000..3f80d01 --- /dev/null +++ b/07-c-semantic-analyzer/test/err40.c @@ -0,0 +1,8 @@ +struct S { + int a; +}; + +void main() { + struct S s1, s2; + s1 < s2; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err41.c b/07-c-semantic-analyzer/test/err41.c new file mode 100644 index 0000000..c801550 --- /dev/null +++ b/07-c-semantic-analyzer/test/err41.c @@ -0,0 +1,3 @@ +void main() { + int a[(int*)0]; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err49.c b/07-c-semantic-analyzer/test/err49.c new file mode 100644 index 0000000..e786554 --- /dev/null +++ b/07-c-semantic-analyzer/test/err49.c @@ -0,0 +1,9 @@ +struct S { + int a; +}; + +void main() { + struct S s; + for (; s; ) { + } +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err50.c b/07-c-semantic-analyzer/test/err50.c new file mode 100644 index 0000000..f685620 --- /dev/null +++ b/07-c-semantic-analyzer/test/err50.c @@ -0,0 +1,6 @@ +void main() { + float f = 3.14; + switch (f) { + case 1: break; + } +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err51.c b/07-c-semantic-analyzer/test/err51.c new file mode 100644 index 0000000..41ecba9 --- /dev/null +++ b/07-c-semantic-analyzer/test/err51.c @@ -0,0 +1,6 @@ +void main() { + int i = 1; + switch (i) { + case 3.14: break; + } +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err57.c b/07-c-semantic-analyzer/test/err57.c new file mode 100644 index 0000000..3fa914f --- /dev/null +++ b/07-c-semantic-analyzer/test/err57.c @@ -0,0 +1,8 @@ +struct S { + int a; +}; + +int func() { + struct S s; + return s; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err58.c b/07-c-semantic-analyzer/test/err58.c new file mode 100644 index 0000000..ec23836 --- /dev/null +++ b/07-c-semantic-analyzer/test/err58.c @@ -0,0 +1,8 @@ +struct S { + int a; +}; + +void main() { + struct S s; + (int)s; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err59.c b/07-c-semantic-analyzer/test/err59.c new file mode 100644 index 0000000..840e0da --- /dev/null +++ b/07-c-semantic-analyzer/test/err59.c @@ -0,0 +1,11 @@ +struct S { + int a; +}; + +void func(struct S s) { +} + +void main() { + int i = 10; + func(i); +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err60.c b/07-c-semantic-analyzer/test/err60.c new file mode 100644 index 0000000..006240b --- /dev/null +++ b/07-c-semantic-analyzer/test/err60.c @@ -0,0 +1,3 @@ +void main() { + 10 = 20; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err71.c b/07-c-semantic-analyzer/test/err71.c new file mode 100644 index 0000000..ac34dc1 --- /dev/null +++ b/07-c-semantic-analyzer/test/err71.c @@ -0,0 +1,3 @@ +void main() { + case 1: ; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err72.c b/07-c-semantic-analyzer/test/err72.c new file mode 100644 index 0000000..56b5386 --- /dev/null +++ b/07-c-semantic-analyzer/test/err72.c @@ -0,0 +1,3 @@ +void main() { + default: ; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err73.c b/07-c-semantic-analyzer/test/err73.c new file mode 100644 index 0000000..c9aa467 --- /dev/null +++ b/07-c-semantic-analyzer/test/err73.c @@ -0,0 +1,3 @@ +void main() { + break; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err74.c b/07-c-semantic-analyzer/test/err74.c new file mode 100644 index 0000000..dba0ef0 --- /dev/null +++ b/07-c-semantic-analyzer/test/err74.c @@ -0,0 +1,3 @@ +void main() { + continue; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err80.c b/07-c-semantic-analyzer/test/err80.c new file mode 100644 index 0000000..3daa3c1 --- /dev/null +++ b/07-c-semantic-analyzer/test/err80.c @@ -0,0 +1,5 @@ +struct S; + +void main() { + struct S s; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err81.c b/07-c-semantic-analyzer/test/err81.c new file mode 100644 index 0000000..93419ef --- /dev/null +++ b/07-c-semantic-analyzer/test/err81.c @@ -0,0 +1,6 @@ +enum E { + A = 3.14 +}; + +void main() { +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err82.c b/07-c-semantic-analyzer/test/err82.c new file mode 100644 index 0000000..a6154a8 --- /dev/null +++ b/07-c-semantic-analyzer/test/err82.c @@ -0,0 +1,3 @@ +void main() { + int a[-1]; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err83.c b/07-c-semantic-analyzer/test/err83.c new file mode 100644 index 0000000..b6defe1 --- /dev/null +++ b/07-c-semantic-analyzer/test/err83.c @@ -0,0 +1,3 @@ +void main() { + void a[10]; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err84.c b/07-c-semantic-analyzer/test/err84.c new file mode 100644 index 0000000..0091e7b --- /dev/null +++ b/07-c-semantic-analyzer/test/err84.c @@ -0,0 +1,6 @@ +struct S { + void a; +}; + +void main() { +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err85.c b/07-c-semantic-analyzer/test/err85.c new file mode 100644 index 0000000..3c3384e --- /dev/null +++ b/07-c-semantic-analyzer/test/err85.c @@ -0,0 +1,7 @@ +typedef int ARR[10]; + +ARR func() { +} + +void main() { +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/err86.c b/07-c-semantic-analyzer/test/err86.c new file mode 100644 index 0000000..836a803 --- /dev/null +++ b/07-c-semantic-analyzer/test/err86.c @@ -0,0 +1,3 @@ +void main() { + int a[]; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/test01.c b/07-c-semantic-analyzer/test/test01.c new file mode 100644 index 0000000..087be72 --- /dev/null +++ b/07-c-semantic-analyzer/test/test01.c @@ -0,0 +1,9 @@ +int add(int a, int b) { + return a + b; +} +int main() { + int x = 3; + int y = 4; + int z = add(x, y); + return z; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/test02.c b/07-c-semantic-analyzer/test/test02.c new file mode 100644 index 0000000..295ca7f --- /dev/null +++ b/07-c-semantic-analyzer/test/test02.c @@ -0,0 +1,6 @@ +int main() { + int arr[5]; + int *p = arr; + int x = p[2]; + return x; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/test03.c b/07-c-semantic-analyzer/test/test03.c new file mode 100644 index 0000000..b38e59f --- /dev/null +++ b/07-c-semantic-analyzer/test/test03.c @@ -0,0 +1,10 @@ +struct Node { + int value; + char *str; +}; +int main() { + struct Node a; + a.value = 10; + a.str = 0; + return a.value; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/test04.c b/07-c-semantic-analyzer/test/test04.c new file mode 100644 index 0000000..e27f9d1 --- /dev/null +++ b/07-c-semantic-analyzer/test/test04.c @@ -0,0 +1,11 @@ +float mul(float x, float y) { + return x * y; +} + +int main() { + float a = 3.5; + float b = 2.0; + float c; + c = mul(a, b); + return 0; +} diff --git a/07-c-semantic-analyzer/test/warn11.c b/07-c-semantic-analyzer/test/warn11.c new file mode 100644 index 0000000..bc20983 --- /dev/null +++ b/07-c-semantic-analyzer/test/warn11.c @@ -0,0 +1,5 @@ +void main() { + int i; + float f = 3.14; + i = f; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/warn12.c b/07-c-semantic-analyzer/test/warn12.c new file mode 100644 index 0000000..c0c5741 --- /dev/null +++ b/07-c-semantic-analyzer/test/warn12.c @@ -0,0 +1,7 @@ +int func() { + float f = 3.14; + return f; +} + +void main() { +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/warn14.c b/07-c-semantic-analyzer/test/warn14.c new file mode 100644 index 0000000..cb53a11 --- /dev/null +++ b/07-c-semantic-analyzer/test/warn14.c @@ -0,0 +1,5 @@ +void main() { + float f = 3.14; + int i = 10; + f + i; +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/test/warn16.c b/07-c-semantic-analyzer/test/warn16.c new file mode 100644 index 0000000..2192726 --- /dev/null +++ b/07-c-semantic-analyzer/test/warn16.c @@ -0,0 +1,4 @@ +void main() { + if (3.14) { + } +} \ No newline at end of file diff --git a/07-c-semantic-analyzer/type.h b/07-c-semantic-analyzer/type.h index c8a2e9a..08c35a0 100644 --- a/07-c-semantic-analyzer/type.h +++ b/07-c-semantic-analyzer/type.h @@ -111,7 +111,7 @@ typedef struct s_id { // 심볼 테이블 struct s_id *link; } A_ID; -typedef union {int i; float f; char c; char *s;} LIT_VALUE; +typedef union {int i; double f; char c; char *s;} LIT_VALUE; typedef struct lit {int addr; A_TYPE *type; LIT_VALUE value;} A_LITERAL;