我试图了解在Free Pascal中看到的某种神奇的行为,该行为在Linux下以Turbo模式(特别是fpc -Mtp -vw
)编译。该代码来自Jack Crenshaw的“让我们构建编译器”第四部分,特别是在http://www.pp4s.co.uk/main/tu-trans-comp-jc-04.html找到带有Input
和Output
过程的最新版本。
我发现“神奇”是Read(Table[GetName]);
过程中的Input
行。根据FP文档,“ Read
从文件F中读取一个或多个值,并将结果存储在V1,V2等中;如果未指定文件F,则将读取标准输入。”
在Read
过程中的GetChar
中,它的行为看起来很像C的getchar()
,即从stdin缓冲区中检索下一个字符。相反,在Input
调用中,它看起来像复杂的scanf()
,它会自动跳过空白并将多位数字转换为Integer,从而消除了对GetNum
函数的需要。如果使用?i 345
则不会被调用,但是如果尝试i=345
则会被调用,并且如果在=
的两边都留有空格,则会导致解析错误。
还有其他一些文档可以证明Free,Turbo甚至是通用Pascal的Read
的明显多功能性吗?
答案 0 :(得分:4)
Pascal的读写例程是不可思议的。 IOW,它不是某个库中存在的实际函数,但是编译器会生成对运行时的一系列调用。该系列由read,readln,write和writeln以及扩展的Pascal readstr和writestr组成,它们是读写的“从字符串”版本。
这些调用根据参数的类型以及是否具有额外的参数而有所不同(例如,write表示整数的:x格式值,对于实数表示:x:y):
writeln(x:10:5);
在Free Pascal中,与Turbo Pascal和Delphi相反,一些类似RTTI的功能也被公开,例如writeln()是枚举类型的变量,将把枚举的值打印为标识符(字符串)。
错误处理和格式有所限制,因此它们的用法随问题的复杂性而变化
根据您的观察,类似getchar的调用可能读取了char类型的变量,而其他函数的类型却不同。
答案 1 :(得分:1)
我发现了有关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中,给函数名称赋值就是您返回值的方式,因此他在这里所说的是“我的超前字符是数字吗?如果是,请对其进行解码并返回它,然后再读取一个新的超前字符字符,否则中止。”在本章的后面,他将扩展此定义以处理多个数字。杰克实际上在上一章中处理了空格,请在其中查找SkipWhite。