private static bool ParseCodeBlock(Stream stream, ShadowClass shadowClass)
        {
            if (stream.Current == '$' && stream.Peek() == '{')
            {
                for (var i = 0; ; i--)
                {
                    var current = stream.Peek(i);
                    if (current == '`' || (current == '/' && stream.Peek(i - 1) == '/'))
                    {
                        return(false);
                    }
                    if (current == '\n' || current == char.MinValue)
                    {
                        break;
                    }
                }

                stream.Advance();

                var block      = stream.PeekBlock(1, '{', '}');
                var codeStream = new Stream(block, stream.Position + 1);

                ParseUsings(codeStream, shadowClass);
                ParseCode(codeStream, shadowClass);

                stream.Advance(block.Length + 1);

                return(true);
            }

            return(false);
        }
        private static bool ParseReference(Stream stream, ShadowClass shadowClass /*, ProjectItem templateProjectItem*/)
        {
            const string keyword = "reference";

            if (stream.Current == '#' && stream.Peek() == keyword[0] && stream.PeekWord(1) == keyword)
            {
                var reference = stream.PeekLine(keyword.Length + 1);
                if (reference != null)
                {
                    var len = reference.Length + keyword.Length + 1;
                    reference = reference.Trim('"', ' ', '\n', '\r');
                    try
                    {
                        /*if (reference.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
                         *  reference = PathResolver.ResolveRelative(reference, templateProjectItem);*/

                        shadowClass.AddReference(reference);
                        return(true);
                    }
                    catch (Exception ex)
                    {
                        //Log.Error("Reference Error: " + ex);
                        Console.WriteLine($"Reference Error: {ex}");
                    }
                    finally
                    {
                        stream.Advance(len - 1);
                    }
                }
            }

            return(false);
        }
        private static bool ParseLambda(Stream stream, ShadowClass shadowClass, Contexts contexts, ref string template)
        {
            if (stream.Current == '$')
            {
                var identifier = stream.PeekWord(1);
                if (identifier != null)
                {
                    var filter = stream.PeekBlock(identifier.Length + 2, '(', ')');
                    if (filter != null && stream.Peek(filter.Length + 2 + identifier.Length + 1) == '[')
                    {
                        try
                        {
                            var index = filter.IndexOf("=>", StringComparison.Ordinal);

                            if (index > 0)
                            {
                                var name = filter.Substring(0, index);

                                var contextName = identifier;
                                // Todo: Make the TemplateCodeParser context aware
                                if (contextName == "TypeArguments")
                                {
                                    contextName = "Types";
                                }
                                else if (contextName.StartsWith("Nested"))
                                {
                                    contextName = contextName.Remove(0, 6);
                                }

                                var type = contexts.Find(contextName)?.Type.FullName;

                                if (type == null)
                                {
                                    return(false);
                                }

                                var methodIndex = _counter++;

                                shadowClass.AddLambda(filter, type, name, methodIndex);

                                stream.Advance(filter.Length + 2 + identifier.Length);
                                template += $"${identifier}($__{methodIndex})";

                                return(true);
                            }
                        }
                        catch
                        {
                            //ignored
                        }
                    }
                }
            }

            return(false);
        }
        private static void ParseUsings(Stream stream, ShadowClass shadowClass)
        {
            stream.Advance();

            while (true)
            {
                stream.SkipWhitespace();

                if ((stream.Current == 'u' && stream.PeekWord() == "using") || (stream.Current == '/' && stream.Peek() == '/'))
                {
                    var line = stream.PeekLine();
                    shadowClass.AddUsing(line, stream.Position);
                    stream.Advance(line.Length);

                    continue;
                }

                break;
            }
        }
        private static void ParseCode(Stream stream, ShadowClass shadowClass)
        {
            var code = new StringBuilder();

            do
            {
                if (stream.Current != char.MinValue)
                {
                    code.Append(stream.Current);
                }
            }while (stream.Advance());

            shadowClass.AddBlock(code.ToString(), 0);
        }
        public static string Parse(/*ProjectItem templateProjectItem, */ string template, List <Type> extensions)
        {
            if (string.IsNullOrWhiteSpace(template))
            {
                return(null);
            }

            var output      = string.Empty;
            var stream      = new Stream(template);
            var shadowClass = new ShadowClass(template);
            var contexts    = new Contexts(shadowClass);

            shadowClass.Clear();

            while (stream.Advance())
            {
                if (ParseReference(stream, shadowClass))
                {
                    continue;
                }
                if (ParseCodeBlock(stream, shadowClass))
                {
                    continue;
                }
                if (ParseLambda(stream, shadowClass, contexts, ref output))
                {
                    continue;
                }
                output += stream.Current;
            }

            shadowClass.Parse();

            extensions.Clear();
            extensions.Add(Compiler.Compile(/*templateProjectItem, */ shadowClass));
            extensions.AddRange(FindExtensionClasses(shadowClass));

            return(output);
        }
示例#7
0
        private bool ParseComment(Stream stream, SemanticModel semanticModel, Stack <Context> context, int depth)
        {
            if (stream.Current == '/')
            {
                var type  = stream.Peek();
                var start = stream.Position;

                if (type == '/')
                {
                    while (stream.Advance())
                    {
                        var length = stream.Position - start;
                        if (ParseDollar(stream, semanticModel, context, depth))
                        {
                            if (length > 0)
                            {
                                semanticModel.Tokens.Add(Classifications.Comment, start, length);
                            }
                            //if (stream.Advance() == false || stream.Current == Constants.NewLine) return true;
                            if (stream.Peek() == char.MinValue)
                            {
                                return(true);
                            }
                            start = stream.Position + 1;
                        }
                        if (stream.Current == Constants.NewLine)
                        {
                            break;
                        }
                    }

                    semanticModel.Tokens.Add(Classifications.Comment, start, stream.Position - start);
                    return(true);
                }

                if (type == '*')
                {
                    while (stream.Advance())
                    {
                        var length = stream.Position - start;

                        if (ParseDollar(stream, semanticModel, context, depth))
                        {
                            if (length > 0)
                            {
                                semanticModel.Tokens.Add(Classifications.Comment, start, length);
                            }
                            //if (stream.Advance() == false || stream.Current == Constants.NewLine) return true;
                            if (stream.Peek() == char.MinValue)
                            {
                                return(true);
                            }
                            start = stream.Position + 1;
                        }

                        if (stream.Current == Constants.NewLine)
                        {
                            semanticModel.Tokens.Add(Classifications.Comment, start, length);
                            if (stream.Advance(2) == false)
                            {
                                return(true);
                            }
                            start = stream.Position;
                        }

                        if (stream.Current == '*' && stream.Peek() == '/')
                        {
                            stream.Advance();
                            semanticModel.Tokens.Add(Classifications.Comment, start, stream.Position + 1 - start);
                            return(true);
                        }
                    }

                    semanticModel.Tokens.Add(Classifications.Comment, start, stream.Position - start);
                    return(true);
                }
            }

            return(false);
        }
示例#8
0
        private bool ParseDollar(Stream stream, SemanticModel semanticModel, Stack <Context> context, int depth)
        {
            if (stream.Current == '$')
            {
                var identifier = GetIdentifier(stream, semanticModel, context);

                if (identifier != null)
                {
                    var classification = GetPropertyClassification(depth);

                    if (identifier.IsParent)
                    {
                        var parent = context.Skip(1).FirstOrDefault()?.Name.ToLowerInvariant();
                        semanticModel.Tokens.Add(classification, stream.Position, identifier.Name.Length + 1, identifier.QuickInfo.Replace("$parent", parent));
                        stream.Advance(identifier.Name.Length);

                        var current = context.Pop();

                        //ParseDot(stream, semanticModel, context, depth); // identifier
                        ParseBlock(stream, semanticModel, context, depth); // template

                        context.Push(current);
                    }
                    else
                    {
                        semanticModel.Tokens.Add(classification, stream.Position, identifier.Name.Length + 1, identifier.QuickInfo);
                        stream.Advance(identifier.Name.Length);

                        if (identifier.IsCollection)
                        {
                            context.Push(_contexts.Find(identifier.Context));

                            ParseFilter(stream, semanticModel, depth);
                            ParseBlock(stream, semanticModel, context, depth); // template

                            context.Pop();

                            ParseBlock(stream, semanticModel, context, depth); // separator
                        }
                        else if (identifier.IsBoolean)
                        {
                            ParseBlock(stream, semanticModel, context, depth); // true
                            ParseBlock(stream, semanticModel, context, depth); // false
                        }
                        else if (identifier.HasContext)
                        {
                            context.Push(_contexts.Find(identifier.Context));

                            //ParseDot(stream, semanticModel, context, depth); // identifier
                            ParseBlock(stream, semanticModel, context, depth); // template

                            context.Pop();
                        }
                    }

                    return(true);
                }
            }

            return(false);
        }