Flex Bison构造的编译器打印正确的结果然后给出语法错误

时间:2016-05-20 08:18:13

标签: c++ parsing compiler-construction bison flex-lexer

我正在尝试构建一个编译器。我建造它,但是当我尝试它时,它会出错。其实我的野牛创建的test.tab.cc文件包含调试标签,但我无法使用它我的测试用例是:

  

ERROR.NEVER.A

我的编译器打印正确的东西(" errrneverrraaabbbr ")但之后错误方法被调用并给出错误:

  

"错误:1.1"

的语法错误

这是否意味着第一行第一个元素,它有什么问题?

%skeleton "lalr1.cc"
%require  "3.0"
%debug 
%defines 
%define api.namespace {YK}
%define parser_class_name {YK_Parser}

%code requires{
   namespace YK {
      class YK_Driver;
      class YK_Scanner;
   }

// The following definitions is missing when %locations isn't used
# ifndef YY_NULLPTR
#  if defined __cplusplus && 201103L <= __cplusplus
#   define YY_NULLPTR nullptr
#  else
#   define YY_NULLPTR 0
#  endif
# endif

}

%parse-param { YK_Scanner  &scanner  }
%parse-param { YK_Driver  &driver  }

%code{
   #include <iostream>
   #include <cstdlib>
   #include <fstream>

   /* include for all driver functions */
   #include "yk_driver.hpp"

#undef yylex
#define yylex scanner.yylex
}

%define api.value.type variant
%define parse.assert
%token           DOT
%token               ERROR
%token               NEVER
%token               A
%token               B
%token               C
%token               BE
%token               AF
%start program

%%

program : rule ;

rule : vio DOT temp DOT event{std::cout<<"r";};

vio : ERROR{std::cout<<"errr";} 
                ;

temp :       NEVER{std::cout<<"neverrr";};

event : basic{std::cout<<"bbb";}
       |  basic DOT temp DOT basic{std::cout<<"c";}
      ;

temporal :  BE{std::cout<<"beeee";} 
          | AF{std::cout<<"affff";}
          ;

basic :      A{std::cout<<"aaa";} 
           | B{std::cout<<"bbb";}
           | C{std::cout<<"c";}
           ;
void test::test_Parser::error( const location_type &l, const std::string &err_message )
{
   std::cerr << std::endl << "Error: " << err_message << " at " << l << "\n";
}
%{
/* C++ string header, for string ops below */
#include <string>

/* Implementation of yyFlexScanner */ 
#include "yk_scanner.hpp"
#undef  YY_DECL
#define YY_DECL int YK::YK_Scanner::yylex( YK::YK_Parser::semantic_type * const lval, YK::YK_Parser::location_type *location )

/* typedef to make the returns for the tokens shorter */
using token = YK::YK_Parser::token;

/* define yyterminate as this instead of NULL */
#define yyterminate() return( token::END )

/* msvc2010 requires that we exclude this header file. */
#define YY_NO_UNISTD_H

/* update location on matching */
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);

%}

%option debug
%option nodefault
%option yyclass="YK::YK_Scanner"
%option noyywrap
%option c++

%%
%{          /** Code executed at the beginning of yylex **/
            yylval = lval;
%}

[ \t\n]+        {} 
.       {return token::DOT;}
ERROR       {return token::ERROR;}
NEVER           {return token::NEVER;}
A           {return token::A;}
B           {return token::B;}
C           {return token::C;}
BE           {return token::BE;}
AF           {return token::AF;}

PS。在yyerrlab标签内,生成了我的错误字符串。以下代码之一导致错误。

if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.type_get ())
      goto yydefault;

    // Reduce or error.
    yyn = yytable_[yyn];
    if (yyn <= 0)
      {
        if (yy_table_value_is_error_ (yyn))
          goto yyerrlab;
        yyn = -yyn;
        goto yyreduce;
      }

    // Discard the token being shifted.
    yyempty = true;

    // Count tokens shifted since error; after three, turn off error status.
    if (yyerrstatus_)
      --yyerrstatus_;
/*-----------------------------------------------------------.
  | yydefault -- do the default action for the current state.  |
  `-----------------------------------------------------------*/
  yydefault:
    yyn = yydefact_[yystack_[0].state];
    if (yyn == 0)
      goto yyerrlab;
    goto yyreduce;
#include <iostream>
#include <cstdlib>
#include <cstring>

#include "yk_driver.hpp"

int main( const int argc, const char **argv )
{
   /** check for the right # of arguments **/
   if( argc == 2 )
   {
      YK::YK_Driver driver;
      /** example for piping input from terminal, i.e., using cat **/ 
      if( std::strncmp( argv[ 1 ], "-o", 2 ) == 0 )
      {
         driver.parse( std::cin );
      }
      /** simple help menu **/
      else if( std::strncmp( argv[ 1 ], "-h", 2 ) == 0 )
      {
         std::cout << "use -o for pipe to std::cin\n";
         std::cout << "just give a filename to count from a file\n";
         std::cout << "use -h to get this menu\n";
         return( EXIT_SUCCESS );
      }
      /** example reading input from a file **/
      else
      {
         /** assume file, prod code, use stat to check **/
         driver.parse( argv[1] );
      }
      driver.print( std::cout ) << "\n";
   }
   else
   {
      /** exit with failure condition **/
      return ( EXIT_FAILURE );
   }
   return( EXIT_SUCCESS );
}

1 个答案:

答案 0 :(得分:2)

最有可能的原因是,在解析A之后,在行尾的rule之后输入中的任何内容引起了这种情况(显然正在减少,根据您的输出显示),它将期待一个EOF减少程序和返回。如果你的词法分析器返回的不是EOF,你就会收到错误。也许是\r(回车),因为你的词法分析器似乎没有忽略它?