This commit is contained in:
nub31
2025-05-16 23:39:57 +02:00
parent 5a6c56c5c2
commit 1371e95b76
4 changed files with 144 additions and 110 deletions

View File

@@ -0,0 +1,7 @@
namespace Nub.Lang.Frontend.Parsing;
public class CastNode(NubType targetType, ExpressionNode expression) : ExpressionNode
{
public NubType TargetType { get; } = targetType;
public ExpressionNode Expression { get; } = expression;
}

View File

@@ -304,53 +304,70 @@ public class Parser
}
private ExpressionNode ParsePrimaryExpression()
{
var token = ExpectToken();
switch (token)
{
var token = ExpectToken();
switch (token)
case LiteralToken literal:
{
case LiteralToken literal:
return new LiteralNode(literal.Value, literal.Type);
}
case IdentifierToken identifier:
{
return ParseExpressionIdentifier(identifier);
}
case SymbolToken symbolToken:
{
switch (symbolToken.Symbol)
{
return new LiteralNode(literal.Value, literal.Type);
}
case IdentifierToken identifier:
{
return ParseExpressionIdentifier(identifier);
}
case SymbolToken symbolToken:
{
switch (symbolToken.Symbol)
case Symbol.OpenParen:
{
case Symbol.OpenParen:
// This is ugly
var nextToken = Peek();
if (nextToken is { Value: IdentifierToken })
{
var expression = ParseExpression();
ExpectSymbol(Symbol.CloseParen);
return expression;
}
case Symbol.New:
{
var type = ParseType();
Dictionary<string, ExpressionNode> initializers = [];
ExpectSymbol(Symbol.OpenBrace);
while (!TryExpectSymbol(Symbol.CloseBrace))
var startIndex = _index;
var identifierToken = ExpectIdentifier();
var type = NubType.Parse(identifierToken.Value);
if (TryExpectSymbol(Symbol.CloseParen))
{
var name = ExpectIdentifier().Value;
ExpectSymbol(Symbol.Assign);
var value = ParseExpression();
initializers.Add(name, value);
var expressionToCast = ParsePrimaryExpression();
return new CastNode(type, expressionToCast);
}
return new StructInitializerNode(type, initializers);
_index = startIndex;
}
default:
var expression = ParseExpression();
ExpectSymbol(Symbol.CloseParen);
return expression;
}
case Symbol.New:
{
var type = ParseType();
Dictionary<string, ExpressionNode> initializers = [];
ExpectSymbol(Symbol.OpenBrace);
while (!TryExpectSymbol(Symbol.CloseBrace))
{
throw new Exception($"Unknown symbol: {symbolToken.Symbol}");
var name = ExpectIdentifier().Value;
ExpectSymbol(Symbol.Assign);
var value = ParseExpression();
initializers.Add(name, value);
}
return new StructInitializerNode(type, initializers);
}
default:
{
throw new Exception($"Unknown symbol: {symbolToken.Symbol}");
}
}
default:
throw new Exception($"Unexpected token type {token.GetType().Name}");
}
default:
throw new Exception($"Unexpected token type {token.GetType().Name}");
}
}
private ExpressionNode ParseExpressionIdentifier(IdentifierToken identifier)
{

View File

@@ -245,7 +245,6 @@ public class TypeChecker
case LiteralNode literal:
resultType = literal.LiteralType;
break;
case IdentifierNode identifier:
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
{
@@ -253,23 +252,21 @@ public class TypeChecker
}
resultType = varType;
break;
case BinaryExpressionNode binaryExpr:
resultType = TypeCheckBinaryExpression(binaryExpr);
break;
case CastNode cast:
resultType = TypeCheckCast(cast);
break;
case FuncCallExpressionNode funcCallExpr:
resultType = TypeCheckFuncCall(funcCallExpr.FuncCall);
break;
case StructInitializerNode structInit:
resultType = TypeCheckStructInitializer(structInit);
break;
case StructFieldAccessorNode fieldAccess:
resultType = TypeCheckStructFieldAccess(fieldAccess);
break;
default:
throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}");
}
@@ -316,6 +313,13 @@ public class TypeChecker
}
}
private NubType TypeCheckCast(CastNode cast)
{
TypeCheckExpression(cast.Expression);
// TODO: Check if castable
return cast.TargetType;
}
private NubType TypeCheckStructInitializer(StructInitializerNode structInit)
{
var structType = structInit.StructType;