Как сопоставить любой символ в парсере ANTLR (не лексере)?

Как сопоставить любой символ в парсере ANTLR (не лексере)? Где полное описание языка для парсеров ANTLR4?

ОБНОВЛЕНИЕ

Ответ "невозможен"?


person Suzan Cioc    schedule 16.05.2013    source источник
comment
Ответ на ваш обновленный вопрос: да, это невозможно (как я указал в своем ответе).   -  person Bart Kiers    schedule 18.05.2013
comment
Я понятия не имею, что именно вам нужно. Но, возможно, вам следует взглянуть на островные грамматики. Это должно помочь в случаях, когда вам нужно разобрать один ввод с двумя разными грамматиками.   -  person ibre5041    schedule 20.05.2013


Ответы (3)


Сначала вам нужно понять роли каждой части в разборе:

Лекспер: это объект, который маркирует вашу входную строку. Токенизация означает преобразование потока входных символов в абстрактный символ токена (обычно просто число).

Синтаксический анализатор: это объект, который работает только с токенами для определения структуры языка. Язык (записанный в виде одного или нескольких файлов грамматики) определяет допустимые комбинации токенов.

Как видите, парсер даже не знает, что такое буква. Он знает только токены. Так что ваш вопрос уже неверен.

Сказав, что, вероятно, было бы полезно узнать, почему вы хотите пропустить отдельные вводимые буквы в своем синтаксическом анализаторе. Похоже, ваша базовая концепция нуждается в корректировке.

person Mike Lischke    schedule 18.05.2013
comment
Как сказал предыдущий ответчик, в ANTLR есть метасимвол DOT. У него также будет некоторое мета-правило лексера для преобразования всех символов в токены в формате 1: 1. Не вижу смысла вообще иметь лексер. Он выполняет тегирование так же, как и парсер, но плохое и ограниченное тегирование. Это избыточная конструкция. - person Suzan Cioc; 18.05.2013
comment
@SuzanCioc, ты просто используешь не тот инструмент. ANTLR не работает так, как вы ожидаете/хотите. То, что вам нужно, это PEG, не нужно жаловаться на тот факт, что ANTLR не работает так, как вы ожидаете / хотите. - person Bart Kiers; 18.05.2013

Это зависит от того, что вы подразумеваете под «символом». Чтобы сопоставить любой токен внутри правила парсера, используйте метасимвол . (DOT). Если вы пытаетесь сопоставить любой символ внутри правила парсера, то вам не повезло, в ANTLR существует строгое разделение между правилами парсера и лексера. Невозможно сопоставить какой-либо символ внутри правила синтаксического анализатора.

person Bart Kiers    schedule 17.05.2013
comment
Не сильно ли это ограничивает работу с Unicode? Unicode состоит из тысяч символов, и ANTLR позволяет мне либо рассматривать большинство из них как один и тот же токен, либо создавать определение лексера для каждого из них. Похоже на очень плохой дизайн. Не так ли? - person Suzan Cioc; 18.05.2013
comment
P.S. Предположим, я хочу описать строковый литерал Java. Он заключен в кавычки, но может содержать что угодно. Если я разберу его с помощью лексера, я потеряю его содержимое. Почему так отличается от целочисленного литерала? - person Suzan Cioc; 18.05.2013
comment
@SuzanCioc извините, я понятия не имею, что вы имеете в виду. Строковые литералы обычно обрабатываются в лексере, зачем вам обрабатывать их в правиле синтаксического анализатора? - person Bart Kiers; 18.05.2013
comment
числовые литералы также обычно обрабатываются лексерами? Строковые литералы могут содержать сложные конструкции, например, строки JSTL/EL или C#. Это работа парсера. Я не вижу причин связывать это с лексером, тем более что у лексера такая ограниченная функциональность. - person Suzan Cioc; 18.05.2013
comment
@SuzanCioc, в этом случае это работа для другого парсера. То, что вы пытаетесь сделать, это проанализировать 2 разных языка: я не знаю ни одного инструмента, который делает это (легко). - person Bart Kiers; 18.05.2013

Это возможно, но только если у вас такая базовая грамматика, что причина использования ANTlr в любом случае сводится на нет.

Если бы у вас была грамматика:

text     : ANY_CHAR* ;
ANY_CHAR : . ;

он будет делать то, что вы (кажется) хотите.

Однако, как отмечают многие, это было бы довольно странным поступком. Целью лексера является идентификация различных токенов, которые могут быть объединены в синтаксическом анализаторе для формирования грамматики, поэтому ваш лексер может либо идентифицировать конкретную строку "JSTL/EL" как токен, либо [AZ]'/ EL', [AZ]'/'[AZ][AZ] и т. д. - в зависимости от того, что вам нужно.

Затем синтаксический анализатор используется для определения грамматики, поэтому:

phrase     : CHAR* jstl CHAR* ;
jstl       : JSTL SLASH QUALIFIER ;

JSTL       : 'JSTL' ;
SLASH      : '/'
QUALIFIER  : [A-Z][A-Z] ;
CHAR       : . ;

будет принимать "бла-бла JSTL/EL..." в качестве входных данных, но не "бла-бла EL/JSTL...".

Я бы порекомендовал ознакомиться с полным справочником по ANTlr 4, в частности с разделом «Острова в потоке» и справочником по грамматике (глава 15), в котором конкретно рассматривается Unicode.

person Dave    schedule 05.06.2013
comment
Ваше правило phrase не будет работать с фразой JSTL - это версия jstl с заглавной буквы, потому что лексер съест первый JSTL как токен JSTL, и тогда он не будет соответствовать правилу фразы. Итак, идея лексера просто плохая идея. - person Suzan Cioc; 06.06.2013
comment
Это довольно странно, так как когда я начинал с ANTlr, у меня было в значительной степени противоположное мнение - и несколько раз я был очень близок к тому, чтобы просто использовать лексер для предоставления токенов, а затем написать свой собственный парсер вне ANTlr. Все, что я могу сказать, это то, что для большинства простых грамматик здесь, которые люди используют для обсуждения ошибок и/или недоразумений, да, кажется излишним иметь и парсер, и лексер. Однако, как только все усложняется, разделение становится выгодным — грамматики лексера и парсера для нашего приложения здесь работают на сотнях строк, и мы считаем, что такое разделение является хорошей идеей. - person Dave; 07.06.2013