让我们用中文编程(二)之C++篇 - 自己做中文编程语言,你也行

编译 同时被 2 个专栏收录
1 篇文章 0 订阅
36 篇文章 0 订阅

ZDNet软件频道 时间:2008-05-18 作者:dancefire | CSDN 我要评论()
本文关键词:中文编程 c++ python 软件

如今,我们要写C++程序,已经完全允许在代码中出现Unicode编码的变量名、函数名、类名等等,并且#define也支持Unicode替换了。
中文编程的神化
随着11月7日,微软Visual C++ 2005的发布,我们关注到,VC8.0中增加了大量新的特性,包括最重要的,引入了C++/CLI,可以说是给C/C++语言历史上掀起了新的一页。作为一个方言的出现C++/CLI会有什么样的作为,却是值得大家拭目以待,是功是过,由历史来评说。但是我们也注意到,VC8.0引入了一个非常有趣的支持,VC8.0开始支持Unicode的源代码了。如同C#和Java一样。如今,我们要写C++程序,已经完全允许在代码中出现Unicode编码的变量名、函数名、类名等等,并且#define也支持Unicode替换了。
虽然是个小变化,但是,中文编程的世界一下就变了。这使我立刻就想到,国内有些公司,在致力于炒作中文编程,细看他们的语言,无非是对现有语言把关键字替换成了中文而已,其他的改进太小了。有的是把Forth给用中文关键字包装了一下,就推出来的;还有的是把C语言用中文的关键字替换一下就推出来的。这样的语言,真的是自己的么?这样的语言真的有价值么?“决定一切的不是语言而是思想!”,这是已经人人共知的思想,国内的某些专家和公司竟然还在为这种“伪中文”编程而津津乐道,甚至有些获得了国家项目的资助。如果真的仅仅是用中文关键字来进行编程就可以改变我们国家的IT面貌的话,那大可不必投资数十万甚至上百万来做,用我下面的一个头文件就够了。

关键字使用中文,很简单的技术;实现一个别人已经发明的语言,也不是什么太复杂的事情(当然如果做一个100%兼容的C++这样的复杂语言的编译器还是具有相当的难度的)。真正难的应该是理解这种语言的创新思想,发现或者创造一种方法,以解决现有语言在程序设计上的存在的种种问题,这样更新或者创造出来的才是真正有用的经典之作。不用细说,大家都知道,C、C++、Java、C#、Ruby、python的诞生都分别解决了什么难题。他们用漂亮的办法解决了一直困扰程序员的问题,他们就成为了经典。而国内那些做中文编程的公司的产品呢?呵呵,也许仅仅是茶余饭后而笑柄而已。

目前我不知道还有哪个编译器能够对Unicode有良好的支持,所以,目前只有Visual C++ 2005才能够编译下面的代码,但是很幸运,原本打算卖US的Visual C++ 2005 Express,从现在开始,一年内是免费的,而且微软没有一年以后的收费计划,所以也许我们可以一直合法的用下去,呵呵。大家可以从微软网站直接下载,需要下载的访问下面的连接:

http://msdn.microsoft.com/vstudio/express/visualc/

下面的代码都可以在Visual C++ 2005 Express 版上编译通过。

好了,真的言归正传了。我用了一系列的#define宏和typedef,作了中文和英文关键字的替换。比如:

 


typedef int     整型;
typedef char    字符型;

#define 如果     if
#define 否则     else
#define 返回     return
#define 常量     const

#define 标准输出 std::cout
#define 行结束   std::endl
#define 标准输入 std::cin
#define 字符串   std::string

#define 主程序   main

经过这样处理后我们就可以写出一个最简单的中文程序:

 

整型 主程序( 整型 参数数量, 常量 字符型** 参数列表 )
{
    字符串 路人甲;
    整型   年龄;

    标准输出 << "请输入姓名:" << 行结束;
    标准输入 >> 路人甲;
    标准输出 << "请输入年龄:" << 行结束;
    标准输入 >> 年龄;

    如果(年龄 > 18){
        标准输出 << 路人甲 << "先生/女士,您好!祝您今天工作愉快哦。" << 行结束;
    }否则{
        标准输出 << 路人甲 << "小朋友,您好!祝你今天玩得开心。" << 行结束;
    }

   返回 0;
}


 程序很简单,执行后,询问你的姓名和年龄,如果你大于18岁呢,它就要对你说“Dancefire先生/女士,您好!祝您今天工作愉快哦。”,如果还不到18岁呢,就会说“Dancefire小朋友,您好!祝你今天玩得开心。”
 

这个程序似乎不够有趣。那么我再来一个有趣一些的,用到了面向对象的继承的概念,新瓶装旧酒了,前一篇文章中提到的,生物圈的例子,(既然是中文嘛,就来点中国文化特色,呵呵),

 

哦,多说一句,下面的程序一共由3个文件组成,其中2个是头文件,另外一个是源文件。三个文件都可以从我的网站下载:

http://www.dancefire.org/file/SinoCPP.zip

如果大家想自己写个中文的类玩玩,只需要#include第一个Sino.h就可以了。我已经在里面替换了大量的关键字,玩玩够了,如果还想替换其他关键字,你们自己加进去就行了,需要注意的是,这几个文件都是受GPL协议保护的,简单而言就是,大家可以随便改,只要继续保持开放就行了。

下面的是主程序:


 


//
// 作者: Dancefire    (Dancefire [at] gmail)
// 日期: 公历 二零零五年十一月十一日
//       农历 乙酉年 丁亥月 己亥日 巳时
//            宜 解除 修饰垣墙 冠笄 出行 馀事勿取
//            忌 开市 动土 破土 嫁娶 安葬
// 项目: 中文C++编程测试
// 版本: 甲子
//

#include <vector>
#include <iostream>
#include <string>
#include "sino.h"
#include "SinoTest.h"


使用 名字空间 标准库;

整型 主程序( 整型 参数数量, 常量 字符型** 参数列表 )
{
    标准输出 << "世界你好!" << 行结束 << 行结束;

    使用 名字空间 中文编程;
    矢量<生物*> 动物们;

    动物们.排到后面( 新建 鸟());
    动物们.排到后面( 新建 鱼());
    动物们.排到后面( 新建 马());
    动物们.排到后面( 新建 动物());
    动物们.排到后面( 新建 生物());

    循环(无符号整型 甲 = 0 ; 甲 < 动物们.多少() ; ++甲)
    {
        生物* 小家伙 = 动物们[甲];
        小家伙->自我介绍();

        动物* 小动物 = 动态转型<动物*>(小家伙);
        如果( 小动物 ){
            小动物->移动();
        }
        标准输出 << 行结束;
    }
    返回 0;
}

 

主程序很简单,先建立了一个动物们的容器,然后一个一个新的动物加入到这个容器(队列)中了。(当然严格来说,应该是生物们,但是听起来好怪,就叫动物们好了。)这些动物们排好队后,开始一个接着一个的自我介绍,如果是动物呢,就动一动,如果不是动物就算了。
 

执行的结果是这样的:

 

 

 


世界你好!

我属于动物, 我是一只可爱的鸟
这只鸟在自由自在的飞翔

我属于动物, 我是一条可爱的鱼
这条鱼在自由自在的游来游去

我属于动物, 我是一匹可爱的马
这匹马在自由自在的奔跑

我属于生物, 我是一只可爱的动物
这只动物在自由自在的移动

我是...咦?我是什么?我也不知道我是什么,难道我是一个外星的生物

大家可以在程序中感受到C++的OO的概念。这里面有5个类,动物类继承了生物类能够自我介绍的能力,鸟、鱼、马 继承了动物类能够移动的能力,而他们在继承自我介绍的时候,用自己的方式替代(重写)了原始生物的自我介绍方式,此处自然用到了虚函数,既然是表现继承,怎么能没了虚函数呢,是吧。在判断是否是动物的时候,用到了C++标准的动态转型,这是在运行期,而不是编译期,进行转型的。类的定义在头文件SinoTest.h中,完整的这个头文件如下:


 

 // 作者: Dancefire    (Dancefire [at] gmail)
// 日期: 公历 二零零五年十一月十一日
//       农历 乙酉年 丁亥月 己亥日 巳时
//            宜 解除 修饰垣墙 冠笄 出行 馀事勿取
//            忌 开市 动土 破土 嫁娶 安葬
// 项目: 中文C++编程测试
// 版本: 甲子
//

名字空间 中文编程
{
    //    生物类
    类 生物
    {
公有:
        生物()    {
            类别 = "生物";
            祖先的类别 = "游离态";
        }

        虚 ~生物(){}
        虚 字符串 我的类别()
        {
            返回 类别;
        }
        虚 字符串 我祖先的类别()
        {
            返回 祖先的类别;
        }
        虚 无值 自我介绍()
        {
            标准输出 << "我是...咦?我是什么?我也不知道我是什么,难道我是一个外星的" << 我的类别() << 行结束;
        }
受保护的:
        字符串 类别;
        字符串 祖先的类别;
    };


    //    动物类,动物当然是生物啦
    类 动物 : 公有 生物
    {
公有:
        动物()    {
            移动方式 = "移动";
            量词 = "只";
            类别 = "动物";
            祖先的类别 = "生物";
        }

        虚 无值 移动(){
            标准输出 << "这" << 量词 << 我的类别() << "在自由自在的" << 移动方式 << 行结束;
        }
        虚 无值 自我介绍()    {
            标准输出 << "我属于" << 我祖先的类别() << ", 我是一" << 量词 << "可爱的" << 我的类别() << 行结束;
        }

受保护的:
        字符串 移动方式;
        字符串 量词;
    };

    //    鸟类,鸟是动物咯。
    类 鸟 : 公有 动物
    {
公有:
        鸟(){
            移动方式 = "飞翔";
            量词 = "只";
            类别 = "鸟";
            祖先的类别 = "动物";
        }
    };


    //    鱼也是动物咯
    类 鱼 : 公有 动物
    {
公有:
        鱼(){
            移动方式 = "游来游去";
            量词 = "条";
            类别 = "鱼";
            祖先的类别 = "动物";
        }
    };


    //    马也是动物
    类 马 : 公有 动物
    {
公有:
        马()
        {
            移动方式 = "奔跑";
            量词 = "匹";
            类别 = "马";
            祖先的类别 = "动物";
        }
    };
}
 

至于Sino.h的内容,我就只列一部分好了,大家需要的,直接从上面的连接下载吧,因为太长了,而且都是一样的宏定义,非常简单,没有什么有趣的事情。

 

 

 


// 作者: Dancefire    (Dancefire [at] gmail)
// 日期: 公历 二零零五年十一月十一日
//       农历 乙酉年 丁亥月 己亥日 巳时
//            宜 解除 修饰垣墙 冠笄 出行 馀事勿取
//            忌 开市 动土 破土 嫁娶 安葬
// 项目: 中文C++编程 头文件
// 版本: 甲子
//


//    变量
typedef bool 布尔;
typedef char 字符型;
typedef short 短整型;
typedef int 整型;
typedef unsigned char 无符号字符型;
typedef unsigned short 无符号短整型;
typedef unsigned int 无符号整型;
typedef unsigned long 无符号长整型;
typedef long 长整型;
typedef float 浮点型;
typedef double 双精度型;
typedef std::string 字符串;

//    常量
const bool 真 = true;
const bool 假 = false;

//    关键字

#define 抽象        abstract
#define 内嵌汇编    __asm
#define 中断        break
#define 得          case        //    ???
#define 捕获        catch
#define 类          class
#define 常量        const
#define 常量转型    const_cast
#define 继续        continue
#define 默认        default
#define 委托        delegate
#define 删除        delete
#define 不推荐      deprecated
#define 动态链接库导出    dllexport
#define 动态链接库导入    dllimport
#define 做            do
#define 动态转型    dynamic_cast
#define 否则        else

哦,唯一的问题是,我不知道switch和case如何翻译。目前我的翻译是,判断和得。所以,如果用到switch的话,代码看起来可能比较奇怪:

判断( 甲吃的饺子盘数 ){
   得 1:
      标准输出 << "竟然甲才吃了1盘饺子,不正常" << 行结束;
      中断;
   得 2:
      标准输出 << "甲一个人就吃了2盘饺子,够实力" << 行结束;
      中断;
   得 3:
      标准输出 << "没搞错吧?甲吃了3盘饺子,不会一天没吃饭,就等这顿了吧??" << 行结束;
      中断;
   默认:
      标准输出 << "无语了~~,我都不知道甲他吃了几盘了" << 行结束;
      中断;
}

 


 

 

 

 

 

自己做一个中文编程语言,你也行
自己做一个中文编程语言?没有开玩笑吧?是的,是没有开玩笑。那些大公司所谓的什么汉语编程语言,相当一部分,就是对某种语言的模拟,只不过关键字用中文替代了而已,有模拟VB的,有模拟C的,还有模拟Forth的。既然是这样也较“中文编程语言”的话,呵呵,那好,我们也做一个好了,比他们更省人力,更简单。

通过刚才的例子,大家已经看到了,我基本上使用纯中文写了一个程序,我相信有C++为依托,这个肯定是最强大的,能够用中文写程序的语言了,哈哈~~(真不要脸,牛什么牛,那些强大的功能是C++给你提供的,你可啥都没做,就是换了换关键字而已嘛。汗~~~)。

想自己创造一个有自己个性的“中文编程语言”,大家从我的网站下载Sino.h这个文件:

http://www.dancefire.org/file/SinoCPP.zip

大家可以根据自己的想法,随意的改动关键字的中文,有什么好的想法,也可以给我回复在这里。给大家举几个简单的例子。大家可以把Sino.h中的public对应的中文,替换成“大家的”,private对应成“我的”,protected对应成“我们家的”,friend可以对应成“哥们儿”,int可以对应成“小样儿”,std::string对应成“条幅”,std::cout对应成“嚷嚷”,std::cin对应成“告诉”。std::endl对应成“行了您呐”,main对应成“龙门客栈”,if对应成“若”,else对应成“否”,return对应成“回报”等等。哈哈,结果这个设计的“中文编程语言”可能就变成下面的样子了:

 小样儿 龙门客栈()
{
    条幅 英雄;
    小样儿 年方几何;

    嚷嚷 << "客官贵姓啊?";
    告诉 >> 英雄;
    嚷嚷 << "哦,兄台,年方几何啊?";
    告诉 >> 年方几何;

    若(年方几何 > 16){
        嚷嚷 << 英雄 << ",大英雄,久仰久仰,您请楼上落座。" << 行了您呐;
    }否{
        嚷嚷 << 英雄 << "小英雄,早有所闻,今日得见果然气度不凡,里面请。" << 行了您呐;
    }
    回报 0;
}

 

来源: http://soft.zdnet.com.cn/software_zone/2008/0518/867411.shtml
  • 0
    点赞
  • 1
    评论
  • 3
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
作者简介: 前桥和弥Maebasi Kazuya 1969年出生著有《征服C指针》、《彻底掌握C语言》、《Java谜和陷阱》等。其一针见血的“毒舌”文风和对编程语言深刻的见地受到广大读者的欢迎。 作者主页:http://kmaebashi.com/。 译者简介: 刘卓 2004年开始从事对日软件开发工作其间还从事技术及软件工程相关培训工作。自2011年开始从事电力业产品研发。持续关注企业级应架构和Web客户端技术。 徐谦 6年技术开发及项目经验曾以技术工程师身份赴日本工作两年后归国联合创办互联网公司现居上海继续创业中。主要从事PHP方向的Web开发。热爱开源曾向Zend Framework等知名PHP开源项目贡献代码并于Github自主研发运维EvaThumber等开源项目获得国内社区认可。乐于分享技术心得个人技术博客avnpc.com在国内PHP圈小有影响。 吴雅明 13年编程经验。其中7年专注于研发基于Java EE和.NET的开发框架以及基于UML 2.0模型的代码生成工具。目前正带领团队开发云计算PaaS平台及云计算自动化配置部署的系统。译著有《征服C指针》等。 目录 · · · · · · 目 录 第1章  引子  001 1.1 为什么要制作编程语言  002 1.2 自制编程语言并不是很难  003 1.3 本书的构成与面向读者  004 1.4 什么语言来制作  006 1.5 要制作怎样的语言  007 1.5.1 要设计怎样的语法  007 1.5.2 要设计怎样的运方式  009 补充知识  “户”指的是谁?  012 补充知识  解释器并不会进翻译  012 1.6 环境搭建  012 1.6.1 搭建开发环境  012 补充知识 关于bison与flex的安装  014 1.6.2 本书涉及的源代码以及编译器  015 第2章  试一个计算器  017 2.1 yacc/lex是什么  018 补充知识  词法分析器与解析器是各自独立的  019 2.2 试一个计算器  020 2.2.1 lex  021 2.2.2 简单正则表达式讲座  024 2.2.3 yacc  026 2.2.4 生成执文件  033 2.2.5 理解冲突所代表的含义  034 2.2.6 错误处理  040 2.3 不借助工具编写计算器  041 2.3.1 自制词法分析器  041 补充知识  保留字关键字  046 补充知识 避免重复包含  047 2.3.2 自制语法分析器  048 补充知识 预读记号的处理  053 2.4 少许理论知识——LL(1)与LALR(1)  054 补充知识 Pascal/C 中的语法处理诀窍  056 2.5 习题:扩展计算器  056 2.5.1 计算器支持括号  056 2.5.2 计算器支持负数  058 第3章  制作无类型语言crowbar  061 3.1 制作crowbar ver.0.1语言的基础部分  062 3.1.1 crowbar是什么  062 3.1.2 程序的结构  063 3.1.3 数据类型  064 3.1.4 变量  064 补充知识 初次赋值兼变量声明的理由  066 补充说明 各种语言的全局变量处理  067 3.1.5 语句与结构控制  067 补充知识 elif、elsif、elseif的选择  068 3.1.6 语句与运算符  069 3.1.7 内置函数  069 3.1.8 crowbar支持C 语言调  070 3.1.9 从crowbar中调C 语言内置函数的编写  071 3.2 预先准备  071 3.2.1 模块与命名规则  072 3.2.2 内存管理模块MEM  073 补充知识 valgrind  075 补充知识 富翁式编程  075 补充知识 符号表与扣留操作  076 3.2.3 调试模块DBG  076 3.3 crowbar ver.0.1的实现  077 3.3.1 crowbar的解释器——CRB_Interpreter  077 补充知识 不完全类型  080 3.3.2 词法分析——crowbar.l  081 补充知识 静态变量的许可范围  084 3.3.3 分析树的构建——crowbar.y 与create.c  085 3.3.4 常量折叠  089 3.3.5 错误信息  089 补充知识 关于crowbar中使的枚举型定义  091 3.3.6 运——execute.c  092 3.3.7 表达式评估——eval.c  096 3.3.8 值——CRB_Value  104 3.3.9 原生指针型  105 3.3.10 变量  106 3.3.11 字符串与垃圾回收机制——string_pool.c  108 3.3.12 编译与运  110 第4章  数组和mark-sweep垃圾回收器  113 4.1 crowbar ver.0.2  114 4.1.1 crowbar的数组  114 4.1.2 访问数组元素  115 4.1.3 数组是一种引类型  116 补充知识  “数组的数组”和多维数组  116 4.1.4 为数组添加元素  118 4.1.5 增加( 模拟) 函数调功能  118 4.1.6 其他细节  118 4.2 制作mark-sweep GC  119 4.2.1 引数据类型的结构  119 4.2.2 mark-sweep GC  121 补充知识 引和immutable  123 4.2.3 crowbar栈  124 4.2.4 其他根  127 4.2.5 原生函数的形式参数  128 4.3 实现GC 本身  129 4.3.1 对象的管理方法  129 4.3.2 GC 何时启动  129 4.3.3 sweep阶段  132 补充知识 GC 现存的问题  133 补充知识 Coping GC  134 4.4 其他修改  136 4.4.1 修改语法  136 4.4.2 函数的模拟  137 4.4.3 左值的处理  139 4.4.4 创建数组和原生函数的书写方法  142 4.4.5 原生指针类型的修改  144 第5章  中文支持和Unicode  147 5.1 中文支持策略和基础知识  148 5.1.1 现存问题  148 5.1.2 宽字符双字节串和多字节字符串  149 补充知识 wchar_t 肯定能表示1 个字符吗?  150 5.1.3 多字节字符/ 宽字符间的转换函数群  150 5.2 Unicode  153 5.2.1 Unicode的历史  153 5.2.2 Unicode的编码方式  154 补充知识 Unicode可以固定字节长度吗?  156 5.3 crowbar book_ver.0.3的实现  156 5.3.1 要实现到什么程度?  156 5.3.2 发起转换的时机  157 5.3.3 关于区域设置  158 5.3.4 解决0x5C问题  158 补充知识 失败的 #ifdef  160 5.3.5 应该是什么样子  160 补充知识 还可以是别的样子——Code Set Independent  161 第6章  制作静态类型的语言Diksam  163 6.1 制作Diksam Ver 0.1语言的基本部分  164 6.1.1 Diksam的运状态  164 6.1.2 什么是Diksam  165 6.1.3 程序结构  165 6.1.4 数据类型  166 6.1.5 变量  166 6.1.6 语句和流程控制  167 6.1.7 表达式  167 6.1.8 内建函数  168 6.1.9 其他  168 6.2 什么是静态的/ 执字节码的语言  169 6.2.1 静态类型的语言  169 6.2.2 什么是字节码  169 6.2.3 将表达式转换为字节码  170 6.2.4 将控制结构转换为字节码  173 6.2.5 函数的实现  173 6.3 Diksam ver.0.1的实现——编译  175 6.3.1 目录结构  175 6.3.2 编译的概要  176 6.3.3 构建分析树create.c  176 6.3.4 修正分析树fix_tree.c  179 6.3.5 Diksam的运形式——DVM_Executable  185 6.3.6 常量池  186 补充知识 YARV 的情况  187 6.3.7 全局变量  188 6.3.8 函数  189 6.3.9 顶层结构的字节码  189 6.3.10 号对应表  190 6.3.11 栈的需要量  190 6.3.12 生成字节码generate.c  191 6.3.13 生成实际的编码  193 6.4 Diksam虚拟机  197 6.4.1 加载/ 链接DVM_Executable到DVM  200 6.4.2 执——巨大的switch case  202 6.4.3 函数调  204 第7章  为Diksam引入数组  207 7.1 Diksam中数组的设计  208 7.1.1 声明数组类型的变量  208 7.1.2 数组常量  209 补充知识 D 语言的数组  210 7.2 修改编译器  210 7.2.1 数组的语法规则  210 7.2.2 TypeSpecifier结构体  212 7.3 修改DVM  213 7.3.1 增加指令  213 补充知识 创建Java 的数组常量  215 补充知识 C 语言中数组的初始化  217 7.3.2 对象  217 补充知识 ArrayStoreException  218 7.3.3 增加null  219 7.3.4 哎! 还缺点什么吧?  219 第8章  将类引入Diksam  221 8.1 分割源文件  222 8.1.1 包和分割源代码  222 补充知识 #include、文件名、号  225 8.1.2 DVM_ExecutableList  225 8.1.3 ExecutableEntry  226 8.1.4 分开编译源代码  227 8.1.5 加载和再链接  230 补充知识 动态加载时的编译器  233 8.2 设计Diksam中的类  233 8.2.1 超简单的面向对象入门  233 8.2.2 类的定义和实例创建  237 8.2.3 继承  239 8.2.4 关于接口  241 8.2.5 编译与接口  242 8.2.6 Diksam怎么会设计成这样?  243 8.2.7 数组和字符串的方法  245 8.2.8 检查类的类型  246 8.2.9 向下转型  246 8.3 关于类的实现——继承和多态  247 8.3.1 字段的内存布局  247 8.3.2 多态——以单继承为前提  249 8.3.3 多继承——C++  250 8.3.4 Diksam的多继承  252 补充知识 无类型语言中的继承  254 8.3.5 重写的条件  254 8.4 关于类的实现  256 8.4.1 语法规则  256 8.4.2 编译时的数据结构  258 8.4.3 DVM_Executable中的数据结构  260 8.4.4 与类有关的指令  262 补充知识 方法调、括号和方法指针  263 8.4.5 方法调  264 8.4.6 super  266 8.4.7 类的链接  266 8.4.8 实现数组和字符串的方法  267 8.4.9 类型检查和向下转型  267 补充知识 对象终结器finalizer和析构函数destructor  268 第9章  应  271 9.1 为crowbar引入对象和闭包  272 9.1.1 crowbar的对象  272 9.1.2 对象实现  273 9.1.3 闭包  274 9.1.4 方法  276 9.1.5 闭包的实现  278 9.1.6 试着跟踪程序实际执时的轨迹  281 9.1.7 闭包的语法规则  284 9.1.8 普通函数  284 9.1.9 模拟方法修改版  285 9.1.10 基于原型的面向对象  286 9.2 异常处理机制  286 9.2.1 为crowbar引入异常  286 9.2.2 setjmp()/longjmp()  289 补充知识 Java 和C# 异常处理的不同  293 9.2.3 为Diksam引入异常  295 补充知识 catch 的编写方法  296 9.2.4 异常的数据结构  297 9.2.5 异常处理时生成的字节码299 9.2.6 受查异常  301 补充知识 受查异常的是与非 303 补充知识 异常处理本身的是与非  304 9.3 构建脚本  305 9.3.1 基本思路  306 9.3.2 YY_INPUT  307 9.3.3 Diksam的构建脚本  308 9.3.4 三次加载/ 链接  308 9.4 为crowbar引入鬼车  309 9.4.1 关于“鬼车”  309 9.4.2 正则表达式常量  310 9.4.3 正则表达式的相关函数  311 9.5 其他  312 9.5.1 foreach 和迭代器crowbar  312 9.5.2 switch caseDiksam)  314 9.5.3 enumDiksam  315 9.5.4 delegateDiksam  316 9.5.5 final、constDiksam  319 附录A  crowbar语言的设计  322 附录B  Diksam语言的设计  336 附录C  Diksam Virtual Machine 指令集  359 编程语言实化指南——写在最后  369 参考文献  375
带完整书签 第1章 引子 001 1.1 为什么要制作编程语言 002 1.2 自制编程语言并不是很难 003 1.3 本书的构成与面向读者 004 1.4 什么语言来制作 006 1.5 要制作怎样的语言 007 1.5.1 要设计怎样的语法 007 1.5.2 要设计怎样的运方式 009 补充知识 “户”指的是谁? 012 补充知识 解释器并不会进翻译 012 1.6 环境搭建 012 1.6.1 搭建开发环境 012 补充知识 关于bison与flex的安装 014 1.6.2 本书涉及的源代码以及编译器 015 第2章 试一个计算器 017 2.1 yacc/lex是什么 018 补充知识 词法分析器与解析器是各自独立的 019 2.2 试一个计算器 020 2.2.1 lex 021 2.2.2 简单正则表达式讲座 024 2.2.3 yacc 026 2.2.4 生成执文件 033 2.2.5 理解冲突所代表的含义 034 2.2.6 错误处理 040 2.3 不借助工具编写计算器 041 2.3.1 自制词法分析器 041 补充知识 保留字关键字 046 补充知识 避免重复包含 047 2.3.2 自制语法分析器 048 补充知识 预读记号的处理 053 2.4 少许理论知识——LL(1)与LALR(1) 054 补充知识 Pascal/C中的语法处理诀窍 056 2.5 习题:扩展计算器 056 2.5.1 计算器支持括号 056 2.5.2 计算器支持负数 058 第3章 制作无类型语言crowbar 061 3.1 制作crowbarver.0.1 语言的基础部分 062 3.1.1 crowbar是什么 062 3.1.2 程序的结构 063 3.1.3 数据类型 064 3.1.4 变量 064 补充知识 初次赋值兼变量声明的理由 066 补充说明 各种语言的全局变量处理 067 3.1.5 语句与结构控制 067 补充知识 elif、elsif、elseif的选择 068 3.1.6 语句与运算符 069 3.1.7 内置函数 069 3.1.8 crowbar支持C语言调 070 3.1.9 从crowbar中调C语言内置函数的编写 071 3.2 预先准备 071 3.2.1 模块与命名规则 072 3.2.2 内存管理模块MEM 073 补充知识 valgrind 075 补充知识 富翁式编程 075 补充知识 符号表与扣留操作 076 3.2.3 调试模块DBG 076 3.3 crowbarver.0.1 的实现 077 3.3.1 crowbar的解释器——CRB_Interpreter 077 补充知识 不完全类型 080 3.3.2 词法分析——crowbar.l 081 补充知识 静态变量的许可范围 084 3.3.3 分析树的构建——crowbar.y与create.c 085 3.3.4 常量折叠 089 3.3.5 错误信息 089 补充知识 关于crowbar中使的枚举型定义 091 3.3.6 运——execute.c 092 3.3.7 表达式评估——eval.c 096 3.3.8 值——CRB_Value 104 3.3.9 原生指针型 105 3.3.1 0变量 106 3.3.1 1字符串与垃圾回收机制——string_pool.c 108 3.3.1 2编译与运 110 第4章 数组和mark-sweep垃圾回收器 113 4.1 crowbarver. 0.2 114 4.1.1 crowbar的数组 114 4.1.2 访问数组元素 115 4.1.3 数组是一种引类型 116 补充知识 “数组的数组”和多维数组 116 4.1.4 为数组添加元素 118 4.1.5 增加(模拟)函数调功能 118 4.1.6 其他细节 118 4.2 制作mark-sweepGC 119 4.2.1 引数据类型的结构 119 4.2.2 mark-sweepGC 121 补充知识 引和immutable 123 4.2.3 crowbar栈 124 4.2.4 其他根 127 4.2.5 原生函数的形式参数 128 4.3 实现GC本身 129 4.3.1 对象的管理方法 129 4.3.2 GC何时启动 129 4.3.3 sweep阶段 132 补充知识 GC现存的问题 133 补充知识 CopingGC 134 4.4 其他修改 136 4.4.1 修改语法 136 4.4.2 函数的模拟 137 4.4.3 左值的处理 139 4.4.4 创建数组和原生函数的书写方法 142 4.4.5 原生指针类型的修改 144 第5章 中文支持和Unicode 147 5.1 中文支持策略和基础知识 148 5.1.1 现存问题 148 5.1.2 宽字符双字节串和多字节字符串 149 补充知识 wchar_t肯定能表示1个字符吗? 150 5.1.3 多字节字符/宽字符间的转换函数群 150 5.2 Unicode 153 5.2.1 Unicode的历史 153 5.2.2 Unicode的编码方式 154 补充知识 Unicode可以固定字节长度吗? 156 5.3 crowbarbook_ver.0.3 的实现 156 5.3.1 要实现到什么程度? 156 5.3.2 发起转换的时机 157 5.3.3 关于区域设置 158 5.3.4 解决0x5C问题 158 补充知识 失败的#ifdef 160 5.3.5 应该是什么样子 160 补充知识 还可以是别的样子——CodeSetIndependent 161 第6章 制作静态类型的语言Diksam 163 6.1 制作DiksamVer0.1 语言的基本部分 164 6.1.1 Diksam的运状态 164 6.1.2 什么是Diksam 165 6.1.3 程序结构 165 6.1.4 数据类型 166 6.1.5 变量 166 6.1.6 语句和流程控制 167 6.1.7 表达式 167 6.1.8 内建函数 168 6.1.9 其他 168 6.2 什么是静态的/执字节码的语言 169 6.2.1 静态类型的语言 169 6.2.2 什么是字节码 169 6.2.3 将表达式转换为字节码 170 6.2.4 将控制结构转换为字节码 173 6.2.5 函数的实现 173 6.3 Diksamver.0.1 的实现——编译 175 6.3.1 目录结构 175 6.3.2 编译的概要 176 6.3.3 构建分析树create.c 176 6.3.4 修正分析树fix_tree.c 179 6.3.5 Diksam的运形式——DVM_Executable 185 6.3.6 常量池 186 补充知识 YARV的情况 187 6.3.7 全局变量 188 6.3.8 函数 189 6.3.9 顶层结构的字节码 189 6.3.1 0号对应表 190 6.3.1 1栈的需要量 190 6.3.1 2生成字节码generate.c 191 6.3.1 3生成实际的编码 193 6.4 Diksam虚拟机 197 6.4.1 加载/链接DVM_Executable到DVM 200 6.4.2 执——巨大的switchcase 202 6.4.3 函数调 204 第7章 为Diksam引入数组 207 7.1 Diksam中数组的设计 208 7.1.1 声明数组类型的变量 208 7.1.2 数组常量 209 补充知识 D语言的数组 210 7.2 修改编译器 210 7.2.1 数组的语法规则 210 7.2.2 TypeSpecifier结构体 212 7.3 修改DVM 213 7.3.1 增加指令 213 补充知识 创建Java的数组常量 215 补充知识 C语言中数组的初始化 217 7.3.2 对象 217 补充知识 ArrayStoreException 218 7.3.3 增加null 219 7.3.4 哎!还缺点什么吧? 219 第8章 将类引入Diksam 221 8.1 分割源文件 222 8.1.1 包和分割源代码 222 补充知识 #include、文件名、号 225 8.1.2 DVM_ExecutableList 225 8.1.3 ExecutableEntry 226 8.1.4 分开编译源代码 227 8.1.5 加载和再链接 230 补充知识 动态加载时的编译器 233 8.2 设计Diksam中的类 233 8.2.1 超简单的面向对象入门 233 8.2.2 类的定义和实例创建 237 8.2.3 继承 239 8.2.4 关于接口 241 8.2.5 编译与接口 242 8.2.6 Diksam怎么会设计成这样? 243 8.2.7 数组和字符串的方法 245 8.2.8 检查类的类型 246 8.2.9 向下转型 246 8.3 关于类的实现——继承和多态 247 8.3.1 字段的内存布局 247 8.3.2 多态——以单继承为前提 249 8.3.3 多继承——C++ 250 8.3.4 Diksam的多继承 252 补充知识 无类型语言中的继承 254 8.3.5 重写的条件 254 8.4 关于类的实现 256 8.4.1 语法规则 256 8.4.2 编译时的数据结构 258 8.4.3 DVM_Executable中的数据结构 260 8.4.4 与类有关的指令 262 补充知识 方法调、括号和方法指针 263 8.4.5 方法调 264 8.4.6 super 266 8.4.7 类的链接 266 8.4.8 实现数组和字符串的方法 267 8.4.9 类型检查和向下转型 267 补充知识 对象终结器finalizer和析构函数destructor 268 第9章 应 271 9.1 为crowbar引入对象和闭包 272 9.1.1 crowbar的对象 272 9.1.2 对象实现 273 9.1.3 闭包 274 9.1.4 方法 276 9.1.5 闭包的实现 278 9.1.6 试着跟踪程序实际执时的轨迹 281 9.1.7 闭包的语法规则 284 9.1.8 普通函数 284 9.1.9 模拟方法修改版 285 9.1.1 0基于原型的面向对象 286 9.2 异常处理机制 286 9.2.1 为crowbar引入异常 286 9.2.2 setjmp()/longjmp() 289 补充知识 Java和C#异常处理的不同 293 9.2.3 为Diksam引入异常 295 补充知识 catch的编写方法 296 9.2.4 异常的数据结构 297 9.2.5 异常处理时生成的字节码 299 9.2.6 受查异常 301 补充知识 受查异常的是与非 303 补充知识 异常处理本身的是与非 304 9.3 构建脚本 305 9.3.1 基本思路 306 9.3.2 YY_INPUT 307 9.3.3 Diksam的构建脚本 308 9.3.4 三次加载/链接 308 9.4 为crowbar引入鬼车 309 9.4.1 关于“鬼车” 309 9.4.2 正则表达式常量 310 9.4.3 正则表达式的相关函数 311 9.5 其他 312 9.5.1 foreach和迭代器crowbar 312 9.5.2 switchcaseDiksam) 314 9.5.3 enumDiksam 315 9.5.4 delegateDiksam 316 9.5.5 final、constDiksam 319 附录A crowbar语言的设计 322 附录B Diksam语言的设计 336 附录C DiksamVirtualMachine指令集 359 编程语言实化指南——写在最后 369 参考文献 375
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值