我正在尝试更新遵循以下规范的 ANTLR 语法
https://github.com/facebook/graphql/pull/327/files
用逻辑术语来说,它的定义为
StringValue ::
- `"` StringCharacter* `"`
- `"""` MultiLineStringCharacter* `"""`
StringCharacter ::
- SourceCharacter but not `"` or \ or LineTerminator
- \u EscapedUnicode
- \ EscapedCharacter
MultiLineStringCharacter ::
- SourceCharacter but not `"""` or `\"""`
- `\"""`
(以上不符合逻辑 - 不是 ANTLR 语法)
我在 ANTRL 4 中尝试了以下操作,但它无法识别三重引号字符串中的超过 1 个字符
string : triplequotedstring | StringValue ;
triplequotedstring: '"""' triplequotedstringpart? '"""';
triplequotedstringpart : EscapedTripleQuote* | SourceCharacter*;
EscapedTripleQuote : '\\"""';
SourceCharacter :[\u0009\u000A\u000D\u0020-\uFFFF];
StringValue: '"' (~(["\\\n\r\u2028\u2029])|EscapedChar)* '"';
使用这些规则,它将识别 '"""a"""' 但一旦我添加更多字符,它就会失败
eg: '"""abc"""' 不会解析并且 ANTLR 的 IntelliJ 插件说
line 1:14 extraneous input 'abc' expecting {'"""', '\\"""', SourceCharacter}
如何在 ANTLR 中使用 '\"""' 转义来处理三重引号字符串?
您的一些解析器规则实际上应该是词法分析器规则。
SourceCharacter
可能应该是 fragment
。
此外,您可能需要
EscapedTripleQuote* | SourceCharacter*
,而不是 ( EscapedTripleQuote | SourceCharacter )*
。第一个匹配 aaa...
或 bbb...
,而您可能想匹配 aababbba...
尝试这样的事情:
string
: Triplequotedstring
| StringValue
;
Triplequotedstring
: '"""' TriplequotedstringPart*? '"""'
;
StringValue
: '"' ( ~["\\\n\r\u2028\u2029] | EscapedChar )* '"'
;
// Fragments never become a token of their own: they are only used inside other lexer rules
fragment TriplequotedstringPart : EscapedTripleQuote | SourceCharacter;
fragment EscapedTripleQuote : '\\"""';
fragment SourceCharacter :[\u0009\u000A\u000D\u0020-\uFFFF];
三重引号字符串通常用于允许字符串中存在多行字符串和未转义字符。 假设您跳过空格和换行符,解析三重引号可能非常棘手,因为存在一些极端情况,例如:
为了解决上述问题,可以使用模式语法:
词法分析器:
START_TRIPLE_QUOTE: '"""' -> pushMode(INSIDE_TRIPLE_QUOTE);
mode INSIDE_TRIPLE_QUOTE;
TRIPLE_QUOTED_STRING_CONTENT : '"' '"'? ~["] // Match one or two quotes followed by a non-quote
| ~["] // Match any character that is not a quote
;
TRIPLE_QUOTE_END_2: '"""""' -> popMode;
TRIPLE_QUOTE_END_1: '""""' -> popMode;
TRIPLE_QUOTE_END_0: '"""' -> popMode;
解析器:
triple_string_literal: START_TRIPLE_QUOTE (TRIPLE_QUOTED_STRING_CONTENT)*
(TRIPLE_QUOTE_END_2
| TRIPLE_QUOTE_END_1
| TRIPLE_QUOTE_END_0);
在你的听众/访客中:
TripleQuotedStringConst(ctx.getText().substring(3, ctx.getText().length() - 3))
作为参考,这是我写的一篇文章:https://medium.com/@alexzerntev/parsing-multi-line-triple-quoted-strings-with-antlr4-ceca41cdeadb