#java #python #antlr4
#java #python #antlr4
Вопрос:
Я хотел бы использовать свое правило лексера
NEW_LINE : 'n' -> skip;
Как обычное правило. Понимание под этим: я хочу игнорировать новые строки, за исключением случаев, когда они обязательны, чтобы создать синтаксис, аналогичный Python. Например, здесь новые строки игнорируются:
cook("banana",
"potatoe)
но невозможно пропустить новую строку для нового оператора, подобного этому:
cook("banana", "potatoe") varA = 12.4
между cook()
и присваиванием должна быть новая строка. Вот почему мне иногда приходится пропускать новые строки, но все равно заставлять их где-то в другом месте.
Вот почему у меня возникла эта идея:
start
: line*
;
line
: line_expression (NEW_LINE | EOF)
;
line_expression
: expression
| assignment
;
expression
: Decimal
| Integer
| Text
| Boolean
;
И создайте семантический предикат типа «если вызывающее правило синтаксического анализатора не является строкой, skip();
это».
Теперь мне просто нужна помощь, чтобы сделать это.
Я надеюсь, что я был ясен!
PS: Я использую Java в качестве основного языка, если это было непонятно
Ответ №1:
Вы могли бы отслеживать количество (
встречаемых вами (и уменьшать это число, если вы сталкиваетесь с )
). Затем вы создаете NL
токены только в том случае, если это число равно нулю.
Вот краткая демонстрация:
grammar T;
@lexer::members {
int parensLevel = 0;
}
parse
: .*? EOF
;
OPAR : '(' {parensLevel ;};
CPAR : ')' {parensLevel--;};
NUMBER : [0-9] ( '.' [0-9] )?;
STRING : '"' ~'"'* '"';
ASSIGN : '=';
COMMA : ',';
ID : [a-zA-Z] ;
SPACES : [ t] -> skip;
NL : {parensLevel == 0}? [rn] ;
NL_SKIP : [rn] -> skip;
Если вы передадите лексеру следующие входные данные:
cook("banana",
"potatoe")
varA = 12.4
будут созданы следующие токены:
ID `cook`
'(' `(`
STRING `"banana"`
',' `,`
STRING `"potatoe"`
')' `)`
NL `n`
ID `varA`
'=' `=`
NUMBER `12.4`
Как вы можете видеть, NL
внутри скобок пропущен, а тот, что после )
, — нет.