Domanda

Qualcuno può indicarmi un programma che rimuove le stringhe dal codice sorgente C?Esempio

#include <stdio.h>
static const char *place = "world";
char * multiline_str = "one \
two \
three\n";
int main(int argc, char *argv[])
{
        printf("Hello %s\n", place);
        printf("The previous line says \"Hello %s\"\n", place);
        return 0;
}

diventa

#include <stdio.h>
static const char *place = ;
char * multiline_str = ;
int main(int argc, char *argv[])
{
        printf(, place);
        printf(, place);
        return 0;
}

Quello che sto cercando è un programma molto simile stripcmtsolo che voglio eliminare le stringhe e non i commenti.

Il motivo per cui sto cercando un programma già sviluppato e non solo una pratica espressione regolare è perché quando inizi a considerare tutti i casi d'angolo (citazioni all'interno di stringhe, stringhe multi-line ecc.) Le cose in genere iniziano a essere (molto) più complesse di esso appare per la prima volta.E ci sono limiti su ciò che la RES può raggiungere, sospetto che non sia possibile per questo compito.Se pensi di avere un estremamente espressione regolare robusta sentiti libero di inviare, ma per favore non ingenuo sed 's/"[^"]*"//g' come suggerimenti.

(Non è necessaria una gestione speciale delle stringhe (possibilmente senza fine) all'interno dei commenti, queste verranno rimosse per prime)

Il supporto per stringhe su più righe con caratteri di fine riga incorporati non è importante (non è legale in C), ma devono essere supportate le stringhe che si estendono su più righe e terminano con \ alla fine.

Questo è quasi lo stesso di Alcuni altro domande, ma non ho trovato alcun riferimento ad alcuno strumento.

È stato utile?

Soluzione

Puoi scaricare il codice sorgente su StripCmt (.tar.gz - 5kB).È banalmente piccolo e non dovrebbe essere troppo difficile adattarlo alle stringhe di striping (è rilasciato sotto GPL).

Potresti anche voler indagare sulle regole linguistiche lessicali ufficiali per le stringhe C.ho trovato Questo molto rapidamente, ma potrebbe non essere definitivo.Definisce una stringa come:

stringcon ::= "{ch}", where ch denotes any printable ASCII character (as specified by isprint()) other than " (double quotes) and the newline character.

Altri suggerimenti

Tutti i token in C (e nella maggior parte degli altri linguaggi di programmazione) sono "regolari".Cioè, possono essere abbinati da un'espressione regolare.

Un'espressione regolare per le stringhe C:

"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"

La regex non è troppo difficile da capire.Fondamentalmente una stringa letterale è una coppia di virgolette doppie che circondano un gruppo di:

  • caratteri non speciali (senza virgolette/barra rovesciata/nuova riga).
  • escape, che iniziano con una barra rovesciata e quindi consistono in uno di:
    • un semplice carattere di fuga
    • Da 1 a 3 cifre ottali
    • x e 1 o più cifre esadecimali

Ciò si basa sulle sezioni 6.1.4 e 6.1.3.4 delle specifiche C89/C90.Se qualcos'altro si è insinuato in C99, questo non lo rileverà, ma non dovrebbe essere difficile da risolvere.

Ecco uno script Python per filtrare un file sorgente C rimuovendo le stringhe letterali:

import re, sys
regex = re.compile(r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"''')
for line in sys.stdin:
  print regex.sub('', line.rstrip('\n'))

MODIFICARE:

Dopo aver pubblicato quanto sopra mi è venuto in mente che, sebbene sia vero che tutti i token C sono regolari, non tokenizzando tutto abbiamo un'opportunità di guai.In particolare, se appare una doppia virgoletta in quello che dovrebbe essere un altro token, possiamo essere condotti lungo il sentiero del giardino.Hai detto che i commenti sono già stati eliminati, quindi l'unica altra cosa di cui dobbiamo veramente preoccuparci sono i caratteri letterali (anche se l'approccio che userò può essere facilmente esteso per gestire anche i commenti).Ecco uno script più robusto che gestisce i caratteri letterali:

import re, sys
str_re = r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"'''
chr_re = r"""'([^'\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))'"""

regex = re.compile('|'.join([str_re, chr_re]))

def repl(m):
  m = m.group(0)
  if m.startswith("'"):
    return m
  else:
    return ''
for line in sys.stdin:
  print regex.sub(repl, line.rstrip('\n'))

Essenzialmente stiamo trovando token letterali di stringhe e caratteri, quindi lasciando da soli i valori letterali char ma eliminando i valori letterali stringa.La regex letterale char è molto simile a quella letterale stringa.

Nel rubino:

#!/usr/bin/ruby
f=open(ARGV[0],"r")
s=f.read
puts(s.gsub(/"(\\(.|\n)|[^\\"\n])*"/,""))
f.close

stampa sull'output standard

In Python usando pyparsing:

from pyparsing import dblQuotedString

source = open(filename).read()
dblQuotedString.setParseAction(lambda : "")
print dblQuotedString.transformString(source)

Stampa anche su stdout.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top