/// <summary>
        /// parses the macro.  We need to do this here, at init time, or else
        /// the local-scope template feature is hard to get to work :)
        /// </summary>
        private void parseTree(String[] callArgs)
        {
            try
            {
                TextReader br = new StringReader(macroBody);

                // now parse the macro - and don't dump the namespace
                nodeTree = runtimeServices.Parse(br, ns, false);

                // now, to make null references render as proper schmoo
                // we need to tweak the tree and change the literal of
                // the appropriate references

                // we only do this at init time, so it's the overhead
                // is irrelevant
                Hashtable hm = new Hashtable();

                for (int i = 1; i < argArray.Length; i++)
                {
                    String arg = callArgs[i - 1];

                    // if the calling arg is indeed a reference
                    // then we add to the map.  We ignore other
                    // stuff
                    if (arg[0] == '$')
                    {
                        hm[argArray[i]] = arg;
                    }
                }

                // now make one of our reference-munging visitor, and
                // let 'er rip
                VMReferenceMungeVisitor v = new VMReferenceMungeVisitor(hm);
                nodeTree.Accept(v, null);
            }
            catch (Exception e)
            {
                runtimeServices.Error(string.Format("VelocimacroManager.parseTree() : exception {0} : {1}", macroName, e));
            }
        }