当我有更好的规则时,为什么我的lex文件中的最后一个规则匹配?

问题描述 投票:1回答:1

我有一个lex文件,其中包含我的规则,例如:

PROGRAM           return Parser::PROGRAM;
PROGRAM_END       return Parser::PROGRAM_END;
VARIABLES:        return Parser::VARIABLES;
INSTRUCTIONS:     return Parser::INSTRUCTIONS; 
SKIP              return Parser::SKIP;
.           {
                std::cerr << lineno() << ": ERROR." << std::endl;
                exit(1);
            }

并且当我尝试使用完全编译的版本(带有yacc文件等)时,则仅在测试文件上使用此规则,即使测试文件正确,也使用最后一条规则。

例如,这是这些规则的测试文件:

PROGRAM fst
INSTRUCTIONS:
    SKIP
PROGRAM_END

对于此文件,我只有:1: ERROR

这是为什么,我该如何解决?

regex bison yacc lex bisonc++
1个回答
1
投票

如注释中所示,几乎可以肯定,PROGRAM开始被识别为令牌并传递给解析器的情况。但是,在几乎所有情况下,解析器都会立即请求另一个令牌,并且输入序列中的下一个字符是一个空格,该空格与最后一个规则匹配。该规则将显示一条错误消息并调用exit(),从而终止该应用程序。 (通常这不是一个好主意,但我想这只是一个测试程序。)这就是您将获得的所有输出。

如果在调用(f)lex时指定-d命令行参数,则将生成调试扫描程序,该扫描程序将报告扫描程序的工作情况。这是查看扫描仪中正在发生的事情的一种非常简单的方法。如bison manual中所述,Bison还具有调试模式。这些工具使用起来非常简单,强烈建议使用。

例如,这里是快速测试装备:

%{
#include <iostream>
#include <cstdlib>
class Parser {
  public:
    enum Token {
      PROGRAM = 257,
      PROGRAM_END, VARIABLES, INSTRUCTIONS, SKIP
    };
};
%}
%option batch noyywrap yylineno c++
%%
PROGRAM           return Parser::PROGRAM;
PROGRAM_END       return Parser::PROGRAM_END;
VARIABLES:        return Parser::VARIABLES;
INSTRUCTIONS:     return Parser::INSTRUCTIONS; 
SKIP              return Parser::SKIP;
.                 {
                    std::cerr << lineno() << ": ERROR." << std::endl;
                    exit(1);
                  }
%%
int main() {
  yyFlexLexer lexer{};
  lexer.set_debug(1);
  while(lexer.yylex() != 0) { }
  return 0;
}

以及示例运行:

$ g++ lex.yy.cc && ./a.out<<<"PROGRAM fst"
--(end of buffer or a NUL)
--accepting rule at line 14("PROGRAM")
--accepting rule at line 19(" ")
1: ERROR.

这很明显,扫描仪在退出空格字符之前先产生了PROGRAM令牌。

© www.soinside.com 2019 - 2024. All rights reserved.