Exemplo n.º 1
0
		override internal void FinalPass()
		{
			_ds = OwnerReport.DataSetsDefn[this._DataSetName];
			if (_ds == null)
				OwnerReport.rl.LogError(8, "DataSetReference refers to unknown data set '" + _DataSetName + "'");
			else
			{
				_vField = _ds.Fields[_ValueField];
				if (_vField == null)
					OwnerReport.rl.LogError(8, "ValueField refers to unknown field '" + _ValueField + "'");
				else
				{
					if (_LabelField == null)
						_lField = _vField;
					else
					{
						_lField = _ds.Fields[_LabelField];
						if (_lField == null)
							OwnerReport.rl.LogError(8, "LabelField refers to unknown field '" + _LabelField + "'");
					}
				}
			}

			return;
		}
Exemplo n.º 2
0
		DataRegion _ParentDataRegion;	// when DataRegions are nested; the nested regions have the parent set 
	
		internal DataRegion(ReportDefn r, ReportLink p, XmlNode xNode):base(r,p,xNode)
		{
			_KeepTogether=false;
			_NoRows=null;
			_DataSetName=null;
			_DataSetDefn=null;
			_PageBreakAtStart=false;
			_PageBreakAtEnd=false;
			_Filters=null;
		}
Exemplo n.º 3
0
		IDictionary _Items;			// list of report items

		internal DataSetsDefn(ReportDefn r, ReportLink p, XmlNode xNode) : base(r, p)
		{
			if (xNode.ChildNodes.Count < 10)
				_Items = new ListDictionary();	// Hashtable is overkill for small lists
			else
				_Items = new Hashtable(xNode.ChildNodes.Count);

			// Loop thru all the child nodes
			foreach(XmlNode xNodeLoop in xNode.ChildNodes)
			{
				if (xNodeLoop.NodeType != XmlNodeType.Element)
					continue;
				if (xNodeLoop.Name == "DataSet")
				{
					DataSetDefn ds = new DataSetDefn(r, this, xNodeLoop);
					if (ds != null && ds.Name != null)
						_Items.Add(ds.Name.Nm, ds);
				}
			}
		}
Exemplo n.º 4
0
        Report _rpt; //    the runtime report

        #endregion Fields

        #region Constructors

        internal DataSet(Report rpt, DataSetDefn dsd)
        {
            _rpt = rpt;
            _dsd = dsd;
        }
Exemplo n.º 5
0
        DataSetDefn _dsd;               //  the true definition of the DataSet

        internal DataSet(Report rpt, DataSetDefn dsd)
        {
            _rpt = rpt;
            _dsd = dsd;
        }
Exemplo n.º 6
0
        // return an IEnumerable that represents the scope of the data
        protected RowEnumerable GetDataScope(Report rpt, Row row, out bool bSave)
        {
            bSave = true;
            RowEnumerable re = null;

            if (this._Scope != null)
            {
                Type t = this._Scope.GetType();

                //150208AJM GJL Trying - And Succeeding!!! to get data from chart
                if (t == typeof(Chart))
                {
                    Chart c = (Chart)this._Scope;
                    this._Scope = c.ChartMatrix;
                    t           = this._Scope.GetType();
                }

                if (t == typeof(Grouping))
                {
                    bSave = false;
                    Grouping g = (Grouping)(this._Scope);
                    if (g.InMatrix)
                    {
                        Rows rows = g.GetRows(rpt);
                        if (rows == null)
                        {
                            return(null);
                        }
                        re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, _LevelCheck);
                    }
                    else
                    {
                        if (row == null || row.R.CurrentGroups == null)                             // currentGroups can be null when reference Textbox in header/footer that has a scoped aggr function reference (TODO: this is a problem!)
                        {
                            return(null);
                        }
                        GroupEntry ge = row.R.CurrentGroups[g.GetIndex(rpt)];
                        re = new RowEnumerable(ge.StartRow, ge.EndRow, row.R.Data, _LevelCheck);
                    }
                }
                else if (t == typeof(Matrix))
                {
                    bSave = false;
                    Matrix m     = (Matrix)(this._Scope);
                    Rows   mData = m.GetMyData(rpt);
                    re = new RowEnumerable(0, mData.Data.Count - 1, mData.Data, false);
                }
                else if (t == typeof(string))
                {                       // happens on page header/footer scope
                    if (row != null)
                    {
                        re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
                    }
                    bSave = false;
                }
                else if (row != null)
                {
                    re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
                }
                else
                {
                    DataSetDefn ds = this._Scope as DataSetDefn;
                    if (ds != null && ds.Query != null)
                    {
                        Rows rows = ds.Query.GetMyData(rpt);
                        if (rows != null)
                        {
                            re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, false);
                        }
                    }
                }
            }
            else if (row != null)
            {
                re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
            }

            return(re);
        }
Exemplo n.º 7
0
		// Handle parsing of function in final pass
		override internal void FinalPass()
		{
			base.FinalPass();

			// DataRegions aren't allowed in PageHeader or PageFooter; 
			if (this.InPageHeaderOrFooter())
				OwnerReport.rl.LogError(8, String.Format("The DataRegion '{0}' is not allowed in a PageHeader or PageFooter", this.Name == null? "unknown": Name.Nm) );

			ResolveNestedDataRegions();

			if (_ParentDataRegion != null)		// when nested we use the dataset of the parent
			{
				_DataSetDefn = _ParentDataRegion.DataSetDefn;
			}
			else if (_DataSetName != null)
			{
				if (OwnerReport.DataSetsDefn != null)
					_DataSetDefn = (DataSetDefn) OwnerReport.DataSetsDefn.Items[_DataSetName];
				if (_DataSetDefn == null)
				{
					OwnerReport.rl.LogError(8, String.Format("DataSetName '{0}' not specified in DataSets list.", _DataSetName));
				}
			}
			else
			{		// No name but maybe we can default to a single Dataset
				if (_DataSetDefn == null && OwnerReport.DataSetsDefn != null &&
					OwnerReport.DataSetsDefn.Items.Count == 1)
				{
					foreach (DataSetDefn d in OwnerReport.DataSetsDefn.Items.Values) 
					{	
						_DataSetDefn = d;
						break;	// since there is only 1 this will obtain it
					}
				}
				if (_DataSetDefn == null)
					OwnerReport.rl.LogError(8, string.Format("{0} must specify a DataSetName.",this.Name == null? "DataRegions": this.Name.Nm));
			}

			if (_NoRows != null) 
				_NoRows.FinalPass();
			if (_Filters != null) 
				_Filters.FinalPass();

			return;
		}
Exemplo n.º 8
0
        // Handle parsing of function in final pass
        override internal void FinalPass()
        {
            base.FinalPass();

            if (this is Table)
            {   // Grids don't have any data responsibilities
                Table t = this as Table;
                if (t.IsGrid)
                {
                    return;
                }
            }

            // DataRegions aren't allowed in PageHeader or PageFooter;
            if (this.InPageHeaderOrFooter())
            {
                OwnerReport.rl.LogError(8, String.Format("The DataRegion '{0}' is not allowed in a PageHeader or PageFooter", this.Name == null? "unknown": Name.Nm));
            }

            ResolveNestedDataRegions();

            if (_ParentDataRegion != null)                      // when nested we use the dataset of the parent
            {
                _DataSetDefn = _ParentDataRegion.DataSetDefn;
            }
            else if (_DataSetName != null)
            {
                if (OwnerReport.DataSetsDefn != null)
                {
                    _DataSetDefn = (DataSetDefn)OwnerReport.DataSetsDefn.Items[_DataSetName];
                }
                if (_DataSetDefn == null)
                {
                    OwnerReport.rl.LogError(8, String.Format("DataSetName '{0}' not specified in DataSets list.", _DataSetName));
                }
            }
            else
            {                           // No name but maybe we can default to a single Dataset
                if (_DataSetDefn == null && OwnerReport.DataSetsDefn != null &&
                    OwnerReport.DataSetsDefn.Items.Count == 1)
                {
                    foreach (DataSetDefn d in OwnerReport.DataSetsDefn.Items.Values)
                    {
                        _DataSetDefn = d;
                        break;                          // since there is only 1 this will obtain it
                    }
                }
                if (_DataSetDefn == null)
                {
                    OwnerReport.rl.LogError(8, string.Format("{0} must specify a DataSetName.", this.Name == null? "DataRegions": this.Name.Nm));
                }
            }

            if (_NoRows != null)
            {
                _NoRows.FinalPass();
            }
            if (_Filters != null)
            {
                _Filters.FinalPass();
            }

            return;
        }
Exemplo n.º 9
0
        override internal void FinalPass()
        {
            // optimization: avoid expression overhead if this isn't really an expression
            if (_Source == null)
            {
                _Expr = new Constant("");
                return;
            }
            else if (_Source == "" ||                   // empty expression
                     _Source[0] != '=')                 // if 1st char not '='
            {
                _Expr = new Constant(_Source);          //   this is a constant value
                return;
            }

            Parser p = new Parser(OwnerReport.DataCache);

            // find the fields that are part of the DataRegion (if there is one)
            IDictionary fields = null;
            ReportLink  dr     = Parent;
            Grouping    grp    = null;                  // remember if in a table group or detail group or list group
            Matrix      m      = null;
            ReportLink  phpf   = null;

            while (dr != null)
            {
                if (dr is Grouping)
                {
                    p.NoAggregateFunctions = true;
                }
                else if (dr is TableGroup)
                {
                    grp = ((TableGroup)dr).Grouping;
                }
                else if (dr is Matrix)
                {
                    m = (Matrix)dr;                                     // if matrix we need to pass special
                    break;
                }
                else if (dr is Details)
                {
                    grp = ((Details)dr).Grouping;
                }
                else if (dr is List)
                {
                    grp = ((List)dr).Grouping;
                    break;
                }
                else if (dr is PageHeader || dr is PageFooter)
                {
                    phpf = dr;
                }
                else if (dr is DataRegion || dr is DataSetDefn)
                {
                    break;
                }
                dr = dr.Parent;
            }
            if (dr != null)
            {
                if (dr is DataSetDefn)
                {
                    DataSetDefn d = (DataSetDefn)dr;
                    if (d.Fields != null)
                    {
                        fields = d.Fields.Items;
                    }
                }
                else                    // must be a DataRegion
                {
                    DataRegion d = (DataRegion)dr;
                    if (d.DataSetDefn != null &&
                        d.DataSetDefn.Fields != null)
                    {
                        fields = d.DataSetDefn.Fields.Items;
                    }
                }
            }

            NameLookup lu = new NameLookup(fields, OwnerReport.LUReportParameters,
                                           OwnerReport.LUReportItems, OwnerReport.LUGlobals,
                                           OwnerReport.LUUser, OwnerReport.LUAggrScope,
                                           grp, m, OwnerReport.CodeModules, OwnerReport.Classes, OwnerReport.DataSetsDefn,
                                           OwnerReport.CodeType);

            if (phpf != null)
            {
                // Non-null when expression is in PageHeader or PageFooter;
                //   Expression name needed for dynamic lookup of ReportItems on a page.
                lu.PageFooterHeader = phpf;
                lu.ExpressionName   = _UniqueName = "xn_" + Interlocked.Increment(ref Parser.Counter).ToString();
            }

            try
            {
                _Expr = p.Parse(lu, _Source);
            }
            catch (Exception e)
            {
                _Expr = new ConstantError(e.Message);
                // Invalid expression
                OwnerReport.rl.LogError(8, ErrorText(e.Message));
            }

            // Optimize removing any expression that always result in a constant
            try
            {
                _Expr = _Expr.ConstantOptimization();
            }
            catch (Exception ex)
            {
                OwnerReport.rl.LogError(4, "Expression:" + _Source + "\r\nConstant Optimization exception:\r\n" + ex.Message + "\r\nStack trace:\r\n" + ex.StackTrace);
            }
            _Type = _Expr.GetTypeCode();

            return;
        }
Exemplo n.º 10
0
        internal TypeCode DoParse(Report rpt)
        {
            // optimization: avoid expression overhead if this isn't really an expression
            if (_Source == null)
            {
                _Expr = new Constant("");
                return(_Expr.GetTypeCode());
            }
            else if (_Source == string.Empty ||         // empty expression
                     _Source[0] != '=')                 // if 1st char not '='
            {
                _Expr = new Constant(_Source);          //   this is a constant value
                return(_Expr.GetTypeCode());
            }

            Parser p = new Parser(new System.Collections.Generic.List <ICacheData>());

            // find the fields that are part of the DataRegion (if there is one)
            IDictionary fields = null;
            ReportLink  dr     = _rl.Parent;
            Grouping    grp    = null;                  // remember if in a table group or detail group or list group
            Matrix      m      = null;

            while (dr != null)
            {
                if (dr is Grouping)
                {
                    p.NoAggregateFunctions = true;
                }
                else if (dr is TableGroup)
                {
                    grp = ((TableGroup)dr).Grouping;
                }
                else if (dr is Matrix)
                {
                    m = (Matrix)dr;                                     // if matrix we need to pass special
                    break;
                }
                else if (dr is Details)
                {
                    grp = ((Details)dr).Grouping;
                }
                else if (dr is List)
                {
                    grp = ((List)dr).Grouping;
                    break;
                }
                else if (dr is DataRegion || dr is DataSetDefn)
                {
                    break;
                }
                dr = dr.Parent;
            }
            if (dr != null)
            {
                if (dr is DataSetDefn)
                {
                    DataSetDefn d = (DataSetDefn)dr;
                    if (d.Fields != null)
                    {
                        fields = d.Fields.Items;
                    }
                }
                else                    // must be a DataRegion
                {
                    DataRegion d = (DataRegion)dr;
                    if (d.DataSetDefn != null &&
                        d.DataSetDefn.Fields != null)
                    {
                        fields = d.DataSetDefn.Fields.Items;
                    }
                }
            }

            NameLookup lu = new NameLookup(fields, rpt.ReportDefinition.LUReportParameters,
                                           rpt.ReportDefinition.LUReportItems, rpt.ReportDefinition.LUGlobals,
                                           rpt.ReportDefinition.LUUser, rpt.ReportDefinition.LUAggrScope,
                                           grp, m, rpt.ReportDefinition.CodeModules, rpt.ReportDefinition.Classes, rpt.ReportDefinition.DataSetsDefn,
                                           rpt.ReportDefinition.CodeType);

            try
            {
                _Expr = p.Parse(lu, _Source);
            }
            catch (Exception e)
            {
                _Expr = new ConstantError(e.Message);
                // Invalid expression
                rpt.rl.LogError(8, ErrorText(e.Message));
            }

            // Optimize removing any expression that always result in a constant
            try
            {
                _Expr = _Expr.ConstantOptimization();
            }
            catch (Exception ex)
            {
                rpt.rl.LogError(4, "Expression:" + _Source + "\r\nConstant Optimization exception:\r\n" + ex.Message + "\r\nStack trace:\r\n" + ex.StackTrace);
            }

            return(_Expr.GetTypeCode());
        }
Exemplo n.º 11
0
        // return an IEnumerable that represents the scope of the data
        protected RowEnumerable GetDataScope(Report rpt, Row row, out bool bSave)
        {
            bSave = true;
            RowEnumerable re = null;

            if (this._Scope != null)
            {
                Type t = this._Scope.GetType();
                if (t == typeof(Grouping))
                {
                    bSave = false;
                    Grouping g = (Grouping)(this._Scope);
                    if (g.InMatrix)
                    {
                        Rows rows = g.GetRows(rpt);
                        if (rows == null)
                        {
                            return(null);
                        }
                        re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, _LevelCheck);
                    }
                    else
                    {
                        if (row == null)
                        {
                            return(null);
                        }
                        GroupEntry ge = row.R.CurrentGroups[g.GetIndex(rpt)];
                        re = new RowEnumerable(ge.StartRow, ge.EndRow, row.R.Data, _LevelCheck);
                    }
                }
                else if (t == typeof(Matrix))
                {
                    bSave = false;
                    Matrix m     = (Matrix)(this._Scope);
                    Rows   mData = m.GetMyData(rpt);
                    re = new RowEnumerable(0, mData.Data.Count - 1, mData.Data, false);
                }
                else if (t == typeof(string))
                {                       // happens on page header/footer scope
                    if (row != null)
                    {
                        re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
                    }
                    bSave = false;
                }
                else if (row != null)
                {
                    re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
                }
                else
                {
                    DataSetDefn ds = this._Scope as DataSetDefn;
                    if (ds != null && ds.Query != null)
                    {
                        Rows rows = ds.Query.GetMyData(rpt);
                        if (rows != null)
                        {
                            re = new RowEnumerable(0, rows.Data.Count - 1, rows.Data, false);
                        }
                    }
                }
            }
            else if (row != null)
            {
                re = new RowEnumerable(0, row.R.Data.Count - 1, row.R.Data, false);
            }

            return(re);
        }
Exemplo n.º 12
0
		// FuncIDent: IDENTIFIER ( [Expr] [, Expr]*) | IDENTIFIER
		private bool MatchFuncIDent(out IExpr result)
		{
			IExpr e;
			string fullname;			// will hold the full name
			string method;				// will hold method name or second part of name
			string firstPart;			// will hold the collection name
			string thirdPart;			// will hold third part of name
			bool bOnePart;				// simple name: no ! or . in name

			result = null;

			if (curToken.Type != TokenTypes.IDENTIFIER)
				return false;

			// Disentangle method calls from collection references
			method = fullname = curToken.Value;
			curToken = tokens.Extract();

			// Break the name into parts
			char[] breakChars = new char[] {'!', '.'};

			int posBreak = method.IndexOfAny(breakChars);
			if (posBreak > 0)
			{
				bOnePart = false;
				firstPart = method.Substring(0, posBreak);
				method = method.Substring(posBreak+1);		// rest of expression
			}
			else
			{
				bOnePart = true;
				firstPart = method;
			}

			posBreak = method.IndexOf('.');
            if (posBreak > 0)
            {
                thirdPart = method.Substring(posBreak + 1);	// rest of expression
                method = method.Substring(0, posBreak);
            }
            else
            {
                thirdPart = null;
            }

			if (curToken.Type != TokenTypes.LPAREN) switch (firstPart)
			{
				case "Fields":
					Field f = null;

					if (inAggregateDataSet != null)
					{
						f = inAggregateDataSet.Fields == null ? null : inAggregateDataSet.Fields[method];
						if (f == null)
							throw new ParserException(string.Format(Strings.Parser_ErrorP_FieldNotInDataSet, method, inAggregateDataSet.Name.Nm));
					}
					else
					{
						f = idLookup.LookupField(method);
						if (f == null)
						{
							throw new ParserException(string.Format(Strings.Parser_ErrorP_FieldNotFound, method));
						}
					}

					if (thirdPart == null || thirdPart == "Value")
					{
						result = new FunctionField(f);	
					}
					else if (thirdPart == "IsMissing")
					{
						result = new FunctionFieldIsMissing(f);
					}
					else
						throw new ParserException(string.Format(Strings.Parser_ErrorP_FieldSupportsValueAndIsMissing, method));
					return true;
                case "Parameters":  // see ResolveParametersMethod for resolution of MultiValue parameter function reference
					ReportParameter p = idLookup.LookupParameter(method);
					if (p == null)
						throw new ParserException(string.Format(Strings.Parser_ErrorP_ParameterNotFound, method));
                    int ci = thirdPart == null? -1: thirdPart.IndexOf(".Count");
                    if (ci > 0)
                        thirdPart = thirdPart.Substring(0, ci);
                    FunctionReportParameter r;                    
					if (thirdPart == null || thirdPart == "Value")
						r = new FunctionReportParameter(p);
					else if (thirdPart == "Label")
						r = new FunctionReportParameterLabel(p);
					else
						throw new ParserException(string.Format(Strings.Parser_ErrorP_ParameterSupportsValueAndLabel, method));
                    if (ci > 0)
                        r.SetParameterMethod("Count", null);
                    
                    result = r;
                    return true;
				case "ReportItems":
					Textbox t = idLookup.LookupReportItem(method);
					if (t == null)
						throw new ParserException(string.Format(Strings.Parser_ErrorP_ItemNotFound, method));
					if (thirdPart != null && thirdPart != "Value")
						throw new ParserException(string.Format(Strings.Parser_ErrorP_ItemSupportsValue, method));
					result = new FunctionTextbox(t, idLookup.ExpressionName);	
					return true;
				case "Globals":
					e = idLookup.LookupGlobal(method);
					if (e == null)
						throw new ParserException(string.Format(Strings.Parser_ErrorP_GlobalsNotFound, method));
					result = e;
					return true;
				case "User":
					e = idLookup.LookupUser(method);
					if (e == null)
						throw new ParserException(string.Format(Strings.Parser_ErrorP_UserVarNotFound, method));
					result = e;
					return true;
				case "Recursive":	// Only valid for some aggregate functions
					result = new IdentifierKey(IdentifierKeyEnum.Recursive);
					return true;
				case "Simple":		// Only valid for some aggregate functions
					result = new IdentifierKey(IdentifierKeyEnum.Simple);
					return true;
				default:
					if (!bOnePart)
						throw new ParserException(string.Format(Strings.Parser_ErrorP_UnknownIdentifer, fullname));

					switch (method.ToLower())		// lexer should probably mark these
					{
						case "true":
						case "false":
							result = new ConstantBoolean(method.ToLower());
							break;
						default:
							// usually this is enum that will be used in an aggregate 
							result = new Identifier(method);
							break;
					}
					return true;
			}

			// We've got an function reference
			curToken = tokens.Extract();		// get rid of '('

			// Got a function now obtain the arguments
			int argCount=0;
			
			bool isAggregate = IsAggregate(method, bOnePart);
			if (_NoAggregate && isAggregate)
				throw new ParserException(string.Format(Strings.Parser_ErrorP_AggregateCannotUsedWithinGrouping, method));
			if (_InAggregate && isAggregate)
				throw new ParserException(string.Format(Strings.Parser_ErrorP_AggregateCannotNestedInAnotherAggregate, method));
			_InAggregate = isAggregate;
			if (_InAggregate)
			{
				int level = 0;
				bool nextScope = false;
				Token scopeToken = null;
				foreach(Token tok in tokens)
				{
					if(nextScope)
					{
						scopeToken = tok;
						break;
					}
					
					if(level == 0 && tok.Type == TokenTypes.COMMA)
					{
						nextScope = true;
						continue;
					}
					if (tok.Type == TokenTypes.RPAREN)
						level--;
					if (tok.Type == TokenTypes.LPAREN)
						level++;
				}

				if (scopeToken != null)
				{
					if (scopeToken.Type != TokenTypes.QUOTE)
						throw new ParserException(string.Format(Strings.Parser_ErrorP_ScopeMustConstant, scopeToken.Value));
					inAggregateDataSet = this.idLookup.ScopeDataSet(scopeToken.Value);
					if (inAggregateDataSet == null)
						throw new ParserException(string.Format(Strings.Parser_ErrorP_ScopeNotKnownDataSet, scopeToken.Value));
				}
			}

            List<IExpr> largs = new List<IExpr>();
			while(true)
			{
				if (curToken.Type == TokenTypes.RPAREN)
				{	// We've got our function
					curToken = tokens.Extract();
					break;
				}
				if (argCount == 0)
				{
					// don't need to do anything
				}
				else if (curToken.Type == TokenTypes.COMMA)
				{
					curToken = tokens.Extract();
				}
				else
					throw new ParserException(Strings.Parser_ErrorP_Invalid_function_arguments + GetLocationInfoWithValue(curToken));
				
				MatchExprAndOr(out e);
				if (e == null)
					throw new ParserException(Strings.Parser_ErrorP_ExpectingComma + GetLocationInfoWithValue(curToken));

				largs.Add(e);
				argCount++;
			}
			if (_InAggregate)
			{
				inAggregateDataSet = null;
				_InAggregate = false;
			}

            IExpr[] args = largs.ToArray();

			object scope;
			bool bSimple;
			if (!bOnePart)				
            {
                result = (firstPart == "Parameters")?
                    ResolveParametersMethod(method, thirdPart, args):
                    ResolveMethodCall(fullname, args);	// throw exception when fails
            }
			else switch(method.ToLower())
			{
				case "iif":
					if (args.Length != 3)
						throw new ParserException(Strings.Parser_ErrorP_iff_function_requires_3_arguments + GetLocationInfo(curToken));
//  We allow any type for the first argument; it will get converted to boolean at runtime
//					if (args[0].GetTypeCode() != TypeCode.Boolean)
//						throw new ParserException("First argument to iif function must be boolean." + GetLocationInfo(curToken));
					result = new FunctionIif(args[0], args[1], args[2]);
					break;
				case "choose":
					if (args.Length <= 2)
						throw new ParserException(Strings.Parser_ErrorP_ChooseRequires2Arguments + GetLocationInfo(curToken));
					switch (args[0].GetTypeCode())
					{
						case TypeCode.Double:
						case TypeCode.Single:
						case TypeCode.Int32:
						case TypeCode.Decimal:
						case TypeCode.Int16:
						case TypeCode.Int64:
                        case TypeCode.UInt16:
                        case TypeCode.UInt32:
                        case TypeCode.UInt64:
							break;
						default:
							throw new ParserException(Strings.Parser_ErrorP_ChooseFirstArgumentMustNumeric + GetLocationInfo(curToken));
					}
					result = new FunctionChoose(args);
					break;
				case "switch":
					if (args.Length <= 2)
						throw new ParserException(Strings.Parser_ErrorP_SwitchRequires2Arguments + GetLocationInfo(curToken));
				    if (args.Length % 2 != 0)
						throw new ParserException(Strings.Parser_ErrorP_SwitchMustEvenArguments + GetLocationInfo(curToken));
					for (int i=0; i < args.Length; i = i+2)
					{
						if (args[i].GetTypeCode() != TypeCode.Boolean)
							throw new ParserException(Strings.Parser_ErrorP_SwitchMustBoolean + GetLocationInfo(curToken));
					}
					result = new FunctionSwitch(args);
					break;
				case "format":
					if (args.Length > 2 || args.Length < 1)
						throw new ParserException(Strings.Parser_ErrorP_FormatRequires2Arguments + GetLocationInfo(curToken));
					if (args.Length == 1)
					{
						result = new FunctionFormat(args[0], new ConstantString(""));
					}
					else
					{
						if (args[1].GetTypeCode() != TypeCode.String)
							throw new ParserException(Strings.Parser_ErrorP_SecondMustString + GetLocationInfo(curToken));
						result = new FunctionFormat(args[0], args[1]);
					}
					break;

				case "fields":
					if (args.Length != 1)
						throw new ParserException(Strings.Parser_ErrorP_FieldsRequires1Argument + GetLocationInfo(curToken));
					result = new FunctionFieldCollection(idLookup.Fields, args[0]);
                    if (curToken.Type == TokenTypes.DOT)
                    {	// user placed "."                  TODO: generalize this code
                        curToken = tokens.Extract();                // skip past dot operator
                        if (curToken.Type == TokenTypes.IDENTIFIER && curToken.Value.ToLowerInvariant() == "value")
                            curToken = tokens.Extract();            // only support "value" property for now
                        else
							throw new ParserException(string.Format(Strings.Parser_ErrorP_UnknownProperty, curToken.Value, "Fields") + GetLocationInfo(curToken));
                    }
                    break;
				case "parameters":
					if (args.Length != 1)
						throw new ParserException(Strings.Parser_ErrorP_ParametersRequires1Argument + GetLocationInfo(curToken));
					result = new FunctionParameterCollection(idLookup.Parameters, args[0]);
                    if (curToken.Type == TokenTypes.DOT)
                    {	// user placed "." 
                        curToken = tokens.Extract();                // skip past dot operator
                        if (curToken.Type == TokenTypes.IDENTIFIER && curToken.Value.ToLowerInvariant() == "value")
                            curToken = tokens.Extract();            // only support "value" property for now
                        else
                            throw new ParserException((string.Format(Strings.Parser_ErrorP_UnknownProperty, curToken.Value, "Parameters") + GetLocationInfo(curToken)));
                    }
                    break;
				case "reportitems":
					if (args.Length != 1)
						throw new ParserException(Strings.Parser_ErrorP_ReportItemsRequires1Argument + GetLocationInfo(curToken));
					result = new FunctionReportItemCollection(idLookup.ReportItems, args[0]);
                    if (curToken.Type == TokenTypes.DOT)
                    {	// user placed "." 
                        curToken = tokens.Extract();                // skip past dot operator
                        if (curToken.Type == TokenTypes.IDENTIFIER && curToken.Value.ToLowerInvariant() == "value")
                            curToken = tokens.Extract();            // only support "value" property for now
                        else
                            throw new ParserException((string.Format(Strings.Parser_ErrorP_UnknownProperty, curToken.Value, "ReportItems") + GetLocationInfo(curToken)));
                    }
                    break;
				case "globals":
					if (args.Length != 1)
						throw new ParserException(Strings.Parser_ErrorP_GlobalsRequires1Argument + GetLocationInfo(curToken));
					result = new FunctionGlobalCollection(idLookup.Globals, args[0]);
					break;
				case "user":
					if (args.Length != 1)
						throw new ParserException(Strings.Parser_ErrorP_UserRequires1Argument + GetLocationInfo(curToken));
					result = new FunctionUserCollection(idLookup.User, args[0]);
					break;
				case "sum":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrSum aggrFS = new FunctionAggrSum(_DataCache, args[0], scope);
					aggrFS.LevelCheck = bSimple;
					result = aggrFS;
					break;
				case "avg":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrAvg aggrFA = new FunctionAggrAvg(_DataCache, args[0], scope);
					aggrFA.LevelCheck = bSimple;
					result = aggrFA;
					break;
				case "min":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrMin aggrFMin = new FunctionAggrMin(_DataCache, args[0], scope);
					aggrFMin.LevelCheck = bSimple;
					result = aggrFMin;
					break;
				case "max":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrMax aggrFMax = new FunctionAggrMax(_DataCache, args[0], scope);
					aggrFMax.LevelCheck = bSimple;
					result = aggrFMax;
					break;
				case "first":
					scope = ResolveAggrScope(args, 2, out bSimple);
					result = new FunctionAggrFirst(_DataCache, args[0], scope);
					break;
				case "last":
					scope = ResolveAggrScope(args, 2, out bSimple);
					result = new FunctionAggrLast(_DataCache, args[0], scope);
					break;
				case "next":
					scope = ResolveAggrScope(args, 2, out bSimple);
					result = new FunctionAggrNext(_DataCache, args[0], scope);
					break;
				case "previous":
				    scope = ResolveAggrScope(args, 2, out bSimple);
					result = new FunctionAggrPrevious(_DataCache, args[0], scope);
					break;
				case "level":
					scope = ResolveAggrScope(args, 1, out bSimple);
					result = new FunctionAggrLevel(scope);
					break;
                case "aggregate":
                    scope = ResolveAggrScope(args, 2, out bSimple);
                    FunctionAggrArray aggr = new FunctionAggrArray(_DataCache, args[0], scope);
                    aggr.LevelCheck = bSimple;
                    result = aggr;
                    break;
                case "count":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrCount aggrFC = new FunctionAggrCount(_DataCache, args[0], scope);
					aggrFC.LevelCheck = bSimple;
					result = aggrFC;
					break;
				case "countrows":
					scope = ResolveAggrScope(args, 1, out bSimple);
					FunctionAggrCountRows aggrFCR = new FunctionAggrCountRows(scope);
					aggrFCR.LevelCheck = bSimple;
					result = aggrFCR;
					break;
                case "countdistinct":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrCountDistinct aggrFCD = new FunctionAggrCountDistinct(_DataCache, args[0], scope);
					aggrFCD.LevelCheck = bSimple;
					result = aggrFCD;
					break;
				case "rownumber":
					scope = ResolveAggrScope(args, 1, out bSimple);
					IExpr texpr = new ConstantDouble("0");
					result = new FunctionAggrRvCount(_DataCache, texpr, scope);
					break;
				case "runningvalue":
					if (args.Length < 2 || args.Length > 3)
						throw new ParserException(Strings.Parser_ErrorP_RunningValue_takes_2_or_3_arguments + GetLocationInfo(curToken));
					string aggrFunc = args[1].EvaluateString(null, null);
					if (aggrFunc == null)
						throw new ParserException(Strings.Parser_ErrorP_RunningValueArgumentInvalid + GetLocationInfo(curToken));
					scope = ResolveAggrScope(args, 3, out bSimple);
					switch(aggrFunc.ToLower())
					{
						case "sum":
							result = new FunctionAggrRvSum(_DataCache, args[0], scope);
							break;
						case "avg":
							result = new FunctionAggrRvAvg(_DataCache, args[0], scope);
							break;
						case "count":
							result = new FunctionAggrRvCount(_DataCache, args[0], scope);
							break;
						case "max":
							result = new FunctionAggrRvMax(_DataCache, args[0], scope);
							break;
						case "min":
							result = new FunctionAggrRvMin(_DataCache, args[0], scope);
							break;
						case "stdev":
							result = new FunctionAggrRvStdev(_DataCache, args[0], scope);
							break;
						case "stdevp":
							result = new FunctionAggrRvStdevp(_DataCache, args[0], scope);
							break;
						case "var":
							result = new FunctionAggrRvVar(_DataCache, args[0], scope);
							break;
						case "varp":
							result = new FunctionAggrRvVarp(_DataCache, args[0], scope);
							break;
						default:
							throw new ParserException(string.Format(Strings.Parser_ErrorP_RunningValueNotSupported, aggrFunc) + GetLocationInfo(curToken));
					}
					break;
				case "stdev":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrStdev aggrSDev = new FunctionAggrStdev(_DataCache, args[0], scope);
					aggrSDev.LevelCheck = bSimple;
					result = aggrSDev;
					break;
				case "stdevp":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrStdevp aggrSDevP = new FunctionAggrStdevp(_DataCache, args[0], scope);
					aggrSDevP.LevelCheck = bSimple;
					result = aggrSDevP;
					break;
				case "var":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrVar aggrVar = new FunctionAggrVar(_DataCache, args[0], scope);
					aggrVar.LevelCheck = bSimple;
					result = aggrVar;
					break;
				case "varp":
					scope = ResolveAggrScope(args, 2, out bSimple);
					FunctionAggrVarp aggrVarP = new FunctionAggrVarp(_DataCache, args[0], scope);
					aggrVarP.LevelCheck = bSimple;
					result = aggrVarP;
					break;
				default:
					result = ResolveMethodCall(fullname, args);		// through exception when fails
					break;
			}

			return true;
		}