コード例 #1
0
ファイル: DefaultFluidParser.cs プロジェクト: ifle/fluid
        public bool TryParse(string template, out IList <Statement> result, out IEnumerable <string> errors)
        {
            errors = Array.Empty <string>();
            var    segment = new StringSegment(template);
            Parser parser  = null;

            _context = new ParserContext();
            result   = _context.CurrentBlock.Statements;

            try
            {
                bool trimBefore = false;
                bool trimAfter  = false;

                int       previous = 0, index = 0;
                Statement s;

                while (true)
                {
                    previous = index;

                    if (!MatchTag(segment, index, out var start, out var end))
                    {
                        index = segment.Length;

                        if (index != previous)
                        {
                            // Consume last Text statement
                            ConsumeTextStatement(segment, previous, index, trimAfter, false);
                        }

                        break;
                    }
                    else
                    {
                        trimBefore = segment.Buffer[start + 2] == '-';

                        // Only create a parser if there are tags in the template
                        if (parser == null)
                        {
                            parser = new Parser(_languageData);
                        }

                        if (start != previous)
                        {
                            // Consume current Text statement
                            ConsumeTextStatement(segment, previous, start, trimAfter, trimBefore);
                        }

                        trimAfter = segment.Buffer[end - 2] == '-';

                        var tag = segment.Substring(start, end - start + 1);

                        if (trimAfter || trimBefore)
                        {
                            // Remove the dashes for the parser

                            StringBuilder sb = new StringBuilder(tag);

                            if (trimBefore)
                            {
                                sb[2] = ' ';
                            }

                            if (trimAfter)
                            {
                                sb[end - start - 2] = ' ';
                            }

                            tag = sb.ToString();
                        }

                        var tree = parser.Parse(tag);

                        if (tree.HasErrors())
                        {
                            errors = tree
                                     .ParserMessages
                                     .Select(x => $"{x.Message} at line:{x.Location.Line}, col:{x.Location.Column}")
                                     .ToArray();

                            return(false);
                        }

                        switch (tree.Root.Term.Name)
                        {
                        case "output":
                            s = BuildOutputStatement(tree.Root);
                            break;

                        case "tag":
                            s = BuildTagStatement(tree.Root);
                            break;

                        default:
                            s = null;
                            break;
                        }

                        if (s != null)
                        {
                            _context.CurrentBlock.AddStatement(s);
                        }

                        index = end + 1;
                    }
                }
コード例 #2
0
        public bool TryParse(string template, bool stripEmptyLines, out List <Statement> result, out IEnumerable <string> errors)
        {
            errors = Array.Empty <string>();
            var    segment = new StringSegment(template);
            Parser parser  = null;

            _context = new ParserContext();
            result   = _context.CurrentBlock.Statements;

            try
            {
                bool trimBefore = false;
                bool trimAfter  = false;

                int       previous = 0, index = 0;
                Statement s;

                while (true)
                {
                    previous = index;

                    if (!MatchTag(segment, index, out var start, out var end))
                    {
                        index = segment.Length;

                        if (index != previous)
                        {
                            // Consume last Text statement
                            ConsumeTextStatement(segment, previous, index, trimAfter, false, stripEmptyLines);
                        }

                        break;
                    }
                    else
                    {
                        trimBefore = segment.Index(start + 2) == '-';

                        // Only create a parser if there are tags in the template
                        if (parser == null)
                        {
                            parser = new Parser(_languageData);
                        }

                        if (start != previous)
                        {
                            // Consume current Text statement
                            ConsumeTextStatement(segment, previous, start, trimAfter, trimBefore, stripEmptyLines);
                        }

                        trimAfter = segment.Index(end - 2) == '-';

                        var tag = segment.Subsegment(start, end - start + 1).ToString();

                        if (trimAfter || trimBefore)
                        {
                            // Remove the dashes for the parser

                            StringBuilder sb = new StringBuilder(tag);

                            if (trimBefore)
                            {
                                sb[2] = ' ';
                            }

                            if (trimAfter)
                            {
                                sb[end - start - 2] = ' ';
                            }

                            tag = sb.ToString();
                        }

                        var tree = parser.Parse(tag);

                        if (tree.HasErrors())
                        {
                            int line = 1, col = 1;

                            for (var i = segment.Offset; i < start; i++)
                            {
                                var ch = segment.Index(i);

                                switch (ch)
                                {
                                case '\n':
                                    line++;
                                    col = 1;
                                    break;

                                case '\r':
                                    // Ignore
                                    break;

                                default:
                                    col++;
                                    break;
                                }
                            }
                            errors = tree
                                     .ParserMessages
                                     .Select(x => $"{x.Message} at line:{line + x.Location.Line}, col:{col + x.Location.Column}")
                                     .ToArray();

                            return(false);
                        }

                        switch (tree.Root.Term.Name)
                        {
                        case "output":
                            s = BuildOutputStatement(tree.Root);
                            break;

                        case "tag":
                            s = BuildTagStatement(tree.Root);
                            break;

                        default:
                            s = null;
                            break;
                        }

                        index = end + 1;

                        // Entered a comment block?
                        if (_isComment)
                        {
                            s     = new CommentStatement(ConsumeTag(segment, end + 1, "endcomment", out end));
                            index = end;
                        }

                        // Entered a raw block?
                        if (_isRaw)
                        {
                            s     = new TextStatement(ConsumeTag(segment, end + 1, "endraw", out end));
                            index = end;
                        }

                        if (s != null)
                        {
                            _context.CurrentBlock.AddStatement(s);
                        }
                    }
                }