【PLY】Lex和Yacc简单示例

PLY是流行的编译器构造工具lex和yacc的纯python实现
PLY官方文档:http://www.dabeaz.com/ply/
PLY文档翻译:https://qyliang.blog.csdn.net/article/details/97686897

PLY由两个单独的模块组成lex.py和 yacc . py 。都可以在名为ply的Python包中找到。

lex.py模块用于将输入的文本通过正则表达式转化成一系列特定的token。

yacc.py用于识别以上下文无关语法形式指定的语言语法。

lex示例

# ------------------------------------------------------------
# calclex.py
#
# tokenizer for a simple expression evaluator for
# numbers and +,-,*,/
# ------------------------------------------------------------
import ply.lex as lex
 
# 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(t):
    r'\d+'
    t.value = int(t.value)    
    return t
 
# Define a rule so we can track line numbers
def t_newline(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(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)
 
# Build the lexer
lexer = lex.lex()


# =============================================================================
# Test it out
# =============================================================================
# Test it out
data = '''
3 + 4 * 10
  + -20 *2
 '''
 
# Give the lexer some input
lexer.input(data)
 
# Tokenize
while True:
    tok = lexer.token()
    if not tok: 
        break      # No more input
    print(tok)

最终打印结果:
在这里插入图片描述

YACC示例

# Yacc example
 
import ply.yacc as yacc
 
# Get the token map from the lexer.  This is required.
from LexExample import tokens
 
def p_expression_plus(p):
    'expression : expression PLUS term'
    p[0] = p[1] + p[3]
 
def p_expression_minus(p):
    'expression : expression MINUS term'
    p[0] = p[1] - p[3]
 
def p_expression_term(p):
    'expression : term'
    p[0] = p[1]
 
def p_term_times(p):
    'term : term TIMES factor'
    p[0] = p[1] * p[3]
 
def p_term_div(p):
    'term : term DIVIDE factor'
    p[0] = p[1] / p[3]
 
def p_term_factor(p):
    'term : factor'
    p[0] = p[1]
 
def p_factor_num(p):
    'factor : NUMBER'
    p[0] = p[1]
 
def p_factor_expr(p):
    'factor : LPAREN expression RPAREN'
    p[0] = p[2]
 
# Error rule for syntax errors
def p_error(p):
    print("Syntax error in input!")
 
# Build the parser
parser = yacc.yacc()
 
while True:
   try:
       s = input('calc > ')
       #s = '3 + 5 * (10 - 20)'
   except EOFError:
       break
   if not s: continue
   result = parser.parse(s)
   print(result)

打印结果为:
在这里插入图片描述

对于结果的解释和跟多的细节在文档中有介绍。

发布了205 篇原创文章 · 获赞 655 · 访问量 53万+

猜你喜欢

转载自blog.csdn.net/qq_33414271/article/details/97700693
今日推荐