如何在flex lex中实现捕获组? 注意事项:

如何解决如何在flex lex中实现捕获组? 注意事项:

我想匹配以“#”开头的字符串,然后匹配所有内容,直到匹配“#”后面的字符。这可以使用这样的捕获组来实现:#(.)[^(?1)]*(?1)EDIT 这个正则表达式也是错误的)。这匹配 #$foo$,不匹配 #%bar&,匹配 #"foo"bar 的前 6 个字符。

但是由于 flex lex 不支持捕获组,这里的解决方法是什么?

解决方法

如您所说,(f)lex 不支持捕获组,当然也不支持反向引用。

所以没有简单的解决方法,但有解决方法。以下是几种可能性:

  1. 您可以使用 input() 函数一次读取一个字符,直到找到匹配的字符(但您必须创建自己的缓冲区来存储字符,因为 input() 读取的字符{1}} 不会添加到当前令牌中)。这不是最有效的,因为一次读取一个字符有点笨重,但它是 (f)lex 提供的唯一界面。 (以下代码段假设您有某种可扩展的 stringBuilder;如果您使用的是 C++,则只需将其替换为 std::string。)

    #.   { StringBuilder sb = string_builder_new();
           int delim = yytext[1];
           for (;;) {
             int next = input();
             if (next == delim) break;
             if (next == EOF ) { /* Signal error */; break; }
             string_builder_addchar(next);
           }
           yylval = string_builder_release();
           return DELIMITED_STRING;
         }
    
  2. 效率更低,但也许更方便,您可以使用 yytext 获得 (f)lex 累积 yymore() 中的字符,在开始条件下一次匹配一个字符:

    %x DELIMITED
    %%
      int delim;
    
    #.              { delim = yytext[1]; BEGIN(DELIMITED); }
    <DELIMITED>.|\n { if (yytext[0] == delim) { 
                        yylval = strdup(yytext);
                        BEGIN(INITIAL);   
                        return DELIMITED_STRING;
                      }
                      yymore();
                    }
    <DELIMITED><<EOF>> { /* Signal unterminated string error */ }
    
  3. 最有效的解决方案(在 (f)lex 中)是只为每个可能的分隔符编写一个规则。虽然这是很多规则,但可以使用您喜欢的任何脚本语言的小脚本轻松生成它们。而且,实际上,没有那么多规则,特别是如果您不允许字母和非打印字符作为分隔符。这有一个额外的好处,如果你想要类似 Perl 的括号分隔符(#(Hello) 而不是 #(Hello(),你可以修改单个模式以适应(就像我在下面所做的那样)。 【注1】由于所有的动作都是一样的;为操作使用宏可能更容易,从而更容易修改。

      /* Ordinary punctuation */
    #:[^:]*:     { yylval = strndup(yytext + 2,yyleng - 3); return DELIMITED_STRING; }
    #:[^:]*:     { yylval = strndup(yytext + 2,yyleng - 3); return DELIMITED_STRING; }
    #![^!]*!     { yylval = strndup(yytext + 2,yyleng - 3); return DELIMITED_STRING; }
    #\.[^.]*\.   { yylval = strndup(yytext + 2,yyleng - 3); return DELIMITED_STRING; }
      /* Matched pairs */
    #<[^>]*>     { yylval = strndup(yytext + 2,yyleng - 3); return DELIMITED_STRING; }
    #\[[^]]*]    { yylval = strndup(yytext + 2,yyleng - 3); return DELIMITED_STRING; }
      /* Trap errors */
    #            { /* Report unmatched or invalid delimiter error */ }
    

    如果我要编写一个脚本来生成这些规则,我会对所有分隔符使用十六进制转义,而不是试图找出哪些需要转义。


注意事项:

  1. Perl 要求在这样的结构中嵌套平衡括号。但是你不能用正则表达式做到这一点;如果您想重现 Perl 行为,您需要对其他建议之一使用一些变体。我稍后会尝试重新访问此答案以解决该功能。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?