예제 #1
0
        private void AddSkippedNamespaceText(
            ref CompilationUnitBodyBuilder body,
            ref SyntaxListBuilder initialBadNodes,
            CSharpSyntaxNode skippedSyntax)
        {
            if (body.Members.Count > 0)
            {
                body.Members[body.Members.Count - 1] = AddTrailingSkippedSyntax(body.Members[body.Members.Count - 1], skippedSyntax);
            }
            else if (body.Imports.Count > 0)
            {
                body.Imports[body.Imports.Count - 1] = AddTrailingSkippedSyntax(body.Imports[body.Imports.Count - 1], skippedSyntax);
            }
            else if (body.Package != null)
            {
                body.Package = AddTrailingSkippedSyntax(body.Package, skippedSyntax);
            }
            else if (body.Annotations.Count > 0)
            {
                body.Annotations[body.Annotations.Count - 1] = AddTrailingSkippedSyntax(body.Annotations[body.Annotations.Count - 1], skippedSyntax);
            }
            else
            {
                if (initialBadNodes == null)
                {
                    initialBadNodes = this._pool.Allocate();
                }

                initialBadNodes.AddRange(skippedSyntax);
            }
        }
        internal CompilationUnitSyntax ParseCompilationUnit()
        {
            SyntaxListBuilder initialBadNodes = null;
            var body = new CompilationUnitBodyBuilder(this._pool);

            try
            {
                this.ParseCompilationUnitBody(ref body, ref initialBadNodes, SyntaxKind.CompilationUnit);
                var eof    = this.EatToken(SyntaxKind.EndOfFileToken);
                var result = _syntaxFactory.CompilationUnit(body.Package, body.Imports, body.Members, eof);
                if (initialBadNodes != null)
                {
                    // attach initial bad nodes as leading trivia on first token
                    result = AddLeadingSkippedSyntax(result, initialBadNodes.ToListNode());
                    this._pool.Free(initialBadNodes);
                }
                return(result);
            }
            finally
            {
                body.Free(this._pool);
            }
        }
예제 #3
0
 private static void AddIncompleteMembers(ref SyntaxListBuilder <MemberDeclarationSyntax> incompleteMembers, ref CompilationUnitBodyBuilder body)
 {
     if (incompleteMembers.Count > 0)
     {
         body.Members.AddRange(incompleteMembers);
         incompleteMembers.Clear();
     }
 }
예제 #4
0
 private void ReduceIncompleteMembers(ref SyntaxListBuilder <MemberDeclarationSyntax> incompleteMembers, ref CompilationUnitBodyBuilder body, ref SyntaxListBuilder initialBadNodes)
 {
     for (int i = 0; i < incompleteMembers.Count; i++)
     {
         this.AddSkippedNamespaceText(ref body, ref initialBadNodes, incompleteMembers[i]);
     }
     incompleteMembers.Clear();
 }
        private void ParseCompilationUnitBody(ref CompilationUnitBodyBuilder body, ref SyntaxListBuilder initialBadNodes, SyntaxKind parentKind)
        {
            var saveTerm = this._termState;

            this._termState |= TerminatorState.IsPackageMemberStartOrStop;
            PackageParts seen = PackageParts.None;
            bool         reportUnexpectedToken    = true;
            var          pendingIncompleteMembers = _pool.Allocate <MemberDeclarationSyntax>();
            var          pendingAnnotations       = _pool.Allocate <AnnotationSyntax>();

            try
            {
                while (true)
                {
                    switch (this.CurrentToken.Kind)
                    {
                    case SyntaxKind.AtToken:
                        if (this.IsPossibleJavaPackageAnnotations())
                        {
                            // incomplete members must be processed before we add any nodes to the body:
                            ReduceIncompleteMembers(ref pendingIncompleteMembers, ref body, ref initialBadNodes);
                            this.ParseAnnotationDeclarations(pendingAnnotations);
                            reportUnexpectedToken = true;
                            break;
                        }
                        goto default;

                    case SyntaxKind.PackageKeyword:

                        // incomplete members must be processed before we add any nodes to the body:
                        ReduceIncompleteMembers(ref pendingIncompleteMembers, ref body, ref initialBadNodes);

                        var package = this.ParsePackageDeclaration(ref pendingAnnotations);
                        pendingAnnotations.Clear();
                        if (seen > PackageParts.Package)
                        {
                            package = this.AddError(package, ErrorCode.ERR_UsingAfterElements);

                            //package 必须在所有using之前
                            this.AddSkippedNamespaceText(ref body, ref initialBadNodes, package);
                        }
                        else if (seen == PackageParts.Package)
                        {
                            //package 重复
                            package = this.AddError(package, ErrorCode.ERR_NamespaceUnexpected);
                            this.AddSkippedNamespaceText(ref body, ref initialBadNodes, package);
                        }
                        else
                        {
                            body.Package = package;
                            seen         = PackageParts.Package;
                        }

                        reportUnexpectedToken = true;
                        break;

                    case SyntaxKind.ImportKeyword:

                        // incomplete members must be processed before we add any nodes to the body:
                        ReduceIncompleteMembers(ref pendingIncompleteMembers, ref body, ref initialBadNodes);
                        var import = this.ParseJavaImportDeclaration();
                        if (seen > PackageParts.Imports)
                        {
                            import = this.AddError(import, ErrorCode.ERR_UsingAfterElements);
                            this.AddSkippedNamespaceText(ref body, ref initialBadNodes, import);
                        }
                        else
                        {
                            body.Imports.Add(import);
                            seen = PackageParts.Imports;
                        }
                        reportUnexpectedToken = true;
                        break;

                    case SyntaxKind.EndOfFileToken:
                        // This token marks the end of a namespace body
                        return;

                    default:
                        var memberDeclaration = this.ParseMemberDeclaration(parentKind);
                        if (memberDeclaration == null)
                        {
                            // incomplete members must be processed before we add any nodes to the body:
                            ReduceIncompleteMembers(ref pendingIncompleteMembers, ref body, ref initialBadNodes);

                            // eat one token and try to parse declaration or statement again:
                            var skippedToken = EatToken();
                            if (reportUnexpectedToken && !skippedToken.ContainsDiagnostics)
                            {
                                skippedToken = this.AddError(skippedToken, ErrorCode.ERR_EOFExpected);

                                // do not report the error multiple times for subsequent tokens:
                                reportUnexpectedToken = false;
                            }

                            this.AddSkippedNamespaceText(ref body, ref initialBadNodes, skippedToken);
                        }
                        else if (memberDeclaration.Kind == SyntaxKind.IncompleteMember && seen < PackageParts.Members)
                        {
                            pendingIncompleteMembers.Add(memberDeclaration);
                            reportUnexpectedToken = true;
                        }
                        else
                        {
                            // incomplete members must be processed before we add any nodes to the body:
                            AddIncompleteMembers(ref pendingIncompleteMembers, ref body);

                            body.Members.Add(memberDeclaration);
                            seen = PackageParts.Members;
                            reportUnexpectedToken = true;
                        }
                        break;
                    }
                }
            }
            finally
            {
                this._termState = saveTerm;

                // adds pending incomplete nodes:
                AddIncompleteMembers(ref pendingIncompleteMembers, ref body);
                _pool.Free(pendingIncompleteMembers);
                _pool.Free(pendingAnnotations);
            }
        }