ply编译语言的应用研究

查看 53|回复 1
作者:话痨司机啊   
Ply中lex与yacc搭配使用
一、lex是用来标记语言中的特殊标记,在tokens 中定义字段
    优先级:t_**的方法>正则长度(越长则优先级越高)
二、yacc 使用BNF语言解析标记字段,堆栈方式解析(先进后出,后进先出原则)
    优先级:precedence 关键字定义优先级,left中第一行level是1级,第二行level2,以此类推,等级level越高则优先级越高,当left和right堆栈中冲突时,则left减少,right转移。nonassoc 关键字一般用来定义非关联字符如“>[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()
运行结果:


Snipaste_2023-04-02_22-48-54.png (84.69 KB, 下载次数: 0)
下载附件
2023-4-2 23:04 上传

优先级, 黑体

whizzer   

谢谢分享
您需要登录后才可以回帖 登录 | 立即注册

返回顶部