Question

Quelqu'un peut-il me pointer vers un programme qui dénude les chaînes à partir du code source C? Exemple

#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;
}

devient

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

Ce que je cherche est un programme très semblable stripcmt seulement que je veux dépouiller les chaînes et pas des commentaires.

La raison pour laquelle je suis à la recherche d'un programme déjà mis au point et non pas seulement une expression régulière à portée de main est parce que quand vous commencez à considérer tous les cas d'angle (guillemets dans les chaînes, les chaînes multi-lignes, etc.) les choses commencent généralement à être (beaucoup) plus complexe qu'il n'y paraît. Et il y a des limites à ce que peuvent atteindre REs, je pense qu'il est impossible pour cette tâche. Si vous ne pensez que vous avez une très expression régulière robuste ne hésitez pas à présenter, mais s'il vous plaît pas sed 's/"[^"]*"//g' naïfs comme des suggestions.

(Pas besoin d'un traitement spécial des cordes (peut-être un CDI) dans les commentaires, ceux-ci seront d'abord enlevé)

Support pour les chaînes multi-lignes avec sauts de lignes n'est pas important (non C juridique), mais les chaînes couvrant plusieurs lignes se terminant par \ à la fin doit être pris en charge.

Ceci est presque le même que le certains < a href = "https://stackoverflow.com/questions/676296/how-to-tokenize-parse-string-literals-from-javascript-source-code"> autre questions , mais j'ai trouvé aucune référence à aucun outil.

Était-ce utile?

La solution

Vous pouvez télécharger le code source à StripCmt (tar.gz - 5 Ko). Il est trivialement petit, et ne devrait pas être trop difficile à adapter aux chaînes de striping à la place (il est edit'e sous la GPL).

Vous pouvez également enquêter sur les règles linguistiques lexicales officielles pour les chaînes C. J'ai trouvé cette très rapidement, mais il pourrait ne pas être définitive. Il définit une chaîne comme:

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

Autres conseils

Tous les jetons en C (et la plupart des autres langages de programmation) sont « réguliers ». Autrement dit, ils peuvent aller de pair avec une expression régulière.

Une expression régulière pour les chaînes C:

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

Le regex est pas trop difficile à comprendre. Fondamentalement, une chaîne littérale est une paire de guillemets doubles autour d'un groupe de:

  • caractères non spéciaux (non-citation / barre oblique inverse / saut de ligne)
  • fuites, qui commencent par une barre oblique inverse, puis se composent d'un élément parmi:
    • simple caractère d'échappement
    • 1 à 3 chiffres octaux
    • x et une ou plusieurs chiffres hexadécimaux

Ceci est basé sur des sections 6.1.4 et 6.1.3.4 de la spécification C89 / C90. Si quelque chose d'autre se glissa dans à C99, ce ne sera pas attraper, mais cela ne devrait pas être difficile à corriger.

Voici un script python pour filtrer un fichier source C suppression littéraux de chaîne:

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'))

EDIT:

Il me est apparu après que j'ai posté ce qui précède que si il est vrai que tous les jetons C sont régulières, de ne pas tokenizing tout ce que nous avons l'occasion des ennuis. En particulier, si une double citation apparaît dans ce qui devrait être un autre jeton, nous pouvons être conduire sur le chemin du jardin. Vous avez mentionné que les commentaires ont déjà été dépouillés, de sorte que la seule chose que nous avons vraiment besoin de vous soucier de caractère sont littéraux (bien que l'approche Im va utiliser peut être facilement étendu pour traiter les observations aussi bien). Voici un script plus robuste qui gère les caractères littéraux:

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'))

Pour l'essentiel, nous nous apercevons la chaîne et le caractère symbolique littéral, puis laissant seul type char littéraux mais décapage à littéraux de chaîne. Le charbon regex littérale est très similaire à la chaîne littérale.

En ruby:

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

imprime sur la sortie standard

En Python utilisant pyparsing:

from pyparsing import dblQuotedString

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

imprime également sur la sortie standard.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top