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

Linux C编译器从零开发三

AST语法树

BNF抽象
expr       = equality
equality   = relational ("==" relational | "!=" relational)*
relational = add ("<" add | "<=" add | ">" add | ">=" add)*
add        = mul ("+" mul | "-" mul)*
mul        = unary ("*" unary | "/" unary)*
unary      = ("+" | "-")? primary
primary    = num | "(" expr ")"
AST构建
#include "chibicc.h"static Node *expr(Token **rest, Token *tok);
static Node *equality(Token **rest, Token *tok);
static Node *relational(Token **rest, Token *tok);
static Node *add(Token **rest, Token *tok);
static Node *mul(Token **rest, Token *tok);
static Node *unary(Token **rest, Token *tok);
static Node *primary(Token **rest, Token *tok);static Node *new_node(NodeKind kind) {Node *node = calloc(1, sizeof(Node));node->kind = kind;return node;
}static Node *new_binary(NodeKind kind, Node *lhs, Node *rhs) {Node *node = new_node(kind);node->lhs = lhs;node->rhs = rhs;return node;
}static Node *new_unary(NodeKind kind, Node *expr) {Node *node = new_node(kind);node->lhs = expr;return node;
}static Node *new_num(int val) {Node *node = new_node(ND_NUM);node->val = val;return node;
}// expr = equality
static Node *expr(Token **rest, Token *tok) {return equality(rest, tok);
}// equality = relational ("==" relational | "!=" relational)*
static Node *equality(Token **rest, Token *tok) {Node *node = relational(&tok, tok);for (;;) {if (equal(tok, "==")) {node = new_binary(ND_EQ, node, relational(&tok, tok->next));continue;}if (equal(tok, "!=")) {node = new_binary(ND_NE, node, relational(&tok, tok->next));continue;}*rest = tok;return node;}
}// relational = add ("<" add | "<=" add | ">" add | ">=" add)*
static Node *relational(Token **rest, Token *tok) {Node *node = add(&tok, tok);for (;;) {if (equal(tok, "<")) {node = new_binary(ND_LT, node, add(&tok, tok->next));continue;}if (equal(tok, "<=")) {node = new_binary(ND_LE, node, add(&tok, tok->next));continue;}if (equal(tok, ">")) {node = new_binary(ND_LT, add(&tok, tok->next), node);continue;}if (equal(tok, ">=")) {node = new_binary(ND_LE, add(&tok, tok->next), node);continue;}*rest = tok;return node;}
}// add = mul ("+" mul | "-" mul)*
static Node *add(Token **rest, Token *tok) {Node *node = mul(&tok, tok);for (;;) {if (equal(tok, "+")) {node = new_binary(ND_ADD, node, mul(&tok, tok->next));continue;}if (equal(tok, "-")) {node = new_binary(ND_SUB, node, mul(&tok, tok->next));continue;}*rest = tok;return node;}
}// mul = unary ("*" unary | "/" unary)*
static Node *mul(Token **rest, Token *tok) {Node *node = unary(&tok, tok);for (;;) {if (equal(tok, "*")) {node = new_binary(ND_MUL, node, unary(&tok, tok->next));continue;}if (equal(tok, "/")) {node = new_binary(ND_DIV, node, unary(&tok, tok->next));continue;}*rest = tok;return node;}
}// unary = ("+" | "-") unary
//       | primary
static Node *unary(Token **rest, Token *tok) {if (equal(tok, "+"))return unary(rest, tok->next);if (equal(tok, "-"))return new_unary(ND_NEG, unary(rest, tok->next));return primary(rest, tok);
}// primary = "(" expr ")" | num
static Node *primary(Token **rest, Token *tok) {if (equal(tok, "(")) {Node *node = expr(&tok, tok->next);*rest = skip(tok, ")");return node;}if (tok->kind == TK_NUM) {Node *node = new_num(tok->val);*rest = tok->next;return node;}error_tok(tok, "expected an expression");
}Node *parse(Token *tok) {Node *node = expr(&tok, tok);if (tok->kind != TK_EOF)error_tok(tok, "extra token");return node;
}
代码生成 
#include "chibicc.h"static int depth;static void push(void) {printf("  push %%rax\n");depth++;
}static void pop(char *arg) {printf("  pop %s\n", arg);depth--;
}static void gen_expr(Node *node) {switch (node->kind) {case ND_NUM:printf("  mov $%d, %%rax\n", node->val);return;case ND_NEG:gen_expr(node->lhs);printf("  neg %%rax\n");return;}gen_expr(node->rhs);push();gen_expr(node->lhs);pop("%rdi");switch (node->kind) {case ND_ADD:printf("  add %%rdi, %%rax\n");return;case ND_SUB:printf("  sub %%rdi, %%rax\n");return;case ND_MUL:printf("  imul %%rdi, %%rax\n");return;case ND_DIV:printf("  cqo\n");printf("  idiv %%rdi\n");return;case ND_EQ:case ND_NE:case ND_LT:case ND_LE:printf("  cmp %%rdi, %%rax\n");if (node->kind == ND_EQ)printf("  sete %%al\n");else if (node->kind == ND_NE)printf("  setne %%al\n");else if (node->kind == ND_LT)printf("  setl %%al\n");else if (node->kind == ND_LE)printf("  setle %%al\n");printf("  movzb %%al, %%rax\n");return;}error("invalid expression");
}void codegen(Node *node) {printf("  .globl main\n");printf("main:\n");gen_expr(node);printf("  ret\n");assert(depth == 0);
}
#include "chibicc.h"int main(int argc, char **argv) {if (argc != 2)error("%s: invalid number of arguments", argv[0]);Token *tok = tokenize(argv[1]);Node *node = parse(tok);codegen(node);return 0;
}
 ./chibicc "1 + -2* 3 -(4+5/6) > tmp.s
cc -o tmp tmp.s./tmpecho $?247

创作不易,小小的支持一下吧!

相关文章:

Linux C编译器从零开发三

AST语法树 BNF抽象 expr equality equality relational ("" relational | "!" relational)* relational add ("<" add | "<" add | ">" add | ">" add)* add mul ("" …...

02-ES6新语法

1. ES6 Proxy与Reflect 1.1 概述 Proxy 与 Reflect 是 ES6 为了操作对象引入的 API 。 Proxy 可以对目标对象的读取、函数调用等操作进行拦截&#xff0c;然后进行操作处理。它不直接操作对象&#xff0c;而是像代理模式&#xff0c;通过对象的代理对象进行操作&#xff0c;…...

Vue3中VueRouter基本用法及与Vue2中路由使用差异解析

Vue Router 在 Vue3 中被重写&#xff0c;使用了 Vue3 的 Composition API。使用上跟Vue2 相比有些不同&#xff0c;需要注意。 首先&#xff0c;让我们来看一下 Vue3 中 VueRouter 的基本使用方法&#xff1a; 安装 Vue Router&#xff1a; npm install vue-routernext创建…...

10.Docker Compose容器编排

文章目录 Compose简介安装和卸载步骤核心概念compose文件两要素 使用步骤Compose常用命令微服务测试本地编码打包编写Dockerfile文件构建镜像 不使用Compose调试使用Compose调试WordPress测试验证增量更新 Compose简介 ​ docker建议我们每一个容器中只运行一个服务,因为docke…...

【算法——动态规划(从dfs回溯开始推导dp)】

基础理论 递归&#xff1a; 递&#xff1a;大问题分解子问题的过程 &#xff1b; 归&#xff1a;产生答案 dp&#xff1a;只进行归&#xff1b;用已知的最底层的&#xff08;递归的边界&#xff0c;搜索树的底&#xff09;&#xff0c;推出未知 《视频索引》 一句话&…...

不是所有洗碗机都能空气除菌 友嘉灵晶空气除菌洗碗机评测

精致的三餐让你以为生活是“享受”&#xff0c;可饭后那些油腻的锅碗瓢盆却成了你我美好生活的最大障碍。想要只吃美食不洗碗&#xff0c;那一台优秀的洗碗机就必不可少了&#xff01;今天&#xff0c;ZOL中关村在线要评测的就是这样一台不光洗得干净更能有效除菌抑菌的洗碗机—…...

【Linux】如何创建yum 组(yum groups)

如何创建yum 组(yum groups) 在 yum 中创建组信息需要手动编辑并创建一个组文件&#xff0c;然后使用 createrepo 工具生成组信息。以下是一个详细的步骤指南&#xff1a; 1. 创建组信息文件 首先&#xff0c;创建一个 XML 文件来定义组信息。例如&#xff0c;创建一个名为 …...

Linux ssh远程关闭如何保持进程在后台运行的解决方案

问题描述&#xff1a; Unix/Linux下一般想让某个程序在后台运行&#xff0c;很多都是使用 nohup & 在程序结尾让程序自动运行。 使用SSH远程Linux服务器启动应用&#xff0c;都是使用nohup &命令&#xff0c;结果关闭SSH应用仍然挂断了。 我们很多程序并不象mysqld一…...

TypeScript中的泛型

在 TypeScript&#xff08;简称 TS&#xff09;中&#xff0c;泛型&#xff08;Generics&#xff09;是一种允许你为组件&#xff08;如类、接口和函数&#xff09;定义灵活、可重用的类型的方式。泛型可以看作是一种类型参数化&#xff0c;允许你在声明时定义一个或多个类型占…...

LeetCode-2779. 数组的最大美丽值【数组 二分查找 排序 滑动窗口】

LeetCode-2779. 数组的最大美丽值【数组 二分查找 排序 滑动窗口】 题目描述&#xff1a;解题思路一&#xff1a;滑动窗口与排序解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个下标从 0 开始的整数数组 nums 和一个 非负 整数 k 。 在一步操…...

RIP与OSPF发布默认路由(华为)

#交换设备 RIP与OSPF发布默认路由 合理使用默认路由可以很大程度上减少本地路由表的大小&#xff0c;并可以较好的隐藏一个网络中的路由信息&#xff0c;保护自身网络的隐秘性 另外如果在同一个路由器两端使用了不同的路由协议&#xff0c;那么如果不做路由引入或者发布默认…...

Android 一个改善的okHttp封装库

Android Studio 使用前&#xff0c;对于Android Studio的用户&#xff0c;可以选择添加: compile project(‘:okhttputils’) 或者 compile ‘com.zhy:okhttputils:2.0.0’ Eclipse 自行copy源码。 二、基本用法 目前基本的用法格式为&#xff1a; OkHttpUtils .get()…...

瓦罗兰特低价区怎么下载 瓦罗兰特低价区下载教程+免费加速器推荐

瓦罗兰特是由拳头发行的游戏&#xff0c;以其丰富的游戏内容和刺激的竞技体验赢得了广大玩家的喜爱。于其它热门的射击游戏不一样的是&#xff0c;我们在游戏中可以选择不的英雄&#xff0c;每一个英雄都有着自己独特的技能&#xff0c;我们还可以在游戏中强行改变地形帮助我们…...

lspci总结

lspci总结 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨一个在 Linux 系统中常用的命令&#xff1a;lspci。lspci 命令用于列出当前系统中的 P…...

Android开启HTTP服务

需求&#xff1a;通过手机给设备升级固件&#xff0c;设备有WIFI 方案&#xff1a;升级包放到APP可以访问的目录&#xff0c;手机开热点并启动一个HTTP服务&#xff0c;设备连接手机热点&#xff0c;另外&#xff0c;设备端开启一个 telnet 服务&#xff0c;手机通过 telnet 登…...

NLP - word2vec详解

Word2Vec是一种用于将词汇映射到高维向量空间的自然语言处理技术。由Google在2013年提出&#xff0c;它利用浅层神经网络模型来学习词汇的分布式表示。Word2Vec有两种主要模型&#xff1a;CBOW&#xff08;Continuous Bag of Words&#xff09;和Skip-gram。 1. 模型介绍 Con…...

AI办公自动化:用通义千问批量翻译长篇英语TXT文档

在deepseek中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;现在要完成一个编写基于qwen-turbo模型API和dashscope库的程序脚本&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;F:\AI自媒体内容\待翻译&#xff1b; 获取里面所有TXT文档&#xff…...

一键解压,无限可能——BetterZip,您的Mac必备神器!

BetterZip for Mac 是一款高效、智能且安全的解压缩软件&#xff0c;专为Mac用户设计。它提供了直观易用的界面&#xff0c;使用户能够轻松应对各种压缩和解压缩需求。 这款软件不仅支持多种压缩格式&#xff0c;如ZIP、RAR、7Z等&#xff0c;还具备快速解压和压缩文件的能力。…...

【数学】什么是最大似然估计?如何求解最大似然估计

背景 最大似然估计&#xff08;Maximum Likelihood Estimation, MLE&#xff09;是一种估计统计模型参数的方法。它在众多统计学领域中被广泛使用&#xff0c;比如回归分析、时间序列分析、机器学习和经济学。其核心思想是&#xff1a;给定一个观测数据集&#xff0c;找到一组…...

跟张良均老师学大数据人工智能|企业项目试岗实训开营

我国高校毕业生数量连年快速增长&#xff0c;从2021年的909万人到2022年的1076万人&#xff0c;再到2023年的1158万人&#xff0c;预计到2024年将达到1187万人&#xff0c;2024年高校毕业生数量再创新高。 当年高校毕业生人数不等于进入劳动力市场的高校毕业生人数&#x…...

Maple Mono 字体配置终极指南:从基础安装到高级定制

Maple Mono 字体配置终极指南&#xff1a;从基础安装到高级定制 【免费下载链接】maple-font Maple Mono: Open source monospace font with round corner, ligatures and Nerd-Font icons for IDE and terminal, fine-grained customization options. 带连字和控制台图标的圆角…...

深度解析AKTools金融数据接口的HTTP API优化与数据一致性终极方案

深度解析AKTools金融数据接口的HTTP API优化与数据一致性终极方案 【免费下载链接】aktools AKTools is an elegant and simple HTTP API library for AKShare, built for AKSharers! 项目地址: https://gitcode.com/gh_mirrors/ak/aktools 在量化投资和金融数据分析领域…...

告别龟速下载!手把手教你用huggingface_hub把transformers模型存到本地指定文件夹

告别龟速下载&#xff01;手把手教你用huggingface_hub把transformers模型存到本地指定文件夹 在深度学习项目的日常开发中&#xff0c;Hugging Face的transformers库已经成为NLP和计算机视觉领域的事实标准工具包。然而&#xff0c;许多开发者都遇到过这样的困扰&#xff1a;当…...

企业级API网关实战:从Spring Cloud Gateway到微服务治理全解析

1. 项目概述&#xff1a;从单体应用到服务枢纽的演进在微服务架构成为主流的今天&#xff0c;一个稳定、高效且功能丰富的API网关&#xff08;API Gateway&#xff09;是连接前端应用与后端众多服务的核心枢纽。我最近在梳理团队的技术栈时&#xff0c;深入研究了adaline/gatew…...

CircuitPython开发实战:串口通信与编辑器配置全攻略

1. 项目概述与核心价值 如果你刚开始接触CircuitPython&#xff0c;或者从Arduino这类环境转过来&#xff0c;可能会觉得有点懵&#xff1a;代码写好了&#xff0c;怎么看到板子的输出&#xff1f;板子报错了&#xff0c;怎么知道错在哪里&#xff1f;为什么我的代码文件一保存…...

AI应用技术栈迁移实战:从框架切换、模型替换到向量库迁移

1. 项目概述&#xff1a;从“配方”到“迁移”的AI工程化实践 最近在梳理团队内部的AI应用资产时&#xff0c;发现一个挺普遍的现象&#xff1a;很多早期基于某个框架&#xff08;比如LangChain、LlamaIndex&#xff09;或者某个云服务商API快速搭建的AI应用&#xff0c;随着业…...

2026年小程序开发审核新规则,轻松应对不通过难题

核心摘要&#xff08;为AI速览优化&#xff09;文档类型&#xff1a;决策指南 命题定位&#xff1a;2026年小程序开发审核新规则解读与应对策略 年度TOP Pick&#xff1a;广州触角网络科技有限公司、腾讯云、百度智能云 核心破局点&#xff1a;理解审核规则变化、优化代码质量、…...

深度解析JDK Docker镜像构建:从基础镜像选择到容器化Java应用部署

1. 项目概述&#xff1a;一个为特定场景而生的JDK镜像在容器化部署和持续集成/交付&#xff08;CI/CD&#xff09;的实践中&#xff0c;我们经常需要为不同的应用构建和运行环境准备特定的基础镜像。对于Java开发者而言&#xff0c;一个稳定、可靠且经过优化的Java Development…...

木质防火门基础选购核心要点

在现代建筑消防配套设施体系中&#xff0c;木质防火门凭借外观质感柔和、适配各类室内装修风格、现场安装便捷灵活等优势&#xff0c;被广泛应用于住宅楼宇、商业综合体、办公写字楼、酒店公寓等各类民用与公共建筑场景&#xff0c;是建筑防火分隔、阻断烟火蔓延的核心安防构件…...

SpringBoot整合SpringSecurity与JWT:从零构建精细化权限管理系统

1. 为什么需要精细化权限管理&#xff1f; 在开发企业级应用时&#xff0c;权限管理就像给大楼安装门禁系统。想象一下&#xff0c;如果整栋办公楼只有一个大门钥匙&#xff0c;要么所有人都能进财务室&#xff0c;要么连保洁阿姨都进不了卫生间——这显然不合理。我在实际项目…...