namespace

This commit is contained in:
nub31
2025-05-26 19:38:02 +02:00
parent cfd7a6ebef
commit 37b4ce3989
7 changed files with 107 additions and 62 deletions

View File

@@ -1,4 +1,4 @@
module c_interop namespace c
extern func printf(fmt: string, ...args: any) extern func printf(fmt: string, ...args: any)
extern func getchar(): i32 extern func getchar(): i32

View File

@@ -1,6 +1,4 @@
import c_interop namespace main
module main
/// # Documentation /// # Documentation
/// ## Documentation subtitle /// ## Documentation subtitle

View File

@@ -6,9 +6,8 @@ public class Lexer
{ {
private static readonly Dictionary<string, Symbol> Keywords = new() private static readonly Dictionary<string, Symbol> Keywords = new()
{ {
["namespace"] = Symbol.Namespace,
["func"] = Symbol.Func, ["func"] = Symbol.Func,
["import"] = Symbol.Import,
["module"] = Symbol.Module,
["if"] = Symbol.If, ["if"] = Symbol.If,
["else"] = Symbol.Else, ["else"] = Symbol.Else,
["while"] = Symbol.While, ["while"] = Symbol.While,
@@ -31,6 +30,7 @@ public class Lexer
[['!', '=']] = Symbol.NotEqual, [['!', '=']] = Symbol.NotEqual,
[['<', '=']] = Symbol.LessThanOrEqual, [['<', '=']] = Symbol.LessThanOrEqual,
[['>', '=']] = Symbol.GreaterThanOrEqual, [['>', '=']] = Symbol.GreaterThanOrEqual,
[[':', ':']] = Symbol.DoubleColon,
}; };
private static readonly Dictionary<char, Symbol> Chars = new() private static readonly Dictionary<char, Symbol> Chars = new()

View File

@@ -9,8 +9,6 @@ public class SymbolToken(SourceText sourceText, int startIndex, int endIndex, Sy
public enum Symbol public enum Symbol
{ {
Import,
Module,
Func, Func,
Return, Return,
If, If,
@@ -44,4 +42,6 @@ public enum Symbol
Struct, Struct,
Caret, Caret,
Ampersand, Ampersand,
DoubleColon,
Namespace,
} }

View File

@@ -1,7 +1,8 @@
namespace Nub.Lang.Frontend.Parsing; namespace Nub.Lang.Frontend.Parsing;
public class FuncCall(string name, List<ExpressionNode> parameters) public class FuncCall(string @namespace, string name, List<ExpressionNode> parameters)
{ {
public string Namespace { get; } = @namespace;
public string Name { get; } = name; public string Name { get; } = name;
public List<ExpressionNode> Parameters { get; } = parameters; public List<ExpressionNode> Parameters { get; } = parameters;

View File

@@ -9,24 +9,19 @@ public class Parser
private List<Diagnostic> _diagnostics = []; private List<Diagnostic> _diagnostics = [];
private List<Token> _tokens = []; private List<Token> _tokens = [];
private int _index; private int _index;
private string _namespace = string.Empty;
public DiagnosticsResult<SourceFile?> ParseModule(List<Token> tokens) public DiagnosticsResult<SourceFile?> ParseModule(List<Token> tokens)
{ {
_diagnostics = []; _diagnostics = [];
_tokens = tokens; _tokens = tokens;
_index = 0; _index = 0;
_namespace = string.Empty;
try try
{ {
List<string> imports = []; ExpectSymbol(Symbol.Namespace);
while (TryExpectSymbol(Symbol.Import)) _namespace = ExpectIdentifier().Value;
{
var name = ExpectIdentifier();
imports.Add(name.Value);
}
ExpectSymbol(Symbol.Module);
var module = ExpectIdentifier().Value;
List<DefinitionNode> definitions = []; List<DefinitionNode> definitions = [];
@@ -34,8 +29,8 @@ public class Parser
{ {
definitions.Add(ParseDefinition()); definitions.Add(ParseDefinition());
} }
return new DiagnosticsResult<SourceFile?>(_diagnostics, new SourceFile(module, imports, definitions)); return new DiagnosticsResult<SourceFile?>(_diagnostics, new SourceFile(_namespace, definitions));
} }
catch (ParseException ex) catch (ParseException ex)
{ {
@@ -187,41 +182,7 @@ public class Parser
{ {
case IdentifierToken identifier: case IdentifierToken identifier:
{ {
var symbol = ExpectSymbol(); return ParseStatementIdentifier(startIndex, identifier);
switch (symbol.Symbol)
{
case Symbol.OpenParen:
{
var parameters = new List<ExpressionNode>();
while (!TryExpectSymbol(Symbol.CloseParen))
{
parameters.Add(ParseExpression());
TryExpectSymbol(Symbol.Comma);
}
return new FuncCallStatementNode(GetTokensForNode(startIndex), new FuncCall(identifier.Value, parameters));
}
case Symbol.Assign:
{
var value = ParseExpression();
return new VariableAssignmentNode(GetTokensForNode(startIndex), identifier.Value, Optional<NubType>.Empty(), value);
}
case Symbol.Colon:
{
var type = ParseType();
ExpectSymbol(Symbol.Assign);
var value = ParseExpression();
return new VariableAssignmentNode(GetTokensForNode(startIndex), identifier.Value, type, value);
}
default:
{
throw new ParseException(Diagnostic
.Error($"Unexpected symbol '{symbol.Symbol}' after identifier")
.WithHelp("Expected '(', '=', or ':' after identifier")
.At(symbol)
.Build());
}
}
} }
case SymbolToken symbol: case SymbolToken symbol:
{ {
@@ -250,6 +211,72 @@ public class Parser
} }
} }
private StatementNode ParseStatementIdentifier(int startIndex, IdentifierToken identifier)
{
var symbol = ExpectSymbol();
switch (symbol.Symbol)
{
case Symbol.DoubleColon:
{
var name = ExpectIdentifier();
ExpectSymbol(Symbol.OpenParen);
var parameters = new List<ExpressionNode>();
while (!TryExpectSymbol(Symbol.CloseParen))
{
parameters.Add(ParseExpression());
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
{
_diagnostics.Add(Diagnostic
.Warning("Missing comma between function arguments")
.WithHelp("Add a ',' to separate arguments")
.At(nextToken)
.Build());
}
}
return new FuncCallStatementNode(GetTokensForNode(startIndex), new FuncCall(identifier.Value, name.Value, parameters));
}
case Symbol.OpenParen:
{
var parameters = new List<ExpressionNode>();
while (!TryExpectSymbol(Symbol.CloseParen))
{
parameters.Add(ParseExpression());
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
{
_diagnostics.Add(Diagnostic
.Warning("Missing comma between function arguments")
.WithHelp("Add a ',' to separate arguments")
.At(nextToken)
.Build());
}
}
return new FuncCallStatementNode(GetTokensForNode(startIndex), new FuncCall(_namespace, identifier.Value, parameters));
}
case Symbol.Assign:
{
var value = ParseExpression();
return new VariableAssignmentNode(GetTokensForNode(startIndex), identifier.Value, Optional<NubType>.Empty(), value);
}
case Symbol.Colon:
{
var type = ParseType();
ExpectSymbol(Symbol.Assign);
var value = ParseExpression();
return new VariableAssignmentNode(GetTokensForNode(startIndex), identifier.Value, type, value);
}
default:
{
throw new ParseException(Diagnostic
.Error($"Unexpected symbol '{symbol.Symbol}' after identifier")
.WithHelp("Expected '(', '=', or ':' after identifier")
.At(symbol)
.Build());
}
}
}
private ReturnNode ParseReturn(int startIndex) private ReturnNode ParseReturn(int startIndex)
{ {
var value = Optional<ExpressionNode>.Empty(); var value = Optional<ExpressionNode>.Empty();
@@ -384,10 +411,11 @@ public class Parser
var next = Peek(); var next = Peek();
switch (next.Value) switch (next.Value)
{ {
case SymbolToken { Symbol: Symbol.OpenParen }: case SymbolToken { Symbol: Symbol.DoubleColon }:
{ {
Next(); var name = ExpectIdentifier();
List<ExpressionNode> parameters = []; ExpectSymbol(Symbol.OpenParen);
var parameters = new List<ExpressionNode>();
while (!TryExpectSymbol(Symbol.CloseParen)) while (!TryExpectSymbol(Symbol.CloseParen))
{ {
parameters.Add(ParseExpression()); parameters.Add(ParseExpression());
@@ -401,7 +429,26 @@ public class Parser
} }
} }
expr = new FuncCallExpressionNode(GetTokensForNode(startIndex), new FuncCall(identifier.Value, parameters)); expr = new FuncCallExpressionNode(GetTokensForNode(startIndex), new FuncCall(identifier.Value, name.Value, parameters));
break;
}
case SymbolToken { Symbol: Symbol.OpenParen }:
{
var parameters = new List<ExpressionNode>();
while (!TryExpectSymbol(Symbol.CloseParen))
{
parameters.Add(ParseExpression());
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
{
_diagnostics.Add(Diagnostic
.Warning("Missing comma between function arguments")
.WithHelp("Add a ',' to separate arguments")
.At(nextToken)
.Build());
}
}
expr = new FuncCallExpressionNode(GetTokensForNode(startIndex), new FuncCall(_namespace, identifier.Value, parameters));
break; break;
} }
default: default:

View File

@@ -1,8 +1,7 @@
namespace Nub.Lang.Frontend.Parsing; namespace Nub.Lang.Frontend.Parsing;
public class SourceFile(string module, List<string> imports, List<DefinitionNode> definitions) public class SourceFile(string @namespace, List<DefinitionNode> definitions)
{ {
public string Module { get; } = module; public string Namespace { get; } = @namespace;
public List<string> Imports { get; } = imports;
public List<DefinitionNode> Definitions { get; } = definitions; public List<DefinitionNode> Definitions { get; } = definitions;
} }