我试图理解fpc -Mtp -vw
在 Linux 下以 Turbo 模式(特别是)编译的 Free Pascal 中出现的一种有点神奇的行为。代码来自 Jack Crenshaw 的“Let's Build a Compiler”,第 IV 部分,特别是带有Input
和Output
过程的最后一个版本,可在http://www.pp4s.co.uk/main/tu-trans-comp-jc-04找到.html。我发现“神奇”的是程序中的Read(Table[GetName]);
一行Input
。根据 FP 文档,“Read
从文件 F 中读取一个或多个值,并将结果存储在 V1、V2 等中;如果未指定文件 F,则读取标准输入。” 在过程Read
中GetChar
,它的行为似乎很像 C getchar()
,即从标准输入缓冲区中检索下一个字符。在里面Input
调用它反而看起来像一个复杂scanf()
的自动跳过空格并将多位数字转换为整数,并消除了对GetNum
函数的需要,如果您使用例如,则不会调用该函数,?i 345
但如果你试试i=345
,如果你在结果的两边留一个空格,就会=
导致解析错误。是否有其他文档可以证实 Free、Turbo 甚至通用 Pascal 的明显多功能性Read
?
2 回答
Pascal 读、写例程很神奇。IOW 它不是某个库中存在的真实函数,但编译器会在运行时生成一系列调用。该系列包括 read、readln、write 和 writeln,以及扩展的 Pascal readstr和writestr,它们是 read 和 write 的“from string”版本。
调用取决于参数的类型,以及它们是否有额外的参数(例如 write 采用 :x 格式化值表示整数和 :x:y 表示实数):
writeln(x:10:5);
在 Free Pascal 中,与 Turbo Pascal 和 Delphi 不同,一些类似 RTTI 的功能也被暴露出来,例如 writeln() 一个 enum 类型的变量,会将 enum 的值打印为标识符(字符串)。
错误处理和格式化在一定程度上受到限制,因此它们的使用随问题的复杂性而变化
至于你的观察,你的 getchar 之类的调用可能读取了一个 char 类型的变量,而另一个函数的类型是不同的。
找了一点关于Pascal的Read procedure的资料,说明它不像C的getchar()
,会自动正确填写各种类型。但这不是你要问的有趣的东西。
Jack 的编译器有一个GetChar()
填充Look
变量的过程;这是一个单字符的前瞻,它在解析器中相当普遍,尽管这些天通常隐藏在多层包装纸下。但是 Jack 的所有方法都知道这个变量,这就是为什么他们先检查它,然后GetChar()
在结束时再次调用,例如:
{ Get a number }
function GetNum : integer;
begin
if not IsDigit(Look) then
Expected('Integer');
GetNum := Ord(Look) - Ord('0');
GetChar;
end;
请记住,在 Pascal 中,分配给函数名称是您返回值的方式,所以他在这里所做的是说“我的前瞻字符是数字吗?如果是,解码并返回它,然后读取一个新的前瞻字符,否则中止。” 在本章后面,他将扩展这个定义来处理多个数字。Jack 实际上在前一章中处理了空格,在那里寻找SkipWhite。