首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PostScript String标记

PostScript String标记
EN

Stack Overflow用户
提问于 2014-03-06 03:38:54
回答 2查看 511关注 0票数 2

我有一个循环,它使用token提取字符串中的每个单词,然后我希望能够像这样对它进行计算:

(%1%2添加%3%4添加)

但是不管你怎么写,我都会得到

代码语言:javascript
复制
    7
    add
    2  
    1

我想让它成为

代码语言:javascript
复制
   7
   3

这就是我正在使用的

代码语言:javascript
复制
{ %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
EN

回答 2

Stack Overflow用户

发布于 2014-03-07 11:00:41

我建议你在每一行的末尾写上堆栈注释。这真的很有帮助。

代码语言:javascript
复制
{ %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不会工作,因为它会在堆栈顶部找到一个字符串,而不是下面的数字。

因此,在执行之前按名称保存子字符串,然后在下一次迭代之前将其放回原处可能会更好。

代码语言:javascript
复制
    {  % 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

对于postscript的新手来说,这一部分可能更令人困惑,而不是有帮助。继续读下去,后果自负。如果你在中间迷路了,一定要看到最后一个超级简单的技巧。

postscript黑客应该问的下一个问题是:“我怎样才能做到这一点而不用这个rem名称污染名称空间?”

为此,我将使用一个疯狂的技巧,即利用loop操作符创建一个具有额外存储空间的过程体。

代码语言:javascript
复制
{ procedure body } exec
{ procedure body exit extra storage } loop

上面的两个构造都将执行procedure body,然后返回控制。但是使用带有显式exitloop可以让我们将额外的东西放入数组中。

因此,我们从上面获取内部循环。

代码语言:javascript
复制
token{}{exit}ifelse exch dup()eq{pop exec exit}if/rem exch def exec rem

将其包装在一个“退出循环”中。

代码语言:javascript
复制
{
    token{}{exit}ifelse exch dup()eq{pop exec exit}if/rem exch def exec rem
exit } loop

我们将把字符串的余数存储在exit之后。

代码语言:javascript
复制
{ 
    token{}{exit}ifelse exch dup()eq{pop exec exit}if/rem exch def exec rem
exit STR } loop

/name exch def替换为存储到数组中的代码。这个数组将是循环体的一个子数组,它只保存[ STR ]额外的存储空间。

代码语言:javascript
复制
/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

这个循环当然是直截了当的:它实际上并没有循环。因此,为了替换上面的内部循环,我们将其包装在另一个循环中。

代码语言:javascript
复制
{ {
    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标记的(内部)内循环的子数组。

代码语言:javascript
复制
%   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

所以我们需要在array10和array16处插入一个子数组20,1。在调用外部作用域中的loop之前,我们可以这样做。

代码语言:javascript
复制
{ {
    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

在那里,一个没有名字的循环。:)

请注意,我们在代码中仍然保留了虚拟名称STR,这没问题。它将解析为一个名称,并在数组中分配一个额外的插槽。它不需要在任何地方定义,因为它永远不会被执行。

对以上内容的改进。我们真的不需要模板代码中的第二个ARR。我们可以将字符串直接存储到过程数组中需要它的位置。那么我们甚至不需要“退出循环”。因此,模板变成:

代码语言:javascript
复制
% 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

代码语言:javascript
复制
{ 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。

代码语言:javascript
复制
{ 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

--

这比它需要的要复杂得多。我们可以简单地做一个小数组来对这两件事的执行进行排序。

代码语言:javascript
复制
{exec rem}

因此:

代码语言:javascript
复制
{  % 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
票数 3
EN

Stack Overflow用户

发布于 2014-03-06 16:13:01

Token只是返回堆栈上的“标记化”对象,它不会对它做任何进一步的事情。如果要执行该操作,必须检查返回对象的类型,并对可执行对象执行“exec”。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22207532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档