我正在尝试为以下方程编写方程解析器:4*sin(1+cos(10/2))
我使用 lex 来获取标记,并使用 yacc 作为解析器模块。
我现在的实际问题是我不知道如何定义函数的语法。函数通常是这样构造的 FunctionName( Expression)
因此对于解析器语法来说它将是 function : FUNCTION LPAREN expression RPAREN
(我希望)。
但是我将如何处理像 sin(3+cos(0)*10) 这样构建的函数
。这将是一个函数中的一个函数,同时不要忘记关心 3+
和 *10
。希望我已经足够好地指出了我的问题。
这是我的代码:
import ply.lex as lex
import ply.yacc as yacc
import math
tokens = (
'DIV',
'TIMES',
'MINUS',
'PLUS',
'FUNCTION',
'NUMBER',
'LPAREN',
'RPAREN',
)
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIV = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_ignore = ' '
def t_NUMBER(t):
r'([0-9]*\.[0-9]+|[0-9]+)'
t.value = float(t.value)
return t
def t_FUNCTION(t):
r'sin|cos|tan'
return t
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
# Parser
'''
Here i need some help
'''
def p_function_exp(p):
'function : expression PLUS function'
p[0] = p[1] + p[3]
def p_function(p):
'function : FUNCTION LPAREN expression RPAREN'
if p[1] == 'sin':
p[0] = math.sin(p[3])
def p_expression_minus(p):
'expression : expression MINUS term'
p[0] = p[1] - p[3]
def p_expression_plus(p):
'expression : expression PLUS term'
p[0] = p[1] + p[3]
def p_expression_term(p):
'expression : term'
p[0] = p[1]
def p_term_div(p):
'term : term DIV factor'
p[0] = p[1] / p[3]
def p_term_times(p):
'term : term TIMES factor'
p[0] = p[1] * p[3]
def p_term_factor(p):
'term : factor'
p[0] = p[1]
def p_factor(p):
'factor : NUMBER'
p[0] = p[1]
def p_factor_exp(p):
'factor : LPAREN expression RPAREN'
p[0] = p[2]
# Error rule for syntax errors
def p_error(p):
print("Syntax error in input!")
# Build the parser
parser = yacc.yacc()
while True:
try:
s = input('>> ')
equation = lex.lex()
equation.input(s)
while True:
tok = equation.token()
if not tok: break
print(tok)
except EOFError:
break
if not s: continue
result = parser.parse(s)
print(result)
提前致谢!约翰
最佳答案
简单表达式的传统 Yacc 语法通常如下所示:
expression
: add_sub_expr
;
add_sub_expr
: mul_div_expr
| mul_div_expr '+' add_sub_expr
| mul_div_expr '-' add_sub_expr
;
mul_div_expr
: funcall_expr
| funcall_expr '*' mul_div_expr
| funcall_expr '/' mul_div_expr
;
funcall_expr
: prim_expr
| FUNCTION_NAME '(' expression_list ')'
;
prim_expr
: NUMBER
| '(' expression ')'
;
expression_list
: expression
| expression ',' expression_list
;
上述语法将使函数调用成为表达式的直接部分,其优先级高于乘法和除法。
对于FUNCTION_NAME
,您可以为每个函数各占一行(如果函数列表很短),也可以使用包含函数标识符列表的非终端,或者使用特殊终端(就像我的语法一样)或只是一个通用标识符终端。
关于python - Yacc - 具有函数支持的方程解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12227597/