/// <summary>
 /// When we leave the function, clean up so we don't accidentally re-use the
 /// function context.
 /// </summary>
 /// <param name="context"></param>
 public override void ExitFunction(FinalStatePatternParser.FunctionContext context)
 {
     _current_cut = null;
     _parsed_functions.Enqueue(Convert(context));
     _current_criteria.Pop();
     base.ExitFunction(context);
 }
 /// <summary>
 /// When we enter a function argument list processing, make sure to specify what is needed.
 /// </summary>
 /// <param name="context"></param>
 public override void EnterFunction(FinalStatePatternParser.FunctionContext context)
 {
     _current_cut = new FinalStateObject()
     {
         Name = string.Format("FuncArg{0}", context.NAME().GetText())
     };
     _current_criteria.Push(new List <ISelectionCriteriaBase>());
     base.EnterFunction(context);
 }
        /// <summary>
        /// Convert a function
        /// </summary>
        /// <param name="functionContext"></param>
        /// <returns></returns>
        private IValueBase Convert(FinalStatePatternParser.FunctionContext functionContext)
        {
            // All the arguments are either on the stack as selection criteria or buried deep.
            var allObjectsInContext =
                functionContext.function_arg()
                .SelectMany(fa => ExtractFSOReferences(fa));
            var allObjectsOnStack =
                _current_criteria.Peek()
                .SelectMany(fa => ExtractFSOReferences(fa));
            var seenObjectNames = new HashSet <FinalStateObject>();

            foreach (var anObject in allObjectsInContext.Concat(allObjectsOnStack))
            {
                seenObjectNames.Add(anObject);
            }

            var textItems =
                functionContext
                .function_arg()
                .Select(a => a.GetText());
            string arglist = "";

            foreach (var at in textItems)
            {
                if (arglist.Length > 0)
                {
                    arglist += ", ";
                }
                arglist += at;
            }

            return(new FunctionPhysicalQuantity()
            {
                Name = functionContext.NAME().GetText(),
                ArgumentList = arglist,
                RefersToObjects = seenObjectNames.ToArray()
            });
        }