我有一种使用模式进行字符串插值的语法:大致如下:
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;
parser grammar ExampleParser;
options {tokenVocab = Example;}
test: string* EOF;
string: OPEN_STRING string_part* CLOSE_STRING;
string_part: TEXT | ID_INTERPOLATION | OPEN_EXPR_INTERPOLATION expr RBRACE;
//more rules that use LBRACE and RBRACE
现在这工作和标记一切主要是我想要的,但它确实有2个缺陷。
我的IDE仅基于令牌突出显示,所以这是一个问题,我希望能够以不同的方式突出显示它们。所以基本上我想要一个解决方案,当RBRACE在字符串中时,它将成为不同的令牌。
我更喜欢不使用语义谓词,因为我不想把它束缚在一种语言上,但如果需要的话,我可以接受,我可能需要更多的解释,因为我没有太多使用它们。
因此,我着手实现一个内插字符串解析器,只使用ANTLR代码(不使用宿主语言代码块)。我发现这很有效,包括嵌套插值字符串。。。
lexer grammar Lexer;
LeftBrace: '{';
RightBrace: '}' -> popMode;
Backtick: '`' -> pushMode(InterpolatedString);
Integer: [0-9]+;
Plus: '+';
mode InterpolatedString;
EscapedLeftBrace: '\\{' -> type(Grapheme);
EscapedBacktick: '\\`' -> type(Grapheme);
ExprStart: '{' -> type(LeftBrace), pushMode(DEFAULT_MODE);
End: '`' -> type(Backtick), popMode;
Grapheme: ~('{' | '`');
parser grammar Parser;
options {
tokenVocab = Lexer;
}
startRule: expression EOF;
interpolatedString: Backtick (Grapheme | interpolatedStringExpression)* Backtick;
interpolatedStringExpression: LeftBrace expression RightBrace;
expression
: expression Plus expression
| atom
;
atom: Integer | interpolatedString;
您可以使用输入进行测试
`{`{`{`{`{`{`{`hello world`}`}`}`}`}`}`}`
感谢@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;
我知道在特定情况下更改令牌类型是非常粗鲁的,但它为我完成了工作,所以我会保留它,除非我找到一种不那么粗鲁的方法来做到这一点。
在普通字符串中,我可以用反斜杠转义: 在字符串文字中有可能做同样的事情吗?反斜杠不再是转义字符: 到目前为止,我看到的唯一解决方案是字符串连接,这非常难看,以及嵌套插值,这开始变得有点可笑:
null null 以下是我的(不完整和不成功的)尝试: 如果不能在lexer中解决这个问题,我可以使用标记、、、、、和自行编写解析器规则。
如果在antlr4 lexer中有一个ONELINE_STRING片段规则标识一行上的一个简单引号字符串,那么如何在lexer中创建一个更通用的字符串规则,该规则将相邻的ONELINE_STRING连接起来(即,只要它们都在不同的行上开始,仅用空格和/或注释分隔)? 即, 将被解析为两个字符串标记,“foo”后跟“bar” 同时: 示例1: Sample3(注意,'output'是该语言中的关键字
问题 你想创建一个字符串,让它包含体现某个 CoffeeScript 变量的文本。 解决方案 使用 CoffeeScript 中类似 Ruby 的字符串插值,而不是 JavaScript 的字符串拼接。 插值: muppet = "Beeker" favorite = "My favorite muppet is #{muppet}!" # => "My favorite muppet is B
我正在尝试编写一个ANTLR语法,用于解析字符串插值表达式,例如: 我得到的错误是: MyParser。g4: MyLemus. g4: 像以下这样的表达式可以正常工作: 知道我做错了什么吗?