话痨司机啊 发表于 2023-4-2 23:01

ply编译语言的应用研究

本帖最后由 话痨司机啊 于 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.此关键词生成错误
def p_production(p):
    'production : some production ...'
    raise SyntaxError
3.令牌错误(语法标记问题,令牌问题)


以下为示例:
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)
      t.lexer.skip(1)

    precedence = (
      ('left', 'PLUS', 'MINUS'),
      ('left', 'TIMES', 'DIVIDE'),
      ('right', 'UMINUS'),
    )

    def p_expression_plus(self, p):
      "expression : expression PLUS expression"
      p = p + p

    def p_expression_minus(self, p):
      'expression : expression MINUS expression'
      p = p - p

    def p_term_times(self, p):
      'expression : expression TIMES expression'
      p = p * p

    def p_term_div(self, p):
      'expression : expression DIVIDE expression'
      p = p / p

    def p_factor_num(self, p):
      'expression : NUMBER'
      p = p

    def p_expr_uminus(self, p):
      'expression : MINUS expression %prec UMINUS'
      p = -p

    def p_factor_expr(self, p):
      'expression : LPAREN expression RPAREN'
      p = p

    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()

运行结果:


whizzer 发表于 2023-4-6 07:50

谢谢分享
页: [1]
查看完整版本: ply编译语言的应用研究