Skip to content

Commit

Permalink
Parser done
Browse files Browse the repository at this point in the history
  • Loading branch information
LPeter1997 committed Oct 31, 2024
1 parent ae6d486 commit 1d0e05f
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 11 deletions.
8 changes: 4 additions & 4 deletions src/Draco.Compiler.Tests/Services/CodeCompletionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ public void TestLocalCompletionGlobalVariable()
{
// TODO: Can we get rid of all this filtering by filtering in the completion service?
var completions = GetCompletionWords("""
val global = 5;
val globalVar = 5;
func main(){
var local = gl|
}
""");

AssertCompletions(completions, "global");
AssertCompletions(completions, "globalVar");
}

[Fact]
Expand Down Expand Up @@ -78,11 +78,11 @@ func main(){
public void TestGlobalCompletionGlobalVariable()
{
var completions = GetCompletionWords("""
val global = 5;
val globalVar = 5;
val x = gl|
""");

AssertCompletions(completions, "global");
AssertCompletions(completions, "globalVar");
}

[Fact]
Expand Down
25 changes: 18 additions & 7 deletions src/Draco.Compiler/Internal/Syntax/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,15 @@ internal sealed class Parser(
private enum DeclarationContext
{
/// <summary>
/// Global, like in a compilation unit, module, class, ...
/// Global, like in a compilation unit or module.
/// </summary>
Global,

/// <summary>
/// Inside a class declaration body.
/// </summary>
Class,

/// <summary>
/// Local to a function body/expression/code-block.
/// </summary>
Expand Down Expand Up @@ -556,6 +561,7 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxList<AttributeSyntax>
var body = this.ParseClassBody();

return new ClassDeclarationSyntax(
attributes,
visibility,
valueModifier,
classKeyword,
Expand Down Expand Up @@ -583,7 +589,7 @@ private ClassBodySyntax ParseClassBody()
if (this.PeekKind() is TokenKind.EndOfInput or TokenKind.CurlyClose) break;

// Parse a declaration
var decl = this.ParseDeclaration(DeclarationContext.Global);
var decl = this.ParseDeclaration(DeclarationContext.Class);
decls.Add(decl);
}
var closeBrace = this.Expect(TokenKind.CurlyClose);
Expand All @@ -594,7 +600,7 @@ private ClassBodySyntax ParseClassBody()
var input = this.Synchronize(t => t.Kind switch
{
TokenKind.Semicolon or TokenKind.CurlyClose => false,
_ when this.IsDeclarationStarter(DeclarationContext.Global) => false,
_ when this.IsDeclarationStarter(DeclarationContext.Class) => false,
_ => true,
});
var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedInput, formatArgs: "class body");
Expand Down Expand Up @@ -629,7 +635,11 @@ private VariableDeclarationSyntax ParseVariableDeclaration(

// Global modifier
this.Matches(TokenKind.KeywordGlobal, out var globalModifier);
// TODO: We need more info to check, if this is an error
if (context != DeclarationContext.Class && globalModifier is not null)
{
var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedGlobalModifier);
this.AddDiagnostic(globalModifier, info);
}

// Field modifier
this.Matches(TokenKind.KeywordField, out var fieldModifier);
Expand Down Expand Up @@ -708,7 +718,7 @@ private FunctionDeclarationSyntax ParseFunctionDeclaration(
TypeSpecifierSyntax? returnType = null;
if (this.PeekKind() == TokenKind.Colon) returnType = this.ParseTypeSpecifier();

var body = this.ParseFunctionBody();
var body = this.ParseFunctionBody(context);

return new FunctionDeclarationSyntax(
attributes,
Expand Down Expand Up @@ -882,8 +892,9 @@ private GenericParameterSyntax ParseGenericParameter()
/// <summary>
/// Parses a function body.
/// </summary>
/// <param name="ctx">The current context we are in.</param>
/// <returns>The parsed <see cref="FunctionBodySyntax"/>.</returns>
private FunctionBodySyntax ParseFunctionBody()
private FunctionBodySyntax ParseFunctionBody(DeclarationContext ctx)
{
if (this.Matches(TokenKind.Assign, out var assign))
{
Expand All @@ -906,7 +917,7 @@ private FunctionBodySyntax ParseFunctionBody()
var input = this.Synchronize(t => t.Kind switch
{
TokenKind.Semicolon or TokenKind.CurlyClose => false,
_ when this.IsDeclarationStarter(DeclarationContext.Global) => false,
_ when this.IsDeclarationStarter(ctx) => false,
_ => true,
});
var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedInput, formatArgs: "function body");
Expand Down
6 changes: 6 additions & 0 deletions src/Draco.Compiler/Internal/Syntax/Syntax.xml
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,12 @@
A class declaration.
</Documentation>

<Field Name="Attributes" Type="SyntaxList&lt;AttributeSyntax&gt;?">
<Documentation>
The attributes of this class.
</Documentation>
</Field>

<Field Name="VisibilityModifier" Type="SyntaxToken?">
<Documentation>
The visibility modifier keyword possibly starting the declaration.
Expand Down
9 changes: 9 additions & 0 deletions src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,13 @@ internal static class SyntaxErrors
severity: DiagnosticSeverity.Error,
format: "unexpected field modifier in a local context",
code: Code(20));

/// <summary>
/// There is a global modifier in a global or local context.
/// </summary>
public static readonly DiagnosticTemplate UnexpectedGlobalModifier = DiagnosticTemplate.Create(
title: "unexpected global modifier",
severity: DiagnosticSeverity.Error,
format: "unexpected global modifier outside of class declaration",
code: Code(21));
}

0 comments on commit 1d0e05f

Please sign in to comment.