具有位置选择的分析器组合器在AST中快速失败

时间:2013-09-12 18:37:18

标签: parsing parsec parser-combinators

我写了一些解析器组合器来构建一个带有源位置信息的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总是运行,无论身体是否成功:

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

预期行为

a一旦明确其body将失败,就会失败。

实际行为

对于“B”代币,locParser的第一个a运行,当body失败时,locParser运行b。嵌套和更多分支,这成为一个性能问题。

边缘情况

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

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

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

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

'D'节点的位置从'('开头'到''结尾')开始。这两种情况都由node正确处理。

问题

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

我更希望保持每个解析器都是自包含的并避免重复逻辑。此外,构建后不得修改节点。

0 个答案:

没有答案