我在java程序中使用调车场算法(https://en.wikipedia.org/wiki/Shunting-yard_algorithm)来创建计算器。我差不多做完了,但我还得实现一些功能。我遇到了一个问题:我想让计算器把x和y这样的变量放在一起自动相乘——例如:计算器把xy转换成x*y。同时,我想让计算器把(x)(y)转换成(x)*(y)和x(y)转换成x*(y)。我使用以下代码完成了所有这些操作:

infix = infix.replaceAll("([a-zA-Z])([a-zA-Z])", "$1*$2");
infix = infix.replaceAll("([a-zA-Z])\\(", "$1*(");
infix = infix.replaceAll("\\)\\(", ")*(");
infix = infix.replaceAll("\\)([a-zA-Z])", ")*$1");

(在我的计算器中,变量名总是单个字符。)
现在这很有效,但是当我实现函数时,这当然不起作用。它会把“s i n(1)”变成“s*i*n*(1)”。如何使此代码只对运算符而不是函数进行乘法转换?

最佳答案

预处理要解析的输入并不是实现所需内容的好方法文本替换无法知道解析算法知道什么,并且您也会丢失原始输入,这对于打印有用的错误消息很有用。
相反,你应该根据上下文来决定该做什么。将先前解析的标记的类型保留为输入开头的特殊类型。
如果前一个标记是值标记(数字、变量名或子拉伸的右大括号),而当前标记也是值标记,则会发出额外的乘法运算符。
同样的逻辑也可以用来决定减号是一元负数还是二元负数:如果减号是在值标记之后找到的,那么它就是减法,否则就是负数。
当然,将x(y)转换为x * (y)的想法会与函数调用语法冲突。

09-12 23:11