Newsgroup: it.comp.lang.perl
Titolo: REQ: Problema di regexp bello peso (almeno, per me...)

Ciao a tutti.
frequento questo newsgroup da un po' di tempo, ed ho visto che qui tra
voi di guru delle regexp ce ne sono parecchi (almeno così sembra). Credo
di conoscere benino il perl, lo uso per lavoro e per diletto e non ho
mai trovato finora grossi problemi a fargli fare ciò che volevo, anche
se talvolta non nel modo migliore. MI ritrovo però ora tra i piedi un
problema, apparentemente idiota, a cui però non riesco a trovare una
soluzione. Almeno, non trovo quella che "dico io". Vi spiego qual è il
problema.
Sto preparando la tesi in perl, che realizza un parser a discesa
ricorsiva che riconosce stringhe appartenenti a grammatiche LL(1) con
azioni. Il tutto funzionante via web. Suppongo che l'argomento possa
risultare interessante solo ad una ristretta (issima) cerchia di
persone, ma spero che qualcuno riesca a darmi una mano su un piccolo
sottoinsieme di tutta la baracca.
Il motore funziona bene, riconosce ed esegue, ma... ecco il pacco
proprio dove meno me lo aspettavo: nei "particolari" del lavoro.
Per motivi pratici, nella pagina web si è preferito creare una maschera
di input dove inserire le produzioni della grammatica facendo uso dei
tag <textarea></textarea>. Ciò significa che il singolo utente può
infilare in tale area un po' quello che gli pare, ma comunque sempre
produzioni della forma /[A-Z]::=.*/s
Per la precisione, una produzione si compone di una parte sinistra (una
lettera maiuscola), un "::=" ed una parte destra, (un mix di lettere
minuscole, maiuscole, simboli, parentesi, a-capo, ecc)
Esempio di input:
S::=aA{S.tot=A.tot} |
    @{S.tot=0}
A::=xA{A.tot=A1.tot+1} |
    qB{A.tot=1+B.tot}
B::=m{B.tot=1} | @{B.tot=0}
Assumo che la parte sx sia sempre attaccata al mio "::="  
Il mio chiodo viene semplicemente qui. Se ho in una variabile tutto ciò
che mi arriva dalla textarea, (es $tutto = "S::=aA{S.tot=A.tot} |\n  
@{S.tot=0}\nA::=xA..." ecc ecc) come posso con una regexp estrarre SIA
la parte sx delle produzione SIA la parte destra?
Ho provato con qualcosa del tipo
while ( $tutto =~ /([A-Z]::=)(.*?)/gs ) {
   print "-->sx:$1; dx:$2\n" }
fino a partorire un orribile (e parzialmente funzionante)
while ( $tutto =~ /([A-Z]::=)(?=((.*?)[A-Z]::=))\3/gs ) {
   print "-->sx:$1; dx:$2\n" }
che fa uso di zero-lenght lookahead, ma chiaramente continuo a non
ottenere quello che desidero. Insomma, vorrei poter ottenere ad ogni
"giro di while" in $1 la singola lettera, ed in $2 tutto quello che sta
a destra del ::= fino al successivo [A-Z]::= o  fine stringa, ma
accidenti non riesco a cavare un ragno da un buco. 
Giusto per onestà, il problema l'ho aggirato attraverso uno "split" ed
un loop con un altro pattern matching sugli elementi dello split; ormai
però ho questo "chiodo fisso" e... ringrazio calorosamente chiunque
riesca a trovare una strada diversa, o a darmi un suggerimento.
Grazie in anticipo,
  un saluto.
   Samuele Manfrin - Pisa



 accidenti non riesco a cavare un ragno da un buco. 
Questa mi pare che funzioni:
 while( $tutto =~ /([A-Z])::=(.*?)(?=([A-Z]::=|$))/sg )
 {
 
 }
Max

    print "-->sx:$1; dx:$2\n" }
Visto che non ti piace la tua probabilmente non ti piacera' nemmeno la mia:
while (($sx,$dx,$tutto)=($tutto =~ /([A-Z]::=)(.*?)\n*(([A-Z]::=.*)|$)/s)){
    print "$sx -> $dx\n"
}
oppure se in $sx vuoi direttamente la singola lettera:
while (($sx,$dx,$tutto)=($tutto =~ /([A-Z])::=(.+?)\n*(([A-Z]::=.+)|$)/s)){
    print "$sx -> $dx\n"
}
io non ci vedo niente di repellente e su un esempio come
  S::=aA{S.tot=A.tot} |
    @{S.tot=0}
  B::=m{B.tot=1} | @{B.tot=0}
  Z::=
  K::=Q::=pincoP::=pallino
restituisce:
  S -> aA{S.tot=A.tot} |
    @{S.tot=0}
  B -> m{B.tot=1} | @{B.tot=0}
  Z ->
  K ->
  Q -> pinco
  P -> pallino
che, mi sembra di capire, e' quello che ti serve.
Direi che non rischia nemmeno di incatagnarsi (ma su questo non sono
disposto a scommetterci grosse somme).
Poi magari un giorno mi fai leggere la tesi ;)
ciao, marco
--
Marco Cacchiani                                
e-mail:ma...@sirius.pisa.it
Public pgp key:         
http://www.sirius.pisa.it/marco/pgp_public_key.asc
Sirius Servizi Informatici                     e-mail: 
in...@sirius.pisa.it
Parco Teatro Pasolini, 1                       Phone:  +39 (50) 865120
I-56019 - Vecchiano                            Fax:    +39 (50) 860260
(Pisa - ITALIA)                                
http://www.sirius.pisa.it/

 Questa mi pare che funzioni:
Beh, che dire: grazie mille a tutti e due. Mi dovrò ripigliare un po' in
mano l'owl book ed il camel book e - neanche dirlo - continuerò a
seguire con assiduità il newsgroup. Finché Marco non mi sega l'account
su Sirius (scaduto ad ottobre: non riesco mai a ritagliarmi un'oretta
per andarlo a trovare) ;-) Sarà il primo a cui porterò la tesi eheheh
   Samuele