xcc.y


    1 %{
    2 #include <stdio.h>
    3 #include <stddef.h>
    4 #include <stdlib.h>
    5 #include <assert.h>
    6 #include "xcc.h"
    7 #include "AST.h"
    8 #include "type.h"
    9 #include "symbol.h"
   10 #include "debug.h"
   11 #include "codegen.h"
   12 #define YYERROR_VERBOSE
   13 
   14 static void init(int argc, char *argv[]);
   15 
   16 struct AST *ast_root;
   17 int AST_is_local = 0;
   18 FILE *xcc_out;
   19 %}
   20 
   21 %token CHAR	"char"
   22 %token ELSE	"else"
   23 %token GOTO	"goto"
   24 %token IF	"if"
   25 %token INT	"int"
   26 %token RETURN	"return"
   27 %token VOID	"void"
   28 %token WHILE	"while"
   29 
   30 %token IDENTIFIER
   31 
   32 %token INTEGER
   33 %token CHARACTER
   34 %token STRING
   35 
   36 %token EQ	"=="
   37 %token NEQ	"!="
   38 %token LEQ	"<="
   39 %token GEQ	">="
   40 %token AND	"&&"
   41 %token OR	"||"
   42 
   43 %right '='
   44 %left "||"
   45 %left "&&"
   46 %left "==" "!="
   47 %left '<' '>' "<=" ">="
   48 %left '+' '-'
   49 %left '*' '/' '%'
   50 %right UNARY_OPERATOR
   51 %left '(' ')'
   52 %right ELSE
   53 
   54 %start translation_unit
   55 
   56 %%
   57 translation_unit
   58  : external_declaration
   59 	{ $$ = create_AST(AST_translation_unit_single, 1, $1);
   60 	  ast_root = $$; }
   61  | translation_unit external_declaration
   62 	{ $$ = create_AST(AST_translation_unit_pair, 2, $1, $2);
   63 	  ast_root = $$; }
   64  ;
   65 
   66 external_declaration
   67  : function_definition
   68 	{ $$ = create_AST(AST_external_declaration_func, 1, $1); }
   69  | declaration
   70 	{ $$ = create_AST(AST_external_declaration_dec, 1, $1);
   71 	  symbol_table.arg = NULL;
   72 	  symbol_table.label = NULL;
   73 	  symbol_table.string = NULL; }
   74  ;
   75 
   76 function_definition
   77  : type_specifier declarator
   78 	{ $$ = create_AST(AST_dummy, 2, $1, $2);
   79 	  $$->type = type_analyze_declarator($2, $1->type);
   80 	  symbol_entry_param($$->type);
   81 	  symbol_entry($$);
   82 	  symbol_begin_function(); }
   83    compound_statement
   84 	{ $$ = create_AST(AST_function_definition, 3, $1, $3, $4);
   85 	  symbol_backpatch($$, $3->type);
   86 	  symbol_end_function($$); }
   87  ;
   88 
   89 declaration_list
   90  : /* empty rule */
   91 	{ $$ = create_AST(AST_declaration_list_null, 0); }
   92  | declaration_list declaration
   93 	{ $$ = create_AST(AST_declaration_list_pair, 2, $1, $2); }
   94  ;
   95 
   96 declaration
   97  : type_specifier declarator ';'
   98 	{ $$ = create_AST(AST_declaration, 2, $1, $2);
   99 	  $$->type = type_analyze_declarator($2, $1->type);
  100 	  symbol_entry($$); }
  101  ;
  102 
  103 type_specifier
  104  : "void"
  105 	{ $$ = create_AST(AST_type_specifier_void, 0);
  106 	  $$->type = create_prim_type(PRIM_TYPE_VOID); }
  107  | "int"
  108 	{ $$ = create_AST(AST_type_specifier_int, 0);
  109 	  $$->type = create_prim_type(PRIM_TYPE_INT); }
  110  | "char"
  111 	{ $$ = create_AST(AST_type_specifier_char, 0);
  112 	  $$->type = create_prim_type(PRIM_TYPE_CHAR); }
  113  ;
  114 
  115 declarator
  116  : IDENTIFIER
  117 	{ $$ = create_AST(AST_declarator_id, 1, $1); }
  118  | '*' declarator
  119 	{ $$ = create_AST(AST_declarator_pointer, 1, $2); }
  120  | '(' declarator ')'
  121 	{ $$ = create_AST(AST_declarator_paren, 1, $2); }
  122  | declarator '(' parameter_list ')'
  123 	{ $$ = create_AST(AST_declarator_func, 2, $1, $3); }
  124  | declarator '(' ')'
  125 	{ $$ = create_AST(AST_declarator_func_null, 1, $1); }
  126  ;
  127 
  128 parameter_list
  129  : parameter_declaration
  130 	{ $$ = create_AST(AST_parameter_list_single, 1, $1); }
  131  | parameter_list ',' parameter_declaration
  132 	{ $$ = create_AST(AST_parameter_list_pair, 2, $1, $3); }
  133  ;
  134 
  135 parameter_declaration
  136  : type_specifier declarator
  137 	{ $$ = create_AST(AST_parameter_declaration, 2, $1, $2);
  138 	  $$->type = type_analyze_declarator($2, $1->type);
  139 	  /* symbol_entry($$); */ }
  140  ;
  141 
  142 statement_list
  143  : statement
  144 	{ $$ = create_AST(AST_statement_list_single, 1, $1); }
  145  | statement_list statement
  146 	{ $$ = create_AST(AST_statement_list_pair, 2, $1, $2); }
  147  ;
  148 
  149 statement
  150  : ';'
  151 	{ $$ = create_AST(AST_statement_null, 0); }
  152  | expression ';'
  153 	{ $$ = create_AST(AST_statement_exp, 1, $1); }
  154  | compound_statement
  155 	{ $$ = create_AST(AST_statement_comp, 1, $1); }
  156  | "if" '(' expression ')' statement
  157 	{ $$ = create_AST(AST_statement_if, 2, $3, $5); }
  158  | "if" '(' expression ')' statement "else" statement
  159 	{ $$ = create_AST(AST_statement_if_else, 3, $3, $5, $7); }
  160  | "while" '(' expression ')' statement
  161 	{ $$ = create_AST(AST_statement_while, 2, $3, $5); }
  162  | "goto" IDENTIFIER ';'
  163 	{ $$ = create_AST(AST_statement_goto, 1, $2); }
  164  | IDENTIFIER ':' statement
  165 	{ $$ = create_AST(AST_statement_label, 2, $1, $3);
  166 	  symbol_entry($$); }
  167  | "return" expression ';'
  168 	{ $$ = create_AST(AST_statement_return, 1, $2); }
  169  | "return" ';'
  170 	{ $$ = create_AST(AST_statement_return_null, 0); }
  171  ;
  172 
  173 compound_statement
  174  : '{'
  175 	{ symbol_begin_block(); }
  176    declaration_list
  177 	{ symbol_middle_block(); }
  178    statement_list '}'
  179 	{ $$ = create_AST(AST_compound_statement, 2, $3, $5);
  180 	  symbol_end_block($$); }
  181  ;
  182 
  183 expression
  184  : IDENTIFIER
  185 	{ struct Symbol *symbol;
  186 	  $$ = create_AST(AST_expression_id, 1, $1);
  187 	  symbol = symbol_check_var_decl($$);
  188 	  $$->type = symbol->type; }
  189  | INTEGER
  190 	{ $$ = create_AST(AST_expression_int, 1, atoi(yytext));
  191 	  $$->type = types.t_int; }
  192  | CHARACTER
  193 	{ $$ = create_AST(AST_expression_char, 1, yytext[1]);
  194 	  $$->type = types.t_int; }
  195  | STRING
  196 	{ $$ = create_AST(AST_expression_string, 1, string_buf);
  197 	  $$->type = types.t_char_p;
  198 	  string_entry($$->u.id); }
  199  | expression '=' expression
  200 	{ $$ = create_AST(AST_expression_assign, 2, $1, $3);
  201 	  $$->type = $1->type; }
  202  | expression '<' expression
  203 	{ $$ = create_AST(AST_expression_lss, 2, $1, $3);
  204 	  $$->type = types.t_int; }
  205  | expression '>' expression
  206 	{ $$ = create_AST(AST_expression_gtr, 2, $1, $3);
  207 	  $$->type = types.t_int; }
  208  | expression "==" expression
  209 	{ $$ = create_AST(AST_expression_eq, 2, $1, $3);
  210 	  $$->type = types.t_int; }
  211  | expression "!=" expression
  212 	{ $$ = create_AST(AST_expression_neq, 2, $1, $3);
  213 	  $$->type = types.t_int; }
  214  | expression "<=" expression
  215 	{ $$ = create_AST(AST_expression_leq, 2, $1, $3);
  216 	  $$->type = types.t_int; }
  217  | expression ">=" expression
  218 	{ $$ = create_AST(AST_expression_geq, 2, $1, $3);
  219 	  $$->type = types.t_int; }
  220  | expression "&&" expression
  221 	{ $$ = create_AST(AST_expression_and, 2, $1, $3);
  222 	  $$->type = types.t_int; }
  223  | expression "||" expression
  224 	{ $$ = create_AST(AST_expression_or, 2, $1, $3);
  225 	  $$->type = types.t_int; }
  226  | expression '+' expression
  227 	{ $$ = create_AST(AST_expression_add, 2, $1, $3);
  228 	  $$->type = type_add($1->type, $3->type); }
  229  | expression '-' expression
  230 	{ $$ = create_AST(AST_expression_sub, 2, $1, $3);
  231 	  $$->type = type_sub($1->type, $3->type); }
  232  | expression '*' expression
  233 	{ $$ = create_AST(AST_expression_mult, 2, $1, $3);
  234 	  $$->type = types.t_int; }
  235  | expression '/' expression
  236 	{ $$ = create_AST(AST_expression_div, 2, $1, $3);
  237 	  $$->type = types.t_int; }
  238  | expression '%' expression
  239 	{ $$ = create_AST(AST_expression_mod, 2, $1, $3);
  240 	  $$->type = types.t_int; }
  241  | '&' expression %prec UNARY_OPERATOR
  242 	{ $$ = create_AST(AST_expression_unary_address, 1, $1);
  243 	  $$->type = create_pointer_type($1->type); }
  244  | '*' expression %prec UNARY_OPERATOR
  245 	{ $$ = create_AST(AST_expression_unary_deref, 1, $1);
  246 	  $$->type = type_check_pointer_deref($$, $2->type); }
  247  | '+' expression %prec UNARY_OPERATOR
  248 	{ $$ = create_AST(AST_expression_unary_plus, 1, $1);
  249 	  $$->type = types.t_int; }
  250  | '-' expression %prec UNARY_OPERATOR
  251 	{ $$ = create_AST(AST_expression_unary_minus, 1, $1);
  252 	  $$->type = types.t_int; }
  253  | '!' expression %prec UNARY_OPERATOR
  254 	{ $$ = create_AST(AST_expression_unary_negative, 1, $1);
  255 	  $$->type = types.t_int; }
  256  | expression '(' argument_expression_list ')'
  257 	{ $$ = create_AST(AST_expression_func, 2, $1, $3);
  258 	  $$->type = $1->type->u.t_function.ret_type;
  259 	  if ($3->u2.arg_size - 24 > total_arg_size)
  260 		total_arg_size = $3->u2.arg_size - 24; }
  261  | expression '(' ')'
  262 	{ $$ = create_AST(AST_expression_func_null, 1, $1);
  263 	  $$->type = $1->type->u.t_function.ret_type; }
  264  | '(' expression ')'
  265 	{ $$ = create_AST(AST_expression_paren, 1, $2);
  266 	  $$->type = $2->type; }
  267  ;
  268 
  269 argument_expression_list
  270  : expression
  271 	{ $$ = create_AST(AST_argument_expression_list_single, 1, $1);
  272 	  $$->u2.arg_size = ROUNDUP($1->type->size, 4); }
  273  | argument_expression_list ',' expression
  274 	{ $$ = create_AST(AST_argument_expression_list_pair, 2, $1, $3);
  275 	  $$->u2.arg_size = $1->u2.arg_size + ROUNDUP($3->type->size, 4); }
  276  ;
  277 
  278 %%
  279 static void init(int argc, char *argv[]) {
  280 	if (argc != 2) {
  281 		fprintf(stderr, "Usage: %s filename\n", argv[0]);
  282 		exit(1);
  283 	}
  284 	yyin = fopen(argv[1], "r");
  285 	if (yyin == NULL) {
  286 		fprintf(stderr, "can't open %s\n", argv[1]);
  287 		exit(1);
  288 	}
  289 	types.t_void = create_prim_type(PRIM_TYPE_VOID);
  290 	types.t_int = create_prim_type(PRIM_TYPE_INT);
  291 	types.t_char = create_prim_type(PRIM_TYPE_CHAR);
  292 	types.t_char_p = create_pointer_type(types.t_char);
  293 	xcc_out = stdout;
  294 }
  295 
  296 int yyerror(char *mesg) {
  297 	fprintf(stderr, "yyerror: %d: %s around `%s'\n", line_index, mesg, yytext);
  298 	exit(1);
  299 }
  300 
  301 void *emalloc(size_t nbytes) {
  302 	void *p = malloc(nbytes);
  303 
  304 	if (p == NULL)
  305 		perror("malloc");
  306 	return p;
  307 }
  308 
  309 void efree(void *ptr) {
  310 	free (ptr);
  311 }
  312 
  313 int main(int argc, char *argv[]) {
  314 	FILE *fp;
  315 
  316 	init(argc, argv);
  317 	yyparse();
  318 #if DEBUG
  319 	fp = fopen("debug.xml", "w");
  320 	if (fp == NULL) {
  321 		fprintf(stderr, "can't open %debug.xml\n");
  322 		exit(1);
  323 	}
  324 	debug(ast_root, fp);
  325 	fclose(fp);
  326 #endif
  327 	start_code(argv[1]);
  328 	codegen(ast_root);
  329 	end_code();
  330 	fclose(yyin);
  331 }