gpt4 book ai didi

c - Flex 和 Bison : Beginning a sentence with a specific keyword

转载 作者:行者123 更新时间:2023-11-30 15:13:34 24 4
gpt4 key购买 nike

我正在使用 Flex 和 Bison 开发一个程序。我的任务只能使用 Flex 完成(使用启动条件等),但我知道使用 Bison 可能会让我的生活更轻松。我的任务是设计一个识别编程语言声明部分的程序。它的语法和逻辑可以通过我下面的代码来理解。我的问题是我希望我的程序将代码中以“var”关键字开头的每个部分都识别为可接受的声明部分!到目前为止,我还没有做到这一点。我怎样才能成功?

下面是我的 .l (flex) 和 .y (bison) 文件。

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"

最佳答案

您的扫描仪永远不会返回 :; token (并提示 , 无法识别)。但你的语法包含这些标记。

因此,

typedecl : varlist ':' var_type ';' ;

永远无法匹配任何内容。它没有看到它所期望的 :,因此 var_type 是意外的。 (如果到了这一步,它就永远不会匹配 ; 了。)

<小时/>

我不知道您正在遵循什么古老的教程,但是 main 的 pre-ansi 原型(prototype)表明它是在上个世纪编写的(也不是在其最后几年)。作为粗略指南,我稍微更新了您的文件。

这是练习4.l;最重要的修改是我删除了手工构建的跟踪日志,因为我打算使用 Flex 的内置调试功能。我还添加了一些选项来减少编译器警告,并启用行号跟踪以在错误消息中使用。我留在了错误中。

/* 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]; }

这是解析器,进行了一些修复(例如使用 1989 C 标准中的标准 C 原型(prototype)语法):

/* 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);
}

现在,我按顺序通过 flex、bison 和 gcc 运行这些文件,以生成可执行文件:

# 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

通常,这三个 shell 命令将进入 Makefile,以便您只需键入 makeexercise4 即可创建可执行文件。但那里并没​​有什么真正复杂的。

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

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 ','

--开始的行是flex的跟踪。您可以看到每个被识别的 token 。因此,当输入中遇到 : 时,就会执行第 13 行的规则。该规则是 {/* 忽略所有冒号 */}。这就是发生的事情。

最后的错误消息是由yyerror打印的。感谢 %errors-verbose 指令,它告诉我们它发现了​​什么(INTEGER)以及它期望什么。

希望对大家有所帮助。

关于c - Flex 和 Bison : Beginning a sentence with a specific keyword,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34501734/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com