当前位置: 首页 > 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

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

相关文章:

  • 02-ES6新语法
  • shell 三剑客-grep
  • SpringSecurity-入门代码
  • 【Linux】如何创建yum 组(yum groups)
  • 计算机类期刊含金量横纵向对比(一)
  • 计算机网络 —— 运输层(UDP和TCP)
  • 面试专区|【32道HDFS高频题整理(附答案背诵版)】
  • 2024 年 Python 基于 Kimi 智能助手 Moonshot Ai 模型搭建微信机器人(更新中)
  • 003.Linux SSH协议工具
  • 工具清单 - CI CD
  • GaussDB技术解读——GaussDB架构介绍(五)
  • 如何快速翻译pdf英文论文(5分钟就可以翻译一篇几十页的英文论文)
  • AI智能盒子助力中钢天源设备工厂升级安全防护
  • Docker 命令大全
  • Pgsql数据库之Linux环境备份Windows环境还原
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • CAP 一致性协议及应用解析
  • CAP理论的例子讲解
  • co.js - 让异步代码同步化
  • java第三方包学习之lombok
  • magento2项目上线注意事项
  • Mysql数据库的条件查询语句
  • Node + FFmpeg 实现Canvas动画导出视频
  • Phpstorm怎样批量删除空行?
  • React的组件模式
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • uni-app项目数字滚动
  • vue中实现单选
  • vue自定义指令实现v-tap插件
  • 动态规划入门(以爬楼梯为例)
  • 动态魔术使用DBMS_SQL
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 猴子数据域名防封接口降低小说被封的风险
  • 回顾 Swift 多平台移植进度 #2
  • 力扣(LeetCode)965
  • 算法之不定期更新(一)(2018-04-12)
  • 原生Ajax
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 积累各种好的链接
  • ​520就是要宠粉,你的心头书我买单
  • ​力扣解法汇总946-验证栈序列
  • ###项目技术发展史
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #if等命令的学习
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • ()、[]、{}、(())、[[]]命令替换
  • (solr系列:一)使用tomcat部署solr服务
  • (二)测试工具
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (一)springboot2.7.6集成activit5.23.0之集成引擎
  • (已解决)vscode如何选择python解释器
  • (转)德国人的记事本
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)