2

我正在用 Java 编写一个简单的 Prolog 解释器。

如何在“列表语法”中找到字符串的头元素或尾元素的第一个元素的最后一个字符索引?

列表语法如下所示:

(X)
(pab)
(func (func2 a) (func3 XY)
)

每个字符串的头部依次为:
头部:“X”,索引:1
头部:“p”,索引:1
头部:“func”,索引:4
头部:“equal”,索引:5

基本上,我需要匹配紧跟第一个“(”并以空格或结束“)”结尾的字符串,以先到者为准。我需要 head 元素的最后一个字符的字符索引。

如何在 Java 中匹配并获取此索引?


Brabster 的解决方案非常接近。但是,考虑以下情况:
((b X) Y)

头元素是(bx)。我试图通过从扫描仪分隔符中删除“(”来修复它,但由于“b”和“x”之间的空格,它仍然会打嗝。

类似地:((((b W)X)Y)Z)

头部是(((bw)x)Y)。

4

3 回答 3

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

这不是一个非常优雅的解决方案,但正则表达式不能计数(即括号)。如果那里有更多复杂性,我会考虑使用解析器生成器:)

于 2009-09-17T19:15:26.510 回答
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;
        }
    }
}

我可能在这里遗漏了一些东西,但我认为这会奏效。

于 2009-09-17T22:07:06.420 回答
0

我建议您编写一个适当的解析器(在 Prolog 的情况下为运算符优先级)并将术语表示为 Java 对象的树以供进一步处理。

于 2009-09-17T19:25:21.410 回答