diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs index 2f02e3d..70b4a3e 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs @@ -1,6 +1,8 @@ +using Nub.Lang.Frontend.Lexing; + namespace Nub.Lang.Frontend.Parsing; -public class AddressOfNode(ExpressionNode expression) : ExpressionNode +public class AddressOfNode(IReadOnlyList tokens, ExpressionNode expression) : ExpressionNode(tokens) { public ExpressionNode Expression { get; } = expression; } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/ArrayIndexNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/ArrayIndexNode.cs index 4fe8606..174834b 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/ArrayIndexNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/ArrayIndexNode.cs @@ -1,6 +1,8 @@ +using Nub.Lang.Frontend.Lexing; + namespace Nub.Lang.Frontend.Parsing; -public class ArrayIndexNode(ExpressionNode expression, ExpressionNode index) : ExpressionNode +public class ArrayIndexNode(IReadOnlyList tokens, ExpressionNode expression, ExpressionNode index) : ExpressionNode(tokens) { public ExpressionNode Expression { get; } = expression; public ExpressionNode Index { get; } = index; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/BinaryExpressionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/BinaryExpressionNode.cs index d2e6f6b..40201b4 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/BinaryExpressionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/BinaryExpressionNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class BinaryExpressionNode(ExpressionNode left, BinaryExpressionOperator @operator, ExpressionNode right) : ExpressionNode +namespace Nub.Lang.Frontend.Parsing; + +public class BinaryExpressionNode(IReadOnlyList tokens, ExpressionNode left, BinaryExpressionOperator @operator, ExpressionNode right) : ExpressionNode(tokens) { public ExpressionNode Left { get; } = left; public BinaryExpressionOperator Operator { get; } = @operator; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/BlockNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/BlockNode.cs index 213cc7c..f990a66 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/BlockNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/BlockNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class BlockNode(List statements) : Node +namespace Nub.Lang.Frontend.Parsing; + +public class BlockNode(IReadOnlyList tokens, List statements) : Node(tokens) { public List Statements { get; } = statements; } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/BreakNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/BreakNode.cs index bc5277d..4356746 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/BreakNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/BreakNode.cs @@ -1,3 +1,5 @@ +using Nub.Lang.Frontend.Lexing; + namespace Nub.Lang.Frontend.Parsing; -public class BreakNode : StatementNode; \ No newline at end of file +public class BreakNode(IReadOnlyList tokens) : StatementNode(tokens); \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/CastNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/CastNode.cs index df0e14e..03117ae 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/CastNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/CastNode.cs @@ -1,6 +1,8 @@ +using Nub.Lang.Frontend.Lexing; + namespace Nub.Lang.Frontend.Parsing; -public class CastNode(NubType targetType, ExpressionNode expression) : ExpressionNode +public class CastNode(IReadOnlyList tokens, NubType targetType, ExpressionNode expression) : ExpressionNode(tokens) { public NubType TargetType { get; } = targetType; public ExpressionNode Expression { get; } = expression; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/ContinueNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/ContinueNode.cs index 484f7d3..7724bc3 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/ContinueNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/ContinueNode.cs @@ -1,3 +1,5 @@ +using Nub.Lang.Frontend.Lexing; + namespace Nub.Lang.Frontend.Parsing; -public class ContinueNode : StatementNode; \ No newline at end of file +public class ContinueNode(IReadOnlyList tokens) : StatementNode(tokens); \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/DefinitionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/DefinitionNode.cs index 6077565..f60c5e2 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/DefinitionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/DefinitionNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public abstract class DefinitionNode(Optional documentation) : Node +namespace Nub.Lang.Frontend.Parsing; + +public abstract class DefinitionNode(IReadOnlyList tokens, Optional documentation) : Node(tokens) { public Optional Documentation { get; set; } = documentation; } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/DereferenceNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/DereferenceNode.cs index 4bb6097..151edd4 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/DereferenceNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/DereferenceNode.cs @@ -1,6 +1,8 @@ +using Nub.Lang.Frontend.Lexing; + namespace Nub.Lang.Frontend.Parsing; -public class DereferenceNode(ExpressionNode expression) : ExpressionNode +public class DereferenceNode(IReadOnlyList tokens, ExpressionNode expression) : ExpressionNode(tokens) { public ExpressionNode Expression { get; } = expression; } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/ExpressionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/ExpressionNode.cs index c02c83c..b495684 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/ExpressionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/ExpressionNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public abstract class ExpressionNode : Node +namespace Nub.Lang.Frontend.Parsing; + +public abstract class ExpressionNode(IReadOnlyList tokens) : Node(tokens) { private NubType? _type; public NubType Type diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/ExternFuncDefinitionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/ExternFuncDefinitionNode.cs index b3ab11a..e5df5b6 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/ExternFuncDefinitionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/ExternFuncDefinitionNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class ExternFuncDefinitionNode(string name, List parameters, Optional returnType, Optional documentation) : DefinitionNode(documentation) +namespace Nub.Lang.Frontend.Parsing; + +public class ExternFuncDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, List parameters, Optional returnType) : DefinitionNode(tokens, documentation) { public string Name { get; } = name; public List Parameters { get; } = parameters; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/FuncCallExpressionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/FuncCallExpressionNode.cs index de013d2..3e982c1 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/FuncCallExpressionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/FuncCallExpressionNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class FuncCallExpressionNode(FuncCall funcCall) : ExpressionNode +namespace Nub.Lang.Frontend.Parsing; + +public class FuncCallExpressionNode(IReadOnlyList tokens, FuncCall funcCall) : ExpressionNode(tokens) { public FuncCall FuncCall { get; } = funcCall; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/FuncCallStatementNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/FuncCallStatementNode.cs index 8b10d5e..16317c8 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/FuncCallStatementNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/FuncCallStatementNode.cs @@ -1,8 +1,10 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class FuncCallStatementNode(FuncCall funcCall) : StatementNode +namespace Nub.Lang.Frontend.Parsing; + +public class FuncCallStatementNode(IReadOnlyList tokens, FuncCall funcCall) : StatementNode(tokens) { public FuncCall FuncCall { get; } = funcCall; - + public override string ToString() => FuncCall.ToString(); } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/IdentifierNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/IdentifierNode.cs index 322b281..58ddb78 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/IdentifierNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/IdentifierNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class IdentifierNode(string identifier) : ExpressionNode +namespace Nub.Lang.Frontend.Parsing; + +public class IdentifierNode(IReadOnlyList tokens, string identifier) : ExpressionNode(tokens) { public string Identifier { get; } = identifier; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/IfNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/IfNode.cs index ce3f10c..f49af8d 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/IfNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/IfNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class IfNode(ExpressionNode condition, BlockNode body, Optional> @else) : StatementNode +namespace Nub.Lang.Frontend.Parsing; + +public class IfNode(IReadOnlyList tokens, ExpressionNode condition, BlockNode body, Optional> @else) : StatementNode(tokens) { public ExpressionNode Condition { get; } = condition; public BlockNode Body { get; } = body; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/LiteralNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/LiteralNode.cs index b9798bc..a7a7d97 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/LiteralNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/LiteralNode.cs @@ -1,7 +1,9 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class LiteralNode(string literal, NubType type) : ExpressionNode +namespace Nub.Lang.Frontend.Parsing; + +public class LiteralNode(IReadOnlyList tokens, string literal, NubType literalType) : ExpressionNode(tokens) { public string Literal { get; } = literal; - public NubType LiteralType { get; } = type; + public NubType LiteralType { get; } = literalType; } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/LocalFuncDefinitionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/LocalFuncDefinitionNode.cs index 8e987c4..da0059a 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/LocalFuncDefinitionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/LocalFuncDefinitionNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class LocalFuncDefinitionNode(string name, List parameters, BlockNode body, Optional returnType, bool global, Optional documentation) : DefinitionNode(documentation) +namespace Nub.Lang.Frontend.Parsing; + +public class LocalFuncDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, List parameters, BlockNode body, Optional returnType, bool global) : DefinitionNode(tokens, documentation) { public string Name { get; } = name; public List Parameters { get; } = parameters; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/MemberAccessNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/MemberAccessNode.cs index 592e6ef..74f5463 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/MemberAccessNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/MemberAccessNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class MemberAccessNode(ExpressionNode expression, string member) : ExpressionNode +namespace Nub.Lang.Frontend.Parsing; + +public class MemberAccessNode(IReadOnlyList tokens, ExpressionNode expression, string member) : ExpressionNode(tokens) { public ExpressionNode Expression { get; } = expression; public string Member { get; } = member; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/ModuleNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/ModuleNode.cs index c992fde..fd09023 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/ModuleNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/ModuleNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class ModuleNode(string path, List imports, List definitions) : Node +namespace Nub.Lang.Frontend.Parsing; + +public class ModuleNode(IReadOnlyList tokens, string path, List imports, List definitions) : Node(tokens) { public string Path { get; } = path; public List Imports { get; } = imports; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/Node.cs b/src/compiler/Nub.Lang/Frontend/Parsing/Node.cs index 0165fd8..7f84457 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/Node.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/Node.cs @@ -1,3 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public abstract class Node; \ No newline at end of file +namespace Nub.Lang.Frontend.Parsing; + +public abstract class Node(IReadOnlyList tokens) +{ + public IReadOnlyList Tokens { get; set; } = tokens; +} \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs index 9b1241b..24ecaf7 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs @@ -29,11 +29,12 @@ public class Parser } } - return new ModuleNode(rootFilePath, imports, definitions); + return new ModuleNode(GetTokensForNode(0), rootFilePath, imports, definitions); } private DefinitionNode ParseDefinition() { + var startIndex = _index; List modifiers = []; List documentationParts = []; @@ -53,13 +54,13 @@ public class Parser var keyword = ExpectSymbol(); return keyword.Symbol switch { - Symbol.Func => ParseFuncDefinition(modifiers, Optional.OfNullable(documentation)), - Symbol.Struct => ParseStruct(modifiers, Optional.OfNullable(documentation)), + Symbol.Func => ParseFuncDefinition(startIndex, modifiers, Optional.OfNullable(documentation)), + Symbol.Struct => ParseStruct(startIndex, modifiers, Optional.OfNullable(documentation)), _ => throw new Exception("Unexpected symbol: " + keyword.Symbol) }; } - private DefinitionNode ParseFuncDefinition(List modifiers, Optional documentation) + private DefinitionNode ParseFuncDefinition(int startIndex, List modifiers, Optional documentation) { var name = ExpectIdentifier(); List parameters = []; @@ -86,7 +87,7 @@ public class Parser throw new Exception($"Modifiers: {string.Join(", ", modifiers)} is not valid for an extern function"); } - return new ExternFuncDefinitionNode(name.Value, parameters, returnType, documentation); + return new ExternFuncDefinitionNode(GetTokensForNode(startIndex), documentation, name.Value, parameters, returnType); } var body = ParseBlock(); @@ -97,10 +98,10 @@ public class Parser throw new Exception($"Modifiers: {string.Join(", ", modifiers)} is not valid for a local function"); } - return new LocalFuncDefinitionNode(name.Value, parameters, body, returnType, global, documentation); + return new LocalFuncDefinitionNode(GetTokensForNode(startIndex), documentation, name.Value, parameters, body, returnType, global); } - private StructDefinitionNode ParseStruct(List _, Optional documentation) + private StructDefinitionNode ParseStruct(int startIndex, List _, Optional documentation) { var name = ExpectIdentifier().Value; @@ -124,7 +125,7 @@ public class Parser variables.Add(new StructField(variableName, variableType, variableValue)); } - return new StructDefinitionNode(name, variables, documentation); + return new StructDefinitionNode(GetTokensForNode(startIndex), documentation, name, variables); } private FuncParameter ParseFuncParameter() @@ -146,6 +147,7 @@ public class Parser private StatementNode ParseStatement() { + var startIndex = _index; var token = ExpectToken(); switch (token) { @@ -163,19 +165,19 @@ public class Parser TryExpectSymbol(Symbol.Comma); } - return new FuncCallStatementNode(new FuncCall(identifier.Value, parameters)); + return new FuncCallStatementNode(GetTokensForNode(startIndex), new FuncCall(identifier.Value, parameters)); } case Symbol.Assign: { var value = ParseExpression(); - return new VariableAssignmentNode(identifier.Value, Optional.Empty(), value); + return new VariableAssignmentNode(GetTokensForNode(startIndex), identifier.Value, Optional.Empty(), value); } case Symbol.Colon: { var type = ParseType(); ExpectSymbol(Symbol.Assign); var value = ParseExpression(); - return new VariableAssignmentNode(identifier.Value, type, value); + return new VariableAssignmentNode(GetTokensForNode(startIndex), identifier.Value, type, value); } default: { @@ -187,11 +189,11 @@ public class Parser { return symbol.Symbol switch { - Symbol.Return => ParseReturn(), - Symbol.If => ParseIf(), - Symbol.While => ParseWhile(), - Symbol.Break => new BreakNode(), - Symbol.Continue => new ContinueNode(), + Symbol.Return => ParseReturn(startIndex), + Symbol.If => ParseIf(startIndex), + Symbol.While => ParseWhile(startIndex), + Symbol.Break => new BreakNode(GetTokensForNode(startIndex)), + Symbol.Continue => new ContinueNode(GetTokensForNode(startIndex)), _ => throw new Exception($"Unexpected symbol {symbol.Symbol}") }; } @@ -202,7 +204,7 @@ public class Parser } } - private ReturnNode ParseReturn() + private ReturnNode ParseReturn(int startIndex) { var value = Optional.Empty(); if (!TryExpectSymbol(Symbol.Semicolon)) @@ -210,10 +212,10 @@ public class Parser value = ParseExpression(); } - return new ReturnNode(value); + return new ReturnNode(GetTokensForNode(startIndex), value); } - private IfNode ParseIf() + private IfNode ParseIf(int startIndex) { var condition = ParseExpression(); var body = ParseBlock(); @@ -221,23 +223,25 @@ public class Parser var elseStatement = Optional>.Empty(); if (TryExpectSymbol(Symbol.Else)) { + var newStartIndex = _index; elseStatement = TryExpectSymbol(Symbol.If) - ? (Variant)ParseIf() + ? (Variant)ParseIf(newStartIndex) : (Variant)ParseBlock(); } - return new IfNode(condition, body, elseStatement); + return new IfNode(GetTokensForNode(startIndex), condition, body, elseStatement); } - private WhileNode ParseWhile() + private WhileNode ParseWhile(int startIndex) { var condition = ParseExpression(); var body = ParseBlock(); - return new WhileNode(condition, body); + return new WhileNode(GetTokensForNode(startIndex), condition, body); } private ExpressionNode ParseExpression(int precedence = 0) { + var startIndex = _index; var left = ParsePrimaryExpression(); while (true) @@ -250,7 +254,7 @@ public class Parser Next(); var right = ParseExpression(GetBinaryOperatorPrecedence(op.Value) + 1); - left = new BinaryExpressionNode(left, op.Value, right); + left = new BinaryExpressionNode(GetTokensForNode(startIndex), left, op.Value, right); } return left; @@ -316,6 +320,7 @@ public class Parser private ExpressionNode ParsePrimaryExpression() { + var startIndex = _index; ExpressionNode expr; var token = ExpectToken(); @@ -323,7 +328,7 @@ public class Parser { case LiteralToken literal: { - expr = new LiteralNode(literal.Value, literal.Type); + expr = new LiteralNode(GetTokensForNode(startIndex), literal.Value, literal.Type); break; } case IdentifierToken identifier: @@ -341,12 +346,12 @@ public class Parser TryExpectSymbol(Symbol.Comma); } - expr = new FuncCallExpressionNode(new FuncCall(identifier.Value, parameters)); + expr = new FuncCallExpressionNode(GetTokensForNode(startIndex), new FuncCall(identifier.Value, parameters)); break; } default: { - expr = new IdentifierNode(identifier.Value); + expr = new IdentifierNode(GetTokensForNode(startIndex), identifier.Value); break; } } @@ -371,7 +376,7 @@ public class Parser ExpectSymbol(Symbol.OpenParen); var expressionToCast = ParseExpression(); ExpectSymbol(Symbol.CloseParen); - expr = new CastNode(type, expressionToCast); + expr = new CastNode(GetTokensForNode(startIndex), type, expressionToCast); break; } case Symbol.New: @@ -387,25 +392,25 @@ public class Parser initializers.Add(name, value); } - expr = new StructInitializerNode(type, initializers); + expr = new StructInitializerNode(GetTokensForNode(startIndex), type, initializers); break; } case Symbol.Ampersand: { var expression = ParsePrimaryExpression(); - expr = new AddressOfNode(expression); + expr = new AddressOfNode(GetTokensForNode(startIndex), expression); break; } case Symbol.Minus: { var expression = ParsePrimaryExpression(); - expr = new UnaryExpressionNode(UnaryExpressionOperator.Negate, expression); + expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Negate, expression); break; } case Symbol.Bang: { var expression = ParsePrimaryExpression(); - expr = new UnaryExpressionNode(UnaryExpressionOperator.Invert, expression); + expr = new UnaryExpressionNode(GetTokensForNode(startIndex), UnaryExpressionOperator.Invert, expression); break; } default: @@ -422,23 +427,23 @@ public class Parser } } - return ParsePostfixOperators(expr); + return ParsePostfixOperators(startIndex, expr); } - private ExpressionNode ParsePostfixOperators(ExpressionNode expr) + private ExpressionNode ParsePostfixOperators(int startIndex, ExpressionNode expr) { while (true) { if (TryExpectSymbol(Symbol.Caret)) { - expr = new DereferenceNode(expr); + expr = new DereferenceNode(GetTokensForNode(startIndex), expr); continue; } if (TryExpectSymbol(Symbol.Period)) { var structMember = ExpectIdentifier().Value; - expr = new MemberAccessNode(expr, structMember); + expr = new MemberAccessNode(GetTokensForNode(startIndex), expr, structMember); continue; } @@ -446,7 +451,7 @@ public class Parser { var index = ParseExpression(); ExpectSymbol(Symbol.CloseBracket); - expr = new ArrayIndexNode(expr, index); + expr = new ArrayIndexNode(GetTokensForNode(startIndex), expr, index); continue; } @@ -458,6 +463,7 @@ public class Parser private BlockNode ParseBlock() { + var startIndex = _index; ExpectSymbol(Symbol.OpenBrace); List statements = []; while (!TryExpectSymbol(Symbol.CloseBrace)) @@ -465,7 +471,7 @@ public class Parser statements.Add(ParseStatement()); } - return new BlockNode(statements); + return new BlockNode(GetTokensForNode(startIndex), statements); } private NubType ParseType() @@ -592,4 +598,9 @@ public class Parser _index++; } + + private IReadOnlyList GetTokensForNode(int startIndex) + { + return _tokens[startIndex..Math.Min(_index, _tokens.Count - 1)]; + } } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/ReturnNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/ReturnNode.cs index 3e5d38e..c4845cd 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/ReturnNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/ReturnNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class ReturnNode(Optional value) : StatementNode +namespace Nub.Lang.Frontend.Parsing; + +public class ReturnNode(IReadOnlyList tokens, Optional value) : StatementNode(tokens) { public Optional Value { get; } = value; } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/StatementNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/StatementNode.cs index 9ad7834..3217030 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/StatementNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/StatementNode.cs @@ -1,3 +1,5 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public abstract class StatementNode : Node; \ No newline at end of file +namespace Nub.Lang.Frontend.Parsing; + +public abstract class StatementNode(IReadOnlyList tokens) : Node(tokens); \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/StructDefinitionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/StructDefinitionNode.cs index 43f3fa4..9f9da96 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/StructDefinitionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/StructDefinitionNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class StructDefinitionNode(string name, List fields, Optional documentation) : DefinitionNode(documentation) +namespace Nub.Lang.Frontend.Parsing; + +public class StructDefinitionNode(IReadOnlyList tokens, Optional documentation, string name, List fields) : DefinitionNode(tokens, documentation) { public string Name { get; } = name; public List Fields { get; } = fields; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/StructInitializerNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/StructInitializerNode.cs index 2ab9b85..6c8a0a3 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/StructInitializerNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/StructInitializerNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class StructInitializerNode(NubType structType, Dictionary initializers) : ExpressionNode +namespace Nub.Lang.Frontend.Parsing; + +public class StructInitializerNode(IReadOnlyList tokens, NubType structType, Dictionary initializers) : ExpressionNode(tokens) { public NubType StructType { get; } = structType; public Dictionary Initializers { get; } = initializers; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/UnaryExpressionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/UnaryExpressionNode.cs index 7a49d5e..d447340 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/UnaryExpressionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/UnaryExpressionNode.cs @@ -1,6 +1,8 @@ +using Nub.Lang.Frontend.Lexing; + namespace Nub.Lang.Frontend.Parsing; -public class UnaryExpressionNode(UnaryExpressionOperator @operator, ExpressionNode operand) : ExpressionNode +public class UnaryExpressionNode(IReadOnlyList tokens, UnaryExpressionOperator @operator, ExpressionNode operand) : ExpressionNode(tokens) { public UnaryExpressionOperator Operator { get; } = @operator; public ExpressionNode Operand { get; } = operand; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/VariableAssignmentNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/VariableAssignmentNode.cs index 2964d04..575f71c 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/VariableAssignmentNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/VariableAssignmentNode.cs @@ -1,6 +1,8 @@ -namespace Nub.Lang.Frontend.Parsing; +using Nub.Lang.Frontend.Lexing; -public class VariableAssignmentNode(string name, Optional explicitType, ExpressionNode value) : StatementNode +namespace Nub.Lang.Frontend.Parsing; + +public class VariableAssignmentNode(IReadOnlyList tokens, string name, Optional explicitType, ExpressionNode value) : StatementNode(tokens) { public string Name { get; } = name; public Optional ExplicitType { get; } = explicitType; diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/WhileNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/WhileNode.cs index cc26d33..cc450c7 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/WhileNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/WhileNode.cs @@ -1,6 +1,8 @@ +using Nub.Lang.Frontend.Lexing; + namespace Nub.Lang.Frontend.Parsing; -public class WhileNode(ExpressionNode condition, BlockNode body) : StatementNode +public class WhileNode(IReadOnlyList tokens, ExpressionNode condition, BlockNode body) : StatementNode(tokens) { public ExpressionNode Condition { get; } = condition; public BlockNode Body { get; } = body;