Antlr4中的字符串插值
我有一个使用模式进行字符串插值的语法: 大致如下:Antlr4中的字符串插值,antlr,antlr4,Antlr,Antlr4,我有一个使用模式进行字符串插值的语法: 大致如下: lexer grammar Example; //default mode tokens LBRACE: '{' -> pushMode(DEFAULT_MODE); RBRACE: '}' -> popMode; OPEN_STRING: '"' -> pushMode(STRING); mode STRING; ID_INTERPOLATION: '$' IDEN; OPEN_EXPR_INTERPOLATION: '
lexer grammar Example;
//default mode tokens
LBRACE: '{' -> pushMode(DEFAULT_MODE);
RBRACE: '}' -> popMode;
OPEN_STRING: '"' -> pushMode(STRING);
mode STRING;
ID_INTERPOLATION: '$' IDEN;
OPEN_EXPR_INTERPOLATION: '${' -> pushMode(DEFAULT_MODE);
TEXT: '$' | (~[$\r\n])+;
CLOSE_STRING: '"' -> popMode;
现在,它可以正常工作,并以我想要的方式标记所有内容,但它确实有两个缺陷
我宁愿不使用语义谓词,因为我不想把它束缚在一种语言上,但如果需要的话,我可以接受,我可能需要更多的解释,因为我没有太多地使用它们。谢谢@sepp2k帮助我解决我的问题 这是一个有点黑客,但它正是我所需要的 我通过将RBRACE上的popMode更改为以下方式解决了此问题:
RBRACE: '}' {
if(_modeStack.size() > 0) {
popMode();
if(_mode != DEFAULT_MODE) {
setType(EXPR_INTERPOLATION);
}
}
};
我还将解析器更改为
string_part: TEXT | ID_INTERPOLATION | EXPR_INTERPOLATION expr EXPR_INTERPOLATION;
我知道在特定情况下更改标记类型是非常困难的,但它为我完成了任务,因此我将保留它,除非我找到一种不太麻烦的方法来完成此操作。
用于关闭块和关闭插值的标记是相同的
:我不明白,我看到两个不同的字符被用来“关闭”东西:“
和}
另外,为什么要使用LBRACE:'{'->pushMode(默认模式)
和RBRACE:'}'->popMode代码>是否存在(即模式推送和弹出)?或者你是否试图过多地简化问题?在这种情况下,请编辑你的问题,使之更接近你原来的语法。我指的是一条规则,我没有包含在这段代码中,我确实简化了一点,我使用LBRACE推送模式的原因是RBRACE使用的每个其他位置都与LBRACE结合,所以我不想意外地弹出最外层的模式。我想区分每次使用RBRACE(当它用于封装代码位时)和每次使用它进行插值时。因此,当返回到字符串模式时,将匹配不同的标记。我正在弹出RBRACE,这样当您完成插值后,它将返回到字符串模式,因此您可以说:“x+1=${x+1}”
我想让Bart困惑的是您似乎忘记了->pushMode(默认模式)
在OPEN\u EXPR\u INTERPOLATION
规则中。无论如何,我相信通过添加跟踪嵌套的{}
s的操作,您可以得到想要的。类似于,但您希望使用堆栈而不仅仅是计数器来跟踪何时弹出{}
和何时弹出${}
,以便可以适当地更改令牌类型。
string_part: TEXT | ID_INTERPOLATION | EXPR_INTERPOLATION expr EXPR_INTERPOLATION;