Palavra de parslet até o delímetro presente

Eu estou apenas começando com ruby ​​e parslet, então isso pode ser óbvio para os outros (espero).

Eu estou querendo obter todas as palavras até um delimitador (^) sem consumi-lo

A regra a seguir funciona (mas consome o delimitador) com um resultado de {:wrd=>"otherthings"@0, :delim=>"^"@11}

 require 'parslet' class Mini > delimeter.as(:delim) } root(:othercontent) end puts Mini.new.parse("otherthings^") 

Eu estava tentando usar o ‘presente’,

 require 'parslet' class Mini > delimeter.present? } root(:othercontent) end puts Mini.new.parse("otherthings^") 

mas isso lança uma exceção:

 Failed to match sequence (wrd:WORD &DELIMETER) at line 1 char 12. (Parslet::ParseFailed) 

Posteriormente, vou querer inspecionar a palavra à direita do delimitador para criar uma gramática mais complexa, e é por isso que não quero consumir o delimitador.

Estou usando o parslet 1.5.0.

Obrigado pela ajuda!

TL; DR; Se você se importa com o que é antes do “^” você deve analisar isso primeiro.

— mais tempo de resposta —

Um analisador sempre consumirá todo o texto. Se não puder consumir tudo, o documento não será totalmente descrito pela gramática. Em vez de pensar nisso como algo que executa “divisões” em seu texto … em vez disso, pense nele como uma máquina de estado inteligente que consome um stream de texto.

Então … como sua gramática completa precisa consumir todo o documento … ao desenvolver seu analisador, você não pode fazer isso para analisar alguma parte e deixar o resto. Você quer transformar seu documento em uma tree para que você possa manipulá-lo de forma definitiva.

Se você realmente queria apenas consumir todo o texto antes de um delimitador, então você poderia fazer algo assim …

Digamos que eu fosse analisar uma lista separada de coisas.

Eu poderia ter as seguintes regras

 rule(:thing) { (str("^").absent? >> any).repeat(1) } # anything that's not a ^ rule(:list) { thing >> ( str("^") >> thing).repeat(0) } #^ separated list of things 

Isso funcionaria da seguinte forma

 parse("thing1^thing2") #=> "thing1^thing2" parse("thing1") #=> "thing1" parse("thing1^") #=> ERROR ... nothing after the ^ there should be a 'thing' 

Isso significaria que a list corresponderia a uma string que não termine ou comece com um ‘^’. Para ser útil, no entanto, preciso extrair os bits que são os valores com a palavra-chave “as”

 rule(:thing) { (str("^").absent? >> any).repeat(1).as(:thing) } rule(:list) { thing >> ( str("^") >> thing).repeat(0) } 

Agora, quando a list corresponde a uma string, recebo uma matriz de hashes de “coisas”.

 parse("thing1^thing2") #=> [ {:thing=>"thing1"@0} , {:thing=>"thing2"@7} ] 

Na realidade, no entanto, você provavelmente se importa com o que é uma ‘coisa’ … não apenas qualquer coisa irá para lá.

Nesse caso, você deve começar definindo essas regras … porque você não quer usar o analisador para dividir por “^”, em seguida, re-analisar as seqüências de caracteres para descobrir o que eles são feitos.

Por exemplo:

 parse("6 + 4 ^ 2") # => [ {:thing=>"6 + 4 "@0}, {:thing=>" 2"@7} ] 

E eu provavelmente quero ignorar o white_space em torno das “coisas” e eu provavelmente quero lidar com o 6 the + e o 4 todos separadamente. Quando faço isso, vou ter que jogar fora minha regra “todas as coisas que não são”.

    Intereting Posts