I have a question about Yacc. Here is my Yacc code for parsing the C language grammar. Note that, the code below is only some relevant parts of the complete code:
%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 ')'
;
And here is my Lex code corresponding to the Yacc code (Again, these are only relevant parts):
"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 ','; }
My problem is that when I enter the input in command such as:
int a,b;
It should print:
type_specifier:int
The identifier: a
The comma:,
The identifier:b
semicolon:;
but my output is
type_specifier:int
The identifier: a
The identifier: b
The comma:,
semicolon:;
What should I do to make the routine: {printf("The comma:%s\n",$<a>2);}
activate between two IDENTIFIER {printf("The identifier: %s\n", $<a>1);}
References (original versions)
Your
printf
doesn't execute until you've completed the parsing ofinit_declarator
. Try this instead: