0

我编写了一些解析器组合器来构建带有源位置信息的 AST。分析表明,至少 30% 的执行时间用于重复解析不必要的信息以生成源位置数据。我需要帮助找到一种替代方法来提高性能。

问题

假设我正在解析一种只包含两个标记的语言:“A”和“B”。为了生成 AST 节点,我目前定义了一个组合器来提取位置并构建节点:

// Parse body and build resulting node from function
// nodeFactory called with position and result from body.
var node = function(body, nodeFactory) {
    return bind(
        locParser, // get the current location in the token stream
        body,
        prevEnd, // get the previous end position in the token stream
        function(o, x, c) {
            return always(f(Location(o, c), x));
        });
};

var a = node(char('A'), buildNodeA);
var b = node(char('B'), buildNodeB);

这种方法的问题是,locParser无论 body 是否成功,它总是运行:

var element = either(a, b);
var program = many(element);
run(program, "AAABBA");

预期行为

a一旦很明显它会失败,它body就会失败。

实际行为

对于“B”令牌,首先运行locParserfor ,失败时运行for 。随着嵌套和更多的分支,这成为一个性能问题。abodylocParserb

边缘案例

该位置包含整个消费输入范围:

var c = node(next(char(' '), char('C')), buildNodeC);

“C”节点的位置从空格字符的开头开始。

var d = node(between(char('('), char(')'), char('D')), buildNodeD);

“D”节点的位置从“(”的开头开始,到“)”的结尾结束。这两种情况都由node.

问题

如何重构这些解析器以快速失败但仍访问正确的位置数据?

我宁愿让每个解析器都相当独立,避免重复逻辑。此外,节点不得在施工后修改。

4

0 回答 0