写一个整数四则运算的解析器——语法分析部分

构建AST

1. 先用BNF定义3个语法

运算表达式
<Expression> ::= <AddExpression><EOF>
加法表达式
<AddExpression> ::= <MultipleExpression> | <AddExpression><+><MultiplicativeExpression> | <AddExpression><-><MultiplicativeExpression>
乘法表达式
<MultipleExpression> ::= <Number> | <MultipleExpression><*><Number> | <MultipleExpression></><Number>

2.按照定义的语法来编写解析函数

function expression(source) {
    // source[0]位置尽可能多地聚合出一个AddExpression
    addExpression(source)
    // 符合Expression语法定义
    if (source[0].type === 'AddExpression' && source[1] && source[1].type === 'EOF') {
        let node = {
            type: "Expression",
            children: [source.shift(), source.shift()]
        }
        source.unshift(node)
    }
    // 出口,如果第0项不是Expression,则是抽象语法树解析错误
    if (source[0].type === 'Expression') {
        return source[0]
    } else {
        throw new Error('解析AST不正确')
    }
}

function addExpression(source) {
    // MultipleExpression --> AddExpression
    if (source[0].type === 'MultipleExpression') {
        let node = {
            type: "AddExpression",
            children: [source[0]]
        }
        source.shift();
        source.unshift(node)
        // 继续递归,寻求合并
        return addExpression(source);
    }
    // AddExpression聚合
    if (source[0].type === 'AddExpression' && source[1] && (source[1].type === '+' || source[1].type === '-')) {
        let node = {
            type: "AddExpression",
            children: [source.shift(), source.shift()]
        }
        multipleExpression(source)
        node.children.push(source.shift())
        source.unshift(node)
        // 继续递归,寻求合并
        return addExpression(source);
    }
    // source[0]位置尽可能多地聚合出一个MultipleExpression
    multipleExpression(source)
    // 递归出口,如果第0项不是AddExpression,则一直递归自己
    if (source[0].type === 'AddExpression') {
        return source
    }
    // 递归自己
    return addExpression(source)
}

function multipleExpression(source) {
   // number --> MultipleExpression
    if (source[0].type === 'number') {
        let node = {
            type: "MultipleExpression",
            children: [source[0]]
        }
        source.shift();
        source.unshift(node)
        // 继续递归,寻求合并
        return multipleExpression(source);
    }
   // MultipleExpression聚合
    if (source[0].type === 'MultipleExpression' && source[1] && (source[1].type === '*' || source[1].type === '/')) {
        let node = {
            type: "MultipleExpression",
            children: [source.shift(), source.shift()]
        }
        node.children.push(source.shift())
        source.unshift(node)
        // 继续递归,寻求合并
        return multipleExpression(source);
    }
    // 递归出口,如果第0项不是MultipleExpression,则一直递归自己
    if (source[0].type === 'MultipleExpression') {
        return source
    }
}

3.

猜你喜欢

转载自www.cnblogs.com/amiezhang/p/11070618.html
今日推荐