Regex для поиска переменных и игнорирования методов - PullRequest
3 голосов
/ 11 апреля 2011

Я пытаюсь написать регулярное выражение, которое находит все переменные (и только переменные, полностью игнорируя методы) в данном фрагменте кода JavaScript.Фактический код (тот, который выполняет регулярные выражения) написан на Java.

На данный момент у меня есть что-то вроде этого:

Matcher matcher=Pattern.compile(".*?([a-z]+\\w*?).*?").matcher(string);
while(matcher.find()) {
    System.out.println(matcher.group(1));
}

Итак, когда значение "string" равноvariable*func()*20

распечатка:

variable
func

Это не то, что я хочу.Простое отрицание ( не сработает, потому что оно заставляет регулярное выражение отлавливать ненужные символы или обрезает их, но функции по-прежнему сохраняются.На данный момент у меня есть следующий код:

Matcher matcher=Pattern.compile(".*?(([a-z]+\\w*)(\\(?)).*?").matcher(formula);
while(matcher.find()) {
    if(matcher.group(3).isEmpty()) {
        System.out.println(matcher.group(2));
    }
}

Это работает, распечатка верна, но мне не нравится дополнительная проверка.Есть идеи?Пожалуйста?

РЕДАКТИРОВАТЬ (2011-04-12):

Спасибо за все ответы.Были вопросы, зачем мне что то подобное.И вы правы, в случае более крупных и сложных сценариев единственным разумным решением будет их анализ.В моем случае, однако, это было бы чрезмерным.Отрывки JS, над которыми я работаю, предназначены для простых формул, что-то вроде (a+b)/2.Никаких комментариев, строковых литералов, массивов и т. Д. Только переменные и (возможно) некоторые встроенные функции.Мне нужен список переменных, чтобы проверить, можно ли их инициализировать и этот момент (и вообще инициализировать).Я понимаю, что все это можно сделать вручную и с помощью RPN (что было бы безопаснее), но эти формулы будут обернуты более крупным сценарием и оценены в веб-браузере, поэтому так удобнее.

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

Есликто-нибудь найдет этот вопрос, желая сделать что-то похожее, если теперь возникнут риски / трудности.Да, по крайней мере, я на это надеюсь;)

Ответы [ 4 ]

1 голос
/ 11 апреля 2011

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

Pattern regex = Pattern.compile(
    "\\b     # word boundary\n" +
    "[A-Za-z]# 1 ASCII letter\n" +
    "\\w*    # 0+ alnums\n" +
    "\\b     # word boundary\n" +
    "(?!     # Lookahead assertion: Make sure there is no...\n" +
    " \\s*   # optional whitespace\n" +
    " \\(    # opening parenthesis\n" +
    ")       # ...at this position in the string", 
    Pattern.COMMENTS);

Это соответствует идентификатору, если за ним не следуетскобкаКонечно, теперь вам нужно group(0) вместо group(1).И, конечно, это соответствует множеству других вещей (внутри строк, комментариев и т. Д.) ...

1 голос
/ 11 апреля 2011

Если вы переосмысливаете регулярное выражение и задаетесь вопросом, что еще можно сделать, вы можете вместо этого использовать AST для программного доступа к своему источнику. Этот ответ показывает, что вы можете использовать Eclipse Java AST для построения синтаксического дерева для источника Java.Я думаю, вы могли бы сделать подобное для Javascript.

1 голос
/ 11 апреля 2011

В этом случае регулярное выражение не будет вырезано, потому что Java не является регулярной. Лучше всего получить парсер, который понимает синтаксис Java и опирается на него. К счастью, ANTLR имеет грамматику Java 1.6 1,5 грамматика ).

Для вашего довольно ограниченного варианта использования вы, вероятно, можете легко расширить правила назначения переменных и получить необходимую информацию. Это что-то вроде кривой обучения, но, вероятно, это будет лучшим решением для быстрого и точного решения.

1 голос
/ 11 апреля 2011

Достаточно хорошо установлено, что регулярное выражение не может быть надежно использовано для анализа структурированного ввода.См. Здесь известный ответ: RegEx соответствует открытым тегам, за исключением автономных тегов XHTML

Поскольку любая заданная последовательность символов может изменить или не изменить значение в зависимости от предыдущей или последующей последовательности символовВы не можете надежно идентифицировать синтаксический элемент без синтаксического анализа входного текста как , так и .Regex может использоваться для первого (разбивая входной поток на токены), но не может использоваться надежно для второго (назначая значение токенам в зависимости от их положения в потоке).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...