public void ParseForeachDirective()
        {
            Parser parser = GetNewParser(
                "#foreach($item in $collection)text here#end text");
            TemplateNode templateNode = parser.ParseTemplate();

            // Do semantic checks so the scope is populated
            templateNode.DoSemanticChecks(new ErrorHandler());

            // Check Template
            Assert.AreEqual(2, templateNode.Content.Count);
            Assert.AreEqual(" text", ((XmlTextNode)templateNode.Content[1]).Text);

            // Check NVForeachDirective
            NVForeachDirective foreachDirective = (NVForeachDirective)templateNode.Content[0];

            AssertPosition(new Position(1, 1, 1, 44), foreachDirective.Position);
            Assert.AreEqual("item", foreachDirective.Iterator);
            //TODO: Assert.AreEqual("collection", ((NVDesignatorExpression)foreachDirective.Collection).Designator.Name);

            // Check directive content
            Assert.AreEqual(1, foreachDirective.Content.Count);
            Assert.AreEqual("text here", ((XmlTextNode)foreachDirective.Content[0]).Text);

            // Check iterator variable is only in the foreach scope
            Assert.IsFalse(templateNode.Scope.Exists("item"));
            Assert.IsTrue(foreachDirective.Scope.Exists("item"));

            AssertNoErrors(parser);
        }
Beispiel #2
0
        private void AddNodesToTree(AstNode parentAstNode, TreeNode parentTreeNode)
        {
            if (parentAstNode is TemplateNode)
            {
                // Template Content
                foreach (AstNode node in ((TemplateNode)parentAstNode).Content)
                {
                    AddNodesToTree(node, parentTreeNode);
                }
            }
            else if (parentAstNode is NVBinaryExpression)
            {
                NVBinaryExpression binExpr         = (NVBinaryExpression)parentAstNode;
                TreeNode           binExprTreeNode = new TreeNode(string.Format("NVBinaryExpression={{Op:\"{0}\"}}",
                                                                                binExpr.Op));
                binExprTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(binExprTreeNode);

                AddNodesToTree(binExpr.Lhs, binExprTreeNode);
                AddNodesToTree(binExpr.Rhs, binExprTreeNode);
            }
            else if (parentAstNode is NVBoolExpression)
            {
                TreeNode boolTreeNode = new TreeNode(string.Format("NVBoolExpression={{Value:\"{0}\"}}",
                                                                   ((NVBoolExpression)parentAstNode).Value));
                boolTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(boolTreeNode);
            }
            else if (parentAstNode is NVForeachDirective)
            {
                NVForeachDirective foreachDirective = (NVForeachDirective)parentAstNode;
                TreeNode           foreachTreeNode  = new TreeNode(string.Format("NVForeachDirective={{Iterator:\"{0}\"}}",
                                                                                 foreachDirective.Iterator));
                foreachTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(foreachTreeNode);

                // Content
                foreach (AstNode astNode in foreachDirective.Content)
                {
                    AddNodesToTree(astNode, foreachTreeNode);
                }
            }
            else if (parentAstNode is NVDirective)
            {
                TreeNode directiveTreeNode = new TreeNode(string.Format("NVDirective={{Name:\"{0}\"}}",
                                                                        ((NVDirective)parentAstNode).Name));
                directiveTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(directiveTreeNode);
            }
            else if (parentAstNode is NVNumExpression)
            {
                TreeNode numTreeNode = new TreeNode(string.Format("NVNumExpression={{Value:\"{0}\"}}",
                                                                  ((NVNumExpression)parentAstNode).Value));
                numTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(numTreeNode);
            }
            else if (parentAstNode is NVReference)
            {
                TreeNode referenceTreeNode = new TreeNode(string.Format("NVReference={{Name:\"{0}\"}}",
                                                                        ((NVReference)parentAstNode).Designator.Name));
                referenceTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(referenceTreeNode);

                foreach (NVSelector selector in ((NVReference)parentAstNode).Designator.Selectors)
                {
                    AddNodesToTree(selector, referenceTreeNode);
                }
            }
            else if (parentAstNode is NVSelector)
            {
                NVSelector selector         = (NVSelector)parentAstNode;
                TreeNode   selectorTreeNode = new TreeNode(string.Format("NVSelector={{Name:\"{0}\", Type:\"{1}\"}}",
                                                                         selector.Name, selector.Type != null ? selector.Type.Name : ""));
                selectorTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(selectorTreeNode);

                if (selector.Actuals.Count > 0)
                {
                    TreeNode actualsTreeNode = new TreeNode("Actuals:");
                    foreach (NVExpression actual in selector.Actuals)
                    {
                        AddNodesToTree(actual, actualsTreeNode);
                    }
                    selectorTreeNode.Nodes.Add(actualsTreeNode);
                }
            }
            else if (parentAstNode is NVStringExpression)
            {
                TreeNode stringTreeNode = new TreeNode(string.Format("NVStringExpression={{Value:\"{0}\"}}",
                                                                     ((NVStringExpression)parentAstNode).Value));
                stringTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(stringTreeNode);
            }
            else if (parentAstNode is XmlAttribute)
            {
                TreeNode attributeTreeNode = new TreeNode(string.Format("XmlAttribute={{Name:\"{0}\"}}",
                                                                        ((XmlAttribute)parentAstNode).Name));
                attributeTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(attributeTreeNode);

                // XML Attribute Content
                foreach (AstNode node in ((XmlAttribute)parentAstNode).Content)
                {
                    AddNodesToTree(node, attributeTreeNode);
                }
            }
            else if (parentAstNode is XmlElement)
            {
                XmlElement xmlElement      = (XmlElement)parentAstNode;
                TreeNode   elementTreeNode = new TreeNode(string.Format("XmlElement={{Name:\"{0}\"}}",
                                                                        xmlElement.Name));
                elementTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(elementTreeNode);

                // XML Element Attributes
                TreeNode attributesTreeNode = new TreeNode("Attributes:");
                foreach (AstNode attribute in xmlElement.Attributes)
                {
                    AddNodesToTree(attribute, attributesTreeNode);
                }
                elementTreeNode.Nodes.Add(attributesTreeNode);

                // XML Element Content
                TreeNode contentTreeNode = new TreeNode("Content:");
                foreach (AstNode node in xmlElement.Content)
                {
                    AddNodesToTree(node, contentTreeNode);
                }
                elementTreeNode.Nodes.Add(contentTreeNode);
            }
            else if (parentAstNode is XmlTextNode)
            {
                TreeNode textNodeTreeNode = new TreeNode(string.Format("XmlTextNode={{Text:\"{0}\"}}",
                                                                       ((XmlTextNode)parentAstNode).Text.Replace("\n", "\\n")));
                textNodeTreeNode.Tag = parentAstNode;
                parentTreeNode.Nodes.Add(textNodeTreeNode);
            }
            else
            {
                if (parentAstNode != null)
                {
                    TreeNode treeNode = new TreeNode("UNKNOWN===" + parentAstNode.GetType().Name);
                    treeNode.Tag = parentAstNode;
                    parentTreeNode.Nodes.Add(treeNode);
                }
            }
        }
Beispiel #3
0
        private NVDirective ParseNVRestDirective(Position startPos)
        {
            // NVRestDirective -> "if" "(" NVExpression ")" Content { NVElseIfStatement } [ NVElseStatement ] NVEnd
            //                 -> "set" "(" NVReference "=" NVExpression ")"
            //                 -> "stop"
            //                 -> "foreach" "(" "$" nvIdentifier "in" NVExpression ")" Content NVEnd.
            //                 -> nvDirectiveName [ "(" { nvIdentifier | NVExpression } ")" [ Content NVEnd ] ].

            NVDirective nvDirective;

            if (_scanner.CurrentToken != null && _scanner.CurrentToken.Type == TokenType.NVDirectiveName)
            {
                if (_scanner.CurrentToken.Image == "foreach")
                {
                    nvDirective = new NVForeachDirective();
                }
                else
                {
                    nvDirective = new NVDirective(_scanner.CurrentToken.Image);
                }
                _scanner.GetToken();
            }
            else
            {
                AddError("Expected directive name");
                nvDirective          = new NVDirective("");
                nvDirective.Position = new Position(startPos, GetCurrentTokenPosition());
                return(nvDirective);
            }

            // Match directive parameters
            if (CurrentTokenType == TokenType.NVDirectiveLParen)
            {
                _scanner.GetToken();
                if (nvDirective is NVForeachDirective)
                {
                    MatchToken(TokenType.NVDollar);
                    if (_scanner.CurrentToken != null && _scanner.CurrentToken.Type == TokenType.NVIdentifier)
                    {
                        ((NVForeachDirective)nvDirective).Iterator = _scanner.CurrentToken.Image;
                        _scanner.GetToken();
                    }
                    else
                    {
                        AddError("Foreach variable declaration expected");
                    }

                    MatchToken(TokenType.NVIn);

                    ((NVForeachDirective)nvDirective).Collection = ParseNVExpression();
                }
                else
                {
                    while (!_scanner.EOF && !CurrentTokenIn(TokenType.NVDirectiveRParen, TokenType.NVDirectiveHash))
                    {
                        _scanner.GetToken();

                        // If the tokens are errors break out
                        if (CurrentTokenType == TokenType.Error)
                        {
                            AddError("Unable to parse all directive contents.");
                            break;
                        }
                    }

                    // If a new directive starts in the middle of an unfinished directive params then stop parsing this directive
                    if (CurrentTokenType != TokenType.NVDirectiveRParen)
                    {
                        AddError("Incomplete directive.");

                        nvDirective.Position = new Position(startPos, GetCurrentTokenPosition());
                        return(nvDirective);
                    }
                }
                MatchToken(TokenType.NVDirectiveRParen);
            }

            // Match directive content and #end if required
            if (nvDirective is NVForeachDirective)
            {
                while (!(CurrentTokenType == TokenType.NVDirectiveHash &&
                         _scanner.PeekToken(1) != null &&
                         _scanner.PeekToken(1).Type == TokenType.NVDirectiveName &&
                         _scanner.PeekToken(1).Image == "end"))
                {
                    List <AstNode> content = ParseContent();
                    ((NVForeachDirective)nvDirective).Content.AddRange(content);

                    // If this is the end of the file then return what has been build
                    if (_scanner.EOF)
                    {
                        AddError("Expected #end directive.");
                        nvDirective.Position = new Position(startPos, _scanner.CurrentPos);
                        return(nvDirective);
                    }

                    // Break out of the loop if no content was found because the directive is incomplete
                    if (content.Count == 0)
                    {
                        AddError("The parser has been pre-emptively terminated because it appears " +
                                 "as if the parser is stuck. [In ParseNVForeachDirective()]");
                        break;
                    }
                }

                // Match #end
                MatchToken(TokenType.NVDirectiveHash);
                if (CurrentTokenType == TokenType.NVDirectiveName)
                {
                    if (_scanner.CurrentToken.Image != "end")
                    {
                        AddError("Expected #end directive.");
                    }

                    nvDirective.Position = new Position(startPos, _scanner.CurrentPos);
                    _scanner.GetToken();
                }
                else
                {
                    _scanner.GetToken();
                    nvDirective.Position = new Position(startPos, _scanner.CurrentPos);
                }
            }
            else
            {
                nvDirective.Position = new Position(startPos, GetCurrentTokenPosition());
            }

            return(nvDirective);
        }