0

我最近尝试使用GNU BisonFlex编写解释器。我希望解释器识别的文本是print "Hello",我尝试了以下方法:

flex file:

%{
#include <iostream>
using namespace std;
#define YY_DECL extern "C" int yylex()
#include "gbison.tab.h"
%}
%%
[ \t\n]            ;
'\"'               return QUOTE;
[a-zA-Z0-9]+       { yylval.sval = strdup(yytext); return STRING; }
%%

bison file:

%{
#include <cstdio> 
#include <cstring>
#include <iostream>
using namespace std;

extern "C" int yylex();
extern "C" int yyparse();
extern "C" FILE* yyin;

void yyerror (const char* s);
%}

%union {
  char* sval;
}

%token <sval> STRING
%token QUOTE
%%

str:
    STRING QUOTE STRING QUOTE
    {
       if (strcmp($1, "print") == 0)
       {
           cout << $3 << flush;
       }
       if (strcmp($1, "println") == 0)
       {
           cout << $3 << endl; 
       }
    }
    ;
%%

main(int argc, char* argv[])
{
   FILE* input = fopen(argv[1], "r");
   if (!input)
   {
      cout << "Bad input. Nonexistant file" << endl; 
      return -1;
   } 

   yyin = input;

   do 
   {
       yyparse();
   } while (!feof(yyin));

}
void yyerror(const char* s)
{
   cout << "Error. " << s << endl; 
   exit(-1);   
}

但是当我传递print "hello"给已编译的程序时,我得到: "Error. syntax error

我认为问题是,STRING QUOTE STRING QUOTE但我不确定。到底出了什么问题?我如何让解释器打印hello

4

1 回答 1

1

答案如下,但我希望以下内容更普遍有用,作为钓鱼指导。

有多种调试工具可以帮助您。特别是, flex 提供了-d标志:

-d, --debug

使生成的扫描仪以“调试”模式运行。每当识别出模式并且全局变量yy_flex_debug不为零(这是默认值)时,扫描仪将写入stderr一行……(弹性手册

bison 还提供了一个调试工具。(野牛手册

有几种方法可以启用跟踪工具的编译:
  • YYDEBUG
  • 选项-t(POSIX Yacc 兼容)…
  • 选项--debug(Bison 扩展)…
  • 指令%debug……
我们建议您始终启用调试选项,以便始终可以进行调试。
...
一旦你用跟踪工具编译了程序,请求跟踪的方法是在变量中存储一个非零值yydebug。您可以通过让 C 代码执行此操作(可能在 中main),或者您可以使用 C 调试器更改该值。

另外,请记住 flex 会插入一个自动规则,该规则会导致将任何其他无法识别的字符回显到输出中。(“默认情况下,flex 扫描仪不匹配的任何文本都会被复制到输出中”——一些简单的例子)这就是为什么你"的程序打印的错误消息中有额外的内容:

"Error. syntax error
^

不过,这有点微妙。追踪flex会更直接地向您展示这一点。

所以,最后,问题:

  1. flex 模式'\"'与 a 不匹配"。它匹配'"',因为单引号对于 flex 不是特殊的。这绝对是您的解析失败的原因。

  2. 修复该问题将使您的程序解析单个命令,但如果您尝试在同一输入中为其提供两个打印命令,则会产生语法错误。这是因为野牛总是解析直到它END从词法分析器接收到一个标记,并且词法分析器(默认情况下)只END在到达输入末尾时提供一个标记。你可以改变

    • 词法分析器行为(通过END在其他情况下发送,例如换行)(推荐)

    • 解析器行为(通过使用ACCEPT)(可能,但很少需要)

    • 语法,因此它可以识别任意数量的语句。(推荐

于 2013-09-29T19:56:36.110 回答