【问题标题】:'unrecognized rule' and 'fatal parse error' on FLEXFLEX 上的“无法识别的规则”和“致命的解析错误”
【发布时间】:2017-01-07 18:34:49
【问题描述】:

我必须使用 flex 和 bison 为简化的 Python 3 制作一个解析器,我得到了这 2 个错误。终端说它们在我写的 78 行中的第 79 行。我在课堂上还有其他具有这种格式的“.l”示例,它们工作正常

这是我写的

    %option noyywrap

%{ 
#define YYSTYPE double
#include "scanner.tab.h"
#include <stdlib.h>
#include <string>

extern int flag;
extern int line;
%}

DELIMITER    [ ]+|[/t]+

KEYWORD      False|class|finally|is|return|None|continue|for|lambda|try|True|def|from|nonlocal|while|and|del|global|not|with|as|elif|if|or|yield|assert|else|import|pass|break|except|in|raise

OPERATOR     ([+\-$@&|^~])|(\*{1,2})|(\/{1,2})|(<[=<]?)|(>[=>]?)|(==)|!

COMMENT      #.+

IDENTIFIER   [a-zA-Z_][a-zA-Z0-9_]*
ID_ERR       [0-9]{IDENTIFIER}

STRINGESCAPESEQ  [\\].  
SHORTSTRINGCHAR1 [^\\'\n]*
SHORTSTRINGCHAR2 [^\\"\n]*
SHORTSTRINGITEM1 {SHORTSTRINGCHAR1}|{STRINGESCAPESEQ}
SHORTSTRINGITEM2 {SHORTSTRINGCHAR2}|{STRINGESCAPESEQ}
STRING       [']{SHORTSTRINGITEM1}*[']|(["]{SHORTSTRINGITEM2}*["])
STRING_ERR   ['].[^'\n\t]*|["].[^"\n\t]* 

BINDIGIT     [01]
BININTEGER   0[bB]{BINDIGIT}+
BIN_ERR1     0[Bb]+{BINDIGIT}+

DIGIT        [0-9]
NONZERODIGIT     [1-9]
INTEGER      {NONZERODIGIT}{DIGIT}*|[0]+
INT_ERR1     {INTEGER}[a-zA-Z]{DIGIT}
INT_ERR2     [-+]{INTEGER}
INT_ERR3     [0+]{INTEGER}

INTPART      {DIGIT}+
EXPONENT     [eE][+-]*{INTPART}
FRACTION     [\.]{INTPART}
EXPONENTFLOAT    ({INTPART}|{POINTFLOAT}){EXPONENT}
POINTFLOAT   {INTPART}*{FRACTION}|{INTPART}[\.]
FLOATNUMBER  {POINTFLOAT}|{EXPONENTFLOAT}
FLOAT_ERR_POINT  {INTPART}*[\.]+{DIGIT}+[\.]*{DIGIT}*|{INTPART}[\.]+
FLOAT_ERR_SIGN   ([-+]{FLOATNUMBER})
FLOAT_ERR_LETTER {FLOATNUMBER}[A-Za-z]+

IMAGINARYNUMBER  ({FLOATNUMBER}|{INTPART})[jJ]

%%

{DELIMITER}     { }
{KEYWORD}       { return KEYWORD; }
{OPERATOR}      { }
{COMMENT}       { printf("Line %d: Found COMMENT\n", line); }   
{IDENTIFIER}        { printf("Line %d: Found IDENTIFIER %s\n", line, yytext);                    return IDENTIFIER; }
{ID_ERR}        { printf("Line %d: !!ERROR!!\tWrong IDENTIFIER statement %s\n", line, yytext);           return ID_ERR;}  
{STRING}        { printf("Line %d: Found STRING %s\n", line, yytext);                        return STRING; }
{STRING_ERR}        { printf("Line %d: !!ERROR!!\tWrong STRING statement %s\n", line, yytext);           return STRING_ERR;}
{BININTEGER}        { printf("Line %d: Found BINARY INTEGER NUMBER %s\n", line, yytext);                 return BININTEGER; }
{BIN_ERR1}      { printf("Line %d: !!ERROR!!\tWrong BINARY NUMBER statement, too many 'Bb's%s\n", line, yytext); return BIN_ERR1;}
{INTEGER}       { printf("Line %d: Found INTEGER NUMBER %s\n", line, yytext);                    return INTEGER; }
{INT_ERR1}      { printf("Line %d: !!ERROR!!\tWrong INT statement %s\n", line, yytext);              return INT_ERR1;}
{INT_ERR2}      { printf("Line %d: !!ERROR!!\tWrong INT statement, '+/-' found %s\n", line, yytext);         return INT_ERR2;}
{INT_ERR3}      { printf("Line %d: !!ERROR!!\tWrong INT statement, first digit(s) zeros %s\n", line, yytext);    return INT_ERR3;}
{FLOATNUMBER}       { printf("Line %d: Found FLOAT NUMBER %s\n", line, yytext);                  return FLOATNUMBER; }
{FLOAT_ERR_POINT}   { printf("Line %d: !!ERROR!!\tWrong FLOAT statement, too many '.' %s\n", line, yytext);      return FLOAT_ERR_POINT;}
{FLOAT_ERR_POINT}   { printf("Line %d: !!ERROR!!\tWrong FLOAT statement, '+/-' FOUND %s\n", line, yytext);       return FLOAT_ERR_SIGN;}
{FLOAT_ERR_LETTER   { printf("Line %d: !!ERROR!!\tWrong FLOAT statement, letter FOUND %s\n", line, yytext);      return FLOAT_ERR_LETTER;}
{IMAGINARYNUMBER}   { printf("Line %d: Found IMAGINARY NUMBER %s\n", line, yytext);                  return IMAGINARYNUMBER; }
.           { printf("Line %d: UNKNOWN TOKEN:%s", line, yytext);    BEGIN(error);}
\n                  { line++; }
<<EOF>>         { printf("#END OF FILE\n"); exit(0); }

完整的错误输出:

 flex scanner.l
 scanner.l:79: unrecognized rule
 scanner.l:79: fatal parse error

【问题讨论】:

    标签: python parsing bison flex-lexer


    【解决方案1】:

    第 74 行末尾缺少一个大括号:

    {FLOAT_ERR_LETTER   { printf("Line %d: !!ERROR!!\tWrong FLOAT statement, letter FOUND %s\n", line, yytext);      return FLOAT_ERR_LETTER;}
                     ^  <--- here
    

    为了让这个答案对未来的读者有用,因为这个问题是一个简单的错字,所以我是这样发现问题的:

    for n in {57..79}; do head -n$n g.l | flex -o /dev/null -w || { echo $n; break; } done
    

    大多数情况下,flex 输入结束后的行中的致命错误是由于缺少大括号或其他类似问题造成的,但是校对整个文件是一件痛苦的事情,而且令人惊讶的是,很少有 IDE 能正确地为 flex 文件设置语法颜色.所以像上面这样的技巧可以节省大量时间。 (它并不总是那么简单;在这种情况下,没有任何动作超过一行。)


    修复该错误后,您会发现有多个模式无法匹配。无法匹配第 73 行,因为该模式与第 72 行 ({FLOAT_ERR_POINT}) 相同。第 65 行和第 66 行(BININTEGERBIN_ERR1)无法匹配,因为有问题的模式以0B 开头,后跟一个数字,也匹配IDERR,这是(奇怪的是)一个数字后跟一个标识符. (你的意思可能是[[:digit:]]+{IDENTIFIER}。)总的来说,你应该把错误模式放在最后,这样它们就不会优先于正确标记的模式。这也使得编写错误标记变得更加简单。 (另外,您需要将特定的错误模式放在更一般的错误模式之前,以便BIN_ERR1 应该在IDERR 之前。)

    其他一些cmets:

    如果您想查看弹性匹配模式,请将--debug(或-d)添加到命令行,而不是在整个代码中添加printf 命令。它可以更好地向您显示正在发生的事情,并且无需编辑整个文件即可打开和关闭。

    总的来说,在输入文件中过度使用 flex 宏并不是很有用。它实际上使规范更难阅读,因为您必须查找宏的每次使用。就个人而言,我只在需要多次使用宏时才使用宏,即使它们只是隐藏内置字符类(如[[:digit:]])的一种方式,我也不会使用它们。 意见>

    【讨论】:

      猜你喜欢
      • 2016-05-14
      • 1970-01-01
      • 1970-01-01
      • 2014-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多