Я хочу написать лексер с несколькими режимами. Но режимы в основном похожи. Единственное различие заключается в том, что я ссылаюсь на один и тот же символ под другим именем. У меня это работает, проблема в том, что мне нужно скопировать весь лексер, чтобы изменить все имена, добавить типы и добавить одну строку для каждого режима.antlr4 правила обмена в режимах
Вот общая проблема, которую я хочу решить. Я хочу, чтобы запятая имела высокий приоритет за пределами '[' ']'. Я хочу, чтобы он имел низкий приоритет внутри '['
, ']'
. Для этого я нажимаю и поп-режимы с '['
и ']'
. Но поскольку единственное, что я меняю, это приоритет, который я должен скопировать все правила в каждый режим и дать им разные имена.
Еще одна вещь, когда-то внутри '['
не было бы возможности вернуться к запятой с высоким приоритетом. Поэтому, когда грамматика переходит в раздел '{'
, '}'
, запятая возвращается к высокому приоритету.
Для этого у меня есть начальный режим по умолчанию плюс CONJUNCTION
(высокий приоритет) и NON_CONJUNCTION
(низкий приоритет). Я копирую все правила из режима по умолчанию и переименовываю их в C_
или NC_
. Затем я верну их тип типа режима по умолчанию.
Я бы предпочел выполнить это, не справляясь, переименовывая и присваивая типы всем правилам из режима по умолчанию.
Вот мой лексер:
lexer grammar DabarLexer;
OPEN_PAREN : '(' -> pushMode(NON_CONJUNCTION) ;
CLOSE_PAREN : ')' -> popMode;
OPEN_BRACKET : '[' -> pushMode(NON_CONJUNCTION) ;
CLOSE_BRACKET : ']' -> popMode ;
OPEN_CURLY : '{' -> pushMode(CONJUNCTION) ;
CLOSE_CURLY : '}' -> popMode ;
SPACE : ' ' ;
HEAVY_COMMA : ',';
ENDLINE : '\n' ;
PERIOD : '.' ;
SINGLE_QUOTE : '\'' ;
DOUBLE_QUOTE : '"' ;
INDENTION : '\t' -> skip;
fragment SYMBOL : HEAVY_COMMA | OPEN_BRACKET | CLOSE_BRACKET | OPEN_PAREN | CLOSE_PAREN | OPEN_CURLY | CLOSE_CURLY | SPACE | ENDLINE | PERIOD | SINGLE_QUOTE | DOUBLE_QUOTE | INDENTION ;
ESCAPE : '\\' SYMBOL ;
fragment NON_SYMBOL : ~[(){}',; \n.\t"\[\]] ;
IDENTIFIER : (NON_SYMBOL | ESCAPE)+ ;
LITERAL : (SINGLE_QUOTE (NON_SYMBOL | ESCAPE)+ SINGLE_QUOTE) | DOUBLE_QUOTE (NON_SYMBOL | ESCAPE)+ DOUBLE_QUOTE ;
mode CONJUNCTION ;
C_HEAVY_COMMA : ',' -> type(HEAVY_COMMA);
C_OPEN_PAREN : '(' -> type(OPEN_PAREN), pushMode(NON_CONJUNCTION) ;
C_CLOSE_PAREN : ')' -> type(CLOSE_PAREN), popMode;
C_OPEN_BRACKET : '[' -> type(OPEN_BRACKET), pushMode(NON_CONJUNCTION) ;
C_CLOSE_BRACKET : ']' -> type(CLOSE_BRACKET), popMode ;
C_OPEN_CURLY : '{' -> type(OPEN_CURLY), pushMode(CONJUNCTION) ;
C_CLOSE_CURLY : '}' -> type(CLOSE_CURLY), popMode ;
C_SPACE : ' ' -> type(SPACE);
C_ENDLINE : '\n' -> type(ENDLINE);
C_PERIOD : '.' -> type(PERIOD);
C_SINGLE_QUOTE : '\'' -> type(SINGLE_QUOTE);
C_DOUBLE_QUOTE : '"' -> type(DOUBLE_QUOTE);
C_INDENTION : '\t' -> type(INDENTION),skip;
fragment C_SYMBOL : (HEAVY_COMMA | C_OPEN_BRACKET | C_CLOSE_BRACKET | C_OPEN_PAREN | C_CLOSE_PAREN | C_OPEN_CURLY | C_CLOSE_CURLY | C_SPACE | C_ENDLINE | C_PERIOD | C_SINGLE_QUOTE | C_DOUBLE_QUOTE | C_INDENTION) ;
C_ESCAPE : '\\' C_SYMBOL -> type(ESCAPE);
fragment C_NON_SYMBOL : ~[(){}',; \n.\t"\[\]] ;
C_IDENTIFIER : (C_NON_SYMBOL | C_ESCAPE)+ -> type(IDENTIFIER);
C_LITERAL : ((C_SINGLE_QUOTE (C_NON_SYMBOL | C_ESCAPE)+ C_SINGLE_QUOTE) | C_DOUBLE_QUOTE (C_NON_SYMBOL | C_ESCAPE)+ C_DOUBLE_QUOTE) -> type(LITERAL);
mode NON_CONJUNCTION ;
LIGHT_COMMA : ',' ;
NC_OPEN_PAREN : '(' -> type(OPEN_PAREN), pushMode(NON_CONJUNCTION) ;
NC_CLOSE_PAREN : ')' -> type(CLOSE_PAREN), popMode;
NC_OPEN_BRACKET : '[' -> type(OPEN_BRACKET), pushMode(NON_CONJUNCTION) ;
NC_CLOSE_BRACKET : ']' -> type(CLOSE_BRACKET), popMode ;
NC_OPEN_CURLY : '{' -> type(OPEN_CURLY), pushMode(CONJUNCTION) ;
NC_CLOSE_CURLY : '}' -> type(CLOSE_CURLY), popMode ;
NC_SPACE : ' ' -> type(SPACE);
NC_ENDLINE : '\n' -> type(ENDLINE);
NC_PERIOD : '.' -> type(PERIOD);
NC_SINGLE_QUOTE : '\'' -> type(SINGLE_QUOTE);
NC_DOUBLE_QUOTE : '"' -> type(DOUBLE_QUOTE);
NC_INDENTION : '\t' -> type(INDENTION),skip;
fragment NC_SYMBOL : (LIGHT_COMMA | NC_OPEN_BRACKET | NC_CLOSE_BRACKET | NC_OPEN_PAREN | NC_CLOSE_PAREN | NC_OPEN_CURLY | NC_CLOSE_CURLY | NC_SPACE | NC_ENDLINE | NC_PERIOD | NC_SINGLE_QUOTE | NC_DOUBLE_QUOTE | NC_INDENTION) ;
NC_ESCAPE : '\\' NC_SYMBOL -> type(ESCAPE);
fragment NC_NON_SYMBOL : ~[(){}',; \n.\t"\[\]] ;
NC_IDENTIFIER : (NC_NON_SYMBOL | NC_ESCAPE)+ -> type(IDENTIFIER);
NC_LITERAL : ((NC_SINGLE_QUOTE (NC_NON_SYMBOL | NC_ESCAPE)+ NC_SINGLE_QUOTE) | NC_DOUBLE_QUOTE (NC_NON_SYMBOL | NC_ESCAPE)+ NC_DOUBLE_QUOTE) -> type(LITERAL);
Я рассмотрел вашу ссылку. Решения они такие же. Определенно использование этого типа позволяет ограничить объем дублирования. Он позволяет синтаксическому анализатору один тип, даже если парсер упоминает несколько. То же самое можно сказать и о парсере. У меня нет кредита, чтобы выбрать ваш ответ. – dodtsair