?? c.y
字號:
/*
* C.Y
* Grammar file for C Compiler
*
* Copyright (c) 2001 by Ren Qi and Lin Ying
* All Rights Reserved.
*
*/
%{
#include "Common.h"
#include "Debug.h"
#include "Error.h"
#include "SymTab.h"
#include "GBStrTab.h"
#include "GenCode.h"
#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
extern char* yytext;
// globe value
// used by cSTRING , record current string context
char g_String[MAX_STR_LEN];
const char _FUNCTION_NAME[] = "func_%s";
const char _CASE_NAME[] = "_case_";
const char _DEFAULT_NAME[] = "_default_";
const char _STRING_NAME[] = "_string_";
#define IS_CASE(x) ( !strcmp( (x)->name, _CASE_NAME ) )
#define IS_DEFAULT(x) ( !strcmp( (x)->name, _DEFAULT_NAME ) )
// label buffer for return
static char sg_return_label_buf[LABEL_LEN];
// used by function, to add parameter list to compound statement
static symbol *sg_parameter_list = NULL;
#define PARSE_INFO(x) StrToDebug(x, "\nIn yyparse() : ", " --- YACC");
void set_return_label(char *lb);
void gen_return_label();
void gen_return_stmt(symbol *x);
char *get_string_context(char *s);
int yylex();
%}
%union
{
// note : NAME_LEN == 32
char p_char[32];
int num;
int ascii;
symbol *p_symbol;
}
/* Definition of terminals */
%term <p_char>idTYPEDEF
%term kFOR
%term kWHILE
%term kIF
%term kELSE
%term kCASE
%term kSWITCH
%term kDEFAULT
%term kGOTO
%term kRETURN
%term kDO
%term kBREAK
%term kCONTINUE
%term kSIZEOF
%term kAUTO
%term kREGISTER
%term kSTATIC
%term kEXTERN
%term kTYPEDEF
%term kINT
%term kLONG
%term kSHORT
%term kCHAR
%term kVOID
%term kFLOAT
%term kDOUBLE
%term kSIGNED
%term kUNSIGNED
%term kCONST
%term kVOLATILE
%term cSTRING /* STRING CONSTANT */
%term <num>cINT /* INT CONSTANT */
%term <p_char>cREAL /* REAL CONSTANT */
%term <p_char>cCHAR /* CHAR CONSTANT */
%term oPLUS
%term oMINUS
%term oMUL
%term oDIV
%term oMOD
%term oEQUAL
%term oASSIGN
%term oUNEQU
%term oLT
%term oLE
%term oGT
%term oGE
%term oCOMMA
%term oSEMI
%term oCOLON
%term oQUESTION
%term oQUOTE
%term oDOTDOTDOT
%term oARROW
%term oLP
%term oRP
%term oLB
%term oRB
%term oLC
%term oRC
%term oBITOR
%term oBITAND
%term oBITNOT
%term oBITXOR
%term oLFTSHT
%term oRITSHT
%term oOR
%term oAND
%term oNOT
%term oADDADD
%term oSUBSUB
%term oPLUSASSIGN
%term oMINUSASSIGN
%term oMULASSIGN
%term oDIVASSIGN
%term oMODASSIGN
%term oBITORASSIGN
%term oBITANDASSIGN
%term oBITNOTASSIGN
%term oBITXORASSIGN
%term oLFTSHTASSIGN
%term oRITSHTASSIGN
%term <p_char>yNAME
/* preprocessor */
%term pINCLUDE
%term pINCLDNAME
/* Definition of nonterminals */
%type <p_symbol>storage_class_specifier type_specifier type_qualifier
%type <p_symbol>declaration_specifiers
%type <p_char>identifier
%type <p_symbol>direct_declarator declarator init_declarator init_declarator_list
%type <p_symbol>declaration declaration_list
%type <p_symbol>parameter_declaration parameter_list parameter_type_list
%type <p_symbol>abstract_declarator direct_abstract_declarator
%type <p_symbol>initializer
%type <p_symbol>function_definition
%type <p_symbol>constant primary_expression postfix_expression unary_expression
%type <p_symbol>cast_expression multiplicative_expression additive_expression
%type <p_symbol>shift_expression relational_expression equality_expression
%type <p_symbol>AND_expression exclusive_OR_expression inclusive_OR_expression
%type <p_symbol>logical_AND_expression logical_OR_expression constant_expression
%type <p_symbol>conditional_expression assignment_expression
%type <p_symbol>expression
%type <p_symbol>argument_expression_list
/*%type <num>unary_operator*/
/*%type <num>assignment_operator*/
/*
// no attribute nonterminals
translation_unit
external_declaration
statement
labeled_statement
expression_statement
statement_list
iteration_statement
jump_statement
*/
%start translation_unit
%%
translation_unit
: external_declaration
{
PARSE_INFO("translation_unit :external_declaration")
}
| translation_unit external_declaration
{
PARSE_INFO("translation_unit :translation_unit external_declaration")
}
;
external_declaration
: function_definition
{
PARSE_INFO("external_declaration :function_definition")
}
| declaration
{
PARSE_INFO("external_declaration :declaration")
// gen globe value
gen_globe_var_list($1);
}
| control_line
{
PARSE_INFO("external_declaration :control_line")
}
;
function_definition
: declaration_specifiers declarator
{
PARSE_INFO("function_definition :declaration_specifiers declarator ")
assert( IS_FUNCTION($2) );
unoin_specifier_to_declarator($1, $2);
del_symbol( $1 );
check_function_retval($2);
// $2->args point to parameter list
// so we can tell the compound statement to link the parameters
// assign $2->args to sg_parameter_list to tell compound statement
sg_parameter_list = $2->args;
// add function definition to sg_function_symtab
// for function call itself
// can search in function definition table
$2 = add_function_def_to_functab($2);
// for compound statement code genc in code2 files
open_code2();
// set return label
set_return_label(get_a_label());
// create goto label symtab
create_goto_label_symtab();
}
compound_statement
{
PARSE_INFO("compound_statement")
// destory the goto label
destory_goto_label_symtab();
// gen return label
gen_return_label();
// set func offset
set_func_offset($2);
// gen function head
gen_func_head($2);
// copy compound statement in code2 to code
copy_code2_code();
// add function end
gen_func_end($2);
// since compound statement code has copy to code file,
// then close code2 for next function
close_code2();
$$ = $2;
}
| declarator
{
PARSE_INFO("function_definition :declarator ")
assert( IS_FUNCTION($1) );
// default the function return value is int
$1->NOUN = SPEC_INT;
// $1->args point to parameter list
// so we can tell the compound statement to link the parameters
// assign $1->args to sg_parameter_list to tell compound statement
sg_parameter_list = $1->args;
// add function definition to sg_function_symtab
// for function call itself
// can search in function definition table
$1 = add_function_def_to_functab($1);
// for compound statement code genc in code2 files
open_code2();
// set return label
set_return_label(get_a_label());
// create goto label symtab
create_goto_label_symtab();
}
compound_statement
{
PARSE_INFO("compound_statement")
// destory the goto label
destory_goto_label_symtab();
// gen return label
gen_return_label();
// set func offset
set_func_offset($1);
// gen function head
gen_func_head($1);
// copy compound statement in code2 to code
copy_code2_code();
// add function end
gen_func_end($1);
// since compound statement code has copy to code file,
// then close code2 for next function
close_code2();
}
;
declaration
: declaration_specifiers init_declarator_list oSEMI
{
symbol *decl_lst;
PARSE_INFO("declaration :declaration_specifiers init_declarator_list oSEMI")
// at same time check declarator , not be void
unoin_specifier_to_declarator_list($1, $2);
del_symbol( $1 );
// $2 is a list
// so add all function in the list to function symtab
decl_lst = $2;
while ( decl_lst )
{
if (IS_FUNCTION(decl_lst))
{
// is function declaration
// so add it to function declaration symtab
// set decl flag
decl_lst->is_declaration = 1;
// only declaration
// add or only check parameter type
// not overwrite parameters type
add_function_decl_to_functab(decl_lst);
}
else if ( IS_LOCAL_VAR(decl_lst) )
{
check_var_declarator(decl_lst);
}
decl_lst = decl_lst->next;
}
add_symbol_list_to_current_symtab($2);
$$ = $2;
}
| declaration_specifiers oSEMI
{
PARSE_INFO("declaration :declaration_specifiers oSEMI")
// empty declaration
// so delete it
del_symbol( $1 );
yyerror("waring : ignored on left of specifier when no variable is declared");
$$ = NULL;
}
;
declaration_list
: declaration
{
PARSE_INFO("declaration_list :declaration")
}
| declaration_list declaration
{
PARSE_INFO("declaration_list :declaration_list declaration")
link_symbol_list( $1, $2 );
}
;
declaration_specifiers
: storage_class_specifier declaration_specifiers
{
PARSE_INFO("declaration_specifiers :storage_class_specifier declaration_specifiers")
union_specifier_symbol( $1, $2 );
del_symbol( $2 );
}
| storage_class_specifier
{
PARSE_INFO("declaration_specifiers :storage_class_specifier")
}
| type_specifier declaration_specifiers
{
PARSE_INFO("declaration_specifiers :type_specifier declaration_specifiers")
union_specifier_symbol( $1, $2 );
del_symbol( $2 );
}
| type_specifier
{
PARSE_INFO("declaration_specifiers :type_specifier")
}
| type_qualifier declaration_specifiers
{
PARSE_INFO("declaration_specifiers :type_qualifier declaration_specifiers")
union_specifier_symbol( $1, $2 );
del_symbol( $2 );
}
| type_qualifier
{
PARSE_INFO("declaration_specifiers :type_qualifier")
}
;
storage_class_specifier
: kAUTO
{
PARSE_INFO("storage_class_specifier :kAUTO")
$$ = new_symbol();
$$->SCLASS = SPEC_AUTO;
}
| kREGISTER
{
PARSE_INFO("storage_class_specifier :kREGISTER")
$$ = new_symbol();
$$->SCLASS = SPEC_REGISTER;
}
| kSTATIC
{
PARSE_INFO("storage_class_specifier :kSTATIC")
$$ = new_symbol();
$$->IS_STATIC = 1;
}
| kTYPEDEF
{
PARSE_INFO("storage_class_specifier :kTYPEDEF")
$$ = new_symbol();
$$->SCLASS = SPEC_TYPEDEF;
}
| kEXTERN
{
PARSE_INFO("storage_class_specifier :kEXTERN")
$$ = new_symbol();
$$->IS_EXTERN = 1;
}
;
type_specifier
: kINT
{
PARSE_INFO("type_specifier :kINT")
$$ = new_symbol();
$$->NOUN = SPEC_INT;
}
| kLONG
{
PARSE_INFO("type_specifier :kLONG")
$$ = new_symbol();
$$->NOUN = SPEC_INT;
$$->IS_LONG = 1;
}
| kSHORT
{
PARSE_INFO("type_specifier :kSHORT")
$$ = new_symbol();
$$->NOUN = SPEC_INT;
}
| kCHAR
{
PARSE_INFO("type_specifier :kCHAR")
$$ = new_symbol();
$$->NOUN = SPEC_CHAR;
}
| kVOID
{
PARSE_INFO("type_specifier :kVOID")
$$ = new_symbol();
$$->NOUN = SPEC_VOID;
}
| kFLOAT
{
PARSE_INFO("type_specifier :kFLOAT")
$$ = new_symbol();
$$->NOUN = SPEC_FLOAT;
}
| kDOUBLE
{
PARSE_INFO("type_specifier :kDOUBLE")
$$ = new_symbol();
$$->NOUN = SPEC_DOUBLE;
}
| kSIGNED
{
PARSE_INFO("type_specifier :kSIGNED")
$$ = new_symbol();
$$->NOUN = SPEC_INT;
}
| kUNSIGNED
{
PARSE_INFO("type_specifier :kUNSIGNED")
$$ = new_symbol();
$$->NOUN = SPEC_INT;
$$->IS_UNSIGNED = 1;
}
| idTYPEDEF
{
symbol *tmp;
PARSE_INFO("type_specifier :idTYPEDEF")
tmp = find_symtab_typedef( $1 );
assert( tmp );
$$ = new_symbol_from_typedef( tmp );
assert( $$ );
}
;
type_qualifier
: kCONST
{
PARSE_INFO("type_qualifier :kCONST")
$$ = new_symbol();
$$->SCLASS = SPEC_CONSTANT;
}
| kVOLATILE
{
PARSE_INFO("type_qualifier :kVOLATILE")
$$ = new_symbol();
// ingore volatile attribute
}
;
init_declarator_list
: init_declarator
{
PARSE_INFO("init_declarator_list :init_declarator")
}
| init_declarator_list oCOMMA init_declarator
{
PARSE_INFO("init_declarator_list :init_declarator_list oCOMMA init_declarator")
link_symbol_list($1, $3);
}
;
init_declarator
: declarator
{
PARSE_INFO("init_declarator :declarator")
// check array element
// for globe or local var, the array element number could not be zero
if ( IS_ARRAY($1) && !$1->num_ele )
{
yyerror("Array must be declarated with element number");
user_exit(1);
}
}
| declarator oASSIGN initializer
{
PARSE_INFO("init_declarator :declarator oASSIGN initializer")
if ( IS_FUNCTION($1) )
{
yyerror("initialization of a function");
user_exit(1);
}
if ( !IS_CL($3) )
{
yyerror("initializer is not a constant");
user_exit(1);
}
if ( IS_ARRAY($1) )
{
yyerror("array initialization unsupport");
user_exit(1);
}
$1->args = $3;
// set assign flag
$1->is_assign = 1;
}
;
/* // cast type 類型轉換, skip
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -