?? c.y
字號:
specifier_qualifier_list
: type_specifier specifier_qualifier_list
{
PARSE_INFO("specifier_qualifier_list :type_specifier specifier_qualifier_list")
}
| type_specifier
{
PARSE_INFO("specifier_qualifier_list :type_specifier")
}
| type_qualifier specifier_qualifier_list
{
PARSE_INFO("specifier_qualifier_list :type_qualifier specifier_qualifier_list")
}
| type_qualifier
{
PARSE_INFO("specifier_qualifier_list :type_qualifier")
}
;
*/
declarator
:
/*
pointer direct_declarator
{
PARSE_INFO("declarator :pointer direct_declarator")
}
|
*/
direct_declarator
{
PARSE_INFO("declarator :direct_declarator")
}
;
direct_declarator
: identifier
{
PARSE_INFO("direct_declarator :identifier")
$$ = new_symbol();
strncpy( $$->name, $1, NAME_LEN );
}
/* // pointer need it, we skip pointer, so skip it
| oLP declarator oRP
{
PARSE_INFO("direct_declarator :oLP declarator oRP")
}
*/
| direct_declarator oLB constant_expression oRB
{
PARSE_INFO("direct_declarator :direct_declarator oLB constant_expression oRB")
// array declaration
if ( IS_FUNCTION($1) )
{
yyerror("function returns array");
user_exit(1);
}
if ( IS_ARRAY($1) )
{
yyerror("only support one demision array");
user_exit(1);
}
// check constant_expression
if ( !IS_CL($3) )
{
yyerror("array unknown size");
user_exit(1);
}
if ( !get_sym_value($3) )
{
yyerror("cannot allocate an array of constant size 0");
user_exit(1);
}
if (get_sym_value($3) < 0)
{
yyerror("negative subscript or subscript is too large");
user_exit(1);
}
// set array flag
$1->is_array = 1;
$1->num_ele = get_sym_value($3);
del_symbol($3);
}
| direct_declarator oLB oRB
{
PARSE_INFO("direct_declarator :direct_declarator oLB oRB")
if ( IS_FUNCTION($1) )
{
yyerror("function returns array");
user_exit(1);
}
if ( IS_ARRAY($1) )
{
yyerror("only support one demision array");
user_exit(1);
}
// set array flag
$1->is_array = 1;
$1->num_ele = 0;
}
| direct_declarator oLP parameter_type_list oRP
{
PARSE_INFO("direct_declarator :direct_declarator oLP parameter_type_list oRP")
if ( IS_FUNCTION($1) )
{
yyerror("function returns function");
user_exit(1);
}
if ( IS_ARRAY($1) )
{
yyerror("array element type cannot be function");
user_exit(1);
}
// set function flag
$1->is_function = 1;
// assign function rname
if ( IS_MAIN_FUNC($1) )
{
// main(..)
strcpy($1->rname, $1->name);
}
else
{
sprintf($1->rname, _FUNCTION_NAME, $1->name);
}
// check weather func(void)
if ( $3->NOUN == SPEC_VOID )
{
if ( $3->next )
{
yyerror("internal error in 'direct_declarator oLP parameter_type_list oRP'");
user_exit(1);
}
//so, ...
$1->args = NULL;
del_symbol($3);
}
else
{
$1->args = $3;
// assign parameters rname
assign_parameters_rname($3);
}
}
/* | direct_declarator oLP identifier_list oRP
{
PARSE_INFO("direct_declarator :direct_declarator oLP identifier_list oRP")
// old style function declaration, not support
}
*/
| direct_declarator oLP oRP
{
PARSE_INFO("direct_declarator :direct_declarator oLP oRP")
if ( IS_FUNCTION($1) )
{
yyerror("function returns function");
user_exit(1);
}
if ( IS_ARRAY($1) )
{
yyerror("array element type cannot be function");
user_exit(1);
}
// set function flag
$1->is_function = 1;
// assign function rname
if ( IS_MAIN_FUNC($1) )
{
// main(..)
strcpy($1->rname, $1->name);
}
else
{
sprintf($1->rname, _FUNCTION_NAME, $1->name);
}
// no parameters , so ->args is NULL as default
}
;
/*
pointer
: oMUL type_qualifier_list
{
PARSE_INFO("pointer :oMUL type_qualifier_list")
}
| oMUL
{
PARSE_INFO("pointer :oMUL")
}
| oMUL type_qualifier_list pointer
{
PARSE_INFO("pointer :oMUL type_qualifier_list pointer")
}
| oMUL pointer
{
PARSE_INFO("pointer :oMUL pointer")
}
;
type_qualifier_list
: type_qualifier
{
PARSE_INFO("type_qualifier_list :type_qualifier")
}
| type_qualifier_list type_qualifier
{
PARSE_INFO("type_qualifier_list :type_qualifier_list type_qualifier")
}
;
*/
parameter_type_list
: parameter_list
{
PARSE_INFO("parameter_type_list :parameter_list")
}
| parameter_list oCOMMA oDOTDOTDOT
{
PARSE_INFO("parameter_type_list :parameter_list oCOMMA oDOTDOTDOT")
yyerror("more arguments not support now");
user_exit(1);
}
;
parameter_list
: parameter_declaration
{
PARSE_INFO("parameter_list :parameter_declaration")
}
| parameter_list oCOMMA parameter_declaration
{
PARSE_INFO("parameter_list :parameter_list oCOMMA parameter_declaration")
// if in this state, parameter is void, it must be
// in declaration_specifiers
// so it must has (..., void,..) or (void, ...)
// error
if ($3->NOUN == SPEC_VOID || $1->NOUN == SPEC_VOID)
{
yyerror("'void' cannot be an argument type, except for '(void)'");
user_exit(1);
}
link_symbol_list($1, $3);
}
;
parameter_declaration
: declaration_specifiers declarator
{
PARSE_INFO("parameter_declaration :declaration_specifiers declarator")
unoin_specifier_to_declarator($1, $2);
del_symbol( $1 );
// set argument flag
$2->is_argument = 1;
if ( !IS_VAR($2) )
{
yyerror("function has bad storage class");
user_exit(1);
}
check_var_declarator($2);
$$ = $2;
}
| declaration_specifiers abstract_declarator
{
PARSE_INFO("parameter_declaration :declaration_specifiers abstract_declarator")
unoin_specifier_to_declarator($1, $2);
del_symbol( $1 );
// set argument flag
$2->is_argument = 1;
if ( !IS_VAR($2) )
{
yyerror("function has bad storage class");
user_exit(1);
}
check_var_declarator($2);
$$ = $2;
}
| declaration_specifiers
{
PARSE_INFO("parameter_declaration :declaration_specifiers")
// it means in declaration is not use, and
// in definition is can not use the parameter
// so assign the args a unmeeted name, such as number, xixi....
// just use specifier symbol as var
// set argument flag
$1->is_argument = 1;
if ( !IS_VAR($1) )
{
yyerror("function has bad storage class");
user_exit(1);
}
// assign symbol a unused name
assign_symbol_unusedname($1);
}
;
/* // used by old style function declaration
identifier_list
: identifier
{
PARSE_INFO("identifier_list :identifier")
}
| identifier_list oCOMMA identifier
{
PARSE_INFO("identifier_list :identifier_list oCOMMA identifier")
}
;
*/
initializer
: assignment_expression
{
PARSE_INFO("initializer :assignment_expression")
}
| oLC initializer_list oRC
{
PARSE_INFO("initializer :oLC initializer_list oRC")
yyerror("initialize = {....} not support");
user_exit(1);
}
| oLC initializer_list oCOMMA oRC
{
PARSE_INFO("initializer :oLC initializer_list oCOMMA oRC")
yyerror("initialize = {...., } not support");
user_exit(1);
}
;
initializer_list
: initializer
{
PARSE_INFO("initializer_list :initializer")
}
| initializer_list oCOMMA initializer
{
PARSE_INFO("initializer_list :initializer_list oCOMMA initializer")
}
;
/* // 類型轉(zhuǎn)換, skip
type_name
: specifier_qualifier_list abstract_declarator
{
PARSE_INFO("type_name :specifier_qualifier_list abstract_declarator")
}
| specifier_qualifier_list
{
PARSE_INFO("type_name :specifier_qualifier_list")
}
;
*/
abstract_declarator
:
/*
pointer
{
PARSE_INFO("abstract_declarator :pointer")
}
| pointer direct_abstract_declarator
{
PARSE_INFO("abstract_declarator :pointer direct_abstract_declarator")
}
|
*/
direct_abstract_declarator
{
PARSE_INFO("abstract_declarator :direct_abstract_declarator")
}
;
direct_abstract_declarator
:
/* // pointer need it, we skip pointer. so we skip it
oLP abstract_declarator oRP
{
PARSE_INFO("direct_abstract_declarator :oLP abstract_declarator oRP")
}
|
*/
/* // we only support one demission array, so skip it
direct_abstract_declarator oLB constant_expression oRB
{
PARSE_INFO("direct_abstract_declarator :direct_abstract_declarator oLB constant_expression oRB")
}
|
*/
oLB constant_expression oRB
{
PARSE_INFO("direct_abstract_declarator :oLB constant_expression oRB")
// array declaration
// check constant_expression
if ( !IS_CL($2) )
{
yyerror("array unknown size");
user_exit(1);
}
if ( !get_sym_value($2) )
{
yyerror("cannot allocate an array of constant size 0");
user_exit(1);
}
if (get_sym_value($2) < 0)
{
yyerror("negative subscript or subscript is too large");
user_exit(1);
}
$$ = new_symbol();
// assign symbol a unused name
assign_symbol_unusedname($$);
// set array flag
$$->is_array = 1;
$$->num_ele = get_sym_value($2);
del_symbol($2);
}
/* // function pointer, so skip
| direct_abstract_declarator oLP parameter_type_list oRP
{
PARSE_INFO("direct_abstract_declarator :direct_abstract_declarator oLP parameter_type_list oRP")
}
| oLP parameter_type_list oRP
{
PARSE_INFO("direct_abstract_declarator :oLP parameter_type_list oRP")
}
*/
;
identifier
: yNAME
{
PARSE_INFO("identifier :yNAME")
PARSE_INFO("======= FOLLOW BY =======")
PARSE_INFO($1)
}
;
statement
: labeled_statement
{
PARSE_INFO("statement :labeled_statement")
}
| expression_statement
{
PARSE_INFO("statement :expression_statement")
}
| compound_statement
{
PARSE_INFO("statement :compound_statement")
}
| selection_statement
{
PARSE_INFO("statement :selection_statement")
}
| iteration_statement
{
PARSE_INFO("statement :iteration_statement")
}
| jump_statement
{
PARSE_INFO("statement :jump_statement")
}
;
labeled_statement
: identifier oCOLON
{
symbol *lb;
PARSE_INFO("labeled_statement :identifier oCOLON ")
lb = search_goto_label($1);
if ( !lb )
{
// the label has not be reference
// so, new symbol and add it to goto label symtab
lb = new_symbol();
lb->NOUN = SPEC_LABEL;
strcpy(lb->name, $1);
strcpy(lb->rname, get_a_label());
add_goto_label(lb);
}
else if ( !IS_LAB_DECL(lb) )
{
// the label has been used
parse_error($1, " : redefine label");
user_exit(1);
}
else
{
// the label only be reference
// so, change the decl flag
lb->is_declaration = 0;
}
// label:
gen_label(lb->rname);
}
statement
{
PARSE_INFO("statement")
}
| kCASE constant_expression oCOLON
{
symbol *cs;
PARSE_INFO("labeled_statement :kCASE constant_expression oCOLON ")
if ( !IS_CL($2) )
{
yyerror("case expression not constant");
user_exit(1);
}
cs = new_symbol();
strcpy(cs->name, _CASE_NAME);
// get a label
strcpy(cs->rname, get_a_label());
cs->V_I = get_sym_value($2);
add_case_to_switch(cs);
// label:
gen_label(cs->rname);
}
statement
{
PARSE_INFO("statement")
}
| kDEFAULT oCOLON
{
symbol *cs;
PARSE_INFO("labeled_statement :kDEFAULT oCOLON ")
cs = new_symbol();
strcpy(cs->name, _DEFAULT_NAME);
// get a label
strcpy(cs->rname, get_a_label());
add_case_to_switch(cs);
// label:
gen_label(cs->rname);
}
statement
{
PARSE_INFO("statement")
}
;
expression_statement
: expression oSEMI
{
PARSE_INFO("expression_statement :expression oSEMI")
GEN_END_EXPRESS($1)
if ($1)
del_symbol($1);
}
compound_statement
: oLC declaration_list
{
PARSE_INFO("compound_statement :oLC declaration_list ");
if ( sg_parameter_list )
// means this compound statement belong to a function, so...
// of course, if sg_parameter_list is NULL it also maybe a
// compound statement belong to a function because the parameters
// is void , heihei....
{
add_symbol_list_to_current_symtab(sg_parameter_list);
sg_parameter_list = NULL;
}
gen_var_assign_init($2);
}
statement_list oRC
{
PARSE_INFO("statement_list oRC");
del_compound_symtab();
}
| oLC
{
PARSE_INFO("compound_statement :oLC ")
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -