2013-12-12 11 views
13

Il mio obiettivo è analizzare come Python fa con le stringhe.Stringhe Lex con virgolette singole, doppie o triple

Domanda: Come scrivere un lex per supportare quanto segue:

  1. "string..."
  2. 'string...'
  3. """multi line string \n \n end"""
  4. '''multi line string \n \n end'''

Alcuni c ode:

 
states = (
     ('string', 'exclusive'), 
     ) 

# Strings 
def t_begin_string(self, t): 
    r'(\'|(\'{3})|\"|(\"{3}))' 
    t.lexer.push_state('string') 

def t_string_end(self, t): 
    r'(\'|(\'{3})|\"|(\"{3}))' 
    t.lexer.pop_state() 

def t_string_newline(self, t): 
    r'\n' 
    t.lexer.lineno += 1 

def t_string_error(self, t): 
    print("Illegal character in string '%s'" % t.value[0]) 
    t.lexer.skip(1) 


La mia idea attuale è di creare 4 stati unici che abbineranno i 4 diversi casi di stringa, ma mi chiedo se c'è un approccio migliore.

Grazie per il vostro aiuto!

+0

avete 4 tipi di stringa distinti quindi mi aspetterei che si avrebbe bisogno di 4 stati diversi. Presumibilmente '' 'stringa' '' è mal formata? – nimish

+0

Si possono usare due stati univoci, uno per le virgolette singole e uno per le virgolette triple, ma è necessario memorizzare il carattere virgolette da qualche parte.E 'discutibile quale metodo sia migliore. – Thayne

+0

Avevo paura di costruire 4 stati ... Possono funzionare due? Perché gli stati di inizio/fine non corrispondono al tipo di preventivo iniziale iniziale Ex '" string ..'... stringa ... "" il parser vedrà " string..' come stringa, quindi vedere '... stringa ..." 'come errore di analisi. –

risposta

0

Provare a utilizzare pyparsing module. Con questo modulo è possibile analizzare facilmente le stringhe con un buon stile senza usare espressioni regolari.

L'esempio seguente dovrebbe essere utile per analizzare espressioni come "string..." e """string""".

from pyparsing import Word, OneOrMore, alphas 

string = """string""" 
w = OneOrMore('\"') + Word(alphas + '.') + OneOrMore('\"') 
w.parseString(string) 
1

isolare la stringa comune per fare un singolo stato e cercare di costruire un automa a stati inferiori comunque u può avere uno sguardo su py yacc lex se u non sono preoccupati per utilizzando una libreria esterna che rende ur lavoro più facile

Tuttavia u bisogno di basi di lex yacc /// il codice di esempio è come mostrato

tokens = (
    'NAME','NUMBER', 
    'PLUS','MINUS','TIMES','DIVIDE','EQUALS', 
    'LPAREN','RPAREN', 
    ) 
    enter code here 

# Tokens 

t_PLUS = r'\+' 
t_MINUS = r'-' 
t_TIMES = r'\*' 
t_DIVIDE = r'/' 
t_EQUALS = r'=' 
t_LPAREN = r'\(' 
t_RPAREN = r'\)' 
t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 

def t_NUMBER(t): 
    r'\d+' 
    try: 
     t.value = int(t.value) 
    except ValueError: 
     print("Integer value too large %d", t.value) 
     t.value = 0 
    return t 

# Ignored characters 
t_ignore = " \t" 

def t_newline(t): 
    r'\n+' 
    t.lexer.lineno += t.value.count("\n") 

def t_error(t): 
    print("Illegal character '%s'" % t.value[0]) 
    t.lexer.skip(1) 

# Build the lexer 
import ply.lex as lex 
lex.lex() 

# Parsing rules 

precedence = (
    ('left','PLUS','MINUS'), 
    ('left','TIMES','DIVIDE'), 
    ('right','UMINUS'), 
    ) 

# dictionary of names 
names = { } 

def p_statement_assign(t): 
    'statement : NAME EQUALS expression' 
    names[t[1]] = t[3] 

def p_statement_expr(t): 
    'statement : expression' 
    print(t[1]) 

def p_expression_binop(t): 
    '''expression : expression PLUS expression 
        | expression MINUS expression 
        | expression TIMES expression 
        | expression DIVIDE expression''' 
    if t[2] == '+' : t[0] = t[1] + t[3] 
    elif t[2] == '-': t[0] = t[1] - t[3] 
    elif t[2] == '*': t[0] = t[1] * t[3] 
    elif t[2] == '/': t[0] = t[1]/t[3] 

def p_expression_uminus(t): 
    'expression : MINUS expression %prec UMINUS' 
    t[0] = -t[2] 

def p_expression_group(t): 
    'expression : LPAREN expression RPAREN' 
    t[0] = t[2] 

def p_expression_number(t): 
    'expression : NUMBER' 
    t[0] = t[1] 

def p_expression_name(t): 
    'expression : NAME' 
    try: 
     t[0] = names[t[1]] 
    except LookupError: 
     print("Undefined name '%s'" % t[1]) 
     t[0] = 0 

def p_error(t): 
    print("Syntax error at '%s'" % t.value) 

import ply.yacc as yacc 
yacc.yacc() 

while 1: 
    try: 
     s = input('calc > ') # Use raw_input on Python 2 
    except EOFError: 
     break 
    yacc.parse(s) 
Problemi correlati