2012-07-19 17 views
7

Estoy implementando un intérprete para un lenguaje de scripting del editor de texto anticuado, y estoy teniendo algunos problemas para conseguir que un lexer funcione correctamente.manera más eficiente de analizar este lenguaje de scripting

Aquí hay un ejemplo de la parte problemática de la lengua:

T 
L /LOCATE ME/ 
C /LOCATE ME/CHANGED ME/ * * 
C ;CHANGED ME;CHANGED ME AGAIN; 1 * 

Los / personajes parecen citar cuerdas y también actúan como un delimitador para el comando C (CHANGE) en una sintaxis sed de tipo, aunque permite cualquier carácter como delimitador.

Probablemente he implementado aproximadamente la mitad de los comandos más comunes, simplemente usando parse_tokens(line.split()) hasta ahora. Eso fue rápido y sucio, pero funcionó sorprendentemente bien.

Para evitar escribir mi propio lexer, probé shlex.

Funciona bastante bien, a excepción de los casos CHANGE:

import shlex 

def shlex_test(cmd_str): 
    lex = shlex.shlex(cmd_str) 
    lex.quotes = '/' 
    return list(lex) 

print(shlex_test('L /spaced string/')) 
# OK! gives: ['L', '/spaced string/'] 

print(shlex_test('C /spaced string/another string/ * *')) 
# gives : ['C', '/spaced string/', 'another', 'string/', '*', '*'] 
# desired : any format that doesn't split on a space between /'s 

print(shlex_test('C ;a b;b a;')) 
# gives : ['C', ';', 'b', 'a', ';', 'a', 'b', ';'] 
# desired : same format as CHANGE command above 

Alguien sabe una manera fácil de lograr esto (con shlex o no)?

EDIT:

Si ayuda, aquí está la sintaxis CHANGE orden dada en el archivo de ayuda:

''' 
C [/stg1/stg2/ [n|n m]] 

    The CHANGE command replaces the m-th occurrence of "stg1" with "stg2" 
for the next n lines. The default value for m and n is 1.''' 

El igualmente difíciles de tokenize X y Y comandos:

''' 
X [/command/[command/[...]]n] 
Y [/command/[command/[...]]n] 

    The X and Y commands allow the execution of several commands contained 
in one command. To define an X or Y "command string", enter X (or Y) 
followed by a space, then individual commands, each separated by a 
delimiter (e.g. a period "."). An unlimited number of commands may be 
placed in the X or Y command string. Once the command string has been 
defined, entering X (or Y) followed optionally by a count n will execute 
the defined command string n times. If n is not specified, it will 
default to 1.''' 
+0

¿Tiene acceso a la definición del idioma? Si es así, una cita de la parte relevante podría ser útil para todos nosotros. – Marcin

+1

@Marcin Agregué información relevante del archivo de ayuda, es toda la documentación que tengo. –

+0

No sé 'shlex' pero creo que' regex' [(re)] (http://docs.python.org/library/re.html) también puede ser útil. – machaku

Respuesta

0

Los Es probable que el problema sea que / no está parado para las comillas, sino solo para delimitar. Supongo que el 3er carácter se usa siempre para definir el delimitador. Además, no necesita / o ; en la salida, ¿verdad?

acabo de hecho lo siguiente solamente con split para el caso de L y de comandos C:

>>> def parse(cmd): 
...  delim = cmd[2] 
...  return cmd.split(delim) 
... 
>>> c_cmd = "C /LOCATE ME/CHANGED ME/ * *" 
>>> parse(c_cmd) 
['C ', 'LOCATE ME', 'CHANGED ME', ' * *'] 

>>> c_cmd2 = "C ;a b;b a;" 
>>> parse(c_cmd2) 
['C ', 'a b', 'b a', ''] 

>>> l_cmd = "L /spaced string/" 
>>> parse(l_cmd) 
['L ', 'spaced string', ''] 

Para la parte opcional " * *" podría utilizar split(" ") el último elemento de la lista.

>>> parse(c_cmd)[-1].split(" ") 
['', '*', '*'] 
+0

desafortunadamente no es * siempre * el tercer personaje, pero voy a probar este enfoque y publicar de nuevo, gracias. –

Cuestiones relacionadas