Tree matching con Oniguruma e Regexp in ruby 1.9 ("Tanaka Akira special")

Eil,

In seguito ad una ennesima discussione su cosa siano le espressioni
regolari, e come le regexp al giorno d’oggi siano in realt turing
complete o robe cos, mi son trovato a scrivere una regex che
matchasse la sintassi delle s-expression in lisp.

Che pi o meno, viene una cosa cos:

r = %r@
(? \w+){0}
(? '\g){0}
(?
\g |
\g |
(
\g
(? (\s+ \g)* )
)
){0}
^\g$
@ix

Il problema che mentre questa cosa funziona[0] come validazione (nel
senso che correttamente risconosce una sexpr e una cosa invalida) non
genera un albero dei match, perch ogni match di una sotto-espressione
sovrascrive l’ultimo named group.

Che poi probabilmente lo stesso anche con i gruppi numerati, e.g.

/((a|b)*)/.match(‘aaa’) => #<MatchData “aaa” 1:“aaa” 2:“a”>

mi perde il riferimento al match della prima “a” e della prima “b”.

Per a giudicare dalle API di oniguruma si dovrebbe poter infilare una
callback per ogni accesso ricorsivo.
Solo, mi pare che in ruby non ci sia. Qualcuno ha una vaga idea di
cosa io stia parlando, e se esiste un workaround che non sia “scrivi
ffi-oniguruma”[1]?

[0] per qualche valore di “funziona”
[1] astenersi “le regex non sono adatte usa un parser generator”, Il
problema “le regex in ruby 1.9” non “il parsing” :slight_smile:


twitter: @riffraff
blog (en, it): www.riffraff.info riffraff.blogsome.com
work: cascaad.com circleme.com

Il giorno 22 febbraio 2012 09:30, gabriele renzi [email protected] ha
scritto:

r = %r@
^\g$
/((a|b)*)/.match(‘aaa’) => #<MatchData “aaa” 1:“aaa” 2:“a”>
[0] per qualche valore di “funziona”
[1] astenersi “le regex non sono adatte usa un parser generator”, Il
problema “le regex in ruby 1.9” non “il parsing” :slight_smile:

****************************** (sono stato censurato per via del motivo
[1]).

Non saprei cosa rispondere se non che sarebbe molto bello fare questo
genere di cose con una regexp, personalmente mi farebbe risparmiare un
sacco di tempo, peccato che raramente riesco ad ottenere il risultato
sperato, ad esempio:

“”.match(/(<\w+>)+/)
=> #<MatchData “” 1:"">

non dovrebbe estrarre anche ?

2012/2/22 Marco M. [email protected]:

Non saprei cosa rispondere se non che sarebbe molto bello fare questo
genere di cose con una regexp, personalmente mi farebbe risparmiare un
sacco di tempo, peccato che raramente riesco ad ottenere il risultato
sperato, ad esempio:

“”.match(/(<\w+>)+/)
=> #<MatchData “” 1:“”>

non dovrebbe estrarre anche ?

gi, sembra essere la stessa situazione: i buffer dei risultati sono
fissati quando viene compilata la regexp e vengono riutilizzati sempre
quelli.

Nel tuo caso specifico te la puoi cavare con scan:

“”.scan(/<\w+>/)

Una cosa curiosa che ho scoperto che puoi avere n volte lo stesso
named group per (anche se non puoi accederci in modo sensato):

m=‘abc’.match(/(? a)(? b)(? c)/x)
=> #<MatchData “abc” lett:“a” lett:“b” lett:“c”>
m[:lett]
=> “c”
m.captures
=> [“a”, “b”, “c”]


twitter: @riffraff
blog (en, it): www.riffraff.info riffraff.blogsome.com
work: cascaad.com circleme.com

mi rispondo da solo (e quindi mi perdono il top posting):

non si pu fare, ed una limitazione che c’ apparentemente in tutti
i regexp engine in giro, anche se c’ un mezzo workaround usando PCRE
in C :frowning:

2012/2/22 gabriele renzi [email protected]:

r = %r@
^\g$
/((a|b)*)/.match(‘aaa’) => #<MatchData “aaa” 1:“aaa” 2:“a”>
[0] per qualche valore di “funziona”
[1] astenersi “le regex non sono adatte usa un parser generator”, Il
problema “le regex in ruby 1.9” non “il parsing” :slight_smile:


twitter: @riffraff
blog (en, it): www.riffraff.info riffraff.blogsome.com
work: cascaad.com circleme.com


twitter: @riffraff
blog (en, it): www.riffraff.info riffraff.blogsome.com
work: cascaad.com circleme.com

2012/3/14 Marco M. [email protected]:

Ciao Gabriele, dove hai trovato quella sintassi per referenziare le
occorrenze ?<>
In ruby 1.8.7 non funziona e volevo capire se per una questione di
sintassi diversa

ruby 1.9 ha un motore diverso (basato su oniguruma) quindi normale
che non ti funzioni con 1.8.

Poi nel frattempo, da quel che ho capito, lo sviluppatore di oniguruma
ha litigato con matz e ha abbandonato lo sviluppo, e adesso c’ un
fork (onigmo) che ha backport dei fix che c’erano in ruby, e che la
cosa che viene importata in ruby-head.

Grossomodo la sintassi sta qua, comunque


twitter: @riffraff
blog (en, it): www.riffraff.info riffraff.blogsome.com
work: cascaad.com circleme.com

Avevo formulato male la domanda, mi interessava sapere se c’era un modo
per farlo anche col vecchio motore usato nell’1.8 o se era una
prerogativa del nuovo.

Grazie per la risposta e per il link.

2012/3/15 Marco M. [email protected]:

Avevo formulato male la domanda, mi interessava sapere se c’era un modo
per farlo anche col vecchio motore usato nell’1.8 o se era una
prerogativa del nuovo.

dunque, la stessa cosa no non si pu.
Puoi “parsare” delle cose un po’ articolate anche col motore vecchio
(e.g. ABNF.rb una figata, converte automaticamente da un subset di
ABNF a Regexp[1]) ma folle farlo :slight_smile:

[1] abnf - converter from ABNF to Regexp


twitter: @riffraff
blog (en, it): www.riffraff.info riffraff.blogsome.com
work: cascaad.com circleme.com

Ciao Gabriele, dove hai trovato quella sintassi per referenziare le
occorrenze ?<>
In ruby 1.8.7 non funziona e volevo capire se per una questione di
sintassi diversa