Repetição e matching loops:


Palavras-chave:  some, any, opt, while.




Palavra-chave ou valor

Descrição

3 <regra>

repita a regra 3 vezes

1 3 <regra>

repita a regra de 1 a 3 vezes

0 3 <regra>

repita a regra de 0 a 3 vezes

some

repita sua (s) regra (s) enquanto (e se) obtiver um true (match) da regra. Retorna false se não obtiver pelo menos uma correspondência (faz com que a análise seja false ).

any

repita sua (s) regra (s) até obter um false (sem correspondência) da regra. Sempre retorna true para a expressão de análise.

while

veja o texto abaixo.



Número de Repetição Conhecido - Exemplos


>> parse "fogfogfog" [3 "fog"]; determined exactly

== true


>> parse "fogfogfog" [0 5 "fog"]; determined by range

== true                              


Exemplos de script para número exato de repetições:


Red[]


a:  ["fox" "dog" "owl" "rat" "elk" "cat"]


print parse a [  

   4 skip        ; see command skip at Parse/Matching

       "elk"  

       "cat"    

]


true


Red[]


a:  ["rat" "rat" "rat" "rat" "elk" "cat"]


print parse a [  

   4 "rat"

       "elk"  

       "cat"    

]


true


Ou um intervalo:


Red[]


a:  ["rat" "rat" "elk" "cat"]


print parse a [  

   0 4 "rat"        ; will return success if there is from zero up to four "rat"

       "elk"  

       "cat"    

]


true



Matching Loops:


PARSE some, PARSE any

Novamente:


some - repita a (s) regra (s) enquanto (e se) obtiver um true (correspondência) da regra. Retorna false se não obtiver pelo menos uma correspondência (faz com que a análise seja false).


any - repete a (s) regra (s) até obter um false (sem correspondência) da regra. Sempre retorna true para a expressão de análise


Ambos retornam sucesso enquanto encontrarem correspondências na entrada, a diferença é que some requer pelo menos uma ocorrência da entrada (correspondência), enquanto any retornará sucesso mesmo sem correspondência.



Red[]


a:  ["fox" "dog" "fox" "dog" "fox" "dog" "elk" "cat"]


print parse a [

       some ["fox" "dog"]

       "elk"

       "cat"

]


print parse a [

       any ["fox" "dog"]

       "elk"

       "cat"

]


true

true



Red[]


a:  ["elk" "cat"]


print parse a [

       some ["fox" "dog"]

       "elk"

       "cat"

]


print parse a [

       any ["fox" "dog"]

       "elk"

       "cat"

]


false

true


Exemplo que mostra o comportamento "loop" mais claramente:


Red []

txt: {In a one-story blue house, there was a blue person,

a blue cat – everything was blue! What color were the stairs?}


print parse txt [some [thru "blue" (print "I found blue!")] to end]


I found blue!

I found blue!

I found blue!

I found blue!

true

>>


Explicando o exemplo:


[some

       [thru "blue" (print "I found blue!")] ; essa regra vai se repetir enquanto encontrar um match

to end]


  • primeiro loop:

In a one-story blue house, there was a blue person,

a blue cat – everything was blue! What color were the stairs?

-> achou um match, então repete [thru "blue" (print "I found blue!")]


  • segundo loop:

In a one-story blue house, there was a blue person,

a blue cat – everything was blue! What color were the stairs?

-> achou um match, então repete [thru "blue" (print "I found blue!")]


  • terceiro loop:

In a one-story blue house, there was a blue person,

a blue cat – everything was blue! What color were the stairs?

->  achou um match, então repete [thru "blue" (print "I found blue!")]


  • quarto loop:

In a one-story blue house, there was a blue person,

a blue cat – everything was blue! What color were the stairs?

->  achou um match, então repete [thru "blue" (print "I found blue!")]


-> SEM match, então sai do loop de some e vai para a próxima regra:  to end, que é um match, porque simplesmente vai para o fim.


Uma vez que todas as regras acharam um match (some achou mais que um), o parse retorna  true.


PARSE while

Definitivamento não é para principiantes, como é explicado a seguir por  by @9214 do gitter.

Como a explicação é complexa e minha tradução deficiente, acredito que a leitura do original em inglês seja necessária para um completo entendimento. Desculpe.


"


>> parse x: [a 1 a 1][while [ahead ['a change quote 1 2] | 'a quote 2]]

== true

>> x

== [a 2 a 2]

>> parse x: [a 1 a 1][any [ahead ['a change quote 1 2] | 'a quote 2]]

== false

>> x

== [a 2 a 1]


A principal diferença entre while e any é que o primeiro continua executando o parse mesmo se o index não avança após uma correspondência bem-sucedida, enquanto o segundo falha tão logo o index permaneça na mesma posição, mesmo que a correspondência tenha sido bem-sucedida.


Foi por isso que eu usei o ahead - é uma regra que faz a correspondência "à frente", mas mantém o index onde está. No exemplo acima,  ahead ['a change quote 1 2] vai fazer a correspondência com sucesso, e 1 depois de "a" vai ser mudado para 2, mas a posição do input não vai avançar, porque o ahead olha para frente, enquando fica no mesmo lugar. Os resultados são:



  • Com while, primeiro ahead ... muda 1 para 2 sem avançar o input, mas uma vez que while não se importa com isso, ele vai para a próxima iteração, na qual uma regra de alto nível vai falhar e dar um passo atrás (uma opção após  | ) para  'a quote 2, que vai dar uma corrêspondência bem-sucedida (porque nós acabamos de mudar a 1  para  a 2  e avançar o input, assim nos levanod ao marcador  end e fazendo o parsing bem sucedido de toda a série.


  • Entretanto, com any, primeiro ahead ... muda  para  2 , não avança o input, e o  any, por ser exigente sobre o avanço do input, resulta em falha sem chegar à segunda iteração.


O uso do while é complicado. Na minha experiência, eu o usei para parsing sensível a contexto (isto é, primeiro você olha para a frente e para trás, determinando o contexto de um token, e só então decide o que fazer; "olhar para frente e para trás requer a correspondência de várias regras enquando você não sai do lugar, na posição corrente*) e também em situações onde o input precisa ser modificado durante o parsing (exemplo acima), ou se o parsing depende de algum estado externo. Também se mostrou útil para  deep-first traversal of tree-like structures (n.t. não sei traduzi isso) .- a situação é a mesma, você está mexendo com node, fazendo correspondências com regras, mas a posição não deve avançar se você fizer uma correspondência, senão você perde a referência do node corrente.


Portanto, while não é amigável para principiantes e você não precisa se preocupar com ele se você está começando. Ele é útil sem situações mais avançadas, onde você precisa de um controle seguro sobre o parsing."