AST原理解析

抽象语法树(AST)是源代码的抽象语法结构的树状表示,常用于webpack、eslint等工具进行代码检查和分析。文章介绍了从词法分析到语法分析的过程,展示了一个简单的函数转换为AST的例子,并详细阐述了词法分析生成tokens和语法分析构建树形结构的过程。通过AST,开发者可以高效地理解和操作代码。

什么是 AST

抽象语法树(Abstract Syntax Tree)简称 AST,是源代码的抽象语法结构的树状表现形式。webpack、eslint 等很多工具库的核心都是通过抽象语法书这个概念来实现对代码的检查、分析等操作。

// 简单函数
function square(n) {
    return n * n;
}
 
// 转换后的AST
{
   type: "FunctionDeclaration",
   id: {
       type: "Identifier",
       name: "square"
   },
   params: [
      {
           type: "Identifier",
           name: "n"
      }
   ],
   ...
}

第一步:词法分析,也叫扫描scanner

它读取我们的代码,然后把它们按照预定的规则合并成一个个的标识 tokens。同时,它会移除空白符、注释等。最后,整个代码将被分割进一个 tokens 列表(或者说一维数组)。

const a = 5;
// 转换成
[{value: 'const', type: 'keyword'}, {value: 'a', type: 'identifier'}, ...]

第二步:语法分析,也称解析器

它会将词法分析出来的数组转换成树形的形式,同时,验证语法。语法如果有错的话,抛出语法错误。

[{value: 'const', type: 'keyword'}, {value: 'a', type: 'identifier'}, ...]
// 语法分析后的树形形式
{
   type: "VariableDeclarator", 
   id: {
       type: "Identifier",
       name: "a"
   },
   ...
}

示例

function add(a, b) {
    return a + b
}

### 使用AST进行语法树解的技术概述 抽象语法树(Abstract Syntax Tree, AST)是一种用于表示程序代码结构的数据结构。它可以被用来分、修改和优化代码,广泛应用于编译器设计、静态代码分以及代码转换等领域。 #### 1. **JavaScript中的AST** 在JavaScript中,可以利用现有的库如`acorn`或`esprima`来生成AST[^1]。这些工具能够将JavaScript代码转化为一棵易于操作的树形结构。例如: ```javascript const acorn = require('acorn'); const code = 'let a = 10; let b = 20;'; const ast = acorn.parse(code, { ecmaVersion: 2020 }); console.log(JSON.stringify(ast, null, 2)); ``` 上述代码展示了如何使用`acorn`库解一段简单的JavaScript代码,并将其转为AST形式。 --- #### 2. **Java中的AST** 对于Java而言,可以通过自定义实现或者借助第三方库完成公式表达式的解[^3]。通常情况下,这种过程分为以下几个阶段: - **词法分**:由Lexer负责将输入字符串分解成标记序列。 - **语法分**:Parser接收来自Lexer的结果构建出最终的AST。 下面是一个简化版本的例子说明如何手动创建一个基本计算器应用: ```java public class ExpressionEvaluator { public static void main(String[] args) throws Exception { String expression = "3 + (5 * 7)"; double result = evaluate(expression); System.out.println(result); // 输出应为38.0 } private static double evaluate(String expr) { return new ShuntingYard().evaluate(expr).doubleValue(); } } ``` 此片段仅作为概念验证用途;实际生产环境需考虑更多边界条件与错误处理逻辑。 --- #### 3. **Golang中的AST** Go语言提供了强大的标准库支持开发者轻松访问源文件内部细节,包括但不限于声明语句、函数定义甚至是注解信息等内容[^4]。尽管官方文档提到过某些特定场景下可能无法提取全部类型的元数据(比如嵌套匿名字段),但这并不妨碍大多数常规需求下的正常使用体验。 以下是获取指定包内所有导出成员名称的一个简单例子: ```go package main import ( "go/ast" "go/parser" "go/token" "fmt" ) func main() { fset := token.NewFileSet() node, err := parser.ParseFile(fset, "./example.go", nil, parser.AllErrors) if err != nil { fmt.Println(err) return } for _, decl := range node.Decls { funcDecl, ok := decl.(*ast.FuncDecl) if !ok || funcDecl.Name.IsExported() == false{ continue; } fmt.Printf("Found exported function %s\n", funcDecl.Name.String()) } } ``` 该脚本读取名为 `example.go` 的本地文件并打印其中所有的公开方法名。 --- #### 总结 无论是在哪种编程环境下工作,掌握好相应平台所提供的API接口及其背后的工作原理都是至关重要的一步。以上分别介绍了几种主流开发框架里关于怎样运用抽象语法树来进行深层次探究的具体做法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭日东升、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值