From ae6d486c0664eadfa42c33ca6b8e6fc32875aadc Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 31 Oct 2024 22:59:45 +0100 Subject: [PATCH] Syntax fixup --- src/Draco.Compiler/Internal/Syntax/Parser.cs | 75 +++++++++---------- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 12 +++ 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 2eca70903..6ee81b492 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -238,7 +238,7 @@ private ExpressionParserDelegate BinaryRight(params TokenKind[] operators) => le TokenKind.Plus, TokenKind.Minus, TokenKind.Star, - TokenKind.KeywordThis + TokenKind.KeywordThis, ]; /// @@ -384,8 +384,7 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) case TokenKind.KeywordValue: case TokenKind.KeywordClass: - // TODO: Attributes? - return this.ParseClassDeclaration(visibility); + return this.ParseClassDeclaration(attributes, visibility); case TokenKind.KeywordFunc: return this.ParseFunctionDeclaration(attributes, visibility, context); @@ -539,9 +538,10 @@ private ImportPathSyntax ParseImportPath() /// /// Parses a class declaration. /// + /// Optional attributes on the class. /// Optional visibility modifier token. /// The parsed . - private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility) + private ClassDeclarationSyntax ParseClassDeclaration(SyntaxList? attributes, SyntaxToken? visibility) { this.Matches(TokenKind.KeywordValue, out var valueModifier); @@ -568,42 +568,40 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility) /// Parses the body of a class. /// /// The parsed . - private ClassBodySyntax ParseClassBody() => this.PeekKind() switch + private ClassBodySyntax ParseClassBody() { - TokenKind.Semicolon => this.ParseEmptyClassBody(), - TokenKind.CurlyOpen => this.ParseBlockClassBody(), - _ => throw new NotImplementedException() - }; - - /// - /// Parses an empty class body, which is just a semicolon. - /// - /// The parsed . - private EmptyClassBodySyntax ParseEmptyClassBody() - { - var semicolon = this.Expect(TokenKind.Semicolon); - return new EmptyClassBodySyntax(semicolon); - } - - /// - /// Parses a block class body declared with curly braces. - /// - /// The parsed . - private BlockClassBodySyntax ParseBlockClassBody() - { - var openBrace = this.Expect(TokenKind.CurlyOpen); - var decls = SyntaxList.CreateBuilder(); - while (true) + if (this.Matches(TokenKind.Semicolon, out var semicolon)) + { + return new EmptyClassBodySyntax(semicolon); + } + else if (this.Matches(TokenKind.CurlyOpen, out var openBrace)) { - // Break on the end of the block - if (this.PeekKind() is TokenKind.EndOfInput or TokenKind.CurlyClose) break; + var decls = SyntaxList.CreateBuilder(); + while (true) + { + // Break on the end of the block + if (this.PeekKind() is TokenKind.EndOfInput or TokenKind.CurlyClose) break; - // Parse a declaration - var decl = this.ParseDeclaration(DeclarationContext.Global); - decls.Add(decl); + // Parse a declaration + var decl = this.ParseDeclaration(DeclarationContext.Global); + decls.Add(decl); + } + var closeBrace = this.Expect(TokenKind.CurlyClose); + return new BlockClassBodySyntax(openBrace, decls.ToSyntaxList(), closeBrace); + } + else + { + var input = this.Synchronize(t => t.Kind switch + { + TokenKind.Semicolon or TokenKind.CurlyClose => false, + _ when this.IsDeclarationStarter(DeclarationContext.Global) => false, + _ => true, + }); + var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedInput, formatArgs: "class body"); + var node = new UnexpectedClassBodySyntax(input); + this.AddDiagnostic(node, info); + return node; } - var closeBrace = this.Expect(TokenKind.CurlyClose); - return new(openBrace, decls.ToSyntaxList(), closeBrace); } /// @@ -631,7 +629,7 @@ private VariableDeclarationSyntax ParseVariableDeclaration( // Global modifier this.Matches(TokenKind.KeywordGlobal, out var globalModifier); - // TODO: Check where this is correct + // TODO: We need more info to check, if this is an error // Field modifier this.Matches(TokenKind.KeywordField, out var fieldModifier); @@ -672,7 +670,6 @@ private VariableDeclarationSyntax ParseVariableDeclaration( semicolon); } - /// /// Parses a function declaration. /// @@ -1665,8 +1662,6 @@ private SeparatedSyntaxList ParseSeparatedSyntaxList( private SyntaxToken? ParseVisibilityModifier() => IsVisibilityModifier(this.PeekKind()) ? this.Advance() : null; - private SyntaxToken? ParseGlobalModifier() => this.PeekKind() == TokenKind.KeywordGlobal ? this.Advance() : null; - private bool CanBailOut(SyntaxNode node) { if (parserMode != ParserMode.Repl) return false; diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index a6c38aed6..014e44059 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -435,6 +435,18 @@ + + + Unexpected input in class body context. + + + + + The unexpected syntax nodes. + + + + A function declaration.