当前位置: 首页 > news >正文

go ast语义分析实现指标计算器

什么是AST

首先我们要知道AST是什么(Abstract Syntax Tree,AST),简称为语法树,是go语言源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。

上demo代码

func main() {expr, _ := parser.ParseExpr("1 + 2 * (3 + 4) + 3 * 4.1")ast.Print(token.NewFileSet(), expr)
}
// 输出结果
0  *ast.BinaryExpr {
1  .  X: *ast.BinaryExpr {
2  .  .  X: *ast.BasicLit {
3  .  .  .  ValuePos: -
4  .  .  .  Kind: INT
5  .  .  .  Value: "1"
6  .  .  }
7  .  .  OpPos: -
8  .  .  Op: +
9  .  .  Y: *ast.BinaryExpr {
10  .  .  .  X: *ast.BasicLit {
11  .  .  .  .  ValuePos: -
12  .  .  .  .  Kind: INT
13  .  .  .  .  Value: "2"
14  .  .  .  }
15  .  .  .  OpPos: -
16  .  .  .  Op: *
17  .  .  .  Y: *ast.ParenExpr {
18  .  .  .  .  Lparen: -
19  .  .  .  .  X: *ast.BinaryExpr {
20  .  .  .  .  .  X: *ast.BasicLit {
21  .  .  .  .  .  .  ValuePos: -
22  .  .  .  .  .  .  Kind: INT
23  .  .  .  .  .  .  Value: "3"
24  .  .  .  .  .  }
25  .  .  .  .  .  OpPos: -
26  .  .  .  .  .  Op: +
27  .  .  .  .  .  Y: *ast.BasicLit {
28  .  .  .  .  .  .  ValuePos: -
29  .  .  .  .  .  .  Kind: INT
30  .  .  .  .  .  .  Value: "4"
31  .  .  .  .  .  }
32  .  .  .  .  }
33  .  .  .  .  Rparen: -
34  .  .  .  }
35  .  .  }
36  .  }
37  .  OpPos: -
38  .  Op: +
39  .  Y: *ast.BinaryExpr {
40  .  .  X: *ast.BasicLit {
41  .  .  .  ValuePos: -
42  .  .  .  Kind: INT
43  .  .  .  Value: "3"
44  .  .  }
45  .  .  OpPos: -
46  .  .  Op: *
47  .  .  Y: *ast.BasicLit {
48  .  .  .  ValuePos: -
49  .  .  .  Kind: FLOAT
50  .  .  .  Value: "4.1"
51  .  .  }
52  .  }
53  }

我们通过上面的代码输出了一砣子非常复杂的结构体,那么我们来看看这些都是些上面东西。
我们来看看源码

	// A BinaryExpr node represents a binary expression.type BinaryExpr struct {X     Expr        // left operandOpPos token.Pos   // position of OpOp    token.Token // operatorY     Expr        // right operand}

我们通过这个结构体就可以看出来X和Y分别是两个值,Op是存储的我们的操作符号,OpPos 代表操作符在表达式中的偏移,这里的 Op 类型是token.Token,实际上是个枚举值。


// The list of tokens.
const (// Special tokensILLEGAL Token = iotaEOFCOMMENTliteral_beg// Identifiers and basic type literals// (these tokens stand for classes of literals)IDENT  // mainINT    // 12345FLOAT  // 123.45IMAG   // 123.45iCHAR   // 'a'STRING // "abc"literal_endoperator_beg// Operators and delimitersADD // +SUB // -MUL // *QUO // /REM // %AND     // &OR      // |XOR     // ^SHL     // <<SHR     // >>AND_NOT // &^ADD_ASSIGN // +=SUB_ASSIGN // -=MUL_ASSIGN // *=QUO_ASSIGN // /=REM_ASSIGN // %=AND_ASSIGN     // &=OR_ASSIGN      // |=XOR_ASSIGN     // ^=SHL_ASSIGN     // <<=SHR_ASSIGN     // >>=AND_NOT_ASSIGN // &^=LAND  // &&LOR   // ||ARROW // <-INC   // ++DEC   // --EQL    // ==LSS    // <GTR    // >ASSIGN // =NOT    // !NEQ      // !=LEQ      // <=GEQ      // >=DEFINE   // :=ELLIPSIS // ...LPAREN // (LBRACK // [LBRACE // {COMMA  // ,PERIOD // .RPAREN    // )RBRACK    // ]RBRACE    // }SEMICOLON // ;COLON     // :operator_endkeyword_beg// KeywordsBREAKCASECHANCONSTCONTINUEDEFAULTDEFERELSEFALLTHROUGHFORFUNCGOGOTOIFIMPORTINTERFACEMAPPACKAGERANGERETURNSELECTSTRUCTSWITCHTYPEVARkeyword_endadditional_beg// additional tokens, handled in an ad-hoc mannerTILDEadditional_end
)

那么token 连存储的就是这些, 他会根据我们输入的表达式,给去OpPos解析匹配这些符号。
请添加图片描述
我们可以从上图可以看出ast 代码树,因为表达式中有() ,我们发现了一个新的结构体ParenExpr ,我们查看源码,发现这个结构体是专门用于计算时如果有()时使用的。我们通过该树就可以看出来计算的先后顺序,就完美的完成了一个计算器功能。

	// A ParenExpr node represents a parenthesized expression.type ParenExpr struct {Lparen token.Pos // position of "("X      Expr      // parenthesized expressionRparen token.Pos // position of ")"}

我们了解了ast代码树以后,我们就可以借助该解析代码树做很多东西,例如我们可以做一个计算器。


type AstParser struct {ExpStr string
}func NewAstParser(expStr string) *AstParser {return &AstParser{ExpStr: expStr}
}func (a *AstParser) Parse() (float64, error) {expr, err := parser.ParseExpr(a.ExpStr)if err != nil {return 0, err}val, err := a.Eval(expr)if err != nil {return 0, err}return val, nil
}func (a *AstParser) Eval(expr ast.Expr) (float64, error) {switch e := expr.(type) {case *ast.BinaryExpr:return a.EvalBinaryExpr(e)case *ast.ParenExpr:return a.Eval(e.X)case *ast.BasicLit:switch e.Kind {case token.INT, token.FLOAT:i, err := strconv.ParseFloat(e.Value, 64)if err != nil {return 0, err}return i, nil}}return 0, nil
}func (a *AstParser) EvalBinaryExpr(e *ast.BinaryExpr) (float64, error) {left, err := a.Eval(e.X)if err != nil {return 0, err}right, err := a.Eval(e.Y)if err != nil {return 0, err}switch e.Op {case token.ADD:return left + right, nilcase token.SUB:return left - right, nilcase token.MUL:return left * right, nilcase token.QUO:return left / right, nil}return 0.0, nil
}

总结:
我们了解了ast代码树后,利用它可以做成一个非常简单的规则引擎。
其实利用 ast 包还可以做更多有意思的事情。例如将文件转成proto,或者解析sql语句并做一些审计等等

相关文章:

go ast语义分析实现指标计算器

什么是AST 首先我们要知道AST是什么&#xff08;Abstract Syntax Tree&#xff0c;AST&#xff09;&#xff0c;简称为语法树&#xff0c;是go语言源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构&#xff0c;树上的每个节点都表示源代码中的一种结构。 …...

【Vue】组件间传参与方法调用

【前言】 … 【目标】 1 了解组件间传参 2 组件间自定义事件绑定与解绑 3 组件的事件总线 4 消息订阅与发布 一 组件间传参 1 props 引入并使用组件:传递参数 <template><div id="app"><HelloWorld :msg="msg" :name="name" …...

类和对象2

三、C对象模型和this指针 3.1 成员变量和成员函数分开存储 在C中&#xff0c;类内的成员变量和成员函数分开存储&#xff0c;只有非静态成员变量才属于类的对象上 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <string.h> using namespace …...

Linux系统命令traceroute详解(语法、选项、原理和实例)

目录 一、traceroute概述 二、语法 1、基本语法 2、命令选项 三、帮助信息 四、示例 1. 使用默认模式&#xff08;ICMP Echo&#xff09;追踪到目标主机 2. 使用UDP模式&#xff08;需要root权限&#xff09;追踪到目标主机 3. 不解析IP地址为主机名&#xff0c;直接显…...

中兴通讯助力中国移动,推动SPN AI节能技术于23省规模部署

SPN作为中国移动自主创新的新一代综合承载网络&#xff0c;相比PTN设备&#xff0c;SPN的单机容量及性能有大幅提升&#xff0c;整机功耗也相应变大。在当前国家双碳政策的目标下&#xff0c;SPN设备的节能降耗也日益成为中国移动关注的焦点。因此&#xff0c;中国移动选择与中…...

SQL Server--死锁

今天&#xff0c;客户反应打不开xxx页面了。好家伙肯定锁表了。。。。。 只能先吧死锁进程先kill掉&#xff0c;不能耽误客户生产环境运行。。。。。 一定要看看是那张表发生了死锁 1、查询死锁语句 select dbid,* from sys.sysprocesses where 11 and spid >50 and blo…...

中科蓝讯AB32VG1中文寄存器说明GPIO端口操作

1 GPIO管理 1.1 GPIO通用控制寄存器 寄存器 1- 1 GPIOA&#xff1a;端口 A 数据寄存器 位寄存器名模式缺省描述31:8---未使用7:0GPIOA写0x00PAx 数据。当 PAx 用作 GPIO 时有效 0&#xff1a;读取时PAx为输入低电平状态&#xff0c;写入时PAx为输出低电平; 1&#xff1a;PAx…...

如何查看热门GPT应用?

1、登陆chatgpt 2、访问 https://chatgpt.com/gpts 3、在该界面&#xff0c;可以搜索并使用image generator, Write For Me&#xff0c;Language Teature等热门应用。...

C++中的各种定义

文章目录 前言一、1、unsigned2、_countof、sizeof 总结 前言 一、 1、unsigned 在C语言中&#xff0c;"unsigned"是一个数据类型修饰符&#xff0c;用于修饰整数类型&#xff0c;表示该类型的变量只能存储非负整数&#xff0c;即无符号整数。它可以应用于char、s…...

Java面向对象-常用类(日期时间类)

常用类-日期时间类 Date&#xff08;java.util.Date&#xff09; – 日期类 SimpleDateFormat – 格式化日期类 Calendar – 日历类 1 Date类 java.util.Date类表示特定的瞬间&#xff0c;精确到毫秒。 package com.qf.datetime;import java.util.Date;public class Test01 {…...

Shell环境变量深入:自定义系统环境变量

Shell环境变量深入&#xff1a;自定义系统环境变量 目标 能够自定义系统级环境变量 全局配置文件/etc/profile应用场景 当前用户进入Shell环境初始化的时候会加载全局配置文件/etc/profile里面的环境变量, 供给所有Shell程序使用 以后只要是所有Shell程序或命令使用的变量…...

【C++课程学习】:命名空间的理解(图文详解)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f4f7;1.命名冲突 &#x1f4f7;2.重定义 &#x1f4f7;3.命名空间 &#x1f37a;命名空间可…...

鸿蒙ArkUI-X平台差异化:【运行态差异化(@ohos.deviceInfo)】

平台差异化 简介 跨平台使用场景是一套ArkTS代码运行在多个终端设备上&#xff0c;如Android、iOS、OpenHarmony&#xff08;含基于OpenHarmony发行的商业版&#xff0c;如HarmonyOS Next&#xff09;。当不同平台业务逻辑不同&#xff0c;或使用了不支持跨平台的API&#xf…...

蓝牙Mesh模块组网时无线回程影响速率吗?

随着科技的发展&#xff0c;智能家居、智能办公等场景越来越广泛地应用于我们的生活。其中&#xff0c;蓝牙Mesh组网技术作为一种新型的无线通信技术&#xff0c;受到了越来越多用户的关注。那么&#xff0c;蓝牙Mesh模块在组网时无线回程过程中是否会影响速率呢&#xff1f;本…...

将3D检测的box框投影到BEV图片上

前言 点云数据作为一种丰富的三维空间信息表达方式&#xff0c;通常用于自动驾驶、机器人导航和三维建模等领域。然而&#xff0c;点云数据的直观性不如二维图像&#xff0c;这限制了它在一些需要快速视觉反馈的应用场景中的使用。本文将探讨如何将点云数据转换为二维图像&…...

Flutter 中的 ClipOval 小部件:全面指南

Flutter 中的 ClipOval 小部件&#xff1a;全面指南 在Flutter的丰富布局库中&#xff0c;ClipOval是一个用于裁剪子组件的显示区域为椭圆形或圆形的小部件。这种裁剪效果可以用于创建头像、图标或其他图形元素的美观边框。本文将提供ClipOval的全面指南&#xff0c;帮助你了解…...

ubuntu 硬盘转移

我插了两个 文件系统&#xff1a; ubuntu 硬盘转移&#xff1a; sudo dd if/dev/sdX1 of/dev/sdY1 bs128K convnoerror,sync statusprogressdd 的意思是DiskToDisk&#xff0c;if 是输入文件系统&#xff0c;of是输出文件系统。 bs是每次传递的数据大小。 注意&#xff1a;接…...

three.js中使用CameraHelper来可视化调整阴影相机的范围

1. three.js中使用CameraHelper来可视化调整阴影相机的范围 光源 const directionLight new THREE.DirectionalLight(0xffffff, 1); directionLight.position.set(100, 60, 20); directionLight.castShadow true; scene.add(directionLight);设置计算阴影的范围 direction…...

Golang发送GET请求并设置查询参数

服务端 package mainimport ("encoding/json""net/http""zdpgo_chi""zdpgo_chi/middleware" )func main() {r : zdpgo_chi.NewRouter()r.Use(middleware.RequestID)r.Use(middleware.RealIP)r.Use(middleware.Logger)r.Use(middlewar…...

c++笔记3

优先队列 普通的队列是一种先进先出的数据结构&#xff0c;元素在队列尾追加&#xff0c;而从队列头删除。优先队列是一种按照优先级决定出队顺序的数据结构&#xff0c;优先队列中的每个元素被赋予级别&#xff0c;队首元素的优先级最高。 例如&#xff1a;4入队&#xff0c…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

android 之 KeyguardService

一、功能定位与核心作用 KeyguardService 是 Android 锁屏功能的核心服务&#xff0c;负责管理设备锁屏界面&#xff08;如密码、图案、指纹等验证流程&#xff09;&#xff0c;并协调系统安全策略与用户交互。主要职责包括&#xff1a; 锁屏状态管理 控制锁屏界面的显示/隐藏…...