public override PerCederberg.Grammatica.Runtime.Node ExitIndexExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			var childValues = this.GetChildValues(node);
			var args = new ArgumentList(childValues);
			var e = new IndexerElement(args);
			node.AddValue(e);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitOr(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(AndOrOperation.Or);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitNot(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(string.Empty);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitArrayBraces(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue("[]");
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitLt(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(LogicalCompareOperation.LessThan);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitDatetime(PerCederberg.Grammatica.Runtime.Token node)
		{
            var context = (ExpressionContext)MyServices.GetService(typeof(ExpressionContext));
			string image = node.Image.Substring(1, node.Image.Length - 2);
			var element = new DateTimeLiteralElement(image, context);
			node.AddValue(element);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitIdentifier(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(node.Image);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitCastTypeExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			var childValues = this.GetChildValues(node);
			var parts = new List<string>();

			foreach (string part in childValues) {
				parts.Add(part);
			}

			bool isArray = false;

			if (parts[parts.Count - 1] == "[]") {
				isArray = true;
				parts.RemoveAt(parts.Count - 1);
			}

			node.AddValue(parts.ToArray());
			node.AddValue(isArray);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitFieldPropertyExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			string name = (string)node.GetChildAt(0).GetValue(0);
			IdentifierElement elem = new IdentifierElement(name);
			node.AddValue(elem);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitInListTargetExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			IList childValues = this.GetChildValues(node);
			node.AddValue(childValues);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitCastExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			var childValues = this.GetChildValues(node);
			string[] destTypeParts = (string[])childValues[1];
			bool isArray = (bool)childValues[2];
            var op = new CastElement((ExpressionElement)childValues[0], destTypeParts, isArray, MyServices);
			node.AddValue(op);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitInExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			var childValues = this.GetChildValues(node);

			if (childValues.Count == 1) {
				this.AddFirstChildValue(node);
				return node;
			}

            var operand = (ExpressionElement)childValues[0];
			childValues.RemoveAt(0);

			object second = childValues[0];
			InElement op = null;

			if ((second) is IList) {
				op = new InElement(operand, (IList)second);
			} else {
				var il = new InvocationListElement(childValues, MyServices);
				op = new InElement(operand, il);
			}

			node.AddValue(op);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitIfExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			var childValues = this.GetChildValues(node);
            var op = new ConditionalElement((ExpressionElement)childValues[0], (ExpressionElement)childValues[1], (ExpressionElement)childValues[2]);
			node.AddValue(op);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitMemberAccessExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			node.AddValue(node.GetChildAt(1).GetValue(0));
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitStringLiteral(PerCederberg.Grammatica.Runtime.Token node)
		{
			string s = this.DoEscapes(node.Image);
			var element = new StringLiteralElement(s);
			node.AddValue(element);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitFunctionCallExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			var childValues = this.GetChildValues(node);
			string name = (string)childValues[0];
			childValues.RemoveAt(0);
			var args = new ArgumentList(childValues);
			var funcCall = new FunctionCallElement(name, args);
			node.AddValue(funcCall);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitCharLiteral(PerCederberg.Grammatica.Runtime.Token node)
		{
			string s = this.DoEscapes(node.Image);
			node.AddValue(new CharLiteralElement(s[0]));
			return node;
		}
		private void AddFirstChildValue(PerCederberg.Grammatica.Runtime.Production node)
		{
			node.AddValue(this.GetChildAt(node, 0).Values[0]);
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitTimespan(PerCederberg.Grammatica.Runtime.Token node)
		{
			string image = node.Image.Substring(2, node.Image.Length - 3);
			var element = new TimeSpanLiteralElement(image);
			node.AddValue(element);
			return node;
		}
		private void AddUnaryOp(PerCederberg.Grammatica.Runtime.Production node, Type elementType)
		{
			var childValues = this.GetChildValues(node);

			if (childValues.Count == 2) {
                var element = (UnaryElement)Activator.CreateInstance(elementType);
				element.SetChild((ExpressionElement)childValues[1]);
				node.AddValue(element);
			} else {
				node.AddValue(childValues[0]);
			}
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitNullLiteral(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(new NullLiteralElement());
			return node;
		}
		private void AddBinaryOp(PerCederberg.Grammatica.Runtime.Production node, Type elementType)
		{
			IList childValues = this.GetChildValues(node);

			if (childValues.Count > 1) {
				BinaryExpressionElement e = BinaryExpressionElement.CreateElement(childValues, elementType);
				node.AddValue(e);
			} else if (childValues.Count == 1) {
				node.AddValue(childValues[0]);
			} else {
				Debug.Assert(false, "wrong number of chilren");
			}
		}
        public override PerCederberg.Grammatica.Runtime.Node ExitPower(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(BinaryArithmeticOperation.Power);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitReal(PerCederberg.Grammatica.Runtime.Token node)
		{
			string image = node.Image;
			var element = RealLiteralElement.Create(image, MyServices);

			node.AddValue(element);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitGte(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(LogicalCompareOperation.GreaterThanOrEqual);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitHexLiteral(PerCederberg.Grammatica.Runtime.Token node)
		{
			var element = IntegralLiteralElement.Create(node.Image, true, MyInUnaryNegate, MyServices);
			node.AddValue(element);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitXor(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue("Xor");
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitFalse(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(new BooleanLiteralElement(false));
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitRightShift(PerCederberg.Grammatica.Runtime.Token node)
		{
			node.AddValue(ShiftOperation.RightShift);
			return node;
		}
		public override PerCederberg.Grammatica.Runtime.Node ExitMemberExpression(PerCederberg.Grammatica.Runtime.Production node)
		{
			var childValues = this.GetChildValues(node);
			object first = childValues[0];

			if (childValues.Count == 1 && !(first is MemberElement)) {
				node.AddValue(first);
			} else {
				var list = new InvocationListElement(childValues, MyServices);
				node.AddValue(list);
			}

			return node;
		}