Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bison 我应该如何处理Flex lexer中的词汇错误?_Bison_Yacc_Lex_Flex Lexer_Lexer - Fatal编程技术网

Bison 我应该如何处理Flex lexer中的词汇错误?

Bison 我应该如何处理Flex lexer中的词汇错误?,bison,yacc,lex,flex-lexer,lexer,Bison,Yacc,Lex,Flex Lexer,Lexer,我目前正在尝试使用Flex+Bison编写一个小型编译器,但我对如何处理错误,特别是如何使所有内容都协调一致,有点不知所措。为了激发讨论,请考虑下面我使用的字符串字符串: ["] { BEGIN(STRING_LITERAL); init_string_buffer(); } <STRING_LITERAL>{ \\\\ { add_char_to_buffer('\\'); } \\\" { add_char_to_buffer('\"

我目前正在尝试使用Flex+Bison编写一个小型编译器,但我对如何处理错误,特别是如何使所有内容都协调一致,有点不知所措。为了激发讨论,请考虑下面我使用的字符串字符串:

["]          { BEGIN(STRING_LITERAL); init_string_buffer(); }
<STRING_LITERAL>{
    \\\\    { add_char_to_buffer('\\'); }
    \\\"    { add_char_to_buffer('\"'); }
    \\.     { /*Invalid escape. How do I treat this error?*/ }
    ["]     { BEGIN(INITIAL); yylval = get_string_buffer(); return TK_STRING; }
}
[“]{BEGIN(STRING_LITERAL);init_STRING_buffer();}
{
\\\\{将字符添加到缓冲区('\\');}
\\\{将字符添加到缓冲区(“\”);}
\\.{/*转义无效。如何处理此错误?*/}
[“]{BEGIN(INITIAL);yylval=get_string_buffer();return TK_string;}
}
我如何处理无效逃逸的情况?现在我只是打印一条错误消息并调用
exit
,但我更希望能够继续运行,并在可能的情况下检测每个文件中的多个错误

我的问题是:

  • 我使用什么功能打印错误消息?和野牛后来预期的一样?如果我有单独的lexer和parser文件,那么我应该把yyerror的定义放在哪里
  • 我应该从我的操作返回什么令牌代码?0表示“文件结束”?一些特殊的TK_无效字符串标记
  • 如何确保语法分析器在出现词法错误(无效的文本、零散的标点符号等)后可以继续解析

    • 有很多选择。哪一个最好可能是意见的问题。(请注意,对于回答为观点而非事实的问题,SO并不友好。)

      这在很大程度上取决于您通常如何处理应用程序中的错误消息。但这里有两种可能性:

    • 直接从lexer打印错误消息。告诉您错误检测系统编译失败:您可以使用全局错误计数(yuk,globals!)或传递给
      yylex
      的共享数据结构作为附加参数。然后忽略字符并继续词法分析

    • 向解析器返回类似于
      TK\u INVALID\u STRING
      的内容。解析器将需要有适当的
      错误
      产品,以便适当地处理和恢复此错误,这需要大量的工作,但其优点是将所有错误处理都放在解析器中。但是,在字符串的特殊情况下,您可能需要完成字符串的词法分析,直到结束引号;否则,继续解析将是徒劳的

    • 至于
      yyerror
      :关于
      yyerror
      ,没有什么神奇之处。这完全是你的责任。bison所做的唯一一件事就是用一组指定的参数调用它。如果您发现它对记录lexer中注意到的错误很有用(我认为可能是这样),那么就继续使用它。您完全负责声明
      yyrorm
      ,因此将其定义放在您在lexer和解析器中包含的任何共享头文件中。或者摆弄bison代码生成选项,以获得包含在使用bison创建的头文件中的定义。什么都容易。一旦你弄明白了如何声明
      yyrorm
      ,你可以在任何你想要的地方定义它:在lexer文件中,在bison文件中,或者(我的首选)在一个单独的支持函数库中


      (FWIW,我尝试了选项2,在我看来,这真的是太多的工作了;选项1对我来说很好。但是口味不同,YMMV;我不打算在这里捍卫我的选择,但我不介意承认。)

      最简单的事情就是有一个最终的规则

      . return yytext[0];
      
      这包括所有单个特殊字符以及所有非法字符。直接在语法中使用特殊字符,如“:”、“;”等。然后,如果获得非法字符,将调用解析器的错误处理,从而提供一些恢复的可能性。如果你在lexer中处理它们,你所能做的就是打印一个错误并忽略它们


      它也减少了Lax文件的大小。

      < P>如果你使用的是带有C++输出的BySon,另一个选项是抛出异常。
      .   throw yy::parser::syntax_error("invalid character: " + std::string(yytext, yyleng);
      

      如果使用选项1,当lexer发现无效的字符串文本时,它会返回什么?你会假装它是一个有效的(返回TK_字符串),然后让负责调用解析器的高级代码检查全局错误变量吗?@missingno:没错。这是继续解析的最简单方法。在准备生成代码之前,不需要检查错误。从这个意义上讲,它与超出范围的整数没有什么不同,例如:您希望确保编译失败,但从解析的角度来看,您应该能够继续检查其余的语法。FWIW我经常使用选项1,但调用yyerror发出错误消息,以便所有的“语法错误”只能在一个地方进行处理。@akim:请在我的回答中搜索“我认为可能是”。这是一个合理的方法,但接下来您如何处理OP中的最后一个问题:“我如何确保语法分析器在出现词法错误后可以继续进行语法分析?”假设,一旦您将flex内部构件从中取出,它们就会被烤熟,?否?@rici:生成的解析器捕获
      语法错误
      ,然后触发常规错误报告/恢复序列。至于
      yylex
      函数本身,我看不出它会发生什么:它的控制流被设计为通过
      返回是可中断的
      继续等等。在实践中,我从来没有遇到过任何问题。