📄 cyacc.y
字号:
;/* A type specifier (but not a type qualifier). Once we have seen one of these in a declaration, if a typedef name appears then it is being redeclared. The _reserved versions start with a reserved word and may appear anywhere in the declaration specifiers; the _nonreserved versions may only appear before any other type specifiers, and after that are (if names) being redeclared. FIXME: should the _nonreserved version be restricted to names being redeclared only? The other entries there relate only the GNU extensions and Objective C, and are historically parsed thus, and don't make sense after other type specifiers, but it might be cleaner to count them as _reserved. _attr means: specifiers that either end with attributes, or are such that any following attributes would be parsed as part of the specifier. _nonattr: other specifiers not ending with attributes. */typespec_nonattr: typespec_reserved_nonattr | typespec_nonreserved_nonattr ;typespec_attr: typespec_reserved_attr ;typespec_reserved_nonattr: TYPESPEC { OBJC_NEED_RAW_IDENTIFIER (1); $$.kind = ctsk_resword; $$.spec = $1; } | structsp_nonattr ;typespec_reserved_attr: structsp_attr ;typespec_nonreserved_nonattr: TYPENAME { /* For a typedef name, record the meaning, not the name. In case of `foo foo, bar;'. */ $$.kind = ctsk_typedef; $$.spec = lookup_name ($1); } | typeof '(' expr ')' { skip_evaluation--; in_typeof--; if (TREE_CODE ($3.value) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND ($3.value, 1))) error ("%<typeof%> applied to a bit-field"); $$.kind = ctsk_typeof; $$.spec = TREE_TYPE ($3.value); pop_maybe_used (variably_modified_type_p ($$.spec, NULL_TREE)); } | typeof '(' typename ')' { skip_evaluation--; in_typeof--; $$.kind = ctsk_typeof; $$.spec = groktypename ($3); pop_maybe_used (variably_modified_type_p ($$.spec, NULL_TREE)); } ;/* typespec_nonreserved_attr does not exist. */initdecls: initdcl | initdecls ',' maybe_resetattrs initdcl ;notype_initdecls: notype_initdcl | notype_initdecls ',' maybe_resetattrs notype_initdcl ;initdcl: declarator maybeasm maybe_attribute '=' { $<ttype>$ = start_decl ($1, current_declspecs, true, chainon ($3, all_prefix_attributes)); if (!$<ttype>$) $<ttype>$ = error_mark_node; start_init ($<ttype>$, $2, global_bindings_p ()); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { finish_init (); if ($<ttype>5 != error_mark_node) { maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6); finish_decl ($<ttype>5, $6.value, $2); } } | declarator maybeasm maybe_attribute { tree d = start_decl ($1, current_declspecs, false, chainon ($3, all_prefix_attributes)); if (d) finish_decl (d, NULL_TREE, $2); } ;notype_initdcl: notype_declarator maybeasm maybe_attribute '=' { $<ttype>$ = start_decl ($1, current_declspecs, true, chainon ($3, all_prefix_attributes)); if (!$<ttype>$) $<ttype>$ = error_mark_node; start_init ($<ttype>$, $2, global_bindings_p ()); } init/* Note how the declaration of the variable is in effect while its init is parsed! */ { finish_init (); if ($<ttype>5 != error_mark_node) { maybe_warn_string_init (TREE_TYPE ($<ttype>5), $6); finish_decl ($<ttype>5, $6.value, $2); } } | notype_declarator maybeasm maybe_attribute { tree d = start_decl ($1, current_declspecs, false, chainon ($3, all_prefix_attributes)); if (d) finish_decl (d, NULL_TREE, $2); } ;/* the * rules are dummies to accept the Apollo extended syntax so that the header files compile. */maybe_attribute: /* empty */ { $$ = NULL_TREE; } | attributes { $$ = $1; } ;attributes: attribute { $$ = $1; } | attributes attribute { $$ = chainon ($1, $2); } ;attribute: ATTRIBUTE stop_string_translation '(' '(' attribute_list ')' ')' start_string_translation { $$ = $5; } | ATTRIBUTE error start_string_translation { $$ = NULL_TREE; } ;attribute_list: attrib { $$ = $1; } | attribute_list ',' attrib { $$ = chainon ($1, $3); } ;attrib: /* empty */ { $$ = NULL_TREE; } | any_word { $$ = build_tree_list ($1, NULL_TREE); } | any_word '(' IDENTIFIER ')' { $$ = build_tree_list ($1, build_tree_list (NULL_TREE, $3)); } | any_word '(' IDENTIFIER ',' nonnull_exprlist ')' { $$ = build_tree_list ($1, tree_cons (NULL_TREE, $3, $5)); } | any_word '(' exprlist ')' { $$ = build_tree_list ($1, $3); } ;/* This still leaves out most reserved keywords, shouldn't we include them? */any_word: identifier | scspec | TYPESPEC | TYPE_QUAL ;scspec: STATIC | SCSPEC ;/* Initializers. `init' is the entry point. */init: expr_no_commas { $$ = $1; } | '{' { really_start_incremental_init (NULL_TREE); } initlist_maybe_comma '}' { $$ = pop_init_level (0); } | error { $$.value = error_mark_node; $$.original_code = ERROR_MARK; } ;/* `initlist_maybe_comma' is the guts of an initializer in braces. */initlist_maybe_comma: /* empty */ { if (pedantic) pedwarn ("ISO C forbids empty initializer braces"); } | initlist1 maybecomma ;initlist1: initelt | initlist1 ',' initelt ;/* `initelt' is a single element of an initializer. It may use braces. */initelt: designator_list '=' initval { if (pedantic && !flag_isoc99) pedwarn ("ISO C90 forbids specifying subobject to initialize"); } | array_designator initval { if (pedantic) pedwarn ("obsolete use of designated initializer without %<=%>"); } | identifier ':' { set_init_label ($1); if (pedantic) pedwarn ("obsolete use of designated initializer with %<:%>"); } initval {} | initval ;initval: '{' { push_init_level (0); } initlist_maybe_comma '}' { process_init_element (pop_init_level (0)); } | expr_no_commas { process_init_element ($1); } | error ;designator_list: designator | designator_list designator ;designator: '.' identifier { set_init_label ($2); } | array_designator ;array_designator: '[' expr_no_commas ELLIPSIS expr_no_commas ']' { set_init_index ($2.value, $4.value); if (pedantic) pedwarn ("ISO C forbids specifying range of elements to initialize"); } | '[' expr_no_commas ']' { set_init_index ($2.value, NULL_TREE); } ;nested_function: declarator { if (pedantic) pedwarn ("ISO C forbids nested functions"); push_function_context (); if (!start_function (current_declspecs, $1, all_prefix_attributes)) { pop_function_context (); YYERROR1; } } old_style_parm_decls save_location { tree decl = current_function_decl; DECL_SOURCE_LOCATION (decl) = $4; store_parm_decls (); } /* This used to use compstmt_or_error. That caused a bug with input `f(g) int g {}', where the use of YYERROR1 above caused an error which then was handled by compstmt_or_error. There followed a repeated execution of that same rule, which called YYERROR1 again, and so on. */ compstmt { tree decl = current_function_decl; add_stmt ($6); finish_function (); pop_function_context (); add_stmt (build_stmt (DECL_EXPR, decl)); } ;notype_nested_function: notype_declarator { if (pedantic) pedwarn ("ISO C forbids nested functions"); push_function_context (); if (!start_function (current_declspecs, $1, all_prefix_attributes)) { pop_function_context (); YYERROR1; } } old_style_parm_decls save_location { tree decl = current_function_decl; DECL_SOURCE_LOCATION (decl) = $4; store_parm_decls (); } /* This used to use compstmt_or_error. That caused a bug with input `f(g) int g {}', where the use of YYERROR1 above caused an error which then was handled by compstmt_or_error. There followed a repeated execution of that same rule, which called YYERROR1 again, and so on. */ compstmt { tree decl = current_function_decl; add_stmt ($6); finish_function (); pop_function_context (); add_stmt (build_stmt (DECL_EXPR, decl)); } ;/* Any kind of declarator (thus, all declarators allowed after an explicit typespec). */declarator: after_type_declarator | notype_declarator ;/* A declarator that is allowed only after an explicit typespec. */after_type_declarator: '(' maybe_attribute after_type_declarator ')' { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; } | after_type_declarator '(' parmlist_or_identifiers %prec '.' { $$ = build_function_declarator ($3, $1); } | after_type_declarator array_declarator %prec '.' { $$ = set_array_declarator_inner ($2, $1, false); } | '*' maybe_type_quals_attrs after_type_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } | TYPENAME { $$ = build_id_declarator ($1); } ;/* Kinds of declarator that can appear in a parameter list in addition to notype_declarator. This is like after_type_declarator but does not allow a typedef name in parentheses as an identifier (because it would conflict with a function with that typedef as arg). */parm_declarator: parm_declarator_starttypename | parm_declarator_nostarttypename ;parm_declarator_starttypename: parm_declarator_starttypename '(' parmlist_or_identifiers %prec '.' { $$ = build_function_declarator ($3, $1); } | parm_declarator_starttypename array_declarator %prec '.' { $$ = set_array_declarator_inner ($2, $1, false); } | TYPENAME { $$ = build_id_declarator ($1); } ;parm_declarator_nostarttypename: parm_declarator_nostarttypename '(' parmlist_or_identifiers %prec '.' { $$ = build_function_declarator ($3, $1); } | parm_declarator_nostarttypename array_declarator %prec '.' { $$ = set_array_declarator_inner ($2, $1, false); } | '*' maybe_type_quals_attrs parm_declarator_starttypename %prec UNARY { $$ = make_pointer_declarator ($2, $3); } | '*' maybe_type_quals_attrs parm_declarator_nostarttypename %prec UNARY { $$ = make_pointer_declarator ($2, $3); } | '(' maybe_attribute parm_declarator_nostarttypename ')' { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; } ;/* A declarator allowed whether or not there has been an explicit typespec. These cannot redeclare a typedef-name. */notype_declarator: notype_declarator '(' parmlist_or_identifiers %prec '.' { $$ = build_function_declarator ($3, $1); } | '(' maybe_attribute notype_declarator ')' { $$ = $2 ? build_attrs_declarator ($2, $3) : $3; } | '*' maybe_type_quals_attrs notype_declarator %prec UNARY { $$ = make_pointer_declarator ($2, $3); } | notype_declarator array_declarator %prec '.' { $$ = set_array_declarator_inner ($2, $1, false); } | IDENTIFIER { $$ = build_id_declarator ($1); } ;struct_head: STRUCT { $$ = NULL_TREE; } | STRUCT attributes { $$ = $2; } ;union_head: UNION { $$ = NULL_TREE; } | UNION attributes { $$ = $2; } ;enum_head: ENUM { $$ = NULL_TREE; } | ENUM attributes { $$ = $2; } ;/* structsp_attr: struct/union/enum specifiers that either end with attributes, or are such that any following attributes would be parsed as part of the struct/union/enum specifier. structsp_nonattr: other struct/union/enum specifiers. */structsp_attr: struct_head identifier '{' { $<ttype>$ = start_struct (RECORD_TYPE, $2); /* Start scope of tag before parsing components. */ } component_decl_list '}' maybe_attribute { $$.spec = finish_struct ($<ttype>4, nreverse ($5), chainon ($1, $7)); $$.kind = ctsk_tagdef; } | struct_head '{' component_decl_list '}' maybe_attribute { $$.spec = finish_struct (start_struct (RECORD_TYPE, NULL_TREE), nreverse ($3), chainon ($1, $5)); $$.kind = ctsk_tagdef; } | union_head identifier '{' { $<ttype>$ = start_struct (UNION_TYPE, $2); } component_decl_list '}' maybe_attribute { $$.spec = finish_struct ($<ttype>4, nreverse ($5), chainon ($1, $7)); $$.kind = ctsk_tagdef; } | union_head '{' component_decl_list '}' maybe_attribute { $$.spec = finish_struct (start_struct (UNION_TYPE, NULL_TREE), nreverse ($3), chainon ($1, $5)); $$.kind = ctsk_tagdef;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -