编辑推荐
只需编程基础。
从零开始自制编程语言。
支持面向对象、异常处理等高级机制。
内容简介
本书手把手地教读者用C语言制作两种编程语言:crowbar与Diksam。crowbar是运行分析树的无类型语言,Diksam是运行字节码的静态类型语言。这两种语言都具备四则运算、变量、条件分支、循环、函数定义、垃圾回收等功能,*终版则可以支持面向对象、异常处理等高级机制。所有源代码都提供下载,读者可以一边对照书中的说明一边调试源代码。这个过程对理解程序的运行机制十分有帮助。
目录
- 第1章 引子
- 1.1 为什么要制作编程语言
- 1.2 自制编程语言并不是很难
- 1.3 本书的构成与面向读者
- 1.4 用什么语言来制作
- 1.5 要制作怎样的语言
- 1.5.1 要设计怎样的语法
- 1.5.2 要设计怎样的运行方式
- 补充知识 “用户”指的是谁?
- 补充知识 解释器并不会进行翻译
- 1.6 环境搭建
- 1.6.1 搭建开发环境
- 补充知识 关于bison与flex的安装
- 1.6.2 本书涉及的源代码以及编译器
- 第2章 试做一个计算器
- 2.1 yacc/lex是什么
- 补充知识 词法分析器与解析器是各自独立的
- 2.2 试做一个计算器
- 2.2.1 lex
- 2.2.2 简单正则表达式讲座
- 2.2.3 yacc
- 2.2.4 生成执行文件
- 2.2.5 理解冲突所代表的含义
- 2.2.6 错误处理
- 2.3 不借助工具编写计算器
- 2.3.1 自制词法分析器
- 补充知识 保留字(关键字)
- 补充知识 避免重复包含
- 2.3.2 自制语法分析器
- 补充知识 预读记号的处理
- 2.4 少许理论知识LL(1)与LALR(1)
- 补充知识 Pascal/C 中的语法处理诀窍
- 2.5 习题:扩展计算器
- 2.5.1 让计算器支持括号
- 2.5.2 让计算器支持负数
- 第3章 制作无类型语言crowbar
- 3.1制作crowbar ver.0.1语言的基础部分
- 3.1.1 crowbar是什么
- 3.1.2 程序的结构
- 3.1.3 数据类型
- 3.1.4 变量
- 补充知识 初次赋值兼做变量声明的理由
- 补充说明 各种语言的全局变量处理
- 3.1.5 语句与结构控制
- 补充知识 elif、elsif、elseif的选择
- 3.1.6 语句与运算符
- 3.1.7 内置函数
- 3.1.8 让crowbar支持C 语言调用
- 3.1.9 从crowbar中调用C 语言(内置函数的编写)
- 3.2 预先准备
- 3.2.1 模块与命名规则
- 3.2.2 内存管理模块MEM
- 补充知识 valgrind
- 补充知识 富翁式编程
- 补充知识 符号表与扣留操作
- 3.2.3 调试模块DBG
- 3.3 crowbar ver.0.1的实现
- 3.3.1 crowbar的解释器CRB_Interpreter
- 补充知识 不完全类型
- 3.3.2 词法分析crowbar.l
- 补充知识 静态变量的许可范围
- 3.3.3 分析树的构建crowbar.y 与create.c
- 3.3.4 常量折叠
- 3.3.5 错误信息
- 补充知识 关于crowbar中使用的枚举型定义
- 3.3.6 运行execute.c
- 3.3.7 表达式评估eval.c
- 3.3.8 值CRB_Value
- 3.3.9 原生指针型
- 3.3.10 变量
- 3.3.11 字符串与垃圾回收机制string_pool.c
- 3.3.12 编译与运行
- 第4章 数组和mark-sweep垃圾回收器
- 4.1 crowbar ver.0.2
- 4.1.1 crowbar的数组
- 4.1.2 访问数组元素
- 4.1.3 数组是一种引用类型
- 补充知识 “数组的数组”和多维数组
- 4.1.4 为数组添加元素
- 4.1.5 增加( 模拟) 函数调用功能
- 4.1.6 其他细节
- 4.2 制作mark-sweep GC
- 4.2.1 引用数据类型的结构
- 4.2.2mark-sweep GC
- 补充知识 引用和immutable
- 4.2.3 crowbar栈
- 4.2.4 其他根
- 4.2.5 原生函数的形式参数
- 4.3 实现GC 本身
- 4.3.1 对象的管理方法
- 4.3.2 GC 何时启动
- 4.3.3 sweep阶段
- 补充知识 GC 现存的问题
- 补充知识 Coping GC
- 4.4 其他修改
- 4.4.1 修改语法
- 4.4.2 函数的模拟
- 4.4.3 左值的处理
- 4.4.4 创建数组和原生函数的书写方法
- 4.4.5 原生指针类型的修改
- 第5章 中文支持和Unicode
- 5.1 中文支持策略和基础知识
- 5.1.1 现存问题
- 5.1.2 宽字符(双字节)串和多字节字符串
- 补充知识 wchar_t 肯定能表示1 个字符吗?
- 5.1.3 多字节字符/ 宽字符之间的转换函数群
- 5.2 Unicode
- 5.2.1 Unicode的历史
- 5.2.2 Unicode的编码方式
- 补充知识 Unicode可以固定(字节)长度吗?
- 5.3 crowbar book_ver.0.3的实现
- 5.3.1 要实现到什么程度?
- 5.3.2 发起转换的时机
- 5.3.3 关于区域设置
- 5.3.4 解决0x5C问题
- 补充知识 失败的 #ifdef
- 5.3.5 应该是什么样子
- 补充知识 还可以是别的样子Code Set Independent
- 第6章 制作静态类型的语言Diksam
- 6.1 制作Diksam Ver 0.1语言的基本部分
- 6.1.1 Diksam的运行状态
- 6.1.2 什么是Diksam
- 6.1.3 程序结构
- 6.1.4 数据类型
- 6.1.5 变量
- 6.1.6 语句和流程控制
- 6.1.7 表达式
- 6.1.8 内建函数
- 6.1.9 其他
- 6.2 什么是静态的/ 执行字节码的语言
- 6.2.1 静态类型的语言
- 6.2.2 什么是字节码
- 6.2.3 将表达式转换为字节码
- 6.2.4 将控制结构转换为字节码
- 6.2.5 函数的实现
- 6.3 Diksam ver.0.1的实现编译篇
- 6.3.1 目录结构
- 6.3.2 编译的概要
- 6.3.3 构建分析树(create.c)
- 6.3.4 修正分析树(fix_tree.c)
- 6.3.5 Diksam的运行形式DVM_Executable
- 6.3.6 常量池
- 补充知识 YARV 的情况
- 6.3.7 全局变量
- 6.3.8 函数
- 6.3.9 顶层结构的字节码
- 6.3.10 行号对应表
- 6.3.11 栈的需要量
- 6.3.12 生成字节码(generate.c)
- 6.3.13 生成实际的编码
- 6.4 Diksam虚拟机
- 6.4.1 加载/ 链接DVM_Executable到DVM
- 6.4.2 执行巨大的switch case
- 6.4.3 函数调用
- 第7章 为Diksam引入数组
- 7.1 Diksam中数组的设计
- 7.1.1 声明数组类型的变量
- 7.1.2 数组常量
- 补充知识 D 语言的数组
- 7.2 修改编译器
- 7.2.1 数组的语法规则
- 7.2.2 TypeSpecifier结构体
- 7.3 修改DVM
- 7.3.1 增加指令
- 补充知识 创建Java 的数组常量
- 补充知识 C 语言中数组的初始化
- 7.3.2 对象
- 补充知识 ArrayStoreException
- 7.3.3 增加null
- 7.3.4 哎! 还缺点什么吧?
- 第8章 将类引入Diksam
- 8.1 分割源文件
- 8.1.1 包和分割源代码
- 补充知识 #include、文件名、行号
- 8.1.2 DVM_ExecutableList
- 8.1.3 ExecutableEntry
- 8.1.4 分开编译源代码
- 8.1.5 加载和再链接
- 补充知识 动态加载时的编译器
- 8.2 设计Diksam中的类
- 8.2.1 超简单的面向对象入门
- 8.2.2 类的定义和实例创建
- 8.2.3 继承
- 8.2.4 关于接口
- 8.2.5 编译与接口
- 8.2.6 Diksam怎么会设计成这样?
- 8.2.7 数组和字符串的方法
- 8.2.8 检查类的类型
- 8.2.9 向下转型
- 8.3 关于类的实现继承和多态
- 8.3.1 字段的内存布局
- 8.3.2 多态以单继承为前提
- 8.3.3 多继承C
- 8.3.4 Diksam的多继承
- 补充知识 无类型语言中的继承
- 8.3.5 重写的条件
- 8.4 关于类的实现
- 8.4.1 语法规则
- 8.4.2 编译时的数据结构
- 8.4.3 DVM_Executable中的数据结构
- 8.4.4 与类有关的指令
- 补充知识 方法调用、括号和方法指针
- 8.4.5 方法调用
- 8.4.6 super
- 8.4.7 类的链接
- 8.4.8 实现数组和字符串的方法
- 8.4.9 类型检查和向下转型
- 补充知识 对象终结器(finalizer)和析构函数(destructor)
- 第9章 应用篇
- 9.1 为crowbar引入对象和闭包
- 9.1.1 crowbar的对象
- 9.1.2 对象实现
- 9.1.3 闭包
- 9.1.4 方法
- 9.1.5 闭包的实现
- 9.1.6 试着跟踪程序实际执行时的轨迹
- 9.1.7 闭包的语法规则
- 9.1.8 普通函数
- 9.1.9 模拟方法(修改版)
- 9.1.10 基于原型的面向对象
- 9.2 异常处理机制
- 9.2.1 为crowbar引入异常
- 9.2.2 setjmp()/longjmp()
- 补充知识 Java 和C# 异常处理的不同
- 9.2.3 为Diksam引入异常
- 补充知识 catch 的编写方法
- 9.2.4 异常的数据结构
- 9.2.5 异常处理时生成的字节码
- 9.2.6 受查异常
- 补充知识 受查异常的是与非
- 补充知识 异常处理本身的是与非
- 9.3 构建脚本
- 9.3.1 基本思路
- 9.3.2 YY_INPUT
- 9.3.3 Diksam的构建脚本
- 9.3.4 三次加载/ 链接
- 9.4 为crowbar引入鬼车
- 9.4.1 关于“鬼车”
- 9.4.2 正则表达式常量
- 9.4.3 正则表达式的相关函数
- 9.5 其他
- 9.5.1 foreach 和迭代器(crowbar)
- 9.5.2 switch case(Diksam)
- 9.5.3 enum(Diksam)
- 9.5.4 delegate(Diksam)
- 9.5.5 final、const(Diksam)
- 附录A crowbar语言的设计
- 附录B Diksam语言的设计
- 附录C Diksam Virtual Machine 指令集
- 编程语言实用化指南写在后
- 参考文献