Also mit EBNF und rekursiver Programmierung ist das eigentlich gar kein Problem.
Code:
<Ausdruck> ::= <Term> { [ "+" | "-" ] <Term> }*
<Term> ::= <Faktor> { [ "*" | "/" ] <Faktor> }*
<Faktor> ::= <Zahl> | <Variable> | <Funktion> | "(" <Ausdruck> ")"
<Funktion> ::= <Name> "(" <ParameterListe> ")"
[ a | b ] => a oder b
{ a }* => 0 oder n Mal a
Damit hat man durch die Aufteilung von +|- und *|/ in zwei Bereiche neben der Klammersetzung auch gleich die Punkt-vor-Strich-Regel erschlagen.
Hier mal ein Ausschnitt dafür
Delphi-Quellcode:
function Term: IExprNode;
var
op: IToken;
fak: IExprNode;
begin
Result := Faktor; // <Faktor>
while Match([tkMultiply, tkDivide]) do // { [ "*" | "/" ] <Faktor> }*
begin
op := Look; // aktueller Token nach op
Next; // nächster Token
fak := Faktor;
Result := TExprNodeBinOp.Create(op, Result, fak); // Baum-Knoten erzeugen und zurückliefern
end;
end;
Man kann sich so einen Baum aufbauen, den man danach nur noch durchlaufen muss und die werte Ausrechnet. Alternativ kann man sich das Aufbauen des Baums sparen und gleich mit einer Variable, die man jeder Funktion als var-Parameter mitgibt, rechnen.