当前位置: 首页 > 知识库问答 >
问题:

用Perl 6语法在proto regex中传递变量

法镜
2023-03-14

将变量传递给Tokenregex规则是相当简单的。例如,的输出

grammar Foo {
    token TOP     { (.) {} <bar($0)> }
    token bar($s) { {say ~$s} .+ }
}
Foo.parse("xyz")

只是x。但是当使用proto时,事情变得不对劲了。例如,1让我们制作一个简单的原型来区分字符串的其余部分是字母还是数字:

grammar Foo {
    token TOP     { (.) {} <bar($0)> }
    proto token bar { * }
          token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
          token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}

Foo.parse("xyz")

这个炸弹,声称它期望1个参数,但得到2个。好的,在普通方法中,我们必须在proto声明中指定args,所以让我们声明:

grammar Foo {
    token TOP     { (.) {} <bar($0)> }
    proto token bar ($s) { * }
          token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
          token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}

Foo.parse("xyz")

现在我们得到了相反的结果:预期有2个参数,但得到了1个。嗯,也许这意味着proto声明正在吞噬这个值,而没有传递任何东西。所以我试着把它塞进去:

grammar Foo {
    token TOP     { (.) {} <bar($0)> }
    proto token bar (|) { * }
          token bar:sym<a> ($s) { {say ~$s} <alpha>+ }
          token bar:sym<1> ($s) { {say ~$s} <digit>+ }
}

Foo.parse("xyz")

这里同样的错误。它声称它预期2个参数,但得到1个参数。2不知何故,proto的使用正在吞噬参数。目前,我找到的唯一解决方案使用动态变量,这让我认为可能有一些隐藏的步骤,其中变量没有从原型传递到候选人。

grammar Foo {
    token TOP     { (.) {} <bar($0)> }
    proto token bar ($*s) { * }
          token bar:sym<a> { {say ~$*s} <alpha>+ }
          token bar:sym<1> { {say ~$*s} <digit>+ }
}

Foo.parse("xyz")

但这似乎不是一个完全直观的步骤。如何以非动态方式将变量直接传递给proto,以使候选对象接收到它?

[1] 请注意,上面的所有代码都将重点放在传递变量上。实际使用的代币与我的真实代码没有任何相似之处
[2]我也开始怀疑这是否(一般来说)是一条LTA错误消息。虽然我知道它是基于first arg=invocant的,但它仍然让人感觉不舒服。也许它应该说“预期发票和一个参数,仅收到发票”之类的话。


共有2个答案

印振国
2023-03-14

第一件事是我真的不明白你打算在这里做什么。我的印象是,您希望令牌的第二部分是第一部分的函数。我不明白你为什么在这里用原型。您可以通过以下方式立即执行此操作:

grammar Foo {
    token TOP     { (.) {} <bar($0)> }
    token bar( $s )  { {say ~$s} $s <alpha>+ }
}

say Foo.parse("xxz")

但我不确定你能不能把符号和参数结合起来syms已经有一个参数:副词中使用的参数。它不仅仅是一个符号,它是要匹配的(如果您使用预定义的标记

grammar Foo {
    token TOP     { (.) {} <bar> }
    proto token bar {*}
    token bar:sym<alpha>  { <alpha>+ }
    token bar:sym<digit>  { <digit>+ }
}

say Foo.parse("xxz");
say Foo.parse("x01")

或者简单地使用字符串作为sym匹配:

grammar Foo {
    token TOP     { (.) {} <bar>+ }
    proto token bar {*}
    token bar:sym<x>  { <sym>+ }
    token bar:sym<z>  { <sym>+ }
    token bar:sym<1>  { <sym>+ }
    token bar:sym<0>  { <sym>+ }
}

say Foo.parse("xxz");
say Foo.parse("x01")

所以我想说,Raiph的答案是你想去的地方syms似乎不是实现这一点的正确方法,因为它们有一个内置变量(sym的参数),但您必须指定每种情况。

厍胤运
2023-03-14

TL; DR

>

我有一个替代方法,用于传递非动态参数。但是看到下一点。

你解释你打高尔夫球的后续评论表明你的动态变量选择可能更好。我也会讨论的。

将原始令牌转换为原始方法

grammar Foo {
  token TOP { (.) {} <bar($0)> }
  proto method bar ($s) {*}
  multi token bar ($s where /<alpha>+/) { {say 'alpha start ', $s} .. }
  multi token bar ($s where /<digit>+/) { {say 'digit start ', $s} .. }
}

say Foo.parse("xyz")

显示:

alpha start 「x」
「xyz」
 0 => 「x」
 bar => 「yz」

在我的实际代码中,变量被传递来阻止某些匹配(主要是为了避免某些类型的递归)

听起来你可以有一个单一的动态变量(比如$*nope),设置为你想要的任何值,然后系统地使用它。或者是一对。动态变量正是为这类事情而设计的。除了在意识形态上对动态变量感到不安(在某种程度上,它们被不小心地用作不受约束的全局变量——它们是坏消息)之外,还有什么不喜欢的呢?

 类似资料:
  • 我正在尝试使用Perl6语法实现Markdown解析器,但被块引号卡住了。块引号段落不能用嵌套大括号表示,因为它是一个特定格式行的列表。但从语义上讲,它是一个嵌套的标记。 基本上可以归结为以下定义: mdBQLine令牌的实际实现与此无关。唯一需要注意的是,mdBQLineBody键包含实际引用的带有

  • 对于在带有@Given注释的方法中实例化的实例变量,我得到一个NullPointerException,如下面代码中的“test”所示: 我已经看到了各种示例(倒数第二个代码示例)和资源(这个答案的第一段),它们说这应该没问题,因为DI只有在尝试在步骤定义Java类之间共享状态时才是必要的,而不是在类本身中。 我有没有遗漏什么,或者有没有办法让这件事奏效?

  • 问题内容: 如何在JavaScript中通过引用传递变量?我要对3个变量执行一些操作,因此我想将它们放在for循环中并对每个变量执行操作。 伪代码: 做这个的最好方式是什么? 问题答案: JavaScript中没有可用的“通过引用传递”。您可以传递一个对象(也就是说,您可以按值传递对一个对象的引用),然后让一个函数修改该对象的内容: 您可以使用数字索引遍历数组的属性,并根据需要修改数组的每个单元格

  • 我刚刚开始探索perl6语法。如何创建一个标记“行”来匹配行首和行尾之间的所有内容?我尝试了以下方法,但没有成功:

  • 问题内容: 我试图将变量传递到Puppeteer中的函数中,但是当我使用以下非常简单的示例时,该变量未定义。 我是Puppeteer的新手,找不到任何可构建的示例,因此我需要帮助将该变量传递到函数中,以便在内部使用它。 问题答案: 您必须像这样将变量作为参数传递给:

  • 问题内容: 我正在尝试将有角度的应用程序从gulp转换为webpack。在gulp中,根据NODE_ENV,我使用gulp- preprocess替换html页面中的某些变量(例如,数据库名称)。使用webpack达到类似结果的最佳方法是什么? 问题答案: 有两种基本方法可以实现此目的。 定义插件 请注意,这只会按原样替换匹配项。这就是字符串具有其格式的原因。您可能有一个更复杂的结构,例如那里的一