C: Conversione ? B : C in se (A) B altro C

Ero alla ricerca di uno strumento che può convertire i C espressioni di codice per il modulo:

a = (A) ? B : C;

in ‘default’ di sintassi con if/else dichiarazioni:

if (A)
  a = B
else
  a = C

Qualcuno conosce un tool che è in grado di fare una tale trasformazione?

Io lavoro con GCC 4.4.2 e creare un file pre-elaborato con -E ma non si desidera che tali strutture in esso.

Modifica:
Codice riportato di seguito deve essere trasformato, troppo:

a = ((A) ? B : C)->b;
  • Questo urla “impressionante, abbozzato macro!” per me.
  • È solo un file? Se è così forse si può fare con una sofisticata espressione regolare e la ricerca di-sostituire la funzione di un editor che può fare questo.
  • Perché? Si dovrebbe prendere in considerazione ci sono situazioni in cui non vi è alcun equivalente semantico. Non c’è niente di sbagliato con l’operatore ternario.
  • Questo è ciò che è stata la prima cosa che mi è venuta in mente “Sketchy ” Macro”
  • Puoi farmi un esempio di codice in cui è nessuna trasformazione è possibile?”. @Felix: Migliaia di file
  • Per l’eco e amplificare GMan: l’operatore ternario è un’espressione e ha un valore, che è l “equivalente” if dichiarazione non. Cieco testuale sostituzione di uno con l’altro non è sicuro.
  • Considerare d = tan(theta = A ? B : C) o anche solo d=tan(A ? B : C) o qualcosa di diverso da un dritto di assegnazione. Sicuramente c’è un codice equivalente utilizzando if, ma la ricerca richiede un po ‘ di non semplice comprensione.
  • forse non ci sono esempi di NESSUNA trasformazione è possibile, ma ci sono molti casi in cui la trasformazione è altamente non banale… per qunto esempio: while(test % 2 ==1 ? oddTest() : evenTest()){….}
  • Perché non è banale ho chiesto è COSÌ 😉
  • i 2 esempi che egli dà sono equivalenti, poiché egli è la conversione di tutta la assegnazione, giusto ? C’è un problema nel farlo ? Muto, cosa penso , sarebbe sostituire A ? B:C; da if (A) B; else C;. Ho ancora l’avvocato che Coccinelle è un ottimo strumento da utilizzare nel caso generale (anche se ho downvoted un paio di volte).
  • In C++: int& i = flag ? a : b; non ha equivalenti. In C con VLA: int somearray[flag ? 10 : 20] non ha equivalenti. Forse c’è in entrambi. Io ancora non vedo alcun motivo per sbarazzarsi di una funzionalità del linguaggio. :]
  • Non hai ancora risposto PERCHÉ vuoi fare questo? ?: Quando utilizzati in modo appropriato è perfettamente ragionevole. Quando utilizzato in modo ingiustificato, non si sta andando ad essere in grado di risolvere il problema a livello di programmazione…
  • Mi analizzare un codice C con un programma che non può gestire ?:
  • tur1ng: potrebbe essere più facile per risolvere il tuo programma di analisi per capire (tutti) C.
  • che dire: int* i_ptr; if (flag) i_ptr = &a; else i_ptr = &b; int& i = *i_ptr;

InformationsquelleAutor tur1ng | 2010-03-11

 

5 Replies
  1. 12

    Coccinelle può farlo abbastanza facilmente.

    Coccinelle è un programma di corrispondenza e
    motore di trasformazione che prevede
    la lingua SmPL (Semantica Patch
    Language) per la definizione desiderata
    le partite e le trasformazioni in C codice.
    Coccinelle è stato inizialmente mirati
    verso l’esecuzione di garanzia
    evoluzioni in Linux. Tali evoluzioni
    comprendere i cambiamenti che sono necessari
    nel codice del client in risposta a
    evoluzioni nella libreria di Api, e può
    includere modifiche come la ridenominazione
    una funzione, l’aggiunta di un argomento di una funzione
    il cui valore è in qualche modo
    dipende dal contesto, e la riorganizzazione di un
    struttura di dati. Al di là di garanzia
    evoluzioni, Coccinelle è successo
    usato (da noi e altri) per la ricerca di
    e correggere i bug nel codice di sistemi.

    EDIT:
    Un esempio di semantica patch:

    @@ expression E; constant C; @@
    (
      !E & !C
    |
    - !E & C
    + !(E & C)
    )

    Dalla documentazione:

    Il modello !x&y. Un’espressione di questa forma è quasi sempre priva di senso, perché unisce un operatore booleano con un po ‘ operatore. In particolare, se il bit all’estrema destra di y è 0, il risultato sarà sempre 0. Questa semantica patch si concentra il caso in cui y è una costante.

    Si dispone di un buon set di esempi qui.

    La mailing list è molto attivo e disponibile.

  2. 3

    La seguente semantica patch per Coccinelle farà la trasformazione.

    @@
    expression E1, E2, E3, E4;
    @@
    
    - E1 = E2 ? E3 : E4;
    + if (E2)
    +   E1 = E3;
    + else
    +   E1 = E4;
    
    @@
    type T;
    identifier E5;
    T *E3;
    T *E4;
    expression E1, E2;
    @@
    
    - E1 = ((E2) ? (E3) : (E4))->E5;
    + if (E2)
    +   E1 = E3->E5;
    + else
    +   E1 = E4->E5;
    
    
    @@
    type T;
    identifier E5;
    T E3;
    T E4;
    expression E1, E2;
    @@
    
    - E1 = ((E2) ? (E3) : (E4)).E5;
    + if (E2)
    +   E1 = (E3).E5;
    + else
    +   E1 = (E4).E5;
  3. 1

    Il DMS Software Reengineering Toolkit può fare questo, applicando il programma di trasformazioni.

    Una specifica DMS trasformazione per abbinare il vostro esempio specifico:

    domain C.
    
    rule ifthenelseize_conditional_expression(a:lvalue,A:condition,B:term,C:term):
    stmt -> stmt
    =  " \a = \A ? \B : \C; "
    -> " if (\A) \a = \B;  else \a=\C ; ".

    È bisogno di un’altra regola per gestire il tuo caso, ma è altrettanto facile esprimere.

    Le trasformazioni che operano sul codice sorgente di strutture piuttosto che di testo, in modo che il layout e i commenti non pregiudica il riconoscimento o l’applicazione. Le virgolette nella regola non tradizionali stringa tra virgolette, ma piuttosto sono metalinguistica citazioni che separano la regola di sintassi del linguaggio dal pattern language età utilizzato per specificare la sintassi concreta di essere cambiato.

    Ci sono alcuni problemi con la pre-elaborazione di direttive, se avete intenzione di mantenere. Poiché a quanto pare sono disposti a lavorare con il preprocessore-ha ampliato il codice, si può chiedere DMS fare la pre-elaborazione, come parte del passaggio di trasformazione; ha piena GCC4 e GCC4-compatibile preprocessori costruito a destra in.

    Come altri hanno osservato, questo è piuttosto un caso facile perché è specificato che il lavoro a livello di una dichiarazione completa. Se si desidera liberare il codice di qualsiasi incarico simile a questa dichiarazione, con tali assegnazioni sono incorporati nei vari contesti (inizializzatori, etc.) potrebbe essere necessario un più ampio insieme di trasformazioni per gestire le varie serie di casi particolari, e potrebbe essere necessario per la fabbricazione di altre strutture di codice (ad esempio, le variabili temp di tipo appropriato). La cosa buona di uno strumento come il DMS è che è possibile calcolare esplicitamente un tipo simbolico per un’espressione arbitraria (e quindi la dichiarazione del tipo di tutte le temps) e che è possibile scrivere ad un insieme più ampio, piuttosto semplice e si applica a tutti loro.

    Tutto ciò che ha detto, io non sono sicuro del valore reale di un ternario-condizionale-espressione operazione di eliminazione. Una volta che il compilatore si impossessa del risultato, si può ottenere un simile oggetto il codice come se non l’avessi fatto le trasformazioni. Dopo tutto, il compilatore è in grado di applicare equivalenza-conservazione trasformazioni, troppo.

    C’è ovviamente il valore nel fare cambiamenti regolari in generale, però.

    (DMS possibile applicare sorgente a sorgente del programma di trasformazioni per molte lingue, tra cui C, C++, Java, C# e PHP).

  4. 0

    Io non sono a conoscenza di una cosa come l’operatore ternario è built-in linguaggio di specifiche, come una scorciatoia per il if logica… l’unico modo che posso pensare di fare questo è quello di cercare manualmente quelle linee e riscrivere nella forma in cui if è utilizzato… come un consenso generale, l’operatore ternario opere come questa

    expr_is_true ? exec_if_expr_is_TRUE : exec_if_expr_is_FALSE; 
    

    Se l’espressione è valutata per essere vero, eseguire la parte tra ? e :, altrimenti eseguire l’ultima parte tra : e ;. Sarebbe l’inverso se l’espressione è valutata per essere false

    expr_is_false ? exec_if_expr_is_FALSE : exec_if_expr_is_TRUE; 
    
  5. 0

    Se le istruzioni sono molto regolari come questo, perché non eseguire il file tramite un piccolo script in Perl? La logica di base per fare la ricerca e trasformazione è semplice per il tuo esempio di linea. Ecco una bare bones approccio:

    use strict;
    while(<>) {
        my $line = $_;
        chomp($line);
        if ( $line =~ m/(\S+)\s*=\s*\((\s*\S+\s*)\)\s*\?\s*(\S+)\s*:\s*(\S+)\s*;/ ) {
            print "if(" . $2 . ")\n\t" . $1 . " = " . $3 . "\nelse\n\t" . $1 . " = " . $4 . "\n";
        } else {
            print $line . "\n";
        }
    }
    exit(0);

    Devi eseguirlo in questo modo:

    perl transformer.pl < foo.c > foo.c.new

    Naturalmente diventa più difficile e più difficile se il modello di testo non è così regolare come quello che hai postato. Ma gratis, facile e veloce da provare.

    • Questo non funziona per: a = ((A) ? B : C)->b;
    • Ho fatto avvertire che era solo per l’esempio che hai fornito. 🙂 Piuttosto che provare a scrivere qualche uber espressione regolare si potrebbe fare un secondo elsif caso è piuttosto semplice: m/(\S+)\s*=\s*(\s*((\s*\S+\s*))\s*\?\s*(\S+)\s*:\ \ s*(\S+)\s*)\s*->\s*(\S+)\s*;/ — il riferimento di chiamata è partita il gruppo $4.
    • Penso che l’esempio con l’-> probabilmente non può farlo senza una variabile temporanea.

Lascia un commento