context: // Generated by TinyPG v1.3 available at www.codeproject.com
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Xml.Serialization;
  using System.Globalization;
  
  namespace Calculator
  {
      #region ParseTreeEvaluator
      // rootlevel of the node tree
      [Serializable]
      public partial class ParseTreeEvaluator : ParseTree
      {
  
          //public Functions Functions { get; private set; }
          public Context Context { get; private set; }
  
          public ParseTreeEvaluator() : base()
          {
          }
  
          public ParseTreeEvaluator(Context context)
              : base()
          {
              Context = context;
          }
  
          /// <summary>
          /// required to override this function from base otherwise the parsetree will consist of incorrect types of nodes
          /// </summary>
          /// <param name="token"></param>
          /// <param name="text"></param>
          /// <returns></returns>
          public override ParseNode CreateNode(Token token, string text)
          {
              ParseTreeEvaluator node = new ParseTreeEvaluator();
              node.Token = token;
              node.text = text;
              node.Parent = this;
              return node;
          }
  
          protected override object EvaluateStart(ParseTree tree, params object[] paramlist)
          {
              return this.GetValue(tree, TokenType.Expression, 0);
          }
  
          protected override object EvaluateUnaryExpression(ParseTree tree, params object[] paramlist)
          {
              TokenType type = this.nodes[0].Token.Type;
              if (type == TokenType.PrimaryExpression)
                  return this.GetValue(tree, TokenType.PrimaryExpression, 0);
  
              if (type == TokenType.MINUS)
              {
                  object val = this.GetValue(tree, TokenType.UnaryExpression, 0);
                  if (val is double)
                      return -((double)val);
  
                  tree.Errors.Add(new ParseError("Illegal UnaryExpression format, cannot interpret minus " + val.ToString(), 1095, this));
                  return null;
              }
              else if (type == TokenType.PLUS)
              {
                  object val = this.GetValue(tree, TokenType.UnaryExpression, 0);
                  return val;
              }
              else if (type == TokenType.NOT)
              {
                  object val = this.GetValue(tree, TokenType.UnaryExpression, 0);
                  if (val is bool)
                      return !((bool)val);
  
                  tree.Errors.Add(new ParseError("Illegal UnaryExpression format, cannot interpret negate " + val.ToString(), 1098, this));
                  return null;
              }
  
              Errors.Add(new ParseError("Illegal UnaryExpression format", 1099, this));
              return null;
          
          }
  
          protected override object EvaluateParams(ParseTree tree, params object[] paramlist)
          {
              List<object> parameters = new List<object>();
              for (int i = 0; i < nodes.Count; i += 2)
              {
                  if (nodes[i].Token.Type == TokenType.Expression)
                  {
                      object val = nodes[i].Evaluate(tree, paramlist);
                      parameters.Add(val);
                  }
              }
              return parameters;
          }
  
          protected override object EvaluateFunction(ParseTree tree, params object[] paramlist)
          {
              ParseNode funcNode = this.nodes[0];
              ParseNode paramNode = this.nodes[2];
  
              ParseTreeEvaluator root = tree as ParseTreeEvaluator;
              if (root == null)
              {
                  tree.Errors.Add(new ParseError("Invalid parser used", 1040, this));
                  return null;
              }
              if (root.Context == null)
              {
                  tree.Errors.Add(new ParseError("No context defined", 1041, this));
                  return null;
              }
              if (root.Context.CurrentStackSize > 50)
              {
                  tree.Errors.Add(new ParseError("Stack overflow: " + funcNode.Token.Text + "()", 1046, this));
                  return null;
              }
              string key = funcNode.Token.Text.ToLowerInvariant();
              if (!root.Context.Functions.ContainsKey(key))
              {
                  tree.Errors.Add(new ParseError("Fuction not defined: " + funcNode.Token.Text + "()", 1042, this));
                  return null;
              }
  
              // retrieves the function from declared functions
              Function func = root.Context.Functions[key];
  
              // evaluate the function parameters
              object[] parameters = new object[0];
              if (paramNode.Token.Type == TokenType.Params)
                  parameters = (paramNode.Evaluate(tree, paramlist) as List<object>).ToArray();
              if (parameters.Length < func.MinParameters) 
              {
                  tree.Errors.Add(new ParseError("At least " + func.MinParameters.ToString() + " parameter(s) expected", 1043, this));
                  return null; // illegal number of parameters
              }
              else if (parameters.Length > func.MaxParameters)
              {
                  tree.Errors.Add(new ParseError("No more than " + func.MaxParameters.ToString() + " parameter(s) expected", 1044, this));
                  return null; // illegal number of parameters
              }
              
              return func.Evaluate(parameters, root);
          }
  
          protected override object EvaluateVariable(ParseTree tree, params object[] paramlist)
          {
              ParseTreeEvaluator root = tree as ParseTreeEvaluator;
              if (root == null)
              {
                  tree.Errors.Add(new ParseError("Invalid parser used", 1040, this));
                  return null;
              }
              if (root.Context == null)
              {
                  tree.Errors.Add(new ParseError("No context defined", 1041, this));
                  return null;
              }
  
              string key = this.nodes[0].Token.Text.ToLowerInvariant();
              // first check if the variable was declared in scope of a function
              if (root.Context.CurrentScope != null && root.Context.CurrentScope.ContainsKey(key))
                  return root.Context.CurrentScope[key];
              
              // if not in scope of a function
              // next check if the variable was declared as a global variable
              if (root.Context.Globals != null && root.Context.Globals.ContainsKey(key))
                  return root.Context.Globals[key];
  
              //variable not found
              tree.Errors.Add(new ParseError("Variable not defined: " + key, 1039, this));
              return null;
          }
  
          protected override object EvaluatePrimaryExpression(ParseTree tree, params object[] paramlist)
          {
              TokenType type = this.nodes[0].Token.Type;
              if (type == TokenType.Function)
                  return this.GetValue(tree, TokenType.Function, 0);
              else if (type == TokenType.Literal)
                  return this.GetValue(tree, TokenType.Literal, 0);
              else if (type == TokenType.ParenthesizedExpression)
                  return this.GetValue(tree, TokenType.ParenthesizedExpression, 0);
              else if (type == TokenType.Variable)
                  return this.GetValue(tree, TokenType.Variable, 0);
  
              tree.Errors.Add(new ParseError("Illegal EvaluatePrimaryExpression format", 1097, this));
              return null;
          }
  
          protected override object EvaluateParenthesizedExpression(ParseTree tree, params object[] paramlist)
          {
              return this.GetValue(tree, TokenType.Expression, 0);
          }
  
          protected override object EvaluatePowerExpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.UnaryExpression, 0);
  
              // IMPORTANT: scanning and calculating the power is done from Left to Right.
              // this is conform the Excel evaluation of power, but not conform strict mathematical guidelines
              // this means that a^b^c evaluates to (a^b)^c  (Excel uses the same kind of evaluation)
              // stricly mathematical speaking a^b^c should evaluate to a^(b^c) (therefore calculating the powers from Right to Left)
              for (int i = 1; i < nodes.Count; i += 2)
              {
                  Token token = nodes[i].Token;
                  object val = nodes[i + 1].Evaluate(tree, paramlist);
                  if (token.Type == TokenType.POWER)
                  {
                      if (
                          (Convert.ToInt64(result) != Convert.ToDouble(result))
                          ||
                          (Convert.ToInt64(val) != Convert.ToDouble(val))
                         )
                      {
                          return Math.Pow(Convert.ToDouble(result), Convert.ToDouble(val));
                      }
                      else // use integral maths instead to avoid silent overflow
                      {
                          long number = Convert.ToInt64(result);
                          long power = Convert.ToInt64(val);
                          long x = 1L;
                          for (long count = 0; count < power; count++)
                          {
                              x *= number;
                          }
                          result = x;
                      }
                  }
              }
  
              return result;
          }
  
          protected override object EvaluateMultiplicativeExpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.PowerExpression, 0);
              for (int i = 1; i < nodes.Count; i+=2 )
              {
                  Token token = nodes[i].Token;
                  object val = nodes[i+1].Evaluate(tree, paramlist);
                  if (token.Type == TokenType.ASTERIKS)
                      result = Convert.ToDouble(result) * Convert.ToDouble(val);
                  else if (token.Type == TokenType.SLASH)
                          result = Convert.ToDouble(result) / Convert.ToDouble(val);
                  else if (token.Type == TokenType.PERCENT)
                      result = Convert.ToDouble(result) % Convert.ToDouble(val);
              }
  
              return result;
          }
  
          protected override object EvaluateAdditiveExpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.MultiplicativeExpression, 0);
              for (int i = 1; i < nodes.Count; i += 2)
              {
                  Token token = nodes[i].Token;
                  object val = nodes[i + 1].Evaluate(tree, paramlist);
                  if (token.Type == TokenType.PLUS)
                      result = Convert.ToDouble(result) + Convert.ToDouble(val);
                  else if (token.Type == TokenType.MINUS)
                      result = Convert.ToDouble(result) - Convert.ToDouble(val);
              }
  
              return result;
          }
  
          protected override object EvaluateConcatEpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.AdditiveExpression, 0);
              for (int i = 1; i < nodes.Count; i += 2)
              {
                  Token token = nodes[i].Token;
                  object val = nodes[i + 1].Evaluate(tree, paramlist);
                  if (token.Type == TokenType.AMP)
                      result = Convert.ToString(result) + Convert.ToString(val);
              }
              return result;
          }
  
          protected override object EvaluateRelationalExpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.ConcatEpression, 0);
              for (int i = 1; i < nodes.Count; i += 2)
              {
                  Token token = nodes[i].Token;
                  object val = nodes[i + 1].Evaluate(tree, paramlist);
   
                  // compare as numbers
                  if (result is double && val is double)
                  {
                      if (token.Type == TokenType.LESSTHAN)
                          result = Convert.ToDouble(result) < Convert.ToDouble(val);
                      else if (token.Type == TokenType.LESSEQUAL)
                          result = Convert.ToDouble(result) <= Convert.ToDouble(val);
                      else if (token.Type == TokenType.GREATERTHAN)
                          result = Convert.ToDouble(result) > Convert.ToDouble(val);
                      else if (token.Type == TokenType.GREATEREQUAL)
                          result = Convert.ToDouble(result) >= Convert.ToDouble(val);
                  }
                  else // compare as strings
                  {
                      int comp = string.Compare(Convert.ToString(result), Convert.ToString(val));
                      if (token.Type == TokenType.LESSTHAN)
                          result = comp < 0;
                      else if (token.Type == TokenType.LESSEQUAL)
                          result = comp <= 0;
                      else if (token.Type == TokenType.GREATERTHAN)
                          result = comp > 0;
                      else if (token.Type == TokenType.GREATEREQUAL)
                          result = comp >= 0;
                  }
                  
              }
              return result;
          }
  
          protected override object EvaluateEqualityExpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.RelationalExpression, 0);
              for (int i = 1; i < nodes.Count; i += 2)
              {
                  Token token = nodes[i].Token;
                  object val = nodes[i + 1].Evaluate(tree, paramlist);
                  if (token.Type == TokenType.EQUAL)
                      result = object.Equals(result, val);
                  else if (token.Type == TokenType.NOTEQUAL)
                      result = !object.Equals(result, val);
              }
              return result;
          }
  
          protected override object EvaluateConditionalAndExpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.EqualityExpression, 0);
              for (int i = 1; i < nodes.Count; i += 2)
              {
                  Token token = nodes[i].Token;
                  object val = nodes[i + 1].Evaluate(tree, paramlist);
                  if (token.Type == TokenType.AMPAMP)
                      result = Convert.ToBoolean(result) && Convert.ToBoolean(val);
              }
              return result;
          }
  
          protected override object EvaluateConditionalOrExpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.ConditionalAndExpression, 0);
              for (int i = 1; i < nodes.Count; i += 2)
              {
                  Token token = nodes[i].Token;
                  object val = nodes[i + 1].Evaluate(tree, paramlist);
                  if (token.Type == TokenType.PIPEPIPE)
                      result = Convert.ToBoolean(result) || Convert.ToBoolean(val);
              }
              return result;
          }
  
          protected override object EvaluateAssignmentExpression(ParseTree tree, params object[] paramlist)
          {
              object result = this.GetValue(tree, TokenType.ConditionalOrExpression, 0);
              if (nodes.Count >= 5 && result is bool 
                  && nodes[1].Token.Type == TokenType.QUESTIONMARK
                  && nodes[3].Token.Type == TokenType.COLON)
              {
                  if (Convert.ToBoolean(result))
                      result = nodes[2].Evaluate(tree, paramlist); // return 1st argument
                  else
                      result = nodes[4].Evaluate(tree, paramlist); // return 2nd argumen
              }
              return result;
          }
  
          protected override object EvaluateExpression(ParseTree tree, params object[] paramlist)
          {
              // if only left hand side available, this is not an assignment, simple evaluate expression
              if (nodes.Count == 1)                 
                  return this.GetValue(tree, TokenType.AssignmentExpression, 0); // return the result
  
              if (nodes.Count != 3)
              {
                  tree.Errors.Add(new ParseError("Illegal EvaluateExpression format", 1092, this));
                  return null;
              }
  
              // ok, this is an assignment so declare the function or variable
                  // assignment only allowed to function or to a variable
                  ParseNode v = GetFunctionOrVariable(nodes[0]);
                  if (v == null)
                  {
                      tree.Errors.Add(new ParseError("Can only assign to function or variable", 1020, this));
                      return null;
                  }
  
                  ParseTreeEvaluator root = tree as ParseTreeEvaluator;
                  if (root == null)
                  {
                      tree.Errors.Add(new ParseError("Invalid parser used", 1040, this));
                      return null;
                  }
  
                  if (root.Context == null)
                  {
                      tree.Errors.Add(new ParseError("No context defined", 1041, this));
                      return null;
                  }
  
                  if (v.Token.Type == TokenType.VARIABLE)
                  {
  
                      // simply overwrite any previous defnition
                      string key = v.Token.Text.ToLowerInvariant();
                      root.Context.Globals[key] = this.GetValue(tree, TokenType.AssignmentExpression, 1);
                      return null;
                  }
                  else if (v.Token.Type == TokenType.Function)
                  {
  
                      string key = v.Nodes[0].Token.Text;
  
                      // function lookup is case insensitive
                      if (root.Context.Functions.ContainsKey(key.ToLower()))
                          if (!(root.Context.Functions[key.ToLower()] is DynamicFunction))
                          {
                              tree.Errors.Add(new ParseError("Built in functions cannot be overwritten", 1050, this));
                              return null;
                          }
  
                      // lets determine the input variables. 
                      // functions must be of te form f(x;y;z) = x+y*z;
                      // check the function parameters to be of type Variable, error otherwise
                      Variables vars = new Variables();
                      ParseNode paramsNode = v.Nodes[2];
                      if (paramsNode.Token.Type == TokenType.Params)
                      {   // function has parameters, so check if they are all variable declarations
                          for (int i = 0; i < paramsNode.Nodes.Count; i += 2)
                          {
                              ParseNode varNode = GetFunctionOrVariable(paramsNode.Nodes[i]);
                              if (varNode == null || varNode.Token.Type != TokenType.VARIABLE)
                              {
                                  tree.Errors.Add(new ParseError("Function declaration may only contain variables", 1051, this));
                                  return null;
                              }
                              // simply declare the variable, no need to evaluate the value of it at this point. 
                              // evaluation will be done when the function is executed
                              // note, variables are Case Sensitive (!)
                              vars.Add(varNode.Token.Text, null);
                          }
                      }
                      // we have all the info we need to know to declare the dynamicly defined function
                      // pass on nodes[2] which is the Right Hand Side (RHS) of the assignment
                      // nodes[2] will be evaluated at runtime when the function is executed.
                      DynamicFunction dynf = new DynamicFunction(key, nodes[2], vars, vars.Count, vars.Count);
                      root.Context.Functions[key.ToLower()] = dynf;
                      return null;
                  }
  
              
  
              // in an assignment, dont return any result (basically void)
              return null;
          }
  
          // helper function to find access the function or variable
          private ParseNode GetFunctionOrVariable(ParseNode n)
          {
              // found the right node, exit
              if (n.Token.Type == TokenType.Function || n.Token.Type == TokenType.VARIABLE)
                  return n;
  
              if (n.Nodes.Count == 1) // search lower branch (left side only, may not contain other node branches)
                  return GetFunctionOrVariable(n.Nodes[0]);
  
              // function or variable not found in branch
              return null;
          }
  
          protected override object EvaluateLiteral(ParseTree tree, params object[] paramlist)
          {
              TokenType type = this.nodes[0].Token.Type;
  
gt:             if (type == TokenType.StringLiteral)