Как сгенерировать несколько деревьев синтаксического анализа для неоднозначного ввода в ANTLR

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

Для простоты, учитывая имя человека, такое как «Альбер Йохансон», это имя можно было бы проанализировать как

(fullName (firstName Alber) (lastName Johanson)) 

или анализируется как

(fullName (firstName Alber) (lastName Johan) (relation son)) 

Во-первых, как настроить правила для второго случая? Поскольку это часть второй строки, а не отдельный токен.

Во-вторых, как сгенерировать деревья синтаксического анализа для всех возможных вариантов входной строки?

ОБНОВЛЕНИЕ

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

fullName: firstName lastName | firstName lastName relation;
firstName: NAME;
lastName: NAME;
relation: REL;

NAME: ('a'..'z'|'A'..'Z')+;
REL: 'son';

WHITESPACE : ('\t' | ' ' | '\r' | '\n'| '\u0020' | '\u000C' )+ -> skip ;

person vanilla    schedule 12.04.2015    source источник
comment
чтобы ответить на ваш вопрос о способах настройки правил, это полностью ваше (приложение) решение (требование)! нам хотя бы нужно знать, как следует разделять имя в вашем приложении? Йохансона следует разделить на Йохана и сына? какие еще правила? нам нужно больше узнать о том, что вы пробовали при разработке своего приложения.   -  person Nirmal    schedule 13.04.2015
comment
@ user3320018 Я обновил свой вопрос грамматикой, которая у меня есть   -  person vanilla    schedule 13.04.2015
comment
Вы хотите обрабатывать случаи по-другому или почему вы хотите сгенерировать несколько деревьев синтаксического анализа?   -  person Adrian Leonhard    schedule 13.04.2015
comment
Ответ @CoronA правильный; вы не можете делать то, что хотите, но это из-за лексера. У вас более глубокая проблема, которая вызывает множественные интерпретации синтаксического анализа. ANTLR не предназначен для этого, и согнуть его, вероятно, будет очень сложно. Вместо этого вы можете рассмотреть возможность использования парсера GLR; они предназначены для выполнения всех возможных синтаксических анализов. Парсер GLR не решит вашу проблему с лексированием; сначала вам нужно решить, что вы хотите с этим делать.   -  person Ira Baxter    schedule 13.04.2015
comment
@AdrianLeonhard да, я хочу собрать все возможные варианты структуры имени, которые будут обрабатываться позже в моем приложении   -  person vanilla    schedule 14.04.2015
comment
@IraBaxter, что лучше для моего второго вопроса? Парсер GEP, рекомендованный CoronA, или парсер GLR? Я мало что знаю ни об одном из них   -  person vanilla    schedule 14.04.2015
comment
@vanilla: ты имеешь в виду ПЭГ? Peg - это анализатор с возвратом. Если он пробует альтернативу, которая не работает, он может вернуться к какой-либо другой допустимой точке в пространстве допустимых префиксов для языка, но он возвращается в случае неудачи для соответствия. Если ему удастся найти альтернативу, он не будет пробовать ничего другого. Таким образом, он не будет перечислять все возможные совпадения вашего ввода и, следовательно, не может захватить все синтаксические анализы. Однако парсеры GLR исследуют / генерируют все возможные синтаксические анализы и возвращают DAG вместо дерева, где совместное использование соответствует идентичным поддеревьям при альтернативных синтаксических анализах (неоднозначности).   -  person Ira Baxter    schedule 14.04.2015
comment
@IraBaxter Спасибо за ваш отзыв. да, извините я про ПЭГ :). знаете ли вы хорошую библиотеку, которую я могу использовать в качестве генератора парсера GLR в java? и почему синтаксический анализатор GLR не может решить проблему лексирования, требуется ли ему внешний лексер или он не предназначен для решения аналогичной проблемы?   -  person vanilla    schedule 14.04.2015


Ответы (2)


ANTLR не позволит вам сделать это так, как вы хотите. Но все же причина не в двусмысленности, а в токенизаторе.

Слово "Johanson" всегда используется как NAME из-за политики лексирования ANTLR:

  • вернуть жетон с самым длинным совпадением
  • в случае совпадения двух токенов одинаковой длины, предпочтение отдается первому определенному

Токен REL никогда не появится, поскольку

  • любое слово с суффиксом «сын» - это NAME (самое длинное совпадение)
  • любое слово с префиксом "сын" - это NAME (самое длинное совпадение)
  • тем не менее, изолированное слово "сын" - это NAME (REL совпадает, но не определяется сначала)

Ответьте на ваш первый вопрос: он не может быть обработан анализатором ANTLR, потому что он полагается на токенизацию перед синтаксическим анализом. У вас есть два варианта:

  • использовать генератор парсера, позволяющий токенизировать направленный парсер (PEG-парсеры, такие как parboiled, крысы должны это делать)
  • отбросить токен REL и повторно проанализировать фамилии при посещении дерева синтаксического анализа

Ответьте на второй вопрос:

Обе альтернативы выше затрудняют решение вопроса о печати возможных интерпретаций одной и той же последовательности символов.

PEG-парсеры разработаны так, чтобы предпочесть первую альтернативу по своей задумке, они не будут исследовать дальше, если будет найдена действительная интерпретация.

ANTLR еще не предназначен для управления лексером, управляемым анализатором. Если вы решите повторно проанализировать фамилии, вероятно, легче найти интерпретацию с помощью чистого java, чем писать новый лексер / парсер для их поиска.

person CoronA    schedule 13.04.2015
comment
спасибо за подробный ответ. Попробую проверить парсер PEG. - person vanilla; 14.04.2015

Переход от долгого потока комментариев:

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

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

Нет, я не знаю хорошего парсера GLR на основе Java. Вот большой список: http://en.wikipedia.org/wiki/Comparison_of_parser_generators

person Ira Baxter    schedule 14.04.2015