【问题标题】:Raku: Mutually recursive tokens cause a "method not found" errorRaku:相互递归令牌导致“未找到方法”错误
【发布时间】:2021-06-18 21:43:54
【问题描述】:

我已经简化了一个更复杂的模式,我试图匹配以下程序:

my token paren { '(' <tok> ')' }
my token tok { <paren>? foo }

say "(foo)foo" ~~ /<tok>/;

这对我来说似乎很简单,但我得到了这个错误:

No such method 'tok' for invocant of type 'Match'.  Did you mean 'to'?
  in regex paren at a.p6 line 1
  in regex tok at a.p6 line 2
  in block <unit> at a.p6 line 4

这个错误的原因是什么?

如果我将第一个 &lt;tok&gt; 更改为 &lt;&amp;tok&gt;,则该模式匹配没有错误,但是我没有捕获该命名模式,在我原来的更复杂的情况下,我需要它。

【问题讨论】:

    标签: regex raku


    【解决方案1】:

    问题是tok 还没有在当前的词法命名空间中,所以&lt;tok&gt; 被编译为一个方法调用。

    如果你用&amp;强制它是一个词法调用,它会起作用。

    my token paren { '(' <&tok> ')' }
    my token tok { <paren>? foo }
    
    say "(foo)foo" ~~ /<tok>/;
    

    如果&lt;…&gt; 以其他字母开头,则它不会捕获。

    所以要以tok 的名义捕获它,我们将tok= 添加到&lt;…&gt;

    my token paren { '(' <tok=&tok> ')' }
    my token tok { <paren>? foo }
    
    say "(foo)foo" ~~ /<tok>/;
    

    【讨论】:

      【解决方案2】:

      Brad 的回答是正确的,但我想提供另一种可能的解决方案:您可以使用特殊的 &lt;~~&gt; token 在单个正则表达式中递归。使用它,加上一个常规的命名捕获,将在您的问题的简化示例中创建您想要的捕获;看起来是这样的:

      my token paren { $<tok> = ['(' <~~> ')']? foo }
      

      我不确定是否可以轻松地重写您的更复杂的案例以对其自身进行递归,而不是使用两个相互递归的令牌。但是,当这种模式起作用时,它可以大大简化代码。

      【讨论】:

        猜你喜欢
        • 2013-06-01
        • 1970-01-01
        • 2017-02-24
        • 2018-10-31
        • 1970-01-01
        • 2021-08-15
        • 1970-01-01
        • 1970-01-01
        • 2022-12-14
        相关资源
        最近更新 更多