This commit is contained in:
nub31
2025-07-21 16:56:28 +02:00
parent 901abf6938
commit 1f6f4eab95
5 changed files with 75 additions and 69 deletions

View File

@@ -1,4 +1,4 @@
template<T> struct Box struct Box<T>
{ {
value: T value: T
} }

View File

@@ -3,24 +3,26 @@ using NubLang.Syntax.Tokenization;
namespace NubLang.Syntax.Parsing.Node; namespace NubLang.Syntax.Parsing.Node;
public abstract record DefinitionSyntax(IReadOnlyList<Token> Tokens, string Namespace) : SyntaxNode(Tokens); public record TemplateParameterSyntax(IReadOnlyList<Token> Tokens, string Name) : SyntaxNode(Tokens);
public abstract record DefinitionSyntax(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<TemplateParameterSyntax> Parameters) : SyntaxNode(Tokens);
public record FuncParameterSyntax(IReadOnlyList<Token> Tokens, string Name, TypeSyntax Type) : SyntaxNode(Tokens); public record FuncParameterSyntax(IReadOnlyList<Token> Tokens, string Name, TypeSyntax Type) : SyntaxNode(Tokens);
public record FuncSignatureSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<FuncParameterSyntax> Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens); public record FuncSignatureSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<FuncParameterSyntax> Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens);
public record LocalFuncSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionSyntax(Tokens, Namespace); public record LocalFuncSyntax(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<TemplateParameterSyntax> Parameters, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionSyntax(Tokens, Namespace, Parameters);
public record ExternFuncSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, string CallName, FuncSignatureSyntax Signature) : DefinitionSyntax(Tokens, Namespace); public record ExternFuncSyntax(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<TemplateParameterSyntax> Parameters, string Name, string CallName, FuncSignatureSyntax Signature) : DefinitionSyntax(Tokens, Namespace, Parameters);
public record StructFieldSyntax(IReadOnlyList<Token> Tokens, int Index, string Name, TypeSyntax Type, Optional<ExpressionSyntax> Value) : SyntaxNode(Tokens); public record StructFieldSyntax(IReadOnlyList<Token> Tokens, int Index, string Name, TypeSyntax Type, Optional<ExpressionSyntax> Value) : SyntaxNode(Tokens);
public record StructSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, IReadOnlyList<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, Namespace); public record StructSyntax(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<TemplateParameterSyntax> Parameters, string Name, IReadOnlyList<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, Namespace, Parameters);
public record TraitFuncSyntax(IReadOnlyList<Token> Tokens, string Name, FuncSignatureSyntax Signature) : SyntaxNode(Tokens); public record TraitFuncSyntax(IReadOnlyList<Token> Tokens, string Name, FuncSignatureSyntax Signature) : SyntaxNode(Tokens);
public record TraitSyntax(IReadOnlyList<Token> Tokens, string Namespace, string Name, IReadOnlyList<TraitFuncSyntax> Functions) : DefinitionSyntax(Tokens, Namespace); public record TraitSyntax(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<TemplateParameterSyntax> Parameters, string Name, IReadOnlyList<TraitFuncSyntax> Functions) : DefinitionSyntax(Tokens, Namespace, Parameters);
public record TraitFuncImplSyntax(IReadOnlyList<Token> Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens); public record TraitFuncImplSyntax(IReadOnlyList<Token> Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens);
public record TraitImplSyntax(IReadOnlyList<Token> Tokens, string Namespace, TypeSyntax TraitType, TypeSyntax ForType, IReadOnlyList<TraitFuncImplSyntax> Functions) : DefinitionSyntax(Tokens, Namespace); public record TraitImplSyntax(IReadOnlyList<Token> Tokens, string Namespace, IReadOnlyList<TemplateParameterSyntax> Parameters, TypeSyntax TraitType, TypeSyntax ForType, IReadOnlyList<TraitFuncImplSyntax> Functions) : DefinitionSyntax(Tokens, Namespace, Parameters);

View File

@@ -37,30 +37,38 @@ public sealed class Parser
var startIndex = _tokenIndex; var startIndex = _tokenIndex;
try try
{
var definition = ParseDefinition(startIndex);
definitions.Add(definition);
}
catch (ParseException ex)
{
_diagnostics.Add(ex.Diagnostic);
RecoverToNextDefinition();
}
}
return new SyntaxTree(_namespace, definitions, _diagnostics);
}
private DefinitionSyntax ParseDefinition(int startIndex)
{ {
var keyword = ExpectSymbol(); var keyword = ExpectSymbol();
var node = keyword.Symbol switch var name = ExpectIdentifier();
var templateParameters = new List<TemplateParameterSyntax>();
if (TryExpectSymbol(Symbol.LessThan))
{ {
Symbol.Extern => ParseExtern(startIndex), while (!TryExpectSymbol(Symbol.GreaterThan))
Symbol.Func => ParseFunc(startIndex), {
Symbol.Struct => ParseStruct(startIndex), var argumentStartIndex = _tokenIndex;
Symbol.Trait => ParseTrait(startIndex), var identifier = ExpectIdentifier();
Symbol.Impl => ParseImpl(startIndex), if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.GreaterThan })
{
_diagnostics.Add(Diagnostic
.Warning("Missing comma between template parameters")
.WithHelp("Add a ',' to separate parameters")
.At(token)
.Build());
}
var parameter = new TemplateParameterSyntax(GetTokens(argumentStartIndex), identifier.Value);
templateParameters.Add(parameter);
}
}
var definition = keyword.Symbol switch
{
Symbol.Extern => ParseExtern(startIndex, name, templateParameters),
Symbol.Func => ParseFunc(startIndex, name, templateParameters),
Symbol.Struct => ParseStruct(startIndex, name, templateParameters),
Symbol.Trait => ParseTrait(startIndex, name, templateParameters),
Symbol.Impl => ParseImpl(startIndex, name, templateParameters),
_ => throw new ParseException(Diagnostic _ => throw new ParseException(Diagnostic
.Error($"Expected 'extern', 'func', 'struct', 'trait' or 'impl' but found '{keyword.Symbol}'") .Error($"Expected 'extern', 'func', 'struct', 'trait' or 'impl' but found '{keyword.Symbol}'")
.WithHelp("Valid definition keywords are 'extern', 'func', 'struct', 'trait' and 'impl'") .WithHelp("Valid definition keywords are 'extern', 'func', 'struct', 'trait' and 'impl'")
@@ -68,7 +76,25 @@ public sealed class Parser
.Build()) .Build())
}; };
return node; definitions.Add(definition);
}
catch (ParseException ex)
{
_diagnostics.Add(ex.Diagnostic);
while (Peek().HasValue)
{
var token = Peek().Value;
if (token is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Trait or Symbol.Impl })
{
break;
}
Next();
}
}
}
return new SyntaxTree(_namespace, definitions, _diagnostics);
} }
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null) private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null)
@@ -113,19 +139,18 @@ public sealed class Parser
return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type); return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type);
} }
private DefinitionSyntax ParseExtern(int startIndex) private DefinitionSyntax ParseExtern(int startIndex, IdentifierToken name, IReadOnlyList<TemplateParameterSyntax> templateParameters)
{ {
var keyword = ExpectSymbol(); var keyword = ExpectSymbol();
return keyword.Symbol switch return keyword.Symbol switch
{ {
Symbol.Func => ParseExternFunc(startIndex), Symbol.Func => ParseExternFunc(startIndex, name, templateParameters),
_ => throw new ParseException(Diagnostic.Error($"Unexpected symbol {keyword.Symbol} after extern declaration").At(keyword).Build()) _ => throw new ParseException(Diagnostic.Error($"Unexpected symbol {keyword.Symbol} after extern declaration").At(keyword).Build())
}; };
} }
private ExternFuncSyntax ParseExternFunc(int startIndex) private ExternFuncSyntax ParseExternFunc(int startIndex, IdentifierToken name, IReadOnlyList<TemplateParameterSyntax> templateParameters)
{ {
var name = ExpectIdentifier();
var callName = name.Value; var callName = name.Value;
if (TryExpectSymbol(Symbol.Calls)) if (TryExpectSymbol(Symbol.Calls))
@@ -135,25 +160,22 @@ public sealed class Parser
var signature = ParseFuncSignature(); var signature = ParseFuncSignature();
return new ExternFuncSyntax(GetTokens(startIndex), _namespace, name.Value, callName, signature); return new ExternFuncSyntax(GetTokens(startIndex), _namespace, templateParameters, name.Value, callName, signature);
} }
private LocalFuncSyntax ParseFunc(int startIndex) private LocalFuncSyntax ParseFunc(int startIndex, IdentifierToken name, IReadOnlyList<TemplateParameterSyntax> templateParameters)
{ {
var name = ExpectIdentifier();
var signature = ParseFuncSignature(); var signature = ParseFuncSignature();
var body = ParseBlock(); var body = ParseBlock();
return new LocalFuncSyntax(GetTokens(startIndex), _namespace, name.Value, signature, body); return new LocalFuncSyntax(GetTokens(startIndex), _namespace, templateParameters, name.Value, signature, body);
} }
private StructSyntax ParseStruct(int startIndex) private DefinitionSyntax ParseStruct(int startIndex, IdentifierToken name, IReadOnlyList<TemplateParameterSyntax> templateParameters)
{ {
var name = ExpectIdentifier().Value;
ExpectSymbol(Symbol.OpenBrace); ExpectSymbol(Symbol.OpenBrace);
List<StructFieldSyntax> variables = []; List<StructFieldSyntax> fields = [];
var fieldIndex = 0; var fieldIndex = 0;
@@ -161,27 +183,25 @@ public sealed class Parser
{ {
var fieldStartIndex = _tokenIndex; var fieldStartIndex = _tokenIndex;
var variableName = ExpectIdentifier().Value; var fieldName = ExpectIdentifier().Value;
ExpectSymbol(Symbol.Colon); ExpectSymbol(Symbol.Colon);
var variableType = ParseType(); var fieldType = ParseType();
var variableValue = Optional<ExpressionSyntax>.Empty(); var fieldValue = Optional<ExpressionSyntax>.Empty();
if (TryExpectSymbol(Symbol.Assign)) if (TryExpectSymbol(Symbol.Assign))
{ {
variableValue = ParseExpression(); fieldValue = ParseExpression();
} }
variables.Add(new StructFieldSyntax(GetTokens(fieldStartIndex), fieldIndex++, variableName, variableType, variableValue)); fields.Add(new StructFieldSyntax(GetTokens(fieldStartIndex), fieldIndex++, fieldName, fieldType, fieldValue));
} }
return new StructSyntax(GetTokens(startIndex), _namespace, name, variables); return new StructSyntax(GetTokens(startIndex), _namespace, templateParameters, name.Value, fields);
} }
private TraitSyntax ParseTrait(int startIndex) private TraitSyntax ParseTrait(int startIndex, IdentifierToken name, IReadOnlyList<TemplateParameterSyntax> templateParameters)
{ {
var name = ExpectIdentifier().Value;
ExpectSymbol(Symbol.OpenBrace); ExpectSymbol(Symbol.OpenBrace);
List<TraitFuncSyntax> functions = []; List<TraitFuncSyntax> functions = [];
@@ -198,10 +218,10 @@ public sealed class Parser
functions.Add(new TraitFuncSyntax(GetTokens(funcStartIndex), funcName, signature)); functions.Add(new TraitFuncSyntax(GetTokens(funcStartIndex), funcName, signature));
} }
return new TraitSyntax(GetTokens(startIndex), _namespace, name, functions); return new TraitSyntax(GetTokens(startIndex), _namespace, templateParameters, name.Value, functions);
} }
private TraitImplSyntax ParseImpl(int startIndex) private TraitImplSyntax ParseImpl(int startIndex, IdentifierToken name, IReadOnlyList<TemplateParameterSyntax> templateParameters)
{ {
var traitType = ParseType(); var traitType = ParseType();
ExpectSymbol(Symbol.For); ExpectSymbol(Symbol.For);
@@ -222,7 +242,7 @@ public sealed class Parser
functions.AddRange(new TraitFuncImplSyntax(GetTokens(funcStartIndex), functionName, signature, body)); functions.AddRange(new TraitFuncImplSyntax(GetTokens(funcStartIndex), functionName, signature, body));
} }
return new TraitImplSyntax(GetTokens(startIndex), _namespace, traitType, forType, functions); return new TraitImplSyntax(GetTokens(startIndex), _namespace, templateParameters, traitType, forType, functions);
} }
private StatementSyntax ParseStatement() private StatementSyntax ParseStatement()
@@ -813,20 +833,6 @@ public sealed class Parser
return identifier; return identifier;
} }
private void RecoverToNextDefinition()
{
while (Peek().HasValue)
{
var token = Peek().Value;
if (token is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Trait or Symbol.Impl or Symbol.Template })
{
break;
}
Next();
}
}
private Optional<Token> Peek(int offset = 0) private Optional<Token> Peek(int offset = 0)
{ {
var peekIndex = _tokenIndex + offset; var peekIndex = _tokenIndex + offset;

View File

@@ -73,5 +73,4 @@ public enum Symbol
Extern, Extern,
Semi, Semi,
Arrow, Arrow,
Template
} }

View File

@@ -23,7 +23,6 @@ public sealed class Tokenizer
["impl"] = Symbol.Impl, ["impl"] = Symbol.Impl,
["for"] = Symbol.For, ["for"] = Symbol.For,
["extern"] = Symbol.Extern, ["extern"] = Symbol.Extern,
["template"] = Symbol.Template,
}; };
private static readonly Dictionary<char[], Symbol> Chians = new() private static readonly Dictionary<char[], Symbol> Chians = new()