diff --git a/ConsoleDemo/DumbWalker.cs b/ConsoleDemo/DumbWalker.cs index 597e084..97a6a54 100644 --- a/ConsoleDemo/DumbWalker.cs +++ b/ConsoleDemo/DumbWalker.cs @@ -22,8 +22,8 @@ namespace ConsoleDemo { switch (lhs.Kind) { - case TokenKind.IdentifierName: - var name = ((IdentifierNameSyntaxNode) lhs).Name.Text; + case TokenKind.IdentifierNameExpression: + var name = ((IdentifierNameExpressionSyntaxNode) lhs).Name.Text; Console.WriteLine($"Adding variable assignment for {name}"); _variableAssignments.Add(name, new Variable()); break; @@ -66,8 +66,8 @@ namespace ConsoleDemo { switch (node.Kind) { - case TokenKind.IdentifierName: - var name = (IdentifierNameSyntaxNode) node; + case TokenKind.IdentifierNameExpression: + var name = (IdentifierNameExpressionSyntaxNode) node; if (_context.FindFunction(name.Name.Text)) { return true; @@ -90,7 +90,7 @@ namespace ConsoleDemo Variable assignment; switch (node.Kind) { - case TokenKind.IdentifierName: + case TokenKind.IdentifierNameExpression: assignment = _variableAssignments.Find(node.Text); if (assignment != null || node.Text == "end") { @@ -98,12 +98,12 @@ namespace ConsoleDemo } break; - case TokenKind.FunctionCall: + case TokenKind.FunctionCallExpression: var functionCall = (FunctionCallExpressionSyntaxNode)node; return (IsDefined(functionCall.FunctionName) && IsDefined(functionCall.Nodes)) || (IsDefinedFunctionName(functionCall.FunctionName) && IsDefined(functionCall.Nodes)); - case TokenKind.CellArrayElementAccess: + case TokenKind.CellArrayElementAccessExpression: var cellArrayElementAccess = (CellArrayElementAccessExpressionSyntaxNode) node; return IsDefined(cellArrayElementAccess.Expression) && IsDefined(cellArrayElementAccess.Nodes); case TokenKind.List: @@ -113,7 +113,7 @@ namespace ConsoleDemo return true; case TokenKind.StringLiteralExpression: return true; - case TokenKind.BinaryOperation: + case TokenKind.BinaryOperationExpression: var binaryOperation = (BinaryOperationExpressionSyntaxNode) node; return IsDefined(binaryOperation.Lhs) && IsDefined(binaryOperation.Rhs); case TokenKind.UnaryPrefixOperationExpression: @@ -139,7 +139,7 @@ namespace ConsoleDemo { var parameterAsNode = parameter.AsNode(); Console.WriteLine($"Parameter node: {parameterAsNode}"); - if (parameterAsNode.Kind == TokenKind.IdentifierName) + if (parameterAsNode.Kind == TokenKind.IdentifierNameExpression) { Console.WriteLine($"Adding variable assignment for {parameterAsNode.Text}"); _variableAssignments.Add(parameterAsNode.Text, new Variable()); @@ -159,17 +159,17 @@ namespace ConsoleDemo _insideFunction = false; } - public override void VisitMethodDefinition(MethodDefinitionSyntaxNode node) + public override void VisitConcreteMethodDeclaration(ConcreteMethodDeclarationSyntaxNode node) { _insideMethod = true; - base.VisitMethodDefinition(node); + base.VisitConcreteMethodDeclaration(node); _insideMethod = false; } public override void VisitFile(FileSyntaxNode node) { _methodAssignments = new MethodAssignments(); - foreach (var nodeOrToken in node.StatementList) + foreach (var nodeOrToken in node.Body.Statements) { if (nodeOrToken.IsToken) { diff --git a/ConsoleDemo/PrettyPrinter.cs b/ConsoleDemo/PrettyPrinter.cs index 1f2be12..1766ce4 100644 --- a/ConsoleDemo/PrettyPrinter.cs +++ b/ConsoleDemo/PrettyPrinter.cs @@ -8,7 +8,7 @@ namespace ProjectConsole { public override void VisitFile(FileSyntaxNode node) { - Visit(node.StatementList); + Visit(node.Body.Statements); OutputKeyword(node.EndOfFile); } @@ -118,7 +118,7 @@ namespace ProjectConsole OutputKeyword(node.ClassdefKeyword); Visit(node.Attributes); BoldOn(); - Visit(node.ClassName); + OutputIdentifier(node.ClassName); BoldOff(); Visit(node.BaseClassList); Visit(node.Nodes); @@ -186,7 +186,7 @@ namespace ProjectConsole OutputKeyword(node.EndKeyword); } - public override void VisitMethodDefinition(MethodDefinitionSyntaxNode node) + public override void VisitConcreteMethodDeclaration(ConcreteMethodDeclarationSyntaxNode node) { OutputKeyword(node.FunctionKeyword); Visit(node.OutputDescription); @@ -274,7 +274,7 @@ namespace ProjectConsole OutputBracket(node.ClosingBrace); } - public override void VisitIdentifierName(IdentifierNameSyntaxNode node) + public override void VisitIdentifierNameExpression(IdentifierNameExpressionSyntaxNode node) { OutputIdentifier(node.Name); } @@ -306,12 +306,12 @@ namespace ProjectConsole OutputControlKeyword(node.EndKeyword); } - public override void VisitUnquotedStringLiteral(UnquotedStringLiteralSyntaxNode node) + public override void VisitUnquotedStringLiteralExpression(UnquotedStringLiteralExpressionSyntaxNode node) { OutputUnquotedStringLiteral(node.StringToken); } - public override void VisitStringLiteral(StringLiteralSyntaxNode node) + public override void VisitStringLiteralExpression(StringLiteralExpressionSyntaxNode node) { OutputStringLiteral(node.StringToken); } @@ -355,11 +355,11 @@ namespace ProjectConsole public override void VisitCommandExpression(CommandExpressionSyntaxNode node) { - Visit(node.CommandName); + OutputIdentifier(node.CommandName); Visit(node.Arguments); } - public override void VisitNumberLiteral(NumberLiteralSyntaxNode node) + public override void VisitNumberLiteralExpression(NumberLiteralExpressionSyntaxNode node) { OutputNumberLiteral(node.Number); } @@ -370,13 +370,13 @@ namespace ProjectConsole Visit(node.Operand); } - public override void VisitUnaryPostixOperationExpression(UnaryPostixOperationExpressionSyntaxNode node) + public override void VisitUnaryPostfixOperationExpression(UnaryPostfixOperationExpressionSyntaxNode node) { Visit(node.Operand); OutputOperator(node.Operation); } - public override void VisitBaseClassInvokation(BaseClassInvokationSyntaxNode node) + public override void VisitClassInvokationExpression(ClassInvokationExpressionSyntaxNode node) { Visit(node.MethodName); OutputOperator(node.AtSign); @@ -391,7 +391,7 @@ namespace ProjectConsole public override void VisitAttribute(AttributeSyntaxNode node) { - Visit(node.Name); + OutputIdentifier(node.Name); Visit(node.Assignment); } @@ -410,12 +410,12 @@ namespace ProjectConsole OutputBracket(node.ClosingBrace); } - public override void VisitCompoundName(CompoundNameSyntaxNode node) + public override void VisitCompoundNameExpression(CompoundNameExpressionSyntaxNode node) { Visit(node.Nodes); } - public override void VisitDoubleQuotedStringLiteral(DoubleQuotedStringLiteralSyntaxNode node) + public override void VisitDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralExpressionSyntaxNode node) { OutputStringLiteral(node.StringToken); } @@ -454,7 +454,7 @@ namespace ProjectConsole public override void VisitEnumerationItem(EnumerationItemSyntaxNode node) { - Visit(node.Name); + OutputIdentifier(node.Name); Visit(node.Values); Visit(node.Commas); } @@ -472,27 +472,27 @@ namespace ProjectConsole OutputOperator(node.AssignmentSign); } - public override void VisitIndirectMemberAccess(IndirectMemberAccessSyntaxNode node) + public override void VisitIndirectMemberAccessExpression(IndirectMemberAccessExpressionSyntaxNode node) { OutputBracket(node.OpeningBracket); Visit(node.Expression); OutputBracket(node.ClosingBracket); } - public override void VisitLambda(LambdaSyntaxNode node) + public override void VisitLambdaExpression(LambdaExpressionSyntaxNode node) { OutputOperator(node.AtSign); Visit(node.Input); Visit(node.Body); } - public override void VisitNamedFunctionHandle(NamedFunctionHandleSyntaxNode node) + public override void VisitNamedFunctionHandleExpression(NamedFunctionHandleExpressionSyntaxNode node) { OutputOperator(node.AtSign); Visit(node.FunctionName); } - public override void VisitMemberAccess(MemberAccessSyntaxNode node) + public override void VisitMemberAccessExpression(MemberAccessExpressionSyntaxNode node) { Visit(node.LeftOperand); OutputOperator(node.Dot); diff --git a/ConsoleDemo/Program.cs b/ConsoleDemo/Program.cs index 8f74c47..1b2f418 100644 --- a/ConsoleDemo/Program.cs +++ b/ConsoleDemo/Program.cs @@ -1,5 +1,4 @@ using Parser; -using Semantics; using System; using System.IO; using System.Linq; @@ -72,7 +71,7 @@ namespace ConsoleDemo var childNodesAndTokens = root.GetChildNodesAndTokens(); var node = childNodesAndTokens[0].AsNode(); var classChildNodesAndTokens = node.GetChildNodesAndTokens(); - var c = GetClass.FromTree(root, fileName); + var c = Semantics.GetClass.FromTree(root, fileName); Console.WriteLine(c.Name); foreach (var m in c.Methods) { @@ -86,13 +85,13 @@ namespace ConsoleDemo public static void ContextDemo() { - var context = new Context(); + var context = new Semantics.Context(); context.ScanPath(BaseDirectory); } public static void DumbPrinterDemo() { - var context = new Context(); + var context = new Semantics.Context(); context.ScanPath(BaseDirectory); var fileName = Path.Combine( BaseDirectory, @@ -105,7 +104,7 @@ namespace ConsoleDemo public static void UsageDemo() { - var context = new Context(); + var context = new Semantics.Context(); context.ScanPath(BaseDirectory); var fileName = Path.Combine( BaseDirectory, @@ -130,7 +129,6 @@ namespace ConsoleDemo //ContextDemo(); //DumbPrinterDemo(); //UsageDemo(); - Console.ReadKey(); } } } diff --git a/ConsoleDemo/UsageGathering.cs b/ConsoleDemo/UsageGathering.cs index 53ea181..6be20d1 100644 --- a/ConsoleDemo/UsageGathering.cs +++ b/ConsoleDemo/UsageGathering.cs @@ -49,8 +49,8 @@ namespace ConsoleDemo { switch (lhs.Kind) { - case TokenKind.IdentifierName: - var name = ((IdentifierNameSyntaxNode)lhs).Name.Text; + case TokenKind.IdentifierNameExpression: + var name = ((IdentifierNameExpressionSyntaxNode)lhs).Name.Text; Console.WriteLine($"Adding variable assignment for {name}"); _variableAssignments.Add(name, new Variable()); break; @@ -72,7 +72,7 @@ namespace ConsoleDemo public override void VisitFile(FileSyntaxNode node) { _methodAssignments = new MethodAssignments(); - foreach (var nodeOrToken in node.StatementList) + foreach (var nodeOrToken in node.Body.Statements) { if (nodeOrToken.IsToken) { @@ -100,7 +100,7 @@ namespace ConsoleDemo { var parameterAsNode = parameter.AsNode(); Console.WriteLine($"Parameter node: {parameterAsNode}"); - if (parameterAsNode.Kind == TokenKind.IdentifierName) + if (parameterAsNode.Kind == TokenKind.IdentifierNameExpression) { Console.WriteLine($"Adding variable assignment for {parameterAsNode.Text}"); _variableAssignments.Add(parameterAsNode.Text, new Variable()); @@ -120,7 +120,7 @@ namespace ConsoleDemo _insideFunction = false; } - public override void VisitMethodDefinition(MethodDefinitionSyntaxNode node) + public override void VisitConcreteMethodDeclaration(ConcreteMethodDeclarationSyntaxNode node) { _insideMethod = true; _variableAssignments = new VariableAssignments(); @@ -131,7 +131,7 @@ namespace ConsoleDemo { var parameterAsNode = parameter.AsNode(); Console.WriteLine($"Parameter node: {parameterAsNode}"); - if (parameterAsNode.Kind == TokenKind.IdentifierName) + if (parameterAsNode.Kind == TokenKind.IdentifierNameExpression) { Console.WriteLine($"Adding variable assignment for {parameterAsNode.Text}"); _variableAssignments.Add(parameterAsNode.Text, new Variable()); @@ -146,7 +146,7 @@ namespace ConsoleDemo Console.WriteLine($"Parameter token: {parameter.AsToken()}"); } } - base.VisitMethodDefinition(node); + base.VisitConcreteMethodDeclaration(node); _variableAssignments = null; _insideMethod = false; } diff --git a/MApplication/ColoringVisitor.cs b/MApplication/ColoringVisitor.cs index 16bce5a..0c6ae72 100644 --- a/MApplication/ColoringVisitor.cs +++ b/MApplication/ColoringVisitor.cs @@ -75,7 +75,7 @@ namespace MApplication public override void VisitFile(FileSyntaxNode node) { - Visit(node.StatementList); + Visit(node.Body.Statements); AddToken(node.EndOfFile, _scheme.Keyword); } @@ -89,7 +89,7 @@ namespace MApplication { AddToken(node.ClassdefKeyword, _scheme.Keyword); Visit(node.Attributes); - Visit(node.ClassName); + AddToken(node.ClassName, _scheme.Identifier); Visit(node.BaseClassList); Visit(node.Nodes); AddToken(node.EndKeyword, _scheme.Keyword); @@ -138,7 +138,7 @@ namespace MApplication AddToken(node.EndKeyword, _scheme.Keyword); } - public override void VisitMethodDefinition(MethodDefinitionSyntaxNode node) + public override void VisitConcreteMethodDeclaration(ConcreteMethodDeclarationSyntaxNode node) { AddToken(node.FunctionKeyword, _scheme.Keyword); Visit(node.OutputDescription); @@ -221,7 +221,7 @@ namespace MApplication AddToken(node.ClosingBrace, _scheme.Bracket); } - public override void VisitIdentifierName(IdentifierNameSyntaxNode node) + public override void VisitIdentifierNameExpression(IdentifierNameExpressionSyntaxNode node) { AddToken(node.Name, _scheme.Identifier); } @@ -253,12 +253,12 @@ namespace MApplication AddToken(node.EndKeyword, _scheme.ControlKeyword); } - public override void VisitUnquotedStringLiteral(UnquotedStringLiteralSyntaxNode node) + public override void VisitUnquotedStringLiteralExpression(UnquotedStringLiteralExpressionSyntaxNode node) { AddToken(node.StringToken, _scheme.UnquotedStringLiteral); } - public override void VisitStringLiteral(StringLiteralSyntaxNode node) + public override void VisitStringLiteralExpression(StringLiteralExpressionSyntaxNode node) { AddToken(node.StringToken, _scheme.StringLiteral); } @@ -302,11 +302,11 @@ namespace MApplication public override void VisitCommandExpression(CommandExpressionSyntaxNode node) { - Visit(node.CommandName); + AddToken(node.CommandName, _scheme.Identifier); Visit(node.Arguments); } - public override void VisitNumberLiteral(NumberLiteralSyntaxNode node) + public override void VisitNumberLiteralExpression(NumberLiteralExpressionSyntaxNode node) { AddToken(node.Number, _scheme.NumberLiteral); } @@ -317,13 +317,13 @@ namespace MApplication Visit(node.Operand); } - public override void VisitUnaryPostixOperationExpression(UnaryPostixOperationExpressionSyntaxNode node) + public override void VisitUnaryPostfixOperationExpression(UnaryPostfixOperationExpressionSyntaxNode node) { Visit(node.Operand); AddToken(node.Operation, _scheme.Operator); } - public override void VisitBaseClassInvokation(BaseClassInvokationSyntaxNode node) + public override void VisitClassInvokationExpression(ClassInvokationExpressionSyntaxNode node) { Visit(node.MethodName); AddToken(node.AtSign, _scheme.Operator); @@ -338,7 +338,7 @@ namespace MApplication public override void VisitAttribute(AttributeSyntaxNode node) { - Visit(node.Name); + AddToken(node.Name, _scheme.Identifier); Visit(node.Assignment); } @@ -357,12 +357,12 @@ namespace MApplication AddToken(node.ClosingBrace, _scheme.Bracket); } - public override void VisitCompoundName(CompoundNameSyntaxNode node) + public override void VisitCompoundNameExpression(CompoundNameExpressionSyntaxNode node) { Visit(node.Nodes); } - public override void VisitDoubleQuotedStringLiteral(DoubleQuotedStringLiteralSyntaxNode node) + public override void VisitDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralExpressionSyntaxNode node) { AddToken(node.StringToken, _scheme.StringLiteral); } @@ -401,7 +401,7 @@ namespace MApplication public override void VisitEnumerationItem(EnumerationItemSyntaxNode node) { - Visit(node.Name); + AddToken(node.Name, _scheme.Identifier); Visit(node.Values); Visit(node.Commas); } @@ -419,27 +419,27 @@ namespace MApplication AddToken(node.AssignmentSign, _scheme.Operator); } - public override void VisitIndirectMemberAccess(IndirectMemberAccessSyntaxNode node) + public override void VisitIndirectMemberAccessExpression(IndirectMemberAccessExpressionSyntaxNode node) { AddToken(node.OpeningBracket, _scheme.Bracket); Visit(node.Expression); AddToken(node.ClosingBracket, _scheme.Bracket); } - public override void VisitLambda(LambdaSyntaxNode node) + public override void VisitLambdaExpression(LambdaExpressionSyntaxNode node) { AddToken(node.AtSign, _scheme.Operator); Visit(node.Input); Visit(node.Body); } - public override void VisitNamedFunctionHandle(NamedFunctionHandleSyntaxNode node) + public override void VisitNamedFunctionHandleExpression(NamedFunctionHandleExpressionSyntaxNode node) { AddToken(node.AtSign, _scheme.Operator); Visit(node.FunctionName); } - public override void VisitMemberAccess(MemberAccessSyntaxNode node) + public override void VisitMemberAccessExpression(MemberAccessExpressionSyntaxNode node) { Visit(node.LeftOperand); AddToken(node.Dot, _scheme.Operator); diff --git a/Parser.Tests/MParserShould.cs b/Parser.Tests/MParserShould.cs index 91bd393..9a5a63e 100644 --- a/Parser.Tests/MParserShould.cs +++ b/Parser.Tests/MParserShould.cs @@ -19,7 +19,7 @@ namespace Parser.Tests var text = "a = b"; var sut = GetSut(text); var actual = sut.Parse(); - var assignment = actual.Root.StatementList[0].AsNode(); + var assignment = actual.Root.Body.Statements[0].AsNode(); Assert.IsType(assignment); if (assignment is null) { @@ -35,7 +35,7 @@ namespace Parser.Tests var text = "2 + 3"; var sut = GetSut(text); var actual = sut.Parse(); - var statement = actual.Root.StatementList[0].AsNode(); + var statement = actual.Root.Body.Statements[0].AsNode(); Assert.IsType(statement); if (statement is null) { @@ -51,7 +51,7 @@ namespace Parser.Tests var text = "a = "; var sut = GetSut(text); var actual = sut.Parse(); - var assignment = actual.Root.StatementList[0].AsNode(); + var assignment = actual.Root.Body.Statements[0].AsNode(); Assert.IsType(assignment); if (assignment is null) { @@ -77,7 +77,7 @@ namespace Parser.Tests var text = "2 + 3"; var sut = GetSut(text); var actual = sut.Parse(); - var statement = actual.Root.StatementList[0].AsNode() as ExpressionStatementSyntaxNode; + var statement = actual.Root.Body.Statements[0].AsNode() as ExpressionStatementSyntaxNode; var expression = statement!.Expression as BinaryOperationExpressionSyntaxNode; var lhs = expression!.Lhs; var operation = expression.Operation; diff --git a/Parser/Binding/Binder.cs b/Parser/Binding/Binder.cs new file mode 100644 index 0000000..9b8fccd --- /dev/null +++ b/Parser/Binding/Binder.cs @@ -0,0 +1,456 @@ +using Parser.Internal; +using Parser.Lowering; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +using static Parser.Binding.BoundNodeFactory; + +namespace Parser.Binding +{ + public class Binder + { + private readonly DiagnosticsBag _diagnostics = new DiagnosticsBag(); + + public static BoundProgram BindProgram(SyntaxTree syntaxTree) + { + var binder = new Binder(); + var boundRoot = binder.BindRoot(syntaxTree.NullRoot); + var statements = ((BoundBlockStatement)boundRoot.File.Body).Statements; + var functionsBuilder = ImmutableDictionary.CreateBuilder(); + var globalStatements = statements.Where(s => s.Kind != BoundNodeKind.FunctionDeclaration).ToArray(); + var mainFunction = (FunctionSymbol?)null; + var scriptFunction = (FunctionSymbol?)null; + if (globalStatements.Length > 0) + { + // we have to gather all bound expression statements into a "script" function. + scriptFunction = new FunctionSymbol("%script"); + var body = Block(globalStatements[0].Syntax, globalStatements); + var loweredBody = Lowerer.Lower(body); + var declaration = new BoundFunctionDeclaration( + syntax: globalStatements[0].Syntax, + name: "%script", + inputDescription: ImmutableArray.Empty, + outputDescription: ImmutableArray.Empty, + body: body); + var loweredFunction = LowerFunction(declaration); + functionsBuilder.Add(scriptFunction, loweredFunction); + } + + var functions = statements.OfType().ToArray(); + var first = true; + foreach (var function in functions) + { + var functionSymbol = new FunctionSymbol( + name: function.Name); + var loweredFunction = LowerFunction(function); + functionsBuilder.Add(functionSymbol, loweredFunction); + if (first && globalStatements.Length == 0) + { + // the first function in a file will become "main". + first = false; + mainFunction = functionSymbol; + } + } + + return new BoundProgram( + binder._diagnostics.ToImmutableArray(), + mainFunction, + scriptFunction, + functionsBuilder.ToImmutable()); + } + + private static LoweredFunction LowerFunction(BoundFunctionDeclaration declaration) + { + var loweredBody = Lowerer.Lower(declaration.Body); + return new LoweredFunction( + declaration: declaration, + name: declaration.Name, + inputDescription: declaration.InputDescription, + outputDescription: declaration.OutputDescription, + body: loweredBody); + } + + private BoundRoot BindRoot(RootSyntaxNode node) + { + var boundFile = BindFile(node.File); + return Root(node, boundFile); + } + + private BoundFile BindFile(FileSyntaxNode node) + { + var body = BindBlockStatement(node.Body); + return File(node, body); + } + + private BoundStatement BindStatement(StatementSyntaxNode node) + { + return node.Kind switch + { + TokenKind.AbstractMethodDeclaration => + BindAbstractMethodDeclaration((AbstractMethodDeclarationSyntaxNode)node), + TokenKind.BlockStatement => + BindBlockStatement((BlockStatementSyntaxNode)node), + TokenKind.ClassDeclaration => + BindClassDeclaration((ClassDeclarationSyntaxNode)node), + TokenKind.ConcreteMethodDeclaration => + BindConcreteMethodDeclaration((ConcreteMethodDeclarationSyntaxNode)node), + TokenKind.EmptyStatement => + BindEmptyStatement((EmptyStatementSyntaxNode)node), + TokenKind.ExpressionStatement => + BindExpressionStatement((ExpressionStatementSyntaxNode)node), + TokenKind.ForStatement => + BindForStatement((ForStatementSyntaxNode)node), + TokenKind.FunctionDeclaration => + BindFunctionDeclaration((FunctionDeclarationSyntaxNode)node), + TokenKind.IfStatement => + BindIfStatement((IfStatementSyntaxNode)node), + TokenKind.SwitchStatement => + BindSwitchStatement((SwitchStatementSyntaxNode)node), + TokenKind.TryCatchStatement => + BindTryCatchStatement((TryCatchStatementSyntaxNode)node), + TokenKind.WhileStatement => + BindWhileStatement((WhileStatementSyntaxNode)node), + _ => + throw new Exception($"Invalid statement node kind '{node.Kind}'."), + }; + } + + private BoundWhileStatement BindWhileStatement(WhileStatementSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundTryCatchStatement BindTryCatchStatement(TryCatchStatementSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundSwitchStatement BindSwitchStatement(SwitchStatementSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundIfStatement BindIfStatement(IfStatementSyntaxNode node) + { + var condition = BindExpression(node.Condition); + var body = BindStatement(node.Body); + var elseifClauses = node.ElseifClauses + .Where(n => n.IsNode) + .Select(n => (ElseifClause)n.AsNode()!); + var builder = ImmutableArray.CreateBuilder(); + foreach (var elseifClause in elseifClauses) + { + var clause = BindElseifClause(elseifClause); + builder.Add(clause); + } + var maybeElseClause = node.ElseClause switch + { + { } elseClause => BindElseClause(elseClause), + _ => null, + }; + + return IfStatement(node, condition, body, builder.ToImmutable(), maybeElseClause); + } + + private BoundStatement BindElseClause(ElseClause node) + { + return BindStatement(node.Body); + } + + private BoundBlockStatement BindBlockStatement(BlockStatementSyntaxNode node) + { + var boundStatements = BindStatementList(node.Statements); + return Block(node, boundStatements.ToArray()); + } + + private IEnumerable BindStatementList(SyntaxNodeOrTokenList list) + { + var statements = list.Where(s => s.IsNode).Select(s => (StatementSyntaxNode)s.AsNode()!); + foreach (var statement in statements) + { + yield return BindStatement(statement); + } + } + + private ImmutableArray BindExpressionList(SyntaxNodeOrTokenList list) + { + var builder = ImmutableArray.CreateBuilder(); + var expressions = list.Where(s => s.IsNode).Select(s => (ExpressionSyntaxNode)s.AsNode()!); + foreach (var expression in expressions) + { + var boundExpression = BindExpression(expression); + builder.Add(boundExpression); + } + + return builder.ToImmutable(); + } + + private BoundElseifClause BindElseifClause(ElseifClause node) + { + var condition = BindExpression(node.Condition); + var body = BindStatement(node.Body); + return ElseifClause(node, condition, body); + } + + private BoundFunctionDeclaration BindFunctionDeclaration(FunctionDeclarationSyntaxNode node) + { + var inputDescription = BindInputDescription(node.InputDescription); + var outputDescription = BindOutputDescription(node.OutputDescription); + var body = BindStatement(node.Body); + return new BoundFunctionDeclaration(node, node.Name.Text, inputDescription, outputDescription, body); + } + + private ImmutableArray BindOutputDescription(FunctionOutputDescriptionSyntaxNode? node) + { + if (node is null) + { + return ImmutableArray.Empty; + } + var outputs = node.OutputList.Where(p => p.IsNode).Select(p => p.AsNode()!); + var builder = ImmutableArray.CreateBuilder(); + foreach (var output in outputs) + { + if (output.Kind != TokenKind.IdentifierNameExpression) + { + throw new Exception($"Invalid function output kind {output.Kind}."); + } + + builder.Add(BindParameterSymbol((IdentifierNameExpressionSyntaxNode)output)); + } + + return builder.ToImmutable(); + } + + private ImmutableArray BindInputDescription(FunctionInputDescriptionSyntaxNode? node) + { + if (node is null) + { + return ImmutableArray.Empty; + } + + var parameters = node.ParameterList.Where(p => p.IsNode).Select(p => p.AsNode()!); + var builder = ImmutableArray.CreateBuilder(); + foreach (var parameter in parameters) + { + if (parameter.Kind != TokenKind.IdentifierNameExpression) + { + throw new Exception($"Invalid function parameter kind {parameter.Kind}."); + } + + builder.Add(BindParameterSymbol((IdentifierNameExpressionSyntaxNode)parameter)); + } + + return builder.ToImmutable(); + } + + private ParameterSymbol BindParameterSymbol(IdentifierNameExpressionSyntaxNode parameter) + { + return new ParameterSymbol(parameter.Text); + } + + private BoundForStatement BindForStatement(ForStatementSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundExpressionStatement BindExpressionStatement(ExpressionStatementSyntaxNode node) + { + var expression = BindExpression(node.Expression); + return ExpressionStatement(node, expression); + } + + private BoundExpression BindExpression(ExpressionSyntaxNode node) + { + return node.Kind switch + { + TokenKind.ArrayLiteralExpression => + BindArrayLiteralExpression((ArrayLiteralExpressionSyntaxNode)node), + TokenKind.AssignmentExpression => + BindAssignmentExpression((AssignmentExpressionSyntaxNode)node), + TokenKind.BinaryOperationExpression => + BindBinaryOperationExpression((BinaryOperationExpressionSyntaxNode)node), + TokenKind.CellArrayElementAccessExpression => + BindCellArrayElementAccessExpression((CellArrayElementAccessExpressionSyntaxNode)node), + TokenKind.CellArrayLiteralExpression => + BindCellArrayLiteralExpression((CellArrayLiteralExpressionSyntaxNode)node), + TokenKind.ClassInvokationExpression => + BindClassInvokationExpression((ClassInvokationExpressionSyntaxNode)node), + TokenKind.CommandExpression => + BindCommandExpression((CommandExpressionSyntaxNode)node), + TokenKind.CompoundNameExpression => + BindCompoundNameExpression((CompoundNameExpressionSyntaxNode)node), + TokenKind.DoubleQuotedStringLiteralExpression => + BindDoubleQuotedStringLiteralExpression((DoubleQuotedStringLiteralExpressionSyntaxNode)node), + TokenKind.EmptyExpression => + BindEmptyExpression((EmptyExpressionSyntaxNode)node), + TokenKind.FunctionCallExpression => + BindFunctionCallExpression((FunctionCallExpressionSyntaxNode)node), + TokenKind.IdentifierNameExpression => + BindIdentifierNameExpression((IdentifierNameExpressionSyntaxNode)node), + TokenKind.IndirectMemberAccessExpression => + BindIndirectMemberAccessExpression((IndirectMemberAccessExpressionSyntaxNode)node), + TokenKind.LambdaExpression => + BindLambdaExpression((LambdaExpressionSyntaxNode)node), + TokenKind.MemberAccessExpression => + BindMemberAccessExpression((MemberAccessExpressionSyntaxNode)node), + TokenKind.NamedFunctionHandleExpression => + BindNamedFunctionHandleExpression((NamedFunctionHandleExpressionSyntaxNode)node), + TokenKind.NumberLiteralExpression => + BindNumberLiteralExpression((NumberLiteralExpressionSyntaxNode)node), + TokenKind.ParenthesizedExpression => + BindParenthesizedExpression((ParenthesizedExpressionSyntaxNode)node), + TokenKind.StringLiteralExpression => + BindStringLiteralExpression((StringLiteralExpressionSyntaxNode)node), + TokenKind.UnaryPrefixOperationExpression => + BindUnaryPrefixOperationExpression((UnaryPrefixOperationExpressionSyntaxNode)node), + TokenKind.UnaryPostfixOperationExpression => + BindUnaryPostfixOperationExpression((UnaryPostfixOperationExpressionSyntaxNode)node), + TokenKind.UnquotedStringLiteralExpression => + BindUnquotedStringLiteralExpression((UnquotedStringLiteralExpressionSyntaxNode)node), + _ => + throw new Exception($"Invalid statement node kind '{node.Kind}'."), + }; + } + + private BoundArrayLiteralExpression BindArrayLiteralExpression(ArrayLiteralExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundAssignmentExpression BindAssignmentExpression(AssignmentExpressionSyntaxNode node) + { + var left = BindExpression(node.Lhs); + var right = BindExpression(node.Rhs); + return Assignment(node, left, right); + } + + private BoundBinaryOperationExpression BindBinaryOperationExpression(BinaryOperationExpressionSyntaxNode node) + { + var left = BindExpression(node.Lhs); + var right = BindExpression(node.Rhs); + return BinaryOperation(node, left, node.Operation.Kind, right); + } + + private BoundCellArrayElementAccessExpression BindCellArrayElementAccessExpression(CellArrayElementAccessExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundCellArrayLiteralExpression BindCellArrayLiteralExpression(CellArrayLiteralExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundClassInvokationExpression BindClassInvokationExpression(ClassInvokationExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundCommandExpression BindCommandExpression(CommandExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundCompoundNameExpression BindCompoundNameExpression(CompoundNameExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundDoubleQuotedStringLiteralExpression BindDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundEmptyExpression BindEmptyExpression(EmptyExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundFunctionCallExpression BindFunctionCallExpression(FunctionCallExpressionSyntaxNode node) + { + var name = BindExpression(node.FunctionName); + var arguments = BindExpressionList(node.Nodes); + return FunctionCall(node, name, arguments); + } + + private BoundIdentifierNameExpression BindIdentifierNameExpression(IdentifierNameExpressionSyntaxNode node) + { + return new BoundIdentifierNameExpression(node, node.Name.Text); + } + + private BoundIndirectMemberAccessExpression BindIndirectMemberAccessExpression(IndirectMemberAccessExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundLambdaExpression BindLambdaExpression(LambdaExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundMemberAccessExpression BindMemberAccessExpression(MemberAccessExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundNamedFunctionHandleExpression BindNamedFunctionHandleExpression(NamedFunctionHandleExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundNumberLiteralExpression BindNumberLiteralExpression(NumberLiteralExpressionSyntaxNode node) + { + var value = (double)node.Number.Value!; + return NumberLiteral(node, value); + } + + private BoundExpression BindParenthesizedExpression(ParenthesizedExpressionSyntaxNode node) + { + return BindExpression(node.Expression); + } + + private BoundStringLiteralExpression BindStringLiteralExpression(StringLiteralExpressionSyntaxNode node) + { + var value = (string)node.StringToken.Value!; + return StringLiteral(node, value); + } + + private BoundUnaryOperationExpression BindUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode node) + { + var operand = BindExpression(node.Operand); + return UnaryOperation(node, node.Operation.Kind, operand); + } + + private BoundUnaryOperationExpression BindUnaryPostfixOperationExpression(UnaryPostfixOperationExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundUnquotedStringLiteralExpression BindUnquotedStringLiteralExpression(UnquotedStringLiteralExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundEmptyStatement BindEmptyStatement(EmptyStatementSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundConcreteMethodDeclaration BindConcreteMethodDeclaration(ConcreteMethodDeclarationSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundClassDeclaration BindClassDeclaration(ClassDeclarationSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundAbstractMethodDeclaration BindAbstractMethodDeclaration(AbstractMethodDeclarationSyntaxNode node) + { + throw new NotImplementedException(); + } + } +} diff --git a/Parser/Binding/BoundBinaryOperator.cs b/Parser/Binding/BoundBinaryOperator.cs new file mode 100644 index 0000000..73dc880 --- /dev/null +++ b/Parser/Binding/BoundBinaryOperator.cs @@ -0,0 +1,48 @@ +using System.Linq; + +namespace Parser.Binding +{ + public class BoundBinaryOperator + { + private static BoundBinaryOperator[] _operators = + { + new BoundBinaryOperator(TokenKind.EqualsToken, BoundBinaryOperatorKind.Equals), + new BoundBinaryOperator(TokenKind.PipePipeToken, BoundBinaryOperatorKind.PipePipe), + new BoundBinaryOperator(TokenKind.AmpersandAmpersandToken, BoundBinaryOperatorKind.AmpersandAmpersand), + new BoundBinaryOperator(TokenKind.PipeToken, BoundBinaryOperatorKind.Pipe), + new BoundBinaryOperator(TokenKind.AmpersandToken, BoundBinaryOperatorKind.Ampersand), + new BoundBinaryOperator(TokenKind.LessToken, BoundBinaryOperatorKind.Less), + new BoundBinaryOperator(TokenKind.LessOrEqualsToken, BoundBinaryOperatorKind.LessOrEquals), + new BoundBinaryOperator(TokenKind.GreaterToken, BoundBinaryOperatorKind.Greater), + new BoundBinaryOperator(TokenKind.GreaterOrEqualsToken, BoundBinaryOperatorKind.GreaterOrEquals), + new BoundBinaryOperator(TokenKind.EqualsEqualsToken, BoundBinaryOperatorKind.EqualsEquals), + new BoundBinaryOperator(TokenKind.TildeEqualsToken, BoundBinaryOperatorKind.TildeEquals), + new BoundBinaryOperator(TokenKind.ColonToken, BoundBinaryOperatorKind.Colon), + new BoundBinaryOperator(TokenKind.PlusToken, BoundBinaryOperatorKind.Plus), + new BoundBinaryOperator(TokenKind.MinusToken, BoundBinaryOperatorKind.Minus), + new BoundBinaryOperator(TokenKind.StarToken, BoundBinaryOperatorKind.Star), + new BoundBinaryOperator(TokenKind.DotStarToken, BoundBinaryOperatorKind.DotStar), + new BoundBinaryOperator(TokenKind.SlashToken, BoundBinaryOperatorKind.Slash), + new BoundBinaryOperator(TokenKind.DotSlashToken, BoundBinaryOperatorKind.DotSlash), + new BoundBinaryOperator(TokenKind.BackslashToken, BoundBinaryOperatorKind.Backslash), + new BoundBinaryOperator(TokenKind.DotBackslashToken, BoundBinaryOperatorKind.DotBackslash), + new BoundBinaryOperator(TokenKind.TildeToken, BoundBinaryOperatorKind.Tilde), + new BoundBinaryOperator(TokenKind.CaretToken, BoundBinaryOperatorKind.Caret), + new BoundBinaryOperator(TokenKind.DotCaretToken, BoundBinaryOperatorKind.DotCaret), + }; + + public BoundBinaryOperator(TokenKind syntaxKind, BoundBinaryOperatorKind kind) + { + SyntaxKind = syntaxKind; + Kind = kind; + } + + public TokenKind SyntaxKind { get; } + public BoundBinaryOperatorKind Kind { get; } + + internal static BoundBinaryOperator? GetOperator(TokenKind kind) + { + return _operators.FirstOrDefault(op => op.SyntaxKind == kind); + } + } +} diff --git a/Parser/Binding/BoundBinaryOperatorKind.cs b/Parser/Binding/BoundBinaryOperatorKind.cs new file mode 100644 index 0000000..cf43bf7 --- /dev/null +++ b/Parser/Binding/BoundBinaryOperatorKind.cs @@ -0,0 +1,29 @@ +namespace Parser.Binding +{ + public enum BoundBinaryOperatorKind + { + Equals, + PipePipe, + AmpersandAmpersand, + Pipe, + Ampersand, + Less, + LessOrEquals, + Greater, + GreaterOrEquals, + EqualsEquals, + TildeEquals, + Colon, + Plus, + Minus, + Star, + DotStar, + Slash, + DotSlash, + Backslash, + DotBackslash, + Tilde, + Caret, + DotCaret, + } +} diff --git a/Parser/Binding/BoundLabel.cs b/Parser/Binding/BoundLabel.cs new file mode 100644 index 0000000..577ce08 --- /dev/null +++ b/Parser/Binding/BoundLabel.cs @@ -0,0 +1,17 @@ +namespace Parser.Binding +{ + public class BoundLabel + { + public string Name { get; } + + public BoundLabel(string name) + { + Name = name; + } + + public override string ToString() + { + return Name; + } + } +} diff --git a/Parser/Binding/BoundNode.cs b/Parser/Binding/BoundNode.cs new file mode 100644 index 0000000..5f3ac1a --- /dev/null +++ b/Parser/Binding/BoundNode.cs @@ -0,0 +1,13 @@ +namespace Parser.Binding +{ + public abstract class BoundNode + { + public BoundNode(SyntaxNode syntax) + { + Syntax = syntax; + } + + public SyntaxNode Syntax { get; } + public abstract BoundNodeKind Kind { get; } + } +} diff --git a/Parser/Binding/BoundNodeFactory.cs b/Parser/Binding/BoundNodeFactory.cs new file mode 100644 index 0000000..f8b60ab --- /dev/null +++ b/Parser/Binding/BoundNodeFactory.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Immutable; + +namespace Parser.Binding +{ + public static class BoundNodeFactory + { + public static BoundRoot Root(SyntaxNode syntax, BoundFile file) + { + return new BoundRoot(syntax, file); + } + + public static BoundFile File(SyntaxNode syntax, BoundStatement body) + { + return new BoundFile(syntax, body); + } + + public static BoundBlockStatement Block(SyntaxNode syntax, params BoundStatement[] statements) + { + return new BoundBlockStatement(syntax, statements.ToImmutableArray()); + } + + public static BoundBlockStatement Block(SyntaxNode syntax, ImmutableArray statements) + { + return new BoundBlockStatement(syntax, statements); + } + + public static BoundExpressionStatement ExpressionStatement(SyntaxNode syntax, BoundExpression expression) + { + return new BoundExpressionStatement(syntax, expression); + } + + public static BoundIfStatement IfStatement( + SyntaxNode syntax, + BoundExpression condition, + BoundStatement body, + ImmutableArray elseifClauses, + BoundStatement? elseClause) + { + return new BoundIfStatement(syntax, condition, body, elseifClauses, elseClause); + } + + public static BoundLabelStatement LabelStatement( + SyntaxNode syntax, + BoundLabel label) + { + return new BoundLabelStatement(syntax, label); + } + + public static BoundAssignmentExpression Assignment( + SyntaxNode syntax, + BoundExpression left, + BoundExpression right) + { + return new BoundAssignmentExpression(syntax, left, right); + } + + public static BoundBinaryOperationExpression BinaryOperation( + SyntaxNode syntax, + BoundExpression left, + TokenKind kind, + BoundExpression right) + { + var op = BindBinaryOperator(kind); + return new BoundBinaryOperationExpression(syntax, left, op, right); + } + + public static BoundConditionalGotoStatement ConditionalGoto( + SyntaxNode syntax, + BoundExpression condition, + BoundLabel label, + bool gotoIfTrue) + { + return new BoundConditionalGotoStatement( + syntax, + condition, + label, + gotoIfTrue); + } + + public static BoundConditionalGotoStatement GotoIfTrue( + SyntaxNode syntax, + BoundExpression condition, + BoundLabel label) + { + return new BoundConditionalGotoStatement( + syntax, + condition, + label, + gotoIfTrue: true); + } + + public static BoundConditionalGotoStatement GotoIfFalse( + SyntaxNode syntax, + BoundExpression condition, + BoundLabel label) + { + return new BoundConditionalGotoStatement( + syntax, + condition, + label, + gotoIfTrue: false); + } + + public static BoundFunctionCallExpression FunctionCall( + SyntaxNode syntax, + BoundExpression name, + ImmutableArray arguments) + { + return new BoundFunctionCallExpression(syntax, name, arguments); + } + + public static BoundGotoStatement Goto( + SyntaxNode syntax, + BoundLabel label) + { + return new BoundGotoStatement(syntax, label); + } + + public static BoundIdentifierNameExpression Identifier( + SyntaxNode syntax, + string name) + { + return new BoundIdentifierNameExpression(syntax, name); + } + + public static BoundNumberLiteralExpression NumberLiteral( + SyntaxNode syntax, + double value) + { + return new BoundNumberLiteralExpression(syntax, value); + } + + public static BoundStringLiteralExpression StringLiteral( + SyntaxNode syntax, + string value) + { + return new BoundStringLiteralExpression(syntax, value); + } + + public static BoundElseifClause ElseifClause( + SyntaxNode syntax, + BoundExpression condition, + BoundStatement body) + { + return new BoundElseifClause(syntax, condition, body); + } + + public static BoundUnaryOperationExpression UnaryOperation( + SyntaxNode syntax, + TokenKind kind, + BoundExpression operand) + { + var op = BindUnaryOperator(kind); + return new BoundUnaryOperationExpression(syntax, op, operand); + } + + private static BoundUnaryOperator BindUnaryOperator(TokenKind kind) + { + return BoundUnaryOperator.GetOperator(kind) + ?? throw new Exception($"Unexpected unary operator kind {kind}."); + } + + private static BoundBinaryOperator BindBinaryOperator(TokenKind kind) + { + return BoundBinaryOperator.GetOperator(kind) + ?? throw new Exception($"Unexpected binary operator kind {kind}."); + } + } +} diff --git a/Parser/Binding/BoundNodeKind.cs b/Parser/Binding/BoundNodeKind.cs new file mode 100644 index 0000000..4158dcd --- /dev/null +++ b/Parser/Binding/BoundNodeKind.cs @@ -0,0 +1,54 @@ +namespace Parser.Binding +{ + public enum BoundNodeKind + { + Root, + File, + + // Statements + + AbstractMethodDeclaration, + BlockStatement, + ClassDeclaration, + ConcreteMethodDeclaration, + ConditionalGotoStatement, + EmptyStatement, + ExpressionStatement, + ForStatement, + FunctionDeclaration, + GotoStatement, + IfStatement, + LabelStatement, + SwitchStatement, + TryCatchStatement, + WhileStatement, + + // Expressions + + ArrayLiteralExpression, + AssignmentExpression, + BinaryOperationExpression, + CellArrayElementAccessExpression, + CellArrayLiteralExpression, + ClassInvokationExpression, + CommandExpression, + CompoundNameExpression, + DoubleQuotedStringLiteralExpression, + EmptyExpression, + FunctionCallExpression, + IdentifierNameExpression, + IndirectMemberAccessExpression, + LambdaExpression, + MemberAccessExpression, + NamedFunctionHandleExpression, + NumberLiteralExpression, + ParenthesizedExpression, + StringLiteralExpression, + UnaryOperationExpression, + UnquotedStringLiteralExpression, + + // Parts + ElseIfClause, + ElseClause + } +} diff --git a/Parser/Binding/BoundProgram.cs b/Parser/Binding/BoundProgram.cs new file mode 100644 index 0000000..ebf8d9d --- /dev/null +++ b/Parser/Binding/BoundProgram.cs @@ -0,0 +1,37 @@ +using Parser.Internal; +using System.Collections.Immutable; + +namespace Parser.Binding +{ + public class BoundProgram + { + public BoundProgram( + ImmutableArray diagnostics, + FunctionSymbol? mainFunction, + FunctionSymbol? scriptFunction, + ImmutableDictionary functions) + { + Diagnostics = diagnostics; + MainFunction = mainFunction; + ScriptFunction = scriptFunction; + Functions = functions; + } + + public ImmutableArray Diagnostics { get; } + + /// + /// A "main" function (first in a file without any global statements). + /// + public FunctionSymbol? MainFunction { get; } + + /// + /// A "script" function (generated from all global statements in a file if there are any). + /// + public FunctionSymbol? ScriptFunction { get; } + + /// + /// So-called "local" functions. + /// + public ImmutableDictionary Functions { get; } + } +} diff --git a/Parser/Binding/BoundRoot.cs b/Parser/Binding/BoundRoot.cs new file mode 100644 index 0000000..5f9d0ca --- /dev/null +++ b/Parser/Binding/BoundRoot.cs @@ -0,0 +1,499 @@ +using System.Collections.Immutable; + +namespace Parser.Binding +{ + public class BoundRoot : BoundNode + { + public BoundRoot(SyntaxNode syntax, BoundFile file) + : base(syntax) + { + File = file; + } + + public BoundFile File { get; } + + public override BoundNodeKind Kind => BoundNodeKind.Root; + } + + public class BoundFile : BoundNode + { + public BoundFile(SyntaxNode syntax, BoundStatement body) + : base(syntax) + { + Body = body; + } + + public BoundStatement Body { get; } + + public override BoundNodeKind Kind => BoundNodeKind.File; + } + + public abstract class BoundStatement : BoundNode + { + public BoundStatement(SyntaxNode syntax) + : base(syntax) + { + } + } + + public abstract class BoundMethodDeclaration : BoundStatement + { + public BoundMethodDeclaration(SyntaxNode syntax) + : base(syntax) + { + } + } + + public class BoundAbstractMethodDeclaration : BoundMethodDeclaration + { + public BoundAbstractMethodDeclaration(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.AbstractMethodDeclaration; + } + + public class BoundBlockStatement : BoundStatement + { + public BoundBlockStatement(SyntaxNode syntax, ImmutableArray statements) + : base(syntax) + { + Statements = statements; + } + + public override BoundNodeKind Kind => BoundNodeKind.BlockStatement; + + public ImmutableArray Statements { get; } + } + + public class BoundClassDeclaration : BoundStatement + { + public BoundClassDeclaration(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.ClassDeclaration; + } + + public class BoundConcreteMethodDeclaration : BoundMethodDeclaration + { + public BoundConcreteMethodDeclaration(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.ConcreteMethodDeclaration; + } + + public class BoundConditionalGotoStatement : BoundStatement + { + public BoundConditionalGotoStatement(SyntaxNode syntax, BoundExpression condition, BoundLabel label, bool gotoIfTrue = true) + : base(syntax) + { + Condition = condition; + Label = label; + GotoIfTrue = gotoIfTrue; + } + + public BoundExpression Condition { get; } + + public BoundLabel Label { get; } + + public bool GotoIfTrue { get; } + + public override BoundNodeKind Kind => BoundNodeKind.ConditionalGotoStatement; + } + + public class BoundEmptyStatement : BoundStatement + { + public BoundEmptyStatement(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.EmptyStatement; + } + + public class BoundExpressionStatement : BoundStatement + { + public BoundExpression Expression { get; } + + public override BoundNodeKind Kind => BoundNodeKind.ExpressionStatement; + + public BoundExpressionStatement(SyntaxNode syntax, BoundExpression expression) + : base(syntax) + { + Expression = expression; + } + } + + public class BoundForStatement : BoundStatement + { + public BoundForStatement(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.ForStatement; + } + + public class BoundFunctionDeclaration : BoundStatement + { + public BoundFunctionDeclaration(SyntaxNode syntax, string name, ImmutableArray inputDescription, ImmutableArray outputDescription, BoundStatement body) + : base(syntax) + { + Name = name; + InputDescription = inputDescription; + OutputDescription = outputDescription; + Body = body; + } + + public override BoundNodeKind Kind => BoundNodeKind.FunctionDeclaration; + + public string Name { get; } + public ImmutableArray InputDescription { get; } + public ImmutableArray OutputDescription { get; } + public BoundStatement Body { get; } + + public BoundFunctionDeclaration WithBody(BoundStatement body) + { + if (body == Body) + { + return this; + } + + return new BoundFunctionDeclaration( + Syntax, + Name, + InputDescription, + OutputDescription, + body); + } + } + + public class BoundGotoStatement : BoundStatement + { + public BoundGotoStatement(SyntaxNode syntax, BoundLabel label) + : base(syntax) + { + Label = label; + } + + public BoundLabel Label { get; } + + public override BoundNodeKind Kind => BoundNodeKind.GotoStatement; + } + + public class BoundIfStatement : BoundStatement + { + public BoundIfStatement(SyntaxNode syntax, BoundExpression condition, BoundStatement body, ImmutableArray elseifClauses, BoundStatement? elseClause) + : base(syntax) + { + Condition = condition; + Body = body; + ElseifClauses = elseifClauses; + ElseClause = elseClause; + } + + public BoundExpression Condition { get; } + public BoundStatement Body { get; } + public ImmutableArray ElseifClauses { get; } + public BoundStatement? ElseClause { get; } + + public override BoundNodeKind Kind => BoundNodeKind.IfStatement; + } + + public class BoundLabelStatement : BoundStatement + { + public BoundLabelStatement(SyntaxNode syntax, BoundLabel label) + : base(syntax) + { + Label = label; + } + + public BoundLabel Label { get; } + + public override BoundNodeKind Kind => BoundNodeKind.LabelStatement; + } + + public class BoundSwitchStatement : BoundStatement + { + public BoundSwitchStatement(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.SwitchStatement; + } + + public class BoundTryCatchStatement : BoundStatement + { + public BoundTryCatchStatement(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.TryCatchStatement; + } + + public class BoundWhileStatement : BoundStatement + { + public BoundWhileStatement(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.WhileStatement; + } + + public abstract class BoundExpression : BoundNode + { + public BoundExpression(SyntaxNode syntax) + : base(syntax) + { + } + } + + public class BoundArrayLiteralExpression : BoundExpression + { + public BoundArrayLiteralExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.ArrayLiteralExpression; + } + + public class BoundAssignmentExpression : BoundExpression + { + public BoundAssignmentExpression(SyntaxNode syntax, BoundExpression left, BoundExpression right) + : base(syntax) + { + Left = left; + Right = right; + } + + public BoundExpression Left { get; } + public BoundExpression Right { get; } + + public override BoundNodeKind Kind => BoundNodeKind.AssignmentExpression; + } + + public class BoundBinaryOperationExpression : BoundExpression + { + public BoundBinaryOperationExpression(SyntaxNode syntax, BoundExpression left, BoundBinaryOperator op, BoundExpression right) + : base(syntax) + { + Left = left; + Op = op; + Right = right; + } + + public BoundExpression Left { get; } + public BoundBinaryOperator Op { get; } + public BoundExpression Right { get; } + + public override BoundNodeKind Kind => BoundNodeKind.BinaryOperationExpression; + } + + public class BoundCellArrayElementAccessExpression : BoundExpression + { + public BoundCellArrayElementAccessExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.CellArrayElementAccessExpression; + } + + public class BoundCellArrayLiteralExpression : BoundExpression + { + public BoundCellArrayLiteralExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.CellArrayLiteralExpression; + } + + public class BoundClassInvokationExpression : BoundExpression + { + public BoundClassInvokationExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.ClassInvokationExpression; + } + + public class BoundCommandExpression : BoundExpression + { + public BoundCommandExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.CommandExpression; + } + + public class BoundCompoundNameExpression : BoundExpression + { + public BoundCompoundNameExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.CompoundNameExpression; + } + + public class BoundDoubleQuotedStringLiteralExpression : BoundExpression + { + public BoundDoubleQuotedStringLiteralExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.DoubleQuotedStringLiteralExpression; + } + + public class BoundEmptyExpression : BoundExpression + { + public BoundEmptyExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.EmptyExpression; + } + + public class BoundFunctionCallExpression : BoundExpression + { + public BoundFunctionCallExpression(SyntaxNode syntax, BoundExpression name, ImmutableArray arguments) + : base(syntax) + { + Name = name; + Arguments = arguments; + } + + public BoundExpression Name { get; } + public ImmutableArray Arguments { get; } + public override BoundNodeKind Kind => BoundNodeKind.FunctionCallExpression; + } + + public class BoundIdentifierNameExpression : BoundExpression + { + public BoundIdentifierNameExpression(SyntaxNode syntax, string name) + : base(syntax) + { + Name = name; + } + + public string Name { get; } + public override BoundNodeKind Kind => BoundNodeKind.IdentifierNameExpression; + } + + public class BoundIndirectMemberAccessExpression : BoundExpression + { + public BoundIndirectMemberAccessExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.IndirectMemberAccessExpression; + } + + public class BoundLambdaExpression : BoundExpression + { + public BoundLambdaExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.LambdaExpression; + } + + public class BoundMemberAccessExpression : BoundExpression + { + public BoundMemberAccessExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.MemberAccessExpression; + } + + public class BoundNamedFunctionHandleExpression : BoundExpression + { + public BoundNamedFunctionHandleExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.NamedFunctionHandleExpression; + } + + public class BoundNumberLiteralExpression : BoundExpression + { + public BoundNumberLiteralExpression(SyntaxNode syntax, double value) + : base(syntax) + { + Value = value; + } + + public double Value { get; } + public override BoundNodeKind Kind => BoundNodeKind.NumberLiteralExpression; + } + + public class BoundStringLiteralExpression : BoundExpression + { + public BoundStringLiteralExpression(SyntaxNode syntax, string value) + : base(syntax) + { + Value = value; + } + + public string Value { get; } + public override BoundNodeKind Kind => BoundNodeKind.StringLiteralExpression; + } + + public class BoundUnaryOperationExpression : BoundExpression + { + public BoundUnaryOperationExpression(SyntaxNode syntax, BoundUnaryOperator op, BoundExpression operand) + : base(syntax) + { + Op = op; + Operand = operand; + } + + public override BoundNodeKind Kind => BoundNodeKind.UnaryOperationExpression; + + public BoundUnaryOperator Op { get; } + public BoundExpression Operand { get; } + } + + public class BoundUnquotedStringLiteralExpression : BoundExpression + { + public BoundUnquotedStringLiteralExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.UnquotedStringLiteralExpression; + } + + public class BoundElseifClause : BoundNode + { + public BoundElseifClause(SyntaxNode syntax, BoundExpression condition, BoundStatement body) + : base(syntax) + { + Condition = condition; + Body = body; + } + + public BoundExpression Condition { get; } + public BoundStatement Body { get; } + public override BoundNodeKind Kind => BoundNodeKind.ElseIfClause; + } +} diff --git a/Parser/Binding/BoundTreeRewriter.cs b/Parser/Binding/BoundTreeRewriter.cs new file mode 100644 index 0000000..83dd602 --- /dev/null +++ b/Parser/Binding/BoundTreeRewriter.cs @@ -0,0 +1,393 @@ +using System; +using System.Collections.Immutable; +using static Parser.Binding.BoundNodeFactory; + +namespace Parser.Binding +{ + public abstract class BoundTreeRewriter + { + public virtual BoundStatement RewriteStatement(BoundStatement node) + { + return node.Kind switch + { + BoundNodeKind.AbstractMethodDeclaration => + RewriteAbstractMethodDeclaration((BoundAbstractMethodDeclaration)node), + BoundNodeKind.BlockStatement => + RewriteBlockStatement((BoundBlockStatement)node), + BoundNodeKind.ClassDeclaration => + RewriteClassDeclaration((BoundClassDeclaration)node), + BoundNodeKind.ConcreteMethodDeclaration => + RewriteConcreteMethodDeclaration((BoundConcreteMethodDeclaration)node), + BoundNodeKind.ConditionalGotoStatement => + RewriteConditionalGotoStatement((BoundConditionalGotoStatement)node), + BoundNodeKind.EmptyStatement => + RewriteEmptyStatement((BoundEmptyStatement)node), + BoundNodeKind.ExpressionStatement => + RewriteExpressionStatement((BoundExpressionStatement)node), + BoundNodeKind.ForStatement => + RewriteForStatement((BoundForStatement)node), + BoundNodeKind.FunctionDeclaration => + RewriteFunctionDeclaration((BoundFunctionDeclaration)node), + BoundNodeKind.GotoStatement => + RewriteGotoStatement((BoundGotoStatement)node), + BoundNodeKind.IfStatement => + RewriteIfStatement((BoundIfStatement)node), + BoundNodeKind.LabelStatement => + RewriteLabelStatement((BoundLabelStatement)node), + BoundNodeKind.SwitchStatement => + RewriteSwitchStatement((BoundSwitchStatement)node), + BoundNodeKind.TryCatchStatement => + RewriteTryCatchStatement((BoundTryCatchStatement)node), + BoundNodeKind.WhileStatement => + RewriteWhileStatement((BoundWhileStatement)node), + _ => + throw new Exception($"Invalid statement kind {node.Kind}."), + }; + } + + public virtual BoundStatement RewriteGotoStatement(BoundGotoStatement node) + { + return node; + } + + public virtual BoundStatement RewriteConditionalGotoStatement(BoundConditionalGotoStatement node) + { + var condition = RewriteExpression(node.Condition); + if (condition == node.Condition) + { + return node; + } + + return ConditionalGoto(node.Syntax, condition, node.Label, node.GotoIfTrue); + } + + public virtual BoundStatement RewriteWhileStatement(BoundWhileStatement node) + { + throw new NotImplementedException(); + } + + public virtual BoundStatement RewriteTryCatchStatement(BoundTryCatchStatement node) + { + throw new NotImplementedException(); + } + + public virtual BoundStatement RewriteSwitchStatement(BoundSwitchStatement node) + { + throw new NotImplementedException(); + } + + public virtual BoundStatement RewriteLabelStatement(BoundLabelStatement node) + { + return node; + } + + public virtual BoundStatement RewriteIfStatement(BoundIfStatement node) + { + var condition = RewriteExpression(node.Condition); + var body = RewriteStatement(node.Body); + ImmutableArray.Builder? builder = null; + for (var i = 0; i < node.ElseifClauses.Length; i++) + { + var oldClause = node.ElseifClauses[i]; + var newClause = RewriteElseifClause(oldClause); + if (oldClause != newClause && builder is null) + { + builder = ImmutableArray.CreateBuilder(node.ElseifClauses.Length); + for (var j = 0; j < i; j++) + { + builder.Add(node.ElseifClauses[j]); + } + } + if (builder is not null) + { + builder.Add(newClause); + } + } + + var elseIfClauses = builder is null ? node.ElseifClauses : builder.MoveToImmutable(); + var elseClause = node.ElseClause is null ? null : RewriteStatement(node.ElseClause); + if (condition == node.Condition && + body == node.Body && + elseIfClauses == node.ElseifClauses && + elseClause == node.ElseClause ) + { + return node; + } + + return IfStatement(node.Syntax, condition, body, elseIfClauses, elseClause); + } + + public virtual BoundElseifClause RewriteElseifClause(BoundElseifClause node) + { + var condition = RewriteExpression(node.Condition); + var body = RewriteStatement(node.Body); + if (condition == node.Condition && body == node.Body) + { + return node; + } + + return ElseifClause(node.Syntax, condition, body); + } + + public virtual BoundStatement RewriteFunctionDeclaration(BoundFunctionDeclaration node) + { + throw new NotImplementedException(); + } + + public virtual BoundStatement RewriteForStatement(BoundForStatement node) + { + throw new NotImplementedException(); + } + + public virtual BoundStatement RewriteExpressionStatement(BoundExpressionStatement node) + { + var expression = RewriteExpression(node.Expression); + if (expression == node.Expression) + { + return node; + } + + return ExpressionStatement(node.Syntax, expression); + } + + public virtual BoundStatement RewriteEmptyStatement(BoundEmptyStatement node) + { + throw new NotImplementedException(); + } + + public virtual BoundStatement RewriteConcreteMethodDeclaration(BoundConcreteMethodDeclaration node) + { + throw new NotImplementedException(); + } + + public virtual BoundStatement RewriteClassDeclaration(BoundClassDeclaration node) + { + throw new NotImplementedException(); + } + + public virtual BoundStatement RewriteBlockStatement(BoundBlockStatement node) + { + ImmutableArray.Builder? builder = null; + for (var i = 0; i < node.Statements.Length; i++) + { + var oldStatement = node.Statements[i]; + var newStatement = RewriteStatement(oldStatement); + if (oldStatement != newStatement && builder is null) + { + builder = ImmutableArray.CreateBuilder(node.Statements.Length); + for (var j = 0; j < i; j++) + { + builder.Add(node.Statements[j]); + } + } + if (builder is not null) + { + builder.Add(newStatement); + } + + } + + if (builder is null) + { + return node; + } + + return Block(node.Syntax, builder.MoveToImmutable()); + } + + public virtual BoundStatement RewriteAbstractMethodDeclaration(BoundAbstractMethodDeclaration node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteExpression(BoundExpression node) + { + return node.Kind switch + { + BoundNodeKind.ArrayLiteralExpression => + RewriteArrayLiteralExpression((BoundArrayLiteralExpression)node), + BoundNodeKind.AssignmentExpression => + RewriteAssignmentExpression((BoundAssignmentExpression)node), + BoundNodeKind.BinaryOperationExpression => + RewriteBinaryOperationExpression((BoundBinaryOperationExpression)node), + BoundNodeKind.CellArrayElementAccessExpression => + RewriteCellArrayElementAccessExpression((BoundCellArrayElementAccessExpression)node), + BoundNodeKind.CellArrayLiteralExpression => + RewriteCellArrayLiteralExpression((BoundCellArrayLiteralExpression)node), + BoundNodeKind.ClassInvokationExpression => + RewriteClassInvokationExpression((BoundClassInvokationExpression)node), + BoundNodeKind.CommandExpression => + RewriteCommandExpression((BoundCommandExpression)node), + BoundNodeKind.CompoundNameExpression => + RewriteCompoundNameExpression((BoundCompoundNameExpression)node), + BoundNodeKind.DoubleQuotedStringLiteralExpression => + RewriteDoubleQuotedStringLiteralExpression((BoundDoubleQuotedStringLiteralExpression)node), + BoundNodeKind.EmptyExpression => + RewriteEmptyExpression((BoundEmptyExpression)node), + BoundNodeKind.FunctionCallExpression => + RewriteFunctionCallExpression((BoundFunctionCallExpression)node), + BoundNodeKind.IdentifierNameExpression => + RewriteIdentifierNameExpression((BoundIdentifierNameExpression)node), + BoundNodeKind.IndirectMemberAccessExpression => + RewriteIndirectMemberAccessExpression((BoundIndirectMemberAccessExpression)node), + BoundNodeKind.LambdaExpression => + RewriteLambdaExpression((BoundLambdaExpression)node), + BoundNodeKind.MemberAccessExpression => + RewriteMemberAccessExpression((BoundMemberAccessExpression)node), + BoundNodeKind.NamedFunctionHandleExpression => + RewriteNamedFunctionHandleExpression((BoundNamedFunctionHandleExpression)node), + BoundNodeKind.NumberLiteralExpression => + RewriteNumberLiteralExpression((BoundNumberLiteralExpression)node), + BoundNodeKind.StringLiteralExpression => + RewriteStringLiteralExpression((BoundStringLiteralExpression)node), + BoundNodeKind.UnaryOperationExpression => + RewriteUnaryOperationExpression((BoundUnaryOperationExpression)node), + BoundNodeKind.UnquotedStringLiteralExpression => + RewriteUnquotedStringLiteralExpression((BoundUnquotedStringLiteralExpression)node), + _ => + throw new Exception($"Invalid expression kind {node.Kind}."), + }; + } + + public virtual BoundExpression RewriteUnquotedStringLiteralExpression(BoundUnquotedStringLiteralExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteUnaryOperationExpression(BoundUnaryOperationExpression node) + { + var operand = RewriteExpression(node.Operand); + return new BoundUnaryOperationExpression(node.Syntax, node.Op, operand); + } + + public virtual BoundExpression RewriteStringLiteralExpression(BoundStringLiteralExpression node) + { + return node; + } + + public virtual BoundExpression RewriteNumberLiteralExpression(BoundNumberLiteralExpression node) + { + return node; + } + + public virtual BoundExpression RewriteNamedFunctionHandleExpression(BoundNamedFunctionHandleExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteMemberAccessExpression(BoundMemberAccessExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteLambdaExpression(BoundLambdaExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteIndirectMemberAccessExpression(BoundIndirectMemberAccessExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteIdentifierNameExpression(BoundIdentifierNameExpression node) + { + return node; + } + + public virtual BoundExpression RewriteFunctionCallExpression(BoundFunctionCallExpression node) + { + + ImmutableArray.Builder? builder = null; + for (var i = 0; i < node.Arguments.Length; i++) + { + var oldArgument = node.Arguments[i]; + var newArgument = RewriteExpression(oldArgument); + if (oldArgument != newArgument && builder is null) + { + builder = ImmutableArray.CreateBuilder(node.Arguments.Length); + for (var j = 0; j < i; j++) + { + builder.Add(node.Arguments[j]); + } + } + if (builder is not null) + { + builder.Add(newArgument); + } + + } + + if (builder is null) + { + return node; + } + + return FunctionCall(node.Syntax, node.Name, builder.MoveToImmutable()); + } + + public virtual BoundExpression RewriteEmptyExpression(BoundEmptyExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteDoubleQuotedStringLiteralExpression(BoundDoubleQuotedStringLiteralExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteCommandExpression(BoundCommandExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteCompoundNameExpression(BoundCompoundNameExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteClassInvokationExpression(BoundClassInvokationExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteCellArrayLiteralExpression(BoundCellArrayLiteralExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteCellArrayElementAccessExpression(BoundCellArrayElementAccessExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteBinaryOperationExpression(BoundBinaryOperationExpression node) + { + var left = RewriteExpression(node.Left); + var right = RewriteExpression(node.Right); + if (left == node.Left && right == node.Right) + { + return node; + } + + return new BoundBinaryOperationExpression(node.Syntax, left, node.Op, right); + } + + public virtual BoundExpression RewriteAssignmentExpression(BoundAssignmentExpression node) + { + var left = RewriteExpression(node.Left); + var right = RewriteExpression(node.Right); + if (left == node.Left && right == node.Right) + { + return node; + } + + return Assignment(node.Syntax, left, right); + } + + public virtual BoundExpression RewriteArrayLiteralExpression(BoundArrayLiteralExpression node) + { + throw new NotImplementedException(); + } + } +} diff --git a/Parser/Binding/BoundUnaryOperator.cs b/Parser/Binding/BoundUnaryOperator.cs new file mode 100644 index 0000000..7006e1a --- /dev/null +++ b/Parser/Binding/BoundUnaryOperator.cs @@ -0,0 +1,26 @@ +using System.Linq; + +namespace Parser.Binding +{ + public class BoundUnaryOperator + { + private static BoundUnaryOperator[] _operators = + { + new BoundUnaryOperator(TokenKind.MinusToken, BoundUnaryOperatorKind.Minus), + }; + + public BoundUnaryOperator(TokenKind syntaxKind, BoundUnaryOperatorKind kind) + { + SyntaxKind = syntaxKind; + Kind = kind; + } + + public TokenKind SyntaxKind { get; } + public BoundUnaryOperatorKind Kind { get; } + + internal static BoundUnaryOperator? GetOperator(TokenKind kind) + { + return _operators.FirstOrDefault(op => op.SyntaxKind == kind); + } + } +} diff --git a/Parser/Binding/BoundUnaryOperatorKind.cs b/Parser/Binding/BoundUnaryOperatorKind.cs new file mode 100644 index 0000000..73d3fc2 --- /dev/null +++ b/Parser/Binding/BoundUnaryOperatorKind.cs @@ -0,0 +1,7 @@ +namespace Parser.Binding +{ + public enum BoundUnaryOperatorKind + { + Minus, + } +} diff --git a/Parser/Binding/FunctionSymbol.cs b/Parser/Binding/FunctionSymbol.cs new file mode 100644 index 0000000..311d052 --- /dev/null +++ b/Parser/Binding/FunctionSymbol.cs @@ -0,0 +1,13 @@ +namespace Parser.Binding +{ + public class FunctionSymbol + { + public FunctionSymbol( + string name) + { + Name = name; + } + + public string Name { get; } + } +} diff --git a/Parser/Binding/LoweredFunction.cs b/Parser/Binding/LoweredFunction.cs new file mode 100644 index 0000000..a8d8c6e --- /dev/null +++ b/Parser/Binding/LoweredFunction.cs @@ -0,0 +1,26 @@ +using System.Collections.Immutable; + +namespace Parser.Binding +{ + public class LoweredFunction { + public LoweredFunction( + BoundFunctionDeclaration declaration, + string name, + ImmutableArray inputDescription, + ImmutableArray outputDescription, + BoundBlockStatement body) + { + Declaration = declaration; + Name = name; + InputDescription = inputDescription; + OutputDescription = outputDescription; + Body = body; + } + + public BoundFunctionDeclaration Declaration { get; } + public string Name { get; } + public ImmutableArray InputDescription { get; } + public ImmutableArray OutputDescription { get; } + public BoundBlockStatement Body { get; } + } +} diff --git a/Parser/Binding/ParameterSymbol.cs b/Parser/Binding/ParameterSymbol.cs new file mode 100644 index 0000000..5b5f234 --- /dev/null +++ b/Parser/Binding/ParameterSymbol.cs @@ -0,0 +1,12 @@ +namespace Parser.Binding +{ + public class ParameterSymbol + { + public ParameterSymbol(string name) + { + Name = name; + } + + public string Name { get; } + } +} diff --git a/Parser/Compilation.cs b/Parser/Compilation.cs new file mode 100644 index 0000000..d566e7e --- /dev/null +++ b/Parser/Compilation.cs @@ -0,0 +1,36 @@ +using Parser.Binding; + +namespace Parser +{ + public class Compilation + { + private readonly SyntaxTree _syntaxTree; + + private Compilation(SyntaxTree syntaxTree) + { + _syntaxTree = syntaxTree; + } + + public static Compilation Create(SyntaxTree syntaxTree) + { + return new Compilation(syntaxTree); + } + + private BoundProgram GetBoundProgram() + { + return Binder.BindProgram(_syntaxTree); + } + + public EvaluationResult Evaluate(CompilationContext context, bool inRepl) + { + var program = GetBoundProgram(); + if (program.Diagnostics.Length > 0) + { + return new EvaluationResult(null, program.Diagnostics); + } + + var evaluator = new Evaluator(program, context, inRepl); + return evaluator.Evaluate(); + } + } +} \ No newline at end of file diff --git a/Parser/CompilationContext.cs b/Parser/CompilationContext.cs new file mode 100644 index 0000000..b716356 --- /dev/null +++ b/Parser/CompilationContext.cs @@ -0,0 +1,11 @@ +using Parser.Objects; +using System.Collections.Generic; + +namespace Parser +{ + public class CompilationContext + { + public Dictionary Variables { get; } = new Dictionary(); + public static CompilationContext Empty => new CompilationContext(); + } +} \ No newline at end of file diff --git a/Parser/EvaluationResult.cs b/Parser/EvaluationResult.cs new file mode 100644 index 0000000..97e0c56 --- /dev/null +++ b/Parser/EvaluationResult.cs @@ -0,0 +1,19 @@ +using Parser.Internal; +using Parser.Objects; +using System.Collections.Immutable; + +namespace Parser +{ + public class EvaluationResult + { + public EvaluationResult(MObject? value, ImmutableArray diagnostics) + { + Value = value; + Diagnostics = diagnostics; + } + + public MObject? Value { get; } + + public ImmutableArray Diagnostics { get; } + } +} \ No newline at end of file diff --git a/Parser/EvaluationScope.cs b/Parser/EvaluationScope.cs new file mode 100644 index 0000000..6eb7a77 --- /dev/null +++ b/Parser/EvaluationScope.cs @@ -0,0 +1,10 @@ +using Parser.Objects; +using System.Collections.Generic; + +namespace Parser +{ + internal class EvaluationScope + { + public Dictionary Variables { get; } = new Dictionary(); + } +} \ No newline at end of file diff --git a/Parser/Evaluator.cs b/Parser/Evaluator.cs new file mode 100644 index 0000000..b03aa7d --- /dev/null +++ b/Parser/Evaluator.cs @@ -0,0 +1,552 @@ +using Parser.Binding; +using Parser.Internal; +using Parser.MFunctions; +using Parser.Objects; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace Parser +{ + internal class Evaluator + { + private readonly BoundProgram _program; + private readonly CompilationContext _context; + private readonly DiagnosticsBag _diagnostics = new DiagnosticsBag(); + private bool _inRepl = false; + private readonly Stack _scopeStack = new Stack(); + private readonly Dictionary _functions = new Dictionary(); + + public Evaluator(BoundProgram program, CompilationContext context, bool inRepl) + { + _program = program; + _context = context; + var outerScope = new EvaluationScope(); + _scopeStack.Push(outerScope); + _inRepl = inRepl; + foreach (var pair in program.Functions) + { + _functions[pair.Key] = pair.Value; + } + } + + internal EvaluationResult Evaluate() + { + if (_program.MainFunction is { } mainFunctionSymbol) + { + var mainFunction = _program.Functions[mainFunctionSymbol]; + if (mainFunction.InputDescription.Length > 0) + { + _diagnostics.ReportNotEnoughInputs( + new TextSpan(mainFunction.Body.Syntax.Position, mainFunction.Body.Syntax.Position + mainFunction.Body.Syntax.FullWidth), + mainFunction.Name); + return new EvaluationResult(null, _diagnostics.ToImmutableArray()); + } + else + { + var result = EvaluateBlockStatement(mainFunction.Body); + return new EvaluationResult(result, _diagnostics.ToImmutableArray()); + } + } + else if (_program.ScriptFunction is { } scriptFunctionSymbol) + { + var scriptFunction = _program.Functions[scriptFunctionSymbol]; + var result = EvaluateBlockStatement(scriptFunction.Body); + return new EvaluationResult(result, _diagnostics.ToImmutableArray()); + } + else + { + return new EvaluationResult(null, _diagnostics.ToImmutableArray()); + } + } + + private MObject? EvaluateFile(BoundFile root) + { + return EvaluateStatement(root.Body); + } + + private MObject? EvaluateBlockStatement(BoundBlockStatement node) + { + var labelToIndex = new Dictionary(); + for (var i = 0; i < node.Statements.Length; i++) + { + var statement = node.Statements[i]; + if (statement.Kind == BoundNodeKind.LabelStatement) + { + labelToIndex[((BoundLabelStatement)statement).Label] = i; + } + } + + MObject? lastResult = null; + var index = 0; + while (index < node.Statements.Length) + { + var statement = node.Statements[index]; + switch (statement.Kind) + { + case BoundNodeKind.GotoStatement: + var gs = (BoundGotoStatement)statement; + index = labelToIndex[gs.Label]; + break; + case BoundNodeKind.ConditionalGotoStatement: + var cgs = (BoundConditionalGotoStatement)statement; + var value = EvaluateExpression(cgs.Condition); + var truth = IsTruthyValue(value); + if ((cgs.GotoIfTrue && truth) || + (!cgs.GotoIfTrue && !truth)) + { + index = labelToIndex[cgs.Label]; + } + else + { + index++; + } + break; + case BoundNodeKind.LabelStatement: + index++; + break; + default: + lastResult = EvaluateStatement(statement) ?? lastResult; + index++; + break; + } + } + + return lastResult; + } + + private bool IsTruthyValue(MObject? expression) + { + if (expression is MLogical { Value: true }) + { + return true; + } + + return false; + } + + private MObject? EvaluateStatement(BoundStatement node) + { + return node.Kind switch + { + BoundNodeKind.AbstractMethodDeclaration => + EvaluateAbstractMethodDeclaration((BoundAbstractMethodDeclaration)node), + BoundNodeKind.BlockStatement => + EvaluateBlockStatement((BoundBlockStatement)node), + BoundNodeKind.ClassDeclaration => + EvaluateClassDeclaration((BoundClassDeclaration)node), + BoundNodeKind.EmptyStatement => + EvaluateEmptyStatement((BoundEmptyStatement)node), + BoundNodeKind.ExpressionStatement => + EvaluateExpressionStatement((BoundExpressionStatement)node), + BoundNodeKind.ForStatement => + EvaluateForStatement((BoundForStatement)node), + BoundNodeKind.FunctionDeclaration => + EvaluateFunctionDeclaration((BoundFunctionDeclaration)node), + BoundNodeKind.IfStatement => + EvaluateIfStatement((BoundIfStatement)node), + BoundNodeKind.ConcreteMethodDeclaration => + EvaluateMethodDefinition((BoundConcreteMethodDeclaration)node), + BoundNodeKind.SwitchStatement => + EvaluateSwitchStatement((BoundSwitchStatement)node), + BoundNodeKind.TryCatchStatement => + EvaluateTryCatchStatement((BoundTryCatchStatement)node), + BoundNodeKind.WhileStatement => + EvaluateWhileStatement((BoundWhileStatement)node), + _ => throw new NotImplementedException($"Invalid statement kind '{node.Kind}'."), + }; + } + + private MObject? EvaluateClassDeclaration(BoundClassDeclaration node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateEmptyStatement(BoundEmptyStatement node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateTryCatchStatement(BoundTryCatchStatement node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateForStatement(BoundForStatement node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateIfStatement(BoundIfStatement node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateWhileStatement(BoundWhileStatement node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateSwitchStatement(BoundSwitchStatement node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateFunctionDeclaration(BoundFunctionDeclaration node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateAbstractMethodDeclaration(BoundAbstractMethodDeclaration node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateMethodDefinition(BoundConcreteMethodDeclaration node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateExpressionStatement(BoundExpressionStatement node) + { + return EvaluateExpression(node.Expression); + } + + private MObject? EvaluateExpression(BoundExpression node) + { + return node.Kind switch + { + BoundNodeKind.ArrayLiteralExpression => + EvaluateArrayLiteralExpression((BoundArrayLiteralExpression)node), + BoundNodeKind.AssignmentExpression => + EvaluateAssignmentExpression((BoundAssignmentExpression)node), + BoundNodeKind.BinaryOperationExpression => + EvaluateBinaryOperation((BoundBinaryOperationExpression)node), + BoundNodeKind.CellArrayElementAccessExpression => + EvaluateCellArrayElementAccess((BoundCellArrayElementAccessExpression)node), + BoundNodeKind.CellArrayLiteralExpression => + EvaluateCellArrayLiteralExpression((BoundCellArrayLiteralExpression)node), + BoundNodeKind.ClassInvokationExpression => + EvaluateClassInvokation((BoundClassInvokationExpression)node), + BoundNodeKind.CommandExpression => + EvaluateCommand((BoundCommandExpression)node), + BoundNodeKind.CompoundNameExpression => + EvaluateCompoundName((BoundCompoundNameExpression)node), + BoundNodeKind.DoubleQuotedStringLiteralExpression => + EvaluateDoubleQuotedStringLiteralExpression((BoundDoubleQuotedStringLiteralExpression)node), + BoundNodeKind.EmptyExpression => + EvaluateEmptyExpression((BoundEmptyExpression)node), + BoundNodeKind.FunctionCallExpression => + EvaluateFunctionCall((BoundFunctionCallExpression)node), + BoundNodeKind.IdentifierNameExpression => + EvaluateIdentifierNameExpression((BoundIdentifierNameExpression)node), + BoundNodeKind.IndirectMemberAccessExpression => + EvaluateIndirectMemberAccess((BoundIndirectMemberAccessExpression)node), + BoundNodeKind.LambdaExpression => + EvaluateLambdaExpression((BoundLambdaExpression)node), + BoundNodeKind.MemberAccessExpression => + EvaluateMemberAccess((BoundMemberAccessExpression)node), + BoundNodeKind.NamedFunctionHandleExpression => + EvaluateNamedFunctionHandleExpression((BoundNamedFunctionHandleExpression)node), + BoundNodeKind.NumberLiteralExpression => + EvaluateNumberLiteralExpression((BoundNumberLiteralExpression)node), + BoundNodeKind.StringLiteralExpression => + EvaluateStringLiteralExpression((BoundStringLiteralExpression)node), + BoundNodeKind.UnaryOperationExpression => + EvaluateUnaryOperationExpression((BoundUnaryOperationExpression)node), + BoundNodeKind.UnquotedStringLiteralExpression => + EvaluateUnquotedStringLiteralExpression((BoundUnquotedStringLiteralExpression)node), + _ => throw new NotImplementedException($"Invalid expression kind '{node.Kind}'."), + }; + } + + private MObject? EvaluateClassInvokation(BoundClassInvokationExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateCommand(BoundCommandExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateIndirectMemberAccess(BoundIndirectMemberAccessExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateMemberAccess(BoundMemberAccessExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateFunctionCall(BoundFunctionCallExpression node) + { + var arguments = new List(); + var allGood = true; + foreach (var argument in node.Arguments) + { + var evaluatedArgument = EvaluateExpression(argument); + if (argument is null) + { + _diagnostics.ReportCannotEvaluateExpression( + new TextSpan(argument.Syntax.Position, argument.Syntax.FullWidth)); + allGood = false; + } + else + { + arguments.Add(evaluatedArgument); + } + + } + if (!allGood) + { + return null; + } + + var function = GetFunctionSymbol(node.Name); + if (function.Name == "disp") + { + return EvaluateDisp(arguments); + } + else + { + var resolvedFunction = ResolveFunction(function); + if (resolvedFunction is null) + { + _diagnostics.ReportFunctionNotFound( + new TextSpan( + node.Name.Syntax.Position, + node.Name.Syntax.Position + node.Name.Syntax.FullWidth), + function.Name); + return null; + } + else + { + // bring arguments into context + var newScope = new EvaluationScope(); + var counter = 0; + foreach (var expectedArgument in resolvedFunction.InputDescription) + { + if (counter >= arguments.Count) + { + break; + } + newScope.Variables.Add(expectedArgument.Name, arguments[counter]); + counter++; + } + + if (counter < arguments.Count) + { + _diagnostics.ReportTooManyInputs( + new TextSpan( + node.Arguments[counter].Syntax.Position, + node.Arguments[counter].Syntax.Position + node.Arguments[counter].Syntax.FullWidth), + function.Name); + return null; + } + _scopeStack.Push(newScope); + var result = EvaluateBlockStatement(resolvedFunction.Body); + _scopeStack.Pop(); + return result; + } + } + } + + private LoweredFunction? ResolveFunction(UnresolvedFunctionSymbol functionSymbol) + { + var maybeKey = _functions.Keys.FirstOrDefault(k => k.Name == functionSymbol.Name); + return maybeKey switch + { + { } key => _functions[key], + _ => null, + }; + } + + private MObject? EvaluateDisp(List arguments) + { + if (arguments.Count != 1) + { + throw new NotImplementedException($"Cannot evaluate disp() with {arguments.Count} arguments."); + } + + Console.WriteLine(arguments[0]); + return arguments[0]; + } + + private UnresolvedFunctionSymbol GetFunctionSymbol(BoundExpression functionName) + { + if (functionName.Kind == BoundNodeKind.IdentifierNameExpression) + { + return new UnresolvedFunctionSymbol(((BoundIdentifierNameExpression)functionName).Name); + } + + throw new NotImplementedException($"Unknown function symbol '{functionName.Syntax.Text}'."); + } + + private MObject? EvaluateCellArrayElementAccess(BoundCellArrayElementAccessExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateCellArrayLiteralExpression(BoundCellArrayLiteralExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateArrayLiteralExpression(BoundArrayLiteralExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateUnquotedStringLiteralExpression(BoundUnquotedStringLiteralExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateDoubleQuotedStringLiteralExpression(BoundDoubleQuotedStringLiteralExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateStringLiteralExpression(BoundStringLiteralExpression node) + { + return node.Value switch + { + string s => MObject.CreateCharArray(s.ToCharArray()), + _ => null, + }; + } + + private MObject? EvaluateNumberLiteralExpression(BoundNumberLiteralExpression node) + { + return MObject.CreateDoubleNumber(node.Value); + } + + private MObject? EvaluateIdentifierNameExpression(BoundIdentifierNameExpression node) + { + var variableName = node.Name; + var maybeValue = GetVariableValue(variableName); + if (maybeValue is null) + { + _diagnostics.ReportVariableNotFound( + new TextSpan(node.Syntax.Position, node.Syntax.FullWidth), + variableName); + } + + return maybeValue; + } + + private MObject? EvaluateBinaryOperation(BoundBinaryOperationExpression node) + { + var left = EvaluateExpression(node.Left); + if (left is null) + { + return null; + } + + var right = EvaluateExpression(node.Right); + if (right is null) + { + return null; + } + + return node.Op.Kind switch + { + BoundBinaryOperatorKind.Plus => MOperations.Plus(left, right), + BoundBinaryOperatorKind.Minus => MOperations.Minus(left, right), + BoundBinaryOperatorKind.Star => MOperations.Star(left, right), + BoundBinaryOperatorKind.Slash => MOperations.Slash(left, right), + BoundBinaryOperatorKind.Greater => MOperations.Greater(left, right), + BoundBinaryOperatorKind.GreaterOrEquals => MOperations.GreaterOrEquals(left, right), + BoundBinaryOperatorKind.Less => MOperations.Less(left, right), + BoundBinaryOperatorKind.LessOrEquals => MOperations.LessOrEquals(left, right), + _ => throw new NotImplementedException($"Binary operation {node.Op.Kind} is not implemented."), + }; + } + + private MObject? EvaluateCompoundName(BoundCompoundNameExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateUnaryOperationExpression(BoundUnaryOperationExpression node) + { + var operand = EvaluateExpression(node.Operand); + if (operand is null) + { + return null; + } + + return node.Op.Kind switch + { + BoundUnaryOperatorKind.Minus => MOperations.Minus(operand), + _ => throw new NotImplementedException($"Unary operation {node.Op.Kind} is not implemented."), + }; + } + + private MObject? EvaluateEmptyExpression(BoundEmptyExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateAssignmentExpression(BoundAssignmentExpression node) + { + var rightValue = EvaluateExpression(node.Right); + if (rightValue is null) + { + _diagnostics.ReportCannotEvaluateExpression( + new TextSpan(node.Right.Syntax.Position, node.Right.Syntax.Position + node.Right.Syntax.FullWidth)); + return null; + } + + var left = node.Left; + if (left.Kind == BoundNodeKind.IdentifierNameExpression) + { + var leftIdentifier = (BoundIdentifierNameExpression)left; + var variableName = leftIdentifier.Name; + SetVariableValue(variableName, rightValue); + return rightValue; + } + + throw new NotImplementedException(); + } + + private MObject? GetVariableValue(string name) + { + if (_inRepl) + { + return _context.Variables.TryGetValue(name, out var globalValue) ? globalValue : null; + } + else + { + var currentScope = _scopeStack.Peek(); + return currentScope.Variables.TryGetValue(name, out var localValue) ? localValue : null; + } + } + + private void SetVariableValue(string name, MObject value) + { + if (_inRepl) + { + _context.Variables[name] = value; + } + else + { + var currentScope = _scopeStack.Peek(); + currentScope.Variables[name] = value; + } + } + + private MObject? EvaluateLambdaExpression(BoundLambdaExpression node) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateNamedFunctionHandleExpression(BoundNamedFunctionHandleExpression node) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/Parser/Internal/DiagnosticsBag.cs b/Parser/Internal/DiagnosticsBag.cs index 1dadf31..a906357 100644 --- a/Parser/Internal/DiagnosticsBag.cs +++ b/Parser/Internal/DiagnosticsBag.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using System.Linq; @@ -37,6 +38,11 @@ namespace Parser.Internal Report(span, "Unexpected end of file."); } + internal void ReportNotEnoughInputs(TextSpan span, string functionName) + { + Report(span, $"Not enough inputs for function '{functionName}'."); + } + internal void ReportUnexpectedCharacterWhileParsingNumber(TextSpan span, char c) { Report(span, $"Unexpected character '{c}' while parsing a number."); @@ -67,6 +73,11 @@ namespace Parser.Internal Report(span, "Unmatched open parenthesis by the end of file."); } + internal void ReportCannotEvaluateExpression(TextSpan span) + { + Report(span, $"Cannot evaluate expression."); + } + public IEnumerator GetEnumerator() { return _diagnostics.GetEnumerator(); @@ -77,5 +88,19 @@ namespace Parser.Internal return GetEnumerator(); } + internal void ReportVariableNotFound(TextSpan span, string variableName) + { + Report(span, $"Variable '{variableName}' not found."); + } + + internal void ReportFunctionNotFound(TextSpan span, string functionName) + { + Report(span, $"Function '{functionName}' not found."); + } + + internal void ReportTooManyInputs(TextSpan span, string functionName) + { + Report(span, $"Too many inputs in the call to '{functionName}'."); + } } } \ No newline at end of file diff --git a/Parser/Internal/GreenNode.cs b/Parser/Internal/GreenNode.cs index dfda086..1ee5b19 100644 --- a/Parser/Internal/GreenNode.cs +++ b/Parser/Internal/GreenNode.cs @@ -43,6 +43,11 @@ namespace Parser.Internal internal abstract Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position); + public virtual object? GetValue() + { + return null; + } + protected int _fullWidth; public int FullWidth => _fullWidth; diff --git a/Parser/Internal/MLexerGreen.cs b/Parser/Internal/MLexerGreen.cs index 1537d84..5c8a170 100644 --- a/Parser/Internal/MLexerGreen.cs +++ b/Parser/Internal/MLexerGreen.cs @@ -13,6 +13,7 @@ namespace Parser.Internal public string Text { get; set; } = ""; public string StringValue { get; set; } = ""; public double DoubleValue { get; set; } + public bool ImaginaryFlag { get; set; } } private ITextWindow Window { get; } @@ -358,20 +359,48 @@ namespace Parser.Internal if (success) { + tokenInfo.Kind = TokenKind.NumberLiteralToken; + Range rangeToParse; if (Window.PeekChar(n) == 'i' || Window.PeekChar(n) == 'j') { + tokenInfo.ImaginaryFlag = true; n++; + rangeToParse = ..^1; + } + else + { + rangeToParse = ..; } - var s = Window.GetAndConsumeChars(n); - tokenInfo.Kind = TokenKind.NumberLiteralToken; + var s = Window.GetAndConsumeChars(n); tokenInfo.Text = s; - return true; + var maybeValue = ParseDoubleValue(s[rangeToParse]); + if (maybeValue is double value) + { + tokenInfo.DoubleValue = value; + return true; + } + else + { + tokenInfo.DoubleValue = double.NaN; + return true; + } } return false; } + private double? ParseDoubleValue(string s) + { + if (double.TryParse(s, out var doubleValue)) + { + return doubleValue; + } else + { + return null; + } + } + private bool ContinueLexingGeneralStringLiteral(ref TokenInfo tokenInfo, char quote) { var status = 0; // no errors diff --git a/Parser/Internal/MParserGreen.cs b/Parser/Internal/MParserGreen.cs index 1591bb2..dfce71e 100644 --- a/Parser/Internal/MParserGreen.cs +++ b/Parser/Internal/MParserGreen.cs @@ -113,7 +113,7 @@ namespace Parser.Internal } firstToken = false; - outputs.Add(Factory.IdentifierNameSyntax(EatToken(TokenKind.IdentifierToken))); + outputs.Add(Factory.IdentifierNameExpressionSyntax(EatToken(TokenKind.IdentifierToken))); } return outputs.ToList(); @@ -141,7 +141,7 @@ namespace Parser.Internal if (PeekToken(1).Kind == TokenKind.EqualsToken) { var identifierToken = EatIdentifier(); - builder.Add(Factory.IdentifierNameSyntax(identifierToken)); + builder.Add(Factory.IdentifierNameExpressionSyntax(identifierToken)); assignmentSign = EatToken(TokenKind.EqualsToken); } else @@ -175,12 +175,12 @@ namespace Parser.Internal if (CurrentToken.Kind == TokenKind.TildeToken) { var notToken = EatToken(); - builder.Add(notToken); + builder.Add(Factory.IdentifierNameExpressionSyntax(notToken)); } else { var identifierToken = EatToken(TokenKind.IdentifierToken); - builder.Add(Factory.IdentifierNameSyntax(identifierToken)); + builder.Add(Factory.IdentifierNameExpressionSyntax(identifierToken)); } } @@ -212,7 +212,7 @@ namespace Parser.Internal var name = EatToken(TokenKind.IdentifierToken); var inputDescription = ParseFunctionInputDescription(); var commas = ParseOptionalCommas(); - var body = ParseStatementList(); + var body = ParseBlockStatement(); var endKeyword = ParseEndKeyword(); //var endKeyword = return Factory.FunctionDeclarationSyntax( @@ -307,13 +307,13 @@ namespace Parser.Internal switch (token.Kind) { case TokenKind.NumberLiteralToken: - expression = Factory.NumberLiteralSyntax(EatToken()); + expression = Factory.NumberLiteralExpressionSyntax(EatToken()); break; case TokenKind.StringLiteralToken: - expression = Factory.StringLiteralSyntax(EatToken()); + expression = Factory.StringLiteralExpressionSyntax(EatToken()); break; case TokenKind.DoubleQuotedStringLiteralToken: - expression = Factory.DoubleQuotedStringLiteralSyntax(EatToken()); + expression = Factory.DoubleQuotedStringLiteralExpressionSyntax(EatToken()); break; case TokenKind.OpenSquareBracketToken: expression = ParseArrayLiteral(); @@ -329,7 +329,7 @@ namespace Parser.Internal break; default: var id = EatToken(TokenKind.IdentifierToken); - expression = Factory.IdentifierNameSyntax(id); + expression = Factory.IdentifierNameExpressionSyntax(id); break; } @@ -377,14 +377,14 @@ namespace Parser.Internal closingBracket); break; case TokenKind.DotToken: // member access - if (expression is IdentifierNameSyntaxNode - || expression is MemberAccessSyntaxNode + if (expression is IdentifierNameExpressionSyntaxNode + || expression is MemberAccessExpressionSyntaxNode || expression is FunctionCallExpressionSyntaxNode || expression is CellArrayElementAccessExpressionSyntaxNode) { var dot = EatToken(); var member = ParseMemberAccess(); - expression = Factory.MemberAccessSyntax(expression, dot, member); + expression = Factory.MemberAccessExpressionSyntax(expression, dot, member); } else { @@ -396,7 +396,7 @@ namespace Parser.Internal case TokenKind.ApostropheToken: case TokenKind.DotApostropheToken: var operation = EatToken(); - expression = Factory.UnaryPostixOperationExpressionSyntax(expression, operation); + expression = Factory.UnaryPostfixOperationExpressionSyntax(expression, operation); break; case TokenKind.UnquotedStringLiteralToken: return ParseCommandExpression(expression); @@ -414,15 +414,15 @@ namespace Parser.Internal private CommandExpressionSyntaxNode ParseCommandExpression(ExpressionSyntaxNode expression) { - if (expression is IdentifierNameSyntaxNode idNameNode) + if (expression is IdentifierNameExpressionSyntaxNode idNameNode) { - var builder = new SyntaxListBuilder(); + var builder = new SyntaxListBuilder(); while (CurrentToken.Kind == TokenKind.UnquotedStringLiteralToken) { - builder.Add(Factory.UnquotedStringLiteralSyntax(EatToken())); + builder.Add(Factory.UnquotedStringLiteralExpressionSyntax(EatToken())); } - return Factory.CommandExpressionSyntax(idNameNode, builder.ToList()); + return Factory.CommandExpressionSyntax(idNameNode._name, builder.ToList()); } if (expression is null) @@ -432,9 +432,9 @@ namespace Parser.Internal throw new ParsingException($"Unexpected token \"{CurrentToken}\" while parsing expression \"{expression.FullText}\" at {CurrentPosition}."); } - private BaseClassInvokationSyntaxNode ParseBaseClassInvokation(ExpressionSyntaxNode expression) + private ClassInvokationExpressionSyntaxNode ParseBaseClassInvokation(ExpressionSyntaxNode expression) { - if (expression is IdentifierNameSyntaxNode methodName + if (expression is IdentifierNameExpressionSyntaxNode methodName && !expression.TrailingTrivia.Any()) { var atToken = EatToken(); @@ -443,9 +443,9 @@ namespace Parser.Internal { throw new Exception($"Base class name cannot be empty."); } - return Factory.BaseClassInvokationSyntax(methodName, atToken, baseClassNameWithArguments); + return Factory.ClassInvokationExpressionSyntax(methodName, atToken, baseClassNameWithArguments); } - if (expression is MemberAccessSyntaxNode memberAccess + if (expression is MemberAccessExpressionSyntaxNode memberAccess && !expression.TrailingTrivia.Any()) { var atToken = EatToken(); @@ -454,7 +454,7 @@ namespace Parser.Internal { throw new Exception($"Base class name cannot be empty."); } - return Factory.BaseClassInvokationSyntax(memberAccess, atToken, baseClassNameWithArguments); + return Factory.ClassInvokationExpressionSyntax(memberAccess, atToken, baseClassNameWithArguments); } throw new ParsingException($"Unexpected token \"{CurrentToken}\" at {CurrentPosition}."); } @@ -463,7 +463,7 @@ namespace Parser.Internal { if (CurrentToken.Kind == TokenKind.IdentifierToken) { - return Factory.IdentifierNameSyntax(EatToken()); + return Factory.IdentifierNameExpressionSyntax(EatToken()); } if (CurrentToken.Kind == TokenKind.OpenParenthesisToken) { @@ -474,7 +474,7 @@ namespace Parser.Internal throw new Exception("Indirect member invokation cannot be empty."); } var closingBracket = EatToken(TokenKind.CloseParenthesisToken); - return Factory.IndirectMemberAccessSyntax( + return Factory.IndirectMemberAccessExpressionSyntax( openingBracket, indirectMember, closingBracket); @@ -523,7 +523,7 @@ namespace Parser.Internal closeParen); } - private CompoundNameSyntaxNode ParseCompoundName() + private CompoundNameExpressionSyntaxNode ParseCompoundName() { var lastToken = EatToken(TokenKind.IdentifierToken); var firstName = lastToken; @@ -538,16 +538,16 @@ namespace Parser.Internal builder.Add(lastToken); } - return Factory.CompoundNameSyntax(builder.ToList()); + return Factory.CompoundNameExpressionSyntax(builder.ToList()); } - private FunctionHandleSyntaxNode ParseFunctionHandle() + private FunctionHandleExpressionSyntaxNode ParseFunctionHandle() { var atSign = EatToken(); if (CurrentToken.Kind == TokenKind.IdentifierToken) { var compoundName = ParseCompoundName(); - return Factory.NamedFunctionHandleSyntax( + return Factory.NamedFunctionHandleExpressionSyntax( atSign, compoundName); } @@ -563,7 +563,7 @@ namespace Parser.Internal { throw new Exception($"Lambda expression body cannot be empty."); } - return Factory.LambdaSyntax(atSign, inputs, body); + return Factory.LambdaExpressionSyntax(atSign, inputs, body); } throw new ParsingException($"Unexpected token {CurrentToken} while parsing function handle at {CurrentPosition}."); } @@ -685,8 +685,8 @@ namespace Parser.Internal throw new Exception("Case label cannot be empty."); } var commas = ParseOptionalCommas(); - var statementList = ParseStatementList(); - return Factory.SwitchCaseSyntax(caseKeyword, caseId, commas, statementList); + var body = ParseBlockStatement(); + return Factory.SwitchCaseSyntax(caseKeyword, caseId, commas, body); } private SwitchStatementSyntaxNode ParseSwitchStatement() @@ -722,7 +722,7 @@ namespace Parser.Internal } var commas = ParseOptionalCommas(); - var body = ParseStatementList(); + var body = ParseBlockStatement(); var endKeyword = EatIdentifier("end"); return Factory.WhileStatementSyntax( whileKeyword, @@ -741,14 +741,14 @@ namespace Parser.Internal throw new Exception("Condition in elseif clause cannot be empty."); } var commas = ParseOptionalCommas(); - var body = ParseStatementList(); + var body = ParseBlockStatement(); return Factory.ElseifClause(elseifKeyword, condition, commas, body); } private ElseClause ParseElseClause() { var elseKeyword = EatIdentifier("else"); - var body = ParseStatementList(); + var body = ParseBlockStatement(); return Factory.ElseClause(elseKeyword, body); } @@ -761,7 +761,7 @@ namespace Parser.Internal throw new Exception("Condition in if statement cannot be empty."); } var commas = ParseOptionalSemicolonsOrCommas(); - var body = ParseStatementList(); + var body = ParseBlockStatement(); var elseifClauses = new SyntaxListBuilder(); ElseClause? elseClause = null; while (true) @@ -804,7 +804,7 @@ namespace Parser.Internal var forAssignment = (AssignmentExpressionSyntaxNode) expression; var commas = ParseOptionalSemicolonsOrCommas(); - var body = ParseStatementList(); + var body = ParseBlockStatement(); var endKeyword = EatIdentifier("end"); return Factory.ForStatementSyntax( forKeyword, @@ -831,7 +831,7 @@ namespace Parser.Internal private TryCatchStatementSyntaxNode ParseTryCatchStatement() { var tryKeyword = EatIdentifier("try"); - var tryBody = ParseStatementList(); + var tryBody = ParseBlockStatement(); var catchClause = ParseCatchClause(); var endKeyword = EatIdentifier("end"); return Factory.TryCatchStatementSyntax(tryKeyword, tryBody, catchClause, endKeyword); @@ -866,7 +866,7 @@ namespace Parser.Internal private AttributeSyntaxNode ParseAttribute() { - var name = Factory.IdentifierNameSyntax(EatToken(TokenKind.IdentifierToken)); + var name = EatToken(TokenKind.IdentifierToken); var assignment = ParseAttributeAssignment(); return Factory.AttributeSyntax(name, assignment); } @@ -920,16 +920,16 @@ namespace Parser.Internal throw new ParsingException($"Unexpected token {CurrentToken} while parsing method declaration at {CurrentPosition}."); } - private MethodDefinitionSyntaxNode ParseMethodDefinition() + private ConcreteMethodDeclarationSyntaxNode ParseMethodDefinition() { var functionKeyword = EatIdentifier("function"); var outputDescription = ParseFunctionOutputDescription(); var name = ParseCompoundName(); var inputDescription = ParseFunctionInputDescription(); var commas = ParseOptionalCommas(); - var body = ParseStatementList(); + var body = ParseBlockStatement(); var endKeyword = ParseEndKeyword(); - return Factory.MethodDefinitionSyntax( + return Factory.ConcreteMethodDeclarationSyntax( functionKeyword, outputDescription, name, @@ -1023,7 +1023,7 @@ namespace Parser.Internal private EnumerationItemSyntaxNode ParseEnumerationItem() { - var name = Factory.IdentifierNameSyntax(EatToken()); + var name = EatToken(); var values = ParseEnumerationValue(); var commas = ParseOptionalCommas(); return Factory.EnumerationItemSyntax(name, values, commas); @@ -1104,7 +1104,7 @@ namespace Parser.Internal { attributes = ParseAttributesList(); } - var className = Factory.IdentifierNameSyntax(EatToken(TokenKind.IdentifierToken)); + var className = EatToken(TokenKind.IdentifierToken); BaseClassListSyntaxNode? baseClassList = null; if (CurrentToken.Kind == TokenKind.LessToken) { @@ -1190,6 +1190,12 @@ namespace Parser.Internal } return ParseExpressionStatement(); } + + private BlockStatementSyntaxNode ParseBlockStatement() + { + var statements = ParseStatementList(); + return Factory.BlockStatementSyntax(statements); + } private SyntaxList ParseStatementList() { @@ -1214,7 +1220,7 @@ namespace Parser.Internal public FileSyntaxNode ParseFile() { - var statementList = ParseStatementList(); + var statementList = ParseBlockStatement(); var endOfFileToken = EatToken(); return Factory.FileSyntax(statementList, endOfFileToken); } diff --git a/Parser/Internal/SyntaxFactory.Generated.cs b/Parser/Internal/SyntaxFactory.Generated.cs index fe84e55..826f4d1 100644 --- a/Parser/Internal/SyntaxFactory.Generated.cs +++ b/Parser/Internal/SyntaxFactory.Generated.cs @@ -3,12 +3,17 @@ namespace Parser.Internal { internal partial class SyntaxFactory { - public FileSyntaxNode FileSyntax(SyntaxList statementList, SyntaxToken endOfFile) + public FileSyntaxNode FileSyntax(BlockStatementSyntaxNode body, SyntaxToken endOfFile) { - return new FileSyntaxNode(statementList, endOfFile); + return new FileSyntaxNode(body, endOfFile); } - public FunctionDeclarationSyntaxNode FunctionDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword) + public BlockStatementSyntaxNode BlockStatementSyntax(SyntaxList statements) + { + return new BlockStatementSyntaxNode(statements); + } + + public FunctionDeclarationSyntaxNode FunctionDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, StatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword) { return new FunctionDeclarationSyntaxNode(functionKeyword, outputDescription, name, inputDescription, commas, body, endKeyword); } @@ -28,32 +33,32 @@ namespace Parser.Internal return new SwitchStatementSyntaxNode(switchKeyword, switchExpression, optionalCommas, cases, endKeyword); } - public SwitchCaseSyntaxNode SwitchCaseSyntax(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, SyntaxList body) + public SwitchCaseSyntaxNode SwitchCaseSyntax(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, StatementSyntaxNode body) { return new SwitchCaseSyntaxNode(caseKeyword, caseIdentifier, optionalCommas, body); } - public WhileStatementSyntaxNode WhileStatementSyntax(SyntaxToken whileKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body, SyntaxToken endKeyword) + public WhileStatementSyntaxNode WhileStatementSyntax(SyntaxToken whileKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxToken endKeyword) { return new WhileStatementSyntaxNode(whileKeyword, condition, optionalCommas, body, endKeyword); } - public ElseifClause ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body) + public ElseifClause ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body) { return new ElseifClause(elseifKeyword, condition, optionalCommas, body); } - public ElseClause ElseClause(SyntaxToken elseKeyword, SyntaxList body) + public ElseClause ElseClause(SyntaxToken elseKeyword, StatementSyntaxNode body) { return new ElseClause(elseKeyword, body); } - public IfStatementSyntaxNode IfStatementSyntax(SyntaxToken ifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body, SyntaxList elseifClauses, ElseClause? elseClause, SyntaxToken endKeyword) + public IfStatementSyntaxNode IfStatementSyntax(SyntaxToken ifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxList elseifClauses, ElseClause? elseClause, SyntaxToken endKeyword) { return new IfStatementSyntaxNode(ifKeyword, condition, optionalCommas, body, elseifClauses, elseClause, endKeyword); } - public ForStatementSyntaxNode ForStatementSyntax(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, SyntaxList body, SyntaxToken endKeyword) + public ForStatementSyntaxNode ForStatementSyntax(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxToken endKeyword) { return new ForStatementSyntaxNode(forKeyword, assignment, optionalCommas, body, endKeyword); } @@ -68,7 +73,7 @@ namespace Parser.Internal return new CatchClauseSyntaxNode(catchKeyword, catchBody); } - public TryCatchStatementSyntaxNode TryCatchStatementSyntax(SyntaxToken tryKeyword, SyntaxList tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword) + public TryCatchStatementSyntaxNode TryCatchStatementSyntax(SyntaxToken tryKeyword, StatementSyntaxNode tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword) { return new TryCatchStatementSyntaxNode(tryKeyword, tryBody, catchClause, endKeyword); } @@ -93,19 +98,19 @@ namespace Parser.Internal return new UnaryPrefixOperationExpressionSyntaxNode(operation, operand); } - public CompoundNameSyntaxNode CompoundNameSyntax(SyntaxList nodes) + public CompoundNameExpressionSyntaxNode CompoundNameExpressionSyntax(SyntaxList nodes) { - return new CompoundNameSyntaxNode(nodes); + return new CompoundNameExpressionSyntaxNode(nodes); } - public NamedFunctionHandleSyntaxNode NamedFunctionHandleSyntax(SyntaxToken atSign, CompoundNameSyntaxNode functionName) + public NamedFunctionHandleExpressionSyntaxNode NamedFunctionHandleExpressionSyntax(SyntaxToken atSign, CompoundNameExpressionSyntaxNode functionName) { - return new NamedFunctionHandleSyntaxNode(atSign, functionName); + return new NamedFunctionHandleExpressionSyntaxNode(atSign, functionName); } - public LambdaSyntaxNode LambdaSyntax(SyntaxToken atSign, FunctionInputDescriptionSyntaxNode input, ExpressionSyntaxNode body) + public LambdaExpressionSyntaxNode LambdaExpressionSyntax(SyntaxToken atSign, FunctionInputDescriptionSyntaxNode input, ExpressionSyntaxNode body) { - return new LambdaSyntaxNode(atSign, input, body); + return new LambdaExpressionSyntaxNode(atSign, input, body); } public BinaryOperationExpressionSyntaxNode BinaryOperationExpressionSyntax(ExpressionSyntaxNode lhs, SyntaxToken operation, ExpressionSyntaxNode rhs) @@ -113,29 +118,29 @@ namespace Parser.Internal return new BinaryOperationExpressionSyntaxNode(lhs, operation, rhs); } - public IdentifierNameSyntaxNode IdentifierNameSyntax(SyntaxToken name) + public IdentifierNameExpressionSyntaxNode IdentifierNameExpressionSyntax(SyntaxToken name) { - return new IdentifierNameSyntaxNode(name); + return new IdentifierNameExpressionSyntaxNode(name); } - public NumberLiteralSyntaxNode NumberLiteralSyntax(SyntaxToken number) + public NumberLiteralExpressionSyntaxNode NumberLiteralExpressionSyntax(SyntaxToken number) { - return new NumberLiteralSyntaxNode(number); + return new NumberLiteralExpressionSyntaxNode(number); } - public StringLiteralSyntaxNode StringLiteralSyntax(SyntaxToken stringToken) + public StringLiteralExpressionSyntaxNode StringLiteralExpressionSyntax(SyntaxToken stringToken) { - return new StringLiteralSyntaxNode(stringToken); + return new StringLiteralExpressionSyntaxNode(stringToken); } - public DoubleQuotedStringLiteralSyntaxNode DoubleQuotedStringLiteralSyntax(SyntaxToken stringToken) + public DoubleQuotedStringLiteralExpressionSyntaxNode DoubleQuotedStringLiteralExpressionSyntax(SyntaxToken stringToken) { - return new DoubleQuotedStringLiteralSyntaxNode(stringToken); + return new DoubleQuotedStringLiteralExpressionSyntaxNode(stringToken); } - public UnquotedStringLiteralSyntaxNode UnquotedStringLiteralSyntax(SyntaxToken stringToken) + public UnquotedStringLiteralExpressionSyntaxNode UnquotedStringLiteralExpressionSyntax(SyntaxToken stringToken) { - return new UnquotedStringLiteralSyntaxNode(stringToken); + return new UnquotedStringLiteralExpressionSyntaxNode(stringToken); } public ArrayLiteralExpressionSyntaxNode ArrayLiteralExpressionSyntax(SyntaxToken openingSquareBracket, SyntaxList nodes, SyntaxToken closingSquareBracket) @@ -163,29 +168,29 @@ namespace Parser.Internal return new FunctionCallExpressionSyntaxNode(functionName, openingBracket, nodes, closingBracket); } - public MemberAccessSyntaxNode MemberAccessSyntax(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand) + public MemberAccessExpressionSyntaxNode MemberAccessExpressionSyntax(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand) { - return new MemberAccessSyntaxNode(leftOperand, dot, rightOperand); + return new MemberAccessExpressionSyntaxNode(leftOperand, dot, rightOperand); } - public UnaryPostixOperationExpressionSyntaxNode UnaryPostixOperationExpressionSyntax(ExpressionSyntaxNode operand, SyntaxToken operation) + public UnaryPostfixOperationExpressionSyntaxNode UnaryPostfixOperationExpressionSyntax(ExpressionSyntaxNode operand, SyntaxToken operation) { - return new UnaryPostixOperationExpressionSyntaxNode(operand, operation); + return new UnaryPostfixOperationExpressionSyntaxNode(operand, operation); } - public IndirectMemberAccessSyntaxNode IndirectMemberAccessSyntax(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket) + public IndirectMemberAccessExpressionSyntaxNode IndirectMemberAccessExpressionSyntax(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket) { - return new IndirectMemberAccessSyntaxNode(openingBracket, expression, closingBracket); + return new IndirectMemberAccessExpressionSyntaxNode(openingBracket, expression, closingBracket); } - public CommandExpressionSyntaxNode CommandExpressionSyntax(IdentifierNameSyntaxNode commandName, SyntaxList arguments) + public CommandExpressionSyntaxNode CommandExpressionSyntax(SyntaxToken commandName, SyntaxList arguments) { return new CommandExpressionSyntaxNode(commandName, arguments); } - public BaseClassInvokationSyntaxNode BaseClassInvokationSyntax(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments) + public ClassInvokationExpressionSyntaxNode ClassInvokationExpressionSyntax(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments) { - return new BaseClassInvokationSyntaxNode(methodName, atSign, baseClassNameAndArguments); + return new ClassInvokationExpressionSyntaxNode(methodName, atSign, baseClassNameAndArguments); } public AttributeAssignmentSyntaxNode AttributeAssignmentSyntax(SyntaxToken assignmentSign, ExpressionSyntaxNode value) @@ -193,7 +198,7 @@ namespace Parser.Internal return new AttributeAssignmentSyntaxNode(assignmentSign, value); } - public AttributeSyntaxNode AttributeSyntax(IdentifierNameSyntaxNode name, AttributeAssignmentSyntaxNode? assignment) + public AttributeSyntaxNode AttributeSyntax(SyntaxToken name, AttributeAssignmentSyntaxNode? assignment) { return new AttributeSyntaxNode(name, assignment); } @@ -203,12 +208,12 @@ namespace Parser.Internal return new AttributeListSyntaxNode(openingBracket, nodes, closingBracket); } - public MethodDefinitionSyntaxNode MethodDefinitionSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword) + public ConcreteMethodDeclarationSyntaxNode ConcreteMethodDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, StatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword) { - return new MethodDefinitionSyntaxNode(functionKeyword, outputDescription, name, inputDescription, commas, body, endKeyword); + return new ConcreteMethodDeclarationSyntaxNode(functionKeyword, outputDescription, name, inputDescription, commas, body, endKeyword); } - public AbstractMethodDeclarationSyntaxNode AbstractMethodDeclarationSyntax(FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription) + public AbstractMethodDeclarationSyntaxNode AbstractMethodDeclarationSyntax(FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription) { return new AbstractMethodDeclarationSyntaxNode(outputDescription, name, inputDescription); } @@ -228,7 +233,7 @@ namespace Parser.Internal return new BaseClassListSyntaxNode(lessSign, baseClasses); } - public ClassDeclarationSyntaxNode ClassDeclarationSyntax(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, IdentifierNameSyntaxNode className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword) + public ClassDeclarationSyntaxNode ClassDeclarationSyntax(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, SyntaxToken className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword) { return new ClassDeclarationSyntaxNode(classdefKeyword, attributes, className, baseClassList, nodes, endKeyword); } @@ -238,7 +243,7 @@ namespace Parser.Internal return new EnumerationItemValueSyntaxNode(openingBracket, values, closingBracket); } - public EnumerationItemSyntaxNode EnumerationItemSyntax(IdentifierNameSyntaxNode name, EnumerationItemValueSyntaxNode? values, SyntaxList commas) + public EnumerationItemSyntaxNode EnumerationItemSyntax(SyntaxToken name, EnumerationItemValueSyntaxNode? values, SyntaxList commas) { return new EnumerationItemSyntaxNode(name, values, commas); } diff --git a/Parser/Internal/SyntaxNode.Generated.cs b/Parser/Internal/SyntaxNode.Generated.cs index 32742dd..149e4bc 100644 --- a/Parser/Internal/SyntaxNode.Generated.cs +++ b/Parser/Internal/SyntaxNode.Generated.cs @@ -3,22 +3,22 @@ namespace Parser.Internal { internal class FileSyntaxNode : SyntaxNode { - internal readonly SyntaxList _statementList; + internal readonly BlockStatementSyntaxNode _body; internal readonly SyntaxToken _endOfFile; - internal FileSyntaxNode(SyntaxList statementList, SyntaxToken endOfFile): base(TokenKind.File) + internal FileSyntaxNode(BlockStatementSyntaxNode body, SyntaxToken endOfFile): base(TokenKind.File) { Slots = 2; - this.AdjustWidth(statementList); - _statementList = statementList; + this.AdjustWidth(body); + _body = body; this.AdjustWidth(endOfFile); _endOfFile = endOfFile; } - internal FileSyntaxNode(SyntaxList statementList, SyntaxToken endOfFile, TokenDiagnostic[] diagnostics): base(TokenKind.File, diagnostics) + internal FileSyntaxNode(BlockStatementSyntaxNode body, SyntaxToken endOfFile, TokenDiagnostic[] diagnostics): base(TokenKind.File, diagnostics) { Slots = 2; - this.AdjustWidth(statementList); - _statementList = statementList; + this.AdjustWidth(body); + _body = body; this.AdjustWidth(endOfFile); _endOfFile = endOfFile; } @@ -30,14 +30,52 @@ namespace Parser.Internal public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new FileSyntaxNode(_statementList, _endOfFile, diagnostics); + return new FileSyntaxNode(_body, _endOfFile, diagnostics); } public override GreenNode? GetSlot(int i) { return i switch { - 0 => _statementList, 1 => _endOfFile, _ => null + 0 => _body, 1 => _endOfFile, _ => null + } + + ; + } + } + + internal class BlockStatementSyntaxNode : StatementSyntaxNode + { + internal readonly SyntaxList _statements; + internal BlockStatementSyntaxNode(SyntaxList statements): base(TokenKind.BlockStatement) + { + Slots = 1; + this.AdjustWidth(statements); + _statements = statements; + } + + internal BlockStatementSyntaxNode(SyntaxList statements, TokenDiagnostic[] diagnostics): base(TokenKind.BlockStatement, diagnostics) + { + Slots = 1; + this.AdjustWidth(statements); + _statements = statements; + } + + internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) + { + return new Parser.BlockStatementSyntaxNode(parent, this, position); + } + + public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) + { + return new BlockStatementSyntaxNode(_statements, diagnostics); + } + + public override GreenNode? GetSlot(int i) + { + return i switch + { + 0 => _statements, _ => null } ; @@ -51,9 +89,9 @@ namespace Parser.Internal internal readonly SyntaxToken _name; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription; internal readonly SyntaxList _commas; - internal readonly SyntaxList _body; + internal readonly StatementSyntaxNode _body; internal readonly EndKeywordSyntaxNode? _endKeyword; - internal FunctionDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.FunctionDeclaration) + internal FunctionDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, StatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.FunctionDeclaration) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -72,7 +110,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal FunctionDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.FunctionDeclaration, diagnostics) + internal FunctionDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, StatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.FunctionDeclaration, diagnostics) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -266,8 +304,8 @@ namespace Parser.Internal internal readonly SyntaxToken _caseKeyword; internal readonly ExpressionSyntaxNode _caseIdentifier; internal readonly SyntaxList _optionalCommas; - internal readonly SyntaxList _body; - internal SwitchCaseSyntaxNode(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, SyntaxList body): base(TokenKind.SwitchCase) + internal readonly StatementSyntaxNode _body; + internal SwitchCaseSyntaxNode(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, StatementSyntaxNode body): base(TokenKind.SwitchCase) { Slots = 4; this.AdjustWidth(caseKeyword); @@ -280,7 +318,7 @@ namespace Parser.Internal _body = body; } - internal SwitchCaseSyntaxNode(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, SyntaxList body, TokenDiagnostic[] diagnostics): base(TokenKind.SwitchCase, diagnostics) + internal SwitchCaseSyntaxNode(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, StatementSyntaxNode body, TokenDiagnostic[] diagnostics): base(TokenKind.SwitchCase, diagnostics) { Slots = 4; this.AdjustWidth(caseKeyword); @@ -319,9 +357,9 @@ namespace Parser.Internal internal readonly SyntaxToken _whileKeyword; internal readonly ExpressionSyntaxNode _condition; internal readonly SyntaxList _optionalCommas; - internal readonly SyntaxList _body; + internal readonly StatementSyntaxNode _body; internal readonly SyntaxToken _endKeyword; - internal WhileStatementSyntaxNode(SyntaxToken whileKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body, SyntaxToken endKeyword): base(TokenKind.WhileStatement) + internal WhileStatementSyntaxNode(SyntaxToken whileKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxToken endKeyword): base(TokenKind.WhileStatement) { Slots = 5; this.AdjustWidth(whileKeyword); @@ -336,7 +374,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal WhileStatementSyntaxNode(SyntaxToken whileKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.WhileStatement, diagnostics) + internal WhileStatementSyntaxNode(SyntaxToken whileKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.WhileStatement, diagnostics) { Slots = 5; this.AdjustWidth(whileKeyword); @@ -377,8 +415,8 @@ namespace Parser.Internal internal readonly SyntaxToken _elseifKeyword; internal readonly ExpressionSyntaxNode _condition; internal readonly SyntaxList _optionalCommas; - internal readonly SyntaxList _body; - internal ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body): base(TokenKind.ElseifClause) + internal readonly StatementSyntaxNode _body; + internal ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body): base(TokenKind.ElseifClause) { Slots = 4; this.AdjustWidth(elseifKeyword); @@ -391,7 +429,7 @@ namespace Parser.Internal _body = body; } - internal ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body, TokenDiagnostic[] diagnostics): base(TokenKind.ElseifClause, diagnostics) + internal ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body, TokenDiagnostic[] diagnostics): base(TokenKind.ElseifClause, diagnostics) { Slots = 4; this.AdjustWidth(elseifKeyword); @@ -428,8 +466,8 @@ namespace Parser.Internal internal class ElseClause : SyntaxNode { internal readonly SyntaxToken _elseKeyword; - internal readonly SyntaxList _body; - internal ElseClause(SyntaxToken elseKeyword, SyntaxList body): base(TokenKind.ElseClause) + internal readonly StatementSyntaxNode _body; + internal ElseClause(SyntaxToken elseKeyword, StatementSyntaxNode body): base(TokenKind.ElseClause) { Slots = 2; this.AdjustWidth(elseKeyword); @@ -438,7 +476,7 @@ namespace Parser.Internal _body = body; } - internal ElseClause(SyntaxToken elseKeyword, SyntaxList body, TokenDiagnostic[] diagnostics): base(TokenKind.ElseClause, diagnostics) + internal ElseClause(SyntaxToken elseKeyword, StatementSyntaxNode body, TokenDiagnostic[] diagnostics): base(TokenKind.ElseClause, diagnostics) { Slots = 2; this.AdjustWidth(elseKeyword); @@ -473,11 +511,11 @@ namespace Parser.Internal internal readonly SyntaxToken _ifKeyword; internal readonly ExpressionSyntaxNode _condition; internal readonly SyntaxList _optionalCommas; - internal readonly SyntaxList _body; + internal readonly StatementSyntaxNode _body; internal readonly SyntaxList _elseifClauses; internal readonly ElseClause? _elseClause; internal readonly SyntaxToken _endKeyword; - internal IfStatementSyntaxNode(SyntaxToken ifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body, SyntaxList elseifClauses, ElseClause? elseClause, SyntaxToken endKeyword): base(TokenKind.IfStatement) + internal IfStatementSyntaxNode(SyntaxToken ifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxList elseifClauses, ElseClause? elseClause, SyntaxToken endKeyword): base(TokenKind.IfStatement) { Slots = 7; this.AdjustWidth(ifKeyword); @@ -496,7 +534,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal IfStatementSyntaxNode(SyntaxToken ifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, SyntaxList body, SyntaxList elseifClauses, ElseClause? elseClause, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.IfStatement, diagnostics) + internal IfStatementSyntaxNode(SyntaxToken ifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxList elseifClauses, ElseClause? elseClause, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.IfStatement, diagnostics) { Slots = 7; this.AdjustWidth(ifKeyword); @@ -541,9 +579,9 @@ namespace Parser.Internal internal readonly SyntaxToken _forKeyword; internal readonly AssignmentExpressionSyntaxNode _assignment; internal readonly SyntaxList _optionalCommas; - internal readonly SyntaxList _body; + internal readonly StatementSyntaxNode _body; internal readonly SyntaxToken _endKeyword; - internal ForStatementSyntaxNode(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, SyntaxList body, SyntaxToken endKeyword): base(TokenKind.ForStatement) + internal ForStatementSyntaxNode(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxToken endKeyword): base(TokenKind.ForStatement) { Slots = 5; this.AdjustWidth(forKeyword); @@ -558,7 +596,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal ForStatementSyntaxNode(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, SyntaxList body, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ForStatement, diagnostics) + internal ForStatementSyntaxNode(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ForStatement, diagnostics) { Slots = 5; this.AdjustWidth(forKeyword); @@ -688,10 +726,10 @@ namespace Parser.Internal internal class TryCatchStatementSyntaxNode : StatementSyntaxNode { internal readonly SyntaxToken _tryKeyword; - internal readonly SyntaxList _tryBody; + internal readonly StatementSyntaxNode _tryBody; internal readonly CatchClauseSyntaxNode? _catchClause; internal readonly SyntaxToken _endKeyword; - internal TryCatchStatementSyntaxNode(SyntaxToken tryKeyword, SyntaxList tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword): base(TokenKind.TryCatchStatement) + internal TryCatchStatementSyntaxNode(SyntaxToken tryKeyword, StatementSyntaxNode tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword): base(TokenKind.TryCatchStatement) { Slots = 4; this.AdjustWidth(tryKeyword); @@ -704,7 +742,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal TryCatchStatementSyntaxNode(SyntaxToken tryKeyword, SyntaxList tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.TryCatchStatement, diagnostics) + internal TryCatchStatementSyntaxNode(SyntaxToken tryKeyword, StatementSyntaxNode tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.TryCatchStatement, diagnostics) { Slots = 4; this.AdjustWidth(tryKeyword); @@ -890,17 +928,17 @@ namespace Parser.Internal } } - internal class CompoundNameSyntaxNode : ExpressionSyntaxNode + internal class CompoundNameExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxList _nodes; - internal CompoundNameSyntaxNode(SyntaxList nodes): base(TokenKind.CompoundName) + internal CompoundNameExpressionSyntaxNode(SyntaxList nodes): base(TokenKind.CompoundNameExpression) { Slots = 1; this.AdjustWidth(nodes); _nodes = nodes; } - internal CompoundNameSyntaxNode(SyntaxList nodes, TokenDiagnostic[] diagnostics): base(TokenKind.CompoundName, diagnostics) + internal CompoundNameExpressionSyntaxNode(SyntaxList nodes, TokenDiagnostic[] diagnostics): base(TokenKind.CompoundNameExpression, diagnostics) { Slots = 1; this.AdjustWidth(nodes); @@ -909,12 +947,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.CompoundNameSyntaxNode(parent, this, position); + return new Parser.CompoundNameExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new CompoundNameSyntaxNode(_nodes, diagnostics); + return new CompoundNameExpressionSyntaxNode(_nodes, diagnostics); } public override GreenNode? GetSlot(int i) @@ -928,11 +966,11 @@ namespace Parser.Internal } } - internal class NamedFunctionHandleSyntaxNode : FunctionHandleSyntaxNode + internal class NamedFunctionHandleExpressionSyntaxNode : FunctionHandleExpressionSyntaxNode { internal readonly SyntaxToken _atSign; - internal readonly CompoundNameSyntaxNode _functionName; - internal NamedFunctionHandleSyntaxNode(SyntaxToken atSign, CompoundNameSyntaxNode functionName): base(TokenKind.NamedFunctionHandle) + internal readonly CompoundNameExpressionSyntaxNode _functionName; + internal NamedFunctionHandleExpressionSyntaxNode(SyntaxToken atSign, CompoundNameExpressionSyntaxNode functionName): base(TokenKind.NamedFunctionHandleExpression) { Slots = 2; this.AdjustWidth(atSign); @@ -941,7 +979,7 @@ namespace Parser.Internal _functionName = functionName; } - internal NamedFunctionHandleSyntaxNode(SyntaxToken atSign, CompoundNameSyntaxNode functionName, TokenDiagnostic[] diagnostics): base(TokenKind.NamedFunctionHandle, diagnostics) + internal NamedFunctionHandleExpressionSyntaxNode(SyntaxToken atSign, CompoundNameExpressionSyntaxNode functionName, TokenDiagnostic[] diagnostics): base(TokenKind.NamedFunctionHandleExpression, diagnostics) { Slots = 2; this.AdjustWidth(atSign); @@ -952,12 +990,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.NamedFunctionHandleSyntaxNode(parent, this, position); + return new Parser.NamedFunctionHandleExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new NamedFunctionHandleSyntaxNode(_atSign, _functionName, diagnostics); + return new NamedFunctionHandleExpressionSyntaxNode(_atSign, _functionName, diagnostics); } public override GreenNode? GetSlot(int i) @@ -971,12 +1009,12 @@ namespace Parser.Internal } } - internal class LambdaSyntaxNode : FunctionHandleSyntaxNode + internal class LambdaExpressionSyntaxNode : FunctionHandleExpressionSyntaxNode { internal readonly SyntaxToken _atSign; internal readonly FunctionInputDescriptionSyntaxNode _input; internal readonly ExpressionSyntaxNode _body; - internal LambdaSyntaxNode(SyntaxToken atSign, FunctionInputDescriptionSyntaxNode input, ExpressionSyntaxNode body): base(TokenKind.Lambda) + internal LambdaExpressionSyntaxNode(SyntaxToken atSign, FunctionInputDescriptionSyntaxNode input, ExpressionSyntaxNode body): base(TokenKind.LambdaExpression) { Slots = 3; this.AdjustWidth(atSign); @@ -987,7 +1025,7 @@ namespace Parser.Internal _body = body; } - internal LambdaSyntaxNode(SyntaxToken atSign, FunctionInputDescriptionSyntaxNode input, ExpressionSyntaxNode body, TokenDiagnostic[] diagnostics): base(TokenKind.Lambda, diagnostics) + internal LambdaExpressionSyntaxNode(SyntaxToken atSign, FunctionInputDescriptionSyntaxNode input, ExpressionSyntaxNode body, TokenDiagnostic[] diagnostics): base(TokenKind.LambdaExpression, diagnostics) { Slots = 3; this.AdjustWidth(atSign); @@ -1000,12 +1038,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.LambdaSyntaxNode(parent, this, position); + return new Parser.LambdaExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new LambdaSyntaxNode(_atSign, _input, _body, diagnostics); + return new LambdaExpressionSyntaxNode(_atSign, _input, _body, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1024,7 +1062,7 @@ namespace Parser.Internal internal readonly ExpressionSyntaxNode _lhs; internal readonly SyntaxToken _operation; internal readonly ExpressionSyntaxNode _rhs; - internal BinaryOperationExpressionSyntaxNode(ExpressionSyntaxNode lhs, SyntaxToken operation, ExpressionSyntaxNode rhs): base(TokenKind.BinaryOperation) + internal BinaryOperationExpressionSyntaxNode(ExpressionSyntaxNode lhs, SyntaxToken operation, ExpressionSyntaxNode rhs): base(TokenKind.BinaryOperationExpression) { Slots = 3; this.AdjustWidth(lhs); @@ -1035,7 +1073,7 @@ namespace Parser.Internal _rhs = rhs; } - internal BinaryOperationExpressionSyntaxNode(ExpressionSyntaxNode lhs, SyntaxToken operation, ExpressionSyntaxNode rhs, TokenDiagnostic[] diagnostics): base(TokenKind.BinaryOperation, diagnostics) + internal BinaryOperationExpressionSyntaxNode(ExpressionSyntaxNode lhs, SyntaxToken operation, ExpressionSyntaxNode rhs, TokenDiagnostic[] diagnostics): base(TokenKind.BinaryOperationExpression, diagnostics) { Slots = 3; this.AdjustWidth(lhs); @@ -1067,17 +1105,17 @@ namespace Parser.Internal } } - internal class IdentifierNameSyntaxNode : ExpressionSyntaxNode + internal class IdentifierNameExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxToken _name; - internal IdentifierNameSyntaxNode(SyntaxToken name): base(TokenKind.IdentifierName) + internal IdentifierNameExpressionSyntaxNode(SyntaxToken name): base(TokenKind.IdentifierNameExpression) { Slots = 1; this.AdjustWidth(name); _name = name; } - internal IdentifierNameSyntaxNode(SyntaxToken name, TokenDiagnostic[] diagnostics): base(TokenKind.IdentifierName, diagnostics) + internal IdentifierNameExpressionSyntaxNode(SyntaxToken name, TokenDiagnostic[] diagnostics): base(TokenKind.IdentifierNameExpression, diagnostics) { Slots = 1; this.AdjustWidth(name); @@ -1086,12 +1124,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.IdentifierNameSyntaxNode(parent, this, position); + return new Parser.IdentifierNameExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new IdentifierNameSyntaxNode(_name, diagnostics); + return new IdentifierNameExpressionSyntaxNode(_name, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1105,17 +1143,17 @@ namespace Parser.Internal } } - internal class NumberLiteralSyntaxNode : ExpressionSyntaxNode + internal class NumberLiteralExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxToken _number; - internal NumberLiteralSyntaxNode(SyntaxToken number): base(TokenKind.NumberLiteralExpression) + internal NumberLiteralExpressionSyntaxNode(SyntaxToken number): base(TokenKind.NumberLiteralExpression) { Slots = 1; this.AdjustWidth(number); _number = number; } - internal NumberLiteralSyntaxNode(SyntaxToken number, TokenDiagnostic[] diagnostics): base(TokenKind.NumberLiteralExpression, diagnostics) + internal NumberLiteralExpressionSyntaxNode(SyntaxToken number, TokenDiagnostic[] diagnostics): base(TokenKind.NumberLiteralExpression, diagnostics) { Slots = 1; this.AdjustWidth(number); @@ -1124,12 +1162,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.NumberLiteralSyntaxNode(parent, this, position); + return new Parser.NumberLiteralExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new NumberLiteralSyntaxNode(_number, diagnostics); + return new NumberLiteralExpressionSyntaxNode(_number, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1143,17 +1181,17 @@ namespace Parser.Internal } } - internal class StringLiteralSyntaxNode : ExpressionSyntaxNode + internal class StringLiteralExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxToken _stringToken; - internal StringLiteralSyntaxNode(SyntaxToken stringToken): base(TokenKind.StringLiteralExpression) + internal StringLiteralExpressionSyntaxNode(SyntaxToken stringToken): base(TokenKind.StringLiteralExpression) { Slots = 1; this.AdjustWidth(stringToken); _stringToken = stringToken; } - internal StringLiteralSyntaxNode(SyntaxToken stringToken, TokenDiagnostic[] diagnostics): base(TokenKind.StringLiteralExpression, diagnostics) + internal StringLiteralExpressionSyntaxNode(SyntaxToken stringToken, TokenDiagnostic[] diagnostics): base(TokenKind.StringLiteralExpression, diagnostics) { Slots = 1; this.AdjustWidth(stringToken); @@ -1162,12 +1200,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.StringLiteralSyntaxNode(parent, this, position); + return new Parser.StringLiteralExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new StringLiteralSyntaxNode(_stringToken, diagnostics); + return new StringLiteralExpressionSyntaxNode(_stringToken, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1181,17 +1219,17 @@ namespace Parser.Internal } } - internal class DoubleQuotedStringLiteralSyntaxNode : ExpressionSyntaxNode + internal class DoubleQuotedStringLiteralExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxToken _stringToken; - internal DoubleQuotedStringLiteralSyntaxNode(SyntaxToken stringToken): base(TokenKind.DoubleQuotedStringLiteralExpression) + internal DoubleQuotedStringLiteralExpressionSyntaxNode(SyntaxToken stringToken): base(TokenKind.DoubleQuotedStringLiteralExpression) { Slots = 1; this.AdjustWidth(stringToken); _stringToken = stringToken; } - internal DoubleQuotedStringLiteralSyntaxNode(SyntaxToken stringToken, TokenDiagnostic[] diagnostics): base(TokenKind.DoubleQuotedStringLiteralExpression, diagnostics) + internal DoubleQuotedStringLiteralExpressionSyntaxNode(SyntaxToken stringToken, TokenDiagnostic[] diagnostics): base(TokenKind.DoubleQuotedStringLiteralExpression, diagnostics) { Slots = 1; this.AdjustWidth(stringToken); @@ -1200,12 +1238,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.DoubleQuotedStringLiteralSyntaxNode(parent, this, position); + return new Parser.DoubleQuotedStringLiteralExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new DoubleQuotedStringLiteralSyntaxNode(_stringToken, diagnostics); + return new DoubleQuotedStringLiteralExpressionSyntaxNode(_stringToken, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1219,17 +1257,17 @@ namespace Parser.Internal } } - internal class UnquotedStringLiteralSyntaxNode : ExpressionSyntaxNode + internal class UnquotedStringLiteralExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxToken _stringToken; - internal UnquotedStringLiteralSyntaxNode(SyntaxToken stringToken): base(TokenKind.UnquotedStringLiteralExpression) + internal UnquotedStringLiteralExpressionSyntaxNode(SyntaxToken stringToken): base(TokenKind.UnquotedStringLiteralExpression) { Slots = 1; this.AdjustWidth(stringToken); _stringToken = stringToken; } - internal UnquotedStringLiteralSyntaxNode(SyntaxToken stringToken, TokenDiagnostic[] diagnostics): base(TokenKind.UnquotedStringLiteralExpression, diagnostics) + internal UnquotedStringLiteralExpressionSyntaxNode(SyntaxToken stringToken, TokenDiagnostic[] diagnostics): base(TokenKind.UnquotedStringLiteralExpression, diagnostics) { Slots = 1; this.AdjustWidth(stringToken); @@ -1238,12 +1276,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.UnquotedStringLiteralSyntaxNode(parent, this, position); + return new Parser.UnquotedStringLiteralExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new UnquotedStringLiteralSyntaxNode(_stringToken, diagnostics); + return new UnquotedStringLiteralExpressionSyntaxNode(_stringToken, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1407,7 +1445,7 @@ namespace Parser.Internal internal readonly SyntaxToken _openingBrace; internal readonly SyntaxList _nodes; internal readonly SyntaxToken _closingBrace; - internal CellArrayElementAccessExpressionSyntaxNode(ExpressionSyntaxNode expression, SyntaxToken openingBrace, SyntaxList nodes, SyntaxToken closingBrace): base(TokenKind.CellArrayElementAccess) + internal CellArrayElementAccessExpressionSyntaxNode(ExpressionSyntaxNode expression, SyntaxToken openingBrace, SyntaxList nodes, SyntaxToken closingBrace): base(TokenKind.CellArrayElementAccessExpression) { Slots = 4; this.AdjustWidth(expression); @@ -1420,7 +1458,7 @@ namespace Parser.Internal _closingBrace = closingBrace; } - internal CellArrayElementAccessExpressionSyntaxNode(ExpressionSyntaxNode expression, SyntaxToken openingBrace, SyntaxList nodes, SyntaxToken closingBrace, TokenDiagnostic[] diagnostics): base(TokenKind.CellArrayElementAccess, diagnostics) + internal CellArrayElementAccessExpressionSyntaxNode(ExpressionSyntaxNode expression, SyntaxToken openingBrace, SyntaxList nodes, SyntaxToken closingBrace, TokenDiagnostic[] diagnostics): base(TokenKind.CellArrayElementAccessExpression, diagnostics) { Slots = 4; this.AdjustWidth(expression); @@ -1460,7 +1498,7 @@ namespace Parser.Internal internal readonly SyntaxToken _openingBracket; internal readonly SyntaxList _nodes; internal readonly SyntaxToken _closingBracket; - internal FunctionCallExpressionSyntaxNode(ExpressionSyntaxNode functionName, SyntaxToken openingBracket, SyntaxList nodes, SyntaxToken closingBracket): base(TokenKind.FunctionCall) + internal FunctionCallExpressionSyntaxNode(ExpressionSyntaxNode functionName, SyntaxToken openingBracket, SyntaxList nodes, SyntaxToken closingBracket): base(TokenKind.FunctionCallExpression) { Slots = 4; this.AdjustWidth(functionName); @@ -1473,7 +1511,7 @@ namespace Parser.Internal _closingBracket = closingBracket; } - internal FunctionCallExpressionSyntaxNode(ExpressionSyntaxNode functionName, SyntaxToken openingBracket, SyntaxList nodes, SyntaxToken closingBracket, TokenDiagnostic[] diagnostics): base(TokenKind.FunctionCall, diagnostics) + internal FunctionCallExpressionSyntaxNode(ExpressionSyntaxNode functionName, SyntaxToken openingBracket, SyntaxList nodes, SyntaxToken closingBracket, TokenDiagnostic[] diagnostics): base(TokenKind.FunctionCallExpression, diagnostics) { Slots = 4; this.AdjustWidth(functionName); @@ -1507,12 +1545,12 @@ namespace Parser.Internal } } - internal class MemberAccessSyntaxNode : ExpressionSyntaxNode + internal class MemberAccessExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxNode _leftOperand; internal readonly SyntaxToken _dot; internal readonly SyntaxNode _rightOperand; - internal MemberAccessSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand): base(TokenKind.MemberAccess) + internal MemberAccessExpressionSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand): base(TokenKind.MemberAccessExpression) { Slots = 3; this.AdjustWidth(leftOperand); @@ -1523,7 +1561,7 @@ namespace Parser.Internal _rightOperand = rightOperand; } - internal MemberAccessSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand, TokenDiagnostic[] diagnostics): base(TokenKind.MemberAccess, diagnostics) + internal MemberAccessExpressionSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand, TokenDiagnostic[] diagnostics): base(TokenKind.MemberAccessExpression, diagnostics) { Slots = 3; this.AdjustWidth(leftOperand); @@ -1536,12 +1574,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.MemberAccessSyntaxNode(parent, this, position); + return new Parser.MemberAccessExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new MemberAccessSyntaxNode(_leftOperand, _dot, _rightOperand, diagnostics); + return new MemberAccessExpressionSyntaxNode(_leftOperand, _dot, _rightOperand, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1555,11 +1593,11 @@ namespace Parser.Internal } } - internal class UnaryPostixOperationExpressionSyntaxNode : ExpressionSyntaxNode + internal class UnaryPostfixOperationExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly ExpressionSyntaxNode _operand; internal readonly SyntaxToken _operation; - internal UnaryPostixOperationExpressionSyntaxNode(ExpressionSyntaxNode operand, SyntaxToken operation): base(TokenKind.UnaryPostfixOperationExpression) + internal UnaryPostfixOperationExpressionSyntaxNode(ExpressionSyntaxNode operand, SyntaxToken operation): base(TokenKind.UnaryPostfixOperationExpression) { Slots = 2; this.AdjustWidth(operand); @@ -1568,7 +1606,7 @@ namespace Parser.Internal _operation = operation; } - internal UnaryPostixOperationExpressionSyntaxNode(ExpressionSyntaxNode operand, SyntaxToken operation, TokenDiagnostic[] diagnostics): base(TokenKind.UnaryPostfixOperationExpression, diagnostics) + internal UnaryPostfixOperationExpressionSyntaxNode(ExpressionSyntaxNode operand, SyntaxToken operation, TokenDiagnostic[] diagnostics): base(TokenKind.UnaryPostfixOperationExpression, diagnostics) { Slots = 2; this.AdjustWidth(operand); @@ -1579,12 +1617,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.UnaryPostixOperationExpressionSyntaxNode(parent, this, position); + return new Parser.UnaryPostfixOperationExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new UnaryPostixOperationExpressionSyntaxNode(_operand, _operation, diagnostics); + return new UnaryPostfixOperationExpressionSyntaxNode(_operand, _operation, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1598,12 +1636,12 @@ namespace Parser.Internal } } - internal class IndirectMemberAccessSyntaxNode : ExpressionSyntaxNode + internal class IndirectMemberAccessExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxToken _openingBracket; internal readonly ExpressionSyntaxNode _expression; internal readonly SyntaxToken _closingBracket; - internal IndirectMemberAccessSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket): base(TokenKind.IndirectMemberAccess) + internal IndirectMemberAccessExpressionSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket): base(TokenKind.IndirectMemberAccessExpression) { Slots = 3; this.AdjustWidth(openingBracket); @@ -1614,7 +1652,7 @@ namespace Parser.Internal _closingBracket = closingBracket; } - internal IndirectMemberAccessSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket, TokenDiagnostic[] diagnostics): base(TokenKind.IndirectMemberAccess, diagnostics) + internal IndirectMemberAccessExpressionSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket, TokenDiagnostic[] diagnostics): base(TokenKind.IndirectMemberAccessExpression, diagnostics) { Slots = 3; this.AdjustWidth(openingBracket); @@ -1627,12 +1665,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.IndirectMemberAccessSyntaxNode(parent, this, position); + return new Parser.IndirectMemberAccessExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new IndirectMemberAccessSyntaxNode(_openingBracket, _expression, _closingBracket, diagnostics); + return new IndirectMemberAccessExpressionSyntaxNode(_openingBracket, _expression, _closingBracket, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1648,9 +1686,9 @@ namespace Parser.Internal internal class CommandExpressionSyntaxNode : ExpressionSyntaxNode { - internal readonly IdentifierNameSyntaxNode _commandName; - internal readonly SyntaxList _arguments; - internal CommandExpressionSyntaxNode(IdentifierNameSyntaxNode commandName, SyntaxList arguments): base(TokenKind.Command) + internal readonly SyntaxToken _commandName; + internal readonly SyntaxList _arguments; + internal CommandExpressionSyntaxNode(SyntaxToken commandName, SyntaxList arguments): base(TokenKind.CommandExpression) { Slots = 2; this.AdjustWidth(commandName); @@ -1659,7 +1697,7 @@ namespace Parser.Internal _arguments = arguments; } - internal CommandExpressionSyntaxNode(IdentifierNameSyntaxNode commandName, SyntaxList arguments, TokenDiagnostic[] diagnostics): base(TokenKind.Command, diagnostics) + internal CommandExpressionSyntaxNode(SyntaxToken commandName, SyntaxList arguments, TokenDiagnostic[] diagnostics): base(TokenKind.CommandExpression, diagnostics) { Slots = 2; this.AdjustWidth(commandName); @@ -1689,12 +1727,12 @@ namespace Parser.Internal } } - internal class BaseClassInvokationSyntaxNode : ExpressionSyntaxNode + internal class ClassInvokationExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly ExpressionSyntaxNode _methodName; internal readonly SyntaxToken _atSign; internal readonly ExpressionSyntaxNode _baseClassNameAndArguments; - internal BaseClassInvokationSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments): base(TokenKind.ClassInvokation) + internal ClassInvokationExpressionSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments): base(TokenKind.ClassInvokationExpression) { Slots = 3; this.AdjustWidth(methodName); @@ -1705,7 +1743,7 @@ namespace Parser.Internal _baseClassNameAndArguments = baseClassNameAndArguments; } - internal BaseClassInvokationSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments, TokenDiagnostic[] diagnostics): base(TokenKind.ClassInvokation, diagnostics) + internal ClassInvokationExpressionSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments, TokenDiagnostic[] diagnostics): base(TokenKind.ClassInvokationExpression, diagnostics) { Slots = 3; this.AdjustWidth(methodName); @@ -1718,12 +1756,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.BaseClassInvokationSyntaxNode(parent, this, position); + return new Parser.ClassInvokationExpressionSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new BaseClassInvokationSyntaxNode(_methodName, _atSign, _baseClassNameAndArguments, diagnostics); + return new ClassInvokationExpressionSyntaxNode(_methodName, _atSign, _baseClassNameAndArguments, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1782,9 +1820,9 @@ namespace Parser.Internal internal class AttributeSyntaxNode : SyntaxNode { - internal readonly IdentifierNameSyntaxNode _name; + internal readonly SyntaxToken _name; internal readonly AttributeAssignmentSyntaxNode? _assignment; - internal AttributeSyntaxNode(IdentifierNameSyntaxNode name, AttributeAssignmentSyntaxNode? assignment): base(TokenKind.Attribute) + internal AttributeSyntaxNode(SyntaxToken name, AttributeAssignmentSyntaxNode? assignment): base(TokenKind.Attribute) { Slots = 2; this.AdjustWidth(name); @@ -1793,7 +1831,7 @@ namespace Parser.Internal _assignment = assignment; } - internal AttributeSyntaxNode(IdentifierNameSyntaxNode name, AttributeAssignmentSyntaxNode? assignment, TokenDiagnostic[] diagnostics): base(TokenKind.Attribute, diagnostics) + internal AttributeSyntaxNode(SyntaxToken name, AttributeAssignmentSyntaxNode? assignment, TokenDiagnostic[] diagnostics): base(TokenKind.Attribute, diagnostics) { Slots = 2; this.AdjustWidth(name); @@ -1871,16 +1909,16 @@ namespace Parser.Internal } } - internal class MethodDefinitionSyntaxNode : MethodDeclarationSyntaxNode + internal class ConcreteMethodDeclarationSyntaxNode : MethodDeclarationSyntaxNode { internal readonly SyntaxToken _functionKeyword; internal readonly FunctionOutputDescriptionSyntaxNode? _outputDescription; - internal readonly CompoundNameSyntaxNode _name; + internal readonly CompoundNameExpressionSyntaxNode _name; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription; internal readonly SyntaxList _commas; - internal readonly SyntaxList _body; + internal readonly StatementSyntaxNode _body; internal readonly EndKeywordSyntaxNode? _endKeyword; - internal MethodDefinitionSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.MethodDefinition) + internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, StatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.ConcreteMethodDeclaration) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -1899,7 +1937,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal MethodDefinitionSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.MethodDefinition, diagnostics) + internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, StatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ConcreteMethodDeclaration, diagnostics) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -1920,12 +1958,12 @@ namespace Parser.Internal internal override Parser.SyntaxNode CreateRed(Parser.SyntaxNode parent, int position) { - return new Parser.MethodDefinitionSyntaxNode(parent, this, position); + return new Parser.ConcreteMethodDeclarationSyntaxNode(parent, this, position); } public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new MethodDefinitionSyntaxNode(_functionKeyword, _outputDescription, _name, _inputDescription, _commas, _body, _endKeyword, diagnostics); + return new ConcreteMethodDeclarationSyntaxNode(_functionKeyword, _outputDescription, _name, _inputDescription, _commas, _body, _endKeyword, diagnostics); } public override GreenNode? GetSlot(int i) @@ -1942,9 +1980,9 @@ namespace Parser.Internal internal class AbstractMethodDeclarationSyntaxNode : MethodDeclarationSyntaxNode { internal readonly FunctionOutputDescriptionSyntaxNode? _outputDescription; - internal readonly CompoundNameSyntaxNode _name; + internal readonly CompoundNameExpressionSyntaxNode _name; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription; - internal AbstractMethodDeclarationSyntaxNode(FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription): base(TokenKind.AbstractMethodDeclaration) + internal AbstractMethodDeclarationSyntaxNode(FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription): base(TokenKind.AbstractMethodDeclaration) { Slots = 3; this.AdjustWidth(outputDescription); @@ -1955,7 +1993,7 @@ namespace Parser.Internal _inputDescription = inputDescription; } - internal AbstractMethodDeclarationSyntaxNode(FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, TokenDiagnostic[] diagnostics): base(TokenKind.AbstractMethodDeclaration, diagnostics) + internal AbstractMethodDeclarationSyntaxNode(FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, TokenDiagnostic[] diagnostics): base(TokenKind.AbstractMethodDeclaration, diagnostics) { Slots = 3; this.AdjustWidth(outputDescription); @@ -2140,11 +2178,11 @@ namespace Parser.Internal { internal readonly SyntaxToken _classdefKeyword; internal readonly AttributeListSyntaxNode? _attributes; - internal readonly IdentifierNameSyntaxNode _className; + internal readonly SyntaxToken _className; internal readonly BaseClassListSyntaxNode? _baseClassList; internal readonly SyntaxList _nodes; internal readonly SyntaxToken _endKeyword; - internal ClassDeclarationSyntaxNode(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, IdentifierNameSyntaxNode className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword): base(TokenKind.ClassDeclaration) + internal ClassDeclarationSyntaxNode(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, SyntaxToken className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword): base(TokenKind.ClassDeclaration) { Slots = 6; this.AdjustWidth(classdefKeyword); @@ -2161,7 +2199,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal ClassDeclarationSyntaxNode(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, IdentifierNameSyntaxNode className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ClassDeclaration, diagnostics) + internal ClassDeclarationSyntaxNode(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, SyntaxToken className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ClassDeclaration, diagnostics) { Slots = 6; this.AdjustWidth(classdefKeyword); @@ -2249,10 +2287,10 @@ namespace Parser.Internal internal class EnumerationItemSyntaxNode : SyntaxNode { - internal readonly IdentifierNameSyntaxNode _name; + internal readonly SyntaxToken _name; internal readonly EnumerationItemValueSyntaxNode? _values; internal readonly SyntaxList _commas; - internal EnumerationItemSyntaxNode(IdentifierNameSyntaxNode name, EnumerationItemValueSyntaxNode? values, SyntaxList commas): base(TokenKind.EnumerationItem) + internal EnumerationItemSyntaxNode(SyntaxToken name, EnumerationItemValueSyntaxNode? values, SyntaxList commas): base(TokenKind.EnumerationItem) { Slots = 3; this.AdjustWidth(name); @@ -2263,7 +2301,7 @@ namespace Parser.Internal _commas = commas; } - internal EnumerationItemSyntaxNode(IdentifierNameSyntaxNode name, EnumerationItemValueSyntaxNode? values, SyntaxList commas, TokenDiagnostic[] diagnostics): base(TokenKind.EnumerationItem, diagnostics) + internal EnumerationItemSyntaxNode(SyntaxToken name, EnumerationItemValueSyntaxNode? values, SyntaxList commas, TokenDiagnostic[] diagnostics): base(TokenKind.EnumerationItem, diagnostics) { Slots = 3; this.AdjustWidth(name); diff --git a/Parser/Internal/SyntaxNode.cs b/Parser/Internal/SyntaxNode.cs index 5970df3..2b0a450 100644 --- a/Parser/Internal/SyntaxNode.cs +++ b/Parser/Internal/SyntaxNode.cs @@ -79,13 +79,13 @@ namespace Parser.Internal } } - internal abstract class FunctionHandleSyntaxNode : ExpressionSyntaxNode + internal abstract class FunctionHandleExpressionSyntaxNode : ExpressionSyntaxNode { - protected FunctionHandleSyntaxNode(TokenKind kind) : base(kind) + protected FunctionHandleExpressionSyntaxNode(TokenKind kind) : base(kind) { } - protected FunctionHandleSyntaxNode(TokenKind kind, TokenDiagnostic[] diagnostics) : base(kind, diagnostics) + protected FunctionHandleExpressionSyntaxNode(TokenKind kind, TokenDiagnostic[] diagnostics) : base(kind, diagnostics) { } } diff --git a/Parser/Internal/SyntaxToken.cs b/Parser/Internal/SyntaxToken.cs index 4c5ff63..22ff7ac 100644 --- a/Parser/Internal/SyntaxToken.cs +++ b/Parser/Internal/SyntaxToken.cs @@ -116,6 +116,7 @@ namespace Parser.Internal _fullWidth = text?.Length ?? 0; } + public override void WriteTokenTo(TextWriter writer, bool leading, bool trailing) { writer.Write(_text); @@ -126,7 +127,9 @@ namespace Parser.Internal return new SyntaxTokenWithValue(Kind, _text, _value, diagnostics); } - public T Value => _value; + public T TypedValue => _value; + + public override object? Value => TypedValue; } internal class SyntaxTokenWithValueAndTrivia : SyntaxTokenWithValue @@ -181,7 +184,7 @@ namespace Parser.Internal public override GreenNode SetDiagnostics(TokenDiagnostic[] diagnostics) { - return new SyntaxTokenWithValueAndTrivia(Kind, _text, Value, LeadingTrivia, TrailingTrivia, diagnostics); + return new SyntaxTokenWithValueAndTrivia(Kind, _text, TypedValue, LeadingTrivia, TrailingTrivia, diagnostics); } } @@ -311,6 +314,10 @@ namespace Parser.Internal internal static SyntaxToken NoneToken => new MissingTokenWithTrivia(TokenKind.None, s_EmptySyntaxTriviaList, s_EmptySyntaxTriviaList); + public virtual object? Value => null; + + public override object? GetValue() => Value; + public virtual int Width => Text.Length; public override IReadOnlyList LeadingTriviaCore => s_EmptySyntaxTriviaList; diff --git a/Parser/Lowering/Lowerer.cs b/Parser/Lowering/Lowerer.cs new file mode 100644 index 0000000..fbe3d05 --- /dev/null +++ b/Parser/Lowering/Lowerer.cs @@ -0,0 +1,116 @@ +using Parser.Binding; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using static Parser.Binding.BoundNodeFactory; + +namespace Parser.Lowering +{ + internal class Lowerer : BoundTreeRewriter + { + private int _labelNumber = 0; + + private Lowerer() + { + } + + private BoundLabel GenerateLabel() + { + var name = $"Label{++_labelNumber}"; + return new BoundLabel(name); + } + + public override BoundStatement RewriteIfStatement(BoundIfStatement node) + { + // if cond + // body + // elseif cond1 + // body1 + // elseif cond2 + // body2 + // else + // body3 + // + // gotoFalse cond Label1 + // body + // goto LabelEnd + // Label1: + // gotoFalse cond1 Label2 + // body1 + // goto LabelEnd + // Label2: + // gotoFalse cond2 Label3 + // body2 + // goto LabelEnd + // Label3: + // body3 + // LabelEnd: + + var builder = ImmutableArray.CreateBuilder(); + var numberOfLabelsNeeded = 1 + node.ElseifClauses.Length + (node.ElseClause is null ? 0 : 1); + var labels = new BoundLabel[numberOfLabelsNeeded]; + for (var i = 0; i < numberOfLabelsNeeded; i++) + { + labels[i] = GenerateLabel(); + } + + builder.Add(GotoIfFalse(node.Syntax, node.Condition, labels[0])); + builder.Add(node.Body); + if (numberOfLabelsNeeded >= 2) + { + var counter = 0; + foreach (var elseifClause in node.ElseifClauses) + { + builder.Add(Goto(node.Syntax, labels[^1])); + builder.Add(LabelStatement(node.Syntax, labels[counter])); + counter++; + builder.Add(GotoIfFalse(node.Syntax, elseifClause.Condition, labels[counter])); + builder.Add(elseifClause.Body); + } + if (node.ElseClause is { } elseClause) + { + builder.Add(Goto(node.Syntax, labels[^1])); + builder.Add(LabelStatement(node.Syntax, labels[counter])); + builder.Add(elseClause); + } + } + + builder.Add(LabelStatement(node.Syntax, labels[^1])); + return RewriteBlockStatement(Block(node.Syntax, builder.ToArray())); + } + + public static BoundBlockStatement Lower(BoundStatement statement) + { + var lowerer = new Lowerer(); + var result = lowerer.RewriteStatement(statement); + var flatResult = lowerer.Flatten(result); + return flatResult; + } + + private BoundBlockStatement Flatten(BoundStatement statement) + { + var builder = ImmutableArray.CreateBuilder(); + var stack = new Stack(); + + stack.Push(statement); + while (stack.Count() > 0) + { + var current = stack.Pop(); + if (current is BoundBlockStatement block) + { + foreach (var s in block.Statements.Reverse()) + { + stack.Push(s); + } + } + else + { + builder.Add(current); + } + } + + return Block(statement.Syntax, builder.ToImmutable()); + } + } +} diff --git a/Parser/MFunctions/MOperations.cs b/Parser/MFunctions/MOperations.cs new file mode 100644 index 0000000..f454b3f --- /dev/null +++ b/Parser/MFunctions/MOperations.cs @@ -0,0 +1,105 @@ +using Parser.Objects; + +namespace Parser.MFunctions +{ + public static class MOperations + { + public static MObject? Plus(MObject left, MObject right) + { + if (left is MDoubleNumber { Value: var lValue } + && right is MDoubleNumber { Value: var rValue }) + { + return MObject.CreateDoubleNumber(lValue + rValue); + } + + return null; + } + + public static MObject? Minus(MObject left, MObject right) + { + if (left is MDoubleNumber { Value: var lValue } + && right is MDoubleNumber { Value: var rValue }) + { + return MObject.CreateDoubleNumber(lValue - rValue); + } + + return null; + } + + public static MObject? Star(MObject left, MObject right) + { + if (left is MDoubleNumber { Value: var lValue } + && right is MDoubleNumber { Value: var rValue }) + { + return MObject.CreateDoubleNumber(lValue * rValue); + } + + return null; + } + + public static MObject? Slash(MObject left, MObject right) + { + if (left is MDoubleNumber { Value: var lValue } + && right is MDoubleNumber { Value: var rValue }) + { + return MObject.CreateDoubleNumber(lValue / rValue); + } + + return null; + } + + public static MObject? Greater(MObject left, MObject right) + { + if (left is MDoubleNumber { Value: var lValue } + && right is MDoubleNumber { Value: var rValue }) + { + return MObject.CreateLogical(lValue > rValue); + } + + return null; + } + + public static MObject? GreaterOrEquals(MObject left, MObject right) + { + if (left is MDoubleNumber { Value: var lValue } + && right is MDoubleNumber { Value: var rValue }) + { + return MObject.CreateLogical(lValue >= rValue); + } + + return null; + } + + public static MObject? Less(MObject left, MObject right) + { + if (left is MDoubleNumber { Value: var lValue } + && right is MDoubleNumber { Value: var rValue }) + { + return MObject.CreateLogical(lValue < rValue); + } + + return null; + } + + public static MObject? LessOrEquals(MObject left, MObject right) + { + if (left is MDoubleNumber { Value: var lValue } + && right is MDoubleNumber { Value: var rValue }) + { + return MObject.CreateLogical(lValue <= rValue); + } + + return null; + } + + public static MObject? Minus(MObject operand) + { + if (operand is MDoubleNumber { Value: var value }) + { + return MObject.CreateDoubleNumber(-value); + } + + return null; + } + } +} diff --git a/Parser/MParser.cs b/Parser/MParser.cs index e47a1a8..f2766b5 100644 --- a/Parser/MParser.cs +++ b/Parser/MParser.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using Parser.Internal; +using Parser.Internal; using System.Linq; namespace Parser @@ -27,18 +25,4 @@ namespace Parser return new SyntaxTree(root, totalDiagnostics); } } - - public class SyntaxTree - { - public SyntaxTree(RootSyntaxNode nullRoot, DiagnosticsBag diagnostics) - { - NullRoot = nullRoot ?? throw new ArgumentNullException(nameof(nullRoot)); - Diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); - } - - public RootSyntaxNode NullRoot { get; } - public FileSyntaxNode Root => NullRoot.File; - public DiagnosticsBag Diagnostics { get; } - } - } \ No newline at end of file diff --git a/Parser/Objects/MCharArray.cs b/Parser/Objects/MCharArray.cs new file mode 100644 index 0000000..188e242 --- /dev/null +++ b/Parser/Objects/MCharArray.cs @@ -0,0 +1,22 @@ +namespace Parser.Objects +{ + public class MCharArray : MObject + { + private MCharArray(char[] chars) + { + Chars = chars; + } + + public char[] Chars { get; } + + public static MCharArray Create(char[] chars) + { + return new MCharArray(chars); + } + + public override string ToString() + { + return new string(Chars); + } + } +} \ No newline at end of file diff --git a/Parser/Objects/MDoubleNumber.cs b/Parser/Objects/MDoubleNumber.cs new file mode 100644 index 0000000..bb7f76f --- /dev/null +++ b/Parser/Objects/MDoubleNumber.cs @@ -0,0 +1,24 @@ +using System.Globalization; + +namespace Parser.Objects +{ + public class MDoubleNumber : MObject + { + private MDoubleNumber(double value) + { + Value = value; + } + + public double Value { get; } + + public static MDoubleNumber Create(double value) + { + return new MDoubleNumber(value); + } + + public override string ToString() + { + return Value.ToString(CultureInfo.InvariantCulture); + } + } +} \ No newline at end of file diff --git a/Parser/Objects/MLogical.cs b/Parser/Objects/MLogical.cs new file mode 100644 index 0000000..693c210 --- /dev/null +++ b/Parser/Objects/MLogical.cs @@ -0,0 +1,24 @@ +using System.Globalization; + +namespace Parser.Objects +{ + public class MLogical : MObject + { + public MLogical(bool value) + { + Value = value; + } + + public bool Value { get; } + + public static MLogical Create(bool value) + { + return new MLogical(value); + } + + public override string ToString() + { + return Value.ToString(CultureInfo.InvariantCulture); + } + } +} \ No newline at end of file diff --git a/Parser/Objects/MObject.cs b/Parser/Objects/MObject.cs new file mode 100644 index 0000000..702e985 --- /dev/null +++ b/Parser/Objects/MObject.cs @@ -0,0 +1,20 @@ +namespace Parser.Objects +{ + public abstract class MObject + { + public static MDoubleNumber CreateDoubleNumber(double value) + { + return MDoubleNumber.Create(value); + } + + public static MCharArray CreateCharArray(char[] chars) + { + return MCharArray.Create(chars); + } + + public static MLogical CreateLogical(bool value) + { + return MLogical.Create(value); + } + } +} \ No newline at end of file diff --git a/Parser/Parser.csproj b/Parser/Parser.csproj index be517b0..acfb9dc 100644 --- a/Parser/Parser.csproj +++ b/Parser/Parser.csproj @@ -3,6 +3,7 @@ netcoreapp3.0 8.0 enable + preview diff --git a/SyntaxGenerator/input.xml b/Parser/SyntaxDefinition.xml similarity index 80% rename from SyntaxGenerator/input.xml rename to Parser/SyntaxDefinition.xml index 09dd3fe..fcbc09a 100644 --- a/SyntaxGenerator/input.xml +++ b/Parser/SyntaxDefinition.xml @@ -1,16 +1,19 @@ - + + + + - + @@ -33,30 +36,30 @@ - + - + - + - + - + @@ -65,7 +68,7 @@ - + @@ -79,7 +82,7 @@ - + @@ -95,36 +98,36 @@ - + - + - + - + - + - + - + - + - + - + @@ -142,37 +145,37 @@ - + - + - + - + - + - - - + + + - + @@ -182,7 +185,7 @@ - + @@ -190,18 +193,18 @@ - + - + - + - + @@ -223,7 +226,7 @@ - + @@ -234,7 +237,7 @@ - + diff --git a/Parser/SyntaxNode.Generated.cs b/Parser/SyntaxNode.Generated.cs index 105fac7..22a137a 100644 --- a/Parser/SyntaxNode.Generated.cs +++ b/Parser/SyntaxNode.Generated.cs @@ -3,7 +3,7 @@ namespace Parser { public class FileSyntaxNode : SyntaxNode { - private SyntaxNode? _statementList; + private SyntaxNode? _body; internal FileSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -16,12 +16,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList StatementList + public BlockStatementSyntaxNode Body { get { - var red = this.GetRed(ref this._statementList!, 0); - return red is null ? throw new System.Exception("statementList cannot be null.") : (SyntaxNodeOrTokenList)red; + var red = this.GetRed(ref this._body!, 0); + return red is null ? throw new System.Exception("body cannot be null.") : (BlockStatementSyntaxNode)red; } } @@ -29,7 +29,7 @@ namespace Parser { return i switch { - 0 => GetRed(ref _statementList!, 0), _ => null + 0 => GetRed(ref _body!, 0), _ => null } ; @@ -41,6 +41,38 @@ namespace Parser } } + public class BlockStatementSyntaxNode : StatementSyntaxNode + { + private SyntaxNode? _statements; + internal BlockStatementSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + { + } + + public SyntaxNodeOrTokenList Statements + { + get + { + var red = this.GetRed(ref this._statements!, 0); + return red is null ? throw new System.Exception("statements cannot be null.") : (SyntaxNodeOrTokenList)red; + } + } + + internal override SyntaxNode? GetNode(int i) + { + return i switch + { + 0 => GetRed(ref _statements!, 0), _ => null + } + + ; + } + + public override void Accept(SyntaxVisitor visitor) + { + visitor.VisitBlockStatement(this); + } + } + public class FunctionDeclarationSyntaxNode : StatementSyntaxNode { private SyntaxNode? _outputDescription; @@ -95,12 +127,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public StatementSyntaxNode Body { get { var red = this.GetRed(ref this._body!, 5); - return red is null ? throw new System.Exception("body cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -320,12 +352,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public StatementSyntaxNode Body { get { var red = this.GetRed(ref this._body!, 3); - return red is null ? throw new System.Exception("body cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -388,12 +420,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public StatementSyntaxNode Body { get { var red = this.GetRed(ref this._body!, 3); - return red is null ? throw new System.Exception("body cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -448,12 +480,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public StatementSyntaxNode Body { get { var red = this.GetRed(ref this._body!, 3); - return red is null ? throw new System.Exception("body cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -488,12 +520,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public StatementSyntaxNode Body { get { var red = this.GetRed(ref this._body!, 1); - return red is null ? throw new System.Exception("body cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -558,12 +590,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public StatementSyntaxNode Body { get { var red = this.GetRed(ref this._body!, 3); - return red is null ? throw new System.Exception("body cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -644,12 +676,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public StatementSyntaxNode Body { get { var red = this.GetRed(ref this._body!, 3); - return red is null ? throw new System.Exception("body cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -783,12 +815,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList TryBody + public StatementSyntaxNode TryBody { get { var red = this.GetRed(ref this._tryBody!, 1); - return red is null ? throw new System.Exception("tryBody cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("tryBody cannot be null.") : (StatementSyntaxNode)red; } } @@ -941,10 +973,10 @@ namespace Parser } } - public class CompoundNameSyntaxNode : ExpressionSyntaxNode + public class CompoundNameExpressionSyntaxNode : ExpressionSyntaxNode { private SyntaxNode? _nodes; - internal CompoundNameSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal CompoundNameExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -969,14 +1001,14 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitCompoundName(this); + visitor.VisitCompoundNameExpression(this); } } - public class NamedFunctionHandleSyntaxNode : FunctionHandleSyntaxNode + public class NamedFunctionHandleExpressionSyntaxNode : FunctionHandleExpressionSyntaxNode { private SyntaxNode? _functionName; - internal NamedFunctionHandleSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal NamedFunctionHandleExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -984,16 +1016,16 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.NamedFunctionHandleSyntaxNode)_green)._atSign, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.NamedFunctionHandleExpressionSyntaxNode)_green)._atSign, this.GetChildPosition(0)); } } - public CompoundNameSyntaxNode FunctionName + public CompoundNameExpressionSyntaxNode FunctionName { get { var red = this.GetRed(ref this._functionName!, 1); - return red is null ? throw new System.Exception("functionName cannot be null.") : (CompoundNameSyntaxNode)red; + return red is null ? throw new System.Exception("functionName cannot be null.") : (CompoundNameExpressionSyntaxNode)red; } } @@ -1009,15 +1041,15 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitNamedFunctionHandle(this); + visitor.VisitNamedFunctionHandleExpression(this); } } - public class LambdaSyntaxNode : FunctionHandleSyntaxNode + public class LambdaExpressionSyntaxNode : FunctionHandleExpressionSyntaxNode { private SyntaxNode? _input; private SyntaxNode? _body; - internal LambdaSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal LambdaExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1025,7 +1057,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.LambdaSyntaxNode)_green)._atSign, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.LambdaExpressionSyntaxNode)_green)._atSign, this.GetChildPosition(0)); } } @@ -1059,7 +1091,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitLambda(this); + visitor.VisitLambdaExpression(this); } } @@ -1113,9 +1145,9 @@ namespace Parser } } - public class IdentifierNameSyntaxNode : ExpressionSyntaxNode + public class IdentifierNameExpressionSyntaxNode : ExpressionSyntaxNode { - internal IdentifierNameSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal IdentifierNameExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1123,7 +1155,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.IdentifierNameSyntaxNode)_green)._name, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.IdentifierNameExpressionSyntaxNode)_green)._name, this.GetChildPosition(0)); } } @@ -1139,13 +1171,13 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitIdentifierName(this); + visitor.VisitIdentifierNameExpression(this); } } - public class NumberLiteralSyntaxNode : ExpressionSyntaxNode + public class NumberLiteralExpressionSyntaxNode : ExpressionSyntaxNode { - internal NumberLiteralSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal NumberLiteralExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1153,7 +1185,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.NumberLiteralSyntaxNode)_green)._number, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.NumberLiteralExpressionSyntaxNode)_green)._number, this.GetChildPosition(0)); } } @@ -1169,13 +1201,13 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitNumberLiteral(this); + visitor.VisitNumberLiteralExpression(this); } } - public class StringLiteralSyntaxNode : ExpressionSyntaxNode + public class StringLiteralExpressionSyntaxNode : ExpressionSyntaxNode { - internal StringLiteralSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal StringLiteralExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1183,7 +1215,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.StringLiteralSyntaxNode)_green)._stringToken, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.StringLiteralExpressionSyntaxNode)_green)._stringToken, this.GetChildPosition(0)); } } @@ -1199,13 +1231,13 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitStringLiteral(this); + visitor.VisitStringLiteralExpression(this); } } - public class DoubleQuotedStringLiteralSyntaxNode : ExpressionSyntaxNode + public class DoubleQuotedStringLiteralExpressionSyntaxNode : ExpressionSyntaxNode { - internal DoubleQuotedStringLiteralSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal DoubleQuotedStringLiteralExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1213,7 +1245,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.DoubleQuotedStringLiteralSyntaxNode)_green)._stringToken, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.DoubleQuotedStringLiteralExpressionSyntaxNode)_green)._stringToken, this.GetChildPosition(0)); } } @@ -1229,13 +1261,13 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitDoubleQuotedStringLiteral(this); + visitor.VisitDoubleQuotedStringLiteralExpression(this); } } - public class UnquotedStringLiteralSyntaxNode : ExpressionSyntaxNode + public class UnquotedStringLiteralExpressionSyntaxNode : ExpressionSyntaxNode { - internal UnquotedStringLiteralSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal UnquotedStringLiteralExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1243,7 +1275,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.UnquotedStringLiteralSyntaxNode)_green)._stringToken, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.UnquotedStringLiteralExpressionSyntaxNode)_green)._stringToken, this.GetChildPosition(0)); } } @@ -1259,7 +1291,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitUnquotedStringLiteral(this); + visitor.VisitUnquotedStringLiteralExpression(this); } } @@ -1523,11 +1555,11 @@ namespace Parser } } - public class MemberAccessSyntaxNode : ExpressionSyntaxNode + public class MemberAccessExpressionSyntaxNode : ExpressionSyntaxNode { private SyntaxNode? _leftOperand; private SyntaxNode? _rightOperand; - internal MemberAccessSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal MemberAccessExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1535,7 +1567,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.MemberAccessSyntaxNode)_green)._dot, this.GetChildPosition(1)); + return new SyntaxToken(this, ((Parser.Internal.MemberAccessExpressionSyntaxNode)_green)._dot, this.GetChildPosition(1)); } } @@ -1569,14 +1601,14 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitMemberAccess(this); + visitor.VisitMemberAccessExpression(this); } } - public class UnaryPostixOperationExpressionSyntaxNode : ExpressionSyntaxNode + public class UnaryPostfixOperationExpressionSyntaxNode : ExpressionSyntaxNode { private SyntaxNode? _operand; - internal UnaryPostixOperationExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal UnaryPostfixOperationExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1584,7 +1616,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.UnaryPostixOperationExpressionSyntaxNode)_green)._operation, this.GetChildPosition(1)); + return new SyntaxToken(this, ((Parser.Internal.UnaryPostfixOperationExpressionSyntaxNode)_green)._operation, this.GetChildPosition(1)); } } @@ -1609,14 +1641,14 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitUnaryPostixOperationExpression(this); + visitor.VisitUnaryPostfixOperationExpression(this); } } - public class IndirectMemberAccessSyntaxNode : ExpressionSyntaxNode + public class IndirectMemberAccessExpressionSyntaxNode : ExpressionSyntaxNode { private SyntaxNode? _expression; - internal IndirectMemberAccessSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal IndirectMemberAccessExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1624,7 +1656,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.IndirectMemberAccessSyntaxNode)_green)._openingBracket, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.IndirectMemberAccessExpressionSyntaxNode)_green)._openingBracket, this.GetChildPosition(0)); } } @@ -1632,7 +1664,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.IndirectMemberAccessSyntaxNode)_green)._closingBracket, this.GetChildPosition(2)); + return new SyntaxToken(this, ((Parser.Internal.IndirectMemberAccessExpressionSyntaxNode)_green)._closingBracket, this.GetChildPosition(2)); } } @@ -1657,24 +1689,22 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitIndirectMemberAccess(this); + visitor.VisitIndirectMemberAccessExpression(this); } } public class CommandExpressionSyntaxNode : ExpressionSyntaxNode { - private SyntaxNode? _commandName; private SyntaxNode? _arguments; internal CommandExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } - public IdentifierNameSyntaxNode CommandName + public SyntaxToken CommandName { get { - var red = this.GetRed(ref this._commandName!, 0); - return red is null ? throw new System.Exception("commandName cannot be null.") : (IdentifierNameSyntaxNode)red; + return new SyntaxToken(this, ((Parser.Internal.CommandExpressionSyntaxNode)_green)._commandName, this.GetChildPosition(0)); } } @@ -1691,7 +1721,7 @@ namespace Parser { return i switch { - 0 => GetRed(ref _commandName!, 0), 1 => GetRed(ref _arguments!, 1), _ => null + 1 => GetRed(ref _arguments!, 1), _ => null } ; @@ -1703,11 +1733,11 @@ namespace Parser } } - public class BaseClassInvokationSyntaxNode : ExpressionSyntaxNode + public class ClassInvokationExpressionSyntaxNode : ExpressionSyntaxNode { private SyntaxNode? _methodName; private SyntaxNode? _baseClassNameAndArguments; - internal BaseClassInvokationSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal ClassInvokationExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1715,7 +1745,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.BaseClassInvokationSyntaxNode)_green)._atSign, this.GetChildPosition(1)); + return new SyntaxToken(this, ((Parser.Internal.ClassInvokationExpressionSyntaxNode)_green)._atSign, this.GetChildPosition(1)); } } @@ -1749,7 +1779,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitBaseClassInvokation(this); + visitor.VisitClassInvokationExpression(this); } } @@ -1795,18 +1825,16 @@ namespace Parser public class AttributeSyntaxNode : SyntaxNode { - private SyntaxNode? _name; private SyntaxNode? _assignment; internal AttributeSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } - public IdentifierNameSyntaxNode Name + public SyntaxToken Name { get { - var red = this.GetRed(ref this._name!, 0); - return red is null ? throw new System.Exception("name cannot be null.") : (IdentifierNameSyntaxNode)red; + return new SyntaxToken(this, ((Parser.Internal.AttributeSyntaxNode)_green)._name, this.GetChildPosition(0)); } } @@ -1823,7 +1851,7 @@ namespace Parser { return i switch { - 0 => GetRed(ref _name!, 0), 1 => GetRed(ref _assignment, 1), _ => null + 1 => GetRed(ref _assignment, 1), _ => null } ; @@ -1883,7 +1911,7 @@ namespace Parser } } - public class MethodDefinitionSyntaxNode : MethodDeclarationSyntaxNode + public class ConcreteMethodDeclarationSyntaxNode : MethodDeclarationSyntaxNode { private SyntaxNode? _outputDescription; private SyntaxNode? _name; @@ -1891,7 +1919,7 @@ namespace Parser private SyntaxNode? _commas; private SyntaxNode? _body; private SyntaxNode? _endKeyword; - internal MethodDefinitionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) + internal ConcreteMethodDeclarationSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } @@ -1899,7 +1927,7 @@ namespace Parser { get { - return new SyntaxToken(this, ((Parser.Internal.MethodDefinitionSyntaxNode)_green)._functionKeyword, this.GetChildPosition(0)); + return new SyntaxToken(this, ((Parser.Internal.ConcreteMethodDeclarationSyntaxNode)_green)._functionKeyword, this.GetChildPosition(0)); } } @@ -1912,12 +1940,12 @@ namespace Parser } } - public CompoundNameSyntaxNode Name + public CompoundNameExpressionSyntaxNode Name { get { var red = this.GetRed(ref this._name!, 2); - return red is null ? throw new System.Exception("name cannot be null.") : (CompoundNameSyntaxNode)red; + return red is null ? throw new System.Exception("name cannot be null.") : (CompoundNameExpressionSyntaxNode)red; } } @@ -1939,12 +1967,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public StatementSyntaxNode Body { get { var red = this.GetRed(ref this._body!, 5); - return red is null ? throw new System.Exception("body cannot be null.") : (SyntaxNodeOrTokenList)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -1969,7 +1997,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitMethodDefinition(this); + visitor.VisitConcreteMethodDeclaration(this); } } @@ -1991,12 +2019,12 @@ namespace Parser } } - public CompoundNameSyntaxNode Name + public CompoundNameExpressionSyntaxNode Name { get { var red = this.GetRed(ref this._name!, 1); - return red is null ? throw new System.Exception("name cannot be null.") : (CompoundNameSyntaxNode)red; + return red is null ? throw new System.Exception("name cannot be null.") : (CompoundNameExpressionSyntaxNode)red; } } @@ -2184,7 +2212,6 @@ namespace Parser public class ClassDeclarationSyntaxNode : StatementSyntaxNode { private SyntaxNode? _attributes; - private SyntaxNode? _className; private SyntaxNode? _baseClassList; private SyntaxNode? _nodes; internal ClassDeclarationSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) @@ -2199,6 +2226,14 @@ namespace Parser } } + public SyntaxToken ClassName + { + get + { + return new SyntaxToken(this, ((Parser.Internal.ClassDeclarationSyntaxNode)_green)._className, this.GetChildPosition(2)); + } + } + public SyntaxToken EndKeyword { get @@ -2216,15 +2251,6 @@ namespace Parser } } - public IdentifierNameSyntaxNode ClassName - { - get - { - var red = this.GetRed(ref this._className!, 2); - return red is null ? throw new System.Exception("className cannot be null.") : (IdentifierNameSyntaxNode)red; - } - } - public BaseClassListSyntaxNode? BaseClassList { get @@ -2247,7 +2273,7 @@ namespace Parser { return i switch { - 1 => GetRed(ref _attributes, 1), 2 => GetRed(ref _className!, 2), 3 => GetRed(ref _baseClassList, 3), 4 => GetRed(ref _nodes!, 4), _ => null + 1 => GetRed(ref _attributes, 1), 3 => GetRed(ref _baseClassList, 3), 4 => GetRed(ref _nodes!, 4), _ => null } ; @@ -2309,19 +2335,17 @@ namespace Parser public class EnumerationItemSyntaxNode : SyntaxNode { - private SyntaxNode? _name; private SyntaxNode? _values; private SyntaxNode? _commas; internal EnumerationItemSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } - public IdentifierNameSyntaxNode Name + public SyntaxToken Name { get { - var red = this.GetRed(ref this._name!, 0); - return red is null ? throw new System.Exception("name cannot be null.") : (IdentifierNameSyntaxNode)red; + return new SyntaxToken(this, ((Parser.Internal.EnumerationItemSyntaxNode)_green)._name, this.GetChildPosition(0)); } } @@ -2347,7 +2371,7 @@ namespace Parser { return i switch { - 0 => GetRed(ref _name!, 0), 1 => GetRed(ref _values, 1), 2 => GetRed(ref _commas!, 2), _ => null + 1 => GetRed(ref _values, 1), 2 => GetRed(ref _commas!, 2), _ => null } ; diff --git a/Parser/SyntaxNode.cs b/Parser/SyntaxNode.cs index e3db3e6..e7eb31e 100644 --- a/Parser/SyntaxNode.cs +++ b/Parser/SyntaxNode.cs @@ -141,9 +141,9 @@ namespace Parser } } - public abstract class FunctionHandleSyntaxNode : ExpressionSyntaxNode + public abstract class FunctionHandleExpressionSyntaxNode : ExpressionSyntaxNode { - internal FunctionHandleSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position) : base(parent, green, position) + internal FunctionHandleExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position) : base(parent, green, position) { } } diff --git a/Parser/SyntaxToken.cs b/Parser/SyntaxToken.cs index e0c27f1..2b68968 100644 --- a/Parser/SyntaxToken.cs +++ b/Parser/SyntaxToken.cs @@ -29,6 +29,8 @@ namespace Parser public int Position { get; } + public object? Value => _token.GetValue(); + public bool Equals(SyntaxToken other) { return Equals(_parent, other._parent) && Equals(_token, other._token); diff --git a/Parser/SyntaxTree.cs b/Parser/SyntaxTree.cs new file mode 100644 index 0000000..598bf5d --- /dev/null +++ b/Parser/SyntaxTree.cs @@ -0,0 +1,27 @@ +using System; +using Parser.Internal; + +namespace Parser +{ + public class SyntaxTree + { + public SyntaxTree(RootSyntaxNode nullRoot, DiagnosticsBag diagnostics) + { + NullRoot = nullRoot ?? throw new ArgumentNullException(nameof(nullRoot)); + Diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); + } + + public RootSyntaxNode NullRoot { get; } + public FileSyntaxNode Root => NullRoot.File; + public DiagnosticsBag Diagnostics { get; } + + public static SyntaxTree Parse(string text) + { + var window = new TextWindowWithNull(text); + var parser = new MParser(window); + var tree = parser.Parse(); + return tree; + } + } + +} \ No newline at end of file diff --git a/Parser/SyntaxVisitor.Generated.cs b/Parser/SyntaxVisitor.Generated.cs index 3ee82f6..7249d3b 100644 --- a/Parser/SyntaxVisitor.Generated.cs +++ b/Parser/SyntaxVisitor.Generated.cs @@ -8,6 +8,11 @@ namespace Parser DefaultVisit(node); } + public virtual void VisitBlockStatement(BlockStatementSyntaxNode node) + { + DefaultVisit(node); + } + public virtual void VisitFunctionDeclaration(FunctionDeclarationSyntaxNode node) { DefaultVisit(node); @@ -93,17 +98,17 @@ namespace Parser DefaultVisit(node); } - public virtual void VisitCompoundName(CompoundNameSyntaxNode node) + public virtual void VisitCompoundNameExpression(CompoundNameExpressionSyntaxNode node) { DefaultVisit(node); } - public virtual void VisitNamedFunctionHandle(NamedFunctionHandleSyntaxNode node) + public virtual void VisitNamedFunctionHandleExpression(NamedFunctionHandleExpressionSyntaxNode node) { DefaultVisit(node); } - public virtual void VisitLambda(LambdaSyntaxNode node) + public virtual void VisitLambdaExpression(LambdaExpressionSyntaxNode node) { DefaultVisit(node); } @@ -113,27 +118,27 @@ namespace Parser DefaultVisit(node); } - public virtual void VisitIdentifierName(IdentifierNameSyntaxNode node) + public virtual void VisitIdentifierNameExpression(IdentifierNameExpressionSyntaxNode node) { DefaultVisit(node); } - public virtual void VisitNumberLiteral(NumberLiteralSyntaxNode node) + public virtual void VisitNumberLiteralExpression(NumberLiteralExpressionSyntaxNode node) { DefaultVisit(node); } - public virtual void VisitStringLiteral(StringLiteralSyntaxNode node) + public virtual void VisitStringLiteralExpression(StringLiteralExpressionSyntaxNode node) { DefaultVisit(node); } - public virtual void VisitDoubleQuotedStringLiteral(DoubleQuotedStringLiteralSyntaxNode node) + public virtual void VisitDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralExpressionSyntaxNode node) { DefaultVisit(node); } - public virtual void VisitUnquotedStringLiteral(UnquotedStringLiteralSyntaxNode node) + public virtual void VisitUnquotedStringLiteralExpression(UnquotedStringLiteralExpressionSyntaxNode node) { DefaultVisit(node); } @@ -163,17 +168,17 @@ namespace Parser DefaultVisit(node); } - public virtual void VisitMemberAccess(MemberAccessSyntaxNode node) + public virtual void VisitMemberAccessExpression(MemberAccessExpressionSyntaxNode node) { DefaultVisit(node); } - public virtual void VisitUnaryPostixOperationExpression(UnaryPostixOperationExpressionSyntaxNode node) + public virtual void VisitUnaryPostfixOperationExpression(UnaryPostfixOperationExpressionSyntaxNode node) { DefaultVisit(node); } - public virtual void VisitIndirectMemberAccess(IndirectMemberAccessSyntaxNode node) + public virtual void VisitIndirectMemberAccessExpression(IndirectMemberAccessExpressionSyntaxNode node) { DefaultVisit(node); } @@ -183,7 +188,7 @@ namespace Parser DefaultVisit(node); } - public virtual void VisitBaseClassInvokation(BaseClassInvokationSyntaxNode node) + public virtual void VisitClassInvokationExpression(ClassInvokationExpressionSyntaxNode node) { DefaultVisit(node); } @@ -203,7 +208,7 @@ namespace Parser DefaultVisit(node); } - public virtual void VisitMethodDefinition(MethodDefinitionSyntaxNode node) + public virtual void VisitConcreteMethodDeclaration(ConcreteMethodDeclarationSyntaxNode node) { DefaultVisit(node); } diff --git a/Parser/TokenKind.cs b/Parser/TokenKind.cs index 52e455c..4645763 100644 --- a/Parser/TokenKind.cs +++ b/Parser/TokenKind.cs @@ -3,7 +3,9 @@ // We use the same set of kinds for syntax tokens & syntax nodes. public enum TokenKind { - // SYNTAX TOKENS + // ***************** + // * SYNTAX TOKENS * + // ***************** None = 0, BadToken = 1, @@ -123,31 +125,58 @@ UnaryNot = 59, UnaryQuestionMark = 60, - // SYNTAX NODES + // **************** + // * SYNTAX NODES * + // **************** + // The whole file. File = 100, + // a list of syntax nodes and/or tokens. List, + + + // STATEMENTS + // The name ends with "Declaration" or "Statement". + + // result = abstractMethod(object) + AbstractMethodDeclaration, + + // statement1 + // statement2; + BlockStatement, + + // classdef MyClass < BaseClass, AnotherBaseClass + // properties + // y + // end + // methods + // <...> + // end + // end + ClassDeclaration, + + // function result = method(obj) + // <...> + // end + ConcreteMethodDeclaration, + + // + EmptyStatement, + + // a = 5; + ExpressionStatement, + + // for a = 1:5 + // process(a); + // end + ForStatement, + // [output1, output2] = function(input1, input2) // <...> // end FunctionDeclaration, - // (input1, input2) - FunctionInputDescription, - // [output1, output2] = - FunctionOutputDescription, - // switch a - // case 1 - // <...> - // end - SwitchStatement, - // case 1 - // doSomething(); - SwitchCase, - // while a < 10 - // doSomething(); - // end - WhileStatement, + // if a < 5 // doSomething(); // elseif a > 10 @@ -156,84 +185,125 @@ // GiveUp(); // end IfStatement, - // elseif a > 10 - // doSomethingElse(); - ElseifClause, - // else - // GiveUp(); - ElseClause, - // for a = 1:5 - // process(a); + + // switch a + // case 1 + // <...> // end - ForStatement, - // a = 1:5 - AssignmentExpression, - // catch e - // dealWithIt(e); - // end - CatchClause, + SwitchStatement, + // try // somethingWeird(); // catch e // dealWithIt(e); // end TryCatchStatement, - // a = 5; - ExpressionStatement, - // - EmptyStatement, - // - EmptyExpression, - // -13 - UnaryPrefixOperationExpression, - // some.complex.name - CompoundName, - // @func - NamedFunctionHandle, - // @(x) x + 1 - Lambda, - // + - BinaryOperation, - // a - IdentifierName, - // 123 - NumberLiteralExpression, - // 'abc' - StringLiteralExpression, - // "abc" - DoubleQuotedStringLiteralExpression, - // abc - UnquotedStringLiteralExpression, + + // while a < 10 + // doSomething(); + // end + WhileStatement, + + + // EXPRESSIONS + // The name ends with "Expression". + // [1, 2; 3 4] ArrayLiteralExpression, + + // a = 1:5 + AssignmentExpression, + + // + + BinaryOperationExpression, + + // abc{2} + CellArrayElementAccessExpression, + // {1, 3, 'abc'} CellArrayLiteralExpression, + + // method@SuperClass(object) + ClassInvokationExpression, + + // cd some/+folder/ + CommandExpression, + + // some.complex.name + CompoundNameExpression, + + // "abc" + DoubleQuotedStringLiteralExpression, + + // + EmptyExpression, + + // doSomething(5) + FunctionCallExpression, + + // a + IdentifierNameExpression, + + // struct.(field) + IndirectMemberAccessExpression, + + // @(x) x + 1 + LambdaExpression, + + // object.member + MemberAccessExpression, + + // @func + NamedFunctionHandleExpression, + + // 123 + NumberLiteralExpression, + // (1 + 2 * 3) ParenthesizedExpression, - // abc{2} - CellArrayElementAccess, - // doSomething(5) - FunctionCall, - // object.member - MemberAccess, + + // 'abc' + StringLiteralExpression, + + // -13 + UnaryPrefixOperationExpression, + // [1 2 3]' UnaryPostfixOperationExpression, - // struct.(field) - IndirectMemberAccess, - // cd some/+folder/ - Command, - // method@SuperClass(object) - ClassInvokation, + + // abc + UnquotedStringLiteralExpression, + + + // PARTS OF STATEMENTS & EXPRESSIONS + + // (input1, input2) + FunctionInputDescription, + // [output1, output2] = + FunctionOutputDescription, + + // case 1 + // doSomething(); + SwitchCase, + + // elseif a > 10 + // doSomethingElse(); + ElseifClause, + // else + // GiveUp(); + ElseClause, + // catch e + // dealWithIt(e); + // end + CatchClause, + // = true AttributeAssignment, // Sealed = true Attribute, // (Sealed = true) AttributeList, - // function result = method(obj) - // <...> - // end - MethodDefinition, + // methods // function result = method(obj) // <...> @@ -247,15 +317,7 @@ PropertiesList, // < BaseClass, AnotherBaseClass BaseClassList, - // classdef MyClass < BaseClass, AnotherBaseClass - // properties - // y - // end - // methods - // <...> - // end - // end - ClassDeclaration, + // (1) EnumerationItemValue, // One (1) @@ -265,8 +327,6 @@ // Two (2) // end EnumerationList, - // result = abstractMethod(object) - AbstractMethodDeclaration, // events // ToggleSomething // end diff --git a/Parser/UnresolvedFunctionSymbol.cs b/Parser/UnresolvedFunctionSymbol.cs new file mode 100644 index 0000000..76dfcda --- /dev/null +++ b/Parser/UnresolvedFunctionSymbol.cs @@ -0,0 +1,12 @@ +namespace Parser +{ + internal class UnresolvedFunctionSymbol + { + public string Name { get; } + + public UnresolvedFunctionSymbol(string name) + { + Name = name; + } + } +} \ No newline at end of file diff --git a/Repl/MRepl.cs b/Repl/MRepl.cs index b64feb0..c8b1b81 100644 --- a/Repl/MRepl.cs +++ b/Repl/MRepl.cs @@ -1,67 +1,80 @@ using System; +using System.Linq; using Parser; namespace Repl { public class MRepl { + private readonly CompilationContext _context; + + public MRepl() + { + _context = CompilationContext.Empty; + } + public void Run() { while (true) { - Console.Write("> "); - var line = Console.ReadLine(); - var window = new TextWindowWithNull(line); - var parser = new MParser(window); - var tree = parser.Parse(); - if (tree.Diagnostics.Diagnostics.Count > 0) + var line = Read(); + if (line.StartsWith('#')) { - foreach (var diagnostic in tree.Diagnostics.Diagnostics) + line = line.Trim(); + if (line == "#q") { - Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}"); + break; } + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine($"Unknown command '{line}'."); + Console.ResetColor(); + continue; + } + var result = Evaluate(line); + Print(result); + } + } + + private void Print(string result) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(result); + Console.ResetColor(); + } + + private string Read() + { + Console.Write("> "); + return Console.ReadLine(); + } + + private string Evaluate(string submission) + { + var tree = SyntaxTree.Parse(submission); + if (tree.Diagnostics.Any()) + { + foreach (var diagnostic in tree.Diagnostics.Diagnostics) + { + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}"); + Console.ResetColor(); } TreeRenderer.RenderTree(tree); + return string.Empty; } - } - } - public class TreeRenderer - { - private static void RenderToken(SyntaxToken token, string indent, bool isLast) - { - Console.Write(indent + (isLast ? "└── " : "├── ")); - Console.Write($"<{token.Kind}>"); - Console.Write($" {token.Text}"); - Console.WriteLine(); - } + TreeRenderer.RenderTree(tree); + var compilation = Compilation.Create(tree); + var evaluationResult = compilation.Evaluate(_context, inRepl: true); - private static void RenderNode(SyntaxNode node, string indent, bool isLast) - { - Console.Write(indent); - Console.Write(isLast ? "└── " : "├── "); - Console.Write($"<{node.Kind}>"); - Console.WriteLine(); - var children = node.GetChildNodesAndTokens(); - var last = children.Count - 1; - indent += isLast ? " " : "│ "; - for (var index = 0; index <= last; index++) + foreach (var diagnostic in evaluationResult.Diagnostics) { - var child = children[index]; - if (child.IsNode) - { - RenderNode(child.AsNode(), indent, index == last); - } - else if (child.IsToken) - { - RenderToken(child.AsToken(), indent, index == last); - } + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}"); + Console.ResetColor(); } - } - public static void RenderTree(SyntaxTree tree) - { - RenderNode(tree.Root, "", true); + return evaluationResult.Value?.ToString() ?? string.Empty; } } } diff --git a/Repl/TreeRenderer.cs b/Repl/TreeRenderer.cs new file mode 100644 index 0000000..c22ebee --- /dev/null +++ b/Repl/TreeRenderer.cs @@ -0,0 +1,44 @@ +using System; +using Parser; + +namespace Repl +{ + public class TreeRenderer + { + private static void RenderToken(SyntaxToken token, string indent, bool isLast) + { + Console.Write(indent + (isLast ? "└── " : "├── ")); + Console.Write($"<{token.Kind}>"); + Console.Write($" {token.Text}"); + Console.WriteLine(); + } + + private static void RenderNode(SyntaxNode node, string indent, bool isLast) + { + Console.Write(indent); + Console.Write(isLast ? "└── " : "├── "); + Console.Write($"<{node.Kind}>"); + Console.WriteLine(); + var children = node.GetChildNodesAndTokens(); + var last = children.Count - 1; + indent += isLast ? " " : "│ "; + for (var index = 0; index <= last; index++) + { + var child = children[index]; + if (child.IsNode) + { + RenderNode(child.AsNode(), indent, index == last); + } + else if (child.IsToken) + { + RenderToken(child.AsToken(), indent, index == last); + } + } + } + + public static void RenderTree(SyntaxTree tree) + { + RenderNode(tree.Root, "", true); + } + } +} diff --git a/Semantics/GetClass.cs b/Semantics/GetClass.cs index d9c31c1..49a38cd 100644 --- a/Semantics/GetClass.cs +++ b/Semantics/GetClass.cs @@ -7,7 +7,7 @@ namespace Semantics { public class GetClass { - private static MMethod MethodFromDefinition(MethodDefinitionSyntaxNode methodDefinition) + private static MMethod MethodFromDefinition(ConcreteMethodDeclarationSyntaxNode methodDefinition) { var name = methodDefinition.Name.Text; var description = ""; @@ -42,7 +42,7 @@ namespace Semantics continue; } - if (method.AsNode() is MethodDefinitionSyntaxNode methodDefinition) + if (method.AsNode() is ConcreteMethodDeclarationSyntaxNode methodDefinition) { result.Add(MethodFromDefinition(methodDefinition)); } @@ -58,7 +58,7 @@ namespace Semantics public static MClass FromTree(FileSyntaxNode tree, string fileName) { - var classDeclaration = tree.StatementList[0].AsNode() as ClassDeclarationSyntaxNode; + var classDeclaration = tree.Body.Statements[0].AsNode() as ClassDeclarationSyntaxNode; if (classDeclaration == null) { return null; diff --git a/Solution.sln b/Solution.sln index b48c4d5..56fc479 100644 --- a/Solution.sln +++ b/Solution.sln @@ -21,7 +21,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Repl", "Repl\Repl.csproj", "{8FEDFE5D-3320-418F-88A6-09C1B51C4441}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MApplication", "MApplication\MApplication.csproj", "{A7EE271C-8822-43EA-BA13-5D6D5DC5B581}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MApplication", "MApplication\MApplication.csproj", "{A7EE271C-8822-43EA-BA13-5D6D5DC5B581}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cmi", "cmi\cmi.csproj", "{C2447F0B-733D-4755-A104-5B82E24D3F47}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -57,6 +59,10 @@ Global {A7EE271C-8822-43EA-BA13-5D6D5DC5B581}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7EE271C-8822-43EA-BA13-5D6D5DC5B581}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7EE271C-8822-43EA-BA13-5D6D5DC5B581}.Release|Any CPU.Build.0 = Release|Any CPU + {C2447F0B-733D-4755-A104-5B82E24D3F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C2447F0B-733D-4755-A104-5B82E24D3F47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2447F0B-733D-4755-A104-5B82E24D3F47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C2447F0B-733D-4755-A104-5B82E24D3F47}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SyntaxGenerator/GenerateSyntax.cs b/SyntaxGenerator/GenerateSyntax.cs index 847da49..ddb8c6f 100644 --- a/SyntaxGenerator/GenerateSyntax.cs +++ b/SyntaxGenerator/GenerateSyntax.cs @@ -844,7 +844,8 @@ namespace SyntaxGenerator public static void Input() { var serializer = new XmlSerializer(typeof(SyntaxDescription)); - using var stream = new FileStream("input.xml", FileMode.Open); + var syntaxDefinitionFileName = Path.Combine(_outputPath, "SyntaxDefinition.xml"); + using var stream = new FileStream(syntaxDefinitionFileName, FileMode.Open); if (!(serializer.Deserialize(stream) is SyntaxDescription syntax)) { Console.WriteLine("Couldn't deserialize syntax."); diff --git a/cmi.cmd b/cmi.cmd new file mode 100644 index 0000000..6a05f9e --- /dev/null +++ b/cmi.cmd @@ -0,0 +1 @@ +dotnet run --project cmi -- %* diff --git a/cmi/Program.cs b/cmi/Program.cs new file mode 100644 index 0000000..f1f0042 --- /dev/null +++ b/cmi/Program.cs @@ -0,0 +1,55 @@ +using Parser; +using System; +using System.IO; + +namespace cmi +{ + + class Program + { + static void Main(string[] args) + { + string fileName; + if (args.Length != 1) + { + Console.Error.WriteLine("Usage: cmi "); + fileName = @"C:\repos\MParser\examples\helloworld\hello.m"; + } + else + { + fileName = args[0]; + } + + var text = File.ReadAllText(fileName); + var tree = SyntaxTree.Parse(text); + var compilation = Compilation.Create(tree); + TreeRenderer.RenderTree(tree); + if (tree.Diagnostics.Diagnostics.Count > 0) + { + foreach (var diagnostic in tree.Diagnostics.Diagnostics) + { + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}"); + Console.ResetColor(); + return; + } + } + + var context = new CompilationContext(); + var evaluationResult = compilation.Evaluate(context, inRepl: false); + + foreach (var diagnostic in evaluationResult.Diagnostics) + { + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}"); + Console.ResetColor(); + } + + var result = evaluationResult.Value?.ToString(); + if (result is not null) + { + Console.WriteLine(result); + } + } + } +} diff --git a/cmi/TreeRenderer.cs b/cmi/TreeRenderer.cs new file mode 100644 index 0000000..e0d6871 --- /dev/null +++ b/cmi/TreeRenderer.cs @@ -0,0 +1,44 @@ +using Parser; +using System; + +namespace cmi +{ + public class TreeRenderer + { + private static void RenderToken(SyntaxToken token, string indent, bool isLast) + { + Console.Write(indent + (isLast ? "└── " : "├── ")); + Console.Write($"<{token.Kind}>"); + Console.Write($" {token.Text}"); + Console.WriteLine(); + } + + private static void RenderNode(SyntaxNode node, string indent, bool isLast) + { + Console.Write(indent); + Console.Write(isLast ? "└── " : "├── "); + Console.Write($"<{node.Kind}>"); + Console.WriteLine(); + var children = node.GetChildNodesAndTokens(); + var last = children.Count - 1; + indent += isLast ? " " : "│ "; + for (var index = 0; index <= last; index++) + { + var child = children[index]; + if (child.IsNode) + { + RenderNode(child.AsNode(), indent, index == last); + } + else if (child.IsToken) + { + RenderToken(child.AsToken(), indent, index == last); + } + } + } + + public static void RenderTree(SyntaxTree tree) + { + RenderNode(tree.Root, "", true); + } + } +} diff --git a/cmi/cmi.csproj b/cmi/cmi.csproj new file mode 100644 index 0000000..7c25f37 --- /dev/null +++ b/cmi/cmi.csproj @@ -0,0 +1,14 @@ + + + + Exe + net5.0 + enable + preview + + + + + + + diff --git a/examples/helloworld/hello.m b/examples/helloworld/hello.m new file mode 100644 index 0000000..fe26aae --- /dev/null +++ b/examples/helloworld/hello.m @@ -0,0 +1,11 @@ +x = 2; +f(x); +f(x); + +function f(x) + disp('X was'); + disp(x); + x = x + 1; + disp('X is') + disp(x); +end \ No newline at end of file