【问题标题】:Regular expression for a string literal in flex/lexflex/lex 中字符串文字的正则表达式
【发布时间】:2011-01-03 15:09:22
【问题描述】:

我正在尝试学习 flex 并希望匹配字符串文字。我的代码目前看起来像:

"\""([^\n\"\\]*(\\[.\n])*)*"\""        {/*matches string-literal*/;}

我已经在变化中苦苦挣扎了一个小时左右,但无法让它按应有的方式工作。我本质上希望匹配一个不能包含换行符(除非它被转义)并支持转义字符的字符串文字。

我可能只是写了一个糟糕的正则表达式或者一个与 flex 不兼容的表达式。请指教!

【问题讨论】:

  • 非常感谢大家!您所有的 cmets 都非常有帮助。最终对我有用的正则表达式是 codadict 链接的 C 规范中使用的正则表达式的变体(由 Jonathan 解释): \"(\(.|\n)|[^\\"\n])* \"
  • 既然您发现乔纳森的回答很有帮助,请考虑为他的回答添加一个赞成票。
  • 顺便说一句:在您的问题中,您没有指定您感兴趣的语言的字符串文字。将您要询问的语言放在问题的标签中是一个非常好的主意。

标签: c regex lex string-literals flex-lexer


【解决方案1】:

字符串由引号组成

"

后跟零个或多个转义的任何东西

\\.

或非引号字符、非反斜杠字符

[^"\\]

最后是结束语

"

把它们放在一起,你就有了

\"(\\.|[^"\\])*\"

分隔引号被转义,因为它们是 Flex 元字符。

【讨论】:

  • 不幸的是,这不能处理转义。所以这会错误地 lex "\""
  • 你一定错过了“零个或多个逃逸的东西”?
  • 这个答案有几个问题。首先,它不是一个有效的弹性模式。前导和尾随双引号需要转义,否则 flex 会将它们视为元字符。所以模式应该是(也许) \"(\\.|[^"])*\" 。其次,该模式仍然不起作用。例如,它输入错误: "\\\\" 。第三,不符合原题禁止换行的要求。
  • 作为一个正则表达式,这是完全正确的。除了换行符,可以通过将. 替换为[^\n][^"] 替换为[^"\n] 来轻松修复。它当然也应该匹配"\\\\",因为重复将匹配引用",然后是转义斜杠\\ ,然后是下一个转义斜杠\\ ,然后是终止引号"。该模式当然适用于 flex 范围之外的我。
  • 在 flex 的范围之外是否可以工作并不重要。问题是关于弹性的。如果 flex 生成的词法分析器看到 "\\\\"foo",它将匹配整个输入,而不是仅匹配 "\\\\" 部分,因为字符类不排除反斜杠。
【解决方案2】:

对于单行...你可以使用这个:

\"([^\\\"]|\\.)*\"  {/*matches string-literal on a single line*/;}

【讨论】:

  • 这是最好的答案。
  • 我们不应该确保起始引号前面没有反斜杠(被转义)吗?
  • 如果前面有一个反斜杠,它应该不匹配其他规则,从而表示错误。
【解决方案3】:

如何使用开始状态...

int enter_dblquotes = 0; %x DBLQUOTES %% \" { 开始(DBLQUOTES); enter_dblquotes++; } *\" { 如果(输入_dblquotes){ handle_this_dblquotes(yytext); 开始(初始); /* 恢复正常 */ enter_dblquotes--; } } ...更多规则如下...

它类似于那个效果(flex 使用%s%x 来指示预期的状态。当 flex 输入检测到一个引号时,它会切换到另一个状态,然后继续词法分析,直到它到达另一个引号,恢复到正常状态。

【讨论】:

  • @Samoz:不是真的,它实际上用在使用字符串文字的语言中,它吃掉了开始引号和结束引号之间的内容,即使里面有额外的引号,因此使用切换状态以咀嚼引号......
  • flex 手册包含解析 C 样式字符串的完整示例(在 flex 使用方面):flex.sourceforge.net/manual/Start-Conditions.html。在该页面上搜索“引用的字符串”。
【解决方案4】:

粘贴我关于在flex中处理字符串的代码sn-p,希望能激发你的思考。

使用Start Condition 处理字符串字面量将更具可扩展性和清晰性。

%x SINGLE_STRING

%%

\"                          BEGIN(SINGLE_STRING);
<SINGLE_STRING>{
  \n                        yyerror("the string misses \" to termiate before newline");
  <<EOF>>                   yyerror("the string misses \" to terminate before EOF");
  ([^\\\"]|\\.)*            {/* do your work like save in here */}
  \"                        BEGIN(INITIAL);
  .                         ;
}

【讨论】:

  • 如何使用此方法将字符串保存到 yytext ?
【解决方案5】:

这是我们在 Zolang 中使用的带有嵌入式模板的单行字符串文字 ${...}

\"(\$\{.*\}|\\.|[^\"\\])*\"

【讨论】:

  • 它可以正确匹配这个:"Hello ${some + "world"}"
【解决方案6】:

一个迟到但对下一个需要它的人有用的答案:

\"(([^\"]|\\\")*[^\\])?\"

【讨论】:

  • 欢迎来到 SO。这个答案将通过解释如何它的工作原理和如何它是不同的文本来改进。
猜你喜欢
  • 1970-01-01
  • 2015-03-30
  • 2013-03-11
  • 1970-01-01
  • 1970-01-01
  • 2018-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多