Beispiel #1
0
        static CodeCommentStatement _ParseCommentStatement(_PC pc, bool docComments = false)
        {
            var s = pc.Value;

            switch (pc.SymbolId)
            {
            case ST.lineComment:
                pc.Advance(false);
                if (docComments && s.StartsWith("///", StringComparison.InvariantCulture))
                {
                    if (3 < s.Length && char.IsWhiteSpace(s[3]))
                    {
                        return(new CodeCommentStatement(s.Substring(4).TrimEnd('\r'), true));
                    }
                    return(new CodeCommentStatement(s.Substring(3).TrimEnd('\r'), true));
                }
                if (2 < s.Length && char.IsWhiteSpace(s[2]))
                {
                    return(new CodeCommentStatement(s.Substring(3).TrimEnd('\r')));
                }
                return(new CodeCommentStatement(s.Substring(2).TrimEnd('\r')));

            case ST.blockComment:
                pc.Advance(false);
                return(new CodeCommentStatement(s.Substring(2, s.Length - 4)));
            }
            pc.Error("Expecting line comment or block comment");
            return(null);
        }
Beispiel #2
0
        static CodeNamespaceImportCollection _ParseNamespaceImports(_PC pc)
        {
            var result = new CodeNamespaceImportCollection();

            while (ST.keyword == pc.SymbolId && "using" == pc.Value)
            {
                pc.Advance();
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated using declaration", "input");
                }
                if (ST.identifier != pc.SymbolId)
                {
                    throw new ArgumentException("Expecting identifier in using declaration", "input");
                }
                var ns = _ParseNamespaceName(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated using declaration", "input");
                }
                if (ST.semi != pc.SymbolId)
                {
                    throw new ArgumentException("Expecting ; in using declaration", "input");
                }
                pc.Advance();
                _SkipComments(pc);
                result.Add(new CodeNamespaceImport(ns));
            }
            return(result);
        }
        static CodeGotoStatement _ParseGotoStatement(_PC pc)
        {
            // expects to be on goto.
            pc.Advance();
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated goto statement", "input");
            }
            if (ST.identifier != pc.SymbolId)
            {
                throw new ArgumentException("Expecting identifier in goto statement", "input");
            }
            var g = new CodeGotoStatement(pc.Value);

            pc.Advance();
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated goto statement", "input");
            }
            if (ST.semi != pc.SymbolId)
            {
                throw new ArgumentException("Expecting ; after goto statement", "input");
            }
            pc.Advance();
            return(g);
        }
Beispiel #4
0
        static CodeStatement _ParseVariableDeclarationStatement(_PC pc)
        {
            var l = pc.Line;
            var c = pc.Column;
            var p = pc.Position;
            CodeTypeReference ctr = null;

            if (ST.varType != pc.SymbolId)
            {
                ctr = _ParseType(pc);
            }
            else
            {
                pc.Advance();
            }
            var            id   = _ParseIdentifier(pc);
            CodeExpression init = null;

            if (ST.eq == pc.SymbolId)
            {
                pc.Advance();
                init = _ParseExpression(pc);
            }
            else if (null == ctr)
            {
                pc.Error("Variable declaration using var must have an initializer", l, c, p);
            }
            if (ST.semi != pc.SymbolId)
            {
                pc.Error("Expecting ; in variable declaration statement");
            }
            pc.Advance();
            return(new CodeVariableDeclarationStatement(ctr, id, init).Mark(l, c, p, null == ctr));
        }
        static CodeIterationStatement _ParseWhileStatement(_PC pc)
        {
            // expects to be on while.
            if (!pc.Advance())
            {
                throw new ArgumentException("Unterminated while statement", "input");
            }
            _SkipComments(pc);
            if (ST.lparen != pc.SymbolId || !pc.Advance())
            {
                throw new ArgumentException("Unterminated while statement", "input");
            }
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated while statement", "input");
            }
            var cnd = _ParseExpression(pc);

            _SkipComments(pc);
            if (ST.rparen != pc.SymbolId || !pc.Advance())
            {
                throw new ArgumentException("Unterminated while statement", "input");
            }
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated while statement", "input");
            }
            var result = new CodeIterationStatement(new CodeSnippetStatement(), cnd, new CodeSnippetStatement());

            if (ST.lbrace == pc.SymbolId)
            {
                if (!pc.Advance())
                {
                    throw new ArgumentException("Unterminated while statement", "input");
                }
                while (!pc.IsEnded && ST.rbrace != pc.SymbolId)
                {
                    result.Statements.Add(_ParseStatement(pc, true));
                }
                if (ST.rbrace != pc.SymbolId)
                {
                    throw new ArgumentException("Unterminated while statement", "input");
                }
                pc.Advance();
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    return(result);
                }
            }
            else
            {
                result.Statements.Add(_ParseStatement(pc));
            }

            _SkipComments(pc);
            return(result);
        }
        static CodeThrowExceptionStatement _ParseThrowStatement(_PC pc)
        {
            // expects to be on throw
            pc.Advance();
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated throw statement", "input");
            }
            if (ST.semi == pc.SymbolId)
            {
                pc.Advance();
                return(new CodeThrowExceptionStatement());
            }
            var e = _ParseExpression(pc);

            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated throw statement", "input");
            }
            if (ST.semi != pc.SymbolId)
            {
                throw new ArgumentException("Invalid expression in throw statement", "input");
            }
            pc.Advance();
            return(new CodeThrowExceptionStatement(e));
        }
Beispiel #7
0
        static CodeStatement _ParseWhileStatement(_PC pc)
        {
            var l = pc.Line;
            var c = pc.Column;
            var p = pc.Position;

            if (ST.whileKeyword != pc.SymbolId)
            {
                pc.Error("Expecting while");
            }
            pc.Advance();
            if (ST.lparen != pc.SymbolId)
            {
                pc.Error("Expecting ( in while statement");
            }
            pc.Advance();
            var test = _ParseExpression(pc);

            if (ST.rparen != pc.SymbolId)
            {
                pc.Error("Expecting ) in while statement");
            }
            pc.Advance();
            var result = new CodeIterationStatement(new CodeSnippetStatement().SetLoc(l, c, p), test, new CodeSnippetStatement().SetLoc(l, c, p)).Mark(l, c, p);

            result.Statements.AddRange(_ParseStatementOrBlock(pc));
            return(result);
        }
Beispiel #8
0
 static CodeTypeReference _ParseTypeGenerics(_PC pc, CodeTypeReference result = null)
 {
     _SkipComments(pc);
     if (null == result)
     {
         result = new CodeTypeReference();
     }
     //result.UserData["slang:unresolved"] = true;
     while (ST.gt != pc.SymbolId)
     {
         _SkipComments(pc);
         if (!pc.Advance())
         {
             throw new ArgumentException("Unterminated generic specification", "input");
         }
         _SkipComments(pc);
         var tp = _ParseTypeRef(pc);
         tp.Options = CodeTypeReferenceOptions.GenericTypeParameter;
         result.TypeArguments.Add(tp);
         if (ST.gt != pc.SymbolId && ST.comma != pc.SymbolId)
         {
             throw new ArgumentException("Invalid token in generic specification", "input");
         }
     }
     if (ST.gt != pc.SymbolId)
     {
         throw new ArgumentException("Unterminated generic specification", "input");
     }
     _SkipComments(pc);
     pc.Advance();
     return(result);
 }
Beispiel #9
0
        static CodeMemberField _ParseEnumField(_PC pc, CodeTypeReference enumType)
        {
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Expecting enum field declaration", "input");
            }
            IList <KeyValuePair <string, CodeAttributeDeclaration> > custAttrs = null;

            if (ST.lbracket == pc.SymbolId)
            {
                custAttrs = _ParseCustomAttributes(pc);
            }
            _SkipComments(pc);
            if (pc.IsEnded || ST.identifier != pc.SymbolId)
            {
                throw new ArgumentException("Expecting enum field declaration", "input");
            }
            var result = new CodeMemberField();

            result.Name = pc.Value;
            _AddCustomAttributes(custAttrs, null, result.CustomAttributes);
            _AddCustomAttributes(custAttrs, "field", result.CustomAttributes);
            if (null != custAttrs && custAttrs.Count > result.CustomAttributes.Count)
            {
                throw new ArgumentException("Invalid custom attribute targets", "input");
            }
            pc.Advance();
            _SkipComments(pc);
            if (pc.IsEnded || (ST.eq != pc.SymbolId && ST.comma != pc.SymbolId && ST.rbrace != pc.SymbolId))
            {
                throw new ArgumentException("Expecting enum field value, }, or ,", "input");
            }
            if (ST.eq == pc.SymbolId)
            {
                pc.Advance();
                _SkipComments(pc);

                if (pc.IsEnded)
                {
                    throw new ArgumentException("Expecting enum field value", "input");
                }
                result.InitExpression = _ParseExpression(pc);
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Expecting , or } in enum declaration", "input");
                }
            }
            if (ST.comma == pc.SymbolId)
            {
                pc.Advance();
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Expecting enum field value", "input");
                }
            }
            return(result);
        }
Beispiel #10
0
        static CodeStatement _ParseIfStatement(_PC pc)
        {
            var l = pc.Line;
            var c = pc.Column;
            var p = pc.Position;

            if (ST.ifKeyword != pc.SymbolId)
            {
                pc.Error("Expecting if");
            }
            pc.Advance();
            if (ST.lparen != pc.SymbolId)
            {
                pc.Error("Expecting ( in if statement");
            }
            pc.Advance();
            var test = _ParseExpression(pc);

            if (ST.rparen != pc.SymbolId)
            {
                pc.Error("Expecting ) in if statement");
            }
            pc.Advance();
            var result = new CodeConditionStatement(test).Mark(l, c, p);

            result.TrueStatements.AddRange(_ParseStatementOrBlock(pc));
            if (ST.elseKeyword == pc.SymbolId)
            {
                pc.Advance();
                result.FalseStatements.AddRange(_ParseStatementOrBlock(pc));
            }
            return(result);
        }
Beispiel #11
0
        static CodeAttributeArgumentCollection _ParseCustomAttributeArguments(_PC pc)
        {
            var result = new CodeAttributeArgumentCollection();

            if (ST.lparen != pc.SymbolId)
            {
                return(result);
            }
            if (!pc.Advance())
            {
                throw new ArgumentException("Unterminated argument list", "input");
            }
            var named = false;

            while (ST.rparen != pc.SymbolId)
            {
                var arg = new CodeAttributeArgument();
                if (ST.identifier == pc.SymbolId)
                {
                    var s   = pc.Value;
                    var pc2 = pc.GetLookAhead();
                    pc2.EnsureStarted();
                    pc2.Advance();
                    _SkipComments(pc2);
                    if (ST.eq == pc2.SymbolId)
                    {
                        pc.Advance();
                        _SkipComments(pc);
                        pc.Advance();
                        arg.Name  = s;
                        arg.Value = _ParseExpression(pc);
                        result.Add(arg);
                        named = true;
                        continue;
                    }
                }
                if (named)
                {
                    throw new ArgumentException("Named custom attribute arguments must follow the unnamed arguments.", "input");
                }
                var exp = _ParseExpression(pc);
                _SkipComments(pc);
                arg.Value = exp;
                result.Add(arg);
                if (ST.comma == pc.SymbolId)
                {
                    if (!pc.Advance())
                    {
                        throw new ArgumentException("Unterminated argument list.", "input");
                    }
                }
            }
            if (ST.rparen != pc.SymbolId)
            {
                throw new ArgumentException("Unterminated argument list.", "input");
            }
            pc.Advance();
            return(result);
        }
Beispiel #12
0
        static CodeStatement _ParseForStatement(_PC pc)
        {
            var l = pc.Line;
            var c = pc.Column;
            var p = pc.Position;

            if (ST.forKeyword != pc.SymbolId)
            {
                pc.Error("Expecting for");
            }
            pc.Advance();
            if (ST.lparen != pc.SymbolId)
            {
                pc.Error("Expecting ( in for statement");
            }
            pc.Advance();
            var init = _ParseStatement(pc, false);
            var test = _ParseExpression(pc);

            if (ST.semi != pc.SymbolId)
            {
                pc.Error("Expecting ; in for statement");
            }
            pc.Advance();
            CodeStatement  inc  = null;
            CodeExpression ince = null;

            if (ST.rparen != pc.SymbolId)
            {
                ince = _ParseExpression(pc);
            }
            if (ST.rparen != pc.SymbolId)
            {
                pc.Error("Expecting ) in for statement");
            }
            if (null == ince)
            {
                inc = new CodeSnippetStatement().SetLoc(pc);
            }
            else
            {
                var bo = ince as CodeBinaryOperatorExpression;
                if (null != bo && CodeBinaryOperatorType.Assign == bo.Operator)
                {
                    // probably not an attach or detach statement but we can't rule it out
                    var ur = bo.UserData.Contains("slang:unresolved");
                    inc = new CodeAssignStatement(bo.Left, bo.Right).Mark(ince, ur);
                }
                else
                {
                    inc = new CodeExpressionStatement(ince).Mark(ince);
                }
            }
            pc.Advance();
            var result = new CodeIterationStatement(init, test, inc).Mark(l, c, p);

            result.Statements.AddRange(_ParseStatementOrBlock(pc));
            return(result);
        }
Beispiel #13
0
        // these aren't true expressions, they're just part of method and indexer parameter declarations
        // that's why we parse them here
        static CodeParameterDeclarationExpression _ParseParamDecl(_PC pc, bool allowDirection = true)
        {
            var attrs = new CodeAttributeDeclarationCollection();

            if (ST.lbracket == pc.SymbolId)
            {
                _AddCustomAttributes(_ParseCustomAttributes(pc), null, attrs);
            }
            FieldDirection d = FieldDirection.In;

            _SkipComments(pc);
            if (allowDirection)
            {
                if (ST.keyword == pc.SymbolId)
                {
                    switch (pc.Value)
                    {
                    case "out":
                        d = FieldDirection.Out;
                        pc.Advance();
                        _SkipComments(pc);
                        break;

                    case "ref":
                        d = FieldDirection.Ref;
                        pc.Advance();
                        _SkipComments(pc);
                        break;

                    default:
                        break;
                    }
                }
            }
            var ctr = _ParseTypeRef(pc);

            _SkipComments(pc);
            if (ST.identifier != pc.SymbolId)
            {
                throw new ArgumentException("Expecting identifier in parameter declaration", "input");
            }
            var result = new CodeParameterDeclarationExpression(ctr, pc.Value);

            result.Direction = d;
            if (null != attrs)
            {
                result.CustomAttributes.AddRange(attrs);
            }
            pc.Advance();
            return(result);
        }
Beispiel #14
0
        static CodeTypeReference _ParseArrayTypeModifiers(CodeTypeReference type, _PC pc)
        {
            var mods   = new List <int>();
            var result = type;

            _SkipComments(pc);
            var t       = pc.Current;
            var ai      = 1;
            var inBrace = true;

            while (pc.Advance())
            {
                _SkipComments(pc);
                t = pc.Current;
                if (inBrace && ST.comma == t.SymbolId)
                {
                    ++ai;
                    continue;
                }
                else if (ST.rbracket == t.SymbolId)
                {
                    mods.Add(ai);
                    ai = 1;
                    if (!pc.Advance())
                    {
                        break;
                    }
                    inBrace = false;
                    if (ST.lbracket != pc.SymbolId)
                    {
                        break;
                    }
                    else
                    {
                        inBrace = true;
                    }
                }
                else
                {
                    break;
                }
            }
            for (var i = mods.Count - 1; -1 < i; --i)
            {
                var ctr = new CodeTypeReference();
                ctr.ArrayElementType = result;
                ctr.ArrayRank        = mods[i];
                result = ctr;
            }
            return(result);
        }
Beispiel #15
0
        internal static CodeStatement ParseStatement(IEnumerable <Token> tokenizer, bool includeComments = false)
        {
            var pc = new _PC(tokenizer);

            pc.Advance(false);
            return(_ParseStatement(pc, includeComments));
        }
        internal static CodeCompileUnit ParseCompileUnit(IEnumerable <Token> tokenizer)
        {
            var pc = new _PC(tokenizer);

            pc.Advance(false);
            return(_ParseCompileUnit(pc));
        }
Beispiel #17
0
        static HashSet <string> _ParseTypeAttributes(_PC pc)
        {
            var result = new HashSet <string>();

            _SkipComments(pc);
            var more = true;

            while (more && !pc.IsEnded && ST.keyword == pc.SymbolId)
            {
                switch (pc.Value)
                {
                case "static":
                case "abstract":
                case "protected":
                case "internal":
                case "public":
                case "private":
                    result.Add(pc.Value);
                    pc.Advance();
                    _SkipComments(pc);
                    break;

                default:
                    more = false;
                    break;
                }
            }
            return(result);
        }
        static CodeCommentStatement _ParseCommentStatement(_PC pc)
        {
            // expects to be on comment
            var s = pc.Value;

            if (ST.lineComment == pc.SymbolId)
            {
                pc.Advance();
                if (s.StartsWith("///"))
                {
                    return(new CodeCommentStatement(s.Substring(3).Trim(), true));
                }
                return(new CodeCommentStatement(s.Substring(2).Trim()));
            }
            pc.Advance();
            return(new CodeCommentStatement(s.Substring(2, s.Length - 4).Trim()));
        }
        static void _SkipComments(_PC pc)
        {
            Token t;

            while ((ST.blockComment == (t = pc.Current).SymbolId ||
                    ST.lineComment == t.SymbolId) && pc.Advance())
            {
                ;
            }
        }
Beispiel #20
0
        static CodeTypeDeclaration _ParseEnum(_PC pc, CodeTypeDeclaration result)
        {
            var bt = new CodeTypeReference(typeof(int));

            if (ST.colon == pc.SymbolId)
            {
                pc.Advance();
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated enum declaration", "input");
                }
                bt = _ParseTypeRef(pc);
                result.BaseTypes.Add(bt);
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated enum declaration", "input");
                }
            }
            if (ST.lbrace != pc.SymbolId)
            {
                throw new ArgumentException("Expecting enum body", "input");
            }
            pc.Advance();
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated enum declaration", "input");
            }
            while (ST.rbrace != pc.SymbolId)
            {
                _SkipComments(pc);
                result.Members.Add(_ParseEnumField(pc, bt));
            }
            if (ST.rbrace != pc.SymbolId)
            {
                throw new ArgumentException("Unterminated enum declaration", "input");
            }
            pc.Advance();
            return(result);
        }
Beispiel #21
0
        static CodeParameterDeclarationExpressionCollection _ParseParamDecls(_PC pc, int endSym = ST.rparen, bool allowDirection = true)
        {
            var result = new CodeParameterDeclarationExpressionCollection();

            while (!pc.IsEnded && endSym != pc.SymbolId)
            {
                var p = _ParseParamDecl(pc, allowDirection);
                result.Add(p);
                if (ST.comma != pc.SymbolId)
                {
                    break;
                }
                pc.Advance();
                _SkipComments(pc);
            }
            if (endSym != pc.SymbolId)
            {
                throw new ArgumentException("Unterminated parameter declarations", "input");
            }
            pc.Advance();
            return(result);
        }
Beispiel #22
0
        static CodeStatementCollection _ParseStatementOrBlock(_PC pc)
        {
            var l = pc.Line;
            var c = pc.Column;
            var p = pc.Position;
            CodeStatementCollection result;

            if (ST.lbrace == pc.SymbolId)
            {
                pc.Advance();
                result = _ParseStatements(pc, true);
                if (ST.rbrace != pc.SymbolId)
                {
                    pc.Error("Unterminated statement block", l, c, p);
                }
                pc.Advance();
                return(result);
            }
            result = new CodeStatementCollection();
            result.Add(_ParseStatement(pc, false));
            return(result);
        }
Beispiel #23
0
        internal static CodeStatementCollection ParseStatements(IEnumerable <Token> tokenizer, bool includeComments = false)
        {
            var pc = new _PC(tokenizer);

            pc.Advance(false);
            var result = new CodeStatementCollection();

            while (!pc.IsEnded && ST.rbrace != pc.SymbolId)
            {
                result.Add(_ParseStatement(pc, includeComments));
            }
            return(result);
        }
Beispiel #24
0
        static CodeCatchClause _ParseCatchClause(_PC pc)
        {
            if (ST.catchKeyword != pc.SymbolId)
            {
                pc.Error("Expecting catch");
            }
            pc.Advance();
            if (ST.lparen != pc.SymbolId)
            {
                pc.Error("Expecting ( in catch clause");
            }
            pc.Advance();
            var result = new CodeCatchClause();

            result.CatchExceptionType = _ParseType(pc);
            if (ST.rparen != pc.SymbolId)
            {
                result.LocalName = _ParseIdentifier(pc);
            }
            if (ST.rparen != pc.SymbolId)
            {
                pc.Error("Expecting ) in catch clause");
            }
            pc.Advance();
            if (ST.lbrace != pc.SymbolId)
            {
                pc.Error("Expecting { in catch clause");
            }
            pc.Advance();
            result.Statements.AddRange(_ParseStatements(pc, true));
            if (ST.rbrace != pc.SymbolId)
            {
                pc.Error("Expecting } in catch clause");
            }
            pc.Advance();
            return(result);
        }
Beispiel #25
0
        static string _ParseNamespaceName(_PC pc)
        {
            var result = "";

            while (ST.identifier == pc.SymbolId)
            {
                if (0 < result.Length)
                {
                    result = string.Concat(result, ".", pc.Value);
                }
                else
                {
                    result = pc.Value;
                }
                pc.Advance();
                _SkipComments(pc);
                if (ST.dot == pc.SymbolId)
                {
                    pc.Advance();
                    _SkipComments(pc);
                }
            }
            return(result);
        }
Beispiel #26
0
        static CodeStatement _ParseTryCatchFinallyStatement(_PC pc)
        {
            var l = pc.Line;
            var c = pc.Column;
            var p = pc.Position;

            if (ST.tryKeyword != pc.SymbolId)
            {
                pc.Error("Expecting try");
            }
            pc.Advance();
            var result = new CodeTryCatchFinallyStatement().Mark(l, c, p);

            if (ST.lbrace != pc.SymbolId)
            {
                pc.Error("Expecting { in try statement");
            }
            pc.Advance();
            result.TryStatements.AddRange(_ParseStatements(pc, true));
            if (ST.rbrace != pc.SymbolId)
            {
                pc.Error("Expecting } in try statement");
            }
            pc.Advance();
            while (ST.catchKeyword == pc.SymbolId)
            {
                result.CatchClauses.Add(_ParseCatchClause(pc));
            }
            if (0 == result.CatchClauses.Count && ST.finallyKeyword != pc.SymbolId)
            {
                pc.Error("Expecting catch or finally");
            }
            if (ST.finallyKeyword == pc.SymbolId)
            {
                pc.Advance();
                if (ST.lbrace != pc.SymbolId)
                {
                    pc.Error("Expecting { in finally statement");
                }
                pc.Advance();
                result.FinallyStatements.AddRange(_ParseStatements(pc, true));
                if (ST.rbrace != pc.SymbolId)
                {
                    pc.Error("Expecting } in finally statement");
                }
                pc.Advance();
            }
            return(result);
        }
        static string _ParseNamespaceName(_PC pc)
        {
            var l      = pc.Line;
            var c      = pc.Column;
            var p      = pc.Position;
            var result = "";

            while (!pc.IsEnded && ST.lbrace != pc.SymbolId && ST.semi != pc.SymbolId)
            {
                if (0 < result.Length)
                {
                    result += ".";
                }
                result += _ParseIdentifier(pc);
                if (ST.lbrace == pc.SymbolId || ST.semi == pc.SymbolId)
                {
                    break;
                }
                var l2 = pc.Line;
                var c2 = pc.Column;
                var p2 = pc.Position;
                if (ST.dot != pc.SymbolId)
                {
                    pc.Error("Expecting . in namespace name");
                }
                pc.Advance();
                if (ST.lbrace == pc.SymbolId || ST.semi == pc.SymbolId)
                {
                    pc.Error("Expecting identifier in namespace name", l2, c2, p2);
                }
            }
            if ("" == result)
            {
                pc.Error("Expecting identifier in namespace name", l, c, p);
            }
            return(result);
        }
        static CodeCompileUnit _ParseCompileUnit(_PC pc)
        {
            var l      = pc.Line;
            var c      = pc.Column;
            var p      = pc.Position;
            var result = new CodeCompileUnit().Mark(l, c, p);
            var ns     = new CodeNamespace().Mark(l, c, p);

            result.Namespaces.Add(ns);
            while (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId)
            {
                switch (pc.SymbolId)
                {
                case ST.directive:
                    var d = _ParseDirective(pc) as CodeDirective;
                    if (null != d)
                    {
                        result.StartDirectives.Add(d);
                    }
                    break;

                case ST.blockComment:
                    ns.Comments.Add(_ParseCommentStatement(pc));
                    break;

                case ST.lineComment:
                    ns.Comments.Add(_ParseCommentStatement(pc, true));
                    break;
                }
            }
            while (ST.usingKeyword == pc.SymbolId)
            {
                while (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId)
                {
                    pc.Advance(false);
                }
                var l2 = pc.Line;
                var c2 = pc.Column;
                var p2 = pc.Position;
                pc.Advance();
                var nsi = new CodeNamespaceImport(_ParseNamespaceName(pc)).SetLoc(l2, c2, p2);
                if (ST.semi != pc.SymbolId)
                {
                    pc.Error("Expecting ; in using declaration");
                }
                pc.Advance(false);
                ns.Imports.Add(nsi);
            }
            while (ST.lbracket == pc.SymbolId)
            {
                var pc2 = pc.GetLookAhead(true);
                pc2.Advance();
                if (ST.assemblyKeyword != pc2.SymbolId)
                {
                    break;
                }
                result.AssemblyCustomAttributes.AddRange(_ParseAttributeGroup(pc, false).Value);
            }
            while (!pc.IsEnded)
            {
                var            startDirs = new CodeDirectiveCollection();
                var            comments  = new CodeCommentStatementCollection();
                CodeLinePragma lp        = null;
                while (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId)
                {
                    switch (pc.SymbolId)
                    {
                    case ST.directive:
                        var d   = _ParseDirective(pc);
                        var llp = d as CodeLinePragma;
                        if (null != llp)
                        {
                            lp = llp;
                        }
                        else if (null != d)
                        {
                            startDirs.Add(d as CodeDirective);
                        }
                        break;

                    case ST.blockComment:
                        comments.Add(_ParseCommentStatement(pc));
                        break;

                    case ST.lineComment:
                        comments.Add(_ParseCommentStatement(pc, true));
                        break;
                    }
                }
                if (ST.namespaceKeyword == pc.SymbolId)
                {
                    var nns = _ParseNamespace(pc);
                    nns.Comments.AddRange(comments);
                    result.Namespaces.Add(nns);
                }
                else
                {
                    var t = _ParseTypeDecl(pc, false, pc.Line, pc.Column, pc.Position, null);
                    t.Comments.AddRange(comments);
                    t.StartDirectives.AddRange(startDirs);
                    t.LinePragma = lp;
                    ns.Types.Add(t);
                }
            }
            return(result);
        }
        static CodeNamespace _ParseNamespace(_PC pc)
        {
            var l = pc.Line;
            var c = pc.Column;
            var p = pc.Position;

            var result = new CodeNamespace().Mark(l, c, p);

            while (ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId || ST.directive == pc.SymbolId)
            {
                if (ST.directive != pc.SymbolId)
                {
                    result.Comments.Add(_ParseCommentStatement(pc, true));
                }
            }
            if (ST.namespaceKeyword != pc.SymbolId)
            {
                pc.Error("Expecting namespace");
            }
            pc.Advance();
            result.Name = _ParseNamespaceName(pc);
            if (ST.lbrace != pc.SymbolId)
            {
                pc.Error("Expecing { in namespace declaration");
            }
            pc.Advance(false);
            if (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId)
            {
                var pc2 = pc.GetLookAhead(true);
                if (ST.usingKeyword == pc2.SymbolId)
                {
                    pc.Advance();
                }
            }
            while (ST.usingKeyword == pc.SymbolId)
            {
                while (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId)
                {
                    pc.Advance(false);
                }
                var l2 = pc.Line;
                var c2 = pc.Column;
                var p2 = pc.Position;
                pc.Advance();
                var nsi = new CodeNamespaceImport(_ParseNamespaceName(pc)).SetLoc(l2, c2, p2);
                if (ST.semi != pc.SymbolId)
                {
                    pc.Error("Expecting ; in using declaration");
                }
                pc.Advance(false);
                result.Imports.Add(nsi);
            }
            while (ST.rbrace != pc.SymbolId)
            {
                result.Types.Add(_ParseTypeDecl(pc, false, pc.Line, pc.Column, pc.Position, null));
            }
            if (ST.rbrace != pc.SymbolId)
            {
                pc.Error("Unterminated namespace declaration", l, c, p);
            }
            pc.Advance(false);
            return(result);
        }
Beispiel #30
0
        static CodeTypeDeclaration _ParseType(_PC pc, bool isNested = false)
        {
            var result = new CodeTypeDeclaration();
            IList <KeyValuePair <string, CodeAttributeDeclaration> > custAttrs = null;
            HashSet <string> attrs = null;

            if (!isNested)
            {
                var comments = new CodeCommentStatementCollection();
                while (ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId)
                {
                    comments.Add(_ParseCommentStatement(pc));
                }
                custAttrs = _ParseCustomAttributes(pc);
                attrs     = _ParseTypeAttributes(pc);
                if (attrs.Contains("static"))
                {
                    throw new NotSupportedException("Explicitly static classes are not supported.");
                }
                result.Attributes     = _BuildMemberAttributes(attrs);
                result.TypeAttributes = (isNested)?_BuildNestedTypeAttributes(attrs): _BuildTopLevelTypeAttributes(attrs);
                result.Comments.AddRange(comments);
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated type declaration", "input");
                }
                if (ST.keyword == pc.SymbolId && "partial" == pc.Value)
                {
                    pc.Advance();
                    _SkipComments(pc);
                    if (pc.IsEnded)
                    {
                        throw new ArgumentException("Unterminated type declaration", "input");
                    }
                    result.IsPartial = true;
                }
                _AddCustomAttributes(custAttrs, null, result.CustomAttributes);
                if (null != custAttrs && custAttrs.Count > result.CustomAttributes.Count)
                {
                    throw new ArgumentException("Invalid custom attribute targets", "input");
                }
            }
            if (ST.keyword != pc.SymbolId)
            {
                throw new ArgumentException("Expecting class, struct, enum, or interface", "input");
            }
            switch (pc.Value)
            {
            case "class":
                result.IsClass = true;
                break;

            case "struct":
                result.IsStruct = true;
                break;

            case "enum":
                if (result.IsPartial)
                {
                    throw new ArgumentException("Enums cannot be partial", "input");
                }
                result.IsEnum = true;
                break;

            case "interface":
                result.IsInterface = true;
                break;

            default:
                throw new ArgumentException("Expecting class, struct, enum, or interface", "input");
            }
            pc.Advance();
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated type declaration", "input");
            }
            if (ST.identifier != pc.SymbolId)
            {
                throw new ArgumentException("Expecting identifier in type declaration", "input");
            }
            result.Name = pc.Value;
            pc.Advance();
            _SkipComments(pc);
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated type declaration", "input");
            }
            if (result.IsEnum)
            {
                return(_ParseEnum(pc, result));
            }
            if (ST.lt == pc.SymbolId)
            {
                // parse the generic type arguments
                pc.Advance();
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated generic type parameter specification", "input");
                }
                if (ST.gt == pc.SymbolId)
                {
                    throw new ArgumentException("Generic type parameter specification cannot be empty", "input");
                }
                while (!pc.IsEnded && ST.gt != pc.SymbolId)
                {
                    var custAttrs2 = _ParseCustomAttributes(pc);
                    if (ST.identifier != pc.SymbolId)
                    {
                        throw new ArgumentException("Expecting identifier in type parameter specification", "input");
                    }
                    var tp = new CodeTypeParameter(pc.Value);
                    _AddCustomAttributes(custAttrs2, null, tp.CustomAttributes);
                    if (tp.CustomAttributes.Count < custAttrs2.Count)
                    {
                        throw new ArgumentException("Invalid target in custom attribute declaration on generic type parameter", "input");
                    }
                    result.TypeParameters.Add(tp);
                    pc.Advance();
                    _SkipComments(pc);
                    if (pc.IsEnded)
                    {
                        throw new ArgumentException("Unterminated generic type parameter specification", "input");
                    }
                    if (ST.comma != pc.SymbolId)
                    {
                        break;
                    }
                    pc.Advance();
                    _SkipComments(pc);
                    if (pc.IsEnded)
                    {
                        throw new ArgumentException("Unterminated generic type parameter specification", "input");
                    }
                }
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated generic type parameter specification", "input");
                }
                if (ST.gt != pc.SymbolId)
                {
                    throw new ArgumentException("Illegal generic type parameter specification", "input");
                }
                pc.Advance();
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated generic type parameter specification", "input");
                }
            }
            if (ST.colon == pc.SymbolId)          // parse base types
            {
                pc.Advance();
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated type declaration", "input");
                }
                if (ST.lbrace == pc.SymbolId || (ST.identifier == pc.SymbolId && "where" == pc.Value))
                {
                    throw new ArgumentException("Empty base type specifiers", "input");
                }
                while (!pc.IsEnded && !(ST.lbrace == pc.SymbolId || (ST.identifier == pc.SymbolId && "where" == pc.Value)))
                {
                    result.BaseTypes.Add(_ParseTypeRef(pc));
                    _SkipComments(pc);
                }
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated type declaration", "input");
                }
            }
            if (ST.identifier == pc.SymbolId && "where" == pc.Value)          // parse type constrants
            {
                pc.Advance();
                _SkipComments(pc);
                if (pc.IsEnded)
                {
                    throw new ArgumentException("Unterminated type constraint", "input");
                }
                var moved = false;
                while (!pc.IsEnded && ST.lbrace != pc.SymbolId)
                {
                    moved = true;
                    if (ST.identifier != pc.SymbolId)
                    {
                        throw new ArgumentException("Expecting identifier in type constraint", "input");
                    }
                    var cp = _LookupTypeParameter(result.TypeParameters, pc.Value);
                    pc.Advance();
                    _SkipComments(pc);
                    if (pc.IsEnded)
                    {
                        throw new ArgumentException("Unterminated type constraint", "input");
                    }
                    if (ST.colon != pc.SymbolId)
                    {
                        throw new ArgumentException("Expecting : in type constraint", "input");
                    }
                    pc.Advance();
                    _SkipComments(pc);
                    if (pc.IsEnded)
                    {
                        throw new ArgumentException("Unterminated type constraint", "input");
                    }
                    cp.Constraints.Add(_ParseTypeRef(pc));
                    _SkipComments(pc);
                    if (pc.IsEnded)
                    {
                        throw new ArgumentException("Unterminated type declaration", "input");
                    }
                    if (ST.comma == pc.SymbolId)
                    {
                        pc.Advance();
                        _SkipComments(pc);
                        if (ST.lbrace == pc.SymbolId)
                        {
                            throw new ArgumentException("Unterminated type constraint", "input");
                        }
                    }
                }
                if (!moved)
                {
                    throw new ArgumentException("Unterminated type constraint", "input");
                }
            }
            if (ST.lbrace != pc.SymbolId)
            {
                throw new ArgumentException("Expecting { in type definition", "input");
            }
            pc.Advance();
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated type declaration", "input");
            }
            while (!pc.IsEnded && ST.rbrace != pc.SymbolId)
            {
                result.Members.Add(_ParseMember(pc, result.Name));
            }
            if (pc.IsEnded)
            {
                throw new ArgumentException("Unterminated type declaration", "input");
            }

            if (ST.rbrace != pc.SymbolId)
            {
                throw new ArgumentException("Illegal member declaration in type", "input");
            }
            pc.Advance();
            return(result);
        }