En ruby la función
match sirve para buscar el primer match de una regex dentro de un string. Por ejemplo (usando el irb):
irb(main):001:0> m = /a/.match "babab"
=> #<MatchData "a">
irb(main):002:0> m.pre_match
=> "b"
irb(main):003:0> m[0]
=> "a"
En particular, el
pre_match es lo que está antes del match en el string. También según había entendido (mal) /\Z/ matchea con el final del string. Por ejemplo:
irb(main):004:0> m = /\Z/.match "hola"
=> #<MatchData "">
irb(main):005:0> m.pre_match
=> "hola"
Pero,
/\Z/ tiene un comportamiento muy extraño, aunque documentado, cuando el último caracter antes del final es un \n. Lo que pasa es que el pre_match queda ¡sin el \n del final!. Lo muestro en el irb:
irb(main):006:0> m = /\Z/.match "\n"
=> #<MatchData "">
irb(main):007:0> m.pre_match
=> ""
Para que no se manduque el
\n, hay que usar /\z/ (¡en minúscula!):
irb(main):008:0> m = /\z/.match "\n"
=> #<MatchData "">
irb(main):009:0> m.pre_match
=> "\n"
Por lo tanto tuve que tocar el tokenizer, ahora la función de initialize quedó así (miren el cambio de la "Z" a "z"):
def initialize( delimiters )
@delimiter_list = [[/\z/, :finish]] +
delimiters.to_a.map { |k,arr| arr.map { |re| [re, k] } }.inject([]) { |ac,ps| ac + ps }
@match_cache = nil
end
Y el test que captura el problema que genera usar \Z en vez de \z quedó así:
def test_carriage_return_ending
tok = Tokenizer.new( :a_kind => [/!/] )
tok.source = "bang!\n"
tok.next_token
assert_equal true, tok.has_next?
tok.next_token
assert_equal true, tok.has_next?
assert_equal "\n", tok.next_token[0].to_s
assert_equal false, tok.has_next?
end
Happy hacking,
Aureliano.
No hay comentarios.:
Publicar un comentario