Example #1
0
        protected TALCommand Compile_METAL_FILL_PARAM(string argument)
        {
            // Compile a fill-param command, resulting argument is:
            // Argument: [(paramName, paramPath),...]

            // Break up the list of defines first
            List<DefineInfo> commandArgs = new List<DefineInfo>();
            // We only want to match semi-colons that are not escaped
            foreach (string defStmt in Constants.METAL_FILL_PARAM_REGEX.Split(argument))
            {
                //  remove any leading space and un-escape any semi-colons
                string defineStmt = defStmt.TrimStart().Replace(";;", ";");
                // Break each defineStmt into pieces "[local|global] varName expression"
                List<string> stmtBits = new List<string>(defineStmt.Split(new char[] { ' ' }));
                string varName;
                string expression;
                if (stmtBits.Count < 2)
                {
                    // Error, badly formed fill-param command
                    string msg = string.Format("Badly formed fill-param command '{0}'.  Fill-param commands must be of the form: 'varName expression[;varName expression]'", argument);
                    throw new TemplateParseException(this.currentStartTag, msg);
                }
                varName = stmtBits[0];
                expression = string.Join(" ", stmtBits.GetRange(1, stmtBits.Count - 1).ToArray());

                DefineInfo di = new DefineInfo();
                di.defAction = DefineAction.Local;
                di.varName = varName;
                di.varPath = expression;
                commandArgs.Add(di);
            }

            // Determine what use-macro statement this belongs to by working through the list backwards
            int? ourMacroLocation = null;
            int location = this.tagStack.Count - 1;
            while (ourMacroLocation == null)
            {
                int macroLocation = this.tagStack[location].UseMacroLocation;
                if (macroLocation != -1)
                {
                    ourMacroLocation = macroLocation;
                }
                else
                {
                    location -= 1;
                    if (location < 0)
                    {
                        string msg = string.Format("metal:fill-param must be used inside a metal:use-macro call");
                        throw new TemplateParseException(this.currentStartTag, msg);
                    }
                }
            }

            // Get the use-macro command we are going to adjust
            TALCommand cmnd = this.commandList[(int)ourMacroLocation];
            string macroName = (string)cmnd.Attributes[0];
            Dictionary<string, TALSubProgram> slotMap = (Dictionary<string, TALSubProgram>)cmnd.Attributes[1];
            List<DefineInfo> paramMap = (List<DefineInfo>)cmnd.Attributes[2];
            int endSymbol = (int)cmnd.Attributes[3];

            // Append param definitions to list
            paramMap.AddRange(commandArgs);

            // Update the command
            TALCommand ci = new TALCommand();
            ci.Tag = cmnd.Tag;
            ci.ID = cmnd.ID;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(macroName);
            ci.Attributes.Add(slotMap);
            ci.Attributes.Add(paramMap);
            ci.Attributes.Add(endSymbol);
            this.commandList[(int)ourMacroLocation] = ci;
            return null;
        }
Example #2
0
        protected TALCommand Compile_METAL_FILL_SLOT(string argument)
        {
            if (argument.Length == 0)
            {
                // No argument passed
                string msg = "No argument passed!  fill-slot commands must be of the form: 'fill-slot: name'";
                throw new TemplateParseException(this.currentStartTag, msg);
            }

            // Check that the name of the slot is valid
            if (Constants.METAL_NAME_REGEX.Match(argument).Length != argument.Length)
            {
                string msg = string.Format("Slot name {0} is invalid.", argument);
                throw new TemplateParseException(this.currentStartTag, msg);
            }

            // Determine what use-macro statement this belongs to by working through the list backwards
            int? ourMacroLocation = null;
            int location = this.tagStack.Count - 1;
            while (ourMacroLocation == null)
            {
                int macroLocation = this.tagStack[location].UseMacroLocation;
                if (macroLocation != -1)
                {
                    ourMacroLocation = macroLocation;
                }
                else
                {
                    location -= 1;
                    if (location < 0)
                    {
                        string msg = string.Format("metal:fill-slot must be used inside a metal:use-macro call");
                        throw new TemplateParseException(this.currentStartTag, msg);
                    }
                }
            }

            // Get the use-macro command we are going to adjust
            TALCommand cmnd = this.commandList[(int)ourMacroLocation];
            string macroName = (string)cmnd.Attributes[0];
            Dictionary<string, TALSubProgram> slotMap = (Dictionary<string, TALSubProgram>)cmnd.Attributes[1];
            List<DefineInfo> paramMap = (List<DefineInfo>)cmnd.Attributes[2];
            int endSymbol = (int)cmnd.Attributes[3];

            if (slotMap.ContainsKey(argument))
            {
                string msg = string.Format("Slot {0} has already been filled!", argument);
                throw new TemplateParseException(this.currentStartTag, msg);
            }

            // The slot starts at the next command.
            TALSubProgram slot = new TALSubProgram(this.commandList.Count, this.endTagSymbol);
            slotMap.Add(argument, slot);

            // Update the command
            TALCommand ci = new TALCommand();
            ci.Tag = cmnd.Tag;
            ci.ID = cmnd.ID;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(macroName);
            ci.Attributes.Add(slotMap);
            ci.Attributes.Add(paramMap);
            ci.Attributes.Add(endSymbol);
            this.commandList[(int)ourMacroLocation] = ci;
            return null;
        }
Example #3
0
        protected TALCommand Compile_METAL_DEFINE_PARAM(string argument)
        {
            // Compile a define-param command, resulting argument is:
            // Argument: [(paramType, paramName, paramPath),...]

            // Break up the list of defines first
            List<DefineInfo> commandArgs = new List<DefineInfo>();
            // We only want to match semi-colons that are not escaped
            foreach (string defStmt in Constants.METAL_DEFINE_PARAM_REGEX.Split(argument))
            {
                //  remove any leading space and un-escape any semi-colons
                string defineStmt = defStmt.TrimStart().Replace(";;", ";");
                // Break each defineStmt into pieces "[local|global] varName expression"
                List<string> stmtBits = new List<string>(defineStmt.Split(new char[] { ' ' }));
                string varType;
                string varName;
                string expression;
                if (stmtBits.Count < 3)
                {
                    // Error, badly formed define-param command
                    string msg = string.Format("Badly formed define-param command '{0}'.  Define commands must be of the form: 'varType varName expression[;varType varName expression]'", argument);
                    throw new TemplateParseException(this.currentStartTag, msg);
                }
                varType = stmtBits[0];
                varName = stmtBits[1];
                expression = string.Join(" ", stmtBits.GetRange(2, stmtBits.Count - 2).ToArray());

                DefineInfo di = new DefineInfo();
                di.defAction = DefineAction.Local;
                di.varType = varType;
                di.varName = varName;
                di.varPath = expression;
                commandArgs.Add(di);
            }

            TALCommand ci = new TALCommand();
            ci.Tag = this.currentStartTag;
            ci.ID = Constants.METAL_DEFINE_PARAM;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(commandArgs);
            return ci;
        }
Example #4
0
        protected TALCommand Compile_METAL_DEFINE_SLOT(string argument)
        {
            // Compile a define-slot command, resulting argument is:
            // Argument: macroName, endTagSymbol

            if (argument.Length == 0)
            {
                // No argument passed
                string msg = "No argument passed!  define-slot commands must be of the form: 'name'";
                throw new TemplateParseException(this.currentStartTag, msg);
            }
            // Check that the name of the slot is valid
            if (Constants.METAL_NAME_REGEX.Match(argument).Length != argument.Length)
            {
                string msg = string.Format("Slot name {0} is invalid.", argument);
                throw new TemplateParseException(this.currentStartTag, msg);
            }

            TALCommand ci = new TALCommand();
            ci.Tag = this.currentStartTag;
            ci.ID = Constants.METAL_DEFINE_SLOT;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(argument);
            ci.Attributes.Add(this.endTagSymbol);
            return ci;
        }
Example #5
0
        protected void AddCommand(TALCommand command)
        {
            // <DEBUG>
            //this.LogCommand(command);
            // </DEBUG>

            //
            // Only following commands can be used inside Tags without scope:
            //	TAL_DEFINE, TAL_OUTPUT
            // Following commands are ignored by the "SourceGenerator" class:
            //	TAL_START_SCOPE, TAL_STARTTAG, TAL_ENDTAG_ENDSCOPE, TAL_OMITTAG
            //
            if (command.Tag != null &&
                command.Tag.OmitTagScope == true &&
                command.ID != Constants.TAL_DEFINE &&
                command.ID != Constants.TAL_OUTPUT &&
                command.ID != Constants.TAL_START_SCOPE &&
                command.ID != Constants.TAL_STARTTAG &&
                command.ID != Constants.TAL_ENDTAG_ENDSCOPE &&
                command.ID != Constants.TAL_OMITTAG)
            {
                // This command can not be used inside tag without his own scope
                string msg = string.Format(@"Command ""{0}"" can not be used inside tag <tal:omit-scope>'.",
                    Constants.GetCommandName(command.ID));
                throw new TemplateParseException(this.currentStartTag, msg);
            }

            if (command.ID == Constants.TAL_OUTPUT &&
                this.commandList.Count > 0 &&
                this.commandList[this.commandList.Count - 1].ID == Constants.TAL_OUTPUT)
            {
                // We can combine output commands
                TALCommand cmd = this.commandList[this.commandList.Count - 1];
                foreach (object att in command.Attributes)
                    cmd.Attributes.Add(att);
            }
            else
            {
                this.commandList.Add(command);
            }
        }
Example #6
0
        protected void addTag(Tag tag, Dictionary<string, string> cleanAttributes, Dictionary<string, object> tagProperties)
        {
            // Used to add a tag to the stack.  Various properties can be passed in the dictionary
            // as being information required by the tag.
            // Currently supported properties are:
            //  'command'         - The (command,args) tuple associated with this command
            //  'originalAtts'    - The original attributes that include any metal/tal attributes
            //  'endTagSymbol'    - The symbol associated with the end tag for this element
            //  'popFunctionList' - A list of functions to execute when this tag is popped
            //  'singletonTag'    - A boolean to indicate that this is a singleton flag

            tag.Attributes = cleanAttributes;

            // Add the tag to the tagStack (list of tuples (tag, properties, useMacroLocation))

            TALCommand command = (TALCommand)(tagProperties.ContainsKey("command") ? tagProperties["command"] : null);
            Dictionary<string, string> originalAtts = (Dictionary<string, string>)(tagProperties.ContainsKey("originalAtts") ? tagProperties["originalAtts"] : null);
            int singletonTag = (int)(tagProperties.ContainsKey("singletonTag") ? tagProperties["singletonTag"] : 0);

            TagInfo ti = new TagInfo();
            if (command != null)
            {
                if (command.ID == Constants.METAL_USE_MACRO)
                {
                    ti.Tag = tag;
                    ti.Properties = tagProperties;
                    ti.UseMacroLocation = this.commandList.Count + 1;
                }
                else
                {
                    ti.Tag = tag;
                    ti.Properties = tagProperties;
                    ti.UseMacroLocation = -1;
                }
            }
            else
            {
                ti.Tag = tag;
                ti.Properties = tagProperties;
                ti.UseMacroLocation = -1;
            }
            this.tagStack.Add(ti);

            if (command != null)
            {
                // All tags that have a TAL attribute on them start with a 'start scope'
                TALCommand cmd = new TALCommand();
                cmd.Tag = this.currentStartTag;
                cmd.ID = Constants.TAL_START_SCOPE;
                cmd.Attributes = new List<object>();
                cmd.Attributes.Add(originalAtts);
                cmd.Attributes.Add(cleanAttributes);
                this.AddCommand(cmd);
                // Now we add the TAL command
                this.AddCommand(command);
            }
            else
            {
                // It's just a straight output, so create an output command and append it
                TALCommand cmd = new TALCommand();
                cmd.Tag = this.currentStartTag;
                cmd.ID = Constants.TAL_OUTPUT;
                cmd.Attributes = new List<object>();
                cmd.Attributes.Add(this.tagAsText(tag, singletonTag));
                this.AddCommand(cmd);
            }
        }
Example #7
0
        protected void parseStartTag(Tag tag, Dictionary<string, string> attributes, int singletonElement)
        {
            // Note down the tag we are handling, it will be used for error handling during
            // compilation
            this.currentStartTag = new Tag();
            this.currentStartTag.Name = tag.Name;
            this.currentStartTag.Attributes = attributes;
            this.currentStartTag.SourcePath = tag.SourcePath;
            this.currentStartTag.LineNumber = tag.LineNumber;
            this.currentStartTag.LinePosition = tag.LinePosition;

            // Look for tal/metal attributes
            List<int> foundTALAtts = new List<int>();
            List<int> foundMETALAtts = new List<int>();
            Dictionary<int, string> foundCommandsArgs = new Dictionary<int, string>();
            Dictionary<string, string> cleanAttributes = new Dictionary<string, string>();
            Dictionary<string, string> originalAttributes = new Dictionary<string, string>();
            Dictionary<string, object> tagProperties = new Dictionary<string, object>();
            List<VoidFuncDelegate> popTagFuncList = new List<VoidFuncDelegate>();
            bool isTALElementNameSpace = false;
            string prefixToAdd = "";
            tagProperties.Add("singletonTag", singletonElement);

            // Determine whether this element is in either the METAL or TAL namespace
            if (tag.Name.IndexOf(':') > 0)
            {
                // We have a namespace involved, so let's look to see if its one of ours
                string _namespace = tag.Name.Substring(0, tag.Name.IndexOf(':'));
                if (_namespace == this.metal_namespace_prefix)
                {
                    isTALElementNameSpace = true;
                    prefixToAdd = this.metal_namespace_prefix + ":";
                }
                else if (_namespace == this.tal_namespace_prefix)
                {
                    // This tag has not his own scope
                    if (tag.Name == tal_namespace_omitscope)
                    {
                        tag.OmitTagScope = true;
                        this.currentStartTag.OmitTagScope = true;
                    }
                    isTALElementNameSpace = true;
                    prefixToAdd = this.tal_namespace_prefix + ":";
                }
                if (isTALElementNameSpace)
                {
                    // We should treat this an implicit omit-tag
                    foundTALAtts.Add(Constants.TAL_OMITTAG);
                    // Will go to default, i.e. yes
                    foundCommandsArgs[Constants.TAL_OMITTAG] = "";
                }
            }

            foreach (KeyValuePair<string, string> attr in attributes)
            {
                string att = attr.Key;
                string value = attr.Value;

                string commandAttName = "";

                originalAttributes.Add(att, value);
                if (isTALElementNameSpace && !(att.IndexOf(':') > 0))
                {
                    // This means that the attribute name does not have a namespace, so use the prefix for this tag.
                    commandAttName = prefixToAdd + att;
                }
                else
                {
                    commandAttName = att;
                }

                if (att.Length > 4 && att.Substring(0, 5) == "xmlns")
                {
                    // We have a namespace declaration.
                    string prefix = att.Length > 5 ? att.Substring(6) : "";
                    if (value == Constants.METAL_NAME_URI)
                    {
                        // It's a METAL namespace declaration
                        if (prefix.Length > 0)
                        {
                            this.metal_namespace_prefix_stack.Add(this.metal_namespace_prefix);
                            this.setMETALPrefix(prefix);
                            // We want this function called when the scope ends
                            popTagFuncList.Add(this.popMETALNamespace);
                        }
                        else
                        {
                            // We don't allow METAL/TAL to be declared as a default
                            string msg = "Can not use METAL name space by default, a prefix must be provided.";
                            throw new TemplateParseException(this.currentStartTag, msg);
                        }
                    }
                    else if (value == Constants.TAL_NAME_URI)
                    {
                        // TAL this time
                        if (prefix.Length > 0)
                        {
                            this.tal_namespace_prefix_stack.Add(this.tal_namespace_prefix);
                            this.setTALPrefix(prefix);
                            // We want this function called when the scope ends
                            popTagFuncList.Add(this.popTALNamespace);
                        }
                        else
                        {
                            // We don't allow METAL/TAL to be declared as a default
                            string msg = "Can not use TAL name space by default, a prefix must be provided.";
                            throw new TemplateParseException(this.currentStartTag, msg);
                        }
                    }
                    else
                    {
                        // It's nothing special, just an ordinary namespace declaration
                        cleanAttributes.Add(att, value);
                    }
                }
                else if (this.tal_attribute_map.ContainsKey(commandAttName))
                {
                    // It's a TAL attribute
                    int cmnd = this.tal_attribute_map[commandAttName];
                    if (cmnd == Constants.TAL_OMITTAG && isTALElementNameSpace)
                    {
                        //this.log.warn("Supressing omit-tag command present on TAL or METAL element");
                    }
                    else
                    {
                        foundCommandsArgs.Add(cmnd, value);
                        foundTALAtts.Add(cmnd);
                    }
                }
                else if (this.metal_attribute_map.ContainsKey(commandAttName))
                {
                    // It's a METAL attribute
                    int cmnd = this.metal_attribute_map[commandAttName];
                    foundCommandsArgs.Add(cmnd, value);
                    foundMETALAtts.Add(cmnd);
                }
                else
                {
                    cleanAttributes.Add(att, value);
                }
            }
            tagProperties.Add("popFunctionList", popTagFuncList);

            // This might be just content
            if ((foundTALAtts.Count + foundMETALAtts.Count) == 0)
            {
                // Just content, add it to the various stacks
                this.addTag(tag, cleanAttributes, tagProperties);
                return;
            }

            // Create a symbol for the end of the tag - we don't know what the offset is yet
            this.endTagSymbol += 1;
            tagProperties.Add("endTagSymbol", this.endTagSymbol);

            // Sort the METAL commands by priority. Priority is defined by opcode number, see Constants.METAL_* opcodes.
            foundMETALAtts.Sort();

            // Sort the TAL commands by priority. Priority is defined by opcode number, see Constants.TAL_* opcodes.
            foundTALAtts.Sort();

            // We handle the METAL before the TAL
            List<int> allCommands = new List<int>();
            allCommands.AddRange(foundMETALAtts);
            allCommands.AddRange(foundTALAtts);
            int firstTag = 1;
            foreach (int talAtt in allCommands)
            {
                // Parse and create a command for each
                TALCommand cmnd = this.commandHandler[talAtt](foundCommandsArgs[talAtt]);
                if (cmnd != null)
                {
                    if (firstTag == 1)
                    {
                        // The first one needs to add the tag
                        firstTag = 0;
                        tagProperties["originalAtts"] = originalAttributes;
                        tagProperties["command"] = cmnd;
                        this.addTag(tag, cleanAttributes, tagProperties);
                    }
                    else
                    {
                        // All others just append
                        this.AddCommand(cmnd);
                    }
                }
            }

            TALCommand cmd = new TALCommand();
            cmd.Tag = this.currentStartTag;
            cmd.ID = Constants.TAL_STARTTAG;
            cmd.Attributes = new List<object>();
            cmd.Attributes.Add(tag);
            cmd.Attributes.Add(singletonElement);

            if (firstTag == 1)
            {
                tagProperties["originalAtts"] = originalAttributes;
                tagProperties["command"] = cmd;
                this.addTag(tag, cleanAttributes, tagProperties);
            }
            else
            {
                // Add the start tag command in as a child of the last TAL command
                this.AddCommand(cmd);
            }
        }
Example #8
0
        protected TALCommand Compile_TAL_CONTENT(string argument, int replaceFlag)
        {
            // Compile a content command, resulting argument is
            // (replaceFlag, structureFlag, expression, endTagSymbol)

            // Sanity check
            if (argument.Length == 0)
            {
                // No argument passed
                string msg = "No argument passed!  content/replace commands must be of the form: 'path'";
                throw new TemplateParseException(this.currentStartTag, msg);
            }

            int structureFlag = 0;
            string[] attProps = argument.Split(new char[] { ' ' });
            string express = "";
            if (attProps.Length > 1)
            {
                if (attProps[0] == "structure")
                {
                    structureFlag = 1;
                    express = string.Join(" ", attProps, 1, attProps.Length - 1);
                }
                else if (attProps[1] == "text")
                {
                    structureFlag = 0;
                    express = string.Join(" ", attProps, 1, attProps.Length - 1);
                }
                else
                {
                    // It's not a type selection after all - assume it's part of the path
                    express = argument;
                }
            }
            else
                express = argument;

            TALCommand ci = new TALCommand();
            ci.Tag = this.currentStartTag;
            ci.ID = Constants.TAL_CONTENT;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(replaceFlag);
            ci.Attributes.Add(structureFlag);
            ci.Attributes.Add(express);
            ci.Attributes.Add(this.endTagSymbol);
            return ci;
        }
Example #9
0
 protected void LogCommand(TALCommand cmd)
 {
     List<string> attributes = new List<string>();
     if (cmd.Attributes != null)
     {
         foreach (object attr in cmd.Attributes)
         {
             attributes.Add(string.Format(@"{0}    {1}", Environment.NewLine, attr));
         }
     }
     Console.WriteLine("{0}Command: {1}{2}",
         Environment.NewLine, Constants.GetCommandName(cmd.ID), string.Join("", attributes.ToArray()));
 }
Example #10
0
 protected void parseData(string data)
 {
     // Just add it as an output
     TALCommand cmd = new TALCommand();
     cmd.Tag = this.currentStartTag;
     cmd.ID = Constants.TAL_OUTPUT;
     cmd.Attributes = new List<object>();
     cmd.Attributes.Add(data);
     this.AddCommand(cmd);
 }
Example #11
0
        protected TALCommand Compile_TAL_REPEAT(string argument)
        {
            // Compile a repeat command, resulting argument is:
            // (varname, expression, endTagSymbol)
            List<string> attProps = new List<string>(argument.Split(new char[] { ' ' }));
            if (attProps.Count < 2)
            {
                // Error, badly formed repeat command
                string msg = string.Format("Badly formed repeat command '{0}'.  Repeat commands must be of the form: 'localVariable path'", argument);
                throw new TemplateParseException(this.currentStartTag, msg);
            }

            string varName = attProps[0];
            string expression = string.Join(" ", attProps.GetRange(1, attProps.Count - 1).ToArray());

            TALCommand ci = new TALCommand();
            ci.Tag = this.currentStartTag;
            ci.ID = Constants.TAL_REPEAT;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(varName);
            ci.Attributes.Add(expression);
            ci.Attributes.Add(this.endTagSymbol);
            return ci;
        }
Example #12
0
        protected TALCommand Compile_TAL_OMITTAG(string argument)
        {
            // Compile a condition command, resulting argument is:
            // path
            // If no argument is given then set the path to default

            string expression = "";
            if (argument.Length == 0)
                expression = Constants.DEFAULT_VALUE_EXPRESSION;
            else
                expression = argument;

            TALCommand ci = new TALCommand();
            ci.Tag = this.currentStartTag;
            ci.ID = Constants.TAL_OMITTAG;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(expression);
            return ci;
        }
Example #13
0
        protected TALCommand Compile_TAL_DEFINE(string argument)
        {
            // Compile a define command, resulting argument is:
            // [(DefineAction (global, local, set), variableName, variablePath),...]
            // Break up the list of defines first
            List<DefineInfo> commandArgs = new List<DefineInfo>();
            // We only want to match semi-colons that are not escaped
            foreach (string defStmt in Constants.TAL_DEFINE_REGEX.Split(argument))
            {
                //  remove any leading space and un-escape any semi-colons
                string defineStmt = defStmt.TrimStart().Replace(";;", ";");
                // Break each defineStmt into pieces "[local|global] varName expression"
                List<string> stmtBits = new List<string>(defineStmt.Split(new char[] { ' ' }));
                DefineAction defAction = DefineAction.Local;
                string varName;
                string expression;
                if (stmtBits.Count < 2)
                {
                    // Error, badly formed define command
                    string msg = string.Format("Badly formed define command '{0}'.  Define commands must be of the form: '[local|global] varName expression[;[local|global] varName expression]'", argument);
                    throw new TemplateParseException(this.currentStartTag, msg);
                }
                // Assume to start with that >2 elements means a local|global flag
                if (stmtBits.Count > 2)
                {
                    if (stmtBits[0] == "global")
                    {
                        defAction = DefineAction.Global;
                        varName = stmtBits[1];
                        expression = string.Join(" ", stmtBits.GetRange(2, stmtBits.Count - 2).ToArray());
                    }
                    else if (stmtBits[0] == "local")
                    {
                        varName = stmtBits[1];
                        expression = string.Join(" ", stmtBits.GetRange(2, stmtBits.Count - 2).ToArray());
                    }
                    else if (stmtBits[0] == "set")
                    {
                        defAction = DefineAction.SetLocal;
                        varName = stmtBits[1];
                        expression = string.Join(" ", stmtBits.GetRange(2, stmtBits.Count - 2).ToArray());
                    }
                    else
                    {
                        // Must be a space in the expression that caused the >3 thing
                        varName = stmtBits[0];
                        expression = string.Join(" ", stmtBits.GetRange(1, stmtBits.Count - 1).ToArray());
                    }
                }
                else
                {
                    // Only two bits
                    varName = stmtBits[0];
                    expression = string.Join(" ", stmtBits.GetRange(1, stmtBits.Count - 1).ToArray());
                }

                DefineInfo di = new DefineInfo();
                di.defAction = defAction;
                di.varName = varName;
                di.varPath = expression;
                commandArgs.Add(di);
            }

            TALCommand ci = new TALCommand();
            ci.Tag = this.currentStartTag;
            ci.ID = Constants.TAL_DEFINE;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(commandArgs);
            return ci;
        }
Example #14
0
 protected TALCommand Compile_METAL_USE_MACRO(string argument)
 {
     // Sanity check
     if (argument.Length == 0)
     {
         // No argument passed
         string msg = "No argument passed!  use-macro commands must be of the form: 'use-macro: path'";
         throw new TemplateParseException(this.currentStartTag, msg);
     }
     TALCommand ci = new TALCommand();
     ci.Tag = this.currentStartTag;
     ci.ID = Constants.METAL_USE_MACRO;
     ci.Attributes = new List<object>();
     ci.Attributes.Add(argument);
     ci.Attributes.Add(new Dictionary<string, TALSubProgram>());
     ci.Attributes.Add(new List<DefineInfo>());
     ci.Attributes.Add(this.endTagSymbol);
     return ci;
 }
Example #15
0
        protected void popTag(Tag tag, int omitTagFlag)
        {
            // omitTagFlag is used to control whether the end tag should be included in the
            // output or not.  In HTML 4.01 there are several tags which should never have
            // end tags, this flag allows the template compiler to specify that these
            // should not be output.

            while (this.tagStack.Count > 0)
            {
                TagInfo ti = this.tagStack[this.tagStack.Count - 1];
                this.tagStack.RemoveAt(this.tagStack.Count - 1);

                Tag oldTag = ti.Tag;
                Dictionary<string, object> tagProperties = ti.Properties;

                int? endTagSymbol = (int?)(tagProperties.ContainsKey("endTagSymbol") ? tagProperties["endTagSymbol"] : null);
                List<VoidFuncDelegate> popCommandList = (List<VoidFuncDelegate>)(tagProperties.ContainsKey("popCommandList") ? tagProperties["popCommandList"] : null);
                int singletonTag = (int)(tagProperties.ContainsKey("singletonTag") ? tagProperties["singletonTag"] : 0);

                if (popCommandList != null)
                {
                    foreach (VoidFuncDelegate func in popCommandList)
                    {
                        func();
                    }
                }

                if (oldTag.Name == tag.Name)
                {
                    // We've found the right tag, now check to see if we have any TAL commands on it
                    if (endTagSymbol != null)
                    {
                        // We have a command (it's a TAL tag)
                        // Note where the end tag symbol should point (i.e. the next command)
                        this.symbolLocationTable[(int)endTagSymbol] = this.commandList.Count;

                        // We need a "close scope and tag" command
                        TALCommand cmd = new TALCommand();
                        cmd.Tag = this.currentStartTag;
                        cmd.ID = Constants.TAL_ENDTAG_ENDSCOPE;
                        cmd.Attributes = new List<object>();
                        cmd.Attributes.Add(tag.Name);
                        cmd.Attributes.Add(omitTagFlag);
                        cmd.Attributes.Add(singletonTag);
                        this.AddCommand(cmd);
                        return;
                    }
                    else if (omitTagFlag == 0 && singletonTag == 0)
                    {
                        // We are popping off an un-interesting tag, just add the close as text
                        // We need a "close scope and tag" command
                        TALCommand cmd = new TALCommand();
                        cmd.Tag = this.currentStartTag;
                        cmd.ID = Constants.TAL_OUTPUT;
                        cmd.Attributes = new List<object>();
                        cmd.Attributes.Add("</" + tag.Name + ">");
                        this.AddCommand(cmd);
                        return;
                    }
                    else
                    {
                        // We are suppressing the output of this tag, so just return
                        return;
                    }
                }
                else
                {
                    // We have a different tag, which means something like <br> which never closes is in
                    // between us and the real tag.

                    // If the tag that we did pop off has a command though it means un-balanced TAL tags!
                    if (endTagSymbol != null)
                    {
                        // ERROR
                        string msg = string.Format("TAL/METAL Elements must be balanced - found close tag {0} expecting {1}", tag.Name, oldTag.Name);
                        throw new TemplateParseException(oldTag, msg);
                    }
                }
            }
            throw new TemplateParseException(null,
                string.Format("</{0}> {1}", tag.Name, "Close tag encountered with no corresponding open tag."));
        }
Example #16
0
        protected TALCommand Compile_TAL_ATTRIBUTES(string argument)
        {
            // Compile tal:attributes into attribute command
            // Argument: [(attributeName, expression)]

            // Break up the list of attribute settings first
            Dictionary<string, string> commandArgs = new Dictionary<string, string>();
            // We only want to match semi-colons that are not escaped
            foreach (string attStmt in Constants.TAL_ATTRIBUTES_REGEX.Split(argument))
            {
                //  remove any leading space and un-escape any semi-colons
                string attributeStmt = attStmt.TrimStart().Replace(";;", ";");
                // Break each attributeStmt into name and expression
                List<string> stmtBits = new List<string>(attributeStmt.Split(new char[] { ' ' }));
                if (stmtBits.Count < 2)
                {
                    // Error, badly formed attributes command
                    string msg = string.Format("Badly formed attributes command '{0}'.  Attributes commands must be of the form: 'name expression[;name expression]'", argument);
                    throw new TemplateParseException(this.currentStartTag, msg);
                }
                string attName = stmtBits[0];
                string attExpr = string.Join(" ", stmtBits.GetRange(1, stmtBits.Count - 1).ToArray());
                commandArgs.Add(attName, attExpr);
            }
            TALCommand ci = new TALCommand();
            ci.Tag = this.currentStartTag;
            ci.ID = Constants.TAL_ATTRIBUTES;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(commandArgs);
            return ci;
        }
Example #17
0
        protected TALCommand Compile_TAL_CONDITION(string argument)
        {
            // Compile a condition command, resulting argument is:
            // path, endTagSymbol
            // Sanity check
            if (argument.Length == 0)
            {
                // No argument passed
                string msg = "No argument passed!  condition commands must be of the form: 'path'";
                throw new TemplateParseException(this.currentStartTag, msg);
            }

            TALCommand ci = new TALCommand();
            ci.Tag = this.currentStartTag;
            ci.ID = Constants.TAL_CONDITION;
            ci.Attributes = new List<object>();
            ci.Attributes.Add(argument);
            ci.Attributes.Add(this.endTagSymbol);
            return ci;
        }