Flex和野牛:开始一个句子有特定关键字 [英] Flex and Bison: Beginning a sentence with a specific keyword

查看:262
本文介绍了Flex和野牛:开始一个句子有特定关键字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Flex和Bison的程序。我的任务可以(使用启动条件等),只使用Flex的工作要做,但我已经明白,使用野牛可能使我的生活更轻松。我的任务是设计一个程序,它可以识别一种编程语言声明的一部分。它的语法和逻辑可以通过我下面code可以理解。我的问题是,我想我的程序来识别一个可以接受的申报环节code的每一个部分而开始的 VAR 的文章!到现在为止,我还没有成功地做到这一点。我怎么能成功呢?

下面我.L(弯曲)和.Y(野牛)的文件,我present。

exercise4.l

 %{
#包括LT&;&stdio.h中GT;
%}
%%
[\\ t \\ n] + {/ *忽略全部空白* /}
; {/ *忽略所有分号* /}
:{/ *忽略所有冒号* /}
VAR {printf的(A关键字:%S \\ n,yytext中);返回VAR; }
真正{printf的(A变量类型:%S \\ n,yytext中);返回REAL; }
布尔{printf的(A变量类型:%S \\ n,yytext中);返回boolean变量; }
整数{printf的(A变量类型:%S \\ n,yytext中);返回整数; }
字符{printf的(A变量类型:%S \\ n,yytext中);返回CHAR; }
[A-ZA-Z] [A-ZA-Z0-9 _] * {printf的(变量名称:%s \\ n,yytext中);返回VAR_NAME; }
。 {printf的(无法识别的字符\\ n!);返回yytext中[0]; }
%%

exercise4.y

 %{
#包括LT&;&stdio.h中GT;
%}
%令牌VAR VAR_NAME REAL布尔INTEGER CHAR
%%
程序:VAR typedecls;
typedecls:typedecl | typedecls typedecl;
typedecl:varlist中':'var_type';' ;
varlist中:VAR_NAME | varlist中','VAR_NAME;
var_type:REAL |布尔| INTEGER | CHAR;
%%
主(ARGC,ARGV)
INT ARGC;
焦炭** argv的;
{
的extern FILE * yyin中;
++ argv的,--argc; / *跳过程序名称* /
如果(argc个大于0)
yyin中FOPEN =(的argv [0],R);
其他
yyin中=标准输入;
//函数yylex();
yyparse();
}
的yyerror(字符* S)
{
 的printf(\\ n错误\\ n);
}
的#includelex.yy.c中


解决方案

您的扫描仪永远不会返回; 令牌(和抱怨是无法识别)。但是你的语法包括这些令牌。

因此​​,

  typedecl:varlist中':'var_type';' ;

永远无法匹配任何内容。它没有看到它期待,而 var_type 因此,出人意料。 (而且它不会永远符合; ,如果它得到那么远)


我不知道你在什么如下古代的教程,但pre-ANSI原型表明它是在上个世纪由(和不是在它的最后几年,无论是)。作为一个粗略的指南,我稍微更新您的文件。

下面是exercise4.l;最重要的修改是我删除了handbuilt跟踪日志,因为我打算用Flex的内置调试功能。我还添加了一些选项,以减少编译器警告,并启用了行号的错误信息使用跟踪。我离开的bug。

  / *文件:exercise4.l * /
%{
  / *野牛生成的头文件中包括令牌声明* /
  #包括exercise4.tab.h
%}%选择noinput nounput noyywrap NODEFAULT
%选择yylineno%%
[\\ t \\ n] + {/ *忽略全部空白* /}
; {/ *忽略所有分号。 BUG * /}
:{/ *忽略所有冒号。 BUG * /}
VAR {VAR回报; }
真正{返回REAL; }
布尔{返回boolean变量; }
整数{返回整数; }
焦炭{返回CHAR; }
[A-ZA-Z] [A-ZA-Z0-9 _] * {返回VAR_NAME; }
。 {返回yytext中[0]; }

和这里的解析器,有一些修正(如使用从1989年C标准标准C原型语法):

  / *文件:exercise4.y * /
%{
  / *用于在该文件中* /
  #包括LT&;&stdio.h中GT;  / *转发和外部声明* /
  EXTERN INT yylineno;
  INT函数yylex();
  无效的yyerror(为const char *味精);
%} / *这两个选项使错误消息的详细信息* /
%定义parse.lac满
%错误详细%令牌VAR VAR_NAME REAL布尔INTEGER CHAR%%程序:VAR typedecls
typedecls:typedecl
          | typedecls typedecl
typedecl:varlist中':'var_type';'
varlist中:VAR_NAME
          | varlist中','VAR_NAME;
var_type:REAL |布尔| INTEGER | CHAR;%%/ *欢迎到1990年* /
INT主(INT ARGC,字符** argv的){
  的extern FILE * yyin中;
  如果(argc个大于1)
    yyin中FOPEN =(的argv [1],R);
  其他
    yyin中=标准输入;
  如果(!yyin中){
    / *如果你不检查,你最终会当段错误
     *函数yylex试图从空读取。检查让我们打印
     *一个希望有意义的错误消息。
     * /
    PERROR(无法打开文件进行读取);
    返回1;
  }
  返回yyparse();
}/ *现在的错误消息有一些内容,这是值得的
 *实际使用传递的参数YYERROR * /
无效的yyerror(为const char *味精){
  fprintf中(标准错误,在列%d:%S \\ n,yylineno,味精);
}

现在,我贯穿弯曲,野牛和海湾合作委员会的文件,按照这个顺序,生成一个可执行:

 #了`-d`选项弯曲使它将调试痕迹。那是
#少了很多的努力和很多比滚动自己的跟踪更为有用
#日志。
柔性-d -o exercise4.scan.c exercise4.l
#了`-d`选项野牛它会导致输出的头文件,其名字
#是相同的,与`.c`改为`.h`输出文件名。那是
#这就需要我们`#include`在扫描仪的文件,这样令牌
#名称可对电脑灯操作。野牛也有一个调试
#功能,但你需要使用`-t`来启用它,再加上添加一行
# 运行。现在,我们会离开它。
野牛-d -o exercise4.tab.c exercise4.y
#现在编译和链接的可执行文件:
GCC -Wall -g -o exercise4 exercise4.tab.c exercise4.scan.c

通常情况下,这三个shell命令将进入一个Makefile文件,让你可以只输入使exercise4 以创建可执行文件。但没有什么很复杂那里。

现在,我们可以尝试一下。由于我没有修正错误,你会很容易看到问题:

 变种A,B:整数;
在14号线--accepting规则(VAR)
在第11行()--accepting规则
在第19行--accepting规则(一)
在第20行--accepting规则()
在第11行()--accepting规则
在第19行--accepting规则(B)
第13行--accepting规则(:)
在第11行()--accepting规则
在17行--accepting规则(整数)
在第1行:语法错误,意想不到的INTEGER,期待':'或','

该行开始 - 是弯曲的痕迹。你可以看到每个令牌,因为它是公认的。因此,当一个在输入中遇到,第13行的规则执行。这条规则是 {/ *忽略所有冒号* /} 。这就是发生了什么。

在最后的错误消息是由的yyerror 打印。多亏了%错误 - 详细指令,它告诉我们它找到了什么( INTEGER )和它所期待。

希望所有帮助一些。

I am working on a program using Flex and Bison. My task can be done using only Flex(using start conditions etc.), but I have understood that using Bison might make my life easier. My task is to design a program which recognizes a programming language declaration part. Its syntax and logic can be understood through my code below. My problem is that I want my program to recognize as an acceptable declaration part every part of code which begins only with the "var" keyword! Until now, I have not managed to do that. How can I succeed it?

I present below my .l (flex) and .y (bison) files.

exercise4.l

%{
#include <stdio.h>
%}
%%
[ \t\n]+                { /* Ignore all whitespaces */ }
";"         { /* Ignore all semicolons */ }
":"         { /* Ignore all colons */ }
var                     { printf("A keyword: %s\n",yytext); return VAR; }
real                    { printf("A variable type: %s\n",yytext); return REAL; }
boolean                 { printf("A variable type: %s\n",yytext); return BOOLEAN; }
integer                 { printf("A variable type: %s\n",yytext); return INTEGER; }
char                    { printf("A variable type: %s\n",yytext); return CHAR; }
[a-zA-Z][a-zA-Z0-9_]*   { printf("A variable name: %s\n",yytext); return VAR_NAME; }
.                       { printf("Unrecognized character!\n"); return yytext[0]; }
%%

exercise4.y

%{
#include <stdio.h>    
%}
%token VAR VAR_NAME REAL BOOLEAN INTEGER CHAR
%%
program : VAR typedecls ;
typedecls : typedecl | typedecls typedecl ;
typedecl : varlist ':' var_type ';' ;
varlist : VAR_NAME | varlist ',' VAR_NAME ;
var_type : REAL | BOOLEAN | INTEGER | CHAR ;
%%
main( argc, argv )
int argc;
char **argv;
{
extern FILE *yyin;
++argv, --argc; /* skip over program name */
if ( argc > 0 )
yyin = fopen( argv[0], "r" );
else
yyin = stdin;
//yylex();
yyparse();
}
yyerror(char *s)  
{  
 printf("\nError\n");  
}
#include "lex.yy.c"

解决方案

Your scanner never returns : or ; tokens (and complains about , being unrecognized). But your grammar includes those tokens.

Consequently,

typedecl : varlist ':' var_type ';' ;

can never match anything. It doesn't see the : it is expecting, and the var_type is thus unexpected. (And it wouldn't ever match the ; if it got that far.)


I don't know what ancient tutorial you're following, but the pre-ansi prototype for main suggests it was composed in the last century (and not in its final years, either). As a rough guide, I slightly updated your files.

Here's exercise4.l; the most important modification is that I removed the handbuilt trace logs, since I intend to use flex's built-in debugging feature. I also added some options to reduce compiler warnings, and enabled line number tracking for use in error messages. I left in the bug.

/* File: exercise4.l */
%{
  /* The bison-generated header file includes token declarations */
  #include "exercise4.tab.h"
%}

%option noinput nounput noyywrap nodefault
%option yylineno

%%
[ \t\n]+                { /* Ignore all whitespaces */ }
";"                     { /* Ignore all semicolons. BUG */ }
":"                     { /* Ignore all colons. BUG */ }
var                     { return VAR; }
real                    { return REAL; }
boolean                 { return BOOLEAN; }
integer                 { return INTEGER; }
char                    { return CHAR; }
[a-zA-Z][a-zA-Z0-9_]*   { return VAR_NAME; }
.                       { return yytext[0]; }

And here's the parser, with a few fixes (like using the standard C prototype syntax from the 1989 C standard):

/* File: exercise4.y */
%{
  /* Used in this file */
  #include <stdio.h>

  /* Forward and external declarations */
  extern int yylineno;
  int yylex();
  void yyerror(const char* msg);
%}

 /* These two options make error messages more informative */    
%define parse.lac full
%error-verbose

%token VAR VAR_NAME REAL BOOLEAN INTEGER CHAR

%%

program   : VAR typedecls
typedecls : typedecl
          | typedecls typedecl
typedecl  : varlist ':' var_type ';'
varlist   : VAR_NAME
          | varlist ',' VAR_NAME ;
var_type  : REAL | BOOLEAN | INTEGER | CHAR ;

%%

/* Welcome to 1990 */
int main( int argc, char** argv ) {
  extern FILE *yyin;
  if ( argc > 1 )
    yyin = fopen( argv[1], "r" );
  else
    yyin = stdin;
  if (!yyin) {
    /* If you don't check, you'll end up segfaulting when
     * yylex tries to read from NULL. Checking lets us print
     * a hopefully meaningful error message.
     */
    perror("Could not open file for reading");
    return 1;
  }
  return yyparse();
}

/* Now that error messages have some content, it's worthwhile
 * actually using the argument passed to yyerror */
void yyerror(const char* msg) {
  fprintf(stderr, "At line %d: %s\n", yylineno, msg);
}

Now, I run the files through flex, bison and gcc, in that order, to produce an executable:

# The `-d` option to flex causes it to insert debugging traces. That's
# a lot less effort and a lot more useful than rolling your own trace
# logs.
flex -d -o exercise4.scan.c exercise4.l
# The `-d` option to bison causes it to output a header file, whose name
# is the same as the output file name with `.c` changed to `.h`. That's
# the file which we need to `#include` in the scanner, so that token
# names are available to scanner actions. Bison also has a debugging
# feature, but you need to use `-t` to enable it, plus add a line at
# runtime. For now, we'll leave it out.
bison -d -o exercise4.tab.c exercise4.y
# Now compile and link an executable:
gcc -Wall -g -o exercise4 exercise4.tab.c exercise4.scan.c

Normally, the three shell commands would go into a Makefile so that you could just type make exercise4 to create the executable. But there's nothing really complicated there.

Now, we can try it out. Since I didn't fix the bugs, you'll easily see the problem:

var a, b: integer;
--accepting rule at line 14 ("var")
--accepting rule at line 11 (" ")
--accepting rule at line 19 ("a")
--accepting rule at line 20 (",")
--accepting rule at line 11 (" ")
--accepting rule at line 19 ("b")
--accepting rule at line 13 (":")
--accepting rule at line 11 (" ")
--accepting rule at line 17 ("integer")
At line 1: syntax error, unexpected INTEGER, expecting ':' or ','

The lines starting -- are flex's trace. You can see each token as it is recognized. So when a : is encountered in the input, the rule at line 13 is executed. That rule is { /* Ignore all colons */ }. And that's what happens.

The error message at the end was printed by yyerror. Thanks to the %errors-verbose directive, it tells us what it found (INTEGER) and what it was expecting.

Hope that all helps some.

这篇关于Flex和野牛:开始一个句子有特定关键字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆