【问题标题】:Perl6: Adding a sigil with SlangsPerl6:用俚语添加印记
【发布时间】:2019-03-09 15:59:34
【问题描述】:

我正在尝试添加«€»作为«$»标量的别名,我认为使用俚语是这样做的。但是 perl6.doc 根本没有提到俚语。

我已阅读以下内容:

并查看了 Slang::Roman 和 Slang::Tuxic 模块。

结果是这个文件(ScalarEU.pm6):

use nqp;

unit module ScalarEU2;

sub EXPORT(|)
{
  my role Euscalar
  {
    token sigil:sym<$> { '€' | '$' }
  }

  my Mu $MAIN-grammar := nqp::atkey(%*LANG, 'MAIN');
  my $grammar := $MAIN-grammar.HOW.mixin($MAIN-grammar, Euscalar);

  $*LANG.define_slang('MAIN', $grammar, $*LANG.actions);

  {}
}

然后是一个程序(称为hello)使用它:

use lib "lib";

use ScalarEU;

sub MAIN ($name)
{
  say "Hello, €name!";
}

但它不起作用,或者更确切地说,它没有做它应该做的事情:

$ ./hello Tom
Hello, €name!

(我这样写程序是为了它不会崩溃。)

我还没有添加动作类,但是设置“令牌印记”的方式不应该要求这样做吗?但这个假设是基于 11 年的文章,可能是错误的。

另外,https://github.com/rakudo/rakudo/issues/2404 表示 $*LANG 已过时,应改为使用 $?LANG。 REPL 同意:

> $*LANG
Dynamic variable $*LANG not found

> $?LANG
(low-level object `Perl6::Grammar`)

但是程序可以同时使用这两种方法,而不会出错。 (我试过了。)

【问题讨论】:

  • 从技术上讲,俚语是 Rakudo Perl 6 编译器的一个特性。它还没有被添加到 Perl 6 规范中,因为它还不够好。有一种名为007 的玩具语言主要用于设计它的工作方式。
  • 在 Rakudo 源代码中散布着许多文字 $s,在其语法和动作之外,这是使 $ 印记起作用的部分原因。 (对于@% 等也是类似的。)当然,从技术上讲,制作一个修改后的 Rakudo 让你可以做你想做的事情。甚至可以在不影响 Rakudo 性能的情况下做到这一点。但这将是很多无聊的小编辑(同样,在俚语的语法/动作之外),我怀疑你很难说服核心开发人员将你的更改合并回 Rakudo 主分支。跨度>
  • (继续)许多文字 $s 与内部变量有关,因此这些无关紧要。看起来其余的一些也无关紧要或无关紧要。例如issigil。但是像 %cont_info&lt;sigil&gt; eq '$'$sigil eq '$' 这样的代码,从单个源文件中选择几个随机示例,看起来会。
  • 好的。所以这是不可能的。我的第一个想法是这样的:使用 MONKEY-TYPING;增强语法 Perl { token sigil:sym { '€' | '$' } } 我的€a = 12;如果那行得通,那就太好了。但我知道 BEGIN 开始太晚了。
  • 感谢您的回复。我刚刚在perl6.eu 发布了结果

标签: syntax raku


【解决方案1】:

简而言之:您必须更改ParseShared nqp 对象的$!target 字符串,这会在解析时更改代码。

为什么: sigil 令牌不再是原型,而是将 rakudo/src/Perl6/Grammar.nqp 定义为替代。

所以作为一个最小的解决方案:token sigil { &lt;[$@%&amp;€]&gt; },但随之而来的新问题是:返回值可以是,并用于其他语法。

地点: 所以你必须将nqp/src/QRegex/Cursor.nqp中定义的$&lt;sigil&gt;.Str改成:

method Str()       {
   $!pos >= $!from
        ?? nqp::substr(nqp::getattr_s($!shared, ParseShared, '$!target'),
            $!from, nqp::sub_i(self.to, $!from))
        !! '' }

The string in target between from and to if pos is not so low.

-> 所以我们必须在NQPMatch 中在$!from$!to 之间更改$!target

演示: 这是嵌入俚语语法的代码:

token sigil {
    | <[$@%&]>
    | <nogil> { say "Nogil returned: ", lk($/, 'nogil').Str; }
}

method nogil {
    # The object to return
    my $cursor := self.nogil-proxy;

    # Get from cursor
    my $shared := nqp::getattr($cursor, NQPMatch, '$!shared');
    my $from = nqp::getattr_i($cursor, NQPMatch, '$!from');
    my $target = $cursor.target;

    # Replace in target current character (€) by $
    $target.substr-rw($from, 1) = '$';

    # Set in cursor
    nqp::bindattr_s($shared, $shared.WHAT, '$!target', $target);

    # Return the "created by proxy" and modified NQPMatch
    return $cursor;
}

token nogil-proxy { '€' }

单独说:_ 它应该在您的情况下完美运行。在我的,(没有印记)我仍然有问题,因为在 $!target 修改期间大小的变化弄乱了其他游标的 tofrom。在这种情况下:

  1. 我必须overwrite NQPMatch.Str function(希望有可能)。
  2. 我必须列出游标(如果可能)并明智地更改它们的$!from$!to 属性,以恢复银河系或至少在客户端代码中的和平。

【讨论】:

  • 我为我非常相关的问题创建了另一个post:启用&lt;?&gt; -> 根本没有标记,让调用者相信有一个“$”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-31
  • 2016-03-20
  • 1970-01-01
  • 1970-01-01
  • 2017-05-31
  • 1970-01-01
相关资源
最近更新 更多