From 8c1ddb0cf71e75c9c18528f6b4b4027daa21391e Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Tue, 14 Jul 2020 13:44:37 +0200 Subject: [PATCH 01/12] Start implementing Evaluator --- ConsoleDemo/Program.cs | 10 +- Parser/Compilation.cs | 23 +++ Parser/CompilationContext.cs | 7 + Parser/EvaluationResult.cs | 19 +++ Parser/Evaluator.cs | 282 ++++++++++++++++++++++++++++++++ Parser/MParser.cs | 18 +- Parser/Objects/MDoubleNumber.cs | 6 + Parser/Objects/MObject.cs | 6 + Parser/SyntaxTree.cs | 27 +++ Repl/MRepl.cs | 95 ++++++----- Repl/TreeRenderer.cs | 44 +++++ 11 files changed, 472 insertions(+), 65 deletions(-) create mode 100644 Parser/Compilation.cs create mode 100644 Parser/CompilationContext.cs create mode 100644 Parser/EvaluationResult.cs create mode 100644 Parser/Evaluator.cs create mode 100644 Parser/Objects/MDoubleNumber.cs create mode 100644 Parser/Objects/MObject.cs create mode 100644 Parser/SyntaxTree.cs create mode 100644 Repl/TreeRenderer.cs 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/Parser/Compilation.cs b/Parser/Compilation.cs new file mode 100644 index 0000000..c4668c6 --- /dev/null +++ b/Parser/Compilation.cs @@ -0,0 +1,23 @@ +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); + } + + public EvaluationResult Evaluate(CompilationContext context) + { + var evaluator = new Evaluator(_syntaxTree, context); + 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..df3c6fc --- /dev/null +++ b/Parser/CompilationContext.cs @@ -0,0 +1,7 @@ +namespace Parser +{ + public class CompilationContext + { + 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/Evaluator.cs b/Parser/Evaluator.cs new file mode 100644 index 0000000..ed0bf15 --- /dev/null +++ b/Parser/Evaluator.cs @@ -0,0 +1,282 @@ +using Parser.Internal; +using Parser.Objects; +using System; +using System.Collections.Immutable; + +namespace Parser +{ + internal class Evaluator + { + private SyntaxTree _syntaxTree; + private CompilationContext _context; + private DiagnosticsBag _diagnostics; + + public Evaluator(SyntaxTree syntaxTree, CompilationContext context) + { + _syntaxTree = syntaxTree; + _context = context; + _diagnostics = new DiagnosticsBag(); + } + + internal EvaluationResult Evaluate() + { + var result = EvaluateFile(_syntaxTree.Root); + return new EvaluationResult(result, _diagnostics.ToImmutableArray()); + } + + private MObject? EvaluateFile(FileSyntaxNode root) + { + MObject? lastResult = null; + foreach (var nodeOrToken in root.StatementList) + { + if (nodeOrToken.IsNode) + { + var statement = (StatementSyntaxNode)nodeOrToken.AsNode()!; + lastResult = EvaluateStatement(statement) ?? lastResult; + } + } + + return lastResult; + } + + private MObject? EvaluateStatement(StatementSyntaxNode statement) + { + return statement.Kind switch + { + TokenKind.ExpressionStatement => + EvaluateExpressionStatement((ExpressionStatementSyntaxNode)statement), + TokenKind.MethodDefinition => + EvaluateMethodDefinition((MethodDefinitionSyntaxNode)statement), + TokenKind.AbstractMethodDeclaration => + EvaluateAbstractMethodDeclaration((AbstractMethodDeclarationSyntaxNode)statement), + TokenKind.FunctionDeclaration => + EvaluateFunctionDeclaration((FunctionDeclarationSyntaxNode)statement), + TokenKind.SwitchStatement => + EvaluateSwitchStatement((SwitchStatementSyntaxNode)statement), + TokenKind.WhileStatement => + EvaluateWhileStatement((WhileStatementSyntaxNode)statement), + TokenKind.IfStatement => + EvaluateIfStatement((IfStatementSyntaxNode)statement), + TokenKind.ForStatement => + EvaluateForStatement((ForStatementSyntaxNode)statement), + TokenKind.TryCatchStatement => + EvaluateTryCatchStatement((TryCatchStatementSyntaxNode)statement), + TokenKind.EmptyStatement => + EvaluateEmptyStatement((EmptyStatementSyntaxNode)statement), + TokenKind.ClassDeclaration => + EvaluateClassDeclaration((ClassDeclarationSyntaxNode)statement), + _ => throw new NotImplementedException($"Invalid statement kind '{statement.Kind}'."), + }; + } + + private MObject? EvaluateClassDeclaration(ClassDeclarationSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateEmptyStatement(EmptyStatementSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateTryCatchStatement(TryCatchStatementSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateForStatement(ForStatementSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateIfStatement(IfStatementSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateWhileStatement(WhileStatementSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateSwitchStatement(SwitchStatementSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateFunctionDeclaration(FunctionDeclarationSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateAbstractMethodDeclaration(AbstractMethodDeclarationSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateMethodDefinition(MethodDefinitionSyntaxNode statement) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateExpressionStatement(ExpressionStatementSyntaxNode statement) + { + return EvaluateExpression(statement.Expression); + } + + private MObject? EvaluateExpression(ExpressionSyntaxNode expression) + { + return expression.Kind switch + { + TokenKind.Lambda => + EvaluateLambda((LambdaSyntaxNode)expression), + TokenKind.AssignmentExpression => + EvaluateAssignmentExpression((AssignmentExpressionSyntaxNode)expression), + TokenKind.EmptyExpression => + EvaluateEmptyExpression((EmptyExpressionSyntaxNode)expression), + TokenKind.UnaryPrefixOperationExpression => + EvaluateUnaryPrefixOperationExpression((UnaryPrefixOperationExpressionSyntaxNode)expression), + TokenKind.CompoundName => + EvaluateCompoundName((CompoundNameSyntaxNode)expression), + TokenKind.BinaryOperation => + EvaluateBinaryOperation((BinaryOperationExpressionSyntaxNode)expression), + TokenKind.IdentifierName => + EvaluateIdentifierName((IdentifierNameSyntaxNode)expression), + TokenKind.NumberLiteralExpression => + EvaluateNumberLiteralExpression((NumberLiteralSyntaxNode)expression), + TokenKind.StringLiteralExpression => + EvaluateStringLiteralExpression((StringLiteralSyntaxNode)expression), + TokenKind.DoubleQuotedStringLiteralExpression => + EvaluateDoubleQuotedStringLiteralExpression((DoubleQuotedStringLiteralSyntaxNode)expression), + TokenKind.UnquotedStringLiteralExpression => + EvaluateUnquotedStringLiteralExpression((UnquotedStringLiteralSyntaxNode)expression), + TokenKind.ArrayLiteralExpression => + EvaluateArrayLiteralExpression((ArrayLiteralExpressionSyntaxNode)expression), + TokenKind.CellArrayLiteralExpression => + EvaluateCellArrayLiteralExpression((CellArrayLiteralExpressionSyntaxNode)expression), + TokenKind.ParenthesizedExpression => + EvaluateNamedFunctionHandle((NamedFunctionHandleSyntaxNode)expression), + TokenKind.CellArrayElementAccess => + EvaluateCellArrayElementAccess((CellArrayElementAccessExpressionSyntaxNode)expression), + TokenKind.FunctionCall => + EvaluateFunctionCall((FunctionCallExpressionSyntaxNode)expression), + TokenKind.MemberAccess => + EvaluateMemberAccess((MemberAccessSyntaxNode)expression), + TokenKind.UnaryPostfixOperationExpression => + EvaluateUnaryPostfixOperationExpression((UnaryPostixOperationExpressionSyntaxNode)expression), + TokenKind.IndirectMemberAccess => + EvaluateIndirectMemberAccess((IndirectMemberAccessSyntaxNode)expression), + TokenKind.Command => + EvaluateCommand((CommandExpressionSyntaxNode)expression), + TokenKind.ClassInvokation => + EvaluateClassInvokation((BaseClassInvokationSyntaxNode)expression), + _ => throw new NotImplementedException($"Invalid expression kind '{expression.Kind}'."), + }; + } + + private MObject? EvaluateClassInvokation(BaseClassInvokationSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateCommand(CommandExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateIndirectMemberAccess(IndirectMemberAccessSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateUnaryPostfixOperationExpression(UnaryPostixOperationExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateMemberAccess(MemberAccessSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateFunctionCall(FunctionCallExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateCellArrayElementAccess(CellArrayElementAccessExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateCellArrayLiteralExpression(CellArrayLiteralExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateArrayLiteralExpression(ArrayLiteralExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateUnquotedStringLiteralExpression(UnquotedStringLiteralSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateStringLiteralExpression(StringLiteralSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateNumberLiteralExpression(NumberLiteralSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateIdentifierName(IdentifierNameSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateBinaryOperation(BinaryOperationExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateCompoundName(CompoundNameSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateEmptyExpression(EmptyExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateAssignmentExpression(AssignmentExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateLambda(LambdaSyntaxNode expression) + { + throw new NotImplementedException(); + } + + private MObject? EvaluateNamedFunctionHandle(NamedFunctionHandleSyntaxNode expression) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file 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/MDoubleNumber.cs b/Parser/Objects/MDoubleNumber.cs new file mode 100644 index 0000000..b745a64 --- /dev/null +++ b/Parser/Objects/MDoubleNumber.cs @@ -0,0 +1,6 @@ +namespace Parser.Objects +{ + public class MDoubleNumber : MObject + { + } +} \ No newline at end of file diff --git a/Parser/Objects/MObject.cs b/Parser/Objects/MObject.cs new file mode 100644 index 0000000..f84b55d --- /dev/null +++ b/Parser/Objects/MObject.cs @@ -0,0 +1,6 @@ +namespace Parser.Objects +{ + public abstract class MObject + { + } +} \ No newline at end of file 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/Repl/MRepl.cs b/Repl/MRepl.cs index b64feb0..c43e3e8 100644 --- a/Repl/MRepl.cs +++ b/Repl/MRepl.cs @@ -5,63 +5,74 @@ 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.Write(result); + } + + private string Read() + { + Console.Write("> "); + return Console.ReadLine(); + } + + private string Evaluate(string submission) + { + var tree = SyntaxTree.Parse(submission); + var compilation = Compilation.Create(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(); } 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); - 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 evaluationResult = compilation.Evaluate(_context); + + 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); + } + } +} From e1a7ea36c9642eb68e82bbd7ae2e1e5218be29eb Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Tue, 14 Jul 2020 14:38:59 +0200 Subject: [PATCH 02/12] Rename token kinds & syntax nodes --- ConsoleDemo/DumbWalker.cs | 18 +- ConsoleDemo/PrettyPrinter.cs | 8 +- ConsoleDemo/UsageGathering.cs | 8 +- MApplication/ColoringVisitor.cs | 8 +- Parser/Evaluator.cs | 119 ++++----- Parser/Internal/MParserGreen.cs | 32 +-- Parser/Internal/SyntaxFactory.Generated.cs | 28 +-- Parser/Internal/SyntaxNode.Generated.cs | 102 ++++---- Parser/Internal/SyntaxNode.cs | 6 +- .../input.xml => Parser/SyntaxDefinition.xml | 38 +-- Parser/SyntaxNode.Generated.cs | 58 ++--- Parser/SyntaxNode.cs | 4 +- Parser/SyntaxVisitor.Generated.cs | 8 +- Parser/TokenKind.cs | 228 +++++++++++------- SyntaxGenerator/GenerateSyntax.cs | 3 +- 15 files changed, 366 insertions(+), 302 deletions(-) rename SyntaxGenerator/input.xml => Parser/SyntaxDefinition.xml (90%) diff --git a/ConsoleDemo/DumbWalker.cs b/ConsoleDemo/DumbWalker.cs index 597e084..7914769 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()); diff --git a/ConsoleDemo/PrettyPrinter.cs b/ConsoleDemo/PrettyPrinter.cs index 1f2be12..0cbf492 100644 --- a/ConsoleDemo/PrettyPrinter.cs +++ b/ConsoleDemo/PrettyPrinter.cs @@ -274,7 +274,7 @@ namespace ProjectConsole OutputBracket(node.ClosingBrace); } - public override void VisitIdentifierName(IdentifierNameSyntaxNode node) + public override void VisitIdentifierNameExpression(IdentifierNameExpressionSyntaxNode node) { OutputIdentifier(node.Name); } @@ -410,7 +410,7 @@ namespace ProjectConsole OutputBracket(node.ClosingBrace); } - public override void VisitCompoundName(CompoundNameSyntaxNode node) + public override void VisitCompoundNameExpression(CompoundNameExpressionSyntaxNode node) { Visit(node.Nodes); } @@ -479,14 +479,14 @@ namespace ProjectConsole 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); diff --git a/ConsoleDemo/UsageGathering.cs b/ConsoleDemo/UsageGathering.cs index 53ea181..6665443 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; @@ -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()); @@ -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()); diff --git a/MApplication/ColoringVisitor.cs b/MApplication/ColoringVisitor.cs index 16bce5a..28aa2f6 100644 --- a/MApplication/ColoringVisitor.cs +++ b/MApplication/ColoringVisitor.cs @@ -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); } @@ -357,7 +357,7 @@ namespace MApplication AddToken(node.ClosingBrace, _scheme.Bracket); } - public override void VisitCompoundName(CompoundNameSyntaxNode node) + public override void VisitCompoundNameExpression(CompoundNameExpressionSyntaxNode node) { Visit(node.Nodes); } @@ -426,14 +426,14 @@ namespace MApplication 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); diff --git a/Parser/Evaluator.cs b/Parser/Evaluator.cs index ed0bf15..15ac7f5 100644 --- a/Parser/Evaluator.cs +++ b/Parser/Evaluator.cs @@ -43,28 +43,28 @@ namespace Parser { return statement.Kind switch { - TokenKind.ExpressionStatement => - EvaluateExpressionStatement((ExpressionStatementSyntaxNode)statement), - TokenKind.MethodDefinition => - EvaluateMethodDefinition((MethodDefinitionSyntaxNode)statement), TokenKind.AbstractMethodDeclaration => EvaluateAbstractMethodDeclaration((AbstractMethodDeclarationSyntaxNode)statement), - TokenKind.FunctionDeclaration => - EvaluateFunctionDeclaration((FunctionDeclarationSyntaxNode)statement), - TokenKind.SwitchStatement => - EvaluateSwitchStatement((SwitchStatementSyntaxNode)statement), - TokenKind.WhileStatement => - EvaluateWhileStatement((WhileStatementSyntaxNode)statement), - TokenKind.IfStatement => - EvaluateIfStatement((IfStatementSyntaxNode)statement), - TokenKind.ForStatement => - EvaluateForStatement((ForStatementSyntaxNode)statement), - TokenKind.TryCatchStatement => - EvaluateTryCatchStatement((TryCatchStatementSyntaxNode)statement), - TokenKind.EmptyStatement => - EvaluateEmptyStatement((EmptyStatementSyntaxNode)statement), TokenKind.ClassDeclaration => EvaluateClassDeclaration((ClassDeclarationSyntaxNode)statement), + TokenKind.EmptyStatement => + EvaluateEmptyStatement((EmptyStatementSyntaxNode)statement), + TokenKind.ExpressionStatement => + EvaluateExpressionStatement((ExpressionStatementSyntaxNode)statement), + TokenKind.ForStatement => + EvaluateForStatement((ForStatementSyntaxNode)statement), + TokenKind.FunctionDeclaration => + EvaluateFunctionDeclaration((FunctionDeclarationSyntaxNode)statement), + TokenKind.IfStatement => + EvaluateIfStatement((IfStatementSyntaxNode)statement), + TokenKind.ConcreteMethodDeclaration => + EvaluateMethodDefinition((MethodDefinitionSyntaxNode)statement), + TokenKind.SwitchStatement => + EvaluateSwitchStatement((SwitchStatementSyntaxNode)statement), + TokenKind.TryCatchStatement => + EvaluateTryCatchStatement((TryCatchStatementSyntaxNode)statement), + TokenKind.WhileStatement => + EvaluateWhileStatement((WhileStatementSyntaxNode)statement), _ => throw new NotImplementedException($"Invalid statement kind '{statement.Kind}'."), }; } @@ -128,52 +128,59 @@ namespace Parser { return expression.Kind switch { - TokenKind.Lambda => - EvaluateLambda((LambdaSyntaxNode)expression), - TokenKind.AssignmentExpression => - EvaluateAssignmentExpression((AssignmentExpressionSyntaxNode)expression), - TokenKind.EmptyExpression => - EvaluateEmptyExpression((EmptyExpressionSyntaxNode)expression), - TokenKind.UnaryPrefixOperationExpression => - EvaluateUnaryPrefixOperationExpression((UnaryPrefixOperationExpressionSyntaxNode)expression), - TokenKind.CompoundName => - EvaluateCompoundName((CompoundNameSyntaxNode)expression), - TokenKind.BinaryOperation => - EvaluateBinaryOperation((BinaryOperationExpressionSyntaxNode)expression), - TokenKind.IdentifierName => - EvaluateIdentifierName((IdentifierNameSyntaxNode)expression), - TokenKind.NumberLiteralExpression => - EvaluateNumberLiteralExpression((NumberLiteralSyntaxNode)expression), - TokenKind.StringLiteralExpression => - EvaluateStringLiteralExpression((StringLiteralSyntaxNode)expression), - TokenKind.DoubleQuotedStringLiteralExpression => - EvaluateDoubleQuotedStringLiteralExpression((DoubleQuotedStringLiteralSyntaxNode)expression), - TokenKind.UnquotedStringLiteralExpression => - EvaluateUnquotedStringLiteralExpression((UnquotedStringLiteralSyntaxNode)expression), TokenKind.ArrayLiteralExpression => EvaluateArrayLiteralExpression((ArrayLiteralExpressionSyntaxNode)expression), + TokenKind.AssignmentExpression => + EvaluateAssignmentExpression((AssignmentExpressionSyntaxNode)expression), + TokenKind.BinaryOperationExpression => + EvaluateBinaryOperation((BinaryOperationExpressionSyntaxNode)expression), + TokenKind.CellArrayElementAccessExpression => + EvaluateCellArrayElementAccess((CellArrayElementAccessExpressionSyntaxNode)expression), TokenKind.CellArrayLiteralExpression => EvaluateCellArrayLiteralExpression((CellArrayLiteralExpressionSyntaxNode)expression), - TokenKind.ParenthesizedExpression => - EvaluateNamedFunctionHandle((NamedFunctionHandleSyntaxNode)expression), - TokenKind.CellArrayElementAccess => - EvaluateCellArrayElementAccess((CellArrayElementAccessExpressionSyntaxNode)expression), - TokenKind.FunctionCall => + TokenKind.ClassInvokationExpression => + EvaluateClassInvokation((BaseClassInvokationSyntaxNode)expression), + TokenKind.CommandExpression => + EvaluateCommand((CommandExpressionSyntaxNode)expression), + TokenKind.CompoundNameExpression => + EvaluateCompoundName((CompoundNameExpressionSyntaxNode)expression), + TokenKind.DoubleQuotedStringLiteralExpression => + EvaluateDoubleQuotedStringLiteralExpression((DoubleQuotedStringLiteralSyntaxNode)expression), + TokenKind.EmptyExpression => + EvaluateEmptyExpression((EmptyExpressionSyntaxNode)expression), + TokenKind.FunctionCallExpression => EvaluateFunctionCall((FunctionCallExpressionSyntaxNode)expression), - TokenKind.MemberAccess => + TokenKind.IdentifierNameExpression => + EvaluateIdentifierNameExpression((IdentifierNameExpressionSyntaxNode)expression), + TokenKind.IndirectMemberAccessExpression => + EvaluateIndirectMemberAccess((IndirectMemberAccessSyntaxNode)expression), + TokenKind.LambdaExpression => + EvaluateLambdaExpression((LambdaExpressionSyntaxNode)expression), + TokenKind.MemberAccessExpression => EvaluateMemberAccess((MemberAccessSyntaxNode)expression), + TokenKind.NamedFunctionHandleExpression => + EvaluateNamedFunctionHandleExpression((NamedFunctionHandleExpressionSyntaxNode)expression), + TokenKind.NumberLiteralExpression => + EvaluateNumberLiteralExpression((NumberLiteralSyntaxNode)expression), + TokenKind.ParenthesizedExpression => + EvaluateParenthesizedExpression((ParenthesizedExpressionSyntaxNode)expression), + TokenKind.StringLiteralExpression => + EvaluateStringLiteralExpression((StringLiteralSyntaxNode)expression), + TokenKind.UnaryPrefixOperationExpression => + EvaluateUnaryPrefixOperationExpression((UnaryPrefixOperationExpressionSyntaxNode)expression), TokenKind.UnaryPostfixOperationExpression => EvaluateUnaryPostfixOperationExpression((UnaryPostixOperationExpressionSyntaxNode)expression), - TokenKind.IndirectMemberAccess => - EvaluateIndirectMemberAccess((IndirectMemberAccessSyntaxNode)expression), - TokenKind.Command => - EvaluateCommand((CommandExpressionSyntaxNode)expression), - TokenKind.ClassInvokation => - EvaluateClassInvokation((BaseClassInvokationSyntaxNode)expression), + TokenKind.UnquotedStringLiteralExpression => + EvaluateUnquotedStringLiteralExpression((UnquotedStringLiteralSyntaxNode)expression), _ => throw new NotImplementedException($"Invalid expression kind '{expression.Kind}'."), }; } + private MObject? EvaluateParenthesizedExpression(ParenthesizedExpressionSyntaxNode expression) + { + throw new NotImplementedException(); + } + private MObject? EvaluateClassInvokation(BaseClassInvokationSyntaxNode expression) { throw new NotImplementedException(); @@ -239,7 +246,7 @@ namespace Parser throw new NotImplementedException(); } - private MObject? EvaluateIdentifierName(IdentifierNameSyntaxNode expression) + private MObject? EvaluateIdentifierNameExpression(IdentifierNameExpressionSyntaxNode expression) { throw new NotImplementedException(); } @@ -249,7 +256,7 @@ namespace Parser throw new NotImplementedException(); } - private MObject? EvaluateCompoundName(CompoundNameSyntaxNode expression) + private MObject? EvaluateCompoundName(CompoundNameExpressionSyntaxNode expression) { throw new NotImplementedException(); } @@ -269,12 +276,12 @@ namespace Parser throw new NotImplementedException(); } - private MObject? EvaluateLambda(LambdaSyntaxNode expression) + private MObject? EvaluateLambdaExpression(LambdaExpressionSyntaxNode expression) { throw new NotImplementedException(); } - private MObject? EvaluateNamedFunctionHandle(NamedFunctionHandleSyntaxNode expression) + private MObject? EvaluateNamedFunctionHandleExpression(NamedFunctionHandleExpressionSyntaxNode expression) { throw new NotImplementedException(); } diff --git a/Parser/Internal/MParserGreen.cs b/Parser/Internal/MParserGreen.cs index 1591bb2..bc87a9b 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 @@ -180,7 +180,7 @@ namespace Parser.Internal else { var identifierToken = EatToken(TokenKind.IdentifierToken); - builder.Add(Factory.IdentifierNameSyntax(identifierToken)); + builder.Add(Factory.IdentifierNameExpressionSyntax(identifierToken)); } } @@ -329,7 +329,7 @@ namespace Parser.Internal break; default: var id = EatToken(TokenKind.IdentifierToken); - expression = Factory.IdentifierNameSyntax(id); + expression = Factory.IdentifierNameExpressionSyntax(id); break; } @@ -377,7 +377,7 @@ namespace Parser.Internal closingBracket); break; case TokenKind.DotToken: // member access - if (expression is IdentifierNameSyntaxNode + if (expression is IdentifierNameExpressionSyntaxNode || expression is MemberAccessSyntaxNode || expression is FunctionCallExpressionSyntaxNode || expression is CellArrayElementAccessExpressionSyntaxNode) @@ -414,7 +414,7 @@ namespace Parser.Internal private CommandExpressionSyntaxNode ParseCommandExpression(ExpressionSyntaxNode expression) { - if (expression is IdentifierNameSyntaxNode idNameNode) + if (expression is IdentifierNameExpressionSyntaxNode idNameNode) { var builder = new SyntaxListBuilder(); while (CurrentToken.Kind == TokenKind.UnquotedStringLiteralToken) @@ -434,7 +434,7 @@ namespace Parser.Internal private BaseClassInvokationSyntaxNode ParseBaseClassInvokation(ExpressionSyntaxNode expression) { - if (expression is IdentifierNameSyntaxNode methodName + if (expression is IdentifierNameExpressionSyntaxNode methodName && !expression.TrailingTrivia.Any()) { var atToken = EatToken(); @@ -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) { @@ -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}."); } @@ -866,7 +866,7 @@ namespace Parser.Internal private AttributeSyntaxNode ParseAttribute() { - var name = Factory.IdentifierNameSyntax(EatToken(TokenKind.IdentifierToken)); + var name = Factory.IdentifierNameExpressionSyntax(EatToken(TokenKind.IdentifierToken)); var assignment = ParseAttributeAssignment(); return Factory.AttributeSyntax(name, assignment); } @@ -1023,7 +1023,7 @@ namespace Parser.Internal private EnumerationItemSyntaxNode ParseEnumerationItem() { - var name = Factory.IdentifierNameSyntax(EatToken()); + var name = Factory.IdentifierNameExpressionSyntax(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 = Factory.IdentifierNameExpressionSyntax(EatToken(TokenKind.IdentifierToken)); BaseClassListSyntaxNode? baseClassList = null; if (CurrentToken.Kind == TokenKind.LessToken) { diff --git a/Parser/Internal/SyntaxFactory.Generated.cs b/Parser/Internal/SyntaxFactory.Generated.cs index fe84e55..389f615 100644 --- a/Parser/Internal/SyntaxFactory.Generated.cs +++ b/Parser/Internal/SyntaxFactory.Generated.cs @@ -93,19 +93,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,9 +113,9 @@ 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) @@ -178,7 +178,7 @@ namespace Parser.Internal return new IndirectMemberAccessSyntaxNode(openingBracket, expression, closingBracket); } - public CommandExpressionSyntaxNode CommandExpressionSyntax(IdentifierNameSyntaxNode commandName, SyntaxList arguments) + public CommandExpressionSyntaxNode CommandExpressionSyntax(IdentifierNameExpressionSyntaxNode commandName, SyntaxList arguments) { return new CommandExpressionSyntaxNode(commandName, arguments); } @@ -193,7 +193,7 @@ namespace Parser.Internal return new AttributeAssignmentSyntaxNode(assignmentSign, value); } - public AttributeSyntaxNode AttributeSyntax(IdentifierNameSyntaxNode name, AttributeAssignmentSyntaxNode? assignment) + public AttributeSyntaxNode AttributeSyntax(IdentifierNameExpressionSyntaxNode name, AttributeAssignmentSyntaxNode? assignment) { return new AttributeSyntaxNode(name, assignment); } @@ -203,12 +203,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 MethodDefinitionSyntaxNode MethodDefinitionSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword) { return new MethodDefinitionSyntaxNode(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 +228,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, IdentifierNameExpressionSyntaxNode className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword) { return new ClassDeclarationSyntaxNode(classdefKeyword, attributes, className, baseClassList, nodes, endKeyword); } @@ -238,7 +238,7 @@ namespace Parser.Internal return new EnumerationItemValueSyntaxNode(openingBracket, values, closingBracket); } - public EnumerationItemSyntaxNode EnumerationItemSyntax(IdentifierNameSyntaxNode name, EnumerationItemValueSyntaxNode? values, SyntaxList commas) + public EnumerationItemSyntaxNode EnumerationItemSyntax(IdentifierNameExpressionSyntaxNode 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..c5cf33c 100644 --- a/Parser/Internal/SyntaxNode.Generated.cs +++ b/Parser/Internal/SyntaxNode.Generated.cs @@ -890,17 +890,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 +909,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 +928,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 +941,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 +952,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 +971,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 +987,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 +1000,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 +1024,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 +1035,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 +1067,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 +1086,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) @@ -1407,7 +1407,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 +1420,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 +1460,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 +1473,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); @@ -1512,7 +1512,7 @@ namespace Parser.Internal internal readonly SyntaxNode _leftOperand; internal readonly SyntaxToken _dot; internal readonly SyntaxNode _rightOperand; - internal MemberAccessSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand): base(TokenKind.MemberAccess) + internal MemberAccessSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand): base(TokenKind.MemberAccessExpression) { Slots = 3; this.AdjustWidth(leftOperand); @@ -1523,7 +1523,7 @@ namespace Parser.Internal _rightOperand = rightOperand; } - internal MemberAccessSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand, TokenDiagnostic[] diagnostics): base(TokenKind.MemberAccess, diagnostics) + internal MemberAccessSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand, TokenDiagnostic[] diagnostics): base(TokenKind.MemberAccessExpression, diagnostics) { Slots = 3; this.AdjustWidth(leftOperand); @@ -1603,7 +1603,7 @@ namespace Parser.Internal internal readonly SyntaxToken _openingBracket; internal readonly ExpressionSyntaxNode _expression; internal readonly SyntaxToken _closingBracket; - internal IndirectMemberAccessSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket): base(TokenKind.IndirectMemberAccess) + internal IndirectMemberAccessSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket): base(TokenKind.IndirectMemberAccessExpression) { Slots = 3; this.AdjustWidth(openingBracket); @@ -1614,7 +1614,7 @@ namespace Parser.Internal _closingBracket = closingBracket; } - internal IndirectMemberAccessSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket, TokenDiagnostic[] diagnostics): base(TokenKind.IndirectMemberAccess, diagnostics) + internal IndirectMemberAccessSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket, TokenDiagnostic[] diagnostics): base(TokenKind.IndirectMemberAccessExpression, diagnostics) { Slots = 3; this.AdjustWidth(openingBracket); @@ -1648,9 +1648,9 @@ namespace Parser.Internal internal class CommandExpressionSyntaxNode : ExpressionSyntaxNode { - internal readonly IdentifierNameSyntaxNode _commandName; + internal readonly IdentifierNameExpressionSyntaxNode _commandName; internal readonly SyntaxList _arguments; - internal CommandExpressionSyntaxNode(IdentifierNameSyntaxNode commandName, SyntaxList arguments): base(TokenKind.Command) + internal CommandExpressionSyntaxNode(IdentifierNameExpressionSyntaxNode commandName, SyntaxList arguments): base(TokenKind.CommandExpression) { Slots = 2; this.AdjustWidth(commandName); @@ -1659,7 +1659,7 @@ namespace Parser.Internal _arguments = arguments; } - internal CommandExpressionSyntaxNode(IdentifierNameSyntaxNode commandName, SyntaxList arguments, TokenDiagnostic[] diagnostics): base(TokenKind.Command, diagnostics) + internal CommandExpressionSyntaxNode(IdentifierNameExpressionSyntaxNode commandName, SyntaxList arguments, TokenDiagnostic[] diagnostics): base(TokenKind.CommandExpression, diagnostics) { Slots = 2; this.AdjustWidth(commandName); @@ -1694,7 +1694,7 @@ namespace Parser.Internal internal readonly ExpressionSyntaxNode _methodName; internal readonly SyntaxToken _atSign; internal readonly ExpressionSyntaxNode _baseClassNameAndArguments; - internal BaseClassInvokationSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments): base(TokenKind.ClassInvokation) + internal BaseClassInvokationSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments): base(TokenKind.ClassInvokationExpression) { Slots = 3; this.AdjustWidth(methodName); @@ -1705,7 +1705,7 @@ namespace Parser.Internal _baseClassNameAndArguments = baseClassNameAndArguments; } - internal BaseClassInvokationSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments, TokenDiagnostic[] diagnostics): base(TokenKind.ClassInvokation, diagnostics) + internal BaseClassInvokationSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments, TokenDiagnostic[] diagnostics): base(TokenKind.ClassInvokationExpression, diagnostics) { Slots = 3; this.AdjustWidth(methodName); @@ -1782,9 +1782,9 @@ namespace Parser.Internal internal class AttributeSyntaxNode : SyntaxNode { - internal readonly IdentifierNameSyntaxNode _name; + internal readonly IdentifierNameExpressionSyntaxNode _name; internal readonly AttributeAssignmentSyntaxNode? _assignment; - internal AttributeSyntaxNode(IdentifierNameSyntaxNode name, AttributeAssignmentSyntaxNode? assignment): base(TokenKind.Attribute) + internal AttributeSyntaxNode(IdentifierNameExpressionSyntaxNode name, AttributeAssignmentSyntaxNode? assignment): base(TokenKind.Attribute) { Slots = 2; this.AdjustWidth(name); @@ -1793,7 +1793,7 @@ namespace Parser.Internal _assignment = assignment; } - internal AttributeSyntaxNode(IdentifierNameSyntaxNode name, AttributeAssignmentSyntaxNode? assignment, TokenDiagnostic[] diagnostics): base(TokenKind.Attribute, diagnostics) + internal AttributeSyntaxNode(IdentifierNameExpressionSyntaxNode name, AttributeAssignmentSyntaxNode? assignment, TokenDiagnostic[] diagnostics): base(TokenKind.Attribute, diagnostics) { Slots = 2; this.AdjustWidth(name); @@ -1875,12 +1875,12 @@ namespace Parser.Internal { 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 EndKeywordSyntaxNode? _endKeyword; - internal MethodDefinitionSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.MethodDefinition) + internal MethodDefinitionSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.ConcreteMethodDeclaration) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -1899,7 +1899,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 MethodDefinitionSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ConcreteMethodDeclaration, diagnostics) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -1942,9 +1942,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 +1955,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 +2140,11 @@ namespace Parser.Internal { internal readonly SyntaxToken _classdefKeyword; internal readonly AttributeListSyntaxNode? _attributes; - internal readonly IdentifierNameSyntaxNode _className; + internal readonly IdentifierNameExpressionSyntaxNode _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, IdentifierNameExpressionSyntaxNode className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword): base(TokenKind.ClassDeclaration) { Slots = 6; this.AdjustWidth(classdefKeyword); @@ -2161,7 +2161,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, IdentifierNameExpressionSyntaxNode className, BaseClassListSyntaxNode? baseClassList, SyntaxList nodes, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ClassDeclaration, diagnostics) { Slots = 6; this.AdjustWidth(classdefKeyword); @@ -2249,10 +2249,10 @@ namespace Parser.Internal internal class EnumerationItemSyntaxNode : SyntaxNode { - internal readonly IdentifierNameSyntaxNode _name; + internal readonly IdentifierNameExpressionSyntaxNode _name; internal readonly EnumerationItemValueSyntaxNode? _values; internal readonly SyntaxList _commas; - internal EnumerationItemSyntaxNode(IdentifierNameSyntaxNode name, EnumerationItemValueSyntaxNode? values, SyntaxList commas): base(TokenKind.EnumerationItem) + internal EnumerationItemSyntaxNode(IdentifierNameExpressionSyntaxNode name, EnumerationItemValueSyntaxNode? values, SyntaxList commas): base(TokenKind.EnumerationItem) { Slots = 3; this.AdjustWidth(name); @@ -2263,7 +2263,7 @@ namespace Parser.Internal _commas = commas; } - internal EnumerationItemSyntaxNode(IdentifierNameSyntaxNode name, EnumerationItemValueSyntaxNode? values, SyntaxList commas, TokenDiagnostic[] diagnostics): base(TokenKind.EnumerationItem, diagnostics) + internal EnumerationItemSyntaxNode(IdentifierNameExpressionSyntaxNode 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/SyntaxGenerator/input.xml b/Parser/SyntaxDefinition.xml similarity index 90% rename from SyntaxGenerator/input.xml rename to Parser/SyntaxDefinition.xml index 09dd3fe..7c2b538 100644 --- a/SyntaxGenerator/input.xml +++ b/Parser/SyntaxDefinition.xml @@ -95,24 +95,24 @@ - + - + - + - + - + - + @@ -142,19 +142,19 @@ - + - + - + @@ -163,16 +163,16 @@ - + - - + + - + @@ -182,7 +182,7 @@ - + @@ -190,10 +190,10 @@ - + - + @@ -201,7 +201,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -234,7 +234,7 @@ - + diff --git a/Parser/SyntaxNode.Generated.cs b/Parser/SyntaxNode.Generated.cs index 105fac7..96c114e 100644 --- a/Parser/SyntaxNode.Generated.cs +++ b/Parser/SyntaxNode.Generated.cs @@ -941,10 +941,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 +969,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 +984,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 +1009,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 +1025,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 +1059,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitLambda(this); + visitor.VisitLambdaExpression(this); } } @@ -1113,9 +1113,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 +1123,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,7 +1139,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitIdentifierName(this); + visitor.VisitIdentifierNameExpression(this); } } @@ -1669,12 +1669,12 @@ namespace Parser { } - public IdentifierNameSyntaxNode CommandName + public IdentifierNameExpressionSyntaxNode 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 red is null ? throw new System.Exception("commandName cannot be null.") : (IdentifierNameExpressionSyntaxNode)red; } } @@ -1801,12 +1801,12 @@ namespace Parser { } - public IdentifierNameSyntaxNode Name + public IdentifierNameExpressionSyntaxNode 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 red is null ? throw new System.Exception("name cannot be null.") : (IdentifierNameExpressionSyntaxNode)red; } } @@ -1912,12 +1912,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; } } @@ -1991,12 +1991,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; } } @@ -2216,12 +2216,12 @@ namespace Parser } } - public IdentifierNameSyntaxNode ClassName + public IdentifierNameExpressionSyntaxNode ClassName { get { var red = this.GetRed(ref this._className!, 2); - return red is null ? throw new System.Exception("className cannot be null.") : (IdentifierNameSyntaxNode)red; + return red is null ? throw new System.Exception("className cannot be null.") : (IdentifierNameExpressionSyntaxNode)red; } } @@ -2316,12 +2316,12 @@ namespace Parser { } - public IdentifierNameSyntaxNode Name + public IdentifierNameExpressionSyntaxNode 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 red is null ? throw new System.Exception("name cannot be null.") : (IdentifierNameExpressionSyntaxNode)red; } } 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/SyntaxVisitor.Generated.cs b/Parser/SyntaxVisitor.Generated.cs index 3ee82f6..b16d17b 100644 --- a/Parser/SyntaxVisitor.Generated.cs +++ b/Parser/SyntaxVisitor.Generated.cs @@ -93,17 +93,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,7 +113,7 @@ namespace Parser DefaultVisit(node); } - public virtual void VisitIdentifierName(IdentifierNameSyntaxNode node) + public virtual void VisitIdentifierNameExpression(IdentifierNameExpressionSyntaxNode node) { DefaultVisit(node); } diff --git a/Parser/TokenKind.cs b/Parser/TokenKind.cs index 52e455c..c1b403e 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,54 @@ 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, + + // 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 +181,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 +313,7 @@ PropertiesList, // < BaseClass, AnotherBaseClass BaseClassList, - // classdef MyClass < BaseClass, AnotherBaseClass - // properties - // y - // end - // methods - // <...> - // end - // end - ClassDeclaration, + // (1) EnumerationItemValue, // One (1) @@ -265,8 +323,6 @@ // Two (2) // end EnumerationList, - // result = abstractMethod(object) - AbstractMethodDeclaration, // events // ToggleSomething // end 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."); From df0cd4dea31644c9defa5af7e965bec8d0c2dcb4 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Tue, 14 Jul 2020 14:47:15 +0200 Subject: [PATCH 03/12] Unpack identifier name syntax where appropriate --- ConsoleDemo/PrettyPrinter.cs | 8 ++-- MApplication/ColoringVisitor.cs | 8 ++-- Parser/Internal/MParserGreen.cs | 8 ++-- Parser/Internal/SyntaxFactory.Generated.cs | 8 ++-- Parser/Internal/SyntaxNode.Generated.cs | 24 ++++++------ Parser/SyntaxDefinition.xml | 8 ++-- Parser/SyntaxNode.Generated.cs | 44 +++++++++------------- 7 files changed, 50 insertions(+), 58 deletions(-) diff --git a/ConsoleDemo/PrettyPrinter.cs b/ConsoleDemo/PrettyPrinter.cs index 0cbf492..c5221f7 100644 --- a/ConsoleDemo/PrettyPrinter.cs +++ b/ConsoleDemo/PrettyPrinter.cs @@ -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); @@ -355,7 +355,7 @@ namespace ProjectConsole public override void VisitCommandExpression(CommandExpressionSyntaxNode node) { - Visit(node.CommandName); + OutputIdentifier(node.CommandName); Visit(node.Arguments); } @@ -391,7 +391,7 @@ namespace ProjectConsole public override void VisitAttribute(AttributeSyntaxNode node) { - Visit(node.Name); + OutputIdentifier(node.Name); Visit(node.Assignment); } @@ -454,7 +454,7 @@ namespace ProjectConsole public override void VisitEnumerationItem(EnumerationItemSyntaxNode node) { - Visit(node.Name); + OutputIdentifier(node.Name); Visit(node.Values); Visit(node.Commas); } diff --git a/MApplication/ColoringVisitor.cs b/MApplication/ColoringVisitor.cs index 28aa2f6..3504b19 100644 --- a/MApplication/ColoringVisitor.cs +++ b/MApplication/ColoringVisitor.cs @@ -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); @@ -302,7 +302,7 @@ namespace MApplication public override void VisitCommandExpression(CommandExpressionSyntaxNode node) { - Visit(node.CommandName); + AddToken(node.CommandName, _scheme.Identifier); Visit(node.Arguments); } @@ -338,7 +338,7 @@ namespace MApplication public override void VisitAttribute(AttributeSyntaxNode node) { - Visit(node.Name); + AddToken(node.Name, _scheme.Identifier); Visit(node.Assignment); } @@ -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); } diff --git a/Parser/Internal/MParserGreen.cs b/Parser/Internal/MParserGreen.cs index bc87a9b..44587c8 100644 --- a/Parser/Internal/MParserGreen.cs +++ b/Parser/Internal/MParserGreen.cs @@ -422,7 +422,7 @@ namespace Parser.Internal builder.Add(Factory.UnquotedStringLiteralSyntax(EatToken())); } - return Factory.CommandExpressionSyntax(idNameNode, builder.ToList()); + return Factory.CommandExpressionSyntax(idNameNode._name, builder.ToList()); } if (expression is null) @@ -866,7 +866,7 @@ namespace Parser.Internal private AttributeSyntaxNode ParseAttribute() { - var name = Factory.IdentifierNameExpressionSyntax(EatToken(TokenKind.IdentifierToken)); + var name = EatToken(TokenKind.IdentifierToken); var assignment = ParseAttributeAssignment(); return Factory.AttributeSyntax(name, assignment); } @@ -1023,7 +1023,7 @@ namespace Parser.Internal private EnumerationItemSyntaxNode ParseEnumerationItem() { - var name = Factory.IdentifierNameExpressionSyntax(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.IdentifierNameExpressionSyntax(EatToken(TokenKind.IdentifierToken)); + var className = EatToken(TokenKind.IdentifierToken); BaseClassListSyntaxNode? baseClassList = null; if (CurrentToken.Kind == TokenKind.LessToken) { diff --git a/Parser/Internal/SyntaxFactory.Generated.cs b/Parser/Internal/SyntaxFactory.Generated.cs index 389f615..393bcbe 100644 --- a/Parser/Internal/SyntaxFactory.Generated.cs +++ b/Parser/Internal/SyntaxFactory.Generated.cs @@ -178,7 +178,7 @@ namespace Parser.Internal return new IndirectMemberAccessSyntaxNode(openingBracket, expression, closingBracket); } - public CommandExpressionSyntaxNode CommandExpressionSyntax(IdentifierNameExpressionSyntaxNode commandName, SyntaxList arguments) + public CommandExpressionSyntaxNode CommandExpressionSyntax(SyntaxToken commandName, SyntaxList arguments) { return new CommandExpressionSyntaxNode(commandName, arguments); } @@ -193,7 +193,7 @@ namespace Parser.Internal return new AttributeAssignmentSyntaxNode(assignmentSign, value); } - public AttributeSyntaxNode AttributeSyntax(IdentifierNameExpressionSyntaxNode name, AttributeAssignmentSyntaxNode? assignment) + public AttributeSyntaxNode AttributeSyntax(SyntaxToken name, AttributeAssignmentSyntaxNode? assignment) { return new AttributeSyntaxNode(name, assignment); } @@ -228,7 +228,7 @@ namespace Parser.Internal return new BaseClassListSyntaxNode(lessSign, baseClasses); } - public ClassDeclarationSyntaxNode ClassDeclarationSyntax(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, IdentifierNameExpressionSyntaxNode 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 +238,7 @@ namespace Parser.Internal return new EnumerationItemValueSyntaxNode(openingBracket, values, closingBracket); } - public EnumerationItemSyntaxNode EnumerationItemSyntax(IdentifierNameExpressionSyntaxNode 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 c5cf33c..fcf0d13 100644 --- a/Parser/Internal/SyntaxNode.Generated.cs +++ b/Parser/Internal/SyntaxNode.Generated.cs @@ -1648,9 +1648,9 @@ namespace Parser.Internal internal class CommandExpressionSyntaxNode : ExpressionSyntaxNode { - internal readonly IdentifierNameExpressionSyntaxNode _commandName; + internal readonly SyntaxToken _commandName; internal readonly SyntaxList _arguments; - internal CommandExpressionSyntaxNode(IdentifierNameExpressionSyntaxNode commandName, SyntaxList arguments): base(TokenKind.CommandExpression) + internal CommandExpressionSyntaxNode(SyntaxToken commandName, SyntaxList arguments): base(TokenKind.CommandExpression) { Slots = 2; this.AdjustWidth(commandName); @@ -1659,7 +1659,7 @@ namespace Parser.Internal _arguments = arguments; } - internal CommandExpressionSyntaxNode(IdentifierNameExpressionSyntaxNode commandName, SyntaxList arguments, TokenDiagnostic[] diagnostics): base(TokenKind.CommandExpression, diagnostics) + internal CommandExpressionSyntaxNode(SyntaxToken commandName, SyntaxList arguments, TokenDiagnostic[] diagnostics): base(TokenKind.CommandExpression, diagnostics) { Slots = 2; this.AdjustWidth(commandName); @@ -1782,9 +1782,9 @@ namespace Parser.Internal internal class AttributeSyntaxNode : SyntaxNode { - internal readonly IdentifierNameExpressionSyntaxNode _name; + internal readonly SyntaxToken _name; internal readonly AttributeAssignmentSyntaxNode? _assignment; - internal AttributeSyntaxNode(IdentifierNameExpressionSyntaxNode name, AttributeAssignmentSyntaxNode? assignment): base(TokenKind.Attribute) + internal AttributeSyntaxNode(SyntaxToken name, AttributeAssignmentSyntaxNode? assignment): base(TokenKind.Attribute) { Slots = 2; this.AdjustWidth(name); @@ -1793,7 +1793,7 @@ namespace Parser.Internal _assignment = assignment; } - internal AttributeSyntaxNode(IdentifierNameExpressionSyntaxNode 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); @@ -2140,11 +2140,11 @@ namespace Parser.Internal { internal readonly SyntaxToken _classdefKeyword; internal readonly AttributeListSyntaxNode? _attributes; - internal readonly IdentifierNameExpressionSyntaxNode _className; + internal readonly SyntaxToken _className; internal readonly BaseClassListSyntaxNode? _baseClassList; internal readonly SyntaxList _nodes; internal readonly SyntaxToken _endKeyword; - internal ClassDeclarationSyntaxNode(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, IdentifierNameExpressionSyntaxNode 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 +2161,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal ClassDeclarationSyntaxNode(SyntaxToken classdefKeyword, AttributeListSyntaxNode? attributes, IdentifierNameExpressionSyntaxNode 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 +2249,10 @@ namespace Parser.Internal internal class EnumerationItemSyntaxNode : SyntaxNode { - internal readonly IdentifierNameExpressionSyntaxNode _name; + internal readonly SyntaxToken _name; internal readonly EnumerationItemValueSyntaxNode? _values; internal readonly SyntaxList _commas; - internal EnumerationItemSyntaxNode(IdentifierNameExpressionSyntaxNode 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 +2263,7 @@ namespace Parser.Internal _commas = commas; } - internal EnumerationItemSyntaxNode(IdentifierNameExpressionSyntaxNode 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/SyntaxDefinition.xml b/Parser/SyntaxDefinition.xml index 7c2b538..81c1532 100644 --- a/Parser/SyntaxDefinition.xml +++ b/Parser/SyntaxDefinition.xml @@ -169,7 +169,7 @@ - + @@ -182,7 +182,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -234,7 +234,7 @@ - + diff --git a/Parser/SyntaxNode.Generated.cs b/Parser/SyntaxNode.Generated.cs index 96c114e..3ac4d57 100644 --- a/Parser/SyntaxNode.Generated.cs +++ b/Parser/SyntaxNode.Generated.cs @@ -1663,18 +1663,16 @@ namespace Parser public class CommandExpressionSyntaxNode : ExpressionSyntaxNode { - private SyntaxNode? _commandName; private SyntaxNode? _arguments; internal CommandExpressionSyntaxNode(SyntaxNode parent, Internal.GreenNode green, int position): base(parent, green, position) { } - public IdentifierNameExpressionSyntaxNode 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.") : (IdentifierNameExpressionSyntaxNode)red; + return new SyntaxToken(this, ((Parser.Internal.CommandExpressionSyntaxNode)_green)._commandName, this.GetChildPosition(0)); } } @@ -1691,7 +1689,7 @@ namespace Parser { return i switch { - 0 => GetRed(ref _commandName!, 0), 1 => GetRed(ref _arguments!, 1), _ => null + 1 => GetRed(ref _arguments!, 1), _ => null } ; @@ -1795,18 +1793,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 IdentifierNameExpressionSyntaxNode 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.") : (IdentifierNameExpressionSyntaxNode)red; + return new SyntaxToken(this, ((Parser.Internal.AttributeSyntaxNode)_green)._name, this.GetChildPosition(0)); } } @@ -1823,7 +1819,7 @@ namespace Parser { return i switch { - 0 => GetRed(ref _name!, 0), 1 => GetRed(ref _assignment, 1), _ => null + 1 => GetRed(ref _assignment, 1), _ => null } ; @@ -2184,7 +2180,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 +2194,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 +2219,6 @@ namespace Parser } } - public IdentifierNameExpressionSyntaxNode ClassName - { - get - { - var red = this.GetRed(ref this._className!, 2); - return red is null ? throw new System.Exception("className cannot be null.") : (IdentifierNameExpressionSyntaxNode)red; - } - } - public BaseClassListSyntaxNode? BaseClassList { get @@ -2247,7 +2241,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 +2303,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 IdentifierNameExpressionSyntaxNode 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.") : (IdentifierNameExpressionSyntaxNode)red; + return new SyntaxToken(this, ((Parser.Internal.EnumerationItemSyntaxNode)_green)._name, this.GetChildPosition(0)); } } @@ -2347,7 +2339,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 } ; From 886b897a4c61a3d485c70e54dd4ec71f51b9a08a Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Tue, 14 Jul 2020 18:48:00 +0200 Subject: [PATCH 04/12] Evaluation in REPL --- Parser/CompilationContext.cs | 6 +- Parser/Evaluator.cs | 116 +++++++++++++++++++++++++++--- Parser/Internal/DiagnosticsBag.cs | 12 +++- Parser/Internal/GreenNode.cs | 5 ++ Parser/Internal/MLexerGreen.cs | 35 ++++++++- Parser/Internal/SyntaxToken.cs | 11 ++- Parser/MFunctions/MOperations.cs | 50 +++++++++++++ Parser/Objects/MDoubleNumber.cs | 20 +++++- Parser/Objects/MObject.cs | 4 ++ Parser/SyntaxToken.cs | 2 + Repl/MRepl.cs | 4 +- 11 files changed, 248 insertions(+), 17 deletions(-) create mode 100644 Parser/MFunctions/MOperations.cs diff --git a/Parser/CompilationContext.cs b/Parser/CompilationContext.cs index df3c6fc..b716356 100644 --- a/Parser/CompilationContext.cs +++ b/Parser/CompilationContext.cs @@ -1,7 +1,11 @@ -namespace Parser +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/Evaluator.cs b/Parser/Evaluator.cs index 15ac7f5..8aeaa9a 100644 --- a/Parser/Evaluator.cs +++ b/Parser/Evaluator.cs @@ -1,21 +1,31 @@ using Parser.Internal; +using Parser.MFunctions; using Parser.Objects; using System; +using System.Collections.Generic; using System.Collections.Immutable; namespace Parser { + internal class EvaluationScope + { + public Dictionary Variables { get; } = new Dictionary(); + } + internal class Evaluator { - private SyntaxTree _syntaxTree; - private CompilationContext _context; - private DiagnosticsBag _diagnostics; + private readonly SyntaxTree _syntaxTree; + private readonly CompilationContext _context; + private readonly DiagnosticsBag _diagnostics = new DiagnosticsBag(); + private bool _insideFunction = false; + private readonly Stack _scopeStack = new Stack(); public Evaluator(SyntaxTree syntaxTree, CompilationContext context) { _syntaxTree = syntaxTree; _context = context; - _diagnostics = new DiagnosticsBag(); + var outerScope = new EvaluationScope(); + _scopeStack.Push(outerScope); } internal EvaluationResult Evaluate() @@ -178,7 +188,7 @@ namespace Parser private MObject? EvaluateParenthesizedExpression(ParenthesizedExpressionSyntaxNode expression) { - throw new NotImplementedException(); + return EvaluateExpression(expression.Expression); } private MObject? EvaluateClassInvokation(BaseClassInvokationSyntaxNode expression) @@ -243,17 +253,47 @@ namespace Parser private MObject? EvaluateNumberLiteralExpression(NumberLiteralSyntaxNode expression) { - throw new NotImplementedException(); + return expression.Number.Value is double value + ? MObject.CreateDoubleNumber(value) + : null; } private MObject? EvaluateIdentifierNameExpression(IdentifierNameExpressionSyntaxNode expression) { - throw new NotImplementedException(); + var variableName = expression.Name.Text; + var maybeValue = GetVariableValue(variableName); + if (maybeValue is null) + { + _diagnostics.ReportVariableNotFound( + new TextSpan(expression.Name.Position, expression.Name.Text.Length), + variableName); + } + + return maybeValue; } private MObject? EvaluateBinaryOperation(BinaryOperationExpressionSyntaxNode expression) { - throw new NotImplementedException(); + var left = EvaluateExpression(expression.Lhs); + if (left is null) + { + return null; + } + + var right = EvaluateExpression(expression.Rhs); + if (right is null) + { + return null; + } + + return expression.Operation.Kind switch + { + TokenKind.PlusToken => MOperations.Plus(left, right), + TokenKind.MinusToken => MOperations.Minus(left, right), + TokenKind.StarToken => MOperations.Star(left, right), + TokenKind.SlashToken => MOperations.Slash(left, right), + _ => throw new NotImplementedException($"Binary operation {expression.Operation.Kind} is not implemented."), + }; } private MObject? EvaluateCompoundName(CompoundNameExpressionSyntaxNode expression) @@ -273,9 +313,69 @@ namespace Parser private MObject? EvaluateAssignmentExpression(AssignmentExpressionSyntaxNode expression) { + var rightValue = EvaluateExpression(expression.Rhs); + if (rightValue is null) + { + _diagnostics.ReportCannotEvaluateExpression( + new TextSpan(expression.Rhs.Position, expression.Rhs.Position + expression.Rhs.FullWidth)); + return null; + } + + var left = expression.Lhs; + if (left.Kind == TokenKind.IdentifierNameExpression) + { + var leftIdentifier = (IdentifierNameExpressionSyntaxNode)left; + var variableName = leftIdentifier.Name.Text; + SetVariableValue(variableName, rightValue); + return rightValue; + } + throw new NotImplementedException(); } + private MObject? GetVariableValue(string name) + { + if (_insideFunction) + { + if (_context.Variables.TryGetValue(name, out var globalValue)) + { + return globalValue; + } + + var currentScope = _scopeStack.Peek(); + return currentScope.Variables.TryGetValue(name, out var localValue) ? globalValue : null; + } + else + { + if (_context.Variables.TryGetValue(name, out var globalValue)) + { + return globalValue; + } + + return null; + } + } + + private void SetVariableValue(string name, MObject value) + { + if (_insideFunction) + { + if (_context.Variables.ContainsKey(name)) + { + _context.Variables[name] = value; + } + else + { + var currentScope = _scopeStack.Peek(); + currentScope.Variables[name] = value; + } + } + else + { + _context.Variables[name] = value; + } + } + private MObject? EvaluateLambdaExpression(LambdaExpressionSyntaxNode expression) { throw new NotImplementedException(); diff --git a/Parser/Internal/DiagnosticsBag.cs b/Parser/Internal/DiagnosticsBag.cs index 1dadf31..76f1540 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; @@ -67,6 +68,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 +83,9 @@ namespace Parser.Internal return GetEnumerator(); } + internal void ReportVariableNotFound(TextSpan span, string variableName) + { + Report(span, $"Variable '{variableName}' not found."); + } } } \ 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/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/MFunctions/MOperations.cs b/Parser/MFunctions/MOperations.cs new file mode 100644 index 0000000..7761f19 --- /dev/null +++ b/Parser/MFunctions/MOperations.cs @@ -0,0 +1,50 @@ +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; + } + } +} diff --git a/Parser/Objects/MDoubleNumber.cs b/Parser/Objects/MDoubleNumber.cs index b745a64..bb7f76f 100644 --- a/Parser/Objects/MDoubleNumber.cs +++ b/Parser/Objects/MDoubleNumber.cs @@ -1,6 +1,24 @@ -namespace Parser.Objects +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/MObject.cs b/Parser/Objects/MObject.cs index f84b55d..cda575b 100644 --- a/Parser/Objects/MObject.cs +++ b/Parser/Objects/MObject.cs @@ -2,5 +2,9 @@ { public abstract class MObject { + public static MDoubleNumber CreateDoubleNumber(double value) + { + return MDoubleNumber.Create(value); + } } } \ No newline at end of file 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/Repl/MRepl.cs b/Repl/MRepl.cs index c43e3e8..3edfe38 100644 --- a/Repl/MRepl.cs +++ b/Repl/MRepl.cs @@ -36,7 +36,9 @@ namespace Repl private void Print(string result) { - Console.Write(result); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(result); + Console.ResetColor(); } private string Read() From 0529e87d4371d0132a2639f873ba89fdc072724e Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Tue, 14 Jul 2020 20:12:38 +0200 Subject: [PATCH 05/12] Evaluate char arrays and 'disp' --- Parser/EvaluationScope.cs | 10 ++++++ Parser/Evaluator.cs | 66 ++++++++++++++++++++++++++++++++---- Parser/FunctionSymbol.cs | 12 +++++++ Parser/Objects/MCharArray.cs | 22 ++++++++++++ Parser/Objects/MObject.cs | 5 +++ Solution.sln | 8 ++++- cmi.cmd | 1 + cmi/Program.cs | 47 +++++++++++++++++++++++++ cmi/cmi.csproj | 14 ++++++++ examples/helloworld/hello.m | 3 ++ 10 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 Parser/EvaluationScope.cs create mode 100644 Parser/FunctionSymbol.cs create mode 100644 Parser/Objects/MCharArray.cs create mode 100644 cmi.cmd create mode 100644 cmi/Program.cs create mode 100644 cmi/cmi.csproj create mode 100644 examples/helloworld/hello.m 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 index 8aeaa9a..74a1d6b 100644 --- a/Parser/Evaluator.cs +++ b/Parser/Evaluator.cs @@ -4,14 +4,10 @@ using Parser.Objects; using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; namespace Parser { - internal class EvaluationScope - { - public Dictionary Variables { get; } = new Dictionary(); - } - internal class Evaluator { private readonly SyntaxTree _syntaxTree; @@ -218,7 +214,59 @@ namespace Parser private MObject? EvaluateFunctionCall(FunctionCallExpressionSyntaxNode expression) { - throw new NotImplementedException(); + var arguments = new List(); + var nodes = expression.Nodes.Where(n => n.IsNode).Select(n => (ExpressionSyntaxNode)n.AsNode()!); + var allGood = true; + foreach (var node in nodes) + { + var argument = EvaluateExpression(node); + if (argument is null) + { + _diagnostics.ReportCannotEvaluateExpression( + new TextSpan(node.Position, node.FullWidth)); + allGood = false; + } + else + { + arguments.Add(argument); + } + + } + if (!allGood) + { + return null; + } + + var function = GetFunctionSymbol(expression.FunctionName); + if (function.Name == "disp") + { + return EvaluateDisp(arguments); + } + else + { + throw new NotImplementedException("Functions are not supported."); + } + } + + private MObject? EvaluateDisp(List arguments) + { + if (arguments.Count != 1) + { + throw new NotImplementedException($"Cannot evaluate disp() with {arguments.Count} arguments."); + } + + Console.WriteLine(arguments[0]); + return null; + } + + private FunctionSymbol GetFunctionSymbol(ExpressionSyntaxNode functionName) + { + if (functionName.Kind == TokenKind.IdentifierNameExpression) + { + return new FunctionSymbol(((IdentifierNameExpressionSyntaxNode)functionName).Text); + } + + throw new NotImplementedException($"Unknown function symbol '{functionName.Text}'."); } private MObject? EvaluateCellArrayElementAccess(CellArrayElementAccessExpressionSyntaxNode expression) @@ -248,7 +296,11 @@ namespace Parser private MObject? EvaluateStringLiteralExpression(StringLiteralSyntaxNode expression) { - throw new NotImplementedException(); + return expression.StringToken.Value switch + { + string s => MObject.CreateCharArray(s.ToCharArray()), + _ => null, + }; } private MObject? EvaluateNumberLiteralExpression(NumberLiteralSyntaxNode expression) diff --git a/Parser/FunctionSymbol.cs b/Parser/FunctionSymbol.cs new file mode 100644 index 0000000..eb43cf0 --- /dev/null +++ b/Parser/FunctionSymbol.cs @@ -0,0 +1,12 @@ +namespace Parser +{ + internal class FunctionSymbol + { + public string Name { get; } + + public FunctionSymbol(string name) + { + Name = name; + } + } +} \ 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/MObject.cs b/Parser/Objects/MObject.cs index cda575b..c76d9e6 100644 --- a/Parser/Objects/MObject.cs +++ b/Parser/Objects/MObject.cs @@ -6,5 +6,10 @@ { return MDoubleNumber.Create(value); } + + public static MCharArray CreateCharArray(char[] chars) + { + return MCharArray.Create(chars); + } } } \ No newline at end of file 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/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..ec8f17d --- /dev/null +++ b/cmi/Program.cs @@ -0,0 +1,47 @@ +using Parser; +using System; +using System.IO; + +namespace cmi +{ + class Program + { + static void Main(string[] args) + { + if (args.Length != 1) + { + Console.Error.WriteLine("Usage: cmi "); + } + + var fileName = args[0]; + var text = File.ReadAllText(fileName); + var tree = SyntaxTree.Parse(text); + var compilation = Compilation.Create(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(); + } + } + + var context = new CompilationContext(); + var evaluationResult = compilation.Evaluate(context); + + 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/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..51c6bb1 --- /dev/null +++ b/examples/helloworld/hello.m @@ -0,0 +1,3 @@ +x = 1; +disp(x + 2); +disp('Hello world!'); From 188dca85d84f8c804a8a661a28c66d93e696ba8e Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Tue, 14 Jul 2020 22:45:34 +0200 Subject: [PATCH 06/12] Introduce binding --- ConsoleDemo/DumbWalker.cs | 4 +- ConsoleDemo/PrettyPrinter.cs | 18 +- ConsoleDemo/UsageGathering.cs | 4 +- MApplication/ColoringVisitor.cs | 18 +- Parser/Binding/Binder.cs | 353 +++++++++++++ Parser/Binding/BoundProgram.cs | 20 + Parser/Binding/BoundRoot.cs | 581 +++++++++++++++++++++ Parser/Compilation.cs | 17 +- Parser/Evaluator.cs | 294 +++++------ Parser/Internal/MParserGreen.cs | 30 +- Parser/Internal/SyntaxFactory.Generated.cs | 38 +- Parser/Internal/SyntaxNode.Generated.cs | 96 ++-- Parser/SyntaxDefinition.xml | 20 +- Parser/SyntaxNode.Generated.cs | 74 +-- Parser/SyntaxVisitor.Generated.cs | 18 +- Repl/MRepl.cs | 6 +- Semantics/GetClass.cs | 4 +- examples/helloworld/hello.m | 14 +- 18 files changed, 1290 insertions(+), 319 deletions(-) create mode 100644 Parser/Binding/Binder.cs create mode 100644 Parser/Binding/BoundProgram.cs create mode 100644 Parser/Binding/BoundRoot.cs diff --git a/ConsoleDemo/DumbWalker.cs b/ConsoleDemo/DumbWalker.cs index 7914769..fc3bd64 100644 --- a/ConsoleDemo/DumbWalker.cs +++ b/ConsoleDemo/DumbWalker.cs @@ -159,10 +159,10 @@ 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; } diff --git a/ConsoleDemo/PrettyPrinter.cs b/ConsoleDemo/PrettyPrinter.cs index c5221f7..3dab17f 100644 --- a/ConsoleDemo/PrettyPrinter.cs +++ b/ConsoleDemo/PrettyPrinter.cs @@ -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); @@ -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); } @@ -359,7 +359,7 @@ namespace ProjectConsole 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); @@ -415,7 +415,7 @@ namespace ProjectConsole Visit(node.Nodes); } - public override void VisitDoubleQuotedStringLiteral(DoubleQuotedStringLiteralSyntaxNode node) + public override void VisitDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralExpressionSyntaxNode node) { OutputStringLiteral(node.StringToken); } @@ -472,7 +472,7 @@ namespace ProjectConsole OutputOperator(node.AssignmentSign); } - public override void VisitIndirectMemberAccess(IndirectMemberAccessSyntaxNode node) + public override void VisitIndirectMemberAccessExpression(IndirectMemberAccessExpressionSyntaxNode node) { OutputBracket(node.OpeningBracket); Visit(node.Expression); @@ -492,7 +492,7 @@ namespace ProjectConsole 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/UsageGathering.cs b/ConsoleDemo/UsageGathering.cs index 6665443..9b227a6 100644 --- a/ConsoleDemo/UsageGathering.cs +++ b/ConsoleDemo/UsageGathering.cs @@ -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(); @@ -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 3504b19..ba9e4c7 100644 --- a/MApplication/ColoringVisitor.cs +++ b/MApplication/ColoringVisitor.cs @@ -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); @@ -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); } @@ -306,7 +306,7 @@ namespace MApplication 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); @@ -362,7 +362,7 @@ namespace MApplication Visit(node.Nodes); } - public override void VisitDoubleQuotedStringLiteral(DoubleQuotedStringLiteralSyntaxNode node) + public override void VisitDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralExpressionSyntaxNode node) { AddToken(node.StringToken, _scheme.StringLiteral); } @@ -419,7 +419,7 @@ 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); @@ -439,7 +439,7 @@ namespace MApplication 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/Binding/Binder.cs b/Parser/Binding/Binder.cs new file mode 100644 index 0000000..23fb3fd --- /dev/null +++ b/Parser/Binding/Binder.cs @@ -0,0 +1,353 @@ +using Parser.Internal; +using System; +using System.Collections.Immutable; +using System.Linq; + +namespace Parser.Binding +{ + public class Binder + { + private readonly DiagnosticsBag _diagnostics = new DiagnosticsBag(); + + private BoundRoot BindRoot(RootSyntaxNode node) + { + var boundFile = BindFile(node.File); + return new BoundRoot(node, boundFile); + } + + private BoundFile BindFile(FileSyntaxNode node) + { + var statements = BindStatementList(node.StatementList); + return new BoundFile(node, statements); + } + + private BoundStatement BindStatement(StatementSyntaxNode node) + { + return node.Kind switch + { + TokenKind.AbstractMethodDeclaration => + BindAbstractMethodDeclaration((AbstractMethodDeclarationSyntaxNode)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 = BindStatementList(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 new BoundIfStatement(node, condition, body, elseIfClauses, maybeElseClause); + } + + private BoundElseClause BindElseClause(ElseClause node) + { + var body = BindStatementList(node.Body); + return new BoundElseClause(node, body); + } + + private ImmutableArray BindStatementList(SyntaxNodeOrTokenList list) + { + var builder = ImmutableArray.CreateBuilder(); + var statements = list.Where(s => s.IsNode).Select(s => (StatementSyntaxNode)s.AsNode()!); + foreach (var statement in statements) + { + var boundStatement = BindStatement(statement); + builder.Add(boundStatement); + } + + return builder.ToImmutable(); + } + + 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 = BindStatementList(node.Body); + return new BoundElseIfClause(node, condition, body); + } + + private BoundFunctionDeclaration BindFunctionDeclaration(FunctionDeclarationSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundForStatement BindForStatement(ForStatementSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundExpressionStatement BindExpressionStatement(ExpressionStatementSyntaxNode node) + { + var expression = BindExpression(node.Expression); + return new BoundExpressionStatement(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 new BoundAssignmentExpression(node, left, right); + } + + private BoundBinaryOperationExpression BindBinaryOperationExpression(BinaryOperationExpressionSyntaxNode node) + { + var left = BindExpression(node.Lhs); + var right = BindExpression(node.Rhs); + var op = BindBinaryOperator(node.Operation); + return new BoundBinaryOperationExpression(node, left, op, right); + } + + private BoundBinaryOperator BindBinaryOperator(SyntaxToken token) + { + return BoundBinaryOperator.GetOperator(token.Kind) + ?? throw new Exception($"Unexpected binary operator kind {token.Kind}."); + } + + 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 new BoundFunctionCallExpression(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 new BoundNumberLiteralExpression(node, value); + } + + private BoundParenthesizedExpression BindParenthesizedExpression(ParenthesizedExpressionSyntaxNode node) + { + var expression = BindExpression(node.Expression); + return new BoundParenthesizedExpression(node, expression); + } + + private BoundStringLiteralExpression BindStringLiteralExpression(StringLiteralExpressionSyntaxNode node) + { + var value = (string)node.StringToken.Value!; + return new BoundStringLiteralExpression(node, value); + } + + private BoundUnaryPrefixOperationExpression BindUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode node) + { + throw new NotImplementedException(); + } + + private BoundUnaryPostfixOperationExpression 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(); + } + + public static BoundProgram BindProgram(SyntaxTree syntaxTree) + { + var binder = new Binder(); + var boundRoot = binder.BindRoot(syntaxTree.NullRoot); + return new BoundProgram(boundRoot, binder._diagnostics.ToImmutableArray()); + } + } +} diff --git a/Parser/Binding/BoundProgram.cs b/Parser/Binding/BoundProgram.cs new file mode 100644 index 0000000..b6cfc94 --- /dev/null +++ b/Parser/Binding/BoundProgram.cs @@ -0,0 +1,20 @@ +using Parser.Internal; +using System.Collections.Immutable; + +namespace Parser.Binding +{ + public class BoundProgram + { + public BoundProgram(BoundRoot nullRoot, ImmutableArray diagnostics) + { + NullRoot = nullRoot; + Diagnostics = diagnostics; + } + + public ImmutableArray Diagnostics { get; } + + public BoundRoot NullRoot { get; } + + public BoundFile Root => NullRoot.File; + } +} diff --git a/Parser/Binding/BoundRoot.cs b/Parser/Binding/BoundRoot.cs new file mode 100644 index 0000000..b800a7e --- /dev/null +++ b/Parser/Binding/BoundRoot.cs @@ -0,0 +1,581 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace Parser.Binding +{ + public enum BoundNodeKind + { + Root, + File, + + // Statements + + AbstractMethodDeclaration, + ClassDeclaration, + ConcreteMethodDeclaration, + EmptyStatement, + ExpressionStatement, + ForStatement, + FunctionDeclaration, + IfStatement, + SwitchStatement, + TryCatchStatement, + WhileStatement, + + // Expressions + + ArrayLiteralExpression, + AssignmentExpression, + BinaryOperationExpression, + CellArrayElementAccessExpression, + CellArrayLiteralExpression, + ClassInvokationExpression, + CommandExpression, + CompoundNameExpression, + DoubleQuotedStringLiteralExpression, + EmptyExpression, + FunctionCallExpression, + IdentifierNameExpression, + IndirectMemberAccessExpression, + LambdaExpression, + MemberAccessExpression, + NamedFunctionHandleExpression, + NumberLiteralExpression, + ParenthesizedExpression, + StringLiteralExpression, + UnaryPrefixOperationExpression, + UnaryPostfixOperationExpression, + UnquotedStringLiteralExpression, + + // Parts + ElseIfClause, + ElseClause + } + + 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, + } + + public abstract class BoundNode + { + public BoundNode(SyntaxNode syntax) + { + Syntax = syntax; + } + + public SyntaxNode Syntax { get; } + public abstract BoundNodeKind Kind { get; } + } + + 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, ImmutableArray statements) + : base(syntax) + { + Statements = statements; + } + + public ImmutableArray Statements { 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 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 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) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.FunctionDeclaration; + } + + public class BoundIfStatement : BoundStatement + { + public BoundIfStatement(SyntaxNode syntax, BoundExpression condition, ImmutableArray body, IEnumerable elseIfClauses, BoundElseClause? elseClause) + : base(syntax) + { + Condition = condition; + Body = body; + ElseIfClauses = elseIfClauses; + ElseClause = elseClause; + } + + public BoundExpression Condition { get; } + public ImmutableArray Body { get; } + public IEnumerable ElseIfClauses { get; } + public BoundElseClause? ElseClause { get; } + + public override BoundNodeKind Kind => BoundNodeKind.IfStatement; + } + + 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 BoundParenthesizedExpression : BoundExpression + { + public BoundParenthesizedExpression(SyntaxNode syntax, BoundExpression expression) + : base(syntax) + { + Expression = expression; + } + + public override BoundNodeKind Kind => BoundNodeKind.ParenthesizedExpression; + + public BoundExpression Expression { get; } + } + + 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 BoundUnaryPrefixOperationExpression : BoundExpression + { + public BoundUnaryPrefixOperationExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.UnaryPrefixOperationExpression; + } + + public class BoundUnaryPostfixOperationExpression : BoundExpression + { + public BoundUnaryPostfixOperationExpression(SyntaxNode syntax) + : base(syntax) + { + } + + public override BoundNodeKind Kind => BoundNodeKind.UnaryPostfixOperationExpression; + } + + 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, ImmutableArray body) + : base(syntax) + { + Condition = condition; + Body = body; + } + + public BoundExpression Condition { get; } + public ImmutableArray Body { get; } + public override BoundNodeKind Kind => BoundNodeKind.ElseIfClause; + } + + public class BoundElseClause : BoundNode + { + public BoundElseClause(SyntaxNode syntax, ImmutableArray body) + : base(syntax) + { + Body = body; + } + + public ImmutableArray Body { get; } + public override BoundNodeKind Kind => BoundNodeKind.ElseClause; + } + + 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/Compilation.cs b/Parser/Compilation.cs index c4668c6..8744a58 100644 --- a/Parser/Compilation.cs +++ b/Parser/Compilation.cs @@ -1,4 +1,6 @@ -namespace Parser +using Parser.Binding; + +namespace Parser { public class Compilation { @@ -14,9 +16,20 @@ return new Compilation(syntaxTree); } + private BoundProgram GetBoundProgram() + { + return Binder.BindProgram(_syntaxTree); + } + public EvaluationResult Evaluate(CompilationContext context) { - var evaluator = new Evaluator(_syntaxTree, context); + var program = GetBoundProgram(); + if (program.Diagnostics.Length > 0) + { + return new EvaluationResult(null, program.Diagnostics); + } + + var evaluator = new Evaluator(program, context); return evaluator.Evaluate(); } } diff --git a/Parser/Evaluator.cs b/Parser/Evaluator.cs index 74a1d6b..2a233a7 100644 --- a/Parser/Evaluator.cs +++ b/Parser/Evaluator.cs @@ -1,4 +1,5 @@ -using Parser.Internal; +using Parser.Binding; +using Parser.Internal; using Parser.MFunctions; using Parser.Objects; using System; @@ -10,15 +11,15 @@ namespace Parser { internal class Evaluator { - private readonly SyntaxTree _syntaxTree; + private readonly BoundProgram _program; private readonly CompilationContext _context; private readonly DiagnosticsBag _diagnostics = new DiagnosticsBag(); private bool _insideFunction = false; private readonly Stack _scopeStack = new Stack(); - public Evaluator(SyntaxTree syntaxTree, CompilationContext context) + public Evaluator(BoundProgram program, CompilationContext context) { - _syntaxTree = syntaxTree; + _program = program; _context = context; var outerScope = new EvaluationScope(); _scopeStack.Push(outerScope); @@ -26,209 +27,204 @@ namespace Parser internal EvaluationResult Evaluate() { - var result = EvaluateFile(_syntaxTree.Root); + var result = EvaluateFile(_program.Root); return new EvaluationResult(result, _diagnostics.ToImmutableArray()); } - private MObject? EvaluateFile(FileSyntaxNode root) + private MObject? EvaluateFile(BoundFile root) { MObject? lastResult = null; - foreach (var nodeOrToken in root.StatementList) + foreach (var statement in root.Statements) { - if (nodeOrToken.IsNode) - { - var statement = (StatementSyntaxNode)nodeOrToken.AsNode()!; - lastResult = EvaluateStatement(statement) ?? lastResult; - } + lastResult = EvaluateStatement(statement) ?? lastResult; } return lastResult; } - private MObject? EvaluateStatement(StatementSyntaxNode statement) + private MObject? EvaluateStatement(BoundStatement node) { - return statement.Kind switch + return node.Kind switch { - TokenKind.AbstractMethodDeclaration => - EvaluateAbstractMethodDeclaration((AbstractMethodDeclarationSyntaxNode)statement), - TokenKind.ClassDeclaration => - EvaluateClassDeclaration((ClassDeclarationSyntaxNode)statement), - TokenKind.EmptyStatement => - EvaluateEmptyStatement((EmptyStatementSyntaxNode)statement), - TokenKind.ExpressionStatement => - EvaluateExpressionStatement((ExpressionStatementSyntaxNode)statement), - TokenKind.ForStatement => - EvaluateForStatement((ForStatementSyntaxNode)statement), - TokenKind.FunctionDeclaration => - EvaluateFunctionDeclaration((FunctionDeclarationSyntaxNode)statement), - TokenKind.IfStatement => - EvaluateIfStatement((IfStatementSyntaxNode)statement), - TokenKind.ConcreteMethodDeclaration => - EvaluateMethodDefinition((MethodDefinitionSyntaxNode)statement), - TokenKind.SwitchStatement => - EvaluateSwitchStatement((SwitchStatementSyntaxNode)statement), - TokenKind.TryCatchStatement => - EvaluateTryCatchStatement((TryCatchStatementSyntaxNode)statement), - TokenKind.WhileStatement => - EvaluateWhileStatement((WhileStatementSyntaxNode)statement), - _ => throw new NotImplementedException($"Invalid statement kind '{statement.Kind}'."), + BoundNodeKind.AbstractMethodDeclaration => + EvaluateAbstractMethodDeclaration((BoundAbstractMethodDeclaration)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(ClassDeclarationSyntaxNode statement) + private MObject? EvaluateClassDeclaration(BoundClassDeclaration node) { throw new NotImplementedException(); } - private MObject? EvaluateEmptyStatement(EmptyStatementSyntaxNode statement) + private MObject? EvaluateEmptyStatement(BoundEmptyStatement node) { throw new NotImplementedException(); } - private MObject? EvaluateTryCatchStatement(TryCatchStatementSyntaxNode statement) + private MObject? EvaluateTryCatchStatement(BoundTryCatchStatement node) { throw new NotImplementedException(); } - private MObject? EvaluateForStatement(ForStatementSyntaxNode statement) + private MObject? EvaluateForStatement(BoundForStatement node) { throw new NotImplementedException(); } - private MObject? EvaluateIfStatement(IfStatementSyntaxNode statement) + private MObject? EvaluateIfStatement(BoundIfStatement node) { throw new NotImplementedException(); } - private MObject? EvaluateWhileStatement(WhileStatementSyntaxNode statement) + private MObject? EvaluateWhileStatement(BoundWhileStatement node) { throw new NotImplementedException(); } - private MObject? EvaluateSwitchStatement(SwitchStatementSyntaxNode statement) + private MObject? EvaluateSwitchStatement(BoundSwitchStatement node) { throw new NotImplementedException(); } - private MObject? EvaluateFunctionDeclaration(FunctionDeclarationSyntaxNode statement) + private MObject? EvaluateFunctionDeclaration(BoundFunctionDeclaration node) { throw new NotImplementedException(); } - private MObject? EvaluateAbstractMethodDeclaration(AbstractMethodDeclarationSyntaxNode statement) + private MObject? EvaluateAbstractMethodDeclaration(BoundAbstractMethodDeclaration node) { throw new NotImplementedException(); } - private MObject? EvaluateMethodDefinition(MethodDefinitionSyntaxNode statement) + private MObject? EvaluateMethodDefinition(BoundConcreteMethodDeclaration node) { throw new NotImplementedException(); } - private MObject? EvaluateExpressionStatement(ExpressionStatementSyntaxNode statement) + private MObject? EvaluateExpressionStatement(BoundExpressionStatement node) { - return EvaluateExpression(statement.Expression); + return EvaluateExpression(node.Expression); } - private MObject? EvaluateExpression(ExpressionSyntaxNode expression) + private MObject? EvaluateExpression(BoundExpression node) { - return expression.Kind switch + return node.Kind switch { - TokenKind.ArrayLiteralExpression => - EvaluateArrayLiteralExpression((ArrayLiteralExpressionSyntaxNode)expression), - TokenKind.AssignmentExpression => - EvaluateAssignmentExpression((AssignmentExpressionSyntaxNode)expression), - TokenKind.BinaryOperationExpression => - EvaluateBinaryOperation((BinaryOperationExpressionSyntaxNode)expression), - TokenKind.CellArrayElementAccessExpression => - EvaluateCellArrayElementAccess((CellArrayElementAccessExpressionSyntaxNode)expression), - TokenKind.CellArrayLiteralExpression => - EvaluateCellArrayLiteralExpression((CellArrayLiteralExpressionSyntaxNode)expression), - TokenKind.ClassInvokationExpression => - EvaluateClassInvokation((BaseClassInvokationSyntaxNode)expression), - TokenKind.CommandExpression => - EvaluateCommand((CommandExpressionSyntaxNode)expression), - TokenKind.CompoundNameExpression => - EvaluateCompoundName((CompoundNameExpressionSyntaxNode)expression), - TokenKind.DoubleQuotedStringLiteralExpression => - EvaluateDoubleQuotedStringLiteralExpression((DoubleQuotedStringLiteralSyntaxNode)expression), - TokenKind.EmptyExpression => - EvaluateEmptyExpression((EmptyExpressionSyntaxNode)expression), - TokenKind.FunctionCallExpression => - EvaluateFunctionCall((FunctionCallExpressionSyntaxNode)expression), - TokenKind.IdentifierNameExpression => - EvaluateIdentifierNameExpression((IdentifierNameExpressionSyntaxNode)expression), - TokenKind.IndirectMemberAccessExpression => - EvaluateIndirectMemberAccess((IndirectMemberAccessSyntaxNode)expression), - TokenKind.LambdaExpression => - EvaluateLambdaExpression((LambdaExpressionSyntaxNode)expression), - TokenKind.MemberAccessExpression => - EvaluateMemberAccess((MemberAccessSyntaxNode)expression), - TokenKind.NamedFunctionHandleExpression => - EvaluateNamedFunctionHandleExpression((NamedFunctionHandleExpressionSyntaxNode)expression), - TokenKind.NumberLiteralExpression => - EvaluateNumberLiteralExpression((NumberLiteralSyntaxNode)expression), - TokenKind.ParenthesizedExpression => - EvaluateParenthesizedExpression((ParenthesizedExpressionSyntaxNode)expression), - TokenKind.StringLiteralExpression => - EvaluateStringLiteralExpression((StringLiteralSyntaxNode)expression), - TokenKind.UnaryPrefixOperationExpression => - EvaluateUnaryPrefixOperationExpression((UnaryPrefixOperationExpressionSyntaxNode)expression), - TokenKind.UnaryPostfixOperationExpression => - EvaluateUnaryPostfixOperationExpression((UnaryPostixOperationExpressionSyntaxNode)expression), - TokenKind.UnquotedStringLiteralExpression => - EvaluateUnquotedStringLiteralExpression((UnquotedStringLiteralSyntaxNode)expression), - _ => throw new NotImplementedException($"Invalid expression kind '{expression.Kind}'."), + 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.ParenthesizedExpression => + EvaluateParenthesizedExpression((BoundParenthesizedExpression)node), + BoundNodeKind.StringLiteralExpression => + EvaluateStringLiteralExpression((BoundStringLiteralExpression)node), + BoundNodeKind.UnaryPrefixOperationExpression => + EvaluateUnaryPrefixOperationExpression((BoundUnaryPrefixOperationExpression)node), + BoundNodeKind.UnaryPostfixOperationExpression => + EvaluateUnaryPostfixOperationExpression((BoundUnaryPostfixOperationExpression)node), + BoundNodeKind.UnquotedStringLiteralExpression => + EvaluateUnquotedStringLiteralExpression((BoundUnquotedStringLiteralExpression)node), + _ => throw new NotImplementedException($"Invalid expression kind '{node.Kind}'."), }; } - private MObject? EvaluateParenthesizedExpression(ParenthesizedExpressionSyntaxNode expression) + private MObject? EvaluateParenthesizedExpression(BoundParenthesizedExpression node) { - return EvaluateExpression(expression.Expression); + return EvaluateExpression(node.Expression); } - private MObject? EvaluateClassInvokation(BaseClassInvokationSyntaxNode expression) + private MObject? EvaluateClassInvokation(BoundClassInvokationExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateCommand(CommandExpressionSyntaxNode expression) + private MObject? EvaluateCommand(BoundCommandExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateIndirectMemberAccess(IndirectMemberAccessSyntaxNode expression) + private MObject? EvaluateIndirectMemberAccess(BoundIndirectMemberAccessExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateUnaryPostfixOperationExpression(UnaryPostixOperationExpressionSyntaxNode expression) + private MObject? EvaluateUnaryPostfixOperationExpression(BoundUnaryPostfixOperationExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateMemberAccess(MemberAccessSyntaxNode expression) + private MObject? EvaluateMemberAccess(BoundMemberAccessExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateFunctionCall(FunctionCallExpressionSyntaxNode expression) + private MObject? EvaluateFunctionCall(BoundFunctionCallExpression node) { var arguments = new List(); - var nodes = expression.Nodes.Where(n => n.IsNode).Select(n => (ExpressionSyntaxNode)n.AsNode()!); var allGood = true; - foreach (var node in nodes) + foreach (var argument in node.Arguments) { - var argument = EvaluateExpression(node); + var evaluatedArgument = EvaluateExpression(argument); if (argument is null) { _diagnostics.ReportCannotEvaluateExpression( - new TextSpan(node.Position, node.FullWidth)); + new TextSpan(argument.Syntax.Position, argument.Syntax.FullWidth)); allGood = false; } else { - arguments.Add(argument); + arguments.Add(evaluatedArgument); } } @@ -237,7 +233,7 @@ namespace Parser return null; } - var function = GetFunctionSymbol(expression.FunctionName); + var function = GetFunctionSymbol(node.Name); if (function.Name == "disp") { return EvaluateDisp(arguments); @@ -256,128 +252,126 @@ namespace Parser } Console.WriteLine(arguments[0]); - return null; + return arguments[0]; } - private FunctionSymbol GetFunctionSymbol(ExpressionSyntaxNode functionName) + private FunctionSymbol GetFunctionSymbol(BoundExpression functionName) { - if (functionName.Kind == TokenKind.IdentifierNameExpression) + if (functionName.Kind == BoundNodeKind.IdentifierNameExpression) { - return new FunctionSymbol(((IdentifierNameExpressionSyntaxNode)functionName).Text); + return new FunctionSymbol(((BoundIdentifierNameExpression)functionName).Name); } - throw new NotImplementedException($"Unknown function symbol '{functionName.Text}'."); + throw new NotImplementedException($"Unknown function symbol '{functionName.Syntax.Text}'."); } - private MObject? EvaluateCellArrayElementAccess(CellArrayElementAccessExpressionSyntaxNode expression) + private MObject? EvaluateCellArrayElementAccess(BoundCellArrayElementAccessExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateCellArrayLiteralExpression(CellArrayLiteralExpressionSyntaxNode expression) + private MObject? EvaluateCellArrayLiteralExpression(BoundCellArrayLiteralExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateArrayLiteralExpression(ArrayLiteralExpressionSyntaxNode expression) + private MObject? EvaluateArrayLiteralExpression(BoundArrayLiteralExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateUnquotedStringLiteralExpression(UnquotedStringLiteralSyntaxNode expression) + private MObject? EvaluateUnquotedStringLiteralExpression(BoundUnquotedStringLiteralExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateDoubleQuotedStringLiteralExpression(DoubleQuotedStringLiteralSyntaxNode expression) + private MObject? EvaluateDoubleQuotedStringLiteralExpression(BoundDoubleQuotedStringLiteralExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateStringLiteralExpression(StringLiteralSyntaxNode expression) + private MObject? EvaluateStringLiteralExpression(BoundStringLiteralExpression node) { - return expression.StringToken.Value switch + return node.Value switch { string s => MObject.CreateCharArray(s.ToCharArray()), _ => null, }; } - private MObject? EvaluateNumberLiteralExpression(NumberLiteralSyntaxNode expression) + private MObject? EvaluateNumberLiteralExpression(BoundNumberLiteralExpression node) { - return expression.Number.Value is double value - ? MObject.CreateDoubleNumber(value) - : null; + return MObject.CreateDoubleNumber(node.Value); } - private MObject? EvaluateIdentifierNameExpression(IdentifierNameExpressionSyntaxNode expression) + private MObject? EvaluateIdentifierNameExpression(BoundIdentifierNameExpression node) { - var variableName = expression.Name.Text; + var variableName = node.Name; var maybeValue = GetVariableValue(variableName); if (maybeValue is null) { _diagnostics.ReportVariableNotFound( - new TextSpan(expression.Name.Position, expression.Name.Text.Length), + new TextSpan(node.Syntax.Position, node.Syntax.FullWidth), variableName); } return maybeValue; } - private MObject? EvaluateBinaryOperation(BinaryOperationExpressionSyntaxNode expression) + private MObject? EvaluateBinaryOperation(BoundBinaryOperationExpression node) { - var left = EvaluateExpression(expression.Lhs); + var left = EvaluateExpression(node.Left); if (left is null) { return null; } - var right = EvaluateExpression(expression.Rhs); + var right = EvaluateExpression(node.Right); if (right is null) { return null; } - return expression.Operation.Kind switch + return node.Op.Kind switch { - TokenKind.PlusToken => MOperations.Plus(left, right), - TokenKind.MinusToken => MOperations.Minus(left, right), - TokenKind.StarToken => MOperations.Star(left, right), - TokenKind.SlashToken => MOperations.Slash(left, right), - _ => throw new NotImplementedException($"Binary operation {expression.Operation.Kind} is not implemented."), + BoundBinaryOperatorKind.Plus => MOperations.Plus(left, right), + BoundBinaryOperatorKind.Minus => MOperations.Minus(left, right), + BoundBinaryOperatorKind.Star => MOperations.Star(left, right), + BoundBinaryOperatorKind.Slash => MOperations.Slash(left, right), + _ => throw new NotImplementedException($"Binary operation {node.Op.Kind} is not implemented."), }; } - private MObject? EvaluateCompoundName(CompoundNameExpressionSyntaxNode expression) + private MObject? EvaluateCompoundName(BoundCompoundNameExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode expression) + private MObject? EvaluateUnaryPrefixOperationExpression(BoundUnaryPrefixOperationExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateEmptyExpression(EmptyExpressionSyntaxNode expression) + private MObject? EvaluateEmptyExpression(BoundEmptyExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateAssignmentExpression(AssignmentExpressionSyntaxNode expression) + private MObject? EvaluateAssignmentExpression(BoundAssignmentExpression node) { - var rightValue = EvaluateExpression(expression.Rhs); + var rightValue = EvaluateExpression(node.Right); if (rightValue is null) { _diagnostics.ReportCannotEvaluateExpression( - new TextSpan(expression.Rhs.Position, expression.Rhs.Position + expression.Rhs.FullWidth)); + new TextSpan(node.Right.Syntax.Position, node.Right.Syntax.Position + node.Right.Syntax.FullWidth)); return null; } - var left = expression.Lhs; - if (left.Kind == TokenKind.IdentifierNameExpression) + var left = node.Left; + if (left.Kind == BoundNodeKind.IdentifierNameExpression) { - var leftIdentifier = (IdentifierNameExpressionSyntaxNode)left; - var variableName = leftIdentifier.Name.Text; + var leftIdentifier = (BoundIdentifierNameExpression)left; + var variableName = leftIdentifier.Name; SetVariableValue(variableName, rightValue); return rightValue; } @@ -428,12 +422,12 @@ namespace Parser } } - private MObject? EvaluateLambdaExpression(LambdaExpressionSyntaxNode expression) + private MObject? EvaluateLambdaExpression(BoundLambdaExpression node) { throw new NotImplementedException(); } - private MObject? EvaluateNamedFunctionHandleExpression(NamedFunctionHandleExpressionSyntaxNode expression) + private MObject? EvaluateNamedFunctionHandleExpression(BoundNamedFunctionHandleExpression node) { throw new NotImplementedException(); } diff --git a/Parser/Internal/MParserGreen.cs b/Parser/Internal/MParserGreen.cs index 44587c8..3566598 100644 --- a/Parser/Internal/MParserGreen.cs +++ b/Parser/Internal/MParserGreen.cs @@ -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(); @@ -378,13 +378,13 @@ namespace Parser.Internal break; case TokenKind.DotToken: // member access if (expression is IdentifierNameExpressionSyntaxNode - || expression is MemberAccessSyntaxNode + || 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); @@ -416,10 +416,10 @@ namespace Parser.Internal { 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._name, builder.ToList()); @@ -432,7 +432,7 @@ 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 IdentifierNameExpressionSyntaxNode methodName && !expression.TrailingTrivia.Any()) @@ -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}."); } @@ -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); @@ -920,7 +920,7 @@ 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(); @@ -929,7 +929,7 @@ namespace Parser.Internal var commas = ParseOptionalCommas(); var body = ParseStatementList(); var endKeyword = ParseEndKeyword(); - return Factory.MethodDefinitionSyntax( + return Factory.ConcreteMethodDeclarationSyntax( functionKeyword, outputDescription, name, diff --git a/Parser/Internal/SyntaxFactory.Generated.cs b/Parser/Internal/SyntaxFactory.Generated.cs index 393bcbe..709f01b 100644 --- a/Parser/Internal/SyntaxFactory.Generated.cs +++ b/Parser/Internal/SyntaxFactory.Generated.cs @@ -118,24 +118,24 @@ namespace Parser.Internal 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 +163,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(SyntaxToken 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) @@ -203,9 +203,9 @@ namespace Parser.Internal return new AttributeListSyntaxNode(openingBracket, nodes, closingBracket); } - public MethodDefinitionSyntaxNode MethodDefinitionSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword) + public ConcreteMethodDeclarationSyntaxNode ConcreteMethodDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList 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, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription) diff --git a/Parser/Internal/SyntaxNode.Generated.cs b/Parser/Internal/SyntaxNode.Generated.cs index fcf0d13..b556632 100644 --- a/Parser/Internal/SyntaxNode.Generated.cs +++ b/Parser/Internal/SyntaxNode.Generated.cs @@ -1105,17 +1105,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 +1124,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 +1143,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 +1162,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 +1181,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 +1200,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 +1219,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 +1238,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) @@ -1507,12 +1507,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.MemberAccessExpression) + internal MemberAccessExpressionSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand): base(TokenKind.MemberAccessExpression) { Slots = 3; this.AdjustWidth(leftOperand); @@ -1523,7 +1523,7 @@ namespace Parser.Internal _rightOperand = rightOperand; } - internal MemberAccessSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand, TokenDiagnostic[] diagnostics): base(TokenKind.MemberAccessExpression, diagnostics) + internal MemberAccessExpressionSyntaxNode(SyntaxNode leftOperand, SyntaxToken dot, SyntaxNode rightOperand, TokenDiagnostic[] diagnostics): base(TokenKind.MemberAccessExpression, diagnostics) { Slots = 3; this.AdjustWidth(leftOperand); @@ -1536,12 +1536,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 +1555,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 +1568,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 +1579,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 +1598,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.IndirectMemberAccessExpression) + internal IndirectMemberAccessExpressionSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket): base(TokenKind.IndirectMemberAccessExpression) { Slots = 3; this.AdjustWidth(openingBracket); @@ -1614,7 +1614,7 @@ namespace Parser.Internal _closingBracket = closingBracket; } - internal IndirectMemberAccessSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket, TokenDiagnostic[] diagnostics): base(TokenKind.IndirectMemberAccessExpression, diagnostics) + internal IndirectMemberAccessExpressionSyntaxNode(SyntaxToken openingBracket, ExpressionSyntaxNode expression, SyntaxToken closingBracket, TokenDiagnostic[] diagnostics): base(TokenKind.IndirectMemberAccessExpression, diagnostics) { Slots = 3; this.AdjustWidth(openingBracket); @@ -1627,12 +1627,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) @@ -1649,8 +1649,8 @@ namespace Parser.Internal internal class CommandExpressionSyntaxNode : ExpressionSyntaxNode { internal readonly SyntaxToken _commandName; - internal readonly SyntaxList _arguments; - internal CommandExpressionSyntaxNode(SyntaxToken commandName, SyntaxList arguments): base(TokenKind.CommandExpression) + internal readonly SyntaxList _arguments; + internal CommandExpressionSyntaxNode(SyntaxToken commandName, SyntaxList arguments): base(TokenKind.CommandExpression) { Slots = 2; this.AdjustWidth(commandName); @@ -1659,7 +1659,7 @@ namespace Parser.Internal _arguments = arguments; } - internal CommandExpressionSyntaxNode(SyntaxToken commandName, SyntaxList arguments, TokenDiagnostic[] diagnostics): base(TokenKind.CommandExpression, diagnostics) + internal CommandExpressionSyntaxNode(SyntaxToken commandName, SyntaxList arguments, TokenDiagnostic[] diagnostics): base(TokenKind.CommandExpression, diagnostics) { Slots = 2; this.AdjustWidth(commandName); @@ -1689,12 +1689,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.ClassInvokationExpression) + internal ClassInvokationExpressionSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments): base(TokenKind.ClassInvokationExpression) { Slots = 3; this.AdjustWidth(methodName); @@ -1705,7 +1705,7 @@ namespace Parser.Internal _baseClassNameAndArguments = baseClassNameAndArguments; } - internal BaseClassInvokationSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments, TokenDiagnostic[] diagnostics): base(TokenKind.ClassInvokationExpression, diagnostics) + internal ClassInvokationExpressionSyntaxNode(ExpressionSyntaxNode methodName, SyntaxToken atSign, ExpressionSyntaxNode baseClassNameAndArguments, TokenDiagnostic[] diagnostics): base(TokenKind.ClassInvokationExpression, diagnostics) { Slots = 3; this.AdjustWidth(methodName); @@ -1718,12 +1718,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) @@ -1871,7 +1871,7 @@ namespace Parser.Internal } } - internal class MethodDefinitionSyntaxNode : MethodDeclarationSyntaxNode + internal class ConcreteMethodDeclarationSyntaxNode : MethodDeclarationSyntaxNode { internal readonly SyntaxToken _functionKeyword; internal readonly FunctionOutputDescriptionSyntaxNode? _outputDescription; @@ -1880,7 +1880,7 @@ namespace Parser.Internal internal readonly SyntaxList _commas; internal readonly SyntaxList _body; internal readonly EndKeywordSyntaxNode? _endKeyword; - internal MethodDefinitionSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.ConcreteMethodDeclaration) + internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.ConcreteMethodDeclaration) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -1899,7 +1899,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal MethodDefinitionSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ConcreteMethodDeclaration, diagnostics) + internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ConcreteMethodDeclaration, diagnostics) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -1920,12 +1920,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) diff --git a/Parser/SyntaxDefinition.xml b/Parser/SyntaxDefinition.xml index 81c1532..de938f6 100644 --- a/Parser/SyntaxDefinition.xml +++ b/Parser/SyntaxDefinition.xml @@ -115,16 +115,16 @@ - + - + - + - + @@ -154,25 +154,25 @@ - + - + - + - + - + @@ -190,7 +190,7 @@ - + diff --git a/Parser/SyntaxNode.Generated.cs b/Parser/SyntaxNode.Generated.cs index 3ac4d57..fa7b896 100644 --- a/Parser/SyntaxNode.Generated.cs +++ b/Parser/SyntaxNode.Generated.cs @@ -1143,9 +1143,9 @@ namespace Parser } } - 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 +1153,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 +1169,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 +1183,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 +1199,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 +1213,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 +1229,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 +1243,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 +1259,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitUnquotedStringLiteral(this); + visitor.VisitUnquotedStringLiteralExpression(this); } } @@ -1523,11 +1523,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 +1535,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 +1569,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 +1584,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 +1609,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 +1624,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 +1632,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,7 +1657,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitIndirectMemberAccess(this); + visitor.VisitIndirectMemberAccessExpression(this); } } @@ -1701,11 +1701,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) { } @@ -1713,7 +1713,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)); } } @@ -1747,7 +1747,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitBaseClassInvokation(this); + visitor.VisitClassInvokationExpression(this); } } @@ -1879,7 +1879,7 @@ namespace Parser } } - public class MethodDefinitionSyntaxNode : MethodDeclarationSyntaxNode + public class ConcreteMethodDeclarationSyntaxNode : MethodDeclarationSyntaxNode { private SyntaxNode? _outputDescription; private SyntaxNode? _name; @@ -1887,7 +1887,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) { } @@ -1895,7 +1895,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)); } } @@ -1965,7 +1965,7 @@ namespace Parser public override void Accept(SyntaxVisitor visitor) { - visitor.VisitMethodDefinition(this); + visitor.VisitConcreteMethodDeclaration(this); } } diff --git a/Parser/SyntaxVisitor.Generated.cs b/Parser/SyntaxVisitor.Generated.cs index b16d17b..d023690 100644 --- a/Parser/SyntaxVisitor.Generated.cs +++ b/Parser/SyntaxVisitor.Generated.cs @@ -118,22 +118,22 @@ namespace Parser 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 +163,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 +183,7 @@ namespace Parser DefaultVisit(node); } - public virtual void VisitBaseClassInvokation(BaseClassInvokationSyntaxNode node) + public virtual void VisitClassInvokationExpression(ClassInvokationExpressionSyntaxNode node) { DefaultVisit(node); } @@ -203,7 +203,7 @@ namespace Parser DefaultVisit(node); } - public virtual void VisitMethodDefinition(MethodDefinitionSyntaxNode node) + public virtual void VisitConcreteMethodDeclaration(ConcreteMethodDeclarationSyntaxNode node) { DefaultVisit(node); } diff --git a/Repl/MRepl.cs b/Repl/MRepl.cs index 3edfe38..ed902d0 100644 --- a/Repl/MRepl.cs +++ b/Repl/MRepl.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Parser; namespace Repl @@ -50,8 +51,7 @@ namespace Repl private string Evaluate(string submission) { var tree = SyntaxTree.Parse(submission); - var compilation = Compilation.Create(tree); - if (tree.Diagnostics.Diagnostics.Count > 0) + if (tree.Diagnostics.Any()) { foreach (var diagnostic in tree.Diagnostics.Diagnostics) { @@ -64,7 +64,7 @@ namespace Repl } TreeRenderer.RenderTree(tree); - + var compilation = Compilation.Create(tree); var evaluationResult = compilation.Evaluate(_context); foreach (var diagnostic in evaluationResult.Diagnostics) diff --git a/Semantics/GetClass.cs b/Semantics/GetClass.cs index d9c31c1..15cb673 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)); } diff --git a/examples/helloworld/hello.m b/examples/helloworld/hello.m index 51c6bb1..9a79ec4 100644 --- a/examples/helloworld/hello.m +++ b/examples/helloworld/hello.m @@ -1,3 +1,13 @@ -x = 1; -disp(x + 2); +x = 2; +y = 3; +disp(x + y * y); disp('Hello world!'); + +% x = 2 * 3; +% if x > 5 +% y = 3; +% else +% y = 10; +% end +% +% disp(y); From d613ea3f125e67e00b28548bc6ca30bb1f8175ed Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Wed, 15 Jul 2020 09:43:48 +0200 Subject: [PATCH 07/12] Add BlockStatement --- Parser/Binding/Binder.cs | 12 ++- Parser/Binding/BoundRoot.cs | 26 ++++-- Parser/Internal/MParserGreen.cs | 26 +++--- Parser/Internal/SyntaxFactory.Generated.cs | 23 +++--- Parser/Internal/SyntaxNode.Generated.cs | 92 +++++++++++++++------- Parser/SyntaxDefinition.xml | 21 ++--- Parser/SyntaxNode.Generated.cs | 68 +++++++++++----- Parser/SyntaxVisitor.Generated.cs | 5 ++ Parser/TokenKind.cs | 4 + 9 files changed, 195 insertions(+), 82 deletions(-) diff --git a/Parser/Binding/Binder.cs b/Parser/Binding/Binder.cs index 23fb3fd..820fc76 100644 --- a/Parser/Binding/Binder.cs +++ b/Parser/Binding/Binder.cs @@ -70,7 +70,7 @@ namespace Parser.Binding private BoundIfStatement BindIfStatement(IfStatementSyntaxNode node) { var condition = BindExpression(node.Condition); - var body = BindStatementList(node.Body); + var body = BindBlockStatement(node.Body); var elseIfClauses = node.ElseifClauses .Where(n => n.IsNode) .Select(n => (ElseifClause)n.AsNode()!); @@ -91,10 +91,16 @@ namespace Parser.Binding private BoundElseClause BindElseClause(ElseClause node) { - var body = BindStatementList(node.Body); + var body = BindBlockStatement(node.Body); return new BoundElseClause(node, body); } + private BoundBlockStatement BindBlockStatement(BlockStatementSyntaxNode node) + { + var boundStatements = BindStatementList(node.Statements); + return new BoundBlockStatement(node, boundStatements); + } + private ImmutableArray BindStatementList(SyntaxNodeOrTokenList list) { var builder = ImmutableArray.CreateBuilder(); @@ -124,7 +130,7 @@ namespace Parser.Binding private BoundElseIfClause BindElseIfClause(ElseifClause node) { var condition = BindExpression(node.Condition); - var body = BindStatementList(node.Body); + var body = BindBlockStatement(node.Body); return new BoundElseIfClause(node, condition, body); } diff --git a/Parser/Binding/BoundRoot.cs b/Parser/Binding/BoundRoot.cs index b800a7e..2b7761f 100644 --- a/Parser/Binding/BoundRoot.cs +++ b/Parser/Binding/BoundRoot.cs @@ -13,6 +13,7 @@ namespace Parser.Binding // Statements AbstractMethodDeclaration, + BlockStatement, ClassDeclaration, ConcreteMethodDeclaration, EmptyStatement, @@ -144,6 +145,19 @@ namespace Parser.Binding 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) @@ -209,7 +223,7 @@ namespace Parser.Binding public class BoundIfStatement : BoundStatement { - public BoundIfStatement(SyntaxNode syntax, BoundExpression condition, ImmutableArray body, IEnumerable elseIfClauses, BoundElseClause? elseClause) + public BoundIfStatement(SyntaxNode syntax, BoundExpression condition, BoundBlockStatement body, IEnumerable elseIfClauses, BoundElseClause? elseClause) : base(syntax) { Condition = condition; @@ -219,7 +233,7 @@ namespace Parser.Binding } public BoundExpression Condition { get; } - public ImmutableArray Body { get; } + public BoundBlockStatement Body { get; } public IEnumerable ElseIfClauses { get; } public BoundElseClause? ElseClause { get; } @@ -511,7 +525,7 @@ namespace Parser.Binding public class BoundElseIfClause : BoundNode { - public BoundElseIfClause(SyntaxNode syntax, BoundExpression condition, ImmutableArray body) + public BoundElseIfClause(SyntaxNode syntax, BoundExpression condition, BoundBlockStatement body) : base(syntax) { Condition = condition; @@ -519,19 +533,19 @@ namespace Parser.Binding } public BoundExpression Condition { get; } - public ImmutableArray Body { get; } + public BoundBlockStatement Body { get; } public override BoundNodeKind Kind => BoundNodeKind.ElseIfClause; } public class BoundElseClause : BoundNode { - public BoundElseClause(SyntaxNode syntax, ImmutableArray body) + public BoundElseClause(SyntaxNode syntax, BoundBlockStatement body) : base(syntax) { Body = body; } - public ImmutableArray Body { get; } + public BoundBlockStatement Body { get; } public override BoundNodeKind Kind => BoundNodeKind.ElseClause; } diff --git a/Parser/Internal/MParserGreen.cs b/Parser/Internal/MParserGreen.cs index 3566598..e935f8d 100644 --- a/Parser/Internal/MParserGreen.cs +++ b/Parser/Internal/MParserGreen.cs @@ -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( @@ -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); @@ -927,7 +927,7 @@ namespace Parser.Internal var name = ParseCompoundName(); var inputDescription = ParseFunctionInputDescription(); var commas = ParseOptionalCommas(); - var body = ParseStatementList(); + var body = ParseBlockStatement(); var endKeyword = ParseEndKeyword(); return Factory.ConcreteMethodDeclarationSyntax( functionKeyword, @@ -1190,6 +1190,12 @@ namespace Parser.Internal } return ParseExpressionStatement(); } + + private BlockStatementSyntaxNode ParseBlockStatement() + { + var statements = ParseStatementList(); + return Factory.BlockStatementSyntax(statements); + } private SyntaxList ParseStatementList() { diff --git a/Parser/Internal/SyntaxFactory.Generated.cs b/Parser/Internal/SyntaxFactory.Generated.cs index 709f01b..edfbbb1 100644 --- a/Parser/Internal/SyntaxFactory.Generated.cs +++ b/Parser/Internal/SyntaxFactory.Generated.cs @@ -8,7 +8,12 @@ namespace Parser.Internal return new FileSyntaxNode(statementList, 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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode body) { return new ElseifClause(elseifKeyword, condition, optionalCommas, body); } - public ElseClause ElseClause(SyntaxToken elseKeyword, SyntaxList body) + public ElseClause ElseClause(SyntaxToken elseKeyword, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword) { return new TryCatchStatementSyntaxNode(tryKeyword, tryBody, catchClause, endKeyword); } @@ -203,7 +208,7 @@ namespace Parser.Internal return new AttributeListSyntaxNode(openingBracket, nodes, closingBracket); } - public ConcreteMethodDeclarationSyntaxNode ConcreteMethodDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword) + public ConcreteMethodDeclarationSyntaxNode ConcreteMethodDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword) { return new ConcreteMethodDeclarationSyntaxNode(functionKeyword, outputDescription, name, inputDescription, commas, body, endKeyword); } diff --git a/Parser/Internal/SyntaxNode.Generated.cs b/Parser/Internal/SyntaxNode.Generated.cs index b556632..9ca04cc 100644 --- a/Parser/Internal/SyntaxNode.Generated.cs +++ b/Parser/Internal/SyntaxNode.Generated.cs @@ -44,6 +44,44 @@ namespace Parser.Internal } } + 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 + } + + ; + } + } + internal class FunctionDeclarationSyntaxNode : StatementSyntaxNode { internal readonly SyntaxToken _functionKeyword; @@ -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 BlockStatementSyntaxNode _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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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 BlockStatementSyntaxNode _body; + internal SwitchCaseSyntaxNode(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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 BlockStatementSyntaxNode _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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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 BlockStatementSyntaxNode _body; + internal ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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 BlockStatementSyntaxNode _body; + internal ElseClause(SyntaxToken elseKeyword, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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 BlockStatementSyntaxNode _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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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 BlockStatementSyntaxNode _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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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 BlockStatementSyntaxNode _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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.TryCatchStatement, diagnostics) { Slots = 4; this.AdjustWidth(tryKeyword); @@ -1878,9 +1916,9 @@ namespace Parser.Internal internal readonly CompoundNameExpressionSyntaxNode _name; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription; internal readonly SyntaxList _commas; - internal readonly SyntaxList _body; + internal readonly BlockStatementSyntaxNode _body; internal readonly EndKeywordSyntaxNode? _endKeyword; - internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.ConcreteMethodDeclaration) + internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.ConcreteMethodDeclaration) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -1899,7 +1937,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, SyntaxList body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ConcreteMethodDeclaration, diagnostics) + internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ConcreteMethodDeclaration, diagnostics) { Slots = 7; this.AdjustWidth(functionKeyword); diff --git a/Parser/SyntaxDefinition.xml b/Parser/SyntaxDefinition.xml index de938f6..1ca6f1f 100644 --- a/Parser/SyntaxDefinition.xml +++ b/Parser/SyntaxDefinition.xml @@ -4,13 +4,16 @@ + + + - + @@ -33,30 +36,30 @@ - + - + - + - + - + @@ -65,7 +68,7 @@ - + @@ -79,7 +82,7 @@ - + @@ -196,7 +199,7 @@ - + diff --git a/Parser/SyntaxNode.Generated.cs b/Parser/SyntaxNode.Generated.cs index fa7b896..b99f89d 100644 --- a/Parser/SyntaxNode.Generated.cs +++ b/Parser/SyntaxNode.Generated.cs @@ -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 BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } @@ -320,12 +352,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } @@ -388,12 +420,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } @@ -448,12 +480,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } @@ -488,12 +520,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } @@ -558,12 +590,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } @@ -644,12 +676,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } @@ -783,12 +815,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList TryBody + public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } @@ -1935,12 +1967,12 @@ namespace Parser } } - public SyntaxNodeOrTokenList Body + public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; } } diff --git a/Parser/SyntaxVisitor.Generated.cs b/Parser/SyntaxVisitor.Generated.cs index d023690..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); diff --git a/Parser/TokenKind.cs b/Parser/TokenKind.cs index c1b403e..4645763 100644 --- a/Parser/TokenKind.cs +++ b/Parser/TokenKind.cs @@ -142,6 +142,10 @@ // result = abstractMethod(object) AbstractMethodDeclaration, + // statement1 + // statement2; + BlockStatement, + // classdef MyClass < BaseClass, AnotherBaseClass // properties // y From 652bd92f0179deb817502594c614b7f61b11fa97 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Wed, 15 Jul 2020 10:22:16 +0200 Subject: [PATCH 08/12] Add BoundTreeRewriter --- Parser/Binding/Binder.cs | 20 +- Parser/Binding/BoundBinaryOperator.cs | 48 +++ Parser/Binding/BoundBinaryOperatorKind.cs | 29 ++ Parser/Binding/BoundNode.cs | 13 + Parser/Binding/BoundNodeKind.cs | 52 +++ Parser/Binding/BoundRoot.cs | 154 +------- Parser/Binding/BoundTreeRewriter.cs | 396 +++++++++++++++++++++ Parser/Internal/SyntaxFactory.Generated.cs | 18 +- Parser/Internal/SyntaxNode.Generated.cs | 54 +-- Parser/Parser.csproj | 1 + Parser/SyntaxDefinition.xml | 18 +- Parser/SyntaxNode.Generated.cs | 36 +- 12 files changed, 622 insertions(+), 217 deletions(-) create mode 100644 Parser/Binding/BoundBinaryOperator.cs create mode 100644 Parser/Binding/BoundBinaryOperatorKind.cs create mode 100644 Parser/Binding/BoundNode.cs create mode 100644 Parser/Binding/BoundNodeKind.cs create mode 100644 Parser/Binding/BoundTreeRewriter.cs diff --git a/Parser/Binding/Binder.cs b/Parser/Binding/Binder.cs index 820fc76..2dd9d83 100644 --- a/Parser/Binding/Binder.cs +++ b/Parser/Binding/Binder.cs @@ -70,14 +70,14 @@ namespace Parser.Binding private BoundIfStatement BindIfStatement(IfStatementSyntaxNode node) { var condition = BindExpression(node.Condition); - var body = BindBlockStatement(node.Body); - var elseIfClauses = node.ElseifClauses + 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 builder = ImmutableArray.CreateBuilder(); + foreach (var elseifClause in elseifClauses) { - var clause = BindElseIfClause(elseIfClause); + var clause = BindElseifClause(elseifClause); builder.Add(clause); } var maybeElseClause = node.ElseClause switch @@ -86,12 +86,12 @@ namespace Parser.Binding _ => null, }; - return new BoundIfStatement(node, condition, body, elseIfClauses, maybeElseClause); + return new BoundIfStatement(node, condition, body, builder.ToImmutable(), maybeElseClause); } private BoundElseClause BindElseClause(ElseClause node) { - var body = BindBlockStatement(node.Body); + var body = BindStatement(node.Body); return new BoundElseClause(node, body); } @@ -127,11 +127,11 @@ namespace Parser.Binding return builder.ToImmutable(); } - private BoundElseIfClause BindElseIfClause(ElseifClause node) + private BoundElseifClause BindElseifClause(ElseifClause node) { var condition = BindExpression(node.Condition); - var body = BindBlockStatement(node.Body); - return new BoundElseIfClause(node, condition, body); + var body = BindStatement(node.Body); + return new BoundElseifClause(node, condition, body); } private BoundFunctionDeclaration BindFunctionDeclaration(FunctionDeclarationSyntaxNode node) 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/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/BoundNodeKind.cs b/Parser/Binding/BoundNodeKind.cs new file mode 100644 index 0000000..d75402f --- /dev/null +++ b/Parser/Binding/BoundNodeKind.cs @@ -0,0 +1,52 @@ +namespace Parser.Binding +{ + public enum BoundNodeKind + { + Root, + File, + + // Statements + + AbstractMethodDeclaration, + BlockStatement, + ClassDeclaration, + ConcreteMethodDeclaration, + EmptyStatement, + ExpressionStatement, + ForStatement, + FunctionDeclaration, + IfStatement, + SwitchStatement, + TryCatchStatement, + WhileStatement, + + // Expressions + + ArrayLiteralExpression, + AssignmentExpression, + BinaryOperationExpression, + CellArrayElementAccessExpression, + CellArrayLiteralExpression, + ClassInvokationExpression, + CommandExpression, + CompoundNameExpression, + DoubleQuotedStringLiteralExpression, + EmptyExpression, + FunctionCallExpression, + IdentifierNameExpression, + IndirectMemberAccessExpression, + LambdaExpression, + MemberAccessExpression, + NamedFunctionHandleExpression, + NumberLiteralExpression, + ParenthesizedExpression, + StringLiteralExpression, + UnaryPrefixOperationExpression, + UnaryPostfixOperationExpression, + UnquotedStringLiteralExpression, + + // Parts + ElseIfClause, + ElseClause + } +} diff --git a/Parser/Binding/BoundRoot.cs b/Parser/Binding/BoundRoot.cs index 2b7761f..6094363 100644 --- a/Parser/Binding/BoundRoot.cs +++ b/Parser/Binding/BoundRoot.cs @@ -1,98 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; namespace Parser.Binding { - public enum BoundNodeKind - { - Root, - File, - - // Statements - - AbstractMethodDeclaration, - BlockStatement, - ClassDeclaration, - ConcreteMethodDeclaration, - EmptyStatement, - ExpressionStatement, - ForStatement, - FunctionDeclaration, - IfStatement, - SwitchStatement, - TryCatchStatement, - WhileStatement, - - // Expressions - - ArrayLiteralExpression, - AssignmentExpression, - BinaryOperationExpression, - CellArrayElementAccessExpression, - CellArrayLiteralExpression, - ClassInvokationExpression, - CommandExpression, - CompoundNameExpression, - DoubleQuotedStringLiteralExpression, - EmptyExpression, - FunctionCallExpression, - IdentifierNameExpression, - IndirectMemberAccessExpression, - LambdaExpression, - MemberAccessExpression, - NamedFunctionHandleExpression, - NumberLiteralExpression, - ParenthesizedExpression, - StringLiteralExpression, - UnaryPrefixOperationExpression, - UnaryPostfixOperationExpression, - UnquotedStringLiteralExpression, - - // Parts - ElseIfClause, - ElseClause - } - - 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, - } - - public abstract class BoundNode - { - public BoundNode(SyntaxNode syntax) - { - Syntax = syntax; - } - - public SyntaxNode Syntax { get; } - public abstract BoundNodeKind Kind { get; } - } - public class BoundRoot : BoundNode { public BoundRoot(SyntaxNode syntax, BoundFile file) @@ -223,18 +133,18 @@ namespace Parser.Binding public class BoundIfStatement : BoundStatement { - public BoundIfStatement(SyntaxNode syntax, BoundExpression condition, BoundBlockStatement body, IEnumerable elseIfClauses, BoundElseClause? elseClause) + public BoundIfStatement(SyntaxNode syntax, BoundExpression condition, BoundStatement body, ImmutableArray elseifClauses, BoundElseClause? elseClause) : base(syntax) { Condition = condition; Body = body; - ElseIfClauses = elseIfClauses; + ElseifClauses = elseifClauses; ElseClause = elseClause; } public BoundExpression Condition { get; } - public BoundBlockStatement Body { get; } - public IEnumerable ElseIfClauses { get; } + public BoundStatement Body { get; } + public ImmutableArray ElseifClauses { get; } public BoundElseClause? ElseClause { get; } public override BoundNodeKind Kind => BoundNodeKind.IfStatement; @@ -523,9 +433,9 @@ namespace Parser.Binding public override BoundNodeKind Kind => BoundNodeKind.UnquotedStringLiteralExpression; } - public class BoundElseIfClause : BoundNode + public class BoundElseifClause : BoundNode { - public BoundElseIfClause(SyntaxNode syntax, BoundExpression condition, BoundBlockStatement body) + public BoundElseifClause(SyntaxNode syntax, BoundExpression condition, BoundStatement body) : base(syntax) { Condition = condition; @@ -533,63 +443,19 @@ namespace Parser.Binding } public BoundExpression Condition { get; } - public BoundBlockStatement Body { get; } + public BoundStatement Body { get; } public override BoundNodeKind Kind => BoundNodeKind.ElseIfClause; } public class BoundElseClause : BoundNode { - public BoundElseClause(SyntaxNode syntax, BoundBlockStatement body) + public BoundElseClause(SyntaxNode syntax, BoundStatement body) : base(syntax) { Body = body; } - public BoundBlockStatement Body { get; } + public BoundStatement Body { get; } public override BoundNodeKind Kind => BoundNodeKind.ElseClause; } - - 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/BoundTreeRewriter.cs b/Parser/Binding/BoundTreeRewriter.cs new file mode 100644 index 0000000..025dca8 --- /dev/null +++ b/Parser/Binding/BoundTreeRewriter.cs @@ -0,0 +1,396 @@ +using System; +using System.Collections.Immutable; + +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.EmptyStatement => + RewriteEmptyStatement((BoundEmptyStatement)node), + BoundNodeKind.ExpressionStatement => + RewriteExpressionStatement((BoundExpressionStatement)node), + BoundNodeKind.ForStatement => + RewriteForStatement((BoundForStatement)node), + BoundNodeKind.FunctionDeclaration => + RewriteFunctionDeclaration((BoundFunctionDeclaration)node), + BoundNodeKind.IfStatement => + RewriteIfStatement((BoundIfStatement)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 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 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; i++) + { + 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 : RewriteElseifClause(node.ElseClause); + if (condition == node.Condition && + body == node.Body && + elseIfClauses == node.ElseifClauses && + elseClause == node.ElseClause ) + { + return node; + } + + return new BoundIfStatement(node.Syntax, condition, body, elseIfClauses, elseClause); + } + + public virtual BoundElseClause RewriteElseifClause(BoundElseClause node) + { + var body = RewriteStatement(node.Body); + if (body == node.Body) + { + return node; + } + + return new BoundElseClause(node.Syntax, body); + } + + 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 new BoundElseifClause(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 new BoundExpressionStatement(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; i++) + { + builder.Add(node.Statements[j]); + } + } + if (builder is not null) + { + builder.Add(newStatement); + } + + } + + if (builder is null) + { + return node; + } + + return new BoundBlockStatement(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.ParenthesizedExpression => + RewriteParenthesizedExpression((BoundParenthesizedExpression)node), + BoundNodeKind.StringLiteralExpression => + RewriteStringLiteralExpression((BoundStringLiteralExpression)node), + BoundNodeKind.UnaryPrefixOperationExpression => + RewriteUnaryPrefixOperationExpression((BoundUnaryPrefixOperationExpression)node), + BoundNodeKind.UnaryPostfixOperationExpression => + RewriteUnaryPostfixOperationExpression((BoundUnaryPostfixOperationExpression)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 RewriteUnaryPostfixOperationExpression(BoundUnaryPostfixOperationExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteUnaryPrefixOperationExpression(BoundUnaryPrefixOperationExpression node) + { + throw new NotImplementedException(); + } + + public virtual BoundExpression RewriteStringLiteralExpression(BoundStringLiteralExpression node) + { + return node; + } + + public virtual BoundExpression RewriteParenthesizedExpression(BoundParenthesizedExpression node) + { + var expression = RewriteExpression(node.Expression); + if (expression == node.Expression) + { + return node; + } + + return new BoundParenthesizedExpression(node.Syntax, expression); + } + + 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; i++) + { + builder.Add(node.Arguments[j]); + } + } + if (builder is not null) + { + builder.Add(newArgument); + } + + } + + if (builder is null) + { + return node; + } + + return new BoundFunctionCallExpression(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 new BoundAssignmentExpression(node.Syntax, left, right); + } + + public virtual BoundExpression RewriteArrayLiteralExpression(BoundArrayLiteralExpression node) + { + throw new NotImplementedException(); + } + } +} diff --git a/Parser/Internal/SyntaxFactory.Generated.cs b/Parser/Internal/SyntaxFactory.Generated.cs index edfbbb1..48981b9 100644 --- a/Parser/Internal/SyntaxFactory.Generated.cs +++ b/Parser/Internal/SyntaxFactory.Generated.cs @@ -13,7 +13,7 @@ namespace Parser.Internal return new BlockStatementSyntaxNode(statements); } - public FunctionDeclarationSyntaxNode FunctionDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword) + 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); } @@ -33,32 +33,32 @@ namespace Parser.Internal return new SwitchStatementSyntaxNode(switchKeyword, switchExpression, optionalCommas, cases, endKeyword); } - public SwitchCaseSyntaxNode SwitchCaseSyntax(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode body) + public ElseifClause ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, StatementSyntaxNode body) { return new ElseifClause(elseifKeyword, condition, optionalCommas, body); } - public ElseClause ElseClause(SyntaxToken elseKeyword, BlockStatementSyntaxNode body) + public ElseClause ElseClause(SyntaxToken elseKeyword, StatementSyntaxNode body) { return new ElseClause(elseKeyword, body); } - public IfStatementSyntaxNode IfStatementSyntax(SyntaxToken ifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, BlockStatementSyntaxNode 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, BlockStatementSyntaxNode body, SyntaxToken endKeyword) + public ForStatementSyntaxNode ForStatementSyntax(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, StatementSyntaxNode body, SyntaxToken endKeyword) { return new ForStatementSyntaxNode(forKeyword, assignment, optionalCommas, body, endKeyword); } @@ -73,7 +73,7 @@ namespace Parser.Internal return new CatchClauseSyntaxNode(catchKeyword, catchBody); } - public TryCatchStatementSyntaxNode TryCatchStatementSyntax(SyntaxToken tryKeyword, BlockStatementSyntaxNode tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword) + public TryCatchStatementSyntaxNode TryCatchStatementSyntax(SyntaxToken tryKeyword, StatementSyntaxNode tryBody, CatchClauseSyntaxNode? catchClause, SyntaxToken endKeyword) { return new TryCatchStatementSyntaxNode(tryKeyword, tryBody, catchClause, endKeyword); } @@ -208,7 +208,7 @@ namespace Parser.Internal return new AttributeListSyntaxNode(openingBracket, nodes, closingBracket); } - public ConcreteMethodDeclarationSyntaxNode ConcreteMethodDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword) + public ConcreteMethodDeclarationSyntaxNode ConcreteMethodDeclarationSyntax(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, StatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword) { return new ConcreteMethodDeclarationSyntaxNode(functionKeyword, outputDescription, name, inputDescription, commas, body, endKeyword); } diff --git a/Parser/Internal/SyntaxNode.Generated.cs b/Parser/Internal/SyntaxNode.Generated.cs index 9ca04cc..014c271 100644 --- a/Parser/Internal/SyntaxNode.Generated.cs +++ b/Parser/Internal/SyntaxNode.Generated.cs @@ -89,9 +89,9 @@ namespace Parser.Internal internal readonly SyntaxToken _name; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription; internal readonly SyntaxList _commas; - internal readonly BlockStatementSyntaxNode _body; + internal readonly StatementSyntaxNode _body; internal readonly EndKeywordSyntaxNode? _endKeyword; - internal FunctionDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode 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); @@ -110,7 +110,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal FunctionDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, SyntaxToken name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode 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); @@ -304,8 +304,8 @@ namespace Parser.Internal internal readonly SyntaxToken _caseKeyword; internal readonly ExpressionSyntaxNode _caseIdentifier; internal readonly SyntaxList _optionalCommas; - internal readonly BlockStatementSyntaxNode _body; - internal SwitchCaseSyntaxNode(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -318,7 +318,7 @@ namespace Parser.Internal _body = body; } - internal SwitchCaseSyntaxNode(SyntaxToken caseKeyword, ExpressionSyntaxNode caseIdentifier, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -357,9 +357,9 @@ namespace Parser.Internal internal readonly SyntaxToken _whileKeyword; internal readonly ExpressionSyntaxNode _condition; internal readonly SyntaxList _optionalCommas; - internal readonly BlockStatementSyntaxNode _body; + internal readonly StatementSyntaxNode _body; internal readonly SyntaxToken _endKeyword; - internal WhileStatementSyntaxNode(SyntaxToken whileKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -374,7 +374,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal WhileStatementSyntaxNode(SyntaxToken whileKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -415,8 +415,8 @@ namespace Parser.Internal internal readonly SyntaxToken _elseifKeyword; internal readonly ExpressionSyntaxNode _condition; internal readonly SyntaxList _optionalCommas; - internal readonly BlockStatementSyntaxNode _body; - internal ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -429,7 +429,7 @@ namespace Parser.Internal _body = body; } - internal ElseifClause(SyntaxToken elseifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -466,8 +466,8 @@ namespace Parser.Internal internal class ElseClause : SyntaxNode { internal readonly SyntaxToken _elseKeyword; - internal readonly BlockStatementSyntaxNode _body; - internal ElseClause(SyntaxToken elseKeyword, BlockStatementSyntaxNode body): base(TokenKind.ElseClause) + internal readonly StatementSyntaxNode _body; + internal ElseClause(SyntaxToken elseKeyword, StatementSyntaxNode body): base(TokenKind.ElseClause) { Slots = 2; this.AdjustWidth(elseKeyword); @@ -476,7 +476,7 @@ namespace Parser.Internal _body = body; } - internal ElseClause(SyntaxToken elseKeyword, BlockStatementSyntaxNode body, TokenDiagnostic[] diagnostics): base(TokenKind.ElseClause, diagnostics) + internal ElseClause(SyntaxToken elseKeyword, StatementSyntaxNode body, TokenDiagnostic[] diagnostics): base(TokenKind.ElseClause, diagnostics) { Slots = 2; this.AdjustWidth(elseKeyword); @@ -511,11 +511,11 @@ namespace Parser.Internal internal readonly SyntaxToken _ifKeyword; internal readonly ExpressionSyntaxNode _condition; internal readonly SyntaxList _optionalCommas; - internal readonly BlockStatementSyntaxNode _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, BlockStatementSyntaxNode 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); @@ -534,7 +534,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal IfStatementSyntaxNode(SyntaxToken ifKeyword, ExpressionSyntaxNode condition, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -579,9 +579,9 @@ namespace Parser.Internal internal readonly SyntaxToken _forKeyword; internal readonly AssignmentExpressionSyntaxNode _assignment; internal readonly SyntaxList _optionalCommas; - internal readonly BlockStatementSyntaxNode _body; + internal readonly StatementSyntaxNode _body; internal readonly SyntaxToken _endKeyword; - internal ForStatementSyntaxNode(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -596,7 +596,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal ForStatementSyntaxNode(SyntaxToken forKeyword, AssignmentExpressionSyntaxNode assignment, SyntaxList optionalCommas, BlockStatementSyntaxNode 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); @@ -726,10 +726,10 @@ namespace Parser.Internal internal class TryCatchStatementSyntaxNode : StatementSyntaxNode { internal readonly SyntaxToken _tryKeyword; - internal readonly BlockStatementSyntaxNode _tryBody; + internal readonly StatementSyntaxNode _tryBody; internal readonly CatchClauseSyntaxNode? _catchClause; internal readonly SyntaxToken _endKeyword; - internal TryCatchStatementSyntaxNode(SyntaxToken tryKeyword, BlockStatementSyntaxNode 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); @@ -742,7 +742,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal TryCatchStatementSyntaxNode(SyntaxToken tryKeyword, BlockStatementSyntaxNode 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); @@ -1916,9 +1916,9 @@ namespace Parser.Internal internal readonly CompoundNameExpressionSyntaxNode _name; internal readonly FunctionInputDescriptionSyntaxNode? _inputDescription; internal readonly SyntaxList _commas; - internal readonly BlockStatementSyntaxNode _body; + internal readonly StatementSyntaxNode _body; internal readonly EndKeywordSyntaxNode? _endKeyword; - internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.ConcreteMethodDeclaration) + internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, StatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword): base(TokenKind.ConcreteMethodDeclaration) { Slots = 7; this.AdjustWidth(functionKeyword); @@ -1937,7 +1937,7 @@ namespace Parser.Internal _endKeyword = endKeyword; } - internal ConcreteMethodDeclarationSyntaxNode(SyntaxToken functionKeyword, FunctionOutputDescriptionSyntaxNode? outputDescription, CompoundNameExpressionSyntaxNode name, FunctionInputDescriptionSyntaxNode? inputDescription, SyntaxList commas, BlockStatementSyntaxNode body, EndKeywordSyntaxNode? endKeyword, TokenDiagnostic[] diagnostics): base(TokenKind.ConcreteMethodDeclaration, 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); 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/Parser/SyntaxDefinition.xml b/Parser/SyntaxDefinition.xml index 1ca6f1f..d3baf5d 100644 --- a/Parser/SyntaxDefinition.xml +++ b/Parser/SyntaxDefinition.xml @@ -13,7 +13,7 @@ - + @@ -36,30 +36,30 @@ - + - + - + - + - + @@ -68,7 +68,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -199,7 +199,7 @@ - + diff --git a/Parser/SyntaxNode.Generated.cs b/Parser/SyntaxNode.Generated.cs index b99f89d..9b60cbd 100644 --- a/Parser/SyntaxNode.Generated.cs +++ b/Parser/SyntaxNode.Generated.cs @@ -127,12 +127,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -352,12 +352,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -420,12 +420,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -480,12 +480,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -520,12 +520,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -590,12 +590,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -676,12 +676,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } @@ -815,12 +815,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("tryBody cannot be null.") : (StatementSyntaxNode)red; } } @@ -1967,12 +1967,12 @@ namespace Parser } } - public BlockStatementSyntaxNode 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.") : (BlockStatementSyntaxNode)red; + return red is null ? throw new System.Exception("body cannot be null.") : (StatementSyntaxNode)red; } } From 7f0889f0d4ce0db51e63124fd85485a0abcb9915 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Wed, 15 Jul 2020 17:22:48 +0200 Subject: [PATCH 09/12] Implement lowering --- ConsoleDemo/DumbWalker.cs | 2 +- ConsoleDemo/PrettyPrinter.cs | 2 +- ConsoleDemo/UsageGathering.cs | 2 +- MApplication/ColoringVisitor.cs | 2 +- Parser.Tests/MParserShould.cs | 8 +- Parser/Binding/Binder.cs | 80 +++++----- Parser/Binding/BoundLabel.cs | 17 +++ Parser/Binding/BoundNodeFactory.cs | 170 +++++++++++++++++++++ Parser/Binding/BoundNodeKind.cs | 6 +- Parser/Binding/BoundRoot.cs | 102 +++++++------ Parser/Binding/BoundTreeRewriter.cs | 89 ++++++----- Parser/Binding/BoundUnaryOperator.cs | 26 ++++ Parser/Binding/BoundUnaryOperatorKind.cs | 7 + Parser/Evaluator.cs | 99 +++++++++--- Parser/Internal/MParserGreen.cs | 2 +- Parser/Internal/SyntaxFactory.Generated.cs | 4 +- Parser/Internal/SyntaxNode.Generated.cs | 18 +-- Parser/Lowering/Lowerer.cs | 116 ++++++++++++++ Parser/MFunctions/MOperations.cs | 55 +++++++ Parser/Objects/MLogical.cs | 24 +++ Parser/Objects/MObject.cs | 5 + Parser/SyntaxDefinition.xml | 2 +- Parser/SyntaxNode.Generated.cs | 10 +- Semantics/GetClass.cs | 2 +- cmi/Program.cs | 12 +- cmi/TreeRenderer.cs | 44 ++++++ examples/helloworld/hello.m | 16 +- 27 files changed, 730 insertions(+), 192 deletions(-) create mode 100644 Parser/Binding/BoundLabel.cs create mode 100644 Parser/Binding/BoundNodeFactory.cs create mode 100644 Parser/Binding/BoundUnaryOperator.cs create mode 100644 Parser/Binding/BoundUnaryOperatorKind.cs create mode 100644 Parser/Lowering/Lowerer.cs create mode 100644 Parser/Objects/MLogical.cs create mode 100644 cmi/TreeRenderer.cs diff --git a/ConsoleDemo/DumbWalker.cs b/ConsoleDemo/DumbWalker.cs index fc3bd64..97a6a54 100644 --- a/ConsoleDemo/DumbWalker.cs +++ b/ConsoleDemo/DumbWalker.cs @@ -169,7 +169,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) { diff --git a/ConsoleDemo/PrettyPrinter.cs b/ConsoleDemo/PrettyPrinter.cs index 3dab17f..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); } diff --git a/ConsoleDemo/UsageGathering.cs b/ConsoleDemo/UsageGathering.cs index 9b227a6..6be20d1 100644 --- a/ConsoleDemo/UsageGathering.cs +++ b/ConsoleDemo/UsageGathering.cs @@ -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) { diff --git a/MApplication/ColoringVisitor.cs b/MApplication/ColoringVisitor.cs index ba9e4c7..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); } 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 index 2dd9d83..a042671 100644 --- a/Parser/Binding/Binder.cs +++ b/Parser/Binding/Binder.cs @@ -1,24 +1,39 @@ 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 loweredStatement = Lowerer.Lower(boundRoot.File.Body); + var newRoot = Root( + boundRoot.Syntax, + File(boundRoot.File.Syntax, loweredStatement)); + return new BoundProgram(newRoot, binder._diagnostics.ToImmutableArray()); + } + private BoundRoot BindRoot(RootSyntaxNode node) { var boundFile = BindFile(node.File); - return new BoundRoot(node, boundFile); + return Root(node, boundFile); } private BoundFile BindFile(FileSyntaxNode node) { - var statements = BindStatementList(node.StatementList); - return new BoundFile(node, statements); + var body = BindBlockStatement(node.Body); + return File(node, body); } private BoundStatement BindStatement(StatementSyntaxNode node) @@ -27,6 +42,8 @@ namespace Parser.Binding { TokenKind.AbstractMethodDeclaration => BindAbstractMethodDeclaration((AbstractMethodDeclarationSyntaxNode)node), + TokenKind.BlockStatement => + BindBlockStatement((BlockStatementSyntaxNode)node), TokenKind.ClassDeclaration => BindClassDeclaration((ClassDeclarationSyntaxNode)node), TokenKind.ConcreteMethodDeclaration => @@ -86,32 +103,27 @@ namespace Parser.Binding _ => null, }; - return new BoundIfStatement(node, condition, body, builder.ToImmutable(), maybeElseClause); + return IfStatement(node, condition, body, builder.ToImmutable(), maybeElseClause); } - private BoundElseClause BindElseClause(ElseClause node) + private BoundStatement BindElseClause(ElseClause node) { - var body = BindStatement(node.Body); - return new BoundElseClause(node, body); + return BindStatement(node.Body); } private BoundBlockStatement BindBlockStatement(BlockStatementSyntaxNode node) { var boundStatements = BindStatementList(node.Statements); - return new BoundBlockStatement(node, boundStatements); + return Block(node, boundStatements.ToArray()); } - private ImmutableArray BindStatementList(SyntaxNodeOrTokenList list) + private IEnumerable BindStatementList(SyntaxNodeOrTokenList list) { - var builder = ImmutableArray.CreateBuilder(); var statements = list.Where(s => s.IsNode).Select(s => (StatementSyntaxNode)s.AsNode()!); foreach (var statement in statements) { - var boundStatement = BindStatement(statement); - builder.Add(boundStatement); + yield return BindStatement(statement); } - - return builder.ToImmutable(); } private ImmutableArray BindExpressionList(SyntaxNodeOrTokenList list) @@ -131,7 +143,7 @@ namespace Parser.Binding { var condition = BindExpression(node.Condition); var body = BindStatement(node.Body); - return new BoundElseifClause(node, condition, body); + return ElseifClause(node, condition, body); } private BoundFunctionDeclaration BindFunctionDeclaration(FunctionDeclarationSyntaxNode node) @@ -147,7 +159,7 @@ namespace Parser.Binding private BoundExpressionStatement BindExpressionStatement(ExpressionStatementSyntaxNode node) { var expression = BindExpression(node.Expression); - return new BoundExpressionStatement(node, expression); + return ExpressionStatement(node, expression); } private BoundExpression BindExpression(ExpressionSyntaxNode node) @@ -212,21 +224,14 @@ namespace Parser.Binding { var left = BindExpression(node.Lhs); var right = BindExpression(node.Rhs); - return new BoundAssignmentExpression(node, left, right); + return Assignment(node, left, right); } private BoundBinaryOperationExpression BindBinaryOperationExpression(BinaryOperationExpressionSyntaxNode node) { var left = BindExpression(node.Lhs); var right = BindExpression(node.Rhs); - var op = BindBinaryOperator(node.Operation); - return new BoundBinaryOperationExpression(node, left, op, right); - } - - private BoundBinaryOperator BindBinaryOperator(SyntaxToken token) - { - return BoundBinaryOperator.GetOperator(token.Kind) - ?? throw new Exception($"Unexpected binary operator kind {token.Kind}."); + return BinaryOperation(node, left, node.Operation.Kind, right); } private BoundCellArrayElementAccessExpression BindCellArrayElementAccessExpression(CellArrayElementAccessExpressionSyntaxNode node) @@ -268,7 +273,7 @@ namespace Parser.Binding { var name = BindExpression(node.FunctionName); var arguments = BindExpressionList(node.Nodes); - return new BoundFunctionCallExpression(node, name, arguments); + return FunctionCall(node, name, arguments); } private BoundIdentifierNameExpression BindIdentifierNameExpression(IdentifierNameExpressionSyntaxNode node) @@ -299,27 +304,27 @@ namespace Parser.Binding private BoundNumberLiteralExpression BindNumberLiteralExpression(NumberLiteralExpressionSyntaxNode node) { var value = (double)node.Number.Value!; - return new BoundNumberLiteralExpression(node, value); + return NumberLiteral(node, value); } - private BoundParenthesizedExpression BindParenthesizedExpression(ParenthesizedExpressionSyntaxNode node) + private BoundExpression BindParenthesizedExpression(ParenthesizedExpressionSyntaxNode node) { - var expression = BindExpression(node.Expression); - return new BoundParenthesizedExpression(node, expression); + return BindExpression(node.Expression); } private BoundStringLiteralExpression BindStringLiteralExpression(StringLiteralExpressionSyntaxNode node) { var value = (string)node.StringToken.Value!; - return new BoundStringLiteralExpression(node, value); + return StringLiteral(node, value); } - private BoundUnaryPrefixOperationExpression BindUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode node) + private BoundUnaryOperationExpression BindUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode node) { - throw new NotImplementedException(); + var operand = BindExpression(node.Operand); + return UnaryOperation(node, node.Operation.Kind, operand); } - private BoundUnaryPostfixOperationExpression BindUnaryPostfixOperationExpression(UnaryPostfixOperationExpressionSyntaxNode node) + private BoundUnaryOperationExpression BindUnaryPostfixOperationExpression(UnaryPostfixOperationExpressionSyntaxNode node) { throw new NotImplementedException(); } @@ -348,12 +353,5 @@ namespace Parser.Binding { throw new NotImplementedException(); } - - public static BoundProgram BindProgram(SyntaxTree syntaxTree) - { - var binder = new Binder(); - var boundRoot = binder.BindRoot(syntaxTree.NullRoot); - return new BoundProgram(boundRoot, binder._diagnostics.ToImmutableArray()); - } } } 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/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 index d75402f..4158dcd 100644 --- a/Parser/Binding/BoundNodeKind.cs +++ b/Parser/Binding/BoundNodeKind.cs @@ -11,11 +11,14 @@ BlockStatement, ClassDeclaration, ConcreteMethodDeclaration, + ConditionalGotoStatement, EmptyStatement, ExpressionStatement, ForStatement, FunctionDeclaration, + GotoStatement, IfStatement, + LabelStatement, SwitchStatement, TryCatchStatement, WhileStatement, @@ -41,8 +44,7 @@ NumberLiteralExpression, ParenthesizedExpression, StringLiteralExpression, - UnaryPrefixOperationExpression, - UnaryPostfixOperationExpression, + UnaryOperationExpression, UnquotedStringLiteralExpression, // Parts diff --git a/Parser/Binding/BoundRoot.cs b/Parser/Binding/BoundRoot.cs index 6094363..5de782a 100644 --- a/Parser/Binding/BoundRoot.cs +++ b/Parser/Binding/BoundRoot.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Collections.Immutable; +using System.Collections.Immutable; namespace Parser.Binding { @@ -18,13 +17,13 @@ namespace Parser.Binding public class BoundFile : BoundNode { - public BoundFile(SyntaxNode syntax, ImmutableArray statements) + public BoundFile(SyntaxNode syntax, BoundStatement body) : base(syntax) { - Statements = statements; + Body = body; } - public ImmutableArray Statements { get; } + public BoundStatement Body { get; } public override BoundNodeKind Kind => BoundNodeKind.File; } @@ -88,6 +87,25 @@ namespace Parser.Binding 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) @@ -131,9 +149,22 @@ namespace Parser.Binding public override BoundNodeKind Kind => BoundNodeKind.FunctionDeclaration; } + 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, BoundElseClause? elseClause) + public BoundIfStatement(SyntaxNode syntax, BoundExpression condition, BoundStatement body, ImmutableArray elseifClauses, BoundStatement? elseClause) : base(syntax) { Condition = condition; @@ -145,11 +176,24 @@ namespace Parser.Binding public BoundExpression Condition { get; } public BoundStatement Body { get; } public ImmutableArray ElseifClauses { get; } - public BoundElseClause? ElseClause { 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) @@ -378,19 +422,6 @@ namespace Parser.Binding public override BoundNodeKind Kind => BoundNodeKind.NumberLiteralExpression; } - public class BoundParenthesizedExpression : BoundExpression - { - public BoundParenthesizedExpression(SyntaxNode syntax, BoundExpression expression) - : base(syntax) - { - Expression = expression; - } - - public override BoundNodeKind Kind => BoundNodeKind.ParenthesizedExpression; - - public BoundExpression Expression { get; } - } - public class BoundStringLiteralExpression : BoundExpression { public BoundStringLiteralExpression(SyntaxNode syntax, string value) @@ -403,24 +434,19 @@ namespace Parser.Binding public override BoundNodeKind Kind => BoundNodeKind.StringLiteralExpression; } - public class BoundUnaryPrefixOperationExpression : BoundExpression + public class BoundUnaryOperationExpression : BoundExpression { - public BoundUnaryPrefixOperationExpression(SyntaxNode syntax) + public BoundUnaryOperationExpression(SyntaxNode syntax, BoundUnaryOperator op, BoundExpression operand) : base(syntax) { + Op = op; + Operand = operand; } - public override BoundNodeKind Kind => BoundNodeKind.UnaryPrefixOperationExpression; - } + public override BoundNodeKind Kind => BoundNodeKind.UnaryOperationExpression; - public class BoundUnaryPostfixOperationExpression : BoundExpression - { - public BoundUnaryPostfixOperationExpression(SyntaxNode syntax) - : base(syntax) - { - } - - public override BoundNodeKind Kind => BoundNodeKind.UnaryPostfixOperationExpression; + public BoundUnaryOperator Op { get; } + public BoundExpression Operand { get; } } public class BoundUnquotedStringLiteralExpression : BoundExpression @@ -446,16 +472,4 @@ namespace Parser.Binding public BoundStatement Body { get; } public override BoundNodeKind Kind => BoundNodeKind.ElseIfClause; } - - public class BoundElseClause : BoundNode - { - public BoundElseClause(SyntaxNode syntax, BoundStatement body) - : base(syntax) - { - Body = body; - } - - public BoundStatement Body { get; } - public override BoundNodeKind Kind => BoundNodeKind.ElseClause; - } } diff --git a/Parser/Binding/BoundTreeRewriter.cs b/Parser/Binding/BoundTreeRewriter.cs index 025dca8..83dd602 100644 --- a/Parser/Binding/BoundTreeRewriter.cs +++ b/Parser/Binding/BoundTreeRewriter.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Immutable; +using static Parser.Binding.BoundNodeFactory; namespace Parser.Binding { @@ -17,6 +18,8 @@ namespace Parser.Binding RewriteClassDeclaration((BoundClassDeclaration)node), BoundNodeKind.ConcreteMethodDeclaration => RewriteConcreteMethodDeclaration((BoundConcreteMethodDeclaration)node), + BoundNodeKind.ConditionalGotoStatement => + RewriteConditionalGotoStatement((BoundConditionalGotoStatement)node), BoundNodeKind.EmptyStatement => RewriteEmptyStatement((BoundEmptyStatement)node), BoundNodeKind.ExpressionStatement => @@ -25,8 +28,12 @@ namespace Parser.Binding 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 => @@ -38,6 +45,22 @@ namespace Parser.Binding }; } + 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(); @@ -53,6 +76,11 @@ namespace Parser.Binding throw new NotImplementedException(); } + public virtual BoundStatement RewriteLabelStatement(BoundLabelStatement node) + { + return node; + } + public virtual BoundStatement RewriteIfStatement(BoundIfStatement node) { var condition = RewriteExpression(node.Condition); @@ -65,7 +93,7 @@ namespace Parser.Binding if (oldClause != newClause && builder is null) { builder = ImmutableArray.CreateBuilder(node.ElseifClauses.Length); - for (var j = 0; j < i; i++) + for (var j = 0; j < i; j++) { builder.Add(node.ElseifClauses[j]); } @@ -74,11 +102,10 @@ namespace Parser.Binding { builder.Add(newClause); } - } var elseIfClauses = builder is null ? node.ElseifClauses : builder.MoveToImmutable(); - var elseClause = node.ElseClause is null ? null : RewriteElseifClause(node.ElseClause); + var elseClause = node.ElseClause is null ? null : RewriteStatement(node.ElseClause); if (condition == node.Condition && body == node.Body && elseIfClauses == node.ElseifClauses && @@ -87,18 +114,7 @@ namespace Parser.Binding return node; } - return new BoundIfStatement(node.Syntax, condition, body, elseIfClauses, elseClause); - } - - public virtual BoundElseClause RewriteElseifClause(BoundElseClause node) - { - var body = RewriteStatement(node.Body); - if (body == node.Body) - { - return node; - } - - return new BoundElseClause(node.Syntax, body); + return IfStatement(node.Syntax, condition, body, elseIfClauses, elseClause); } public virtual BoundElseifClause RewriteElseifClause(BoundElseifClause node) @@ -110,7 +126,7 @@ namespace Parser.Binding return node; } - return new BoundElseifClause(node.Syntax, condition, body); + return ElseifClause(node.Syntax, condition, body); } public virtual BoundStatement RewriteFunctionDeclaration(BoundFunctionDeclaration node) @@ -131,7 +147,7 @@ namespace Parser.Binding return node; } - return new BoundExpressionStatement(node.Syntax, expression); + return ExpressionStatement(node.Syntax, expression); } public virtual BoundStatement RewriteEmptyStatement(BoundEmptyStatement node) @@ -159,7 +175,7 @@ namespace Parser.Binding if (oldStatement != newStatement && builder is null) { builder = ImmutableArray.CreateBuilder(node.Statements.Length); - for (var j = 0; j < i; i++) + for (var j = 0; j < i; j++) { builder.Add(node.Statements[j]); } @@ -176,7 +192,7 @@ namespace Parser.Binding return node; } - return new BoundBlockStatement(node.Syntax, builder.MoveToImmutable()); + return Block(node.Syntax, builder.MoveToImmutable()); } public virtual BoundStatement RewriteAbstractMethodDeclaration(BoundAbstractMethodDeclaration node) @@ -222,14 +238,10 @@ namespace Parser.Binding RewriteNamedFunctionHandleExpression((BoundNamedFunctionHandleExpression)node), BoundNodeKind.NumberLiteralExpression => RewriteNumberLiteralExpression((BoundNumberLiteralExpression)node), - BoundNodeKind.ParenthesizedExpression => - RewriteParenthesizedExpression((BoundParenthesizedExpression)node), BoundNodeKind.StringLiteralExpression => RewriteStringLiteralExpression((BoundStringLiteralExpression)node), - BoundNodeKind.UnaryPrefixOperationExpression => - RewriteUnaryPrefixOperationExpression((BoundUnaryPrefixOperationExpression)node), - BoundNodeKind.UnaryPostfixOperationExpression => - RewriteUnaryPostfixOperationExpression((BoundUnaryPostfixOperationExpression)node), + BoundNodeKind.UnaryOperationExpression => + RewriteUnaryOperationExpression((BoundUnaryOperationExpression)node), BoundNodeKind.UnquotedStringLiteralExpression => RewriteUnquotedStringLiteralExpression((BoundUnquotedStringLiteralExpression)node), _ => @@ -242,14 +254,10 @@ namespace Parser.Binding throw new NotImplementedException(); } - public virtual BoundExpression RewriteUnaryPostfixOperationExpression(BoundUnaryPostfixOperationExpression node) + public virtual BoundExpression RewriteUnaryOperationExpression(BoundUnaryOperationExpression node) { - throw new NotImplementedException(); - } - - public virtual BoundExpression RewriteUnaryPrefixOperationExpression(BoundUnaryPrefixOperationExpression node) - { - throw new NotImplementedException(); + var operand = RewriteExpression(node.Operand); + return new BoundUnaryOperationExpression(node.Syntax, node.Op, operand); } public virtual BoundExpression RewriteStringLiteralExpression(BoundStringLiteralExpression node) @@ -257,17 +265,6 @@ namespace Parser.Binding return node; } - public virtual BoundExpression RewriteParenthesizedExpression(BoundParenthesizedExpression node) - { - var expression = RewriteExpression(node.Expression); - if (expression == node.Expression) - { - return node; - } - - return new BoundParenthesizedExpression(node.Syntax, expression); - } - public virtual BoundExpression RewriteNumberLiteralExpression(BoundNumberLiteralExpression node) { return node; @@ -309,7 +306,7 @@ namespace Parser.Binding if (oldArgument != newArgument && builder is null) { builder = ImmutableArray.CreateBuilder(node.Arguments.Length); - for (var j = 0; j < i; i++) + for (var j = 0; j < i; j++) { builder.Add(node.Arguments[j]); } @@ -326,7 +323,7 @@ namespace Parser.Binding return node; } - return new BoundFunctionCallExpression(node.Syntax, node.Name, builder.MoveToImmutable()); + return FunctionCall(node.Syntax, node.Name, builder.MoveToImmutable()); } public virtual BoundExpression RewriteEmptyExpression(BoundEmptyExpression node) @@ -385,7 +382,7 @@ namespace Parser.Binding return node; } - return new BoundAssignmentExpression(node.Syntax, left, right); + return Assignment(node.Syntax, left, right); } public virtual BoundExpression RewriteArrayLiteralExpression(BoundArrayLiteralExpression node) 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/Evaluator.cs b/Parser/Evaluator.cs index 2a233a7..d5714b8 100644 --- a/Parser/Evaluator.cs +++ b/Parser/Evaluator.cs @@ -5,7 +5,6 @@ using Parser.Objects; using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; namespace Parser { @@ -33,21 +32,77 @@ namespace Parser private MObject? EvaluateFile(BoundFile root) { - MObject? lastResult = null; - foreach (var statement in root.Statements) + return EvaluateStatement(root.Body); + } + + private MObject? EvaluateBlockStatement(BoundBlockStatement node) + { + var labelToIndex = new Dictionary(); + for (var i = 0; i < node.Statements.Length; i++) { - lastResult = EvaluateStatement(statement) ?? lastResult; + 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 => @@ -165,25 +220,16 @@ namespace Parser EvaluateNamedFunctionHandleExpression((BoundNamedFunctionHandleExpression)node), BoundNodeKind.NumberLiteralExpression => EvaluateNumberLiteralExpression((BoundNumberLiteralExpression)node), - BoundNodeKind.ParenthesizedExpression => - EvaluateParenthesizedExpression((BoundParenthesizedExpression)node), BoundNodeKind.StringLiteralExpression => EvaluateStringLiteralExpression((BoundStringLiteralExpression)node), - BoundNodeKind.UnaryPrefixOperationExpression => - EvaluateUnaryPrefixOperationExpression((BoundUnaryPrefixOperationExpression)node), - BoundNodeKind.UnaryPostfixOperationExpression => - EvaluateUnaryPostfixOperationExpression((BoundUnaryPostfixOperationExpression)node), + BoundNodeKind.UnaryOperationExpression => + EvaluateUnaryOperationExpression((BoundUnaryOperationExpression)node), BoundNodeKind.UnquotedStringLiteralExpression => EvaluateUnquotedStringLiteralExpression((BoundUnquotedStringLiteralExpression)node), _ => throw new NotImplementedException($"Invalid expression kind '{node.Kind}'."), }; } - private MObject? EvaluateParenthesizedExpression(BoundParenthesizedExpression node) - { - return EvaluateExpression(node.Expression); - } - private MObject? EvaluateClassInvokation(BoundClassInvokationExpression node) { throw new NotImplementedException(); @@ -199,11 +245,6 @@ namespace Parser throw new NotImplementedException(); } - private MObject? EvaluateUnaryPostfixOperationExpression(BoundUnaryPostfixOperationExpression node) - { - throw new NotImplementedException(); - } - private MObject? EvaluateMemberAccess(BoundMemberAccessExpression node) { throw new NotImplementedException(); @@ -338,6 +379,10 @@ namespace Parser 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."), }; } @@ -347,9 +392,19 @@ namespace Parser throw new NotImplementedException(); } - private MObject? EvaluateUnaryPrefixOperationExpression(BoundUnaryPrefixOperationExpression node) + private MObject? EvaluateUnaryOperationExpression(BoundUnaryOperationExpression node) { - throw new NotImplementedException(); + 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) diff --git a/Parser/Internal/MParserGreen.cs b/Parser/Internal/MParserGreen.cs index e935f8d..2c2e250 100644 --- a/Parser/Internal/MParserGreen.cs +++ b/Parser/Internal/MParserGreen.cs @@ -1220,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 48981b9..826f4d1 100644 --- a/Parser/Internal/SyntaxFactory.Generated.cs +++ b/Parser/Internal/SyntaxFactory.Generated.cs @@ -3,9 +3,9 @@ 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 BlockStatementSyntaxNode BlockStatementSyntax(SyntaxList statements) diff --git a/Parser/Internal/SyntaxNode.Generated.cs b/Parser/Internal/SyntaxNode.Generated.cs index 014c271..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,14 @@ 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 } ; 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 index 7761f19..f454b3f 100644 --- a/Parser/MFunctions/MOperations.cs +++ b/Parser/MFunctions/MOperations.cs @@ -36,6 +36,7 @@ namespace Parser.MFunctions return null; } + public static MObject? Slash(MObject left, MObject right) { if (left is MDoubleNumber { Value: var lValue } @@ -46,5 +47,59 @@ namespace Parser.MFunctions 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/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 index c76d9e6..702e985 100644 --- a/Parser/Objects/MObject.cs +++ b/Parser/Objects/MObject.cs @@ -11,5 +11,10 @@ { return MCharArray.Create(chars); } + + public static MLogical CreateLogical(bool value) + { + return MLogical.Create(value); + } } } \ No newline at end of file diff --git a/Parser/SyntaxDefinition.xml b/Parser/SyntaxDefinition.xml index d3baf5d..fcbc09a 100644 --- a/Parser/SyntaxDefinition.xml +++ b/Parser/SyntaxDefinition.xml @@ -1,7 +1,7 @@ - + diff --git a/Parser/SyntaxNode.Generated.cs b/Parser/SyntaxNode.Generated.cs index 9b60cbd..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 } ; diff --git a/Semantics/GetClass.cs b/Semantics/GetClass.cs index 15cb673..49a38cd 100644 --- a/Semantics/GetClass.cs +++ b/Semantics/GetClass.cs @@ -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/cmi/Program.cs b/cmi/Program.cs index ec8f17d..ec5f7fe 100644 --- a/cmi/Program.cs +++ b/cmi/Program.cs @@ -4,19 +4,26 @@ 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"; } - - var fileName = args[0]; + 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) @@ -24,6 +31,7 @@ namespace cmi Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine($"{diagnostic.Span}: {diagnostic.Message}"); Console.ResetColor(); + return; } } 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/examples/helloworld/hello.m b/examples/helloworld/hello.m index 9a79ec4..6b8f93b 100644 --- a/examples/helloworld/hello.m +++ b/examples/helloworld/hello.m @@ -3,11 +3,11 @@ y = 3; disp(x + y * y); disp('Hello world!'); -% x = 2 * 3; -% if x > 5 -% y = 3; -% else -% y = 10; -% end -% -% disp(y); +x = 2 * 3; +if x > 5 + y = 'Greater than 5'; +elseif x > 0 + y = 10; +end + +disp(y); From 2f04f86af3107b10d4cdbd6854ed2193e3c74fda Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Thu, 16 Jul 2020 11:40:53 +0200 Subject: [PATCH 10/12] Implement script function --- Parser/Binding/Binder.cs | 101 ++++++++++++++++++++++++++++-- Parser/Binding/BoundProgram.cs | 25 ++++++-- Parser/Binding/BoundRoot.cs | 11 +++- Parser/Binding/FunctionSymbol.cs | 23 +++++++ Parser/Binding/ParameterSymbol.cs | 12 ++++ Parser/Evaluator.cs | 26 +++++++- Parser/Internal/DiagnosticsBag.cs | 5 ++ Parser/Internal/MParserGreen.cs | 2 +- 8 files changed, 191 insertions(+), 14 deletions(-) create mode 100644 Parser/Binding/FunctionSymbol.cs create mode 100644 Parser/Binding/ParameterSymbol.cs diff --git a/Parser/Binding/Binder.cs b/Parser/Binding/Binder.cs index a042671..e0b5c87 100644 --- a/Parser/Binding/Binder.cs +++ b/Parser/Binding/Binder.cs @@ -17,11 +17,49 @@ namespace Parser.Binding { var binder = new Binder(); var boundRoot = binder.BindRoot(syntaxTree.NullRoot); - var loweredStatement = Lowerer.Lower(boundRoot.File.Body); - var newRoot = Root( - boundRoot.Syntax, - File(boundRoot.File.Syntax, loweredStatement)); - return new BoundProgram(newRoot, binder._diagnostics.ToImmutableArray()); + 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( + name: "%script", + parameters: ImmutableArray.Empty, + declaration: null); + var body = Block(globalStatements[0].Syntax, globalStatements); + var loweredBody = Lowerer.Lower(body); + functionsBuilder.Add(scriptFunction, loweredBody); + } + else + { + } + + var functions = statements.OfType().ToArray(); + var first = true; + foreach (var function in functions) + { + var functionSymbol = new FunctionSymbol( + name: function.Name, + parameters: function.InputDescription, + declaration: (FunctionDeclarationSyntaxNode)function.Syntax); + var loweredBody = Lowerer.Lower(function.Body); + functionsBuilder.Add(functionSymbol, loweredBody); + 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 BoundRoot BindRoot(RootSyntaxNode node) @@ -148,7 +186,58 @@ namespace Parser.Binding private BoundFunctionDeclaration BindFunctionDeclaration(FunctionDeclarationSyntaxNode node) { - throw new NotImplementedException(); + 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) diff --git a/Parser/Binding/BoundProgram.cs b/Parser/Binding/BoundProgram.cs index b6cfc94..ab7eea6 100644 --- a/Parser/Binding/BoundProgram.cs +++ b/Parser/Binding/BoundProgram.cs @@ -5,16 +5,33 @@ namespace Parser.Binding { public class BoundProgram { - public BoundProgram(BoundRoot nullRoot, ImmutableArray diagnostics) + public BoundProgram( + ImmutableArray diagnostics, + FunctionSymbol? mainFunction, + FunctionSymbol? scriptFunction, + ImmutableDictionary functions) { - NullRoot = nullRoot; Diagnostics = diagnostics; + MainFunction = mainFunction; + ScriptFunction = scriptFunction; + Functions = functions; } public ImmutableArray Diagnostics { get; } - public BoundRoot NullRoot { get; } + /// + /// A "main" function (first in a file without any global statements). + /// + public FunctionSymbol? MainFunction { get; } - public BoundFile Root => NullRoot.File; + /// + /// 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 index 5de782a..3f18f1b 100644 --- a/Parser/Binding/BoundRoot.cs +++ b/Parser/Binding/BoundRoot.cs @@ -141,12 +141,21 @@ namespace Parser.Binding public class BoundFunctionDeclaration : BoundStatement { - public BoundFunctionDeclaration(SyntaxNode syntax) + 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 class BoundGotoStatement : BoundStatement diff --git a/Parser/Binding/FunctionSymbol.cs b/Parser/Binding/FunctionSymbol.cs new file mode 100644 index 0000000..bf5ee25 --- /dev/null +++ b/Parser/Binding/FunctionSymbol.cs @@ -0,0 +1,23 @@ +using System.Collections.Immutable; + +namespace Parser.Binding +{ + public class FunctionSymbol + { + public FunctionSymbol( + string name, + ImmutableArray parameters, + FunctionDeclarationSyntaxNode? declaration) + { + Name = name; + Parameters = parameters; + Declaration = declaration; + } + + public string Name { get; } + + public ImmutableArray Parameters { get; } + + public FunctionDeclarationSyntaxNode? Declaration { 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/Evaluator.cs b/Parser/Evaluator.cs index d5714b8..bb06ca0 100644 --- a/Parser/Evaluator.cs +++ b/Parser/Evaluator.cs @@ -26,8 +26,30 @@ namespace Parser internal EvaluationResult Evaluate() { - var result = EvaluateFile(_program.Root); - return new EvaluationResult(result, _diagnostics.ToImmutableArray()); + if (_program.MainFunction is { } mainFunction) + { + if (mainFunction.Parameters.Length > 0) + { + _diagnostics.ReportNotEnoughInputs( + new TextSpan(mainFunction.Declaration.Position, mainFunction.Declaration.Position + mainFunction.Declaration.FullWidth), + mainFunction.Name); + return new EvaluationResult(null, _diagnostics.ToImmutableArray()); + } + else + { + var result = EvaluateBlockStatement(_program.Functions[mainFunction]); + return new EvaluationResult(result, _diagnostics.ToImmutableArray()); + } + } + else if (_program.ScriptFunction is { } scriptFunction) + { + var result = EvaluateBlockStatement(_program.Functions[scriptFunction]); + return new EvaluationResult(result, _diagnostics.ToImmutableArray()); + } + else + { + return new EvaluationResult(null, _diagnostics.ToImmutableArray()); + } } private MObject? EvaluateFile(BoundFile root) diff --git a/Parser/Internal/DiagnosticsBag.cs b/Parser/Internal/DiagnosticsBag.cs index 76f1540..949b51a 100644 --- a/Parser/Internal/DiagnosticsBag.cs +++ b/Parser/Internal/DiagnosticsBag.cs @@ -38,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."); diff --git a/Parser/Internal/MParserGreen.cs b/Parser/Internal/MParserGreen.cs index 2c2e250..dfce71e 100644 --- a/Parser/Internal/MParserGreen.cs +++ b/Parser/Internal/MParserGreen.cs @@ -175,7 +175,7 @@ namespace Parser.Internal if (CurrentToken.Kind == TokenKind.TildeToken) { var notToken = EatToken(); - builder.Add(notToken); + builder.Add(Factory.IdentifierNameExpressionSyntax(notToken)); } else { From 5e9111a08529a5ce71fc62b5c34a721766230df2 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Thu, 16 Jul 2020 11:50:19 +0200 Subject: [PATCH 11/12] Fix REPL context handling --- Parser/Compilation.cs | 4 ++-- Parser/Evaluator.cs | 40 ++++++++++++---------------------------- Repl/MRepl.cs | 2 +- cmi/Program.cs | 2 +- 4 files changed, 16 insertions(+), 32 deletions(-) diff --git a/Parser/Compilation.cs b/Parser/Compilation.cs index 8744a58..d566e7e 100644 --- a/Parser/Compilation.cs +++ b/Parser/Compilation.cs @@ -21,7 +21,7 @@ namespace Parser return Binder.BindProgram(_syntaxTree); } - public EvaluationResult Evaluate(CompilationContext context) + public EvaluationResult Evaluate(CompilationContext context, bool inRepl) { var program = GetBoundProgram(); if (program.Diagnostics.Length > 0) @@ -29,7 +29,7 @@ namespace Parser return new EvaluationResult(null, program.Diagnostics); } - var evaluator = new Evaluator(program, context); + var evaluator = new Evaluator(program, context, inRepl); return evaluator.Evaluate(); } } diff --git a/Parser/Evaluator.cs b/Parser/Evaluator.cs index bb06ca0..efa86c8 100644 --- a/Parser/Evaluator.cs +++ b/Parser/Evaluator.cs @@ -13,15 +13,16 @@ namespace Parser private readonly BoundProgram _program; private readonly CompilationContext _context; private readonly DiagnosticsBag _diagnostics = new DiagnosticsBag(); - private bool _insideFunction = false; + private bool _inRepl = false; private readonly Stack _scopeStack = new Stack(); - public Evaluator(BoundProgram program, CompilationContext context) + public Evaluator(BoundProgram program, CompilationContext context, bool inRepl) { _program = program; _context = context; var outerScope = new EvaluationScope(); _scopeStack.Push(outerScope); + _inRepl = inRepl; } internal EvaluationResult Evaluate() @@ -33,7 +34,7 @@ namespace Parser _diagnostics.ReportNotEnoughInputs( new TextSpan(mainFunction.Declaration.Position, mainFunction.Declaration.Position + mainFunction.Declaration.FullWidth), mainFunction.Name); - return new EvaluationResult(null, _diagnostics.ToImmutableArray()); + return new EvaluationResult(null, _diagnostics.ToImmutableArray()); } else { @@ -458,44 +459,27 @@ namespace Parser private MObject? GetVariableValue(string name) { - if (_insideFunction) + if (_inRepl) { - if (_context.Variables.TryGetValue(name, out var globalValue)) - { - return globalValue; - } - - var currentScope = _scopeStack.Peek(); - return currentScope.Variables.TryGetValue(name, out var localValue) ? globalValue : null; + return _context.Variables.TryGetValue(name, out var globalValue) ? globalValue : null; } else { - if (_context.Variables.TryGetValue(name, out var globalValue)) - { - return globalValue; - } - - return null; + var currentScope = _scopeStack.Peek(); + return currentScope.Variables.TryGetValue(name, out var localValue) ? localValue : null; } } private void SetVariableValue(string name, MObject value) { - if (_insideFunction) + if (_inRepl) { - if (_context.Variables.ContainsKey(name)) - { - _context.Variables[name] = value; - } - else - { - var currentScope = _scopeStack.Peek(); - currentScope.Variables[name] = value; - } + _context.Variables[name] = value; } else { - _context.Variables[name] = value; + var currentScope = _scopeStack.Peek(); + currentScope.Variables[name] = value; } } diff --git a/Repl/MRepl.cs b/Repl/MRepl.cs index ed902d0..c8b1b81 100644 --- a/Repl/MRepl.cs +++ b/Repl/MRepl.cs @@ -65,7 +65,7 @@ namespace Repl TreeRenderer.RenderTree(tree); var compilation = Compilation.Create(tree); - var evaluationResult = compilation.Evaluate(_context); + var evaluationResult = compilation.Evaluate(_context, inRepl: true); foreach (var diagnostic in evaluationResult.Diagnostics) { diff --git a/cmi/Program.cs b/cmi/Program.cs index ec5f7fe..f1f0042 100644 --- a/cmi/Program.cs +++ b/cmi/Program.cs @@ -36,7 +36,7 @@ namespace cmi } var context = new CompilationContext(); - var evaluationResult = compilation.Evaluate(context); + var evaluationResult = compilation.Evaluate(context, inRepl: false); foreach (var diagnostic in evaluationResult.Diagnostics) { From f6de2931ea82dc846ecf3376606e02b56f739134 Mon Sep 17 00:00:00 2001 From: Alexander Luzgarev Date: Thu, 16 Jul 2020 12:29:41 +0200 Subject: [PATCH 12/12] Implement function calls --- Parser/Binding/Binder.cs | 38 ++++++---- Parser/Binding/BoundProgram.cs | 4 +- Parser/Binding/BoundRoot.cs | 15 ++++ Parser/Binding/FunctionSymbol.cs | 14 +--- Parser/Binding/LoweredFunction.cs | 26 +++++++ Parser/Evaluator.cs | 74 ++++++++++++++++--- Parser/Internal/DiagnosticsBag.cs | 10 +++ ...nSymbol.cs => UnresolvedFunctionSymbol.cs} | 4 +- examples/helloworld/hello.m | 20 +++-- 9 files changed, 155 insertions(+), 50 deletions(-) create mode 100644 Parser/Binding/LoweredFunction.cs rename Parser/{FunctionSymbol.cs => UnresolvedFunctionSymbol.cs} (54%) diff --git a/Parser/Binding/Binder.cs b/Parser/Binding/Binder.cs index e0b5c87..9b8fccd 100644 --- a/Parser/Binding/Binder.cs +++ b/Parser/Binding/Binder.cs @@ -18,23 +18,24 @@ namespace Parser.Binding var binder = new Binder(); var boundRoot = binder.BindRoot(syntaxTree.NullRoot); var statements = ((BoundBlockStatement)boundRoot.File.Body).Statements; - var functionsBuilder = ImmutableDictionary.CreateBuilder(); + 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( - name: "%script", - parameters: ImmutableArray.Empty, - declaration: null); + scriptFunction = new FunctionSymbol("%script"); var body = Block(globalStatements[0].Syntax, globalStatements); var loweredBody = Lowerer.Lower(body); - functionsBuilder.Add(scriptFunction, loweredBody); - } - else - { + 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(); @@ -42,11 +43,9 @@ namespace Parser.Binding foreach (var function in functions) { var functionSymbol = new FunctionSymbol( - name: function.Name, - parameters: function.InputDescription, - declaration: (FunctionDeclarationSyntaxNode)function.Syntax); - var loweredBody = Lowerer.Lower(function.Body); - functionsBuilder.Add(functionSymbol, loweredBody); + 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". @@ -62,6 +61,17 @@ namespace Parser.Binding 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); diff --git a/Parser/Binding/BoundProgram.cs b/Parser/Binding/BoundProgram.cs index ab7eea6..ebf8d9d 100644 --- a/Parser/Binding/BoundProgram.cs +++ b/Parser/Binding/BoundProgram.cs @@ -9,7 +9,7 @@ namespace Parser.Binding ImmutableArray diagnostics, FunctionSymbol? mainFunction, FunctionSymbol? scriptFunction, - ImmutableDictionary functions) + ImmutableDictionary functions) { Diagnostics = diagnostics; MainFunction = mainFunction; @@ -32,6 +32,6 @@ namespace Parser.Binding /// /// So-called "local" functions. /// - public ImmutableDictionary Functions { get; } + public ImmutableDictionary Functions { get; } } } diff --git a/Parser/Binding/BoundRoot.cs b/Parser/Binding/BoundRoot.cs index 3f18f1b..5f9d0ca 100644 --- a/Parser/Binding/BoundRoot.cs +++ b/Parser/Binding/BoundRoot.cs @@ -156,6 +156,21 @@ namespace Parser.Binding 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 diff --git a/Parser/Binding/FunctionSymbol.cs b/Parser/Binding/FunctionSymbol.cs index bf5ee25..311d052 100644 --- a/Parser/Binding/FunctionSymbol.cs +++ b/Parser/Binding/FunctionSymbol.cs @@ -1,23 +1,13 @@ -using System.Collections.Immutable; - -namespace Parser.Binding +namespace Parser.Binding { public class FunctionSymbol { public FunctionSymbol( - string name, - ImmutableArray parameters, - FunctionDeclarationSyntaxNode? declaration) + string name) { Name = name; - Parameters = parameters; - Declaration = declaration; } public string Name { get; } - - public ImmutableArray Parameters { get; } - - public FunctionDeclarationSyntaxNode? Declaration { 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/Evaluator.cs b/Parser/Evaluator.cs index efa86c8..b03aa7d 100644 --- a/Parser/Evaluator.cs +++ b/Parser/Evaluator.cs @@ -5,6 +5,7 @@ using Parser.Objects; using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; namespace Parser { @@ -15,6 +16,7 @@ namespace Parser 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) { @@ -23,28 +25,34 @@ namespace Parser 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 { } mainFunction) + if (_program.MainFunction is { } mainFunctionSymbol) { - if (mainFunction.Parameters.Length > 0) + var mainFunction = _program.Functions[mainFunctionSymbol]; + if (mainFunction.InputDescription.Length > 0) { _diagnostics.ReportNotEnoughInputs( - new TextSpan(mainFunction.Declaration.Position, mainFunction.Declaration.Position + mainFunction.Declaration.FullWidth), + 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(_program.Functions[mainFunction]); + var result = EvaluateBlockStatement(mainFunction.Body); return new EvaluationResult(result, _diagnostics.ToImmutableArray()); } } - else if (_program.ScriptFunction is { } scriptFunction) + else if (_program.ScriptFunction is { } scriptFunctionSymbol) { - var result = EvaluateBlockStatement(_program.Functions[scriptFunction]); + var scriptFunction = _program.Functions[scriptFunctionSymbol]; + var result = EvaluateBlockStatement(scriptFunction.Body); return new EvaluationResult(result, _diagnostics.ToImmutableArray()); } else @@ -304,10 +312,58 @@ namespace Parser } else { - throw new NotImplementedException("Functions are not supported."); + 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) @@ -319,11 +375,11 @@ namespace Parser return arguments[0]; } - private FunctionSymbol GetFunctionSymbol(BoundExpression functionName) + private UnresolvedFunctionSymbol GetFunctionSymbol(BoundExpression functionName) { if (functionName.Kind == BoundNodeKind.IdentifierNameExpression) { - return new FunctionSymbol(((BoundIdentifierNameExpression)functionName).Name); + return new UnresolvedFunctionSymbol(((BoundIdentifierNameExpression)functionName).Name); } throw new NotImplementedException($"Unknown function symbol '{functionName.Syntax.Text}'."); diff --git a/Parser/Internal/DiagnosticsBag.cs b/Parser/Internal/DiagnosticsBag.cs index 949b51a..a906357 100644 --- a/Parser/Internal/DiagnosticsBag.cs +++ b/Parser/Internal/DiagnosticsBag.cs @@ -92,5 +92,15 @@ namespace Parser.Internal { 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/FunctionSymbol.cs b/Parser/UnresolvedFunctionSymbol.cs similarity index 54% rename from Parser/FunctionSymbol.cs rename to Parser/UnresolvedFunctionSymbol.cs index eb43cf0..76dfcda 100644 --- a/Parser/FunctionSymbol.cs +++ b/Parser/UnresolvedFunctionSymbol.cs @@ -1,10 +1,10 @@ namespace Parser { - internal class FunctionSymbol + internal class UnresolvedFunctionSymbol { public string Name { get; } - public FunctionSymbol(string name) + public UnresolvedFunctionSymbol(string name) { Name = name; } diff --git a/examples/helloworld/hello.m b/examples/helloworld/hello.m index 6b8f93b..fe26aae 100644 --- a/examples/helloworld/hello.m +++ b/examples/helloworld/hello.m @@ -1,13 +1,11 @@ x = 2; -y = 3; -disp(x + y * y); -disp('Hello world!'); +f(x); +f(x); -x = 2 * 3; -if x > 5 - y = 'Greater than 5'; -elseif x > 0 - y = 10; -end - -disp(y); +function f(x) + disp('X was'); + disp(x); + x = x + 1; + disp('X is') + disp(x); +end \ No newline at end of file