Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex flex中无法识别的规则-负前瞻_Regex_Flex Lexer_Lex - Fatal编程技术网

Regex flex中无法识别的规则-负前瞻

Regex flex中无法识别的规则-负前瞻,regex,flex-lexer,lex,Regex,Flex Lexer,Lex,当我在这段代码上运行flex时,它会抱怨无法识别的规则。我想匹配字符串,比如(b | b)^n(a | a)^m,这样n>=4和m(F)lex就不会实现。(注意:前面的链接不是背书。) 您可以在中找到flex接受的正则表达式运算符的完整列表;如果某个语法不在该列表中,则无论在线正则表达式服务告诉您什么,它都不会被识别。(注意:前面的链接是背书。) (F) lex确实实现了一个积极的前瞻断言,但只在模式的最后实现。这是用符号表示的。您可以使用该运算符来识别您的令牌,方法是要求它后面跟一个A以外的字

当我在这段代码上运行flex时,它会抱怨
无法识别的规则
。我想匹配字符串,比如
(b | b)^n(a | a)^m
,这样
n>=4和m(F)lex就不会实现。(注意:前面的链接不是背书。)

您可以在中找到flex接受的正则表达式运算符的完整列表;如果某个语法不在该列表中,则无论在线正则表达式服务告诉您什么,它都不会被识别。(注意:前面的链接是背书。)

(F) lex确实实现了一个积极的前瞻断言,但只在模式的最后实现。这是用符号表示的。您可以使用该运算符来识别您的令牌,方法是要求它后面跟一个A以外的字符:

但这与语义并不完全相同,因为它无法识别输入端的标记。它要求令牌后面跟有非A的东西;先开始,然后什么都不算。(实际上,这可能没有多大区别。如果您正在扫描文本流中的输入,您可以合理地预期该流的最后一个字符是换行符,并且换行符将匹配
[^Aa]
。但是,如果要扫描可能根本没有换行符的文本字符串,则需要注意此问题。)

大多数时候,这并不是你真正想要的。或者,如果它确实是您想要的,那么(f)lex可能不适合您的用例

(F) lex设计用于将输入划分为连续的令牌。它不搜索代币;它标识当前输入点的令牌。它期望整个输入将由令牌组成,因此某些模式需要在每个点匹配

在此基础上,您需要考虑非匹配序列是什么类型的令牌。例如:

bbbbbbbaaaa
这太多了,以至于不能成为您规则的“字符串”。那是什么呢

  • 有效令牌
    bbb AAA
    后跟另一个以a开头的令牌

  • 匹配其他模式的有效令牌?(例如,
    长字符串

  • 应忽略的无效令牌,是否允许继续扫描

  • 无法恢复的错误

  • 所有这些情况都可以在不使用任何lookaround操作符的情况下处理

    在第一种情况下,使用与有效令牌匹配的正则表达式即可:

    [bB]{4,}[aA]{1,3}     { printf("Valid STRING: %s ", yytext); }
    
    在第二种情况下,您可以依赖(f)lex maximum munch匹配规则,该规则规定将使用与最长匹配对应的模式:

    [bB]{4,}[aA]{1,3}     { printf("Valid STRING: %s ", yytext); }
    [bB]{4,}[aA]{4,}      { printf("Valid LONG STRING: %s ", yytext); }
    
    这可以简化:

    [bB]{4,}[aA]{1,3}     { printf("Valid STRING: %s ", yytext); }
    [bB]{4,}[aA]          { printf("Valid LONG STRING: %s ", yytext); }
    
    这将产生相同的效果,因为(f)lex规则决定两个匹配时间最长的模式是使用输入文件中的第一个模式。因此,
    bbbbaaa---
    的前六个字符与两种模式匹配,因此第一个模式获胜,而
    bbbbbbaaa---
    与第一个模式匹配七个字符,与第二个模式匹配八个字符,因此第二个模式获胜


    对于第三和第四种情况,也可以使用上述一对模式;唯一的区别在于与第二种模式对应的动作。对于案例3:忽略令牌,可能发出警告;对于案例4:生成一条错误消息并终止扫描。

    感谢您的全面回答!其实我还是解决不了我的问题。我发现我原来的模式逻辑并不好,即使它起作用,因为我只需要匹配由空格或逗号分隔的整个单词,而不需要匹配子字符串(编辑问题)。我可以做到这一点,但最后的分隔符成为我比赛的一部分。在这种情况下使用lookahead似乎很自然。@pavlee:你需要(对自己)回答我在回答开头提出的问题:什么样的代币是
    bbbbaaaa
    ?因为如果您要使用令牌服务器,那么一切都是令牌。(即使是空白,它通常是一个被忽略的——因此未报告的——标记。)我建议的两种模式框架几乎肯定是您所需要的。一句话:因为最长的标记是匹配的,所以你不需要明确地考虑下一个标记,因为你已经知道下一个标记不可能是标记的一部分。这为我澄清了问题,现在我完全明白了两种模式的概念:)我还不太了解正则表达式,所以在一开始了解它是非常有用的。我很感激你的回答。
    [bB]{4,}[aA]{1,3}     { printf("Valid STRING: %s ", yytext); }
    [bB]{4,}[aA]{4,}      { printf("Valid LONG STRING: %s ", yytext); }
    
    [bB]{4,}[aA]{1,3}     { printf("Valid STRING: %s ", yytext); }
    [bB]{4,}[aA]          { printf("Valid LONG STRING: %s ", yytext); }