Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.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
Java 我可以确定由正则表达式模式匹配的第一个字符集吗?_Java_Regex_Scala_Automata_Dfa - Fatal编程技术网

Java 我可以确定由正则表达式模式匹配的第一个字符集吗?

Java 我可以确定由正则表达式模式匹配的第一个字符集吗?,java,regex,scala,automata,dfa,Java,Regex,Scala,Automata,Dfa,我希望能够计算所有字符的集合,这些字符可以通过给定的java.util.regex.Pattern实例作为字符串中的第一个字符进行匹配。更正式地说,给定DFA等价于某个正则表达式,我需要从开始状态开始的所有传出转换的集合 例如: Pattern p = Pattern.compile("[abc]def|daniel|chris|\\s+"); Set<Character> first = getFirstSet(p); 有什么想法吗?我很清楚,我可以自己构造DFA并以这种方式确定

我希望能够计算所有字符的集合,这些字符可以通过给定的
java.util.regex.Pattern
实例作为字符串中的第一个字符进行匹配。更正式地说,给定DFA等价于某个正则表达式,我需要从开始状态开始的所有传出转换的集合

例如:

Pattern p = Pattern.compile("[abc]def|daniel|chris|\\s+");
Set<Character> first = getFirstSet(p);

有什么想法吗?我很清楚,我可以自己构造DFA并以这种方式确定相关状态,但我希望避免这种麻烦(请阅读:它对我来说不值得这么多)。请注意,我的宿主语言实际上是Scala,因此我可以访问所有的核心Scala库(不管它值多少)。

我认为您可以解析正则表达式,并定义一些递归函数,以从左到右的方式对解析的正则表达式进行操作,从而建立这样一组第一

有些事情很简单:

  • 顺序:first(r1r2)=first(r1)+(如果第一(r1)中的“”第一(r2)否则为空)
  • 交替:第一(r1 | r2)=第一(r1)+第一(r2)
  • 迭代:第一(r*)=第一(r)+”
  • 字符:第一(c)=c
  • CharacterClass:第一([c1 cn])=集合(c1,c2,…,cn)

将其扩展到正则表达式方言所知道的所有原语和特殊标志,这样就可以了

你可以递归地解决它

  • 去掉括号并递归调用
  • 在顶层拆分备选方案,并为每个部分递归调用
  • 如果没有其他选择,
    • 输出所有符号,从左起到第一个无可选符号
    • 如果有字符组,则输出所有符号
这个想法可能有很多错误,但这就是我要尝试的。你必须去掉断言、组名和其他成千上万的东西。如果你发现像[^0-9]这样的倒排字符类,你必须输出大量字符


所以我认为这确实是一个复杂的问题。

是的,我考虑过了。这实际上与我自己构建DFA的前端是一样的。如果归结起来,也许我会这么做,但我更愿意找到一个更简单的解决方案。我不确定它比解析它(根据语言标准中的固定语法)和一些非常明显的递归要简单多少,但也许这只是我的编译结构注入了脑力,解析和递归遍历并不是很糟糕,我只是不喜欢为了得到第一个集合而不得不复制Java的正则表达式语义,我没有考虑否定类。考虑到Java使用UTF-8,第一组可能有几十万个大小。哎哟也许我会假设正则表达式可以匹配任何东西,并保持未优化状态……我只是想重写表达式-如果您可以构建一个只匹配输入表达式的第一个符号的表达式,那么您可以循环一些单个符号字符串,并测试派生表达式是否匹配。但是要获得所有字符,您必须在整个字符集上循环-Unicode需要大量的工作。我想不出一个方法来得到这样一个派生表达式。也许入侵regex实现并通过反射检查内部状态。但所有这些可能都会影响到自己编写regex实现。所以我没有(好的)想法。
{ 'a', 'b', 'c', 'd', ' ', '\n', '\r', '\t' }