如何使用Java在我的字符串中找到第一个“元素”的索引?

时间:2009-09-17 19:05:03

标签: java parsing string prolog

我正在用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)。

3 个答案:

答案 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对象的树,以便进一步处理。