using System.Collections.Generic; using System.Linq; using Lexer; namespace Parser { public class SyntaxNode { public SyntaxNode Parent { get; set; } public List Children { get; } public virtual IEnumerable ChildTokens => Children.SelectMany(c => c.ChildTokens); public SyntaxNode(List children) { Children = children; } public virtual string FullText => string.Join("", Children.Select(c => c.FullText)); public List TrailingTrivia { get { if (ChildTokens.Any()) { return ChildTokens.Last().TrailingTrivia; } else { return new List(); } } } } public class TokenNode : SyntaxNode { public Token Token { get; } public TokenNode(Token token) : base(null) { Token = token; } public override string FullText => Token.FullText; public override IEnumerable ChildTokens { get { yield return Token; } } } public class OutputIdentifierNode : SyntaxNode { public OutputIdentifierNode(List children) : base(children) { } } public class FunctionOutputDescriptionNode : SyntaxNode { public List Outputs { get; } public TokenNode EqualitySign { get; } public FunctionOutputDescriptionNode( List children, List outputs, TokenNode equalitySign) : base(children) { Outputs = outputs; EqualitySign = equalitySign; } } public class FunctionInputDescriptionNode : SyntaxNode { public TokenNode OpeningBracket { get; } public ParameterListNode Parameters { get; } public TokenNode ClosingBracket { get; } public FunctionInputDescriptionNode( List children, TokenNode openingBracket, ParameterListNode parameters, TokenNode closingBracket) : base(children) { OpeningBracket = openingBracket; Parameters = parameters; ClosingBracket = closingBracket; } } public class FunctionDeclarationNode : StatementNode { public TokenNode Token { get; } public FunctionOutputDescriptionNode OutputDescription { get; } public TokenNode Name { get; } public FunctionInputDescriptionNode InputDescription { get; } public StatementListNode Body { get; } public TokenNode End { get; } public FunctionDeclarationNode( List children, TokenNode token, FunctionOutputDescriptionNode outputDescription, TokenNode name, FunctionInputDescriptionNode inputDescription, StatementListNode body, TokenNode end, TokenNode semicolonOrComma ) : base(children, semicolonOrComma) { Token = token; OutputDescription = outputDescription; Name = name; InputDescription = inputDescription; Body = body; End = end; } } public class StatementListNode : SyntaxNode { public List Statements => Children; public StatementListNode(List children) : base(children) { } } public class ParameterListNode : SyntaxNode { public List Parameters { get; } public ParameterListNode(List children, List parameters) : base(children) { Parameters = parameters; } } public class ExpressionNode : SyntaxNode { public ExpressionNode(List children) : base(children) { } } public class AssignmentExpressionNode : ExpressionNode { public ExpressionNode Lhs { get; } public TokenNode Assignment { get; } public ExpressionNode Rhs { get; } public AssignmentExpressionNode( List children, ExpressionNode lhs, TokenNode assignment, ExpressionNode rhs) : base(children) { Lhs = lhs; Assignment = assignment; Rhs = rhs; } } public class UnaryPrefixOperationExpressionNode : ExpressionNode { public TokenNode Operation { get; } public ExpressionNode Operand { get; } public UnaryPrefixOperationExpressionNode( List children, TokenNode operation, ExpressionNode operand) : base(children) { Operation = operation; Operand = operand; } } public class UnaryPostfixOperationExpressionNode : ExpressionNode { public ExpressionNode Operand { get; } public TokenNode Operation { get; } public UnaryPostfixOperationExpressionNode( List children, ExpressionNode operand, TokenNode operation) : base(children) { Operand = operand; Operation = operation; } } public class BinaryOperationExpressionNode : ExpressionNode { public ExpressionNode Lhs { get; } public TokenNode Operation { get; } public ExpressionNode Rhs { get; } public BinaryOperationExpressionNode( List children, ExpressionNode lhs, TokenNode operation, ExpressionNode rhs) : base(children) { Lhs = lhs; Operation = operation; Rhs = rhs; } } public class SwitchStatementNode : StatementNode { public TokenNode SwitchKeyword { get; } public ExpressionNode SwitchExpression { get; } public List OptionalCommasAfterExpression { get; } public List Cases { get; } public TokenNode EndKeyword { get; } public SwitchStatementNode( List children, TokenNode switchKeyword, ExpressionNode switchExpression, List cases, TokenNode endKeyword, TokenNode semicolonOrComma, List optionalCommasAfterExpression = null ) : base(children, semicolonOrComma) { SwitchKeyword = switchKeyword; SwitchExpression = switchExpression; OptionalCommasAfterExpression = optionalCommasAfterExpression; Cases = cases; EndKeyword = endKeyword; } } public class SwitchCaseNode : SyntaxNode { public TokenNode CaseKeyword { get; } public ExpressionNode CaseIdentifier { get; } public List OptionalCommasAfterIdentifier { get; } public StatementListNode StatementList { get; } public SwitchCaseNode( List children, TokenNode caseKeyword, ExpressionNode caseIdentifier, StatementListNode statementList, List optionalCommasAfterIdentifier = null ) : base(children) { CaseKeyword = caseKeyword; CaseIdentifier = caseIdentifier; StatementList = statementList; OptionalCommasAfterIdentifier = optionalCommasAfterIdentifier; } } public class IdentifierNameNode : ExpressionNode { public Token Token { get; } public IdentifierNameNode(Token token) : base(null) { Token = token; } public override string FullText => Token.FullText; public override IEnumerable ChildTokens { get { yield return Token; } } } public class NumberLiteralNode : ExpressionNode { public Token Token { get; } public NumberLiteralNode(Token token) : base(null) { Token = token; } public override string FullText => Token.FullText; public override IEnumerable ChildTokens { get { yield return Token; } } } public class StringLiteralNode : ExpressionNode { public Token Token { get; } public StringLiteralNode(Token token) : base(null) { Token = token; } public override string FullText => Token.FullText; public override IEnumerable ChildTokens { get { yield return Token; } } } public class DoubleQuotedStringLiteralNode : ExpressionNode { public Token Token { get; } public DoubleQuotedStringLiteralNode(Token token) : base(null) { Token = token; } public override string FullText => Token.FullText; public override IEnumerable ChildTokens { get { yield return Token; } } } public class UnquotedStringLiteralNode : ExpressionNode { public Token Token { get; } public UnquotedStringLiteralNode(Token token) : base(null) { Token = token; } public override string FullText => Token.FullText; public override IEnumerable ChildTokens { get { yield return Token; } } } public class StatementNode : SyntaxNode { public TokenNode SemicolonOrComma { get; set; } public StatementNode(List children, TokenNode semicolonOrComma = null) : base(children) { SemicolonOrComma = semicolonOrComma; } } public class ExpressionStatementNode : StatementNode { public ExpressionNode Expression { get; } public ExpressionStatementNode(List children, ExpressionNode expression, TokenNode semicolonOrComma) : base(children, semicolonOrComma) { Expression = expression; } } public class CellArrayElementAccessExpressionNode : ExpressionNode { public ExpressionNode CellArray { get; } public TokenNode OpeningBrace { get; } public ArrayElementListNode Indices { get; } public TokenNode ClosingBrace { get; } public CellArrayElementAccessExpressionNode( List children, ExpressionNode cellArray, TokenNode openingBrace, ArrayElementListNode indices, TokenNode closingBrace) : base(children) { CellArray = cellArray; OpeningBrace = openingBrace; Indices = indices; ClosingBrace = closingBrace; } } public class FunctionCallExpressionNode : ExpressionNode { public ExpressionNode FunctionName { get; } public TokenNode OpeningBracket { get; } public FunctionCallParameterListNode Parameters { get; } public TokenNode ClosingBracket { get; } public FunctionCallExpressionNode( List children, ExpressionNode functionName, TokenNode openingBracket, FunctionCallParameterListNode parameters, TokenNode closingBracket) : base(children) { FunctionName = functionName; OpeningBracket = openingBracket; Parameters = parameters; ClosingBracket = closingBracket; } } public class FunctionCallParameterListNode : SyntaxNode { public List Parameters; public FunctionCallParameterListNode( List children, List parameters) : base(children) { Parameters = parameters; } } public class ArrayElementListNode : SyntaxNode { public List Elements; public ArrayElementListNode( List children, List elements) : base(children) { Elements = elements; } } public class ArrayLiteralExpressionNode : ExpressionNode { public TokenNode OpeningSquareBracket { get; } public ArrayElementListNode Elements { get; } public TokenNode ClosingSquareBracket { get; } public ArrayLiteralExpressionNode( List children, TokenNode openingSquareBracket, ArrayElementListNode elements, TokenNode closingSquareBracket) : base(children) { OpeningSquareBracket = openingSquareBracket; Elements = elements; ClosingSquareBracket = closingSquareBracket; } } public class CellArrayLiteralExpressionNode : ExpressionNode { public TokenNode OpeningBrace { get; } public ArrayElementListNode Elements { get; } public TokenNode ClosingBrace { get; } public CellArrayLiteralExpressionNode( List children, TokenNode openingBrace, ArrayElementListNode elements, TokenNode closingBrace) : base(children) { OpeningBrace = openingBrace; Elements = elements; ClosingBrace = closingBrace; } } public class EmptyExpressionNode : ExpressionNode { public EmptyExpressionNode() : base(null) { } public override IEnumerable ChildTokens { get { yield break; } } public override string FullText => ""; } public class CompoundNameNode : ExpressionNode { public List Names; public CompoundNameNode( List children, List names ) : base(children) { Names = names; } } public class MemberAccessNode : ExpressionNode { public SyntaxNode LeftOperand { get; } public TokenNode Dot { get; } public SyntaxNode RightOperand { get; } public MemberAccessNode( List children, SyntaxNode leftOperand, TokenNode dot, SyntaxNode rightOperand) : base(children) { LeftOperand = leftOperand; Dot = dot; RightOperand = rightOperand; } } public class WhileStatementNode : StatementNode { public TokenNode WhileKeyword { get; } public ExpressionNode Condition { get; } public List OptionalCommasAfterCondition { get; } public StatementListNode Body { get; } public TokenNode End { get; } public WhileStatementNode( List children, TokenNode whileKeyword, ExpressionNode condition, List optionalCommasAfterCondition, StatementListNode body, TokenNode end, TokenNode semicolonOrComma ) : base(children, semicolonOrComma) { WhileKeyword = whileKeyword; Condition = condition; OptionalCommasAfterCondition = optionalCommasAfterCondition; Body = body; End = end; } } public class IfStatementNode : StatementNode { public TokenNode IfKeyword { get; } public ExpressionNode Condition { get; } public List OptionalCommasAfterCondition { get; } public StatementListNode Body { get; } public TokenNode ElseKeyword { get; } public StatementListNode ElseBody { get; } public TokenNode EndKeyword { get; } public IfStatementNode( List children, TokenNode ifKeyword, ExpressionNode condition, List optionalCommasAfterCondition, StatementListNode body, TokenNode elseKeyword, StatementListNode elseBody, TokenNode endKeyword ) : base(children) { IfKeyword = ifKeyword; Condition = condition; OptionalCommasAfterCondition = optionalCommasAfterCondition; Body = body; ElseKeyword = elseKeyword; ElseBody = elseBody; EndKeyword = endKeyword; } } public class ParenthesizedExpressionNode : ExpressionNode { public TokenNode OpenParen { get; } public ExpressionNode Expression { get; } public TokenNode CloseParen { get; } public ParenthesizedExpressionNode( List children, TokenNode openParen, ExpressionNode expression, TokenNode closeParen) : base(children) { OpenParen = openParen; Expression = expression; CloseParen = closeParen; } } public class ForStatementNode : StatementNode { public TokenNode ForKeyword { get; } public AssignmentExpressionNode ForAssignment { get; } public List OptionalCommasAfterAssignment { get; } public StatementListNode Body { get; } public TokenNode EndKeyword { get; } public ForStatementNode( List children, TokenNode forKeyword, AssignmentExpressionNode forAssignment, StatementListNode body, TokenNode endKeyword, List optionalCommasAfterAssignment ) : base(children) { ForKeyword = forKeyword; ForAssignment = forAssignment; Body = body; EndKeyword = endKeyword; OptionalCommasAfterAssignment = optionalCommasAfterAssignment; } } public class IndirectMemberAccessNode : ExpressionNode { public TokenNode OpeningBracket { get; } public ExpressionNode IndirectMemberName { get; } public TokenNode ClosingBracket { get; } public IndirectMemberAccessNode( List children, TokenNode openingBracket, ExpressionNode indirectMemberName, TokenNode closingBracket) : base(children) { OpeningBracket = openingBracket; IndirectMemberName = indirectMemberName; ClosingBracket = closingBracket; } } public abstract class FunctionHandleNode : ExpressionNode { protected FunctionHandleNode( List children) : base(children) { } } public class NamedFunctionHandleNode : FunctionHandleNode { public TokenNode AtSign { get; } public CompoundNameNode FunctionName { get; } public NamedFunctionHandleNode( List children, TokenNode atSign, CompoundNameNode functionName) : base(children) { AtSign = atSign; FunctionName = functionName; } } public class LambdaNode : FunctionHandleNode { public TokenNode AtSign { get; } public FunctionInputDescriptionNode Input { get; } public ExpressionNode Body { get; } public LambdaNode( List children, TokenNode atSign, FunctionInputDescriptionNode input, ExpressionNode body) : base(children) { AtSign = atSign; Input = input; Body = body; } } public class TryCatchStatementNode : StatementNode { public TokenNode TryKeyword { get; } public StatementListNode TryBody { get; } public TokenNode CatchKeyword { get; } public StatementListNode CatchBody { get; } public TokenNode EndKeyword { get; } public TryCatchStatementNode( List children, TokenNode tryKeyword, StatementListNode tryBody, TokenNode catchKeyword, StatementListNode catchBody, TokenNode endKeyword ) : base(children) { TryKeyword = tryKeyword; TryBody = tryBody; CatchKeyword = catchKeyword; CatchBody = catchBody; EndKeyword = endKeyword; } } public class CommandExpressionNode : ExpressionNode { public IdentifierNameNode CommandName { get; } public List Arguments { get; } public CommandExpressionNode( List children, IdentifierNameNode commandName, List arguments ) : base(children) { CommandName = commandName; Arguments = arguments; } } }