Предикаты ANTLR4 с жадным * квантификатором: избегайте ненужных вызовов предикатов (лексизм) - PullRequest
0 голосов
/ 19 июня 2019

Следующий фрагмент грамматики лексера должен маркировать «пользовательские имена» в зависимости от предиката, определенного в классе LexerHelper:

fragment NUMERICAL      : [0-9];

fragment XML_NameStartChar
                        : [:a-zA-Z]
                        | '\u2070'..'\u218F'
                        | '\u2C00'..'\u2FEF'
                        | '\u3001'..'\uD7FF'
                        | '\uF900'..'\uFDCF'
                        | '\uFDF0'..'\uFFFD'
                        ;

fragment XML_NameChar   : XML_NameStartChar
                        | '-' | '_' | '.' | NUMERICAL
                        | '\u00B7'
                        | '\u0300'..'\u036F'
                        | '\u203F'..'\u2040'
                        ;

fragment XML_NAME_FRAG  : XML_NameStartChar XML_NameChar*;

CUSTOM_NAME             : XML_NAME_FRAG ':' XML_NAME_FRAG {LexerHelper.myPredicate(getText())}?;

Правильное совпадение для CUSTOM_NAME всегда самое длинное из возможных совпадений.Теперь, если лексер встречает пользовательское имя, такое как some:cname, я бы хотел, чтобы он целую строку some:cname и затем вызывал предикат один раз с аргументом some: cname.

Вместо этогоlexer вызывает предикат с каждым возможным «действительным» соответствием, которое он находит по пути, поэтому some:c, some:cn, some:cna, some:cnam до тех пор, пока, наконец, some:cname.

Есть ли способизменить поведение, чтобы заставить antlr4 сначала найти максимально возможное совпадение, прежде чем вызывать предикат?В качестве альтернативы, есть ли эффективный способ для предиката определить, что совпадение не является самым длинным из всех, чтобы просто вернуться с false в этом случае?

РЕДАКТИРОВАТЬ: забавно, что такое поведение так долго, как долготак как предикату передаются только частичные совпадения, результат предиката, похоже, полностью игнорируется лексером.Это кажется странно неэффективным.

1 Ответ

0 голосов
/ 19 июня 2019

Как выясняется, поведение известно и разрешено Antlr.Antlr может или не может вызывать предикаты больше, чем необходимо ( см. Здесь для более подробной информации ).Чтобы избежать такого поведения, я теперь использую действия, которые выполняются только после полного и успешного соответствия правила.Это позволяет мне, например, переключать режимы в действии.

...