【问题标题】:Regular expression error in FlexFlex 中的正则表达式错误
【发布时间】:2018-07-16 08:06:11
【问题描述】:

我正在学习使用 Flex 编写词法分析器,但发现了一个奇怪的问题。 我尝试定义关键字class的正则​​表达式。

对于我的测试用例:

class T{
}

表达式1:

ws [\t\r\f\v ]
CLASS (^class$)|(^class{ws})|({ws}class{ws})|({ws}class$)

没用。

表达式2:

ws [\t\r\f\v ]
CLASS ^class{ws}

有效。

表达式 3:

ws [\t\r\f\v ]
CLASS1 ^class{ws}
CLASS {CLASS1}

报告错误说无法识别的规则

我感到很困惑,2和3之间有什么区别吗? 我参考Flex github 上的示例。它只是使用类似的表达式来定义数字。

任何帮助将不胜感激!

更新:

我的脚本:

%{

/* Some include headers here */

/* The compiler assumes these identifiers. */
#define yylval cool_yylval
#define yylex  cool_yylex

/* Max size of string constants */
#define MAX_STR_CONST 1025
#define YY_NO_UNPUT   /* keep g++ happy */

extern FILE *fin; /* we read from this file */

/* define YY_INPUT so we read from the FILE fin:
 * This change makes it possible to use this scanner in
 * the Cool compiler.
 */
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
        if ( (result = fread( (char*)buf, sizeof(char), max_size, fin)) < 0) \
                YY_FATAL_ERROR( "read() in flex scanner failed");

char string_buf[MAX_STR_CONST]; /* to assemble string constants */
char *string_buf_ptr;
extern int curr_lineno;
extern int verbose_flag;
extern YYSTYPE cool_yylval;

%}

/*
 * Define names for regular expressions here.
 */
ws              [\t\r\f\v ]
CLASS1          {ws}class$
CLASS2          ^class$
CLASS3          ^class{ws}
CLASS4          {ws}class{ws}
CLASS           {CLASS2}
DARROW          =>
STRING          \"[^\n"]+\"

%%
{CLASS} {return (CLASS);}  /*returned CLASS is defined in other header files*/
%%

【问题讨论】:

  • 我无法重现您的问题。你能发布一个产生“无法识别的规则”错误的最小但完整的 flex 文件吗?
  • @sepp2k 我更新了 flex 文件。 CLASS {CLASS2} 导致错误,但 CLASS {CLASS1} 没问题。

标签: regex flex-lexer


【解决方案1】:

您正在做的事情是不必要的:您可以使用 class 作为您的正则表达式,而无需任何锚点或提及空白。您可能会这样定义它,因为您想避免正则表达式匹配较大标识符的部分(例如,您不希望将classOf99 解释为关键字class,后跟标识符Of99),但这不会发生:当有多个正则表达式可以匹配当前输入时,Flex 将始终采用导致最长匹配的那个(并且在平局的情况下,它将选择在 flex 中首先出现的那个文件)。这就是所谓的最大咀嚼规则,正好避免了这个问题。

所以你的代码应该只是class { return CLASS; } 并且不需要任何定义。


也就是说,这就是您的尝试失败的原因:

您不能使用^$。有时这会导致“无法识别的规则”,有时会导致匹配失败。

这就解释了为什么您的第一个定义不起作用。但是为什么第二个不起作用?如果您在其他定义中使用定义,它们会被隐式包裹在括号中以避免优先级问题。因此,您也不能在其他定义中使用使用 ^$ 的定义。

因此,拥有涉及^$ 的多个替代方案的唯一方法是制定单独的规则,如下所示:

^re  { return X; }
re$  { return X; }

但是,在您的情况下(或曾经),这确实不是必需的。

【讨论】:

  • 我明白你的意思。你是对的。但我想知道是否存在需要在括号内使用 ^ 的情况以及 flex 如何处理这种事情?
  • @lionel 有些事情变得难以表达,但您应该始终能够重写规则以使其发挥作用。也就是说,你可以只写^foo {...},然后写foo$ {...},而不是(^foo)|(foo$) {...}(也许将...代码放入它自己的函数中以避免代码重复)。请注意,如果您只想在行首识别某些关键字,则只需要^,这在开始时并不常见。当该用例出现时,您通常不需要使用|。因此,它在实践中应该很少(如果有的话)成为问题。
  • 清除!非常感谢~
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-19
  • 1970-01-01
  • 2013-11-26
相关资源
最近更新 更多