Я хотел бы создать парсер Antlr для пользовательского языка и решил в качестве примера выбрать простой калькулятор . В моей новой грамматике должно быть возможно определить строку, как это:
s = "Hello, I am a string"
и обрабатывать интерполяцию строк.
Текст в двойных кавычках, заключенный в persent, должен рассматриваться как интерполированный, например,
s = "Hello, did you know that %2 + 2% is 4?"
Двойной знак процента не должен обрабатываться, например,
s = "He wants 50%% of this deal."
Но в то же время мой калькулятор должен поддерживать работу модуля:
x = 5 % 2
Пока что мне удалось создать лексер / грамматику, которая могла бы переключать режим и анализировать простые строки, вот они:
lexer grammar CalcLexer;
EQ: '=';
PLUS: '+';
MINUS: '-';
MULT: '*';
DIV: '/';
LPAREN : '(' ;
RPAREN : ')' ;
SINGLE_PERCENT_POP: '%' -> popMode;
ID : [a-zA-Z]+ ;
INT : [0-9]+ ;
OPEN_DOUBLE_QUOTE: '"' -> pushMode(STRING_MODE);
NEWLINE:'\r'? '\n' ;
WS : [ \t]+ -> skip;
mode STRING_MODE;
DOUBLE_PERCENT: '%%';
SINGLE_PERCENT: '%' -> pushMode(DEFAULT_MODE);
TEXT: ~('%'|'\n'|'"')+;
CLOSE_DOUBLE_QUOTE: '"' -> popMode;
и
parser grammar CalcGrammar;
options { tokenVocab=CalcLexer; } // use tokens from CalcLexer.g4
prog: stat+ ;
stat: expr NEWLINE
| ID EQ (expr|text) NEWLINE
| NEWLINE
;
text: OPEN_DOUBLE_QUOTE content* CLOSE_DOUBLE_QUOTE;
content: DOUBLE_PERCENT | TEXT | SINGLE_PERCENT expr SINGLE_PERCENT_POP;
expr: expr (MULT|DIV) expr
| expr (PLUS|MINUS) expr
| INT
| ID
| LPAREN expr RPAREN
;
Но единственное, что не работает, и я не уверен, что когда-либо возможно реализовать без пользовательского кода (членов), это операция модуля:
x = 5 % 2
Нет способа попросить Anltr проверить предыдущий режим и безопасный поп-режим.
Но я надеюсь, что мое понимание неверно, и есть какой-то способ трактовать знак %
как оператор в режиме по умолчанию?
Я нашел несколько источников вдохновения, возможно, они вам тоже помогут: