📄 c.y
字号:
| abstract_decl { discard_symbol ($1); $$ = NULL ; }
| ELLIPSIS { $$ = NULL ; }
;
abstract_decl
: type abs_decl { add_spec_to_decl ( $1, $$ = $2 ); }
| TTYPE abs_decl {
$$ = $2;
add_spec_to_decl( $1->type, $2 );
}
;
abs_decl
: /* epsilon */ { $$ = new_symbol("",0); }
| LP abs_decl RP LP RP { add_declarator( $$ = $2, FUNCTION ); }
| STAR abs_decl { add_declarator( $$ = $2, POINTER ); }
| abs_decl LB RB { add_declarator( $$, POINTER ); }
| abs_decl LB const_expr RB { add_declarator( $$, ARRAY );
$$->etype->NUM_ELE = $3;
}
| LP abs_decl RP { $$ = $2; }
;
struct_specifier
: STRUCT opt_tag LC def_list RC
{
if( !$2->fields )
{
$2->fields = reverse_links( $4 );
if( !illegal_struct_def( $2, $4 ) )
$2->size = figure_struct_offsets( $2->fields, $1=='s' );
}
else
{
yyerror("Ignoring redefinition of %s", $2->tag );
discard_symbol_chain( $4 );
}
$$ = $2;
}
| STRUCT tag { $$ = $2; }
;
opt_tag : tag
| /* empty */ {
static unsigned label = 0;
static char tag[16];
sprintf( tag, "%03d", label++ );
$$ = new_structdef( tag );
addsym( Struct_tab, $$ );
}
;
tag : NAME {
if( !($$=(structdef *) findsym(Struct_tab,yytext)))
{
$$ = new_structdef( yytext );
$$->level = Nest_lev;
addsym( Struct_tab, $$ );
}
}
;
def_list
: def_list def { symbol *p;
if( p = $2 )
{
for(; p->next; p = p->next )
;
p->next = $1;
$$ = $2;
}
}
| /* epsilon */ { $$ = NULL; } /* Initialize end-of-list */
; /* pointer. */
def
: specifiers decl_list { add_spec_to_decl( $1, $2 ); }
SEMI { $$ = $2; }
| specifiers SEMI { $$ = NULL; }
;
decl_list
: decl { $$->next = NULL;}
| decl_list COMMA decl
{
$3->next = $1;
$$ = $3;
}
;
decl
: funct_decl
| var_decl
| var_decl EQUAL initializer { yyerror( "Ignoring initializer.\n");
discard_value( $3 );
}
| var_decl COLON const_expr %prec COMMA
| COLON const_expr %prec COMMA
;
enum_specifier
: enum name opt_enum_list { if( $2->type )
yyerror("%s: redefinition",$2->name);
else
discard_symbol($2);
}
| enum LC enumerator_list RC
;
opt_enum_list
: LC enumerator_list RC
| /* empty */
;
enum : ENUM { Enum_val = 0; }
;
enumerator_list
: enumerator
| enumerator_list COMMA enumerator
;
enumerator
: name { do_enum( $1, Enum_val++ ); }
| name EQUAL const_expr { Enum_val = $3;
do_enum( $1, Enum_val++ ); }
;
compound_stmt
: LC { if( ++Nest_lev == 1 )
loc_reset();
}
local_defs stmt_list RC { --Nest_lev;
remove_symbols_from_table ( $3 );
discard_symbol_chain ( $3 );
}
;
local_defs
: def_list { add_symbols_to_table ( $$ = reverse_links( $1 ));
figure_local_offsets ( $$, Funct_name );
create_static_locals ( $$, Funct_name );
print_offset_comment ( $$, "variable" );
}
;
ext_def : opt_specifiers ext_decl_list
{
add_spec_to_decl( $1, $2 );
if( !$1->tdef )
discard_link_chain( $1 );
add_symbols_to_table ( $2 = reverse_links( $2 ) );
figure_osclass ( $2 );
generate_defs_and_free_args ( $2 );
remove_duplicates ( $2 );
}
SEMI
| opt_specifiers
{
if( !($1->class == SPECIFIER && $1->NOUN == STRUCTURE) )
yyerror("Useless definition (no identifier)\n");
if( !$1->tdef )
discard_link_chain( $1 );
}
SEMI
| opt_specifiers funct_decl
{
static unsigned link_val = 0; /* Labels used for link args.*/
add_spec_to_decl( $1, $2 ); /* Merge the specifier and */
/* declarator. */
if( !$1->tdef )
discard_link_chain( $1 ); /* Discard extra specifier. */
figure_osclass ( $2 ); /* Update symbol table. */
add_symbols_to_table ( $2 ); /* Add function itself. */
add_symbols_to_table ( $2->args ); /* Add the arguments. */
strcpy ( Funct_name, $2->name );
sprintf( Vspace, "%s%d", L_LINK, link_val++ );
sprintf( Tspace, "%s%d", L_LINK, link_val++ );
yycode( "\n#undef T\n" );
yycode( "#define T(n) (fp-(%s*%d)-(n*%d))\n\n",
Vspace, SWIDTH, SWIDTH );
gen( "PROC", $2->rname, $2->etype->STATIC ? "private":"public");
gen( "link", Vspace, Tspace );
++Nest_lev; /* Make nesting level of definition_list
* match nesting level in the funct_decl
*/
}
def_list
{
fix_types_and_discard_syms ( $4 );
figure_param_offsets ( $2->args );
print_offset_comment ( $2->args, "argument" );
--Nest_lev; /* It's incremented again in the compound_stmt */
}
compound_stmt
{
purge_undecl(); /* Deal with implicit declarations */
/* and undeclared symbols. */
remove_symbols_from_table ( $2->args ); /* Delete arguments. */
discard_symbol_chain ( $2->args );
gen( ":%s%d", L_RET, rlabel(1) ); /* End-of-function */
gen( "unlink" ); /* code. */
gen( "ret" );
gen( "ENDP", $2->rname );
yybss ( "\n#define %s %d\t/* %s: locals */\n",
Vspace, loc_var_space(), $2->name );
yybss ( "#define %s %d\t/* %s: temps. */\n",
Tspace, tmp_var_space(), $2->name );
tmp_reset(); /* Reset temporary-variable system.*/
/* (This is just insurance.) */
}
;
stmt_list
: stmt_list statement
| /* epsilon */
;
/*----------------------------------------------------------------------
* Statements
*/
statement
: SEMI
| compound_stmt
| expr SEMI { release_value($1); tmp_freeall(); }
| RETURN SEMI { gen( "goto%s%d", L_RET, rlabel(0) ); }
| RETURN expr SEMI { gen("=", IS_INT ($2->type) ? "rF.w.low" :
IS_POINTER($2->type) ? "rF.pp" :
"rF.l",
rvalue($2) );
gen( "goto%s%d", L_RET, rlabel(0) );
release_value( $2 );
tmp_freeall();
}
| GOTO target SEMI { gen("goto",$2); }
| target COLON { gen(":", $1); }
statement
| IF LP test RP statement { gen( ":%s%d", L_NEXT, $3 );
}
| IF LP test RP statement ELSE { gen( "goto%s%d", L_ELSE, $3 );
gen( ":%s%d", L_NEXT, $3 );
}
statement { gen( ":%s%d", L_ELSE, $3 );
}
| WHILE LP test RP { push(S_con, $3); push( S_con_label, L_TEST);
push(S_brk, $3); push( S_brk_label, L_NEXT);
}
statement { gen( "goto%s%d", L_TEST, $3 );
gen( ":%s%d", L_NEXT, $3 );
pop( S_con ); pop( S_con_label );
pop( S_brk ); pop( S_brk_label );
}
| DO { static int label;
gen(":%s%d", L_DOTOP, $<num>$ = ++label );
push( S_con, label );
push( S_con_label, L_DOTEST );
push( S_brk, label );
push( S_brk_label, L_DOEXIT );
}
statement WHILE { gen(":%s%d", L_DOTEST, $<num>2 ); }
LP test RP SEMI { gen("goto%s%d", L_DOTOP, $<num>2 );
gen( ":%s%d", L_DOEXIT, $<num>2 );
gen( ":%s%d", L_NEXT, $7 );
pop( S_con );
pop( S_con_label );
pop( S_brk );
pop( S_brk_label );
}
| FOR LP opt_expr SEMI
test SEMI {
gen("goto%s%d", L_BODY, $5 );
gen(":%s%d", L_INCREMENT, $5 );
push(S_con, $5);
push(S_con_label, L_INCREMENT );
push(S_brk, $5);
push(S_brk_label, L_NEXT );
}
opt_expr RP { gen("goto%s%d", L_TEST, $5 );
gen(":%s%d", L_BODY, $5 );
}
statement { gen("goto%s%d", L_INCREMENT, $5 );
gen( ":%s%d", L_NEXT, $5 );
pop( S_con );
pop( S_con_label );
pop( S_brk );
pop( S_brk_label );
}
| BREAK SEMI { if( stack_empty(S_brk) )
yyerror("Nothing to break from\n");
gen_comment("break");
gen("goto%s%d", stack_item(S_brk_label,0),
stack_item(S_brk, 0));
}
| CONTINUE SEMI { if( stack_empty(S_brk) )
yyerror("Continue not in loop\n");
gen_comment("continue");
gen("goto%s%d", stack_item(S_con_label,0),
stack_item(S_con,0 ));
}
| SWITCH LP expr RP
{
/* Note that the end-of-switch label is the 2nd argument to
* new_stab + 1; This label should be used for breaks when in
* the switch.
*/
push( S_switch, new_stab($3, ++Case_label) );
gen_comment("Jump to case-processing code" );
gen("goto%s%d", L_SWITCH, Case_label );
push( S_brk, ++Case_label );
push( S_brk_label, L_SWITCH );
release_value( $3 );
tmp_freeall();
}
compound_stmt
{
gen_stab_and_free_table( pop( S_switch ) );
pop( S_brk );
pop( S_brk_label );
}
| CASE const_expr COLON
{
add_case ( stack_item(S_switch,0), $2, ++Case_label );
gen_comment ( "case %d:", $2 );
gen ( ":%s%d" , L_SWITCH, Case_label );
}
| DEFAULT COLON
{
add_default_case( stack_item(S_switch,0), ++Case_label );
gen_comment("default:");
gen(":%s%d", L_SWITCH, Case_label );
}
;
target : NAME { static char buf[ NAME_MAX ];
sprintf(buf, "_%0.*s", NAME_MAX-2, yytext );
$$ = buf;
}
;
test : { static int label = 0;
gen( ":%s%d", L_TEST, $<num>$ = ++label );
}
expr {
$$ = $<num>1;
if( IS_INT_CONSTANT($2->type) )
{
if( ! $2->type->V_INT )
yyerror("Test is always false\n");
}
else /* not an endless loop */
{
gen( "EQ", rvalue($2), "0" );
gen( "goto%s%d", L_NEXT, $$ );
}
release_value( $2 );
tmp_freeall();
}
| /* empty */ { $$ = 0; /* no test */
}
;
unary
: LP expr RP { $$ = $2; }
| FCON { yyerror("Floating-point not supported\n"); }
| ICON { $$ = make_icon ( yytext, 0 ); }
| NAME { $$ = do_name ( yytext, $1 ); }
| string_const %prec COMMA
{
$$ = make_scon();
yydata( "private\tchar\t%s[]=\"%s\";\n", $$->name,$1);
}
| SIZEOF LP string_const RP %prec SIZEOF
{ $$ = make_icon(NULL,strlen($3) + 1 ); }
| SIZEOF LP expr RP %prec SIZEOF
{ $$ = make_icon(NULL,get_sizeof($3->type));
release_value( $3 );
}
| SIZEOF LP abstract_decl RP %prec SIZEOF
{
$$ = make_icon( NULL,
get_sizeof($3->type));
discard_symbol( $3 );
}
| LP abstract_decl RP unary %prec UNOP
{
if( IS_AGGREGATE($2->type) )
{
yyerror( "Illegal cast to aggregate type\n" );
$$ = $4;
}
else if( IS_POINTER($2->type) && IS_POINTER($4->type) )
{
discard_link_chain( $4->type );
$4->type = $2->type;
$4->etype = $2->type;
$$ = $4;
}
else
{
$$ = tmp_gen( $2->type, $4 );
}
}
| MINUS unary { $$ = do_unop( '-', $2 ); } %prec UNOP
| UNOP unary { $$ = do_unop( $1, $2 ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -