📄 gram.y
字号:
;tk_rcurly_brace : '}' { fire_operator(); } ;tk_elipsis : TK_ELIPSIS { fire_operator(); } ;tk_case : TK_CASE { fire_keyword(); } ;tk_default : TK_DEFAULT { fire_keyword(); } ;tk_if : TK_IF { fire_keyword(); } ;tk_switch : TK_SWITCH { fire_keyword(); } ;tk_else : TK_ELSE { fire_keyword(); } ;tk_while : TK_WHILE { fire_keyword(); } ;tk_do : TK_DO { fire_keyword(); } ;tk_for : TK_FOR { fire_keyword(); } ;tk_goto : TK_GOTO { fire_keyword(); } ;tk_continue : TK_CONTINUE { fire_keyword(); } ;tk_break : TK_BREAK { fire_keyword(); } ;tk_return : TK_RETURN { fire_keyword(); } ;tk_string : TK_STRING_LITERAL { found_string(); } ;tk_constant : TK_CONSTANT { found_constant(); } ;identifier : TK_IDENTIFIER { /* Fire the identifier trigger. */ fire_identifier(); /* Save this identifier in case token buffer (yytext[]) gets overwritten by the time the identifier is needed. */ strcpy(last_ident, token()); } ;primary_expr : identifier | tk_constant | string_list | tk_lparen expr tk_rparen ;/* (In case a preprocessor wasn't run to join adjacent strings.) */string_list : tk_string | string_list tk_string ;postfix_expr : primary_expr | postfix_expr tk_lsquare_brace expr tk_rsquare_brace | postfix_expr tk_lparen { function_call(); } tk_rparen | postfix_expr tk_lparen { function_call(); } argument_expr_list tk_rparen | postfix_expr tk_dot identifier | postfix_expr tk_ptr_to identifier | postfix_expr tk_inc | postfix_expr tk_dec ;argument_expr_list : assignment_expr | argument_expr_list tk_comma assignment_expr ;unary_expr : postfix_expr | tk_inc unary_expr | tk_dec unary_expr | unary_operator cast_expr | tk_sizeof unary_expr | tk_sizeof tk_lparen type_name tk_rparen ;unary_operator : tk_ampersand | tk_asterisk | tk_plus | tk_minus | tk_tilde | tk_exclamation ;cast_expr : unary_expr | tk_lparen type_name tk_rparen cast_expr ;multiplicative_expr : cast_expr | multiplicative_expr tk_asterisk cast_expr | multiplicative_expr tk_slash cast_expr | multiplicative_expr tk_percent cast_expr ;additive_expr : multiplicative_expr | additive_expr tk_plus multiplicative_expr | additive_expr tk_minus multiplicative_expr ;shift_expr : additive_expr | shift_expr tk_left additive_expr | shift_expr tk_right additive_expr ;relational_expr : shift_expr | relational_expr tk_lt shift_expr | relational_expr tk_gt shift_expr | relational_expr tk_le shift_expr | relational_expr tk_ge shift_expr ;equality_expr : relational_expr | equality_expr tk_eq relational_expr | equality_expr tk_ne relational_expr ;and_expr : equality_expr | and_expr tk_ampersand equality_expr ;exclusive_or_expr : and_expr | exclusive_or_expr tk_circumflex and_expr ;inclusive_or_expr : exclusive_or_expr | inclusive_or_expr tk_bar exclusive_or_expr ;logical_and_expr : inclusive_or_expr | logical_and_expr tk_land /* Logical-and operator counts as a condition. */ { ++fcn_conditions; } inclusive_or_expr ;logical_or_expr : logical_and_expr | logical_or_expr tk_lor /* Logical-or operator counts as a condition. */ { ++fcn_conditions; } logical_and_expr ;conditional_expr : logical_or_expr | logical_or_expr tk_question expr tk_colon conditional_expr /* I consider the conditional operator to be a decision point and a condition. */ { ++fcn_decisions; ++fcn_conditions; } ;assignment_expr : conditional_expr | unary_expr assignment_operator assignment_expr ;assignment_operator : tk_assign | tk_mul_assign | tk_div_assign | tk_mod_assign | tk_add_assign | tk_sub_assign | tk_left_assign | tk_right_assign | tk_and_assign | tk_xor_assign | tk_or_assign ;expr : assignment_expr | expr tk_comma assignment_expr ;constant_expr : conditional_expr ;declaration /* Regardless of whether we were really parsing a typedef, indicate that we are no longer by setting is_typedef to FALSE. */ : declaration_specifiers tk_semicolon { is_typedef = FALSE; ++int_fcn.decl; /* Declaration statement. */ ++int_mod.decl; /* Indicate at the end of a declaration statement then fire the end-of-statement trigger. */ int_stm.is_decl = int_stm.end = TRUE; fire_stm(); ZERO(int_stm); } | declaration_specifiers init_declarator_list tk_semicolon { is_typedef = FALSE; ++int_fcn.decl; /* Declaration statement. */ ++int_mod.decl; /* Indicate at the end of a declaration statement then fire the end-of-statement trigger. */ int_stm.is_decl = int_stm.end = TRUE; fire_stm(); ZERO(int_stm); } ;declaration_specifiers /* nested_decl_specs is incremented and decremented here so that the name of the root-level item can be distinguished from other identifiers in the declaration. */ : storage_class_specifier | storage_class_specifier { ++nested_decl_specs; } declaration_specifiers { --nested_decl_specs; } | type_specifier | type_specifier { ++nested_decl_specs; } declaration_specifiers { --nested_decl_specs; } ;init_declarator_list : init_declarator | init_declarator_list tk_comma init_declarator ;init_declarator : declarator | declarator { before_initializer(); } tk_assign initializer { after_initializer(); } ;storage_class_specifier : tk_typedef /* Indicate that we are within a typedef. This is used to find the type name so that it can be added to the typedef symbol table. */ { is_typedef = TRUE; } | tk_extern | tk_static | tk_auto | tk_register ;type_specifier : tk_char | tk_short | tk_int | tk_long | tk_signed | tk_unsigned | tk_float | tk_double | tk_const | tk_volatile | tk_void | struct_or_union_specifier | enum_specifier | tk_type_name ;struct_or_union_specifier /* In the following rules, regardless of whether there was a tag, indicate that we are no longer looking for one by setting looking_for_tag to FALSE. */ : struct_or_union identifier { looking_for_tag = FALSE; } tk_lcurly_brace struct_declaration_list tk_rcurly_brace | struct_or_union tk_lcurly_brace { looking_for_tag = FALSE; } struct_declaration_list tk_rcurly_brace | struct_or_union identifier { looking_for_tag = FALSE; } ;struct_or_union /* Indicate that we are looking for a tag. This information is passed to the lexer. Since tags are in a separate name space from other identifiers, this helps the lexer determine whether a lexeme is an identifier or a type name. */ : tk_struct { looking_for_tag = TRUE; } | tk_union { looking_for_tag = TRUE; } ;struct_declaration_list : struct_declaration | struct_declaration_list struct_declaration ;struct_declaration : type_specifier_list struct_declarator_list tk_semicolon { ++int_fcn.decl; /* Declaration statement. */ ++int_mod.decl; /* Indicate at the end of a declaration statement then fire the end-of-statement trigger. */ int_stm.is_decl = int_stm.end = TRUE; fire_stm(); ZERO(int_stm); } ;struct_declarator_list : struct_declarator | struct_declarator_list tk_comma struct_declarator ;struct_declarator : declarator | tk_colon constant_expr | declarator tk_colon constant_expr ;enum_specifier /* In the following rules, regardless of whether there was a tag, indicate that we are no longer looking for one by setting looking_for_tag to FALSE. */ : enum enumeration { looking_for_tag = FALSE; } | enum identifier { looking_for_tag = FALSE; } enumeration | enum identifier { looking_for_tag = FALSE; } ;enumeration /* Note that an enumerator list can have a trailing comma. This is not Standard C, but some C compilers allow it anyway. */ : tk_lcurly_brace enumerator_list tk_rcurly_brace | tk_lcurly_brace enumerator_list tk_comma tk_rcurly_brace ;enum /* Indicate that we are looking for a tag. See struct_or_union for more info. */ : tk_enum { looking_for_tag = TRUE; } ;enumerator_list : enumerator | enumerator_list tk_comma enumerator ;enumerator : identifier | identifier tk_assign constant_expr ;declarator : declarator2 | pointer declarator2 ;declarator2 : identifier { if (nested_decl_specs == 0) { strcpy(last_decl, last_identifier()); /* Fire the declarator trigger. */ fire_declarator(); /* If we are parsing a typedef and this is the root-level declaration, this identifier must be the type name that is being being defined by the typedef. Therefore, add it to the typedef symbol table so that the lexer can distinguish type names from identifiers. */ if (is_typedef) typedef_symbol_table_add(token()); } } | tk_lparen declarator tk_rparen | declarator2 tk_lsquare_brace tk_rsquare_brace | declarator2 tk_lsquare_brace constant_expr tk_rsquare_brace /* For the next three rules, if we are not within a function definition already, use the last identifier as the function name. */ | declarator2 tk_lparen { if (!is_within_function) strcpy(function_name, last_identifier()); } tk_rparen /* nested_decl_specs is incremented and decremented in the following two rules so that the name of the root-level item in a declaration can be distinguished from other identifiers in the declaration. */ | declarator2 tk_lparen { ++nested_decl_specs; if (!is_within_function) strcpy(function_name, last_identifier()); } parameter_type_list { --nested_decl_specs; } tk_rparen | declarator2 tk_lparen { ++nested_decl_specs; if (!is_within_function) strcpy(function_name, last_identifier()); } parameter_identifier_list { --nested_decl_specs; } tk_rparen ;pointer : tk_asterisk | tk_asterisk type_specifier_list | tk_asterisk pointer | tk_asterisk type_specifier_list pointer ;type_specifier_list : type_specifier | type_specifier_list type_specifier ;parameter_identifier_list : identifier_list | identifier_list tk_comma tk_elipsis ;identifier_list : identifier | identifier_list tk_comma identifier ;parameter_type_list : parameter_list | parameter_list tk_comma tk_elipsis ;parameter_list : parameter_declaration | parameter_list tk_comma parameter_declaration ;parameter_declaration : declaration_specifiers declarator | declaration_specifiers | declaration_specifiers abstract_declarator ;type_name : type_specifier_list | type_specifier_list abstract_declarator ;abstract_declarator : pointer | direct_abstract_declarator | pointer direct_abstract_declarator ;direct_abstract_declarator : tk_lparen abstract_declarator tk_rparen | tk_lsquare_brace tk_rsquare_brace | tk_lsquare_brace constant_expr tk_rsquare_brace | direct_abstract_declarator tk_lsquare_brace tk_rsquare_brace | direct_abstract_declarator tk_lsquare_brace constant_expr tk_rsquare_brace | tk_lparen tk_rparen | tk_lparen parameter_type_list tk_rparen | direct_abstract_declarator tk_lparen tk_rparen | direct_abstract_declarator tk_lparen parameter_type_list tk_rparen ;initializer : assignment_expr | tk_lcurly_brace initializer_list tk_rcurly_brace | tk_lcurly_brace initializer_list tk_comma tk_rcurly_brace ;initializer_list : initializer | initializer_list tk_comma initializer ;statement : labeled_statement | compound_statement { is_else = is_if = FALSE; ++int_fcn.high; /* High-level statement. */ /* Used to consider adjacent case labels as one decision point. */ not_case_label(); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -