ANTLR4 сопоставляет любые несоответствующие разделы в один токен STRING - PullRequest
0 голосов
/ 03 февраля 2020

Я пытаюсь создать Lexer / Parser с ANTLR, который может анализировать простой текст с «тегами», разбросанными между ними. Эти теги обозначаются открывающими ({) и закрывающими (}) скобками, и они представляют Java объекты, которые могут преобразовываться в строку, которая затем заменяется в исходном вводе для создания динамического c шаблона сортов.

Вот пример: {player: name} говорит привет! {Player: name} должен быть заменен на имя игрока и привести к выводу, т.е. Марк говорит привет! для игрока по имени Марк.

Теперь я могу отлично распознавать и анализировать теги, с чем у меня проблемы, это текст, который идет после. Вот грамматика, которую я использую:

    grammar : content+

    content : tag 
            | literal
            ;

    tag : player_tag
        | <...>
        | <other kinds of tags, not important for this example>
        | <...>
        ;

    player_tag : BRACKET_OPEN player_identifier SEMICOLON player_string_parameter BRACKET_CLOSE ;
    player_string_parameter : NAME
                            | <...>
                            ;
    player_identifier : PLAYER ;

    literal : NUMBER
            | STRING
            ;

    BRACKET_OPEN : '{';
    BRACKET_CLOSE : '}';

    PLAYER : 'player'
    NAME : 'name'

    NUMBER : <...>
    STRING : (.+)? /* <- THIS IS THE PROBLEMATIC PART !*/

Теперь это определение STRING Lexer должно соответствовать всему, что не является пустой строкой, но проблема в том, что оно слишком жадное, а затем также использует токены скобки {}, необходимые правило тега. Я попытался установить для него значение ~ [{}] +, которое должно соответствовать чему-либо, что не включает скобки {}, но содержит винты с разбором тега, что я тоже не понимаю. Я мог бы установить что-то вроде [a-zA-Z0-9! "§ $% & / () = et c ...] +, но я действительно не хочу ограничивать его для анализа только символов, доступных на клавиатура briti sh (немецкие умляты или французские акценты и все другие специальные символы, которые должны присутствовать в других языках!) Единственное, что несколько работает, хотя мне это очень не нравится, это заставляет строки иметь префикс и суффикс, например, так:

  STRING : '\'' ~[}{]+ '\'' ;

Это заставляет меня изменить форму с "{player: name} говорит привет!" На "{player: name} 'говорит привет!" ", И я действительно отчаянно хочу избежать таких ограничений, потому что Затем я должен был бы учитывать буквенные символы в самой строке, и работать с ним просто некрасиво.

Имеются два следующих решения: - Есть ли способ сопоставить любое количество символов который не был сопоставлен лексером как токен STRING и передал его парсеру? Таким образом, я мог бы сопоставить все теги и сказать, что остальная часть ввода представляет собой просто текст, вернуть его мне как STRING токен или еще что-нибудь ... - Поддерживает ли ANTLR выражения регулярных выражений lookahead и lookbehind, с которыми я могу сопоставить любое количество символов перед первым '{', после последнего '}' и что-нибудь между '}' и '{'? Я пробовал

  STRING : (?<=})(.+)?(?={) ;

, но я не могу понять правильный синтаксис, потому что он вообще не компилируется, что приводит меня к мысли, что ANTLR не поддерживает синтаксис lookahead и lookbehind, но я мог не найти окончательного ответа на этот вопрос rnet.

Любой совет, что делать?

1 Ответ

1 голос
/ 03 февраля 2020

Antlr не поддерживает просмотр вперед или назад. Он поддерживает сопоставления без жадных подстановочных знаков, но только в том случае, если после правила в правиле используется не * жадный подстановочный знак *1002* с последовательностью завершения (которая, как вы говорите, также содержится в совпадении, хотя вы можете вернуть sh обратно во входной поток).

Так что ~[{}]* правильно. Но есть небольшая проблема: правила лексера (обычно) всегда активны. Таким образом, правило лексера также будет активным внутри фигурных скобок , а это означает, что оно будет поглощать все содержимое между фигурными скобками (если только внутри кавычек или некоторых подобных фигур не вставлены вложенные фигурные скобки, и это еще хуже) .

Таким образом, вам нужно определить различное лексическое содержимое, называемое "лексические режимы" в Antlr. В «Общем справочнике по Antlr» есть общедоступный пример , в котором показано решение очень похожей проблемы: синтаксический анализ HTML.

...