コード例 #1
0
        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);
        }
コード例 #2
0
ファイル: Tokens.cs プロジェクト: ChinaJason/Typewriter
        internal void AddBrace(Stream stream, string classification = Classifications.Operator)
        {
            var brace = stream.Current;

            if (brace == '{' || brace == '[' || brace == '(' || brace == ')' || brace == ']' || brace == '}')
            {
                var token = new Token { Classification = classification, Start = stream.Position, Length = 1 };

                if (brace == '{' || brace == '[' || brace == '(')
                {
                    token.IsOpen = true;
                    braces.Push(token, stream.Current);
                }
                else
                {
                    var match = braces.Pop(brace);
                    if (match != null)
                    {
                        token.MatchingToken = match;
                        match.MatchingToken = token;
                    }
                }

                Add(token);
            }
        }
コード例 #3
0
        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);
                    }
                    finally
                    {
                        stream.Advance(len - 1);
                    }
                }
            }

            return(false);
        }
コード例 #4
0
        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", StringComparison.OrdinalIgnoreCase))
                                {
                                    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
                        {
                        }
                    }
                }
            }

            return(false);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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;
            }
        }
コード例 #7
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();
            var contexts    = new Contexts(shadowClass);

            shadowClass.Clear();

            while (stream.Advance())
            {
                if (ParseReference(stream, shadowClass, templateProjectItem))
                {
                    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);
        }