带YACC的词法分析器,识别循环

时间:2015-01-07 16:07:06

标签: compilation yacc lex

lex文件

%%
^((for)|(while))[(][)] return FORWHILE;
[ ]* return SPACE;
([a-z ]+[;])+ return LINE;
. ;
%%

yacc文件

%start   s
%token FORWHILE
%token SPACE
%token LINE
%%
s: FORWHILE SPACE '{' SPACE LINE SPACE '}' SPACE
{
  printf("Data OK\n");
};

%%
#include <stdio.h>
#include <string.h>
#include "lex.yy.c"
int main()
{
  return yyparse();
}

int yyerror()
{
  printf("Error in data\n");
  return 0;
}

这就是我的尝试。

我希望输入for(){bla bla;bla bla;}会产生Data OK。 我出于某种原因无法让它工作。 问题是什么? 感谢

更新

%start   s
%token FOR
%token WHILE
%token LINE
%token DO
%%
s: forwhile | dowhile { printf("Data OK\n"); };
dowhile: do_stmt '{' lines '}' while_stmt;
forwhile: for_or_while_stmt '{' lines '}';
lines: line | lines line;
line: LINE;
for_or_while_stmt: for_stmt | while_stmt;
for_stmt: FOR'()';
while_stmt: WHILE'()';
do_stmt: DO;
%%
#include <stdio.h>
#include <string.h>
#include "lex.yy.c"
int main()
{
  return yyparse();
}

int yyerror()
{
  printf("Error in data\n");
  return 0;
}

%%
"while" return WHILE;
"for" return FOR;
"do" return DO;
[a-z ]+[;] return LINE;
. return yytext[0];
%%

我也添加了。但仍然无法做到正确。

1 个答案:

答案 0 :(得分:1)

根据您的词汇扫描程序,bla bla;bla bla;包含两个LINE令牌。但是,你的语法只允许一个

s: FORWHILE SPACE '{' SPACE LINE SPACE '}' SPACE

您还应该解决其他一些问题。首先,与[ ]* { return SPACE; }一样,lex模式与空字符串匹配并不是一个好主意。如果匹配成功(只有在不再存在匹配时才可能),那么您将发现自己处于无限循环中,因为扫描仪永远不会前进。

通常不建议将空格标记传递给解析器;更好的是在词法扫描器中简单地忽略它们,特别是(如本例所示)它们是可选的。另一方面,忽略无法识别的字符(. ;)可以轻松掩盖错误。

最后,.与任何角色都不匹配。它匹配换行符以外的任何字符。在您的词法扫描程序定义中,换行符不符合任何规则,因此会导致上面提到的无限循环。如果您将SPACE规则修复为仅匹配非空序列,则新行将落入隐式默认规则ECHO。这也不是一个好主意。

我强烈建议使用%option nodefault,如果任何输入与任何规则不匹配,将导致flex提供诊断。但是,这不会警告你关于匹配空模式的规则,所以你仍然需要小心。