527 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			527 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System.Collections.Generic;
 | 
						|
using System.Linq;
 | 
						|
using System.Reflection.Metadata;
 | 
						|
using Lexer;
 | 
						|
 | 
						|
namespace Parser
 | 
						|
{
 | 
						|
    public class SyntaxFactory
 | 
						|
    {
 | 
						|
        private static SyntaxNode SetParent(SyntaxNode parent)
 | 
						|
        {
 | 
						|
            foreach (var node in parent.Children)
 | 
						|
            {
 | 
						|
                node.Parent = parent;
 | 
						|
            }
 | 
						|
 | 
						|
            return parent;
 | 
						|
        }
 | 
						|
        
 | 
						|
        public FunctionDeclarationNode FunctionDeclaration(
 | 
						|
            TokenNode functionKeyword,
 | 
						|
            FunctionOutputDescriptionNode outputDescription,
 | 
						|
            TokenNode name,
 | 
						|
            FunctionInputDescriptionNode inputDescription,
 | 
						|
            StatementListNode body,
 | 
						|
            TokenNode end,
 | 
						|
            TokenNode semicolonOrComma = null)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode> {functionKeyword};
 | 
						|
            if (outputDescription != null)
 | 
						|
            {
 | 
						|
                children.Add(outputDescription);
 | 
						|
            }
 | 
						|
            children.Add(name);
 | 
						|
            children.Add(inputDescription);
 | 
						|
            children.Add(body);
 | 
						|
            if (end != null)
 | 
						|
            {
 | 
						|
                children.Add(end);
 | 
						|
            }
 | 
						|
            if (semicolonOrComma != null)
 | 
						|
            {
 | 
						|
                children.Add(semicolonOrComma);
 | 
						|
            }
 | 
						|
            var result =
 | 
						|
                new FunctionDeclarationNode(
 | 
						|
                    children,
 | 
						|
                    functionKeyword,
 | 
						|
                    outputDescription,
 | 
						|
                    name,
 | 
						|
                    inputDescription,
 | 
						|
                    body,
 | 
						|
                    end,
 | 
						|
                    semicolonOrComma);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public FunctionOutputDescriptionNode FunctionOutputDescription(
 | 
						|
            List<SyntaxNode> nodes,
 | 
						|
            TokenNode equalitySign)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>(nodes);
 | 
						|
            nodes.Add(equalitySign);
 | 
						|
            var result = new FunctionOutputDescriptionNode(
 | 
						|
                nodes,
 | 
						|
                nodes
 | 
						|
                    .Where(node => node is TokenNode && ((TokenNode) node).Token.Kind == TokenKind.Identifier)
 | 
						|
                    .Select(node => node as TokenNode)
 | 
						|
                    .ToList(),
 | 
						|
                equalitySign
 | 
						|
                );
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public ParameterListNode ParameterList(List<SyntaxNode> nodes)
 | 
						|
        {
 | 
						|
            var result = new ParameterListNode(
 | 
						|
                nodes,
 | 
						|
                nodes
 | 
						|
                    .Where(
 | 
						|
                        node => node is TokenNode && ((TokenNode) node).Token.Kind != TokenKind.Comma
 | 
						|
                    ).ToList());
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public StatementListNode StatementList(List<SyntaxNode> nodes)
 | 
						|
        {
 | 
						|
            var result = new StatementListNode(nodes);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public FunctionInputDescriptionNode FunctionInputDescription(
 | 
						|
            TokenNode openingBracket,
 | 
						|
            ParameterListNode parameterList,
 | 
						|
            TokenNode closingBracket)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                openingBracket,
 | 
						|
                parameterList,
 | 
						|
                closingBracket
 | 
						|
            };
 | 
						|
            var result = new FunctionInputDescriptionNode(children, openingBracket, parameterList, closingBracket);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public TokenNode Token(Token token)
 | 
						|
        {
 | 
						|
            return new TokenNode(token);
 | 
						|
        }
 | 
						|
 | 
						|
        public SwitchStatementNode SwitchStatement(
 | 
						|
            TokenNode switchKeyword,
 | 
						|
            ExpressionNode switchExpression,
 | 
						|
            List<SwitchCaseNode> cases,
 | 
						|
            TokenNode endKeyword,
 | 
						|
            TokenNode semicolonOrComma = null)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode> { switchKeyword, switchExpression };
 | 
						|
            children.AddRange(cases);
 | 
						|
            children.Add(endKeyword);
 | 
						|
            if (semicolonOrComma != null)
 | 
						|
            {
 | 
						|
                children.Add(semicolonOrComma);
 | 
						|
            }
 | 
						|
 | 
						|
            var result = new SwitchStatementNode(
 | 
						|
                children,
 | 
						|
                switchKeyword,
 | 
						|
                switchExpression,
 | 
						|
                cases,
 | 
						|
                endKeyword,
 | 
						|
                semicolonOrComma);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public SwitchCaseNode SwitchCase(
 | 
						|
            TokenNode caseKeyword,
 | 
						|
            TokenNode caseIdentifier,
 | 
						|
            StatementListNode statementList)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                caseKeyword,
 | 
						|
                caseIdentifier,
 | 
						|
                statementList
 | 
						|
            };
 | 
						|
            var result = new SwitchCaseNode(children, caseKeyword, caseIdentifier, statementList);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public AssignmentExpressionNode AssignmentExpression(
 | 
						|
            ExpressionNode lhs,
 | 
						|
            TokenNode assignmentSign,
 | 
						|
            ExpressionNode rhs)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                lhs,
 | 
						|
                assignmentSign,
 | 
						|
                rhs
 | 
						|
            };
 | 
						|
            var result = new AssignmentExpressionNode(children, lhs, assignmentSign, rhs);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public UnaryPrefixOperationExpressionNode UnaryPrefixOperationExpression(
 | 
						|
            TokenNode operation,
 | 
						|
            ExpressionNode operand)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                operation,
 | 
						|
                operand
 | 
						|
            };
 | 
						|
            var result = new UnaryPrefixOperationExpressionNode(children, operation, operand);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public UnaryPostfixOperationExpressionNode UnaryPostfixOperationExpression(
 | 
						|
            ExpressionNode operand,
 | 
						|
            TokenNode operation)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                operand,
 | 
						|
                operation
 | 
						|
            };
 | 
						|
            var result = new UnaryPostfixOperationExpressionNode(children, operand, operation);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public BinaryOperationExpressionNode BinaryOperationExpression(
 | 
						|
            ExpressionNode lhs,
 | 
						|
            TokenNode operation,
 | 
						|
            ExpressionNode rhs)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                lhs,
 | 
						|
                operation,
 | 
						|
                rhs
 | 
						|
            };
 | 
						|
            var result = new BinaryOperationExpressionNode(children, lhs, operation, rhs);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public IdentifierNameNode IdentifierName(
 | 
						|
            Token identifier)
 | 
						|
        {
 | 
						|
            return new IdentifierNameNode(identifier);
 | 
						|
        }
 | 
						|
 | 
						|
        public NumberLiteralNode NumberLiteral(
 | 
						|
            Token numberLiteral)
 | 
						|
        {
 | 
						|
            return new NumberLiteralNode(numberLiteral);
 | 
						|
        }
 | 
						|
 | 
						|
        public StringLiteralNode StringLiteral(
 | 
						|
            Token stringLiteral)
 | 
						|
        {
 | 
						|
            return new StringLiteralNode(stringLiteral);
 | 
						|
        }
 | 
						|
 | 
						|
        public ExpressionStatementNode ExpressionStatement(ExpressionNode expression)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode> {expression};
 | 
						|
            var result = new ExpressionStatementNode(children, expression, null);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public ExpressionStatementNode ExpressionStatement(ExpressionNode expression, TokenNode semicolonOrComma)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode> {expression, semicolonOrComma};
 | 
						|
            var result = new ExpressionStatementNode(children, expression, semicolonOrComma);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public CellArrayElementAccessExpressionNode CellArrayElementAccessExpression(
 | 
						|
            ExpressionNode cellArray,
 | 
						|
            TokenNode openingBrace,
 | 
						|
            ExpressionNode index,
 | 
						|
            TokenNode closingBrace)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode> {cellArray, openingBrace, index, closingBrace};
 | 
						|
            var result = new CellArrayElementAccessExpressionNode(
 | 
						|
                children,
 | 
						|
                cellArray,
 | 
						|
                openingBrace,
 | 
						|
                index,
 | 
						|
                closingBrace);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public FunctionCallExpressionNode FunctionCallExpression(
 | 
						|
            ExpressionNode functionName,
 | 
						|
            TokenNode openingBracket,
 | 
						|
            FunctionCallParameterListNode parameters,
 | 
						|
            TokenNode closingBracket)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                functionName,
 | 
						|
                openingBracket,
 | 
						|
                parameters,
 | 
						|
                closingBracket
 | 
						|
            };
 | 
						|
            var result = new FunctionCallExpressionNode(
 | 
						|
                children,
 | 
						|
                functionName,
 | 
						|
                openingBracket,
 | 
						|
                parameters,
 | 
						|
                closingBracket);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
        
 | 
						|
        public FunctionCallParameterListNode FunctionCallParameterList(List<SyntaxNode> nodes)
 | 
						|
        {
 | 
						|
            var result = new FunctionCallParameterListNode(
 | 
						|
                nodes,
 | 
						|
                nodes
 | 
						|
                    .OfType<ExpressionNode>()
 | 
						|
                    .ToList());
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public ArrayElementListNode ArrayElementList(List<SyntaxNode> nodes)
 | 
						|
        {
 | 
						|
            var result = new ArrayElementListNode(
 | 
						|
                nodes,
 | 
						|
                nodes
 | 
						|
                    .OfType<ExpressionNode>()
 | 
						|
                    .ToList());
 | 
						|
            SetParent(result);
 | 
						|
            return result;            
 | 
						|
        }
 | 
						|
 | 
						|
        public ArrayLiteralExpressionNode ArrayLiteralExpression(
 | 
						|
            TokenNode openingSquareBracket,
 | 
						|
            ArrayElementListNode elements,
 | 
						|
            TokenNode closingSquareBracket)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                openingSquareBracket,
 | 
						|
                elements,
 | 
						|
                closingSquareBracket
 | 
						|
            };
 | 
						|
            var result = new ArrayLiteralExpressionNode(
 | 
						|
                children,
 | 
						|
                openingSquareBracket,
 | 
						|
                elements,
 | 
						|
                closingSquareBracket);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public CellArrayLiteralExpressionNode CellArrayLiteralExpression(
 | 
						|
            TokenNode openingBrace,
 | 
						|
            ArrayElementListNode elements,
 | 
						|
            TokenNode closingBrace)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                openingBrace,
 | 
						|
                elements,
 | 
						|
                closingBrace
 | 
						|
            };
 | 
						|
            var result = new CellArrayLiteralExpressionNode(
 | 
						|
                children,
 | 
						|
                openingBrace,
 | 
						|
                elements,
 | 
						|
                closingBrace);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public EmptyExpressionNode EmptyExpression()
 | 
						|
        {
 | 
						|
            return new EmptyExpressionNode();
 | 
						|
        }
 | 
						|
 | 
						|
        public MemberAccessNode MemberAccess(
 | 
						|
            SyntaxNode leftOperand,
 | 
						|
            TokenNode dot,
 | 
						|
            SyntaxNode rightOperand)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                leftOperand,
 | 
						|
                dot,
 | 
						|
                rightOperand
 | 
						|
            };
 | 
						|
            var result = new MemberAccessNode(
 | 
						|
                children,
 | 
						|
                leftOperand,
 | 
						|
                dot,
 | 
						|
                rightOperand);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public WhileStatementNode WhileStatement(
 | 
						|
            TokenNode whileKeyword,
 | 
						|
            ExpressionNode condition,
 | 
						|
            StatementListNode body,
 | 
						|
            TokenNode end,
 | 
						|
            List<TokenNode> optionalCommasAfterCondition = null,
 | 
						|
            TokenNode semicolonOrComma = null)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                whileKeyword,
 | 
						|
                condition,
 | 
						|
            };
 | 
						|
            if (optionalCommasAfterCondition != null)
 | 
						|
            {
 | 
						|
                children.AddRange(optionalCommasAfterCondition);
 | 
						|
            }
 | 
						|
 | 
						|
            children.Add(body);
 | 
						|
            children.Add(end);
 | 
						|
            if (semicolonOrComma != null)
 | 
						|
            {
 | 
						|
                children.Add(semicolonOrComma);
 | 
						|
            }
 | 
						|
            var result = new WhileStatementNode(
 | 
						|
                children,
 | 
						|
                whileKeyword,
 | 
						|
                condition,
 | 
						|
                optionalCommasAfterCondition,
 | 
						|
                body,
 | 
						|
                end,
 | 
						|
                semicolonOrComma);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public StatementNode AppendSemicolonOrComma(StatementNode statement, TokenNode semicolonOrComma)
 | 
						|
        {
 | 
						|
            statement.SemicolonOrComma = semicolonOrComma;
 | 
						|
            statement.Children.Add(semicolonOrComma);
 | 
						|
            statement.Children[statement.Children.Count - 1].Parent = statement;
 | 
						|
            return statement;
 | 
						|
        }
 | 
						|
 | 
						|
        public IfStatementNode IfStatement(
 | 
						|
            TokenNode ifKeyword,
 | 
						|
            ExpressionNode condition,
 | 
						|
            StatementListNode body,
 | 
						|
            TokenNode elseKeyword,
 | 
						|
            StatementListNode elseBody,
 | 
						|
            TokenNode endKeyword,
 | 
						|
            List<TokenNode> optionalCommasAfterCondition = null)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                ifKeyword,
 | 
						|
                condition
 | 
						|
            };
 | 
						|
            if (optionalCommasAfterCondition != null)
 | 
						|
            {
 | 
						|
                children.AddRange(optionalCommasAfterCondition);
 | 
						|
            }
 | 
						|
 | 
						|
            children.Add(body);
 | 
						|
            if (elseKeyword != null)
 | 
						|
            {
 | 
						|
                children.Add(elseKeyword);
 | 
						|
                children.Add(elseBody);
 | 
						|
            }
 | 
						|
 | 
						|
            children.Add(endKeyword);
 | 
						|
            var result = new IfStatementNode(
 | 
						|
                children,
 | 
						|
                ifKeyword,
 | 
						|
                condition,
 | 
						|
                optionalCommasAfterCondition,
 | 
						|
                body,
 | 
						|
                elseKeyword,
 | 
						|
                elseBody,
 | 
						|
                endKeyword);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public ParenthesizedExpressionNode ParenthesizedExpression(
 | 
						|
            TokenNode openParen,
 | 
						|
            ExpressionNode expression,
 | 
						|
            TokenNode closeParen)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                openParen,
 | 
						|
                expression,
 | 
						|
                closeParen
 | 
						|
            };
 | 
						|
            var result = new ParenthesizedExpressionNode(
 | 
						|
                children,
 | 
						|
                openParen,
 | 
						|
                expression,
 | 
						|
                closeParen);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public ForStatementNode ForStatement(
 | 
						|
            TokenNode forKeyword,
 | 
						|
            AssignmentExpressionNode forAssignment,
 | 
						|
            StatementListNode body,
 | 
						|
            TokenNode endKeyword)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                forKeyword,
 | 
						|
                forAssignment,
 | 
						|
                body,
 | 
						|
                endKeyword
 | 
						|
            };
 | 
						|
            var result = new ForStatementNode(
 | 
						|
                children,
 | 
						|
                forKeyword,
 | 
						|
                forAssignment,
 | 
						|
                body,
 | 
						|
                endKeyword);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        public IndirectMemberAccessNode IndirectMemberAccess(
 | 
						|
            TokenNode openingBracket,
 | 
						|
            ExpressionNode indirectMemberName,
 | 
						|
            TokenNode closingBracket)
 | 
						|
        {
 | 
						|
            var children = new List<SyntaxNode>
 | 
						|
            {
 | 
						|
                openingBracket,
 | 
						|
                indirectMemberName,
 | 
						|
                closingBracket
 | 
						|
            };
 | 
						|
            var result = new IndirectMemberAccessNode(
 | 
						|
                children,
 | 
						|
                openingBracket,
 | 
						|
                indirectMemberName,
 | 
						|
                closingBracket);
 | 
						|
            SetParent(result);
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
    }
 | 
						|
} |