Index: branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs
===================================================================
--- branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 18159)
+++ branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs	(revision 18175)
@@ -158,4 +158,6 @@
           var newExponent = (NumberTreeNode)numberSy.CreateTreeNode();
           newExponent.Value = ((NumberTreeNode)newPower.GetSubtree(1)).Value - 1;
+          newPower.RemoveSubtree(1);
+          newPower.AddSubtree(newExponent);
           return Product(Product(CreateNumber(exponent.Value), newPower), Derive(f, variableName));
         } else throw new NotSupportedException("Cannot derive non-integer powers");
Index: branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
===================================================================
--- branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 18159)
+++ branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs	(revision 18175)
@@ -37,7 +37,12 @@
         var token = GetToken(node.Symbol);
         // operators
-        if (token == "+" || token == "-" || token == "OR" || token == "XOR" ||
-            token == "*" || token == "/" || token == "AND") {
-          strBuilder.Append("(");
+        if (token == "+" || token == "-" || token == "OR" || token == "XOR") {
+          var parenthesisRequired = false;
+          if (node.Parent != null && node.Parent.SubtreeCount > 1) {
+            var parentOp = GetToken(node.Parent.Symbol);
+            if (parentOp != "+" && parentOp != "-" && parentOp != "OR" && parentOp != "XOR")
+              parenthesisRequired = true;
+          }
+          if (parenthesisRequired) strBuilder.Append("(");
           FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString, parameters);
 
@@ -47,12 +52,25 @@
           }
 
-          strBuilder.Append(")");
+          if (parenthesisRequired) strBuilder.Append(")");
+        } else if (token == "*" || token == "/" || token == "AND") {
+          FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString, parameters);
+
+          foreach (var subtree in node.Subtrees.Skip(1)) {
+            strBuilder.Append(" ").Append(token).Append(" ");
+            // a / b * c => a / (b * C)
+            if (subtree.SubtreeCount > 1 && token == "/" && GetToken(subtree.Symbol) == "*") {
+              strBuilder.Append("(");
+              FormatRecursively(subtree, strBuilder, numberFormat, formatString, parameters);
+              strBuilder.Append(")");
+            } else {
+              FormatRecursively(subtree, strBuilder, numberFormat, formatString, parameters);
+            }
+          }
         } else if (token == "^") {
           // handle integer powers directly
-          strBuilder.Append("(");
           FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString, parameters);
 
           var power = node.GetSubtree(1);
-          if(power is INumericTreeNode numNode && Math.Truncate(numNode.Value) == numNode.Value) {
+          if (power is INumericTreeNode numNode && Math.Truncate(numNode.Value) == numNode.Value) {
             strBuilder.Append(" ").Append(token).Append(" ").Append(numNode.Value.ToString(formatString, numberFormat));
           } else {
@@ -60,6 +78,4 @@
             FormatRecursively(power, strBuilder, numberFormat, formatString, parameters);
           }
-
-          strBuilder.Append(")");
         } else {
           // function with multiple arguments
@@ -76,7 +92,6 @@
         var token = GetToken(node.Symbol);
         if (token == "-" || token == "NOT") {
-          strBuilder.Append("(").Append(token).Append("(");
-          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString, parameters);
-          strBuilder.Append("))");
+          strBuilder.Append(token);
+          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString, parameters);
         } else if (token == "/") {
           strBuilder.Append("1/");
@@ -95,5 +110,4 @@
           var varNode = node as LaggedVariableTreeNode;
           if (!varNode.Weight.IsAlmost(1.0)) {
-            strBuilder.Append("(");
             AppendNumber(strBuilder, parameters, varNode.Weight, formatString, numberFormat);
             strBuilder.Append("*");
@@ -105,16 +119,11 @@
                     .AppendFormat(numberFormat, "{0}", varNode.Lag)
                     .Append(")");
-          if (!varNode.Weight.IsAlmost(1.0)) strBuilder.Append(")");
         } else if (node.Symbol is Variable) {
           var varNode = node as VariableTreeNode;
           if (!varNode.Weight.IsAlmost(1.0)) {
-            strBuilder.Append("(");
             AppendNumber(strBuilder, parameters, varNode.Weight, formatString, numberFormat);
             strBuilder.Append("*");
           }
-
           AppendVariableName(strBuilder, varNode.VariableName);
-
-          if (!varNode.Weight.IsAlmost(1.0)) strBuilder.Append(")");
         } else if (node.Symbol is FactorVariable) {
           var factorNode = node as FactorVariableTreeNode;
@@ -130,20 +139,14 @@
           var factorNode = node as BinaryFactorVariableTreeNode;
           if (!factorNode.Weight.IsAlmost(1.0)) {
-            strBuilder.Append("(");
             AppendNumber(strBuilder, parameters, factorNode.Weight, formatString, numberFormat);
-
             strBuilder.Append("*");
           }
-
           AppendVariableName(strBuilder, factorNode.VariableName);
           strBuilder.Append(" = ");
           AppendVariableName(strBuilder, factorNode.VariableValue);
-
-          if (!factorNode.Weight.IsAlmost(1.0)) strBuilder.Append(")");
         } else if (node is INumericTreeNode numNode) {
           if (parameters == null && numNode.Value < 0) {
             // negative value
-            strBuilder.Append("(").Append(numNode.Value.ToString(formatString, numberFormat))
-                      .Append(")"); 
+            strBuilder.Append(numNode.Value.ToString(formatString, numberFormat));
           } else {
             AppendNumber(strBuilder, parameters, numNode.Value, formatString, numberFormat);
Index: branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
===================================================================
--- branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 18159)
+++ branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs	(revision 18175)
@@ -40,5 +40,5 @@
   /// 
   /// S             = Expr EOF
-  /// Expr          = ['-' | '+'] Term { '+' Term | '-' Term }
+  /// Expr          = Term { '+' Term | '-' Term }
   /// Term          = Fact { '*' Fact | '/' Fact }
   /// Fact          = SimpleFact [ '^' SimpleFact ]
@@ -49,7 +49,8 @@
   ///                 | VarExpr
   ///                 | number
+  ///                 | ['+' | '-'] SimpleFact
   /// ArgList       = Expr { ',' Expr }
   /// VarExpr       = varId OptFactorPart
-  /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ]
+  /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ]  number {',' ['+' | '-' ]  number } ']' ) ]
   /// varId         =  ident | ' ident ' | " ident "
   /// varVal        =  ident | ' ident ' | " ident "
@@ -83,5 +84,5 @@
 
     private Number number = new Number();
-    private Constant constant = new Constant();
+    private Constant minusOne = new Constant() { Value = -1 };
     private Variable variable = new Variable();
     private BinaryFactorVariable binaryFactorVar = new BinaryFactorVariable();
@@ -162,5 +163,5 @@
       int pos = 0;
       while (true) {
-        while (pos < str.Length && Char.IsWhiteSpace(str[pos])) pos++;
+        while (pos < str.Length && char.IsWhiteSpace(str[pos])) pos++;
         if (pos >= str.Length) {
           yield return new Token { TokenType = TokenType.End, strVal = "" };
@@ -168,5 +169,5 @@
         }
         if (char.IsDigit(str[pos])) {
-          // read number (=> read until white space or operator or comma)
+          // read number (=> read until white space or other symbol)
           var sb = new StringBuilder();
           sb.Append(str[pos]);
@@ -269,8 +270,8 @@
         } else if (str[pos] == '<') {
           pos++;
-          yield return new Token {TokenType = TokenType.LeftAngleBracket, strVal = "<"};
+          yield return new Token { TokenType = TokenType.LeftAngleBracket, strVal = "<" };
         } else if (str[pos] == '>') {
           pos++;
-          yield return new Token {TokenType = TokenType.RightAngleBracket, strVal = ">"};
+          yield return new Token { TokenType = TokenType.RightAngleBracket, strVal = ">" };
         } else {
           throw new ArgumentException("Invalid character: " + str[pos]);
@@ -289,32 +290,31 @@
     }
 
-    /// Expr          = ['-' | '+'] Term { '+' Term | '-' Term }
+    /// Expr          = Term { '+' Term | '-' Term }
     private ISymbolicExpressionTreeNode ParseExpr(Queue<Token> tokens) {
+      // build tree from bottom to top and left to right
+      // a + b - c => ((a + b) - c)
+      // a - b - c => ((a - b) - c)
+      // and then flatten as far as possible
+      var left = ParseTerm(tokens);
+
       var next = tokens.Peek();
-      var posTerms = new List<ISymbolicExpressionTreeNode>();
-      var negTerms = new List<ISymbolicExpressionTreeNode>();
-      bool negateFirstTerm = false;
-      if (next.TokenType == TokenType.Operator && (next.strVal == "+" || next.strVal == "-")) {
-        tokens.Dequeue();
-        if (next.strVal == "-")
-          negateFirstTerm = true;
-      }
-      var t = ParseTerm(tokens);
-      if (negateFirstTerm) negTerms.Add(t);
-      else posTerms.Add(t);
-
-      next = tokens.Peek();
       while (next.strVal == "+" || next.strVal == "-") {
         switch (next.strVal) {
           case "+": {
               tokens.Dequeue();
-              var term = ParseTerm(tokens);
-              posTerms.Add(term);
+              var right = ParseTerm(tokens);
+              var op = GetSymbol("+").CreateTreeNode();
+              op.AddSubtree(left);
+              op.AddSubtree(right);
+              left = op;
               break;
             }
           case "-": {
               tokens.Dequeue();
-              var term = ParseTerm(tokens);
-              negTerms.Add(term);
+              var right = ParseTerm(tokens);
+              var op = GetSymbol("-").CreateTreeNode();
+              op.AddSubtree(left);
+              op.AddSubtree(right);
+              left = op;
               break;
             }
@@ -323,26 +323,6 @@
       }
 
-      var sum = GetSymbol("+").CreateTreeNode();
-      foreach (var posTerm in posTerms) sum.AddSubtree(posTerm);
-      if (negTerms.Any()) {
-        if (negTerms.Count == 1) {
-          var sub = GetSymbol("-").CreateTreeNode();
-          sub.AddSubtree(negTerms.Single());
-          sum.AddSubtree(sub);
-        } else {
-          var sumNeg = GetSymbol("+").CreateTreeNode();
-          foreach (var negTerm in negTerms) sumNeg.AddSubtree(negTerm);
-
-          var constNode = (NumberTreeNode)number.CreateTreeNode();
-          constNode.Value = -1.0;
-          var prod = GetSymbol("*").CreateTreeNode();
-          prod.AddSubtree(constNode);
-          prod.AddSubtree(sumNeg);
-
-          sum.AddSubtree(prod);
-        }
-      }
-      if (sum.SubtreeCount == 1) return sum.Subtrees.First();
-      else return sum;
+      FoldLeftRecursive(left);
+      return left;
     }
 
@@ -355,7 +335,10 @@
     /// Term          = Fact { '*' Fact | '/' Fact }
     private ISymbolicExpressionTreeNode ParseTerm(Queue<Token> tokens) {
-      var factors = new List<ISymbolicExpressionTreeNode>();
-      var firstFactor = ParseFact(tokens);
-      factors.Add(firstFactor);
+      // build tree from bottom to top and left to right
+      // a / b * c => ((a / b) * c)
+      // a / b / c => ((a / b) / c)
+      // and then flatten as far as possible
+
+      var left = ParseFact(tokens);
 
       var next = tokens.Peek();
@@ -364,14 +347,19 @@
           case "*": {
               tokens.Dequeue();
-              var fact = ParseFact(tokens);
-              factors.Add(fact);
+              var right = ParseFact(tokens);
+
+              var op = GetSymbol("*").CreateTreeNode();
+              op.AddSubtree(left);
+              op.AddSubtree(right);
+              left = op;
               break;
             }
           case "/": {
               tokens.Dequeue();
-              var invFact = ParseFact(tokens);
-              var divNode = GetSymbol("/").CreateTreeNode(); // 1/x
-              divNode.AddSubtree(invFact);
-              factors.Add(divNode);
+              var right = ParseFact(tokens);
+              var op = GetSymbol("/").CreateTreeNode();
+              op.AddSubtree(left);
+              op.AddSubtree(right);
+              left = op;
               break;
             }
@@ -380,9 +368,22 @@
         next = tokens.Peek();
       }
-      if (factors.Count == 1) return factors.First();
-      else {
-        var prod = GetSymbol("*").CreateTreeNode();
-        foreach (var f in factors) prod.AddSubtree(f);
-        return prod;
+      // remove all nodes where the child op is the same as the parent op
+      // (a * b) * c) => (a * b * c)
+      // (a / b) / c) => (a / b / c)
+
+      FoldLeftRecursive(left);
+      return left;
+    }
+
+    private void FoldLeftRecursive(ISymbolicExpressionTreeNode parent) {
+      if (parent.SubtreeCount > 1) {
+        var child = parent.GetSubtree(0);
+        FoldLeftRecursive(child);
+        if (parent.Symbol == child.Symbol && IsAssociative(parent.Symbol)) {
+          parent.RemoveSubtree(0);
+          for (int i = 0; i < child.SubtreeCount; i++) {
+            parent.InsertSubtree(i, child.GetSubtree(i));
+          }
+        }
       }
     }
@@ -409,5 +410,7 @@
     ///                 | funcId '(' ArgList ')
     ///                 | VarExpr
+    ///                 | '<' 'num' [ '=' [ '+' | '-' ] number ] '>' 
     ///                 | number
+    ///                 | ['+' | '-' ] SimpleFact
     /// ArgList       = Expr { ',' Expr }
     /// VarExpr       = varId OptFactorPart
@@ -433,137 +436,187 @@
         if (tokens.Peek().TokenType == TokenType.LeftPar) {
           // function identifier or LAG
-          var funcId = idTok.strVal.ToUpperInvariant();
-
-          var funcNode = GetSymbol(funcId).CreateTreeNode();
-          var lPar = tokens.Dequeue();
-          if (lPar.TokenType != TokenType.LeftPar)
-            throw new ArgumentException("expected (");
-
-          // handle 'lag' specifically
-          if (funcNode.Symbol is LaggedVariable) {
-            var varId = tokens.Dequeue();
-            if (varId.TokenType != TokenType.Identifier) throw new ArgumentException("Identifier expected. Format for lagged variables: \"lag(x, -1)\"");
-            var comma = tokens.Dequeue();
-            if (comma.TokenType != TokenType.Comma) throw new ArgumentException("',' expected, Format for lagged variables: \"lag(x, -1)\"");
-            double sign = 1.0;
-            if (tokens.Peek().strVal == "+" || tokens.Peek().strVal == "-") {
-              // read sign
-              var signTok = tokens.Dequeue();
-              if (signTok.strVal == "-") sign = -1.0;
-            }
-            var lagToken = tokens.Dequeue();
-            if (lagToken.TokenType != TokenType.Number) throw new ArgumentException("Number expected, Format for lagged variables: \"lag(x, -1)\"");
-            if (!lagToken.doubleVal.IsAlmost(Math.Round(lagToken.doubleVal)))
-              throw new ArgumentException("Time lags must be integer values");
-            var laggedVarNode = funcNode as LaggedVariableTreeNode;
-            laggedVarNode.VariableName = varId.strVal;
-            laggedVarNode.Lag = (int)Math.Round(sign * lagToken.doubleVal);
-            laggedVarNode.Weight = 1.0;
+          return ParseFunctionOrLaggedVariable(tokens, idTok);
+        } else {
+          return ParseVariable(tokens, idTok);
+        }
+      } else if (next.TokenType == TokenType.LeftAngleBracket) {
+        // '<' 'num' [ '=' ['+'|'-'] number ] '>'
+        return ParseNumber(tokens);
+      } else if (next.TokenType == TokenType.Operator && (next.strVal == "-" || next.strVal == "+")) {
+        // ['+' | '-' ] SimpleFact
+        if (tokens.Dequeue().strVal == "-") {
+          var arg = ParseSimpleFact(tokens);
+          if (arg is NumberTreeNode numNode) {
+            numNode.Value *= -1;
+            return numNode;
+          } else if (arg is ConstantTreeNode constNode) {
+            var constSy = new Constant { Value = -constNode.Value };
+            return constSy.CreateTreeNode();
+          } else if (arg is VariableTreeNode varNode) {
+            varNode.Weight *= -1;
+            return varNode;
           } else {
-            // functions
-            var args = ParseArgList(tokens);
-            // check number of arguments
-            if (funcNode.Symbol.MinimumArity > args.Length || funcNode.Symbol.MaximumArity < args.Length) {
-              throw new ArgumentException(string.Format("Symbol {0} requires between {1} and  {2} arguments.", funcId,
-                funcNode.Symbol.MinimumArity, funcNode.Symbol.MaximumArity));
-            }
-            foreach (var arg in args) funcNode.AddSubtree(arg);
+            var mul = GetSymbol("*").CreateTreeNode();
+            var neg = minusOne.CreateTreeNode();
+            mul.AddSubtree(neg);
+            mul.AddSubtree(arg);
+            return mul;
           }
-
-          var rPar = tokens.Dequeue();
-          if (rPar.TokenType != TokenType.RightPar)
-            throw new ArgumentException("expected )");
-
-
-          return funcNode;
         } else {
-          // variable
-          if (tokens.Peek().TokenType == TokenType.Eq) {
-            // binary factor
-            tokens.Dequeue(); // skip Eq
-            var valTok = tokens.Dequeue();
-            if (valTok.TokenType != TokenType.Identifier) throw new ArgumentException("expected identifier");
-            var binFactorNode = (BinaryFactorVariableTreeNode)binaryFactorVar.CreateTreeNode();
-            binFactorNode.Weight = 1.0;
-            binFactorNode.VariableName = idTok.strVal;
-            binFactorNode.VariableValue = valTok.strVal;
-            return binFactorNode;
-          } else if (tokens.Peek().TokenType == TokenType.LeftBracket) {
-            // factor variable
-            var factorVariableNode = (FactorVariableTreeNode)factorVar.CreateTreeNode();
-            factorVariableNode.VariableName = idTok.strVal;
-
-            tokens.Dequeue(); // skip [
-            var weights = new List<double>();
-            // at least one weight is necessary
-            var sign = 1.0;
-            if (tokens.Peek().TokenType == TokenType.Operator) {
-              var opToken = tokens.Dequeue();
-              if (opToken.strVal == "+") sign = 1.0;
-              else if (opToken.strVal == "-") sign = -1.0;
-              else throw new ArgumentException();
-            }
-            if (tokens.Peek().TokenType != TokenType.Number) throw new ArgumentException("number expected");
-            var weightTok = tokens.Dequeue();
-            weights.Add(sign * weightTok.doubleVal);
-            while (tokens.Peek().TokenType == TokenType.Comma) {
-              // skip comma
-              tokens.Dequeue();
-              if (tokens.Peek().TokenType == TokenType.Operator) {
-                var opToken = tokens.Dequeue();
-                if (opToken.strVal == "+") sign = 1.0;
-                else if (opToken.strVal == "-") sign = -1.0;
-                else throw new ArgumentException();
-              }
-              weightTok = tokens.Dequeue();
-              if (weightTok.TokenType != TokenType.Number) throw new ArgumentException("number expected");
-              weights.Add(sign * weightTok.doubleVal);
-            }
-            var rightBracketToken = tokens.Dequeue();
-            if (rightBracketToken.TokenType != TokenType.RightBracket) throw new ArgumentException("closing bracket ] expected");
-            factorVariableNode.Weights = weights.ToArray();
-            return factorVariableNode;
-          } else {
-            // variable
-            var varNode = (VariableTreeNode)variable.CreateTreeNode();
-            varNode.Weight = 1.0;
-            varNode.VariableName = idTok.strVal;
-            return varNode;
-          }
-        }
-      } else if (next.TokenType == TokenType.LeftAngleBracket) {
-        Token numberTok = null;
-        var leftAngleBracket = tokens.Dequeue();
-        if (leftAngleBracket.TokenType != TokenType.LeftAngleBracket)
-          throw new ArgumentException("opening bracket < expected");
-
-        var idTok = tokens.Dequeue();
-        if (idTok.TokenType != TokenType.Identifier || idTok.strVal.ToLower() != "num")
-          throw new ArgumentException("string 'num' expected");
-
-        if (tokens.Peek().TokenType == TokenType.Eq) {
-          var equalTok = tokens.Dequeue();
-          if (tokens.Peek().TokenType != TokenType.Number)
-            throw new ArgumentException("No value for number specified.");
-
-          numberTok = tokens.Dequeue();
-        }
-
-        var rightAngleBracket = tokens.Dequeue();
-        if (rightAngleBracket.TokenType != TokenType.RightAngleBracket)
-          throw new ArgumentException("closing bracket > expected");
-        var numNode = (NumberTreeNode)number.CreateTreeNode();
-        if (numberTok != null) numNode.Value = numberTok.doubleVal;
-        return numNode;
+          return ParseSimpleFact(tokens);
+        }
       } else if (next.TokenType == TokenType.Number) {
+        // number
         var numTok = tokens.Dequeue();
-        var constSy = new Constant {Value = numTok.doubleVal};
+        var constSy = new Constant { Value = numTok.doubleVal };
         return constSy.CreateTreeNode();
-        /*var constNode = (ConstantTreeNode)constant.CreateTreeNode();
-        constNode.Value = numTok.doubleVal;
-        return constNode;*/
       } else {
         throw new ArgumentException(string.Format("unexpected token in expression {0}", next.strVal));
       }
+    }
+
+    private ISymbolicExpressionTreeNode ParseNumber(Queue<Token> tokens) {
+      // we distinguish parameters and constants. The values of parameters can be changed.
+      // a parameter is written as '<' 'num' [ '=' ['+'|'-'] number ] '>' with an optional initialization 
+      Token numberTok = null;
+      var leftAngleBracket = tokens.Dequeue();
+      if (leftAngleBracket.TokenType != TokenType.LeftAngleBracket)
+        throw new ArgumentException("opening bracket < expected");
+
+      var idTok = tokens.Dequeue();
+      if (idTok.TokenType != TokenType.Identifier || idTok.strVal.ToLower() != "num")
+        throw new ArgumentException("string 'num' expected");
+
+      var numNode = (NumberTreeNode)number.CreateTreeNode();
+
+      if (tokens.Peek().TokenType == TokenType.Eq) {
+        tokens.Dequeue(); // skip "="
+        var next = tokens.Peek();
+        if (next.strVal != "+" && next.strVal != "-" && next.TokenType != TokenType.Number)
+          throw new ArgumentException("Expected '+', '-' or number.");
+
+        var sign = 1.0;
+        if (next.strVal == "+" || next.strVal == "-") {
+          if (tokens.Dequeue().strVal == "-") sign = -1.0;
+        }
+        if (tokens.Peek().TokenType != TokenType.Number) {
+          throw new ArgumentException("Expected number.");
+        }
+        numberTok = tokens.Dequeue();
+        numNode.Value = sign * numberTok.doubleVal;
+      }
+
+      var rightAngleBracket = tokens.Dequeue();
+      if (rightAngleBracket.TokenType != TokenType.RightAngleBracket)
+        throw new ArgumentException("closing bracket > expected");
+
+      return numNode;
+    }
+
+    private ISymbolicExpressionTreeNode ParseVariable(Queue<Token> tokens, Token idTok) {
+      // variable
+      if (tokens.Peek().TokenType == TokenType.Eq) {
+        // binary factor
+        tokens.Dequeue(); // skip Eq
+        var valTok = tokens.Dequeue();
+        if (valTok.TokenType != TokenType.Identifier) throw new ArgumentException("expected identifier");
+        var binFactorNode = (BinaryFactorVariableTreeNode)binaryFactorVar.CreateTreeNode();
+        binFactorNode.Weight = 1.0;
+        binFactorNode.VariableName = idTok.strVal;
+        binFactorNode.VariableValue = valTok.strVal;
+        return binFactorNode;
+      } else if (tokens.Peek().TokenType == TokenType.LeftBracket) {
+        // factor variable
+        var factorVariableNode = (FactorVariableTreeNode)factorVar.CreateTreeNode();
+        factorVariableNode.VariableName = idTok.strVal;
+
+        tokens.Dequeue(); // skip [
+        var weights = new List<double>();
+        // at least one weight is necessary
+        var sign = 1.0;
+        if (tokens.Peek().TokenType == TokenType.Operator) {
+          var opToken = tokens.Dequeue();
+          if (opToken.strVal == "+") sign = 1.0;
+          else if (opToken.strVal == "-") sign = -1.0;
+          else throw new ArgumentException();
+        }
+        if (tokens.Peek().TokenType != TokenType.Number) throw new ArgumentException("number expected");
+        var weightTok = tokens.Dequeue();
+        weights.Add(sign * weightTok.doubleVal);
+        while (tokens.Peek().TokenType == TokenType.Comma) {
+          // skip comma
+          tokens.Dequeue();
+          if (tokens.Peek().TokenType == TokenType.Operator) {
+            var opToken = tokens.Dequeue();
+            if (opToken.strVal == "+") sign = 1.0;
+            else if (opToken.strVal == "-") sign = -1.0;
+            else throw new ArgumentException();
+          }
+          weightTok = tokens.Dequeue();
+          if (weightTok.TokenType != TokenType.Number) throw new ArgumentException("number expected");
+          weights.Add(sign * weightTok.doubleVal);
+        }
+        var rightBracketToken = tokens.Dequeue();
+        if (rightBracketToken.TokenType != TokenType.RightBracket) throw new ArgumentException("closing bracket ] expected");
+        factorVariableNode.Weights = weights.ToArray();
+        return factorVariableNode;
+      } else {
+        // variable
+        var varNode = (VariableTreeNode)variable.CreateTreeNode();
+        varNode.Weight = 1.0;
+        varNode.VariableName = idTok.strVal;
+        return varNode;
+      }
+    }
+
+    private ISymbolicExpressionTreeNode ParseFunctionOrLaggedVariable(Queue<Token> tokens, Token idTok) {
+      var funcId = idTok.strVal.ToUpperInvariant();
+
+      var funcNode = GetSymbol(funcId).CreateTreeNode();
+      var lPar = tokens.Dequeue();
+      if (lPar.TokenType != TokenType.LeftPar)
+        throw new ArgumentException("expected (");
+
+      // handle 'lag' specifically
+      if (funcNode.Symbol is LaggedVariable) {
+        ParseLaggedVariable(tokens, funcNode);
+      } else {
+        // functions
+        var args = ParseArgList(tokens);
+        // check number of arguments
+        if (funcNode.Symbol.MinimumArity > args.Length || funcNode.Symbol.MaximumArity < args.Length) {
+          throw new ArgumentException(string.Format("Symbol {0} requires between {1} and  {2} arguments.", funcId,
+            funcNode.Symbol.MinimumArity, funcNode.Symbol.MaximumArity));
+        }
+        foreach (var arg in args) funcNode.AddSubtree(arg);
+      }
+
+      var rPar = tokens.Dequeue();
+      if (rPar.TokenType != TokenType.RightPar)
+        throw new ArgumentException("expected )");
+
+
+      return funcNode;
+    }
+
+    private static void ParseLaggedVariable(Queue<Token> tokens, ISymbolicExpressionTreeNode funcNode) {
+      var varId = tokens.Dequeue();
+      if (varId.TokenType != TokenType.Identifier) throw new ArgumentException("Identifier expected. Format for lagged variables: \"lag(x, -1)\"");
+      var comma = tokens.Dequeue();
+      if (comma.TokenType != TokenType.Comma) throw new ArgumentException("',' expected, Format for lagged variables: \"lag(x, -1)\"");
+      double sign = 1.0;
+      if (tokens.Peek().strVal == "+" || tokens.Peek().strVal == "-") {
+        // read sign
+        var signTok = tokens.Dequeue();
+        if (signTok.strVal == "-") sign = -1.0;
+      }
+      var lagToken = tokens.Dequeue();
+      if (lagToken.TokenType != TokenType.Number) throw new ArgumentException("Number expected, Format for lagged variables: \"lag(x, -1)\"");
+      if (!lagToken.doubleVal.IsAlmost(Math.Round(lagToken.doubleVal)))
+        throw new ArgumentException("Time lags must be integer values");
+      var laggedVarNode = funcNode as LaggedVariableTreeNode;
+      laggedVarNode.VariableName = varId.strVal;
+      laggedVarNode.Lag = (int)Math.Round(sign * lagToken.doubleVal);
+      laggedVarNode.Weight = 1.0;
     }
 
@@ -579,4 +632,10 @@
       return exprList.ToArray();
     }
+
+    private bool IsAssociative(ISymbol sy) {
+      return sy == GetSymbol("+") || sy == GetSymbol("-") ||
+             sy == GetSymbol("*") || sy == GetSymbol("/") ||
+             sy == GetSymbol("AND") || sy == GetSymbol("OR") || sy == GetSymbol("XOR");
+    }
   }
 }
