SOURCE

/** 
 *   [
 *     { type: 'paren',  value: '('        },
 *     { type: 'name',   value: 'add'      },
 *     { type: 'number', value: '2'        },
 *     { type: 'paren',  value: '('        },
 *     { type: 'name',   value: 'subtract' },
 *     { type: 'number', value: '4'        },
 *     { type: 'number', value: '2'        },
 *     { type: 'paren',  value: ')'        },
 *     { type: 'paren',  value: ')'        },
 *   ]
 *
 * And an Abstract Syntax Tree (AST) might look like this:
 *
 *   {
 *     type: 'Program',
 *     body: [{
 *       type: 'CallExpression',
 *       name: 'add',
 *       params: [{
 *         type: 'NumberLiteral',
 *         value: '2',
 *       }, {
 *         type: 'CallExpression',
 *         name: 'subtract',
 *         params: [{
 *           type: 'NumberLiteral',
 *           value: '4',
 *         }, {
 *           type: 'NumberLiteral',
 *           value: '2',
 *         }]
 *       }]
 *     }]
 *   }
 */

function parser(tokens){
    let current = 0
    function walk(){
        let token = tokens[current]
        if(token.type==='number'){
            current++
            return {
                type: 'NumberLiteral',
                value:token.value,
            }
        }

        if(token.type==='string'){
            current++
            return {
                type: 'StringLiteral',
                value:token.value,
            }
        }
        if(token.type==='paren' && token.value==="("){
            token = tokens[++current] //add
            const node = {
                type: 'CallExpression',
                name: token.value,
                params: []
            }

            token = tokens[++current] //num || (

            while((token.type!=="paren") || (token.type==='paren' && token.value!==")")){
                node.params.push(walk()) // current add 4
                token = tokens[current];// 递归结束,此时current往前推进,所以要重新赋值token,来继续while判断
            }
            current++
            return node
        }
    }
    const ast = {
        type:'Program',
        body:[]
    }
    
    ast.body.push(walk())
    console.log(ast)
}

const tokens = [
      { type: 'paren',  value: '('        },
      { type: 'name',   value: 'add'      },
      { type: 'number', value: '2'        },
      { type: 'paren',  value: '('        },
      { type: 'name',   value: 'subtract' },
      { type: 'number', value: '4'        },
      { type: 'number', value: '2'        },
      { type: 'paren',  value: ')'        },
      { type: 'paren',  value: ')'        },
    ]
parser(tokens)
console 命令行工具 X clear

                    
>
console