1700436810
1700436811
1700436812
1700436813
1700436814
图5-7 洛琳达·彻丽,约1981年(杰勒德·霍尔兹曼供图)
1700436815
1700436816
洛琳达一直在探索如何实现数学符号输出工具,而我希望有一种语言能像数学家朗读数学内容那样直观。我想,关于这种语言的想法根植于我的潜意识里,因为我还在读研时,就曾自愿加入“为盲人录音”(Recording for the Blind[7])项目,朗读技术书籍并录制下来。这项工作持续了好几年,所以我花了很多时间口述数学内容。
1700436817
1700436818
Eqn能很好地处理简单数学表达式。例如,级数求和:
1700436819
1700436820
1700436821
1700436822
1700436823
写作:
1700436824
1700436825
sum from i=0 to inf 1 over 2 sup i = 2
1700436826
1700436827
1700436828
1700436829
1700436830
1700436831
事实证明,数学打字员很容易学会Eqn,其他人也很容易学会,实践证明它比手工打字机快得多。这种语言非常简单,连物理学博士也能掌握。没过多久,人们就开始自己动手打字,不再依赖专业打字员。Eqn是启发高德纳(Don Knuth)开发TeX(1978)中数学模式的灵感之一。TeX已成为数学内容输入的标准。
1700436832
1700436833
Eqn是作为Troff的预处理器来实现的,通常用法是把Eqn的输出通过管道引入Troff中,就像这样:
1700436834
1700436835
eqn file | troff >typeset.output
1700436836
1700436837
1700436838
1700436839
1700436840
1700436841
Eqn识别数学结构,并将其转化为Troff命令,而其他内容则不做处理。预处理器式方法干净爽利地切出两种语言和两种程序,用于不同目的。PDP-11的物理限制逼着洛琳达和我想出这个好主意。由于内存限制,Troff已经是单个程序所能达到的最大尺寸,不能再添加处理数学内容的功能。再者,即使我们想修改Troff,乔·奥桑纳也不会容许我们碰它。
1700436842
1700436843
Eqn语言基于盒子模型:表达式由一系列盒子组成,这些盒子相互决定位置和大小。例如,分数是一条长线将分子盒和分母盒上下分开。像xi这样的下标表达式是一对盒子,其中第二个盒子的内容尺寸较小,位置比第一个盒子略低。
1700436844
1700436845
我们用史蒂夫·约翰逊新发明的编译器-编译器Yacc来定义语法,并将语义挂接上去。Eqn是首个基于Yacc的语言,不同于传统语言的传统编译器。就我自己而言,如果没有Yacc,Eqn不会出现,因为我不肯为一门新语言亲手写语法分析器。语法太复杂,而且在我和洛琳达试验语法的时候,经常会改动它,所以不适合写专门的语法分析器。我们使用Yacc的经验有力地说明,有了好的工具,就能做一些原本太难甚至无法想象的事情。
1700436846
1700436847
为不同类型的难以排版的材料提供预处理器是个好主意。在Eqn面世之后不久,迈克尔·莱斯克创造了Tbl,它提供了相当不一样的语言来制作复杂表格。莱斯克还写了用于管理文献引用的Refer程序。管理文献引用对技术论文来说非常重要。
1700436848
1700436849
本章介绍的许多程序都是预处理器,也就是将一些语言转换成适合后续处理的形式的程序。C++的最初版本Cfront,更准确的描述是C语言的面向对象的预处理器,最终演变成了C++。有时,随着功能被吸收到下游处理环节中,预处理器最终消失了,就像C++那样。更多情况下,预处理器继续独立存在,就像文档编制工具Eqn和Tbl。另一个例子是bc[8],它是dc[9]的预处理器。dc是鲍勃 · 莫里斯原作的不限精度计算器。洛琳达·彻丽编写bc是为了给dc提供传统算术符号,因为dc的后缀式符号对于新手来说太难了。
1700436850
1700436851
预处理器有很多优点。首先,在实现一种语言时,不会受到现有语法的限制,可以使用完全不同的风格,如各种Troff预处理器。其次,内存很小时,根本没办法在已经很大的程序中加入更多功能,Troff的情况尤其如此。最后,因为预处理器有输出,所以可以在继续传递之前对其进行操作,执行其他类型的数据处理。在文档编制套件中,我经常使用sed脚本等预处理器来修正字符集和间距。克里斯 · 范·维克(Chris Van Wyk)和我写了一些程序,通过修改Troff的输出,在页面传送到设备驱动程序之前,对它进行纵向对齐处理。这些功能无法整合到单一程序,在管道流水线中处理时,就很容易在前面或后面或中间添加新的环节。
1700436852
1700436853
4.与设备无关的Troff
1700436854
1700436855
1700436856
1700436857
1700436858
1700436859
乔·奥桑纳于1977年去世,享年48岁。他的部分遗产是Troff源代码。那近万行难以捉摸的C语言代码,是乔从原本的汇编语言形式手工翻译出来的——缺乏注释,几十个双字母名称的全局变量,以及(见前文关于内存的讨论)各种小技巧,把尽可能多的信息塞进不够多的内存。乔认为,这样做绝对有必要,因为得把Troff的所有功能打包到65 KB中,那是当时我们使用的PDP-11/45上用户程序可用的最大内存。
[
上一页 ]
[ :1.70043681e+09 ]
[
下一页 ]