2013-12-12 11 views
13

私の目的は、Pythonが文字列で行うように解析することです。一重引用符、二重引用符、三重引用符を含むLex文字列

質問:以下をサポートするためのlexの書き方を

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

一部の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) 


私の現在の考えは4つの異なる文字列の例と一致します4の固有の状態を作成することですが、もっと良い方法があります場合、私は思ったんだけど。

ありがとうございました!

+0

を示すようにlexのyaccの ///サンプルコードの基本は、私はあなたが4つの異なる状態を必要とするだろうと期待しておりますので、あなたは4つの異なる文字列型を持っている必要があります。 – nimish

+0

一重引用符と三重引用符の2つのユニークな状態を使用できますが、引用符をどこかに格納する必要があります。どの方法が良いかは議論の余地があります。 – Thayne

+0

私は4つの状態を構築することを恐れていました... 2つのことができますか?開始/終了の状態が最初の開始引用符の型と一致していないためEx '" string .. "... string ..." 'パーサーは' string ... 'を文字列として使用すると、' ... string ... "'が解析エラーとして表示されます。 –

答えて

0

pyparsing moduleをお試しください。このモジュールを使うと、正規表現を使わなくても良いスタイルで文字列を簡単に解析できます。

次の例は、"string...""""string"""のような式の解析にも役立ちます。

from pyparsing import Word, OneOrMore, alphas 

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

単一の状態を作り、低い状態とオートマトンを構築しようとする一般的な文字列を隔離uはウル作業が容易になり、外部ライブラリを使用して心配していない場合はuはPYのlex yaccの上で見ることができます

しかしuが

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) 
関連する問題