2013-12-12 314 views
13

我的目標是像Python一樣用字符串進行解析。帶單引號,雙引號或三引號的Lex字符串

問題:如何寫一個法支持以下內容:

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

一些C頌:

 
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

你有4種不同的字符串類型,所以我期望你會需要4個不同的狀態。大概'''字符串「'''是不合格的? – nimish

+0

你可以使用兩個獨特的狀態,一個用於單引號,一個用於三引號,但是你需要在某處存儲引號字符,有什麼好方法值得商榷 – Thayne

+0

因爲開始/結束狀態不匹配最初的開始引用類型,例如''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

隔離常見字符串,使一個單一的狀態,並嘗試建立與較小的狀態自動機然而ü可以對PY法YACC看看,如果妳不擔心使用,使烏拉圭回合的工作更容易的外部庫

但是u需要YACC法的 基本///的示例代碼所示

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) 
相關問題