在野牛中的特定错误处理

时间:2013-03-02 03:11:01

标签: bison

Flex定义:

"view"  { return VIEW;}
"cell"  { return CELL;}
[A-Za-z]+ {
      yylval.strval=strdup(yytext);
      return ALPHA;
      }
[()]   {return yytext[0];}  

我的野牛语法:

static int len=10;
static char *allkeywords[10]=   {"view","acload","actual","after","alpha","and","annotate","apply","arc","array" };

cell:’(’ CELL ALPHA ’)’ { goal=$3;
                       flag=binary_search(allkeywords,len,goal);
                       if(flag) 
                        { 
                       yyerror("warnning: the component name is a keyword");
                       yyclearin;
                       yyerrok;
                       }                                                                    
            ;
int binary_search(const char *a[10], int len, char *goal)
  {    
   int low = 0;    
   int high = len - 1;    
   while(low <= high)    
    {        
     int middle = (low + high)/2;        
     if(strcmp (goal,a[middle])==0 )           
         return 1;        
       else if(strcmp (goal,a[middle]) < 0)        
          high = middle - 1;            
            else            
               low = middle + 1;    
 }    
 return 0;     
 }

我的指示:

bison -d -v bison.y
flex  flex.l 
gcc bison.tab.c lex.yy.c

例如,输入流是(单元格视图),单词“view”是用户给出的随机会标。巧合的是,它是EDIF文件的关键字,它也对应于ALPHA。我设置如果用户给出的ALPHA是关键字,请调用yyerror函数进行警告,但是野牛调用yyerror本身。它的输出是“zhouzhou:1.3-1.6:语法错误,意外的CELL,期待EDIF”,实际上,我希望它出现“zhouzhou:1.3-1.6:warnning:组件名称是一个关键字”。 如何让野牛不要叫它的yyerror,只是做我的意思?

1 个答案:

答案 0 :(得分:1)

虽然您可以编写语法代码以便允许关键字作为标识符,但这样做是不自然的,并且非常困难。所谓的关键字是因为你不能将它们用作标识符。

工作flex.l

%{
#include "bison.tab.h"
%}

%%
"view"  { puts("VIEW"); return VIEW;}
"cell"  { puts("CELL"); return CELL;}
[A-Za-z]+ {
      yylval.strval=strdup(yytext);
      puts("ALPHA:");
      puts(yylval.strval);
      return ALPHA;
      }
[()]   {puts("PARENS"); return yytext[0];}  

.      { printf("SKIP: %d %c\n", yytext[0], yytext[0]); }

%%

int yywrap(void)
{
    return(1);
}

工作bison.y

%{
#include <stdio.h>
#include <string.h>

static int binary_search(char **a, int len, char *goal);

static char *goal;
static int flag;
static int len=10;
static char *allkeywords[10]=   {"view", "acload", "actual", "after", "alpha", "and", "annotate", "apply", "arc", "array" };

%}

%union { char *strval; }

%token <strval> CELL
%token <strval> ALPHA
%token <strval> VIEW

%%

cell: '(' CELL ALPHA ')'
        {
            goal=$3;
            flag=binary_search(allkeywords, len, goal);
            if(flag) 
            { 
                printf("Before yyerror()\n");
                yyerror("warning: the component name is a keyword");
                printf("After yyerror()\nBefore yyclearin\n");
                yyclearin;
                printf("After yyclearin\nBefore yyerrok\n");
                yyerrok;
                printf("After yyerrok\n");
            }                                                                    
        }
    ;

%%

static int binary_search(char **a, int len, char *goal)
{    
    int low = 0;    
    int high = len - 1;    
    while(low <= high)    
    {        
        int middle = (low + high)/2;        
        if(strcmp (goal, a[middle])==0 )           
            return 1;        
        else if(strcmp (goal, a[middle]) < 0)        
            high = middle - 1;            
        else            
            low = middle + 1;    
    }    
    return 0;     
}

int main(void)
{
    int rc;
    yydebug = 1;
    setvbuf(stdout, 0, _IOLBF, 0);
    rc = yyparse();
    printf("== In main after yyparse() = %d\n", rc);
    return(0);
}

Mac OS X 10.8.2的构建脚本

set -x
bison -d -v bison.y &&
flex  flex.l  &&
gcc -DYYDEBUG bison.tab.c lex.yy.c -ly &&

a.out < data

数据文件

(cell alpha)

来自运行程序的跟踪

++ bison -d -v bison.y
++ flex flex.l
++ gcc -DYYDEBUG bison.tab.c lex.yy.c -ly
++ a.out
Starting parse
Entering state 0
Reading a token: PARENS
Next token is token '(' ()
Shifting token '(' ()
Entering state 1
Reading a token: CELL
Next token is token CELL ()
Shifting token CELL ()
Entering state 4
Reading a token: SKIP: 32  
ALPHA:
alpha
Next token is token ALPHA ()
Shifting token ALPHA ()
Entering state 6
Reading a token: PARENS
Next token is token ')' ()
Shifting token ')' ()
Entering state 7
Reducing stack by rule 3 (line 29):
   $1 = token '(' ()
   $2 = token CELL ()
   $3 = token ALPHA ()
   $4 = token ')' ()
Before yyerror()
warning: the component name is a keyword
After yyerror()
Before yyclearin
After yyclearin
Before yyerrok
After yyerrok
-> $$ = nterm cell ()
Stack now 0
Entering state 3
Reducing stack by rule 2 (line 25):
   $1 = nterm cell ()
Stack now 0
== In main after yyparse() = 0

注意代码如何成功返回main()函数一次,而不是调用yyerror()