gpt4 book ai didi

operators - PostScript 标记 token

转载 作者:行者123 更新时间:2023-12-04 23:04:56 25 4
gpt4 key购买 nike

在 PostScript 中,如果你有

[4 5 6]

您有以下 token :
mark integer integer integer mark

堆栈是这样的:
| mark |
| mark | integer |
| mark | integer | integer |
| mark | integer | integer | integer |
| array |

现在我的问题:
]-mark 运算符是文字对象还是可执行对象?

[-mark 是一个文字对象(只是数据),而 ]-mark 是一个可执行对象(因为当您看到这个 ]-mark 运算符时总是需要创建一个数组),我是否正确?

PostScript 语言引用手册第 3.3.2 节给了我:

The [ and ] operators, when executed, produce a literal array object with the en-closed objects as elements. Likewise, << and >> (LanguageLevel 2) produce a literal dictionary object.



如果两个 [ ] 操作符都是可执行的,或者只有 ] 操作符,这对我来说还不清楚。

最佳答案

概括。

所有这些特殊 token ,[ , ] , << , >> , 作为可执行名称从扫描仪中出来。 [<<被定义为产生一个标记类型对象(因此它们本身不是运算符,但它们是在所有运算符所在的 systemdict 中定义的可执行名称)。 ]>>被定义为像任何其他过程或运算符一样执行的过程或运算符。这些使用 counttomark运算符来找到左括号。但是所有这些标记都被扫描器特别处理,扫描器可以识别它们而没有周围的空白,因为它们是其分隔符集的一部分。

细节。

这一切都取决于你何时看它。让我们来看看解释器对这些标记做了什么。我将用一个字符串来说明这一点,但它的工作原理与文件相同。

所以如果你有一个输入字符串

([4 5 6]) cvx exec
cvx使文字对象可执行。程序流是一个文件对象,也标记为可执行文件。 exec将一个对象推送到执行堆栈上,解释器在内部解释器处理循环的下一次迭代中遇到它。执行程序流时,可执行文件对象位于执行堆栈的最顶部。

解释器使用 token调用扫描仪。扫描器跳过初始空白,然后读取所有非空白字符直到下一个分隔符,然后尝试将字符串解释为数字,如果失败,它就成为可执行名称。括号是定界符集的一部分,因此称为“自定界”。所以扫描器读取一个括号字符,停止读取,因为它是一个分隔符,发现它不能是一个数字,所以它产生了一个可执行文件名。
Top of Exec Stack | Operand Stack
(4 5 6]) [ |

接下来,解释器循环执行任何可执行文件(除非它是一个数组)。执行 token 意味着从字典中加载它,然后如果它是可执行的,则执行定义。 [定义为 -mark-对象,与名称相同 mark被定义为。从技术上讲,它不是运算符或程序,它只是一个定义。自动加载发生是因为名称来自带有可执行标志设置的扫描仪。
(4 5 6])  | -mark-

然后扫描器产生 4、5 和 6,它们是数字并直接推送到操作数堆栈。 6 由 ] 分隔它被推回到流上。
(])  | -mark- 4 5 6

解释器不执行这些数字,因为它们不可执行,但如果执行了,它会是一样的。执行一个数字的 Action 只是将它压入堆栈。

然后,最后扫描仪遇到右括号 ] .这就是魔法发生的地方。自定界,后面不需要任何空格。扫描程序产生可执行文件名称 ]解释器通过加载来执行它,它发现......
{ counttomark array astore exch pop }

或者可能是执行此操作的实际运算符(operator)。但是,是的。 counttomark产生元素的数量。 array创建一个该大小的数组。 astore用堆栈中的元素填充数组。和 exch pop一劳永逸地丢弃那个讨厌的标记。

对于词典, <<[ 完全相同.它掉了一个标记。然后你排列一些键值对,然后 >>是对……产生影响的程序
{ counttomark dup dict begin 2 idiv { def } repeat pop currentdict end }

做一本字典。定义所有对。弹出标记。产生字典。这个版本的过程试图通过将其双倍大小来创建一个快速字典。移动 2 idiv到之前 dup做一本小字典。

所以,为了哲学, counttomark是您使用的运算符。它需要一个特殊的对象类型,它不用于其他任何东西,标记类型对象, -mark- .其余的只是语法糖,让您可以使用这种堆栈计数功能来创建线性数据结构。

附录

这是一个模拟从 currentfile 读取的解释器循环的过程。 .
{currentfile token not {exit} if dup type /arraytype ne {exec} if }loop
exec负责 load ing(并进一步执行)任何可执行文件名称。从中可以看出 token真的是扫描仪的名字;并且不执行解释器循环直接遇到的过程(数组)( type /arraytype ne {exec} if )。

使用 token然而,在字符串上可以让你做很酷的事情。例如,您可以使用替换名称动态构造过程主体。这非常像一个 lisp 宏。
/makeadder { % n  .  { n add }
1 dict begin
/n exch def
({//n add}) token % () {n add} true
pop exch pop % {n add}
end
} def
token从字符串中读取整个过程,替换为立即计算的名称 //n以其当前定义的值。请注意,扫描器一次读取一个可执行数组,有效地执行 [ ... ] cvx在返回之前内部(在某些解释器中,例如我自己的 xpost ,这允许您绕过堆栈大小限制来构建数组,因为数组是在单独的内存中构建的。但级别 2 垃圾收集使这在很大程度上无关紧要)。

还有 bind运算符,它通过用运算符对象本身替换运算符名称来修改过程。这些技巧可帮助您在速度关键的过程(如内循环)中排除名称查找。

关于operators - PostScript 标记 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14801445/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com