gpt4 book ai didi

python - 在我实现变量后,PLY 认为数学表达式是语法错误

转载 作者:行者123 更新时间:2023-12-01 05:02:32 25 4
gpt4 key购买 nike

我一直在使用 PLY,在让示例发挥作用后,我决定应该实现变量。这很好用,但现在任何未分配给变量的数学表达式似乎都会引发语法错误(不是 python 语法错误,而是我的语言中的语法错误)。例如:

calc> a = 5
Name: a
Number: 5
Assigning variable a to 5
{'a': 5}
calc> 6 + 1
Number: 6
SYNTACTIC ERROR: line: 1 position: 0 Syntax error: 6
Number: 1
{'a': 5}

我注意到我将数字语法函数放在变量赋值之上,然后变量就会中断并且计算可以工作。

词法分析器:

#!/usr/bin/env python

### LEXICAL ANALYSIS ###


import ply.lex as lex

import colorama
colorama.init()

tokens = (
"NUMBER",
"PLUS",
"MINUS",
"MULTIPLY",
"DIVIDE",
"LBRACKET",
"RBRACKET",
"NAME",
"EQUALS"
)

t_PLUS = r"\+"
t_MINUS = r"-"
t_MULTIPLY = r"\*"
t_DIVIDE = r"/"
t_LBRACKET = r"\("
t_RBRACKET = r"\)"
t_EQUALS = r"="

t_ignore = "\t\r "

def t_NUMBER(t):
r"\d+"
print "Number:", t.value
t.value = int(t.value)
return t

def t_NAME(t):
r"[a-zA-Z]+\w*"
print "Name:", t.value
return t

def t_newline(t):
r"\n+"
t.lexer.lineno += len(t.value)

def t_COMMENT(t):
r"\#.*"
print "Comment:", t.value

def t_error(t):
print colorama.Fore.RED + "LEXICAL ERROR: line:", t.lexer.lineno, "position:", t.lexer.lexpos, "Invalid token:", t.value, colorama.Fore.RESET
t.lexer.skip(len(t.value))

lexer = lex.lex()

解析器:

import ply.yacc as yacc

from langlex import tokens

import colorama
colorama.init()

variables = {}

def p_assignment(p):
"assignment : NAME EQUALS expression"
print "Assigning variable", p[1], "to", p[3]
variables[p[1]] = p[3]

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_expression_name(p):
"expression : NAME"
p[0] = variables[p[1]]

def p_term_times(p):
"term : term MULTIPLY 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_expr(p):
"factor : LBRACKET expression RBRACKET"
p[0] = p[2]

def p_factor_num(p):
"factor : NUMBER"
p[0] = p[1]

def p_error(p):
if(p):
print colorama.Fore.RED + "SYNTACTIC ERROR: line:", p.lexer.lineno, "position:", p.lexpos, "Syntax error:", p.value, colorama.Fore.RESET
else:
print colorama.Fore.RED + "SYNTACTIC ERROR: Unknown syntax error" + colorama.Fore.RESET

parser = yacc.yacc()

while True:
s = raw_input("calc> ")

if not(s):
continue
result = parser.parse(s)

if(result):
print result

print variables

最佳答案

在创建p_assignment时,您创建了一个新的起始语法符号。来自文档:

The first rule defined in the yacc specification determines the starting grammar symbol. Whenever the starting rule is reduced by the parser and no more input is available, parsing stops and the final value is returned.

http://www.dabeaz.com/ply/ply.html#ply_nn24

这意味着,对于您的语法人员来说,唯一允许的输入句子是赋值:

$ python p_o.py 
Generating LALR tables
calc> a=1
Name: a
Number: 1
Assigning variable a to 1
{'a': 1}
calc> a
Name: a
SYNTACTIC ERROR: Unknown syntax error
{'a': 1}
calc> 1
Number: 1
SYNTACTIC ERROR: line: 1 position: 0 Syntax error: 1
{'a': 1}

因此,我们需要一个起始语法符号,通过某种路径解析为表达式。我选择添加一个语句非终结符作为起始语法符号:

...
def p_statement_assignment(p):
"statement : assignment"
pass

def p_statement_expression(p):
"statement : expression"
p[0] = p[1]

def p_assignment(p):
"assignment : NAME EQUALS expression"
print "Assigning variable", p[1], "to", p[3]
variables[p[1]] = p[3]
...
$ python p_1.py 
Generating LALR tables
calc> a=1
Name: a
Number: 1
Assigning variable a to 1
{'a': 1}
calc> a
Name: a
1
{'a': 1}
calc> 1
Number: 1
1
{'a': 1}
calc>

关于python - 在我实现变量后,PLY 认为数学表达式是语法错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25770562/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com