2013-12-12 13 views
13

Mein Ziel ist es, wie Python mit Strings zu parsen.Lex Strings mit Einzel-, Doppel- oder Dreifach-Anführungszeichen

Frage: Wie eine lex schreiben folgendes zu unterstützen:

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

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


Meine aktuelle Idee ist 4 eindeutige Zustände zu erstellen, die die 4 verschiedenen String Fällen übereinstimmen, aber ich frage mich, ob es ein besserer Ansatz ist.

Danke für Ihre Hilfe!

+0

Sie haben 4 verschiedene String-Typen, so würde ich erwarten, würden Sie 4 verschiedene Zustände benötigen. Vermutlich ist "string" '' schlecht gebildet? – nimish

+0

Sie könnten zwei eindeutige Zustände verwenden, einen für einfache Anführungszeichen und einen für dreifache Anführungszeichen, aber Sie müssten das Anführungszeichen irgendwo speichern. Es ist strittig, welche Methode besser ist. – Thayne

+0

Ich habe befürchtet, 4 Zustände aufzubauen ... Können zwei durchgehen? Weil die Start-/Endzustände nicht mit dem anfänglichen Startquotietyp übereinstimmen. Ex '" String .. '... String ... "' wird der Parser sehen ' string..' als String dann '' string ... "' als Parse-Fehler. –

Antwort

0

Verwenden Sie die pyparsing module. Mit diesem Modul können Sie Strings mit gutem Stil analysieren, ohne reguläre Ausdrücke zu verwenden. Das folgende Beispiel soll Ihnen beim Parsen von Ausdrücken wie "string..." und """string""" helfen.

from pyparsing import Word, OneOrMore, alphas 

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

isolieren die gemeinsame Zeichenfolge, die einen einzigen Staat zu machen und versucht, einen Automaten mit kleineren Staaten bauen jedoch u einen Blick auf py lex yacc haben kann, wenn u über die Verwendung eine externe Bibliothek nicht besorgt sind, die ur Arbeit erleichtert

Allerdings müssen u Grundlagen der lex yacc /// das Codebeispiel wie

gezeigt ist
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)