A new parsers frame in JavaScript
- 目标是能灵活简单任意扩展的做任何自定义语法分析
- 测试例子基本实现了
ES6
的语法分析, 基本解析结果和Esprima
没啥区别(SourceLocation
有点不一样)
- 由于使用的
hash
查找匹配,当前效率只有Esprima
的1/2
左右,到时候会将hash
大头映射为数组下标查找,应该性能可以高一截,不过还有其他事情要处理,现在主要用于测试,这个改了不利于调试延后在做
- Examples:
{
"BinaryExpression": {
//匹配 collector 描述的结果最终被收集到 handler 中处理或直接作为语法树的一部分
handler(context: Context) {
let [collected] = context;
collected.operator = collected.operator.value;
return collected;
},
//可在结果被收集前进行最后的验证或者从这里返回结果
validator(context: Context) {
return context[CONTEXT.right] - context[CONTEXT.left] >= 2
},
/*
两个相同优先级遵循先后顺序的左结合
需要右结合 `Right-associative` 的两个同级匹配可用 `new Number(precedence)`
依据:
extreme[MATCHED_RECORDS.precedence] > longest[MATCHED_RECORDS.precedence]
|| extreme[MATCHED_RECORDS.precedence] === Number(longest[MATCHED_RECORDS.precedence])
*/
precedence: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
//收集器
collector: [
{
left: EXPRESSION_OR_THROW_STRICT_RESERVED_WORDS_PATTERN,
operator: `Punctuator **`,
right: _Option(EXPRESSION_OR_VALIDATE_STRICT_RESERVED_WORDS_PATTERN)
},
["operator", `Punctuator * / %`],
["operator", `Punctuator + -`],
["operator", `Punctuator << >> >>>`],
["operator", _Or(`Punctuator < <= > >=`, `Keyword in instanceof`)],
["operator", `Punctuator == != === !==`],
["operator", `Punctuator &`],
["operator", `Punctuator ^`],
["operator", `Punctuator |`],
["operator", `Punctuator ??`]
]
},
"AwaitExpression": [
{
precedence: 17,
filter(context: Context) {
return context[CONTEXT.allowAwait];
},
collector: {
token: _NonCollecting("Keyword await"),
argument: EXPRESSION_OR_THROW_STRICT_RESERVED_WORDS_PATTERN
}
},
{
handler([collected, parser]: Context) {
return parser.parseIdentifier(collected.token);
},
filter(context: Context) {
return !context[CONTEXT.allowAwait];
},
collector: {
token: "Keyword await",
}
},
]
}
//用于多个地方的通用 pattern 可以在外部定义
const THROW_STRICT_RESERVED_WORDS_PATTERN = _Or(
"Identifier implements interface package private protected public static yield let"
).watch(
function (context: Context, token: Token) {
if (context[CONTEXT.strict]) {
context[CONTEXT.parser].err(token);
}
}
);
const IDENTIFIER_OR_THROW_STRICT_RESERVED_WORDS_PATTERN = _Or(
"Identifier", THROW_STRICT_RESERVED_WORDS_PATTERN
);
const EXPRESSION_OR_THROW_STRICT_RESERVED_WORDS_PATTERN = _Or(
"[Expression]", THROW_STRICT_RESERVED_WORDS_PATTERN
);
const IDENTIFIER_OR_VALIDATE_STRICT_RESERVED_WORDS_PATTERN = _Or("Identifier").watch(validateIdentifier);