书海网短评:
只需编程基础。 从零开始自制编程语言。 支持面向对象、异常处理等高级机制。 《图灵程序设计丛书:自制编程语言》手把手地教读者用C语言制作两种编程语言:crowb
只需编程基础。
从零开始自制编程语言。
支持面向对象、异常处理等高级机制。
前桥和弥(MaebasiKazuya),1969年出生,著有《征服C指针》、《彻底掌握C语言》、《Java之谜和陷阱》等。其一针见血的“毒舌”文风和对编程语言深刻的见地受到广大读者的欢迎。
刘卓,2004年开始从事对日软件开发工作,其间还从事技术及软件工程相关培训工作。自2011年开始从事电力行业产品研发。持续关注企业级应用架构和Web客户端技术。
徐谦,6年技术开发及项目经验,曾以技术工程师身份赴日本工作两年,后归国联合创办互联网公司,现居上海继续创业中。主要从事PHP方向的Web开发。热爱开源,曾向ZendFramework等知名PHP开源项目贡献代码,并于Github自主研发运维EvaThumber等开源项目获得国内社区认可。乐于分享技术心得,个人技术博客avnpc.com在国内PHP圈小有影响。
吴雅明,13年编程经验。其中7年专注于研发基于JavaEE和.NET的开发框架以及基于UML2.0模型的代码生成工具。目前正带领团队开发云计算PaaS平台及云计算自动化配置部署的系统。译著有《征服C指针》等。
第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.1yacc/lex是什么
补充知识词法分析器与解析器是各自独立的
2.2试做一个计算器
2.2.1lex
2.2.2简单正则表达式讲座
2.2.3yacc
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制作crowbarver.0.1语言的基础部分
3.1.1crowbar是什么
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.3crowbarver.0.1的实现
3.3.1crowbar的解释器--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.1crowbarver.0.2
4.1.1crowbar的数组
4.1.2访问数组元素
4.1.3数组是一种引用类型
补充知识“数组的数组”和多维数组
4.1.4为数组添加元素
4.1.5增加(模拟)函数调用功能
4.1.6其他细节
4.2制作mark-sweepGC
4.2.1引用数据类型的结构
4.2.2 mark-sweepGC
补充知识引用和immutable
4.2.3crowbar栈
4.2.4其他根
4.2.5原生函数的形式参数
4.3实现GC本身
4.3.1对象的管理方法
4.3.2GC何时启动
4.3.3sweep阶段
补充知识GC现存的问题
补充知识CopingGC
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.2Unicode
5.2.1Unicode的历史
5.2.2Unicode的编码方式
补充知识Unicode可以固定(字节)长度吗?
5.3crowbarbook_ver.0.3的实现
5.3.1要实现到什么程度?
5.3.2发起转换的时机
5.3.3关于区域设置
5.3.4解决0x5C问题
补充知识失败的#ifdef
5.3.5应该是什么样子
补充知识还可以是别的样子--CodeSetIndependent
第6章制作静态类型的语言Diksam
6.1制作DiksamVer0.1语言的基本部分
6.1.1Diksam的运行状态
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.3Diksamver.0.1的实现--编译篇
6.3.1目录结构
6.3.2编译的概要
6.3.3构建分析树(create.c)
6.3.4修正分析树(fix_tree.c)
6.3.5Diksam的运行形式--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.4Diksam虚拟机
6.4.1加载/链接DVM_Executable到DVM
6.4.2执行--巨大的switchcase
6.4.3函数调用
第7章为Diksam引入数组
7.1Diksam中数组的设计
7.1.1声明数组类型的变量
7.1.2数组常量
补充知识D语言的数组
7.2修改编译器
7.2.1数组的语法规则
7.2.2TypeSpecifier结构体
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.2DVM_ExecutableList
8.1.3ExecutableEntry
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.6Diksam怎么会设计成这样?
8.2.7数组和字符串的方法
8.2.8检查类的类型
8.2.9向下转型
8.3关于类的实现--继承和多态
8.3.1字段的内存布局
8.3.2多态--以单继承为前提
8.3.3多继承--C++
8.3.4Diksam的多继承
补充知识无类型语言中的继承
8.3.5重写的条件
8.4关于类的实现
8.4.1语法规则
8.4.2编译时的数据结构
8.4.3DVM_Executable中的数据结构
8.4.4与类有关的指令
补充知识方法调用、括号和方法指针
8.4.5方法调用
8.4.6super
8.4.7类的链接
8.4.8实现数组和字符串的方法
8.4.9类型检查和向下转型
补充知识对象终结器(finalizer)和析构函数(destructor)
第9章应用篇
9.1为crowbar引入对象和闭包
9.1.1crowbar的对象
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.2setjmp()/longjmp()
补充知识Java和C#异常处理的不同
9.2.3为Diksam引入异常
补充知识catch的编写方法
9.2.4异常的数据结构
9.2.5异常处理时生成的字节码
9.2.6受查异常
补充知识受查异常的是与非
补充知识异常处理本身的是与非
9.3构建脚本
9.3.1基本思路
9.3.2YY_INPUT
9.3.3Diksam的构建脚本
9.3.4三次加载/链接
9.4为crowbar引入鬼车
9.4.1关于“鬼车”
9.4.2正则表达式常量
9.4.3正则表达式的相关函数
9.5其他
9.5.1foreach和迭代器(crowbar)
9.5.2switchcase(Diksam)
9.5.3enum(Diksam)
9.5.4delegate(Diksam)
9.5.5final、const(Diksam)
附录Acrowbar语言的设计
附录BDiksam语言的设计
附录CDiksamVirtualMachine指令集
编程语言实用化指南--写在最后
参考文献
在一些C的入门书中都有这样一句话:为了提高移植性而适当地使用#ifdef。以我的理解,“适当地使用”其实就是“尽量别用”的意思。因此,这次我(在处理器切换时)使用了#ifdef,这对我来说也是一次失败。
根据处理器不同而使用#ifdef选择不同代码片段的话,会使代码变得很难理解。另外,像这样分散的代码通常很难进行充分的测试。在理想状态下,所有#ifdef的组合可以伴随着每日构建进行自动化测试,这感觉还不错,但是我认为这在实际中很难实现。
如果是为了提高移植性,那么也可以不使用#ifdef来处理各种分支,只要写一个尽可能适应各种处理器的代码不是就行了吗?
编程方面的著作《程序设计实践》中有以下记载。
如果我们对于条件编译持否定态度,那么就会由此发生一些问题。先不说最麻烦的。条件编译基本上都不可能进行测试。(中间省略)在对其中一个#ifdef代码块进行测试的同时,如果想测试另外的#ifdef代码块,除非改变环境使另一个#ifdef代码块生效,否则无法进行验证。
(中间省略)
由此我们得知。让我们感兴趣的是。在所有目标环境中都可以运行的共通性功能。
5.3.1节决定了crowbar不处理合成字符和UCS2范围以外的字符。
如果只是为了对应中文的话,这样的设计(指5.3.1节中提到的设计方式)就没问题了。但如果想要完美地实现,恐怕就需要考虑以下几点(以Unicode为前提)。
1.内部表现也要使用UTF.8
如果考虑合成字符的话,就不可能让字符有固定长度。如果想要取得字符串的第n个字符,每次都必须从字符串的开头扫描,所以还是算了吧。
2.不使用mbtowc()系列函数,自己实现全部的转换
如果自己保存转码表,就要根据不同的情况使用不同的转码表。比如,在需要和Java兼容的时候要使用Java的转码表,如果要在Windows对话框中显示一个字符串的时候又要使用Windows的转码表等。
mbtowc()系列函数不仅意味着“在所有的处理器中,总是可以返回所期望结果”,还表示“如果自己保存转码表的话,所有转换都要自己进行”。
作为一个还算现实的做法(只要能处理好中文就可以了),我制作的这个语法处理器,正好解决了所有的问题。如果一味追求结果而不能实现也是没有意义的。
……
这《图灵程序设计丛书:自制编程语言》是为那些想独立制作一门编程语言的人而写的。
一听到这个话题,有的人会想:太疯狂了,制作编程语言肯定很有难度吧?有人会怀疑:制作编程语言能有什么用呢?其实这些都是误解。
制作编程语言在技术层面上其实并不难,只要掌握一些基础知识即可。而且,制作编程语言对于我们深入理解日常使用的C、Java、JavaScript等语言都有帮助。在一些应用程序的内置脚本语言中,我们也经常会因为种种限制从而萌生制作替代语言的想法。因此,自制编程语言并不是少数极客的个人癖好,它对大多数程序员都颇具实用价值。
日本关于制作编程语言的书已经很多了,其中一些还被选定为大学教科书。这些书中常出现有限状态机、NFA、LL(1)、LR(1)、SLA等专业词汇,同时还大量使用∩、∈等数学符号,对于不熟悉这部分理论知识的人(包括我自己在内)来说非常难以读懂。针对这种现状,《图灵程序设计丛书:自制编程语言》会偏重实践,避免枯燥的理论。
《图灵程序设计丛书:自制编程语言》将分别制作两种编程语言:crowbar与Diksam。crowbar是运行分析树的无类型语言,Diksam是运行字节码的静态类型语言。无论哪种语言,都具备四则运算、变量、条件分支、循环、函数定义、垃圾回收等功能,最终版则可以支持面向对象、异常处理等高级机制。总之,作为现代编程语言所必须具备的功能都基本覆盖了(唯一可能没实现的就是多线程了吧)。所有源代码都提供下载,读者可以一边对照书中的说明一边调试源代码,这样应该不难理解整个程序的运行机制。
当然,要一次实现如此多功能的编程语言,对于初学者而言可能有点吃力,因此《图灵程序设计丛书:自制编程语言》会详细介绍crowbar、Diksam的制作步骤,请放心。
在制作编程语言的过程中,我体会到了一种无法用语言形容的快乐。其实无论在日本或其他地区,世界上还有很多人都在尝试自制编程语言,这正是编程语言不断增加的原因。如果以《图灵程序设计丛书:自制编程语言》为契机,有朝一日你也向本已混乱的巴比伦之塔再添一门新语言的话,作为《图灵程序设计丛书:自制编程语言》作者,这将是无上的光荣。









