2013-09-29 40 views
0

我最近尝试使用GNU BisonFlex来编写解释器。我想解释识别的文字是print "Hello",我已经试过如下:Bison/Flex解​​析文件

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

回答

1

答案在下面,但是我希望下面的内容更全面有用,就像钓鱼指令一样。

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

-d, --debug

使得 “调试” 模式生成的扫描仪运行。只要识别出模式并且全局变量yy_flex_debug非零(这是默认值),扫描器就会向stderr写入一行...... (flex manual

野牛还提供调试工具。 (bison manual

有几种手段,使的跟踪工具编译:
  • 宏观YYDEBUG&hellip;
  • 选项-t(符合POSIX Yacc)&hellip;
  • 选项--debug(野牛延伸)&hellip;
  • 该指令%debug&hellip;
我们建议您始终启用调试选项,以便始终可以调试 。
&hellip;
使用跟踪工具编译程序后, 请求跟踪的方式是将非零值存储在变量 yydebug中。 您可以通过使C代码执行此操作(也许在 main中),或者您可以使用C调试器更改该值。

另外,请记住,flex会插入自动规则,导致任何其他无法识别的字符被回显到输出。 (“默认情况下,不通过柔性扫描器匹配任何文本复制到输出” - Some simple examples)这就是为什么你在错误信息的额外"正在打印您的程序:

"Error. syntax error 
^ 

这是一个有点尽管微妙。跟踪flex本可以更直接地向您显示。

所以,最后,问题(S):

  1. 柔性模式'\"'不匹配它匹配。“”,因为单引号不特别要弯曲。这绝对是解析失败的原因。

  2. 修复会让程序解析单个命令,但如果您尝试在同一个输入中为其提供两个打印命令,则会生成语法错误。这是因为野牛总是解析,直到它从词法分析器收到END标记,并且词法分析器(默认情况下)仅在输入结束时提供END标记。您可以更改

    • 词法分析器的行为(在其他情况下发送END,例如新线)(未推荐

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

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