Eu tenho esta gramática raku:
#!/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));
Funciona muito bem:
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>
existe para permitir que o estado e o zip residam em uma única linha ou para abranger várias linhas. Lembre-se que se trata de um MRE, por isso procuro respostas que não alterem a Gramática, mas sim os aspectos make/made das Ações.
MAS - para agilizar meu código, gostaria de poder acessar o estado e o CEP no nível superior da method TOP($/) {}
ação de acordo com meus exemplos state2 e zipcode2. Tenho tentado "levantar" os valores de estado criados e tokenizar a árvore de correspondência - por exemplo, talvez algo como:
# doesn't work
method TOP($/) {
make $<state>.made;
make $<zip>.made;
...
}
method state-zip($/) {
make $<state>.made;
make $<zip>.made;
}
Isso é possível?
TL;DR Você não pode modificar as
Match
capturas de um objeto. Há três coisas que posso pensar que você pode fazer: Ⓐ Modificar o.made
atributo do objeto de correspondência e/ou Ⓑ Modificar$/
para usar seus atalhos e/ou Ⓒ Limpar?Você não pode modificar as
Match
capturas de um objetoO que você está perguntando é uma coisa natural de se querer fazer. Lembro-me de querer isso sozinho.
Na minha resposta a Como faço para alterar as capturas em uma gramática? ), sugeri que você não pode alterar as
Match
capturas de um objeto. E isso é verdade atualmente em Raku(do). Mas agora me pergunto se algo poderia ser feito. Voltarei a isso na última seção desta resposta..made
Modifique o atributo do objeto de correspondênciaO que sugiro por enquanto é que você use o
.made
atributo do objeto matchmethod TOP
como segue.Mantenha seu código original:
Insira o código para criar o dicionário e depois
make
:Mantenha seu código original, mas extraia dos objetos de correspondência
.made
:Modifique
$/
para usar seus atalhosNota. Esta seção é sobre como modificar (atribuir/vincular) o símbolo (variável)
$/
para que ele se refira a um objeto/valor diferente. Não se trata de modificar um objeto/valor que foi atribuído ou vinculado a$/
.A seguir está uma combinação do código da primeira seção acima com alguns ajustes. Dessa forma, seu código ainda poderá usar os
$/
atalhos usuais de.¹Adicione uma
is copy
característica para que o$/
parâmetro possa ser reatribuído:Mantenha o resto do código igual até a
make
linha:Insira uma reatribuição (ou ligação) à
$/
sua.made
carga útil:Agora seu código pode voltar aos atalhos habituais:
Nota. Ao reatribuir/vincular,
$/
você substitui a ligação original pelo objeto de correspondência original. Então isso para de funcionar:Na última seção desta resposta, esboço possíveis soluções para esse problema.
Limpe?
Talvez
Match
os objetos possam ser fornecidos com novos métodos que permitam aos usuários adicionar aliases às capturas existentes em objetos correspondentes a outros objetos correspondentes, desde que tenham sido construídos com base na mesma string de entrada?Uma ideia mais hackeada é criar uma nova classe que seja como um mutável vazio
Hash
(portanto, pode ter chaves adicionadas a ele), mas que seja inicializada com umMatch
objeto existente que esteja vinculado a um atributo de delegação (has Match $original handles **;
). O último lidaria com quaisquer pesquisas que não correspondessem a uma chave no hash, fazendo failover para fazer a pesquisa noMatch
objeto existente. (Não tenho certeza se essa é ahandles
expressão correta, mas quero postar esta atualização para poder dormir.)Notas de rodapé
¹ Qualquer dado pode ser atribuído ou vinculado a
$/
, não apenasMatch
a objetos. É sempre o caso que$0
tem o alias de$/[0]
,$1
to$/[1]
e$<foo>
to$/<foo>
e$<bar>
to$/<bar>
e assim por diante, não importa o que tenha sido atribuído ou vinculado a$/
. Na verdade, por muitos anos tenho usado$/
o que chamo de "a variável de dados", abreviação de variável "(des)estrutura de dados", de modo que "objeto de correspondência atual" é apenas um dos "variáveis de dados "são muitos usos.Seu código original:
Código adicional para criar dicionário e depois
make
:Seu código original, mas baseado em objetos de correspondência
.made
: