2012-07-19 18 views
7

Sto implementando un interprete per un linguaggio di scripting dell'editor di testo obsoleto e sto avendo qualche problema a far funzionare correttamente un lexer.modo più efficiente per analizzare questo linguaggio di scripting

Ecco un esempio della parte problematica del linguaggio:

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

I / personaggi sembrano citare le stringhe e anche agire come delimitatore per il comando C (CHANGE) in una sintassi sed tipo, anche se consente qualsiasi carattere come delimitatore.

Probabilmente ho implementato circa la metà dei comandi più comuni, usando solo parse_tokens(line.split()) fino ad ora. Era veloce e sporco, ma funzionava sorprendentemente bene.

Per evitare di scrivere il mio lexer, ho provato shlex.

Funziona abbastanza bene, tranne per i casi 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 

Qualcuno sa un modo semplice per ottenere questo risultato (con shlex o altro)?

EDIT:

Se aiuta, ecco la CHANGE comando di sintassi indicata nel file di aiuto:

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

La similmente difficile tokenize X e Y comandi:

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

Avete accesso alla definizione della lingua? Se è così, una citazione dalla parte rilevante potrebbe essere utile a tutti noi. – Marcin

+1

@Marcin Ho aggiunto alcune informazioni rilevanti dal file di aiuto, è tutta la documentazione che ho. –

+0

Non conosco 'shlex', ma penso che' regex' [(re)] (http://docs.python.org/library/re.html) possa anche essere utile. – machaku

risposta

0

I il problema è probabilmente che lo / non è in attesa di virgolette ma solo di delimitazione. Immagino che il terzo carattere sia sempre usato per definire il delimitatore. Inoltre non è necessario il / o ; nell'output, vero?

Ho appena fatto il seguente solo con split per il caso L e il comando 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', ''] 

Per la " * *" parte opzionale è possibile utilizzare split(" ") sulla ultimo elemento nell'elenco.

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

sfortunatamente non è * sempre * il terzo personaggio, ma proverò questo approccio e postback, grazie. –

Problemi correlati