我想为自定义语言创建一个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 {
}
符号在默认模式下视为运算符?
我找到了一些灵感来源,也许它们也可以为您提供帮助:
答案 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
;
我希望这会对某人有所帮助。可能是我。