首页 > 解决方案 > 如何使用 Javascript 将字符串转换为 AST 对象?

问题描述

我需要将字符串转换为遵守特定语法规则的对象(类似 AST)。

我基本上有 3 种类型的表达式 ( '@', '$' and '#')。'#' 类型的表达式写成,#something而其他两个写成@something==somethingelseand $something==somethingelse

可以使用连词 ( ) 对这些表达式进行分组'and', 'or',并且可以使用括号修改运算顺序。

下面是一个完整表达式的示例:

const expression = 
     `#buy
      && (@car == white || @bike == blue)
      && $user==authenticated`;

我正在寻找一种使用javascript或基于javascript的工具(将在React项目中使用)将其转换为对象(类似AST)的方法。

const ast = {
    type: 'expression',
    conjunction: 'null',
    expressions: [{
            type: 'expression',
            conjunction: null,
            expressions: [{
                type: '#',
                left: 'buy',
                operator: null,
                right: null
            }]
        },
        {
            type: 'expression',
            conjunction: '&&',
            expressions: [{
                    type: 'expression',
                    conjunction: 'null',
                    expressions: [{
                        type: '@',
                        left: 'car',
                        operator: '==',
                        right: 'white'
                    }]
                },
                {
                    type: 'expression',
                    conjunction: '||',
                    expressions: [{
                        type: '@',
                        left: 'bike',
                        operator: '==',
                        right: 'blue'
                    }]
                }
            ]
        },
        {
            type: 'expression',
            conjunction: '&&',
            expressions: [{
                type: '$',
                left: 'user',
                operator: '==',
                right: 'authenticaded'
            }]
        }
    ]
};

标签: javascriptparsingcompiler-constructionabstract-syntax-tree

解决方案


虽然会有特定于您的情况的细微差别,虽然听起来很明显,但它可能有助于将问题分解为更易于管理的部分。

这个问题的一大块将是你的表达式字符串的解析和随后的标记化。首先编写一些代码,这些代码可以接受类似的字符串#something并将其转换为中间数据结构,以后可以利用该结构来执行与构建 AST 相关的更具体的任务。这个想法是您希望将最简单的可能工作的东西包装到一个黑盒中,使您能够以增量和可靠的方式改进/更改/添加功能。一开始尽量不要过度设计,只添加与当前手头任务相关的功能,以避免陷入分析瘫痪陷阱。

一旦您在标记化步骤上进行了一些迭代,您就可以开始考虑下一个阶段,即为您的 AST 实现访问者/步行者。我有信心说您的设计随着您完成此过程而发展,因此设计您的代码以进行更改至关重要 - 这应该包括可测试性作为主要考虑因素。

虽然它不是 javascript,但这个基于 C#/Roslyn 的项目(完全披露:我是该存储库的作者/维护者)非常接近地展示了您所询问的功能类型。高温高压


推荐阅读