一个真正有用的下一步将是建立一个解析树:
你会成为其中一个写的缀解析器。你可以通过编写一个简单的递归下降解析器,或者通过引入大枪和using a parser generator来做到这一点。在这两种情况下,它有助于建立一个正式的语法:
expression: additive
additive: multiplicative ([+-] multiplicative)*
multiplicative: primary ('*' primary)*
primary: variable
| number
| '(' expression ')'
请注意,此语法不处理2x
语法,但它应该是很容易添加。
注意在语法规则中巧妙地使用递归。 primary
只捕获变量,数字和括号表达式,并在运行时运行时停止。 multiplicative
解析由*
标志分隔的一个或多个primary
表达式,但当它运行到+
或-
标志时停止。 additive
解析由+
和-
分隔的一个或多个multiplicative
表达式,但在运行到)
时会停止。因此,递归方案决定了运算符的优先级。
这是不是太可怕难以实现predictive parser手,因为我已经做了以下(see full example at ideone.com):
function parse()
{
global $tokens;
reset($tokens);
$ret = parseExpression();
if (current($tokens) !== FALSE)
die("Stray token at end of expression\n");
return $ret;
}
function popToken()
{
global $tokens;
$ret = current($tokens);
if ($ret !== FALSE)
next($tokens);
return $ret;
}
function parseExpression()
{
return parseAdditive();
}
function parseAdditive()
{
global $tokens;
$expr = parseMultiplicative();
for (;;) {
$next = current($tokens);
if ($next !== FALSE && $next->type == "operator" &&
($next->op == "+" || $next->op == "-"))
{
next($tokens);
$left = $expr;
$right = parseMultiplicative();
$expr = mkOperatorExpr($next->op, $left, $right);
} else {
return $expr;
}
}
}
function parseMultiplicative()
{
global $tokens;
$expr = parsePrimary();
for (;;) {
$next = current($tokens);
if ($next !== FALSE && $next->type == "operator" &&
$next->op == "*")
{
next($tokens);
$left = $expr;
$right = parsePrimary();
$expr = mkOperatorExpr($next->op, $left, $right);
} else {
return $expr;
}
}
}
function parsePrimary()
{
$tok = popToken();
if ($tok === FALSE)
die("Unexpected end of token list\n");
if ($tok->type == "variable")
return mkVariableExpr($tok->name);
if ($tok->type == "number")
return mkNumberExpr($tok->value);
if ($tok->type == "operator" && $tok->op == "(") {
$ret = parseExpression();
$tok = popToken();
if ($tok->type == "operator" && $tok->op == ")")
return $ret;
else
die("Missing end parenthesis\n");
}
die("Unexpected $tok->type token\n");
}
好了,现在你有这样的可爱的解析树,甚至一个漂亮图片去与它。怎么办?你的目标(现在)可能是简单地合并条款以表格的结果:
n1*a + n2*b + n3*c + n4*d + ...
我会离开的那部分给你。有一个分析树应该让事情变得更直接。
你VAR令牌有一个相关的字符串。为什么您的NUMBER令牌没有关联号码? – 2011-03-23 22:54:07
根据您的约束条件,为什么不尝试构建[OOP解释器](http://sourcemaking.com/design_patterns/interpreter)?它应该比处理令牌更容易,并且树应该代表它自己。它应该相当容易处理 – ircmaxell 2011-03-23 23:03:22
@David Heffernan:PHP处理表达式和编程语言的一个优点是变量。你可以命名变量'$ operator'和'$ var',而不必担心与编程语言中的关键字冲突。 – 2011-03-23 23:04:16