如何在Yacc中制定一个特定的规则,以便在另一个规则之前先减少?

时间:2016-12-16 08:58:59

标签: c yacc lex

我对Yacc有疑问。这是我用于解析C语言语法的Yacc代码。请注意,下面的代码只是完整代码的一些相关部分:

%token  IDENTIFIER I_CONSTANT F_CONSTANT STRING_LITERAL FUNC_NAME SIZEOF
%token  PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
%token  AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token  SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token  XOR_ASSIGN OR_ASSIGN
%token  TYPEDEF_NAME ENUMERATION_CONSTANT
%token  TYPEDEF EXTERN STATIC AUTO REGISTER INLINE
%token  CONST RESTRICT VOLATILE
%token  BOOL CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE VOID
%token  COMPLEX IMAGINARY
%token  STRUCT UNION ENUM ELLIPSIS
%token  CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
%token  ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATIC_ASSERT THREAD_LOCAL

%union{
    char* a;
    char* b;
}

%type <a>IDENTIFIER
%type <a>SIGNED UNSIGNED
%type <a>INT CHAR DOUBLE FLOAT LONG SHORT
%type <b>EXTERN STATIC AUTO REGISTER

%%
declaration
: declaration_specifiers ';'  
| declaration_specifiers init_declarator_list ';' { printf("semicolon:%s\n", $<a>3);} 
| static_assert_declaration
;

declaration_specifiers
: storage_class_specifier declaration_specifiers 
| storage_class_specifier                    
| type_specifier declaration_specifiers      
| type_specifier                             
| type_qualifier declaration_specifiers      
| type_qualifier                             
| function_specifier declaration_specifiers
| function_specifier
| alignment_specifier declaration_specifiers
| alignment_specifier
;

init_declarator_list
: init_declarator                           
| init_declarator_list ',' init_declarator  {printf("The comma:%s\n",$<a>2);} 
;

type_specifier
: VOID                                          {printf("type_specifier:%s\n",$<a>1);}
| CHAR                                          {printf("type_specifier:%s\n",$<a>1);}
| SHORT                                         {printf("type_specifier:%s\n",$<a>1);}
| INT                                           {printf("type_specifier:%s\n",$<a>1);}
| LONG                                          {printf("type_specifier:%s\n",$<a>1);}
| FLOAT                                         {printf("type_specifier:%s\n",$<a>1);}
| DOUBLE                                        {printf("type_specifier:%s\n",$<a>1);}
| SIGNED                                        {printf("type_specifier:%s\n",$<a>1);}
| UNSIGNED                                      {printf("type_specifier:%s\n",$<a>1);}
| BOOL                                          {printf("type_specifier:%s\n",$<a>1);}
| COMPLEX                                       {printf("type_specifier:%s\n",$<a>1);}
| IMAGINARY     /* non-mandated extension */    {printf("type_specifier:%s\n",$<a>1);}
| atomic_type_specifier                         {printf("type_specifier:%s\n",$<a>1);}
| struct_or_union_specifier                     {printf("type_specifier:%s\n",$<a>1);}
| enum_specifier                                {printf("type_specifier:%s\n",$<a>1);}
| TYPEDEF_NAME  {printf("type_specifier:%s\n",$<a>1);}
;

declarator
: pointer direct_declarator  
| direct_declarator  
;

direct_declarator
: IDENTIFIER {printf("The identifier: %s\n", $<a>1);}   
| '(' declarator ')'   
| direct_declarator '[' ']'     
| direct_declarator '[' '*' ']' 
| direct_declarator '[' STATIC type_qualifier_list assignment_expression ']' 
| direct_declarator '[' STATIC assignment_expression ']' 
| direct_declarator '[' type_qualifier_list '*' ']' 
| direct_declarator '[' type_qualifier_list STATIC assignment_expression ']' 
| direct_declarator '[' type_qualifier_list assignment_expression ']' 
| direct_declarator '[' type_qualifier_list ']'
| direct_declarator '[' assignment_expression ']' 
| direct_declarator '(' parameter_type_list ')'
| direct_declarator '(' ')' 
| direct_declarator '(' identifier_list ')' 
;

这是我的Lex代码对应Yacc代码(同样,这些只是相关部分):

"int"                   { yylval.a=strdup(yytext); return(INT); } /* Data Type*/
"long"                  { yylval.a=strdup(yytext); return(LONG); }
"char"                  { yylval.a=strdup(yytext); return(CHAR); }
"short"                 { yylval.a=strdup(yytext); return(SHORT); }
"signed"                { yylval.a=strdup(yytext); return(SIGNED); }
"double"                { yylval.a=strdup(yytext); return(DOUBLE); }
"unsigned"              { yylval.a=strdup(yytext); return(UNSIGNED); }
"float"                 { yylval.a=strdup(yytext); return(FLOAT); }
";"                     { yylval.a=strdup(yytext); return ';'; }
","                     { yylval.a=strdup(yytext); return ','; }

我的问题是当我输入命令输入时,例如:

int a,b;

应该打印:

type_specifier:int
The identifier: a
The comma:,
The identifier:b
semicolon:;

但我的输出是

type_specifier:int
The identifier: a
The identifier: b
The comma:,
semicolon:;

我应该怎么做才能完成例行程序:{printf("The comma:%s\n",$<a>2);}在两个IDENTIFIER {printf("The identifier: %s\n", $<a>1);}之间激活

参考资料 (原始版本)

https://www.lysator.liu.se/c/ANSI-C-grammar-y.html

https://www.lysator.liu.se/c/ANSI-C-grammar-l.html

1 个答案:

答案 0 :(得分:0)

在您完成printf的解析之前,您的init_declarator不会执行。试试这个:

| init_declarator_list ',' {printf("The comma:%s\n",$<a>2);}  init_declarator