一個真正有用的下一步將是建立一個解析樹:
你會成爲其中一個寫的綴解析器。你可以通過編寫一個簡單的遞歸下降解析器,或者通過引入大槍和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