Как я могу найти индекс первого «элемента» в моей строке, используя Java? - PullRequest
2 голосов
/ 17 сентября 2009

Я работаю над написанием простого интерпретатора Пролога на Java.

Как мне найти последний символьный индекс первого элемента, либо элемент head, либо tail-элемент строки в «Синтаксисе списка»?

Синтаксис списка выглядит так:

(X)
(p a b)
(func (func2 a) (func3 X Y))
(равная ночь (мать Каин))

Заголовок для каждой из этих строк в следующем порядке:
Голова: «Х», индекс: 1
Руководитель: "p", индекс: 1
Руководитель: "func", индекс: 4
Голова: «равная», индекс: 5

По сути, мне нужно сопоставить строку, которая следует сразу за первым "(" и заканчивается либо пробелом, либо закрывающим ")", в зависимости от того, что произойдет раньше. Мне нужен индекс символа последнего символа элемента head.

Как я могу сопоставить и получить этот индекс в Java?


Решение Брабстера действительно близко. Однако рассмотрим случай:
((b X) Y)

Где элемент head (b x). Я попытался исправить это, удалив "(" из разделителей сканера, но он все еще работает из-за пробела между "b" и "x".

Аналогично: ((((б Ш) Х) Y) Z) * ​​1030 *

Где голова (((б ш) х) Y).

Ответы [ 3 ]

4 голосов
/ 17 сентября 2009

Java Сканер класс (представлен в 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 голос
/ 18 сентября 2009

Есть ли причина, по которой вы не можете просто перебор? Как то так?

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;
        }
    }
}

Возможно, я что-то здесь упускаю, но я думаю , что будет работать.

0 голосов
/ 17 сентября 2009

Я предлагаю вам написать правильный синтаксический анализатор ( приоритет оператора в случае Prolog) и представить термины в виде деревьев объектов Java для дальнейшей обработки.

...