Почему этот код зубра производит неожиданный вывод?

гибкий код:

  1 %option noyywrap nodefault yylineno case-insensitive
  2 %{
  3 #include "stdio.h"
  4 #include "tp.tab.h"
  5 %}
  6 
  7 %%
  8 "{"             {return '{';}
  9 "}"             {return '}';}
 10 ";"             {return ';';}
 11 "create"        {return CREATE;}
 12 "cmd"           {return CMD;}
 13 "int"           {yylval.intval = 20;return INT;}
 14 [a-zA-Z]+       {yylval.strval = yytext;printf("id:%s\n" , yylval.strval);return ID;}
 15 [ \t\n]
 16          {return 0;}
 17 .               {printf("mistery char\n");}
 18 

код бизона:

  1 %{
  2 #include "stdlib.h"
  3 #include "stdio.h"
  4 #include "stdarg.h"
  5 void yyerror(char *s, ...);
  6 #define YYDEBUG 1
  7 int yydebug = 1;
  8 %}
  9 
 10 %union{
 11     char *strval;
 12     int intval;
 13 }
 14 
 15 %token  ID
 16 %token  INT
 17 %token CREATE
 18 %token CMD
 19 
 20 %type  col_definition
 21 %type  create_type
 22 %start stmt_list
 23 
 24 %%
 25 stmt_list:stmt ';'
 26 | stmt_list stmt ';'
 27 ;
 28 
 29 stmt:create_cmd_stmt         {/*printf("create cmd\n");*/}
 30 ;
 31 
 32 create_cmd_stmt:CREATE CMD ID'{'create_col_list'}'    {printf("%s\n" , $3);}
 33 ;
 34 create_col_list:col_definition
 35 | create_col_list col_definition
 36 ;
 37 
 38 col_definition:create_type ID ';' {printf("%d , %s\n" , $1, $2);}
 39 ;
 40 
 41 create_type:INT {$ = $1;}
 42 ;
 43 
 44 %%
 45 extern FILE *yyin;
 46 
 47 void
 48 yyerror(char *s, ...)
 49 {
 50     extern yylineno;
 51     va_list ap;
 52     va_start(ap, s);
 53     fprintf(stderr, "%d: error: ", yylineno);
 54     vfprintf(stderr, s, ap);
 55     fprintf(stderr, "\n");
 56 }
 57 
 58 int main(int argc , char *argv[])
 59 {
 60     yyin = fopen(argv[1] , "r");
 61     if(!yyin){
 62         printf("open file %s failed\n" ,argv[1]);
 63         return -1;
 64     }
 65 
 66     if(!yyparse()){
 67         printf("parse work!\n");
 68     }else{
 69         printf("parse failed!\n");
 70     }
 71 
 72     fclose(yyin);
 73     return 0;
 74 }
 75

тестовый входной файл:

create cmd keeplive
{
    int a;
    int b;
};

тестовый вывод:

root@VM-Ubuntu203001:~/test/tpp# ./a.out t1.tp 
id:keeplive
id:a
20 , a;
id:b
20 , b;
keeplive
{
    int a;
    int b;
}
parse work!

У меня есть два вопроса:

1) Почему действие в строке 38 выводит токен ';'? Например, "20, а; " а также "20, б; "

2) Почему действие в строке 32 печатается "keeplive {int a; int b; }» а не простоkeeplive "?

Ответы на вопрос(1)

Ваш ответ на вопрос