字符串插值:是否可以不添加成员?

时间:2018-11-05 22:34:45

标签: antlr antlr4 string-interpolation

我想为自定义语言创建一个Antlr解析器,并决定选择一个简单的calculator作为示例。在我的新语法中,应该可以定义一个字符串,如下所示:

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;

到目前为止,我能够制作一个Lexer / Grammar,它可以切换模式并解析简单的字符串,它们是:

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检查以前的模式和安全弹出模式。 但是我希望我的理解是错误的,并且有某种方法可以将@RequestMapping(value = "/Upload", method = RequestMethod.POST) public String FileUpload(HttpServletRequest request, @RequestParam("fileUpload") MultipartFile[] fileUpload) throws Exception { } 符号在默认模式下视为运算符?

我找到了一些灵​​感来源,也许它们也可以为您提供帮助:

1 个答案:

答案 0 :(得分:1)

墨菲关于StackOverflow的定律:在将详细问题发布到SO几分钟后,您将找到自己问题的答案。

我应该创建一个单独的文件-DEFAULT_MODE,而不是切换到STRING_INTERPOLATION。这样,我必须为此模式定义单独的标记,这将允许在正常模式下使用%符号(并禁止在插值模式下使用)。

这是对我有用的Lexer和文法:

lexer grammar CalcLexer;

EQ: '=';
PLUS: '+';
MINUS: '-';
MULT: '*';
DIV: '/';
MOD: '%';

LPAREN : '(' ;
RPAREN : ')' ;

ID  : F_ID;
INT : F_INT;

fragment F_ID: [a-zA-Z]+ ;
fragment F_INT: [0-9]+ ;

OPEN_DOUBLE_QUOTE: '"' -> pushMode(STRING_MODE);

NEWLINE:'\r'? '\n' ;
WS  :   [ \t]+ -> skip;


mode STRING_MODE;
DOUBLE_PERCENT: '%%';
SINGLE_PERCENT: '%' -> pushMode(STRING_INTERPOLATION);
TEXT: ~('%'|'\n'|'"')+;


CLOSE_DOUBLE_QUOTE: '"' -> popMode;

mode STRING_INTERPOLATION;
SINGLE_PERCENT_POP: '%' -> popMode;

I_PLUS: PLUS -> type(PLUS);
I_MINUS: MINUS -> type(MINUS);
I_MULT: MULT -> type(MULT);
I_DIV: DIV -> type(DIV);
I_MOD: MOD -> type(MOD);

I_LPAREN: LPAREN -> type(LPAREN);
I_RPAREN: RPAREN -> type(RPAREN);

I_ID  : F_ID -> type(ID);
I_INT : F_INT -> type(INT);

WS1  :   [ \t]+ -> skip;

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|MOD) expr
    |   expr (PLUS|MINUS) expr
    |   INT
    |   ID
    |   LPAREN expr RPAREN
    ;

我希望这会对某人有所帮助。可能是我。