Flex 匹配字符串文字,转义换行符
Flex match string literal, escaping line feed
我正在使用 flex 来尝试匹配类似 C 的简化字符串文字。
这样的正则表达式:
\"([^"\]|\["?\btnr]|\x{HEXDIG}{HEXDIG})*\"
将匹配我感兴趣的所有单行字符串文字。
字符串文字不能包含非转义的反斜杠。字符串文字也不能包含文字换行符 (0x0a
),除非它被反斜杠转义,在这种情况下,换行符和任何后续空格和制表将被忽略。.
例如,假设 {LF} 是一个实际的换行符,而 {TAB} 是一个实际的表格(我没有比这更好的格式了)。
在中:"This is an example \{LF}{TAB}{TAB}{TAB}of a confusing valid string"
令牌:"This is an example of a confusing valid string"
我的第一个想法是使用起始状态、尾随上下文和 yymore()
来匹配我想要的内容并检查错误,给出如下内容:
...
%%
\" { BEGIN STRING; yymore(); }
<STRING>{
\n { /* ERROR HERE! */ }
<<EOF>> { /* ERROR HERE AS WELL */ }
([^"\]|\["?\btnr]|\x{HEXDIG}{HEXDIG})* {
/* String ok up to here*/
yymore();
}
\\n[ \t]* {
/*Vadid inside a tring but needs to be ignored! */
yymore();
}
\" { /* Full string matched */ BEGIN INITIAL;}
.|\n { \* Anything else is considered an error *\ }
}
%%
...
有没有办法按照我想做的方式做我想做的事?是否有其他 'standard' 可能由 flex 提供的方法,我只是愚蠢地没有想到?在我看来,这并不像一个不常见的用例。我是否应该单独匹配字符串(从 before 开始,到 whitespace 之后结束)并连接它们。这有点复杂,因为可以使用反斜杠将字符串分解为任意数量的行。
如果您只想识别字符串文字,则不需要启动条件。您可以使用简单模式的一些变体,您会在许多答案中找到这些变体:
["]({normal}|{escape})*["]
(我使用宏来使结构清晰,尽管在实践中我几乎不会使用它们。)
这里的“普通”是指字符串中没有特殊意义的任意字符。换句话说,除 "
(结束文字)、\
(开始转义序列)或换行符(尽管某些语言允许在字符串中使用换行符,这通常是错误)以外的任何字符。在换句话说,[^"\n\]
(或类似的东西)。
"escape" 可以是任何有效的转义序列。如果您不想验证转义序列,您可以只匹配一个反斜杠后跟任何单个字符(包括换行符):\(.|\n)
。但是由于您似乎确实想要验证,因此您需要明确说明您准备的转义序列:
\([\n\btnr"]|x[[:xdigit:]]{2})
但是所有这些都只能识别有效的字符串文字。无效的字符串文字将不匹配该模式,因此将回退到您用作回退规则的任何内容(仅匹配初始 "
)。由于这实际上不是您想要的,因此您需要添加第二条检测错误的规则。编写第二条规则的最简单方法是 ["]({normal}|{escape})*
,即没有最后双引号的有效规则。由于 (f)lex 的最大咀嚼规则,这只会匹配错误的字符串文字:有效的字符串文字与有效规则的匹配比与错误规则的匹配更长(因为有效规则的匹配包括最后的双引号)。
在现实生活中的词法扫描器(与学校练习相反)中,更常见的是期望词法扫描器通过用相应的字符替换转义序列,将字符串文字实际解析为它所代表的实际字节。这通常是在开始条件下完成的,但个别模式更加集中(并且有更多)。对于此类解析器的示例,您可以查看这两个答案(以及许多其他答案):
- Flex / Lex Encoding Strings with Escaped Characters
我正在使用 flex 来尝试匹配类似 C 的简化字符串文字。 这样的正则表达式:
\"([^"\]|\["?\btnr]|\x{HEXDIG}{HEXDIG})*\"
将匹配我感兴趣的所有单行字符串文字。
字符串文字不能包含非转义的反斜杠。字符串文字也不能包含文字换行符 (0x0a
),除非它被反斜杠转义,在这种情况下,换行符和任何后续空格和制表将被忽略。.
例如,假设 {LF} 是一个实际的换行符,而 {TAB} 是一个实际的表格(我没有比这更好的格式了)。
在中:"This is an example \{LF}{TAB}{TAB}{TAB}of a confusing valid string"
令牌:"This is an example of a confusing valid string"
我的第一个想法是使用起始状态、尾随上下文和 yymore()
来匹配我想要的内容并检查错误,给出如下内容:
...
%%
\" { BEGIN STRING; yymore(); }
<STRING>{
\n { /* ERROR HERE! */ }
<<EOF>> { /* ERROR HERE AS WELL */ }
([^"\]|\["?\btnr]|\x{HEXDIG}{HEXDIG})* {
/* String ok up to here*/
yymore();
}
\\n[ \t]* {
/*Vadid inside a tring but needs to be ignored! */
yymore();
}
\" { /* Full string matched */ BEGIN INITIAL;}
.|\n { \* Anything else is considered an error *\ }
}
%%
...
有没有办法按照我想做的方式做我想做的事?是否有其他 'standard' 可能由 flex 提供的方法,我只是愚蠢地没有想到?在我看来,这并不像一个不常见的用例。我是否应该单独匹配字符串(从 before 开始,到 whitespace 之后结束)并连接它们。这有点复杂,因为可以使用反斜杠将字符串分解为任意数量的行。
如果您只想识别字符串文字,则不需要启动条件。您可以使用简单模式的一些变体,您会在许多答案中找到这些变体:
["]({normal}|{escape})*["]
(我使用宏来使结构清晰,尽管在实践中我几乎不会使用它们。)
这里的“普通”是指字符串中没有特殊意义的任意字符。换句话说,除 "
(结束文字)、\
(开始转义序列)或换行符(尽管某些语言允许在字符串中使用换行符,这通常是错误)以外的任何字符。在换句话说,[^"\n\]
(或类似的东西)。
"escape" 可以是任何有效的转义序列。如果您不想验证转义序列,您可以只匹配一个反斜杠后跟任何单个字符(包括换行符):\(.|\n)
。但是由于您似乎确实想要验证,因此您需要明确说明您准备的转义序列:
\([\n\btnr"]|x[[:xdigit:]]{2})
但是所有这些都只能识别有效的字符串文字。无效的字符串文字将不匹配该模式,因此将回退到您用作回退规则的任何内容(仅匹配初始 "
)。由于这实际上不是您想要的,因此您需要添加第二条检测错误的规则。编写第二条规则的最简单方法是 ["]({normal}|{escape})*
,即没有最后双引号的有效规则。由于 (f)lex 的最大咀嚼规则,这只会匹配错误的字符串文字:有效的字符串文字与有效规则的匹配比与错误规则的匹配更长(因为有效规则的匹配包括最后的双引号)。
在现实生活中的词法扫描器(与学校练习相反)中,更常见的是期望词法扫描器通过用相应的字符替换转义序列,将字符串文字实际解析为它所代表的实际字节。这通常是在开始条件下完成的,但个别模式更加集中(并且有更多)。对于此类解析器的示例,您可以查看这两个答案(以及许多其他答案):
- Flex / Lex Encoding Strings with Escaped Characters