【问题标题】:Error in the output of my flex file我的 flex 文件的输出错误
【发布时间】:2013-03-19 20:46:34
【问题描述】:

我写了一个.l文件,想输出“c17.isc”中的内容。

但是有一个错误,我不知道为什么。我已经给出了我打算读取的文件,flex文件和执行结果。

这是 c17.isc 文件 内容是什么意思

number  gate_name  gate_type  output_number  input_number  fault

带有“from”的行表示扇出。 2个数字的行只表示输入列表。

*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 文件。

首先,这是声明文件:

# 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"

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


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;
%}

%start A B C D E

DIGITS [0-9]+
BLANK [ \t\n]+
ALPHA [a-z]+

%%

"*".*\n     {ECHO; BEGIN A;}

<A>{BLANK}{DIGITS} {printf("num=%s\t",yytext); BEGIN B;}
<B>{BLANK}{DIGITS}{ALPHA} {printf("name=%s",yytext); BEGIN C;}
<C>{BLANK}{DIGITS} {printf("op=%s\t",yytext);BEGIN D;}
<C>{BLANK}{DIGITS}{ALPHA} {ECHO; BEGIN A;}
<D>{BLANK}{DIGITS} {inum=atoi(yytext);
                    printf("ip=%s\t",yytext);
                    if(gi==1)
                    {BEGIN A;}
                    if(gi!=1)
                    {BEGIN E;}
                   }

<E>{BLANK}{DIGITS} {inum--;
                    if(inum<0)
                    {printf("num=%s\t",yytext); BEGIN B;}
                    else
                    {printf("il=%s\t",yytext); BEGIN E;} 
                   }


{ALPHA} {gi=lookup(yytext);
         if(gi!=0) printf("\tty=%d\t",gi);
         else ECHO;

         }

{BLANK}">sa"[0-1] {val=atoi(&yytext[yyleng-1]);printf("\tfl=%d",val);}

{BLANK}    ;



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

main()
{
FILE *x=fopen("c17.isc","r");
yyin=x;
yylex();
}

这是执行结果。我用 * 标记了错误的地方。基本上错误发生在输入列表的行。

比如图片第一错行应该是“num=10”,第二错错行应该是“il=1 il=8”等等

我对flex文件中输入列表的操作位于E部分,但我不知道为什么它不起作用。

num=1  name=1gat  ty=1  op=1  ip=0  fl=1
num=2  name=2gat  ty=1  op=1  ip=0  fl=1
num=3  name=3gat  ty=1  op=2  ip=0  fl=0  fl=1
num=8  name=8fan  ty=8  3gat  fl=1
num=9  name=9fan  ty=8  3gat  fl=1
num=6  name=6gat  ty=1  op=1  ip=0  fl=1
num=7  name=7gat  ty=1  op=1  ip=0  fl=1
**il=10**  name=10gat  ty=3  op=1  ip=2  fl=1
**num=1**  il=8
**il=11**  name=11gat  ty=3  op=2  ip=2  fl=0  fl=1
**num=9**  il=6
**num=4**  ...
**num=5**  ...
**il=16**  ...
**num=2**  il=14
**num=0**  ...
**num=1**  ...
**il=19**  ...
**num=15** il=7
**il=22**  ...
**il=23**  ...

【问题讨论】:

  • 你为什么要使用诸如lookup(s) char* s; 之类的非原型函数的准标准C 方言编写?您应该使用具有显式函数返回类型的原型进行编写:int lookup(char *s)(甚至int lookup(const char *s)。新代码(过去 15 年左右编写的任何内容)都应该使用原型函数定义编写,而不是使用“K&R”风格的函数定义。
  • 嗯,那是因为我有一个 1980 年代的例子。现在我注意到函数查找的定义中没有返回类型和参数类型。
  • 你不能取消一个有答案的问题。在你问这个问题之前,你应该考虑到这一点。不要再破坏你的问题了。
  • Michael,我看到了一个建议的编辑,您在其中删除了一些不是您的帖子中的代码。如果您有任何问题,请在Meta Stack Overflow 上提问或使用联系表与站点管理员联系。

标签: token bison flex-lexer


【解决方案1】:

您的代码的这种改编似乎可以按您的预期工作。有各种变化,最明显的是输出了一些换行符,并明确了num= 部分的识别位置。

%{
#include "declare.h"

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

extern int lookup(const char *s);

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;
%}

%start A B C D E

DIGITS [0-9]+
BLANK [ \t\n]+
ALPHA [a-z]+

%%

"*".*\n              {ECHO; BEGIN A;}

<A>{DIGITS}          {printf("\nnum1=%s\t", yytext); BEGIN B;}
<B>{DIGITS}{ALPHA}   {printf(" name=%s\t",  yytext); BEGIN C;}
<C>{DIGITS}          {printf(" op=%s\t",    yytext); BEGIN D;}
<C>{DIGITS}{ALPHA}   {ECHO; BEGIN A;}
<D>{DIGITS}          {
                     inum=atoi(yytext);
                     printf(" ip=%s\t", yytext);
                     if (gi==1)
                     {BEGIN A;}
                     if (gi!=1)
                     {BEGIN E;}
                     }

<E>{DIGITS}          {inum--;
                     if (inum<0)
                     {printf("\nnum2=%s\t", yytext); BEGIN B;}
                     else
                     {printf(" il=%s\t", yytext); BEGIN E;} 
                     }

{ALPHA}              {
                     gi = lookup(yytext);
                     if (gi!=0) printf(" ty=%d (%s)\t", gi, yytext);
                     else { printf("Lookup failed: "); ECHO; }
                     }

">sa"[0-1]           {int val=atoi(&yytext[yyleng-1]);printf(" fl=%d", val);}

{BLANK}              ;
.                    { printf("Unmatched: %s\n", yytext); }

%%
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);
}

int main(void)
{
    FILE *x=fopen("c17.isc", "r");
    yyin=x;
    yylex();
    putchar('\n');
}

对于您的示例输入,输出为:

*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
*
* 
*
*
*

num1=1   name=1gat   ty=1 (inpt)     op=1    ip=0    fl=1
num1=2   name=2gat   ty=1 (inpt)     op=1    ip=0    fl=1
num1=3   name=3gat   ty=1 (inpt)     op=2    ip=0    fl=0 fl=1
num1=8   name=8fan   ty=8 (from)    3gat fl=1
num1=9   name=9fan   ty=8 (from)    3gat fl=1
num1=6   name=6gat   ty=1 (inpt)     op=1    ip=0    fl=1
num1=7   name=7gat   ty=1 (inpt)     op=1    ip=0    fl=1
num1=10  name=10gat  ty=3 (nand)     op=1    ip=2    fl=1 il=1   il=8   
num2=11  name=11gat  ty=3 (nand)     op=2    ip=2    fl=0 fl=1 il=9  il=6   
num2=14  name=14fan  ty=8 (from)    11gat fl=1
num1=15  name=15fan  ty=8 (from)    11gat fl=1
num1=16  name=16gat  ty=3 (nand)     op=2    ip=2    fl=0 fl=1 il=2  il=14  
num2=20  name=20fan  ty=8 (from)    16gat fl=1
num1=21  name=21fan  ty=8 (from)    16gat fl=1
num1=19  name=19gat  ty=3 (nand)     op=1    ip=2    fl=1 il=15  il=7   
num2=22  name=22gat  ty=3 (nand)     op=0    ip=2    fl=0 fl=1 il=10     il=20  
num2=23  name=23gat  ty=3 (nand)     op=0    ip=2    fl=0 fl=1 il=21     il=19

带有num1=10 的行有il=1il=8 与之关联,这似乎反映了数据。 (我修改了打印输出以包括类型名称和类型编号。)

我不确定哪些变化是重要的。我认为,丢失匹配数字和字母的规则中的{BLANK} 部分可以简化事情(扫描仪基本上忽略间距是很常见的)。

【讨论】:

  • 非常感谢,它有效。你是对的,我的规则中不应该有 {BLANK} 并且我不应该使用非原型函数。但我有一个问题,为什么会有“不匹配”的符号。当我运行程序时,每行末尾都有不匹配的符号。我认为那应该是一个换行符,它包含在 {BLANK} 中。
  • 有相当高的信心,我猜你一定是在 Windows 上,你在换行符之前得到一个回车,并且回车与任何其他规则都不匹配。 Lex/Flex 扫描器的技巧之一是确保有一个. 规则,当触发检测数据是否包含未被扫描器其余部分分类的字符时,该规则会让人感觉到它的存在。我在 Mac OS X 上没有触发该规则。您可以将打印更改为 printf("Unmatched: %d\n", *yytext); 以报告字符代码;它可能有助于更好地识别角色。
  • 感谢您的建议。所以我应该保留“。”在我的 flex 文件中设置规则,我应该在 linux 下编写文件。如果方便的话,你能看看我在解析器中的规则吗?我认为规则有问题,但我找不到错误。 stackoverflow.com/questions/15526259/…
  • 保留点规则,但升级您的其他模式(可能是 BLANK 的定义)以处理(忽略)回车。当您在输入数据中遇到其他标点符号、重音字符或 ... 时,将触发点规则。
  • 哦,我明白了。我的 {BLANK} 应该像这样 [ \t\n\r\f\v\b]+ 和 "\r" 表示回车。
【解决方案2】:

我不确定我是否正确理解了您的场景,但您似乎正在使用 Flex 和正则表达式解析文件?

通常的方法是使用 Flex 生成一个仅识别令牌的扫描器(函数 yylex)。令牌可以是单个数字或门名称。扫描器在找到令牌后立即返回。因此扫描器将输入(文件中的字符序列)转换为标记序列。

然后您使用解析器生成器(通常是 Bison)来生成解析器,该解析器将这些单个标记与语法进行比较,然后在解析器级别处理您输入的更大结构。

当您尝试在 Flex 中完成这一切时会变得非常复杂,而这并不适合它。

【讨论】:

  • 是的,托马斯。我明白你的意思。事实上,我确实需要使用野牛来解析这个文件。现在的问题是我不能让我的 flex 文件输出我想要的东西。此外,我的野牛文件也有问题。我可能需要稍后发布关于野牛文件的问题。
猜你喜欢
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 2011-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多