PostScript字符串令牌 [英] PostScript String Token
问题描述
我有一个循环,该循环使用令牌取出字符串中的每个单词,然后我希望能够像这样进行计算:
I have a loop that takes out each word in a string using token, then I want to be able to do computations on it like this:
(1 2加3 4加)
但是无论用什么方式编码,我都会不断得到
But any way you code it i keep getting
7
add
2
1
我要
7
3
这就是我的工作
{ %loop
pstack
(repl> )print flush
(%lineedit)(r)file
dup bytesavailable string readstring pop
{
token
{}{exit}ifelse
exch
dup () eq {pop exec exit}if
exec
}loop
}loop
推荐答案
我建议您最后写堆栈注释每行。
I would advise you to write stack comments at the end of each line. It really helps.
{ %loop
pstack
(repl> )print flush
(%lineedit)(r)file % f
dup bytesavailable string readstring pop % s
{
token % s t b
{}{exit}ifelse % s t
exch % t s
dup () eq {pop exec exit}if % t s
exec % t
}loop
}loop
因此,您正在执行其余的子字符串而不是令牌。在内部循环中的 exec
之前,您还需要另一个 exch
。那将执行令牌而不是子字符串。但是与此有关的一个问题是字符串位于堆栈上。因此 add
将不起作用,因为它将在堆栈顶部找到一个字符串,而不是下面的数字。
So you're executing the remaining substring instead of the token. You need another exch
in there before the exec
in the inner loop. That would execute the token instead of the substring. But a problem with this is that the string is sitting there on the stack. So add
won't work because it will find a string on top of the stack instead of the numbers below.
因此,最好在执行前按名称保存子字符串,然后在下一次迭代之前将其放回去。
So it may be better to save the substring by name before exec-ing, and then put it back before the next iteration.
{ % s
token % s t b
{}{exit}ifelse % s t
exch % t s
dup () eq {pop exec exit}if % t s
/rem exch def % t
exec
rem % s
}loop
对于刚起步的人来说,这部分可能比帮助更令人困惑。 如果您迷失在中间,请确保从头到尾看到最终的超级简单技术。
后记黑客应该问的下一个问题是:如何在不使用此 rem $ c $污染名称空间的情况下做到这一点? c>名称?
The next question a postscript hacker should ask is: "How can I do this without polluting the name space with this rem
name?"
我为此使用的疯狂技巧是利用 loop
运算符具有额外存储空间的过程主体。
The insane trick I would use for this is to exploit the loop
operator to make a procedure body with extra storage.
{ procedure body } exec
{ procedure body exit extra storage } loop
以上两个构造都将执行程序体
,然后返回控制。但是,将 loop
与明确的 exit
结合使用,我们可以将多余的东西打包到数组中。
Both constructs above will execute procedure body
and then return control. But using loop
with an explicit exit
lets us pack extra things into the array.
因此,我们从上面进行内循环。
So, we take the inner loop from above.
token{}{exit}ifelse exch dup()eq{pop exec exit}if/rem exch def exec rem
将其包装在出口中-loop。
Wrap it in an "exit-loop".
{
token{}{exit}ifelse exch dup()eq{pop exec exit}if/rem exch def exec rem
exit } loop
然后我们要存储 exit
之后的字符串剩余部分。
And we're going to store the string remainder just after exit
.
{
token{}{exit}ifelse exch dup()eq{pop exec exit}if/rem exch def exec rem
exit STR } loop
用存储在数组中的代码替换 / name exch def
。该数组将是循环主体的子数组,其中仅包含 [STR]
额外的存储空间。
Replace the /name exch def
with code that stores into an array. This array will be a subarray of the loop body which just holds the [ STR ]
extra storage.
/rem exch def --> ARR exch 0 exch put
rem --> ARR 0 get
{
token{}{exit}ifelse exch dup()eq{pop exec exit}if ARR exch 0 exch put exec ARR 0 get
exit STR } loop
当然,此循环是直截了当的:实际上并没有循环。因此,要从上方替换内部循环,请将其包装在另一个循环中。
This loop is of course a straight-shot: it doesn't actually loop. So to replace the inner loop from above, we wrap it in another loop.
{ {
token{}{exit}ifelse exch dup()eq{pop exec exit}if ARR exch 0 exch put exec ARR 0 get
exit STR } loop } loop
然后,我们需要在代码中的 ARR
处插入子数组。这是(内部)内部循环的子数组,其中包含(虚拟) STR
令牌。
Then we need to insert the subarray where ARR
is in the code. This is the subarray of the (inner) inner loop that contains the (dummy) STR
token.
% 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
{ { token{}{exit}ifelse exch dup()eq{pop exec exit}if ARR exch 0 exch put exec ARR 0 get exit STR } loop } loop
子数组[20,1]将插入到数组[10]和数组[16]处。我们可以在外部范围调用 loop
之前完成此操作。
So we need a subarray [20, 1] to be inserted at array[10] and array[16]. And we can do this before calling loop
at the outer scope.
{ {
token{}{exit}ifelse exch dup()eq{pop exec exit}if ARR exch 0 exch put exec ARR 0 get
exit STR } loop }
dup 0 get % loop-body inner-loop get a copy of the exit-loop
dup 20 1 getinterval % loop-body inner-loop [STR] take a subarray of the exit-loop
2 copy 10 exch put % loop-body inner-loop [STR] insert in position 10
16 exch put % loop-body' insert in position 16
loop % call the loop operator
那里是一个没有名字的循环。 :)
There, a loop with no name. :)
注意,我们在代码中仍然有虚拟名称 STR
,这没关系。它将解析为一个名称,并在数组中分配一个额外的插槽。而且不需要在任何地方定义它,因为它永远不会执行。
Notice, we still have the dummy name STR
in the code, and that's ok. It will parse as a name and allocate an extra slot in the array. And it doesn't need to be defined anywhere because it never gets executed.
对上述内容的改进。我们确实不需要模板代码中的第二个 ARR
。我们可以将字符串直接存储到过程数组中所需的位置。然后,我们甚至不需要退出循环。因此模板变为:
An improvement over the above. We really do not need the second ARR
in the template code. We can store the string directly into the procedure array at the position where it is needed. Then we don't even need the "exit-loop". So the template becomes:
% 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
{ token{}{exit}ifelse exch dup()eq{pop exec exit}if ARR exch 0 exch put exec STR } loop
和完全铰接的循环
{ token{}{exit}ifelse exch dup()eq{pop exec exit}if ARR exch 0 exch put exec STR }
dup dup 10 exch % loop loop 10 loop prepare stack
16 1 getinterval % loop loop 10 [STR] take a subarray
put % loop insert in position 10
loop % call loop operator
改进的改进。我们实际上也不需要子数组。我们可以将整个循环数组存储在ARR位置,并在存储代码中使用索引16而不是0。
An improvement of the improvement. We don't actually need a subarray either. We can store the entire loop array in the ARR position and use the index 16 instead of 0 in the storing code.
{ token not{exit}if exch dup()eq{pop exec exit}if ARR exch 16 exch put exec STR }
dup 10 1 index % loop loop 10 loop prepare stack
put % loop insert in position 10
loop % call loop operator
-
更晚的时间...
这比需要的复杂得多。我们可以简单地排列一个数组来对这两件事的执行进行排序。
This is way more complicated than it needs to be. We can simply make a little array to sequence the execution of these two things.
{exec rem}
因此:
{ % s
token % s t b
not{exit}if % s t
exch % t s
dup () eq {pop exec exit}if % t s
/exec cvx exch 2 array astore cvx % t {exec s}
exec
}loop
这篇关于PostScript字符串令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!