Lex带有单引号,双引号或三引号

时间:2013-12-12 12:08:32

标签: python yacc lexer ply

我的目标是像Python一样解析字符串。

问题:如何撰写lex以支持以下内容:

  1. "string..."
  2. 'string...'
  3. """multi line string \n \n end"""
  4. '''multi line string \n \n end'''
  5. 部分代码:

    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个独特状态,但我想知道是否有更好的方法。

    感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

隔离公共字符串以构成单个状态并尝试构建具有较小状态的自动机但是如果您不担心使用外部库使您的工作更容易,则可以查看py lex yacc

但是你需要lex 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)

答案 1 :(得分:0)

尝试使用pyparsing module。使用此模块,您可以轻松解析具有良好风格的字符串,而无需使用正则表达式

以下示例也可以帮助您解析"string...""""string"""等表达式。

from pyparsing import Word, OneOrMore, alphas

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