本帖最后由 话痨司机啊 于 2023-4-2 23:07 编辑
Ply中lex与yacc搭配使用
一、lex是用来标记语言中的特殊标记,在tokens 中定义字段
优先级:t_**的方法>正则长度(越长则优先级越高)
二、yacc 使用BNF语言解析标记字段,堆栈方式解析(先进后出,后进先出原则)
优先级:precedence 关键字定义优先级,left中第一行level是1级,第二行level2,以此类推,等级level越高则优先级越高,当left和right堆栈中冲突时,则left减少,right转移。nonassoc 关键字一般用来定义非关联字符如“><“”等
三、关于语法常见错误
1.递归错误:一般为BNF语法定义无终端引起
2.此关键词生成错误
[Python] 纯文本查看 复制代码 def p_production(p):
'production : some production ...'
raise SyntaxError
3.令牌错误(语法标记问题,令牌问题)
以下为示例:
[Python] 纯文本查看 复制代码 from ply import yacc, lex
class Parse:
def __init__(self, name, debug: bool = False):
self.name = name
self.debug = debug
self.lexer = lex.lex(module=self)
self.parser = yacc.yacc(module=self)
def print_input(self):
self.lexer.input(self.name)
for tok in self.lexer:
print(tok)
def exec(self):
return self.parser.parse(self.name, debug=self.debug)
class BaseParse(Parse):
def __init__(self, name):
super().__init__(name)
# List of token names. This is always required
tokens = (
'NUMBER',
'PLUS',
'MINUS',
'TIMES',
'DIVIDE',
'LPAREN',
'RPAREN',
)
# Regular expression rules for simple tokens
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'
# A regular expression rule with some action code
def t_NUMBER(self, t):
r'\d+'
t.value = int(t.value)
return t
# Define a rule so we can track line numbers
def t_newline(self, t):
r'\n+'
t.lexer.lineno += len(t.value)
# A string containing ignored characters (spaces and tabs)
t_ignore = '\t'
# Error handling rule
def t_error(self, t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
precedence = (
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
('right', 'UMINUS'),
)
def p_expression_plus(self, p):
"expression : expression PLUS expression"
p[0] = p[1] + p[3]
def p_expression_minus(self, p):
'expression : expression MINUS expression'
p[0] = p[1] - p[3]
def p_term_times(self, p):
'expression : expression TIMES expression'
p[0] = p[1] * p[3]
def p_term_div(self, p):
'expression : expression DIVIDE expression'
p[0] = p[1] / p[3]
def p_factor_num(self, p):
'expression : NUMBER'
p[0] = p[1]
def p_expr_uminus(self, p):
'expression : MINUS expression %prec UMINUS'
p[0] = -p[2]
def p_factor_expr(self, p):
'expression : LPAREN expression RPAREN'
p[0] = p[2]
def p_error(self, p):
print("Syntax error in input!")
class Filter:
def __init__(self):
self.filter = BaseParse(data)
self.print_lex_signle()
self.exec()
def exec(self):
reslut = self.filter.exec()
print(reslut)
def print_lex_signle(self):
self.filter.print_input()
if __name__ == "__main__":
data = "-5+(2*-3)" # 必须有data字段
Filter()
运行结果:
|