我正在用Java编写一个简单的Prolog解释器。
如何在“列表语法”中找到第一个元素的最后一个字符索引:字符串的head元素或tail元素?
列表语法如下所示:
(X)
(p a b)
(func(func2 a)(func3 X Y))
(平等前夜(母亲))
按顺序排列每个字符串的头部是:
头:“X”,索引:1
负责人:“p”,指数:1
负责人:“func”,指数:4
负责人:“平等”,指数:5
基本上,我需要匹配紧跟在第一个“(”并以空格或结束“)结束的字符串”,以先到者为准。我需要head元素的最后一个字符的字符索引。
如何在Java中匹配并获取此索引?
Brabster的解决方案非常接近。但是,请考虑以下情况:
((b X)Y)
头元素是(b x)。我尝试通过从扫描仪分隔符中删除“(”来修复它,但由于“b”和“x”之间的空间,它仍然会打嗝。
类似地: ((((b W)X)Y)Z)
头部是(((b w)x)Y)。
答案 0 :(得分:4)
Java的Scanner类(在Java 1.5中引入)可能是一个很好的起点。
这是一个我认为可以做你想要的例子(更新为包括字符计数功能)
public class Test {
public static void main(String[] args) {
String[] data = new String[] {
"(X)",
"(p a b)",
"(func (func2 a) (func3 X Y))",
"(equal eve (mother cain))",
"((b X) Y)",
"((((b W) X) Y) Z)"
};
for (String line:data) {
int headIdx = 0;
if (line.charAt(1) == '(') {
headIdx = countBrackets(line);
} else {
String head = "";
Scanner s = new Scanner(line);
s.useDelimiter("[)|(| ]");
head = s.next();
headIdx = line.indexOf(head) + head.length() - 1;
}
System.out.println(headIdx);
}
}
private static int countBrackets(String line) {
int bracketCount = 0;
int charCount = 0;
for (int i = 1; i < line.length(); i++) {
char c = line.charAt(i);
if (c == '(') {
bracketCount++;
} else if (c == ')') {
bracketCount--;
}
if (bracketCount == 0) {
return charCount + 1;
}
charCount++;
}
throw new IllegalStateException("Brackets not nested properly");
}
}
输出:
1
1
4
5
5
13
这不是一个非常优雅的解决方案,但正则表达式无法计算(即括号)。如果那里有更复杂的话,我会考虑使用解析器生成器:)
答案 1 :(得分:1)
有没有理由你不能蛮力呢?像这样的东西?
public int firstIndex( String exp ) {
int parenCount = 0;
for (int i = 1; i < exp.length(); i++) {
if (exp.charAt(i) == '(') {
parenCount++;
}
else if (exp.charAt(i) == ')') {
parenCount--;
}
if (parenCount == 0 && (exp.charAt(i+1) == ' ' || exp.charAt(i) == ')')) {
return i;
}
}
}
我可能在这里遗漏了一些东西,但我认为会起作用。
答案 2 :(得分:0)
我建议您编写一个正确的解析器(在Prolog的情况下为operator precedence),并将这些术语表示为Java对象的树,以便进一步处理。