Pregunta

Puede alguien me punto a un programa que se despoja de cadenas de código fuente en C? Ejemplo

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

se convierte

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

Lo que busco es un programa muy parecido stripcmt Sólo que quiero despojar cuerdas y no comentarios.

La razón por la que estoy en busca de un programa ya desarrollado y no sólo algunos de expresiones regulares es útil porque cuando se inicie la consideración de todos los casos de esquina (cotizaciones dentro de las cadenas, las cadenas multilínea, etc) cosas por lo general comienzan a ser (mucho) más complejo de lo que parece. Y hay límites a lo que pueden lograr los RE, sospecho que no es posible para esta tarea. Si cree que tiene una muy robusta expresión regular no dude en aportar, pero por favor no sed 's/"[^"]*"//g' ingenua como sugerencias.

(No hay necesidad de un manejo especial de cuerdas (posiblemente un-ended) dentro de los comentarios, los que se elimina en primer lugar)

El apoyo a las cadenas multilínea con saltos de línea empotrados no es importante (no legal C), pero las cadenas que abarcan múltiples líneas que terminan con \ al final debe ser apoyada.

Esto es casi el mismo que el algunos < a href = "https://stackoverflow.com/questions/676296/how-to-tokenize-parse-string-literals-from-javascript-source-code"> otro questions , pero no he encontrado ninguna referencia a la necesidad de herramientas.

¿Fue útil?

Solución

Puede descargar el href="http://www.bdc.cx/download/stripcmt/stripcmt-0.1.2.tar.gz" rel="nofollow noreferrer"> código fuente (.tar.gz - 5kB). Es trivialmente pequeña, y no debe ser demasiado difícil de adaptar a las cadenas de creación de bandas en su lugar (es publicado el bajo la GPL).

También puede ser que desee investigar las reglas del lenguaje léxicas oficiales para las cadenas C. Me encontrado este muy rápidamente, pero no podría ser definitivo. Define una cadena como:

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

Otros consejos

Todas las fichas en C (y la mayoría de otros lenguajes de programación) son "regular". Es decir, que pueden ir acompañadas de una expresión regular.

Una expresión regular para cadenas de C:

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

La expresión regular no es demasiado difícil de entender. Básicamente una cadena literal es un par de comillas dobles que rodean un montón de:

  • no especiales (no presupuesto / barra invertida / salto de línea) caracteres
  • escapa, que comienzan con una barra invertida y luego se componen de uno de:
    • un simple carácter de escape
    • 1 a 3 dígitos octales
    • x y 1 o más dígitos hexadecimales

Esto se basa en las secciones 6.1.4 y 6.1.3.4 de la especificación C89 / C90. Si todo lo demás se deslizó en en C99, esto no va a coger, pero eso no debería ser difícil de solucionar.

Aquí hay un script en Python para filtrar un fichero fuente C eliminar los literales de cadena:

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:

Se me ocurrió después de que he publicado lo anterior que si bien es cierto que todos los tokens de C son regulares, por no tokenizar todo lo que tenemos una oportunidad para los problemas. En particular, si una doble cita aparece en lo que debería ser otra ficha que podemos ser guiados por el camino del jardín. Usted ha mencionado que los comentarios ya han sido despojados, por lo que la única otra cosa que realmente necesitamos es preocuparse por caracteres literales (aunque el enfoque Im que va a utilizar puede ser fácilmente ampliado para tramitar las observaciones también). Aquí está una escritura más robusta que maneja literales de caracteres:

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

En esencia estamos encontrando cadena y el carácter simbólico literal, y luego dejando literales de char solo, pero excluyendo los literales de cadena. La expresión regular literal char es muy similar a la cadena literal.

En Ruby:

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

imprime en la salida estándar

En Python usando pyparsing:

from pyparsing import dblQuotedString

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

También imprime en la salida estándar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top