Anon funcs works
This commit is contained in:
@@ -12,7 +12,6 @@ public sealed class Parser
|
||||
private readonly IEnumerable<Token> _tokens;
|
||||
|
||||
private readonly List<Diagnostic> _diagnostics = [];
|
||||
private NubType? _functionReturnType;
|
||||
private int _tokenIndex;
|
||||
|
||||
public Parser(IEnumerable<Token> tokens)
|
||||
@@ -24,7 +23,6 @@ public sealed class Parser
|
||||
public SyntaxTree Parse()
|
||||
{
|
||||
_diagnostics.Clear();
|
||||
_functionReturnType = null;
|
||||
_tokenIndex = 0;
|
||||
|
||||
if (TryExpectSymbol(Symbol.Namespace))
|
||||
@@ -61,7 +59,7 @@ public sealed class Parser
|
||||
Symbol.Func => ParseFunc(startIndex),
|
||||
Symbol.Struct => ParseStruct(startIndex),
|
||||
Symbol.Trait => ParseTrait(startIndex),
|
||||
Symbol.Impl => ParseImplementation(startIndex),
|
||||
Symbol.Impl => ParseImpl(startIndex),
|
||||
_ => throw new ParseException(Diagnostic
|
||||
.Error($"Expected 'func' or 'struct', but found '{keyword.Symbol}'")
|
||||
.WithHelp("Valid definition keywords are 'func' and 'struct'")
|
||||
@@ -72,6 +70,48 @@ public sealed class Parser
|
||||
return node;
|
||||
}
|
||||
|
||||
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null)
|
||||
{
|
||||
var startIndex = _tokenIndex;
|
||||
|
||||
List<FuncParameterSyntax> parameters = [];
|
||||
|
||||
if (thisArg != null)
|
||||
{
|
||||
parameters.Add(thisArg);
|
||||
}
|
||||
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
parameters.Add(ParseFuncParameter());
|
||||
|
||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||
{
|
||||
_diagnostics.Add(Diagnostic
|
||||
.Warning("Missing comma between function parameters")
|
||||
.WithHelp("Add a ',' to separate parameters")
|
||||
.At(token)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
||||
|
||||
return new FuncSignatureSyntax(GetTokens(startIndex), parameters, returnType);
|
||||
}
|
||||
|
||||
private FuncParameterSyntax ParseFuncParameter()
|
||||
{
|
||||
var startIndex = _tokenIndex;
|
||||
var name = ExpectIdentifier();
|
||||
ExpectSymbol(Symbol.Colon);
|
||||
var type = ParseType();
|
||||
|
||||
return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type);
|
||||
}
|
||||
|
||||
private DefinitionSyntax ParseExtern(int startIndex)
|
||||
{
|
||||
var keyword = ExpectSymbol();
|
||||
@@ -85,25 +125,6 @@ public sealed class Parser
|
||||
private ExternFuncSyntax ParseExternFunc(int startIndex)
|
||||
{
|
||||
var name = ExpectIdentifier();
|
||||
List<FuncParameterSyntax> parameters = [];
|
||||
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
parameters.Add(ParseFuncParameter());
|
||||
|
||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||
{
|
||||
_diagnostics.Add(Diagnostic
|
||||
.Warning("Missing comma between function parameters")
|
||||
.WithHelp("Add a ',' to separate parameters")
|
||||
.At(token)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
||||
var callName = name.Value;
|
||||
|
||||
if (TryExpectSymbol(Symbol.Calls))
|
||||
@@ -111,36 +132,18 @@ public sealed class Parser
|
||||
callName = ExpectIdentifier().Value;
|
||||
}
|
||||
|
||||
return new ExternFuncSyntax(GetTokens(startIndex), _namespace, name.Value, callName, parameters, returnType);
|
||||
var signature = ParseFuncSignature();
|
||||
|
||||
return new ExternFuncSyntax(GetTokens(startIndex), _namespace, name.Value, callName, signature);
|
||||
}
|
||||
|
||||
private LocalFuncSyntax ParseFunc(int startIndex)
|
||||
{
|
||||
var name = ExpectIdentifier();
|
||||
List<FuncParameterSyntax> parameters = [];
|
||||
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
parameters.Add(ParseFuncParameter());
|
||||
|
||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||
{
|
||||
_diagnostics.Add(Diagnostic
|
||||
.Warning("Missing comma between function parameters")
|
||||
.WithHelp("Add a ',' to separate parameters")
|
||||
.At(token)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
||||
_functionReturnType = returnType;
|
||||
|
||||
var signature = ParseFuncSignature();
|
||||
var body = ParseBlock();
|
||||
|
||||
return new LocalFuncSyntax(GetTokens(startIndex), _namespace, name.Value, parameters, body, returnType);
|
||||
return new LocalFuncSyntax(GetTokens(startIndex), _namespace, name.Value, signature, body);
|
||||
}
|
||||
|
||||
private StructSyntax ParseStruct(int startIndex)
|
||||
@@ -189,32 +192,15 @@ public sealed class Parser
|
||||
ExpectSymbol(Symbol.Func);
|
||||
|
||||
var funcName = ExpectIdentifier().Value;
|
||||
var parameters = new List<FuncParameterSyntax>();
|
||||
var signature = ParseFuncSignature();
|
||||
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
var parameter = ParseFuncParameter();
|
||||
parameters.Add(parameter);
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
||||
|
||||
functions.Add(new TraitFuncSyntax(GetTokens(funcStartIndex), funcName, parameters, returnType));
|
||||
functions.Add(new TraitFuncSyntax(GetTokens(funcStartIndex), funcName, signature));
|
||||
}
|
||||
|
||||
return new TraitSyntax(GetTokens(startIndex), _namespace, name, functions);
|
||||
}
|
||||
|
||||
private TraitImplSyntax ParseImplementation(int startIndex)
|
||||
private TraitImplSyntax ParseImpl(int startIndex)
|
||||
{
|
||||
var traitType = ParseType();
|
||||
ExpectSymbol(Symbol.For);
|
||||
@@ -228,47 +214,16 @@ public sealed class Parser
|
||||
var funcStartIndex = _tokenIndex;
|
||||
ExpectSymbol(Symbol.Func);
|
||||
var functionName = ExpectIdentifier().Value;
|
||||
var parameters = new List<FuncParameterSyntax>
|
||||
{
|
||||
new([], "this", forType)
|
||||
};
|
||||
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
parameters.Add(ParseFuncParameter());
|
||||
|
||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||
{
|
||||
_diagnostics.Add(Diagnostic
|
||||
.Warning("Missing comma between function parameters")
|
||||
.WithHelp("Add a ',' to separate parameters")
|
||||
.At(token)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
||||
|
||||
var signature = ParseFuncSignature(new FuncParameterSyntax([], "this", forType));
|
||||
var body = ParseBlock();
|
||||
|
||||
functions.AddRange(new TraitFuncImplSyntax(GetTokens(funcStartIndex), functionName, parameters, returnType, body));
|
||||
functions.AddRange(new TraitFuncImplSyntax(GetTokens(funcStartIndex), functionName, signature, body));
|
||||
}
|
||||
|
||||
return new TraitImplSyntax(GetTokens(startIndex), _namespace, traitType, forType, functions);
|
||||
}
|
||||
|
||||
private FuncParameterSyntax ParseFuncParameter()
|
||||
{
|
||||
var startIndex = _tokenIndex;
|
||||
var name = ExpectIdentifier();
|
||||
ExpectSymbol(Symbol.Colon);
|
||||
var type = ParseType();
|
||||
|
||||
return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type);
|
||||
}
|
||||
|
||||
private StatementSyntax ParseStatement()
|
||||
{
|
||||
var startIndex = _tokenIndex;
|
||||
@@ -353,7 +308,8 @@ public sealed class Parser
|
||||
ExpectSymbol(Symbol.Return);
|
||||
|
||||
var value = Optional<ExpressionSyntax>.Empty();
|
||||
if (_functionReturnType is not NubVoidType)
|
||||
|
||||
if (!TryExpectSymbol(Symbol.Semi))
|
||||
{
|
||||
value = ParseExpression();
|
||||
}
|
||||
@@ -500,27 +456,18 @@ public sealed class Parser
|
||||
{
|
||||
case Symbol.Func:
|
||||
{
|
||||
List<FuncParameterSyntax> parameters = [];
|
||||
List<AnonymousFuncParameterSyntax> parameters = [];
|
||||
ExpectSymbol(Symbol.OpenParen);
|
||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||
{
|
||||
var parameter = ParseFuncParameter();
|
||||
parameters.Add(parameter);
|
||||
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());
|
||||
}
|
||||
var parameterStartIndex = _tokenIndex;
|
||||
var name = ExpectIdentifier();
|
||||
parameters.Add(new AnonymousFuncParameterSyntax(GetTokens(parameterStartIndex), name.Value));
|
||||
}
|
||||
|
||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
||||
|
||||
var body = ParseBlock();
|
||||
|
||||
expr = new AnonymousFuncSyntax(GetTokens(startIndex), parameters, body, returnType);
|
||||
expr = new AnonymousFuncSyntax(GetTokens(startIndex), parameters, body);
|
||||
break;
|
||||
}
|
||||
case Symbol.OpenParen:
|
||||
|
||||
Reference in New Issue
Block a user