From 57ccd0a38acdebceece5da0c22e682d2ce490afc Mon Sep 17 00:00:00 2001 From: nub31 Date: Fri, 16 May 2025 20:46:38 +0200 Subject: [PATCH] modifiers --- .../Nub.Lang/Frontend/Lexing/Lexer.cs | 13 ++- .../Nub.Lang/Frontend/Lexing/ModifierToken.cs | 12 +++ .../Nub.Lang/Frontend/Lexing/SymbolToken.cs | 2 - .../Nub.Lang/Frontend/Parsing/Parser.cs | 101 +++++++----------- 4 files changed, 64 insertions(+), 64 deletions(-) create mode 100644 src/compiler/Nub.Lang/Frontend/Lexing/ModifierToken.cs diff --git a/src/compiler/Nub.Lang/Frontend/Lexing/Lexer.cs b/src/compiler/Nub.Lang/Frontend/Lexing/Lexer.cs index be654a8..e36c490 100644 --- a/src/compiler/Nub.Lang/Frontend/Lexing/Lexer.cs +++ b/src/compiler/Nub.Lang/Frontend/Lexing/Lexer.cs @@ -5,8 +5,6 @@ public class Lexer private static readonly Dictionary Keywords = new() { ["func"] = Symbol.Func, - ["global"] = Symbol.Global, - ["extern"] = Symbol.Extern, ["import"] = Symbol.Import, ["if"] = Symbol.If, ["else"] = Symbol.Else, @@ -17,6 +15,12 @@ public class Lexer ["new"] = Symbol.New, ["struct"] = Symbol.Struct, }; + + private static readonly Dictionary Modifers = new() + { + ["global"] = Modifier.Global, + ["extern"] = Modifier.Extern, + }; private static readonly Dictionary Chians = new() { @@ -84,6 +88,11 @@ public class Lexer return new SymbolToken(keywordSymbol); } + if (Modifers.TryGetValue(buffer, out var modifer)) + { + return new ModifierToken(modifer); + } + if (buffer is "true" or "false") { return new LiteralToken(NubPrimitiveType.Bool, buffer); diff --git a/src/compiler/Nub.Lang/Frontend/Lexing/ModifierToken.cs b/src/compiler/Nub.Lang/Frontend/Lexing/ModifierToken.cs new file mode 100644 index 0000000..3446034 --- /dev/null +++ b/src/compiler/Nub.Lang/Frontend/Lexing/ModifierToken.cs @@ -0,0 +1,12 @@ +namespace Nub.Lang.Frontend.Lexing; + +public class ModifierToken(Modifier symbol) : Token +{ + public Modifier Modifier { get; } = symbol; +} + +public enum Modifier +{ + Extern, + Global +} \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Lexing/SymbolToken.cs b/src/compiler/Nub.Lang/Frontend/Lexing/SymbolToken.cs index ccaa7ec..068b52f 100644 --- a/src/compiler/Nub.Lang/Frontend/Lexing/SymbolToken.cs +++ b/src/compiler/Nub.Lang/Frontend/Lexing/SymbolToken.cs @@ -9,8 +9,6 @@ public enum Symbol { Whitespace, Import, - Extern, - Global, Func, Return, If, diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs index 45567a4..b35a595 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs @@ -35,18 +35,23 @@ public class Parser private DefinitionNode ParseDefinition() { + List modifiers = []; + + while (TryExpectModifier(out var modifier)) + { + modifiers.Add(modifier); + } + var keyword = ExpectSymbol(); return keyword.Symbol switch { - Symbol.Func => ParseFuncDefinition(), - Symbol.Global => ParseGlobalFuncDefinition(), - Symbol.Extern => ParseExternFuncDefinition(), - Symbol.Struct => ParseStruct(), + Symbol.Func => ParseFuncDefinition(modifiers), + Symbol.Struct => ParseStruct(modifiers), _ => throw new Exception("Unexpected symbol: " + keyword.Symbol) }; } - private LocalFuncDefinitionNode ParseFuncDefinition() + private DefinitionNode ParseFuncDefinition(List modifiers) { var name = ExpectIdentifier(); List parameters = []; @@ -66,64 +71,27 @@ public class Parser returnType = ParseType(); } + if (modifiers.Remove(Modifier.Extern)) + { + if (modifiers.Count != 0) + { + throw new Exception($"Modifiers: {string.Join(", ", modifiers)} is not valid for an extern function"); + } + ExpectSymbol(Symbol.Semicolon); + return new ExternFuncDefinitionNode(name.Value, parameters, returnType); + } + var body = ParseBlock(); - - return new LocalFuncDefinitionNode(name.Value, parameters, body, returnType, false); + var global = modifiers.Remove(Modifier.Global); + + if (modifiers.Count != 0) + { + throw new Exception($"Modifiers: {string.Join(", ", modifiers)} is not valid for a local function"); + } + return new LocalFuncDefinitionNode(name.Value, parameters, body, returnType, global); } - private LocalFuncDefinitionNode ParseGlobalFuncDefinition() - { - ExpectSymbol(Symbol.Func); - var name = ExpectIdentifier(); - List parameters = []; - ExpectSymbol(Symbol.OpenParen); - if (!TryExpectSymbol(Symbol.CloseParen)) - { - while (!TryExpectSymbol(Symbol.CloseParen)) - { - parameters.Add(ParseFuncParameter()); - TryExpectSymbol(Symbol.Comma); - } - } - - var returnType = Optional.Empty(); - if (TryExpectSymbol(Symbol.Colon)) - { - returnType = ParseType(); - } - - var body = ParseBlock(); - - return new LocalFuncDefinitionNode(name.Value, parameters, body, returnType, true); - } - - private ExternFuncDefinitionNode ParseExternFuncDefinition() - { - ExpectSymbol(Symbol.Func); - var name = ExpectIdentifier(); - List parameters = []; - ExpectSymbol(Symbol.OpenParen); - if (!TryExpectSymbol(Symbol.CloseParen)) - { - while (!TryExpectSymbol(Symbol.CloseParen)) - { - parameters.Add(ParseFuncParameter()); - TryExpectSymbol(Symbol.Comma); - } - } - - var returnType = Optional.Empty(); - if (TryExpectSymbol(Symbol.Colon)) - { - returnType = ParseType(); - } - - ExpectSymbol(Symbol.Semicolon); - - return new ExternFuncDefinitionNode(name.Value, parameters, returnType); - } - - private StructDefinitionNode ParseStruct() + private StructDefinitionNode ParseStruct(List modifiers) { var name = ExpectIdentifier().Value; @@ -503,6 +471,19 @@ public class Parser return result; } + private bool TryExpectModifier(out Modifier modifier) + { + if (Peek() is { HasValue: true, Value: ModifierToken modifierToken }) + { + modifier = modifierToken.Modifier; + Next(); + return true; + } + + modifier = default; + return false; + } + private IdentifierToken ExpectIdentifier() { var token = ExpectToken();