Как сопоставить строку в круглых скобках (вложенных) в Java?

Я хотел бы совместить строку в круглых скобках, например:

(i, j, k(1))
^^^^^^^^^^^^

Строка также может содержать закрытые круглые скобки. Как сопоставить его с регулярным выражением в Java без написания парсера, так как это небольшая часть моего проекта. Спасибо!

Edit:

Я хочу найти строковый блок и найти что-то вроде u(i, j, k), u(i, j, k(1)) или просто u(<anything within this paired parens>) и заменить их на __u%array(i, j, k) и __u%array(i, j, k(1)) для моего приложения для перевода Fortran.

Ответ 1

Как я уже говорил, вопреки распространенному мнению (не верьте всему, что говорят люди), сопоставление вложенных скобок возможно с регулярным выражением.

Недостатком использования является то, что вы можете только до фиксированного уровня вложенности. И для каждого дополнительного уровня, который вы хотите поддержать, ваше регулярное выражение будет больше и больше.

Но не верьте мне на слово. Позволь мне показать тебе. Регулярное выражение:

\([^()]*\)

Соответствует одному уровню. Для до двух уровней вам потребуется:

\(([^()]*|\([^()]*\))*\)

И так далее. Чтобы добавить уровни, все, что вам нужно сделать, это изменить среднюю (вторую) часть [^()]* на ([^()]*|\([^()]*\))* (проверить три уровня здесь). Как я уже сказал, он будет становиться все больше и больше.

Ваша проблема:

В вашем случае может быть достаточно двух уровней. Таким образом, для него был бы Java-код:

String fortranCode = "code code u(i, j, k) code code code code u(i, j, k(1)) code code code u(i, j, k(m(2))) should match this last 'u', but it doesnt.";
String regex = "(\\w+)(\\(([^()]*|\\([^()]*\\))*\\))"; // (\w+)(\(([^()]*|\([^()]*\))*\))
System.out.println(fortranCode.replaceAll(regex, "__$1%array$2"));

Input:

code code u(i, j, k) code code code code u(i, j, k(1)) code code code u(i, j, k(m(2))) should match this last 'u', but it doesnt.

Вывод:

code code __u%array(i, j, k) code code code code __u%array(i, j, k(1)) code code code u(i, j, __k%array(m(2))) should match this last 'u', but it doesnt.

Нижняя строка:

В общем случае синтаксические анализаторы сделают лучшую работу - вот почему люди так извиваются за это. Но для простых приложений регулярное выражение может быть достаточно.

Примечание. Некоторые варианты регулярного выражения поддерживают оператор вложенности R (Java не работает, такие как PCRE-движки, как PHP и Perl), что позволяет вам устанавливать произвольное количество уровней, С ними вы можете сделать: \(([^()]|(?R))*\).

Ответ 2

Отделите свою работу. Есть регулярное выражение:

([a-z]+)\((.*)\)

Первая группа будет содержать идентификатор, второй - параметры. Затем выполните следующие действия:

private static final Pattern PATTERN = Pattern.compile("([a-z]+)\\((.*)\\)");

// ...

final Matcher m = Pattern.matcher(input);

if (!m.matches())
    // No match! Deal with it.

// If match, then:

final String identifier = m.group(1);
final String params = m.group(2);

// Test if there is a paren
params.indexOf('(') != -1;

Замените [a-z]+ тем, чем может быть идентификатор в Fortran.