为什么我的野牛规则不起作用

时间:2013-03-20 14:24:34

标签: syntax-error bison flex-lexer

每次运行解析器时,它都会出现“第1行附近<>”的语法错误(因为有一个子程序yyerror(char * s))。我认为那是因为我的野牛规则有问题。

我要解析的文件(c17.isc)。

*c17 iscas example (to test conversion program only)
*---------------------------------------------------
*
*
*  total number of lines in the netlist ..............    17
*  simplistically reduced equivalent fault set size =     22
*        lines from primary input  gates .......     5
*        lines from primary output gates .......     2
*        lines from interior gate outputs ......     4
*        lines from **     3 ** fanout stems ...     6
*
*        avg_fanin  =  2.00,     max_fanin  =  2
*        avg_fanout =  2.00,     max_fanout =  2
*
*
*
*
*
    1     1gat inpt    1   0      >sa1
    2     2gat inpt    1   0      >sa1
    3     3gat inpt    2   0 >sa0 >sa1
    8     8fan from     3gat      >sa1
    9     9fan from     3gat      >sa1
    6     6gat inpt    1   0      >sa1
    7     7gat inpt    1   0      >sa1
   10    10gat nand    1   2      >sa1
     1     8
   11    11gat nand    2   2 >sa0 >sa1
     9     6
   14    14fan from    11gat      >sa1
   15    15fan from    11gat      >sa1
   16    16gat nand    2   2 >sa0 >sa1
     2    14
   20    20fan from    16gat      >sa1
   21    21fan from    16gat      >sa1
   19    19gat nand    1   2      >sa1
    15     7
   22    22gat nand    0   2 >sa0 >sa1
    10    20
   23    23gat nand    0   2 >sa0 >sa1
    21    19

我的flex文件如下,它是正确的。您可以在此找到有关我的扫描仪如何工作的一些信息。 Error in the output of my flex file

declare.h

# include <stdio.h>
# include <string.h>
# include <stdlib.h>

# define INPT 1
# define NOR 2
# define NAND 3
# define NOT 4
# define XOR 5
# define AND 6
# define BUFF 7
# define FROM 8

flex文件

%{
# include "declare.h"
# include "parse.tab.h"

/*gi=1,it's input;gi=8,it's fanout;otherwise,it's gate*/
static int gi=-1;
static int inum=0;



struct{
    char *symbol;
    int val;
} symtab[]={
{"inpt", INPT},
{"nor", NOR},
{"nand", NAND},
{"not", NOT},
{"xor", XOR},
{"and", AND},
{"buff", BUFF},
{"from",FROM},
{"0",0}
};

extern FILE *yyin;

extern int yylval;
%}

%start A B C D E

DIGITS [0-9]+
BLANK [ \t\n\r\f\v\b]+
ALPHA [a-z]+

%%

"*".*\n     {BEGIN A; return(COMMENT);}

<A>{DIGITS}        {yylval=atoi(yytext); BEGIN B; return(NUM);}
<B>{DIGITS}{ALPHA} {yylval=atoi(yytext); BEGIN C; return(GNAME);}
<C>{DIGITS}        {yylval=atoi(yytext); BEGIN D; return(OPNUM);}
<C>{DIGITS}{ALPHA} {yylval=atoi(yytext); BEGIN A; return(FR);}
<D>{DIGITS}        {inum=atoi(yytext);
                    yylval=inum;
                    if(gi==1)
                    {BEGIN A;}
                    if(gi!=1)
                    {BEGIN E;}
                    return(IPNUM);
                   }

<E>{DIGITS}        {inum--;
                    yylval=atoi(yytext);
                    if(inum<0)
                    {BEGIN B; return(NUM);}
                    else
                    {BEGIN E; return(ILIST);} 
                   }


{ALPHA} {yylval=lookup(yytext);
         return(GTYPE);      
         }

">sa"[0-1] {yylval=atoi(&yytext[yyleng-1]);return(FAULT);}

{BLANK}    ;

.          ;



%%
int lookup(const char *s)
{
    int i;
    for (i = 0; symtab[i].val != 0; i++)
    {
        if (strcmp(symtab[i].symbol, s) == 0)
            break;
    }
    return(symtab[i].val);
}

野牛档案中的正确规则如下

parto: 
     | parto COMMENT
     | parto parti
     ;

parti: NUM
       {...}

       GNAME
       {...}


       GTYPE
       {...}

      | parti partii 
      | parti partiii
      ;

partii:OPNUM
       {...}

       IPNUM
       {...}

       partiv

       partv
       ;

partiii: FR
        {...}

         partiv
         ;

partiv: 
      | partiv FAULT
      {...}

      ;

partv:
     | partv ILIST
     {...}

     ;

1 个答案:

答案 0 :(得分:0)

将关键评论转移到答案中。

第一版代码有几个问题。在扫描仪代码中,有这样的行:

<A>{DIGITS}        { yylval=atoi(yytext); return(NUM); BEGIN B; }
  

您应该收到有关返回后出现的BEGIN操作无法访问的代码的警告。必须执行BEGIN个操作。它们没有被执行,所以你不会切换到你的开始状态。

迈克尔评论道:

  

没有警告。我已按照您的说法对其进行了修改,并在问题中编辑了我的代码。现在我在BEGIN之后回来了。仍然,“第1行附近的语法错误&lt; &gt;”。

这可能意味着您没有使用足够的警告编译C代码。假设您正在使用GCC,请将-Wall添加到初学者的编译选项中。警告也有可能需要优化。

  

您是否在返回时(在Flex扫描仪中)打印了令牌?你用-DYYDEBUG汇编了Bison语法吗?您还需要在yydebug = 1;程序中打开调试:main()。当你期望它们时,你可能没有得到你期望的代币。我还没有尝试过编译这段代码。跟踪令牌是获得语法工作的关键(根据我的经验)。否则,你是盲目的。

     

另一个问题(密切相关)是你需要从语法中生成FAULT等的符号名称(bison -d grammar.y生成grammar.tab.h)。例如,您会发现COMMENT被赋值为258。但是,您的扫描仪正在返回其他数字,因为它们位于declare.h。你必须解决这个不匹配问题。一种选择是在扫描仪中#include "grammar.tab.h";这或多或少是正常的。

回想起来,我认为这可能是最重要的观察;在解决之后,事情似乎恢复了正常的C调试。

  

(如果'grammar.tab.h'的内容发生变化,人们通常会包含'grammar.h'并且只更新'grammar.h',因此您不会一直重新编译扫描程序)。

这一点的重要性在于语法使用的令牌集趋于相当稳定,而与规则相关的操作随着语法的实现的发展而一直在变化。因此,如果需要花费足够的时间来值得担心,您可以创建grammar.h的副本grammar.tab.h,但仅在grammar.h的内容时更新grammar.tab.h变化。

cmp -s grammar.tab.h grammar.h || cp grammar.tab.h grammar.h

您可以在makefile规则中包含它,将该语法转换为C文件(或目标文件)。

如果扫描仪足够小并且您的机器足够快,可能更容易不打扰这种改进;在具有少量MiB RAM的50 MHz机器的日子里,它比在多个内核运行在2+ GHz以及少量GiB RAM的情况下更为重要。