Python PLY yacc解析器:如何处理未知值,如虚数?

Python PLY yacc解析器:如何处理未知值,如虚数?,python,parsing,yacc,ply,Python,Parsing,Yacc,Ply,我使用PLY:lex和yacc创建一种“bc”命令:可以解析,也可以分配变量 所以我可以解决这样的问题: 1+3.12-4=?或 5*3=?或 (1+3)*7/2=? 还有类似的东西,知道“abc”=10: (abc+3*abc)*2=? 但我真的不知道该如何处理未知值,或复数,比如虚数 我如何处理这个问题: 2*2*i+3-1应该等于4i+2 我想不出一个解析规则来处理这个虚数。有什么帮助吗 我的代码: 1。主代码: 从全局变量导入令牌 从lexer导入lexer 从解析器导入解析器 尽管如此

我使用PLY:lex和yacc创建一种“bc”命令:可以解析,也可以分配变量

所以我可以解决这样的问题:
1+3.12-4=?
5*3=?
(1+3)*7/2=?

还有类似的东西,知道“abc”=10:
(abc+3*abc)*2=?

但我真的不知道该如何处理未知值,或复数,比如虚数

我如何处理这个问题:
2*2*i+3-1
应该等于
4i+2

我想不出一个解析规则来处理这个虚数。有什么帮助吗

我的代码:

1。主代码:

从全局变量导入令牌
从lexer导入lexer
从解析器导入解析器
尽管如此:
s=输入(“>”)
如果是:
#lexer.input(s)
#尽管如此:
#tok=lexer.token()
#如果不是tok:
#中断
#打印(tok)
parser.parse(s)
2。lexer:

从全局变量导入令牌
将ply.lex导入为lex
t\u PLUS=r'\+'
t\u减号=r'\-'
t_次=r'\*'
t_DIVIDE=r'\/'
t_模=r'\%'
t_等于r'\='
t_LPAREN=r'\('
t_rpare=r'\)'
t_POWER=r'\^'
t_QUESTION=r'\?'
t#NAME=r'[a-zA-Z]{2,}|[a-hj-zA-hj-Z]'#除“i”之外的所有单词(仅字母)
t#u IMAGINE=r'i'#只有“i”这个词
t_命令=r'![\x00-\x7F]*'#在'!'之后的所有unicode字符
def t_编号(t):
r'\d+(\.\d+)
尝试:
t、 value=int(t.value)
除:
t、 值=浮动(t值)
返回t
t\u ignore=“\t”
def t_错误(t):
打印(“非法字符'%s'%t.value[0])
t、 lexer.skip(1)
lexer=lex.lex()
3。解析器:

从全局变量导入令牌
从全局变量导入变量
从全局变量导入prRed
从全局变量导入prGreen
从全局变量导入prLightPurple
将ply.yacc导入为yacc
优先权=(
(‘左’、‘加’、‘减’),
(‘左’、‘倍’、‘除’),
('right','UMINUS'),
)
def p_语句_赋值(t):
'语句:名称等于表达式'
变量[t[1]。lower()]=t[3]
打印(t[3])
def p_声明expr(t):
''声明:表达
|表达式等于问题“”
打印(t[1])
def p_表达式_binop(t):
''表达式:表达式加表达式
|表达式负表达式
|表达时间表达
|表达式除法表达式
|表达能力表达
|表达式模表达式“”'
如果t[2]='+':t[0]=t[1]+t[3]
elif t[2]='-':t[0]=t[1]-t[3]
elif t[2]=='*':t[0]=t[1]*t[3]
elif t[2]=='%':t[0]=t[1]%t[3]
elif t[2]=='^':t[0]=t[1]**t[3]
elif t[2]=='/':t[0]=float(t[1])/float(t[3])
如果t[0]%1==0:
t[0]=int(t[0])
其他:
t[0]=浮点数(t[0])
定义p_表达式(t):
'表达式:减去表达式%prec-UMINUS'
t[0]=-t[2]
def p_表达式_组(t):
'表达式:LPAREN表达式RPAREN'
t[0]=t[2]
def p_表达式_编号(t):
''表达式:数字
|想象一下“
t[0]=t[1]
def p_表达式_名称(t):
''表达式:名称
|名称等于问题“”“
尝试:
t[0]=变量[t[1]。下限()
除LookupError外:
prRed(“未定义的名称'%s'%t[1])
t[0]=0
def p_执行_命令(t):
'语句:命令'
字母=t[1]。拆分(“!”)[1]
如果字母==“h”:
绿色(“帮助:”)
打印(“-!p=打印所有变量”)
打印(“-!q=退出计算机”)
elif字母=='p':
如果变量:
prGreen(“变量:”)
对于键,变量中的值。项()
打印(“{}={}”。格式(键、值))
其他:
prRed(“变量:”)
打印(“没有变量”)
elif字母=='q':
prGreen(“再见!”)
退出()
其他:
打印(“键入“!h”以获取帮助。”)
def p_错误(t):
如果t:
打印(““%s”处的语法错误%t.value)
其他:
打印(“语法错误!”)
parser=yacc.yacc()
4。一些全局变量:

tokens=(
“姓名”,
“数字”,
"加",,
“负”,
"时代",,
"分",,
“模”,
“等于”,
“LPAREN”,
“RPAREN”,
"权力",,
“问题”,
“想象”,
“命令”,
)
变量={}
def prRed(skk):打印(“\033[91m{}\033[00m.”格式(skk))
def prGreen(skk):打印(“\033[92m{}\033[00m.”格式(skk))
def prLightPurple(skk):打印(“\033[94m{}\033[00m.”格式(skk))

i
在这里只是一个保留名称,因此您可以在lexer中识别它(与您识别任何其他关键字的方式相同)。如果您确实希望
2i
有效,那么您需要在lexer中做更多的工作,但应该清楚需要什么。(或者,您可以将其放入解析器中,这样
2i
也将有效,但我不得不说,这在我看来很奇怪。)

因此,您的问题实际上不是解析问题。您所需要的只是一个复数数据类型,可以方便地使用Python


Ply对语义值没有任何限制。如果您想使用复数,只需使用它们。(但请注意,Python使用
j
而不是
i
来表示jmagjnary数字。这并不意味着您也必须使用它们,但如果您想使用
i
,则必须进行显式的数字到字符串转换。)

将代码直接粘贴到文章中,这将有助于提高可读性。非常感谢您的回答。不幸的是,没有任何库可以简化com的管理