You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否将Raku Grammar中state和zipcode的made值提升至TOP层级?

问题描述

我编写了如下Raku语法规则(Grammar)及对应的Actions类:

#!/usr/bin/env raku
use v6.d;

use Grammar::Tracer;

grammar Grammar {
    token TOP {
          <city>      \v
          <state-zip> \v?
    }
    token city {
        ^^ \V* $$
    }
    token state-zip {
        ^^ <state> <.ws>? <zipcode> $$    #<.ws> is [\h* | \v]
    }
    token state {
        \w \w
    }
    token zipcode {
        \d ** 5
    }
}

class Actions {
    method TOP($/) {
        #works
        say "city is ",    $_ with $<city>.made;
        say "state is ",   $_ with $<state-zip><state>.made;
        say "zipcode is ", $_ with $<state-zip><zipcode>.made;

        #doesn't work
        say "state2 is ",   $_ with $<state>.made;
        say "zipcode2 is ", $_ with $<zipcode>.made;
    }

    method city($/)     { make ~$/ }
    method state($/)    { make ~$/ }
    method zipcode($/)  { make ~$/ }
}

my $address = q:to/END/;
Springfield,
IL 62704
END

Grammar.parse($address, :actions(Actions));

当前代码运行正常,输出如下:

TOP
|  city
|  * MATCH "Springfield,"
|  state-zip
|  |  state
|  |  * MATCH "IL"
|  |  zipcode
|  |  * MATCH "62704"
|  * MATCH "IL 62704"
city is Springfield,
state is IL
zipcode is 62704
* MATCH "Springfield,\nIL 62704\n"

其中token <state-zip>用于支持州(state)与邮编(zipcode)在同一行或跨行。这是最小可复现示例,我希望不修改Grammar规则,仅通过调整Actions中的make/made逻辑,实现在TOP方法中直接访问state和zipcode的made值(即示例中state2和zipcode2的访问方式),请问是否可行?

解决方案

可行。核心思路是在state-zip的Action方法中,把内部state和zipcode的made值向上绑定到当前匹配对象的哈希结构中,让TOP方法能直接访问到这些值。

修改后的Actions类如下:

class Actions {
    method TOP($/) {
        # 原有可用代码保留
        say "city is ",    $_ with $<city>.made;
        say "state is ",   $_ with $<state-zip><state>.made;
        say "zipcode is ", $_ with $<state-zip><zipcode>.made;

        # 现在可以正常工作
        say "state2 is ",   $_ with $<state>.made;
        say "zipcode2 is ", $_ with $<zipcode>.made;
    }

    method city($/)     { make ~$/ }
    method state($/)    { make ~$/ }
    method zipcode($/)  { make ~$/ }
    
    # 新增state-zip方法,将内部子规则的made值绑定到当前匹配对象
    method state-zip($/) {
        # 把state和zipcode的made值挂载到当前$/的哈希表,让上层可直接访问
        $/<state> = $<state>.made;
        $/<zipcode> = $<zipcode>.made;
        # 可选择make一个包含两者的结构,不影响上层访问逻辑
        make { state => $<state>.made, zipcode => $<zipcode>.made };
    }
}

原理说明

  • Raku的匹配对象$/本质是哈希结构,子规则的匹配结果以键值对形式存储其中。
  • 默认情况下,state和zipcode的匹配结果仅存在于state-zip的子匹配对象中,TOP方法无法直接访问。
  • 通过在state-zip的Action方法中,将state和zipcode的made值赋值给当前$/的对应键,相当于把这些值“提升”到了上层匹配对象的作用域中,这样TOP方法就能通过$<state>和$<zipcode>直接获取到它们的made值。

内容的提问来源于stack exchange,提问作者librasteve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 19:27:28