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

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

                        var current = context.Pop();
                        ParseBlock(stream, semanticModel, context); // template
                        context.Push(current);
                    }
                    else
                    {
                        semanticModel.Tokens.Add(Classifications.Property, 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, context);
                            ParseBlock(stream, semanticModel, context); // template

                            context.Pop();

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

                            //ParseDot(stream, SemanticModel, Contexts.Find(identifier.Context), context); // Identifier
                            ParseBlock(stream, semanticModel, context); // template

                            context.Pop();
                        }
                    }

                    return true;
                }
            }

            return false;
        }
示例#2
0
        public void Tokenize(SemanticModel semanticModel, string code)
        {
            var context = new Stack<Context>(new[] { fileContext });
            Parse(code, semanticModel, context, 0);

            if (semanticModel.Tokens.BraceStack.IsBalanced(']') == false)
            {
                semanticModel.ErrorTokens.Add(new Token
                {
                    QuickInfo = "] expected",
                    Start = code.Length,
                    Length = 0
                });
            }
        }
示例#3
0
        private SemanticModel GetSemanticModel(ITextBuffer buffer)
        {
            if (currentSnapshot == buffer.CurrentSnapshot)
                return semanticModelCache;

            currentSnapshot = buffer.CurrentSnapshot;
            semanticModelCache = new SemanticModel(shadowClass);

            var code = currentSnapshot.GetText();

            codeLexer.Tokenize(semanticModelCache, code);
            templateLexer.Tokenize(semanticModelCache, code);
            
            return semanticModelCache;
        }
示例#4
0
        public void Tokenize(SemanticModel semanticModel, string code)
        {
            this.semanticModel = semanticModel;
            context = new Stack<Context>(new[] { fileContext });

            semanticModel.ShadowClass.Clear();

            Parse(code, 0);

            semanticModel.ShadowClass.Parse();
            
            semanticModel.Tokens.AddRange(semanticModel.ShadowClass.GetTokens());
            semanticModel.ErrorTokens.AddRange(semanticModel.ShadowClass.GetErrorTokens());
            semanticModel.TempIdentifiers.Add(semanticModel.ShadowClass.GetIdentifiers(contexts));
        }
示例#5
0
        private void Parse(string template, SemanticModel semanticModel, Stack<Context> context, int offset)
        {
            var stream = new Stream(template, offset);

            do
            {
                if (ParseCodeBlock(stream, semanticModel, context)) continue;
                if (ParseDollar(stream, semanticModel, context)) continue;
                if (ParseString(stream, semanticModel, context)) continue;
                if (ParseComment(stream, semanticModel, context)) continue;
                if (ParseNumber(stream, semanticModel)) continue;
                if (ParseOperators(stream, semanticModel)) continue;
                if (ParseKeywords(stream, semanticModel)) continue;

                semanticModel.Tokens.AddBrace(stream);
            }
            while (stream.Advance());

            var parent = context.Skip(1).FirstOrDefault();
            semanticModel.ContextSpans.Add(context.Peek(), parent, ContextType.Template, offset, stream.Position);
        }
示例#6
0
        private bool ParseCodeBlock(Stream stream, SemanticModel semanticModel, Stack<Context> context)
        {
            if (stream.Current == '$' && stream.Peek() == '{' && context.Peek() == _fileContext)
            {
                semanticModel.Tokens.Add(Classifications.Property, stream.Position);

                stream.Advance();
                semanticModel.Tokens.AddBrace(stream, Classifications.Property);

                var block = stream.PeekBlock(1, '{', '}');
                stream.Advance(block.Length);

                if (stream.Peek() == '}')
                {
                    stream.Advance();
                    semanticModel.Tokens.AddBrace(stream, Classifications.Property);
                }

                return true;
            }

            return false;
        }
示例#7
0
        private Identifier GetIdentifier(Stream stream, SemanticModel semanticModel, Stack<Context> context)
        {
            var word = stream.PeekWord(1);
            if (word == null) return null;

            var c = context.Peek();
            var identifier = semanticModel.GetIdentifier(c, word);

            if (identifier == null)
                return null;

            if (identifier.IsBoolean == false && identifier.IsCollection == false)
                return identifier;

            var next = stream.Peek(identifier.Name.Length + 1);

            if (identifier.IsBoolean && next == '[')
                return identifier;

            if (identifier.IsCollection && (identifier.RequireTemplate == false || next == '[' || (identifier.IsCustom == false && next == '(')))
                return identifier;

            return null;
        }
示例#8
0
        //private void ParseDot(Stream stream, SemanticModel semanticModel, Stack<Context> context, int depth)
        //{
        //    if (stream.Peek() == '.')
        //    {
        //        stream.Advance();
        //        var identifier = GetIdentifier(stream, semanticModel, context);
        //        if (identifier != null)
        //        {
        //            var classification = GetPropertyClassification(depth);
        //            var parent = context.Skip(1).FirstOrDefault();
        //            semanticModel.Tokens.Add(classification, stream.Position);
        //            semanticModel.ContextSpans.Add(context.Peek(), parent, ContextType.Template, stream.Position, stream.Position + 1);
        //            if (identifier.IsParent)
        //            {
        //                semanticModel.Tokens.Add(classification, stream.Position + 1, identifier.Name.Length, identifier.QuickInfo.Replace("$parent", parent?.Name.ToLowerInvariant()));
        //                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 + 1, identifier.Name.Length, identifier.QuickInfo);
        //                stream.Advance(identifier.Name.Length);
        //                if (identifier.IsCollection)
        //                {
        //                    context.Push(_contexts.Find(identifier.Context));
        //                    ParseFilter(stream, semanticModel, context, 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();
        //                }
        //            }
        //        }
        //    }
        //}
        private void ParseBlock(Stream stream, SemanticModel semanticModel, Stack<Context> context, int depth)
        {
            if (stream.Peek() == '[')
            {
                stream.Advance();
                var classification = GetPropertyClassification(depth);

                semanticModel.Tokens.AddBrace(stream, classification);

                var block = stream.PeekBlock(1, '[', ']');
                Parse(block, semanticModel, context, stream.Position + 1, depth + 1);
                stream.Advance(block.Length);

                if (stream.Peek() == ']')
                {
                    stream.Advance();
                    semanticModel.Tokens.AddBrace(stream, classification);
                }
            }
        }
示例#9
0
        private bool ParseString(Stream stream, SemanticModel semanticModel, Stack<Context> context, int depth)
        {
            if (stream.Current == '\'' || stream.Current == '"')
            {
                var start = stream.Position;
                var open = stream.Current;

                while (stream.Advance())
                {
                    var length = stream.Position - start;
                    if (ParseDollar(stream, semanticModel, context, depth))
                    {
                        semanticModel.Tokens.Add(Classifications.String, start, length);
                        if (stream.Advance() == false || stream.Current == Constants.NewLine) return true;
                        start = stream.Position;
                    }

                    if (stream.Current == open)
                    {
                        if (stream.Peek(-1) != '\\')
                        {
                            semanticModel.Tokens.Add(Classifications.String, start, stream.Position + 1 - start);
                            return true;
                        }
                    }
                }

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

            return false;
        }
示例#10
0
        private bool ParseSymbols(Stream stream, SemanticModel semanticModel)
        {
            if (_isSymbol && stream.Position > _objectLiteralEnds)
            {
                var name = stream.PeekWord();
                if (name == null) return false;

                semanticModel.Tokens.Add(Classifications.ClassSymbol, stream.Position, name.Length);
                stream.Advance(name.Length - 1);

                return true;
            }

            return false;
        }
示例#11
0
        private bool ParseNumber(Stream stream, SemanticModel semanticModel)
        {
            if (char.IsDigit(stream.Current) || (stream.Current == '.' && char.IsDigit(stream.Peek())))
            {
                var start = stream.Position;

                do
                {
                    if (char.IsDigit(stream.Peek()) == false && (stream.Peek() == '.' && char.IsDigit(stream.Peek(2))) == false)
                        break;
                }
                while (stream.Advance());

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

            return false;
        }
示例#12
0
        private bool ParseOperators(Stream stream, SemanticModel semanticModel)
        {
            if (_operators.Contains(stream.Current))
            {
                semanticModel.Tokens.Add(Classifications.Operator, stream.Position);

                if (stream.Current == ':')
                {
                    while (stream.Peek() == ' ') stream.Advance();
                    _isSymbol = true;
                }
                return true;
            }

            return false;
        }
示例#13
0
        private bool ParseKeywords(Stream stream, SemanticModel semanticModel)
        {
            var peek = stream.Peek(-1);

            if (char.IsLetterOrDigit(peek) == false && peek != '.')
            {
                var name = stream.PeekWord();

                if (name != null && _keywords.Contains(name))
                {
                    semanticModel.Tokens.Add(Classifications.Keyword, stream.Position, name.Length);
                    stream.Advance(name.Length - 1);

                    if (_symbolKeywords.Contains(name))
                    {
                        while (stream.Peek() == ' ') stream.Advance();
                        _isSymbol = true;
                    }

                    return true;
                }
            }

            return false;
        }
示例#14
0
        private void ParseFilter(Stream stream, SemanticModel semanticModel, Stack<Context> context, int depth)
        {
            if (stream.Peek() == '(')
            {
                stream.Advance();
                var classification = GetPropertyClassification(depth);

                semanticModel.Tokens.AddBrace(stream, classification);

                var block = stream.PeekBlock(1, '(', ')');

                if (block.Contains("=>") == false)
                    semanticModel.Tokens.Add(Classifications.String, stream.Position + 1, block.Length);

                stream.Advance(block.Length);

                if (stream.Peek() == ')')
                {
                    stream.Advance();
                    semanticModel.Tokens.AddBrace(stream, classification);
                }
            }
        }
示例#15
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;
        }
示例#16
0
        private bool ParseOperators(Stream stream, SemanticModel semanticModel)
        {
            if (operators.Contains(stream.Current))
            {
                semanticModel.Tokens.Add(Classifications.Operator, stream.Position);
                return true;
            }

            return false;
        }
示例#17
0
        private bool ParseKeywords(Stream stream, SemanticModel semanticModel)
        {
            var name = stream.PeekWord();

            if (name == null) return false;

            if (keywords.Contains(name))
            {
                semanticModel.Tokens.Add(Classifications.Keyword, stream.Position, name.Length);
            }

            stream.Advance(name.Length - 1);
            return true;
        }