From 62c9d86cda1b002a01b9e70ff6c01d97d7018a5f Mon Sep 17 00:00:00 2001 From: nub31 Date: Tue, 22 Jul 2025 23:01:29 +0200 Subject: [PATCH] Parser now uses enumerator --- example/src/c.nub | 2 - example/src/main.nub | 3 +- src/compiler/NubLang/Syntax/Parsing/Parser.cs | 257 +++++++----------- src/runtime/targets/x64.s | 2 +- 4 files changed, 105 insertions(+), 159 deletions(-) diff --git a/example/src/c.nub b/example/src/c.nub index b5b09da..67309ca 100644 --- a/example/src/c.nub +++ b/example/src/c.nub @@ -1,4 +1,2 @@ -namespace c - extern func printf(fmt: cstring, arg: i64): void extern func puts(fmt: cstring) diff --git a/example/src/main.nub b/example/src/main.nub index 2cce740..b97d3d7 100644 --- a/example/src/main.nub +++ b/example/src/main.nub @@ -1,6 +1,5 @@ func main(args: []cstring): i64 { - c::puts("test") - + puts("test") return 0 } diff --git a/src/compiler/NubLang/Syntax/Parsing/Parser.cs b/src/compiler/NubLang/Syntax/Parsing/Parser.cs index 532ded2..bc8dfde 100644 --- a/src/compiler/NubLang/Syntax/Parsing/Parser.cs +++ b/src/compiler/NubLang/Syntax/Parsing/Parser.cs @@ -8,10 +8,10 @@ namespace NubLang.Syntax.Parsing; public sealed class Parser { - private IEnumerable _tokens = null!; - + private IEnumerator _tokenEnumerator = null!; private readonly List _diagnostics = []; - private int _tokenIndex; + private Token? _currentToken; + private bool _hasCurrentToken; public IReadOnlyList GetDiagnostics() { @@ -21,12 +21,13 @@ public sealed class Parser public SyntaxTree Parse(IEnumerable tokens) { _diagnostics.Clear(); - _tokenIndex = 0; - _tokens = tokens; + _tokenEnumerator = tokens.GetEnumerator(); + _hasCurrentToken = _tokenEnumerator.MoveNext(); + _currentToken = _hasCurrentToken ? _tokenEnumerator.Current : null; var definitions = new List(); - while (Peek().HasValue) + while (_hasCurrentToken) { try { @@ -49,10 +50,9 @@ public sealed class Parser catch (ParseException ex) { _diagnostics.Add(ex.Diagnostic); - while (Peek().HasValue) + while (_hasCurrentToken) { - var token = Peek().Value; - if (token is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Interface }) + if (_currentToken is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Interface }) { break; } @@ -80,7 +80,7 @@ public sealed class Parser { parameters.Add(ParseFuncParameter()); - if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen }) + if (!TryExpectSymbol(Symbol.Comma) && _currentToken is not SymbolToken { Symbol: Symbol.CloseParen }) { _diagnostics.Add(Diagnostic .Warning("Missing comma between function parameters") @@ -204,14 +204,7 @@ public sealed class Parser private StatementSyntax ParseStatement() { - if (!Peek().TryGetValue(out var token)) - { - throw new ParseException(Diagnostic - .Error("Unexpected end of file while parsing statement") - .Build()); - } - - if (token is SymbolToken symbol) + if (_currentToken is SymbolToken symbol) { switch (symbol.Symbol) { @@ -269,7 +262,6 @@ public sealed class Parser private StatementSyntax ParseBreak() { ExpectSymbol(Symbol.Break); - Next(); return new BreakSyntax(); } @@ -322,18 +314,10 @@ public sealed class Parser { var left = ParsePrimaryExpression(); - while (true) + while (_currentToken is SymbolToken symbolToken && TryGetBinaryOperator(symbolToken.Symbol, out var op) && GetBinaryOperatorPrecedence(op.Value) >= precedence) { - var token = Peek(); - if (!token.HasValue || token.Value is not SymbolToken symbolToken || !TryGetBinaryOperator(symbolToken.Symbol, out var op) || - GetBinaryOperatorPrecedence(op.Value) < precedence) - { - break; - } - Next(); var right = ParseExpression(GetBinaryOperatorPrecedence(op.Value) + 1); - left = new BinaryExpressionSyntax(left, op.Value, right); } @@ -400,125 +384,99 @@ public sealed class Parser private ExpressionSyntax ParsePrimaryExpression() { - ExpressionSyntax expr; - var token = ExpectToken(); - switch (token) + var expr = token switch { - case LiteralToken literal: + LiteralToken literal => new LiteralSyntax(literal.Value, literal.Kind), + IdentifierToken identifier => new IdentifierSyntax(identifier.Value), + SymbolToken symbolToken => symbolToken.Symbol switch { - expr = new LiteralSyntax(literal.Value, literal.Kind); - break; - } - case IdentifierToken identifier: - { - expr = new IdentifierSyntax(identifier.Value); - break; - } - case SymbolToken symbolToken: - { - switch (symbolToken.Symbol) - { - case Symbol.Func: - { - List parameters = []; - ExpectSymbol(Symbol.OpenParen); - while (!TryExpectSymbol(Symbol.CloseParen)) - { - var name = ExpectIdentifier(); - parameters.Add(new ArrowFuncParameterSyntax(name.Value)); - } - - BlockSyntax body; - - if (TryExpectSymbol(Symbol.Arrow)) - { - var returnValue = ParseExpression(); - var arrowExpression = new ReturnSyntax(returnValue); - body = new BlockSyntax([arrowExpression]); - } - else - { - body = ParseBlock(); - } - - expr = new ArrowFuncSyntax(parameters, body); - break; - } - case Symbol.OpenParen: - { - var expression = ParseExpression(); - ExpectSymbol(Symbol.CloseParen); - expr = expression; - break; - } - case Symbol.Minus: - { - var expression = ParsePrimaryExpression(); - expr = new UnaryExpressionSyntax(UnaryOperator.Negate, expression); - break; - } - case Symbol.Bang: - { - var expression = ParsePrimaryExpression(); - expr = new UnaryExpressionSyntax(UnaryOperator.Invert, expression); - break; - } - case Symbol.OpenBracket: - { - var capacity = ParseExpression(); - ExpectSymbol(Symbol.CloseBracket); - var type = ParseType(); - expr = new ArrayInitializerSyntax(capacity, type); - break; - } - case Symbol.Alloc: - { - var type = ParseType(); - Dictionary initializers = []; - ExpectSymbol(Symbol.OpenBrace); - while (!TryExpectSymbol(Symbol.CloseBrace)) - { - var name = ExpectIdentifier().Value; - ExpectSymbol(Symbol.Assign); - var value = ParseExpression(); - initializers.Add(name, value); - } - - expr = new StructInitializerSyntax(type, initializers); - break; - } - default: - { - throw new ParseException(Diagnostic - .Error($"Unexpected symbol '{symbolToken.Symbol}' in expression") - .WithHelp("Expected literal, identifier, or '(' to start expression") - .Build()); - } - } - - break; - } - default: - { - throw new ParseException(Diagnostic - .Error($"Unexpected token '{token.GetType().Name}' in expression") - .WithHelp("Expected literal, identifier, or parenthesized expression") - .Build()); - } - } + Symbol.Func => ParseArrowFunction(), + Symbol.OpenParen => ParseParenthesizedExpression(), + Symbol.Minus => new UnaryExpressionSyntax(UnaryOperator.Negate, ParsePrimaryExpression()), + Symbol.Bang => new UnaryExpressionSyntax(UnaryOperator.Invert, ParsePrimaryExpression()), + Symbol.OpenBracket => ParseArrayInitializer(), + Symbol.Alloc => ParseStructInitializer(), + _ => throw new ParseException(Diagnostic + .Error($"Unexpected symbol '{symbolToken.Symbol}' in expression") + .WithHelp("Expected literal, identifier, or '(' to start expression") + .Build()) + }, + _ => throw new ParseException(Diagnostic + .Error($"Unexpected token '{token.GetType().Name}' in expression") + .WithHelp("Expected literal, identifier, or parenthesized expression") + .Build()) + }; return ParsePostfixOperators(expr); } + private ExpressionSyntax ParseArrowFunction() + { + List parameters = []; + ExpectSymbol(Symbol.OpenParen); + while (!TryExpectSymbol(Symbol.CloseParen)) + { + var name = ExpectIdentifier(); + parameters.Add(new ArrowFuncParameterSyntax(name.Value)); + } + + ExpectSymbol(Symbol.Arrow); + BlockSyntax body; + + if (_currentToken is SymbolToken { Symbol: Symbol.OpenBrace }) + { + var returnValue = ParseExpression(); + var arrowExpression = new ReturnSyntax(returnValue); + body = new BlockSyntax([arrowExpression]); + } + else + { + body = ParseBlock(); + } + + return new ArrowFuncSyntax(parameters, body); + } + + private ExpressionSyntax ParseParenthesizedExpression() + { + var expression = ParseExpression(); + ExpectSymbol(Symbol.CloseParen); + return expression; + } + + private ExpressionSyntax ParseArrayInitializer() + { + var capacity = ParseExpression(); + ExpectSymbol(Symbol.CloseBracket); + var type = ParseType(); + return new ArrayInitializerSyntax(capacity, type); + } + + private ExpressionSyntax ParseStructInitializer() + { + var type = ParseType(); + Dictionary initializers = []; + ExpectSymbol(Symbol.OpenBrace); + while (!TryExpectSymbol(Symbol.CloseBrace)) + { + var name = ExpectIdentifier().Value; + ExpectSymbol(Symbol.Assign); + var value = ParseExpression(); + initializers.Add(name, value); + } + + return new StructInitializerSyntax(type, initializers); + } + private ExpressionSyntax ParsePostfixOperators(ExpressionSyntax expr) { - while (true) + while (_hasCurrentToken) { if (TryExpectSymbol(Symbol.Ampersand)) { expr = new AddressOfSyntax(expr); - break; + continue; } if (TryExpectSymbol(Symbol.Caret)) @@ -548,7 +506,7 @@ public sealed class Parser while (!TryExpectSymbol(Symbol.CloseParen)) { parameters.Add(ParseExpression()); - if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen }) + if (!TryExpectSymbol(Symbol.Comma) && _currentToken is not SymbolToken { Symbol: Symbol.CloseParen }) { _diagnostics.Add(Diagnostic .Warning("Missing comma between function arguments") @@ -571,7 +529,7 @@ public sealed class Parser { ExpectSymbol(Symbol.OpenBrace); List statements = []; - while (Peek().HasValue && !TryExpectSymbol(Symbol.CloseBrace)) + while (!TryExpectSymbol(Symbol.CloseBrace)) { try { @@ -625,7 +583,7 @@ public sealed class Parser { var parameter = ParseType(); parameters.Add(parameter); - if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen }) + if (!TryExpectSymbol(Symbol.Comma) && _currentToken is not SymbolToken { Symbol: Symbol.CloseParen }) { _diagnostics.Add(Diagnostic .Warning("Missing comma between func type arguments") @@ -647,21 +605,22 @@ public sealed class Parser } throw new ParseException(Diagnostic - .Error("Invalid type Syntax") + .Error("Invalid type syntax") .WithHelp("Expected type name, '^' for pointer, or '[]' for array") .Build()); } private Token ExpectToken() { - if (!Peek().TryGetValue(out var token)) + if (!_hasCurrentToken) { throw new ParseException(Diagnostic .Error("Unexpected end of file") - .WithHelp("Expected more tokens to complete the Syntax") + .WithHelp("Expected more tokens to complete the syntax") .Build()); } + var token = _currentToken!; Next(); return token; } @@ -694,7 +653,7 @@ public sealed class Parser private bool TryExpectSymbol(Symbol symbol) { - if (Peek() is { Value: SymbolToken symbolToken } && symbolToken.Symbol == symbol) + if (_currentToken is SymbolToken symbolToken && symbolToken.Symbol == symbol) { Next(); return true; @@ -705,7 +664,7 @@ public sealed class Parser private bool TryExpectIdentifier([NotNullWhen(true)] out IdentifierToken? identifier) { - if (Peek() is { Value: IdentifierToken identifierToken }) + if (_currentToken is IdentifierToken identifierToken) { identifier = identifierToken; Next(); @@ -730,20 +689,10 @@ public sealed class Parser return identifier; } - private Optional Peek(int offset = 0) - { - var peekIndex = _tokenIndex + offset; - if (peekIndex < _tokens.Count()) - { - return _tokens.ElementAt(peekIndex); - } - - return Optional.Empty(); - } - private void Next() { - _tokenIndex++; + _hasCurrentToken = _tokenEnumerator.MoveNext(); + _currentToken = _hasCurrentToken ? _tokenEnumerator.Current : null; } } diff --git a/src/runtime/targets/x64.s b/src/runtime/targets/x64.s index 68e8922..f55a1d0 100644 --- a/src/runtime/targets/x64.s +++ b/src/runtime/targets/x64.s @@ -4,7 +4,7 @@ .globl _start _start: mov rdi, rsp - call default_main + call main mov rdi, rax mov rax, 60 syscall