Как мне найти индекс первого «элемента» в моей строке с помощью Java?
Вопрос
Я работаю над написанием простого интерпретатора Пролога на 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 для дальнейшей обработки.