我正试图用java从LaTeX源代码中提取定理。我的代码几乎可以工作,但有一个测试用例失败了——嵌套定理。
@Test
public void testNestedTheorems() {
String source = "\begin{theorem}" +
"this is the outer theorem" +
"\begin{theorem}" +
"this is the inner theorem" +
"\end{theorem}" +
"\end{theorem}";
LatexTheoremProofExtractor extractor = new LatexTheoremProofExtractor(source);
extractor.parse();
ArrayList<String> theorems = extractor.getTheorems();
assertNotNull(theorems);
assertEquals(2, theorems.size()); // theorems.size() is 1
assertEquals("this is the outer theorem", theorems.get(0));
assertEquals("this is the inner theorem", theorems.get(1));
}
这是我的定理提取器,它被LatexTheoremProofExtractor#parse
:调用
private void extractTheorems() {
// If this has been called before, return
if(theorems != null) {
return;
}
theorems = new ArrayList<String>();
final Matcher matcher = THEOREM_REGEX.matcher(source);
// Add trimmed matches while you can find them
while (matcher.find()) {
theorems.add(matcher.group(1).trim());
}
}
CCD_ 2定义如下:
private static final Pattern THEOREM_REGEX = Pattern.compile(Pattern.quote("\begin{theorem}")
+ "(.+?)" + Pattern.quote("\end{theorem}"));
有人对处理嵌套标签有什么建议吗?
如果你只想匹配双嵌套的theorem
s,你可以为它写一个显式正则表达式。我想它会是这样的。
Pattern.compile(
Pattern.quote("\begin{theorem}")
+ "("
+ "(.+?)"
+ Pattern.quote("\begin{theorem}")
+ "(.+?)"
+ Pattern.quote("\end{theorem}")
+ ")*"
+ Pattern.quote("\end{theorem}"));
(这段代码应该会给你这个想法,但它还没有经过测试,可能不像写的那样工作。这不是我想说的。)
对于三重嵌套,您可以继续执行此操作,对于所需的任何固定数量的嵌套,依此类推。不用说,它很快就会变得相当尴尬。
然而,如果您的目标是匹配任意深度嵌套,那么根本不可能使用正则表达式。问题是,您想要匹配的语言不是正则的(但与上下文无关)。上下文无关语言严格来说比正则语言更强大,正则表达式只能精确匹配正则语言。一般来说,如果你想匹配一种上下文无关的语言,你需要构造一个下推自动机。
进一步阅读:
- 乔姆斯基层次
- "现在你有两个问题"是什么意思