c-flex/bison我如何让它识别一个模式,不管最后的字符是否是点



我试图对prolog的代码进行分析/解析器,下面是一个事实的例子:"dadof(阿图罗,阿曼多("它以一个点(.(结束,我的解析器识别它,然后打印("hecho"(但我有另一个选择,如果输入是"0";dadof(arturo,armando(;它没有认出它。唯一的区别是没有点。但它假设它也应该识别它,然后打印";(hecho(。但它不能成功。

这是我的代码

lex代码:

%{
#include <stdio.h>
#include <string.h>
#include "que.tab.h"
void showError();
%}
%option noyywrap

LETTER [a-zA-Z]
WORD    {LETTER}+

%%
[[:blank:]] {}
[ tr] {} 
{WORD}  { sscanf(yytext, "%s",yylval.cad); return CADENA; }
"%"     { return PERCENT; }
"("     { return OPENB; }
")"     { return CLOSEB; }
","     { return COMA; }
"."     { return POINT; }
":-"    { return POINTSLASH; }
"[papa]"  { return NOFACT; }
.   { showError(); return OTROS; }
%%
void showError(char *OTROS){
printf("  <<Error lexico: "%s">>  ", OTROS);
}

野牛代码:

%{
#include <stdio.h>
int yylex(void);
void yyerror(char *s);
%}
%token CADENA PERCENT OTROS 
%token OPENB CLOSEB COMA POINT POINTSLASH
%type <cad> CADENA
%union{
char cad[20];
}
%start INPUT

%%
INPUT
: INICIO
| INPUT INICIO
;
INICIO:
HECHOS
{
printf("(Hecho)");
}

;
HECHOS
: HECHO POINT
| HECHO


; 


HECHO
:INSTRUCCION OPENB INSTRUCCION COMA INSTRUCCION CLOSEB 
| INSTRUCCION OPENB INSTRUCCION COMA INSTRUCCION CLOSEB COMA HECHO


;

INSTRUCCION:
| CADENA
| OTROS
;
%%
int main(){
return(yyparse());
return 0;
}
void yyerror(char *s){
printf("%s", s);
}

正如我之前所说,它应该打印";(Hecho(";无论输入是否以点结束。

尽管您的代码有很多问题,但它与问题中的测试输入完美配合。所以我假设你所做的是这样的:

$ bison -d -o que.tab.c que.y
$ flex -o que.lex.c que.l
$ gcc -o que que.tab.c que.lex.c
$ ./que
dadof(arturo,armando)

然后你等着看发生了什么。但什么也没发生,因为您的程序仍在等待您输入更多输入。

或者您可能通过键入Ctrl-C终止了您的程序。和以前一样,您的程序仍在等待输入,所以它还没有尝试打印任何内容。Control-C会立即终止正在运行的程序。砰,死了。没有机会清理,打印任何最终结果,什么都没有。戏剧性,是的,但有时你需要这样做。在这种情况下不会。

如果您将dadof(arturo,armando)行放入一个文件中,并将该文件作为输入运行程序,您将或多或少地得到预期的输出:

$ echo "dadof(arturo,armando)" > test.txt
$ ./que < test.txt
(Hecho)$

如果要从控制台键入输入,则需要通过键入Ctrl-Z-Enter(在Windows上(或Ctrl-D(在Linux/Mac上(来告诉程序输入已完成。(顺便说一句,你必须在一行的开头键入它。(然后你会看到与上面相同的输出。

该输出确实显示了代码的几个问题:

  1. 由于您的模式都无法识别换行符(n(,因此Flex扫描仪使用默认规则处理这种情况。默认规则是将未识别的字符写入标准输出,然后继续查找令牌。这就是为什么在´(Hecho(´之前出现了一个意想不到的换行符。在解析器中,您几乎不想触发默认的lex操作;我建议使用option nodefault禁用默认值,如果您错过了一些字符,这将导致flex打印警告。为了避免这种情况发生,使用模式.|n而不是.作为最终的回退规则,和/或确保显式处理换行符。(例如,您可以使用[[:space:]]而不是[[:blank:]]。(

  2. 使用printf("(Hecho)");打印(Hecho)。这不会打印新行,然后您的程序将控制权返回给shell。因此,shell提示会在您的消息之后立即打印出来,这很难阅读。您应该始终记住以n结束所有输出行。

最新更新