Newsgroup: it.comp.lang.c
Titolo: Avete una soluzione un po più elegante?

Salve a tutti,
avrei bisogno di un vostro consiglio/parere su una piccola questione.
Per Hobby e per studiare nella pratica il C sto scrivendo un piccolo
interprete per un linguaggio di scripting WEB (simile a PHP).
Il parser della sintassi per ora è un semplice parser a discesa ricorsiva
che ho scopiazzato in piccola parte da un manuale di C.
Dopo aver fatto tutte le funzioni per lo stack delle variabili
globali/locali e per la gestione delle funzioni personali dell'utente mi
sono arenato sul parsing degli IF (che poi si ripresenterà anche nei while).
La cosa complessa da implementare è il riconoscimento dei vari OR, AND
all'interno dell'espressione condizionale, che potrebbero essere parecchi e
nidificati:
Ho sviluppato due funzioni che forse potrebbero funzionare (premetto che non
ho ancora fatto le prove in quanto il sistema da me usato non mi convince
molto dal punto di vista dell'eleganza e della velocità);
La funzione analizza_parametri entra in gioco dopo che viene parsato il TAG
if(.
Questa funzione ricerca le parentesi annidate e per ogni parentesi esegue la
analizza parentesi per estrarne il valore.
Alcune piccole premesse per farvi capire meglio il codice:
get_token: Restituisce il token successivo letto dal file che sto
analizzando
CondPush: Inserisce la condizione(|| o &&) trovata nello Stack delle
condizioni
CondPop: Estrae la condizione (|| o &&) dallo Stack delle condizioni
1° FUNZIONE
void analizza_parametri(&value)
{
 int brace=0,i=0,a=0,TempCond;
 char partial_value[10][];
 do {
  get_token();
  swicth(token_type) {
   case APERTURA_PARENTESI:
    brase++;
    break;
   case OR:
   case AND:
    CondPush();
    if (brace==1) {
     // Sono uscito dalle parentesi ma c'è ancora qualche cosa da analizzare
     analizza_parentesi(&partial_value[i][]);
     a++;i++,brace--;
    }
    break;
   default:
    analizza_parentesi(&partial_value[i][]);
    a++;i++,brace--;
    break;
  }
  if (a==2 && value_present==0) {
   Temp_cond = CondPop();
   if (Temp_cond == AND) {
    value = (partial_value[i-1][] && partial_value[i][]);
   } else {
    value = (partial_value[i-1][] || partial_value[i][]);
   }
   value_present = 1;
   a=0;
  } else if(a==1 && value_present==1) {
   Temp_cond = CondPop();
   if (Temp_cond == AND) {
    value = (value && partial_value[i][]);
   } else {
     value = (value || partial_value[i][]);
   }
   a=0;
  }
 } while (brace!=0);
}
2° FUNZIONE
void analizza_parentesi(&value)
{
 int brace=1,i=0,a=0,Temp_cond;
 char *old_prog;
 char partial_value[10][];
 do {
  get_token();
  switch(token_type) {
   case CHIUSURA_PARENTESI:
    return;
    break;
   case OR:
    CondPush();
    break;
   case AND:
    CondPush();
    break;
   default:
    // Analizzo ed estraggo il valore della singola condizione
    eval_exp0(&partial_value[i][]);
    i++;a++;
    break;
  }
  if (a==2 && value_present==0) {
   Temp_cond = CondPop();
   if (Temp_cond == AND) {
    value = (partial_value[i-1][] && partial_value[i][]);
   } else {
    value = (partial_value[i-1][] || partial_value[i][]);
   }
   value_present = 1;
   a=0;
  } else if(a==1 && value_present==1) {
   Temp_cond = CondPop();
   if (Temp_cond == AND) {
    value = (value && partial_value[i][]);
   } else {
     value = (value || partial_value[i][]);
   }
   a=0;
  }
 } while(brace!=0);
}
Credo anche io che forse non è un buon codice ma è solo da un mesetto che
scrivo C.
Se qualcuno ha una soluzione un pochino più elegante e migliore mi potrebbe
dare una mano?
Grazie del tempo che mi avete dedicato.
Gianni

 e nidificati:
Io userei qualcosa di simile: if (condizione) istruzioni
Così quando trovi un if ti assicuri che il prossimo token sia una (, chiami
read_condizione o qualcosa del genere e ti assicuri che il prossimo token
sia ).
-- 
Andrea Bergia - studente          Linux Registred User #281550
Per favore non mandatemi allegati in Word o PowerPoint.
Si veda 
http://www.fsf.org/philosophy/no-word-attachments.html

 ha scritto nel messaggio
news:frvsa-...@host.andreabergia.torino.it...


 Gianni.
Vediamo un po'... Prendendo quel pochissimo che so di parser a discesa
ricorsiva grazie al capitolo 6 dello Stroustrup, potresti rendere la
grammatica qualcosa di simile (spero sia comprensibile):
condizione:
        booleano
        booleano operatore1 condizione
booleano:
        valore          # != 0
        valore operatore2 valore
        ! booleano
        ( condizione )
operatore1:
        &&
        ||
operatore2:
        ==
        !=
        <
        <=
        >
        >=
valore:
        numero
        variabile
        carattere
        stringa
Però effettivamente inizia a diventare molto complesso... Comunque ammetto
la mia ignoranza in termini di parsing, spero qualcuno più competente di me
ti aiuti. Ciao.


Gianni.
Ho provato a leggere il tuo codice e confesso di non averci
capito molto. Io ho scritto molti parser ricorsivi a discesa
e questo secondo me implica che uno di noi due sta usando
il nome "parser ricorsivo a discesa" in modo improprio :)
Comunque tempo fa avevo fatto un post con un esempio di
parser che calcola una espressione con gestione delle
quattro operazioni (con gestione delle precedenze) e
parentesi...
http://groups.google.com/groups?hl=it&lr=&ie=UTF-8&oe=UTF-8&selm=3b1feff0.6463203%40news.interbusiness.it
Una espressione usata nelle IF non e' mai stata diversa da
una normale espressione nei linguaggi che ho implementato
(anzi... il parsing di una IF semplicemente chiama la
richiesta di parsing di una espressione) e non riesco a
capire come puoi gestire le espressioni con operatori
multipli con precedenze e associativita' diverse in altre
parti del linguaggio e avere invece problemi sulle IF...
Sia che tu scriva un parser che semplicemente valuta
"al volo" l'espressione, oppure un compilatore che
genera una diversa rappresentazione (es. un tree letto
runtime oppure delle istruzioni di una VM) il problema
e' sempre assolutamente identico a quello di una normale
espressione.
HTH
Andrea


http://groups.google.com/groups?hl=it&lr=&ie=UTF-8&oe=UTF-8&selm=3b1feff0.6463203%40news.interbusiness.it
Guarderò.
