jsx中antlr4解析templateLiteral
Antlr4 parsing templateLiteral in jsx
我尝试使用grammars-v4项目(https://github.com/antlr/grammars-v4/tree/master/javascript/jsx)中定义的语法来解析jsx文件。
当我解析下面的代码片段时,
let str =
`${dsName}${parameterStr ? `( ${parameterStr} )` : ""}${returns ? `{
${returns}}` : ""}`;
显示如下错误
line 2:32 at [@8,42:42='(',<8>,2:32]:no viable alternative at input '('
https://astexplorer.net/ 显示它是一个 TemplateLiteral,里面有 conditionalExpression,对解析这种语法有什么想法吗?
提前致谢。
编辑:
谢谢@Bart,它有效。
在下面的代码中运行良好。
const href1 = `https://example.com/lib/downloads_${page}.htm?joinSource=${joinSource}${inviter?`&inviter=${inviter}`: ''}`;
const href2 = `https://example.com/act/kol/detail_${this.props.values.list.res.rows && this.props.values.list.res.rows[0].id}_${page}.htm?joinSource=${joinSource}${inviter?`&inviter=${inviter}`: ''}`;
快速浏览一下 ANTLR 语法表明:
// TODO: `${`tmp`}`
TemplateStringLiteral: '`' ('\`' | ~'`')* '`'
所以,显然,它在“TODO 列表”上。允许嵌套的“`”字符串插值是令人惊讶的(至少可以说),并且对于 ANTLR Lexer 来说将是“非常重要的”(所以,我不会“屏住呼吸”等待修复)。
您尝试过吗:(将嵌套的“`”替换为“'s?)。
let str =
`${dsName}${parameterStr ? “( ${parameterStr} )” : ""}${returns ? “{
${returns}}” : ""}`;
根据 Mike 的观察,是模板字符串造成了混乱,这里有一个快速解决方案:
变化:
JavaScriptLexerBase.java
添加实例变量:
// Keeps track of the the current depth of nested template string backticks.
// E.g. after the X in:
//
// `${a ? `${X
//
// templateDepth will be 2. This variable is needed to determine if a `}` is a
// plain CloseBrace, or one that closes an expression inside a template string.
protected int templateDepth = 0;
JavaScriptLexer.g4
// Place TemplateCloseBrace above CloseBrace!
TemplateCloseBrace: {this.templateDepth > 0}? '}' -> popMode;
...
// Remove (or comment) TemplateStringLiteral
// TemplateStringLiteral: '`' ('\`' | ~'`')* '`';
BackTick
: '`' {this.templateDepth++;} -> pushMode(TEMPLATE)
;
...
// Place at the end of the file:
mode TEMPLATE;
BackTickInside
: '`' {this.templateDepth--;} -> type(BackTick), popMode
;
TemplateStringStartExpression
: '${' -> pushMode(DEFAULT_MODE)
;
TemplateStringAtom
: ~[`]
;
JavaScriptParser.g4
singleExpression
: ...
| singleExpression templateStringLiteral # TemplateStringExpression // ECMAScript 6
| ...
;
literal
: ...
| templateStringLiteral
| ...
;
templateStringLiteral
: BackTick templateStringAtom* BackTick
;
templateStringAtom
: TemplateStringAtom
| TemplateStringStartExpression singleExpression TemplateCloseBrace
;
我没有完全测试我的解决方案,但它成功解析了您的示例输入:
我尝试使用grammars-v4项目(https://github.com/antlr/grammars-v4/tree/master/javascript/jsx)中定义的语法来解析jsx文件。 当我解析下面的代码片段时,
let str =
`${dsName}${parameterStr ? `( ${parameterStr} )` : ""}${returns ? `{
${returns}}` : ""}`;
显示如下错误
line 2:32 at [@8,42:42='(',<8>,2:32]:no viable alternative at input '('
https://astexplorer.net/ 显示它是一个 TemplateLiteral,里面有 conditionalExpression,对解析这种语法有什么想法吗?
提前致谢。
编辑: 谢谢@Bart,它有效。
在下面的代码中运行良好。
const href1 = `https://example.com/lib/downloads_${page}.htm?joinSource=${joinSource}${inviter?`&inviter=${inviter}`: ''}`;
const href2 = `https://example.com/act/kol/detail_${this.props.values.list.res.rows && this.props.values.list.res.rows[0].id}_${page}.htm?joinSource=${joinSource}${inviter?`&inviter=${inviter}`: ''}`;
快速浏览一下 ANTLR 语法表明:
// TODO: `${`tmp`}`
TemplateStringLiteral: '`' ('\`' | ~'`')* '`'
所以,显然,它在“TODO 列表”上。允许嵌套的“`”字符串插值是令人惊讶的(至少可以说),并且对于 ANTLR Lexer 来说将是“非常重要的”(所以,我不会“屏住呼吸”等待修复)。
您尝试过吗:(将嵌套的“`”替换为“'s?)。
let str =
`${dsName}${parameterStr ? “( ${parameterStr} )” : ""}${returns ? “{
${returns}}” : ""}`;
根据 Mike 的观察,是模板字符串造成了混乱,这里有一个快速解决方案:
变化:
JavaScriptLexerBase.java
添加实例变量:
// Keeps track of the the current depth of nested template string backticks.
// E.g. after the X in:
//
// `${a ? `${X
//
// templateDepth will be 2. This variable is needed to determine if a `}` is a
// plain CloseBrace, or one that closes an expression inside a template string.
protected int templateDepth = 0;
JavaScriptLexer.g4
// Place TemplateCloseBrace above CloseBrace!
TemplateCloseBrace: {this.templateDepth > 0}? '}' -> popMode;
...
// Remove (or comment) TemplateStringLiteral
// TemplateStringLiteral: '`' ('\`' | ~'`')* '`';
BackTick
: '`' {this.templateDepth++;} -> pushMode(TEMPLATE)
;
...
// Place at the end of the file:
mode TEMPLATE;
BackTickInside
: '`' {this.templateDepth--;} -> type(BackTick), popMode
;
TemplateStringStartExpression
: '${' -> pushMode(DEFAULT_MODE)
;
TemplateStringAtom
: ~[`]
;
JavaScriptParser.g4
singleExpression
: ...
| singleExpression templateStringLiteral # TemplateStringExpression // ECMAScript 6
| ...
;
literal
: ...
| templateStringLiteral
| ...
;
templateStringLiteral
: BackTick templateStringAtom* BackTick
;
templateStringAtom
: TemplateStringAtom
| TemplateStringStartExpression singleExpression TemplateCloseBrace
;
我没有完全测试我的解决方案,但它成功解析了您的示例输入: