Flex 中的正则表达式错误
Regular expression error in Flex
我正在学习用 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*/
%%
您所做的是不必要的:您可以只使用 class
作为您的正则表达式,而无需任何锚点或提及白色 space。您可能会这样定义它,因为您希望避免正则表达式匹配较大标识符的部分(例如,您不希望 classOf99
被解释为关键字 class
,后跟标识符 Of99
),但这不会发生:当有多个正则表达式可以匹配当前输入时,Flex 将始终选择导致最长匹配的那个(如果是平局,它将选择一个在 flex 文件中首先出现)。这被称为最大咀嚼规则,正好避免了这个问题。
所以你的代码应该只是 class { return CLASS; }
并且 none 的定义是必要的。
也就是说,这就是您的尝试无效的原因:
您不能使用 ^
和 $
。有时这会导致 "unrecognized rules",有时它会匹配失败。
这就解释了为什么您的第一个定义不起作用。但是为什么第二个不起作用?如果您在其他定义中使用定义,它们会隐式地包含在括号中以避免优先级问题。因此,您也不能在其他定义中使用使用 ^
或 $
的定义。
因此,拥有涉及 ^
和 $
的多个备选方案的唯一方法是采用如下单独的规则:
^re { return X; }
re$ { return X; }
但同样,这对你的情况(或永远)来说真的没有必要。
我正在学习用 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*/
%%
您所做的是不必要的:您可以只使用 class
作为您的正则表达式,而无需任何锚点或提及白色 space。您可能会这样定义它,因为您希望避免正则表达式匹配较大标识符的部分(例如,您不希望 classOf99
被解释为关键字 class
,后跟标识符 Of99
),但这不会发生:当有多个正则表达式可以匹配当前输入时,Flex 将始终选择导致最长匹配的那个(如果是平局,它将选择一个在 flex 文件中首先出现)。这被称为最大咀嚼规则,正好避免了这个问题。
所以你的代码应该只是 class { return CLASS; }
并且 none 的定义是必要的。
也就是说,这就是您的尝试无效的原因:
您不能使用 ^
和 $
。有时这会导致 "unrecognized rules",有时它会匹配失败。
这就解释了为什么您的第一个定义不起作用。但是为什么第二个不起作用?如果您在其他定义中使用定义,它们会隐式地包含在括号中以避免优先级问题。因此,您也不能在其他定义中使用使用 ^
或 $
的定义。
因此,拥有涉及 ^
和 $
的多个备选方案的唯一方法是采用如下单独的规则:
^re { return X; }
re$ { return X; }
但同样,这对你的情况(或永远)来说真的没有必要。