Как мне найти индекс первого «элемента» в моей строке с помощью Java?

StackOverflow https://stackoverflow.com/questions/1440748

  •  10-07-2019
  •  | 
  •  

Вопрос

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

Как я могу найти индекс последнего символа первого элемента, либо головного элемента, либо хвостового элемента строки в «Синтаксисе списка»?

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

(ИКС)
(п а б)
(функ (функ2 а) (функ3 X Y))
(равна Еве (матери Каин))

Головка каждой из этих строк по порядку:
Голова:«Х», Индекс:1
Голова:«п», Индекс:1
Голова:"функция", индекс:4
Голова:"равный", Индекс:5

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

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


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

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

Сходным образом:((((b W) X) Y) Z)

Где голова (((b w) x) Y).

Это было полезно?

Решение

Java Сканер class (представленный в 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

Это не очень элегантное решение, но регулярные выражения не могут считаться (т.кронштейны).Я бы подумал об использовании генератора синтаксического анализатора, если там есть еще какие-то сложности :)

Другие советы

Есть ли причина, по которой вы не можете просто использовать грубую силу?Что-то вроде этого?

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top