【问题标题】:How to implement for circular dependency grammar structure in parser using PLY如何使用 PLY 在解析器中实现循环依赖语法结构
【发布时间】:2020-07-23 08:03:23
【问题描述】:

作为家庭作业的一部分,我正在尝试使用 PLY 构建扫描仪和解析器。

下面是我想要达到的语法:

我认为我能够处理扫描仪部分,但我需要一些关于解析器部分的帮助。我正在努力在 和 中添加规则。我不断收到以下消息。根据语法,就像某种循环引用。在这种情况下,我不确定如何正确实施它。我对编译器概念和 Python 编程相当陌生。非常感谢任何帮助。

警告:1 减少/减少冲突

警告:使用规则(语句 -> binop)解决状态 3 中的减少/减少冲突

警告:在状态 3 中拒绝规则(术语 -> binop)

这是我的源代码:

import sys
sys.path.insert(0, "../..")

tokens = ('ID',   # ID represents a variable name
          'NUM',  # NUM represents the signed integer data type
          'EQL',  # EQL represents the equal sign (=)
          'ADD',  # ADD represents the addition operator (+)
          'SUB',  # SUB represents the subtraction operator (-)
          'MUL',  # MUL represents the multiplication operator (*)
          'DIV',  # DIV represents the division operator (/)
          'EXP',  # EXP represents the exponentiation operator (**)
          'STR',  # STR represents the string data type
          'VAR'   # var represents the literal string 'VAR'
          )

# Regular expresssion rules for the equal sign and literals
t_EQL = r'\='
t_ADD = r'\+'
t_SUB = r'-'
t_MUL = r'\*'
t_DIV = r'\/'

# create a method for parsing VAR tokens
    # regex for finding VAR tokens
    # return token
def t_VAR(t):
  r'VAR'
  return t

# create a method for parsing ID tokens
    # regex for finding ID tokens
    # return token
def t_ID(t):
  r'[a-zA-Z_][0-9a-zA-Z_]*'
  return t

# create a method for parsing NUM tokens
    # regex for finding NUM tokens
    # convert token from str to int
    # return token
def t_NUM(t):
  r'-?\d+'
  t.value = int(t.value)
  return t

# create a method for parsing EXP tokens
    # regex for finding EXP tokens
    # return token
def t_EXP(t):
  r'\*{2}'
  return t

# create a method for parsing STR tokens
    # regex for finding STR tokens
    # return token
def t_STR(t):
  r'"[\s.a-zA-Z_]+"'
  return t

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
lexer = lex.lex()


# Parsing rules

precedence = (
    ('left','ADD','SUB'),
    ('left','MUL','DIV'),
    ('left', 'EXP'),
    ('right', 'UMINUS')
    )

# dictionary of names
names = { }

def p_statement(p):
  '''statement : assign
               | declare
               | binop
               '''
  p[0] = p[1]

def p_statement_print(p):
  '''statement : term'''
  print(p[1])

def p_assign(p):
    '''assign : ID EQL term
              | ID EQL STR'''
    names[p[1]] = p[3]

def p_binop(p):
    '''binop : term ADD term
                  | term SUB term
                  | term MUL term
                  | term DIV term
                  | term EXP term
                  | STR ADD STR'''
    if p[2] == '+'  : p[0] = p[1] + p[3]
    elif p[2] == '-': p[0] = p[1] - p[3]
    elif p[2] == '*': p[0] = p[1] * p[3]
    elif p[2] == '/': p[0] = p[1] / p[3]
    elif p[2] == '**': p[0] = p[1] ** p[3]

def p_declare(p):
  '''declare : VAR ID
             | VAR assign'''
  names[p[0]] = p[2]

def p_uminus(p):
    'term : SUB term %prec UMINUS'
    p[0] = -p[2]

def p_term_binop(p):
  'term : binop'
  p[0] = p[1]


def p_term_number(p):
  'term : NUM'
  p[0] = p[1]

def p_term_name(p):
  'term : ID'
  try:
    p[0] = names[p[1]]
  except LookupError:
    print("Undefined name '%s'" % p[1])
    p[0] = 0

def p_error(p):
  print("Syntax error at '%s'" % p.value)

import ply.yacc as yacc
parser = yacc.yacc()

while True:
  try:
    s = input("Enter a line of code: ")
  except EOFError:
    break
  if not s:
    continue
  yacc.parse(s)

【问题讨论】:

    标签: python-3.x parsing lexer ply


    【解决方案1】:

    你有这三个规则:

    statement : binop
    statement : term
    term : binop
    

    这是模棱两可的,因为包含binop 的语句可以直接解析为binop,也可以解析为term,即binop。 (碰巧,这两种情况下的操作不同,但即使操作相同,Ply 也会抱怨,因为 Ply 并没有真正看到这些操作;它们是不透明的 Python 代码。)

    因此,您需要通过删除其中一个模棱两可的产品来解决这个问题。原始语法应该会指导您。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-27
      • 2020-01-26
      • 1970-01-01
      • 2022-12-07
      • 2015-04-09
      • 1970-01-01
      相关资源
      最近更新 更多