592 lines
18 KiB
C#
592 lines
18 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Lexer;
|
|
|
|
namespace Parser
|
|
{
|
|
public class SyntaxFactory
|
|
{
|
|
private static List<SyntaxNode> RemoveNulls(List<SyntaxNode> children)
|
|
{
|
|
return children.Where(x => x != null).ToList();
|
|
}
|
|
|
|
public FunctionDeclarationNode FunctionDeclaration(
|
|
TokenNode functionKeyword,
|
|
FunctionOutputDescriptionNode outputDescription,
|
|
TokenNode name,
|
|
FunctionInputDescriptionNode inputDescription,
|
|
StatementListNode body,
|
|
TokenNode end,
|
|
TokenNode semicolonOrComma = null)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
functionKeyword,
|
|
outputDescription,
|
|
name,
|
|
inputDescription,
|
|
body,
|
|
end,
|
|
semicolonOrComma
|
|
};
|
|
return new FunctionDeclarationNode(
|
|
RemoveNulls(children),
|
|
functionKeyword,
|
|
outputDescription,
|
|
name,
|
|
inputDescription,
|
|
body,
|
|
end,
|
|
semicolonOrComma);
|
|
}
|
|
|
|
public FunctionOutputDescriptionNode FunctionOutputDescription(
|
|
List<SyntaxNode> nodes,
|
|
TokenNode equalitySign)
|
|
{
|
|
var children = new List<SyntaxNode>(nodes);
|
|
children.Add(equalitySign);
|
|
return new FunctionOutputDescriptionNode(
|
|
children,
|
|
children
|
|
.Where(node => node is TokenNode tokenNode && tokenNode.Token.Kind == TokenKind.Identifier)
|
|
.Select(node => (TokenNode)node)
|
|
.ToList(),
|
|
equalitySign
|
|
);
|
|
}
|
|
|
|
public ParameterListNode ParameterList(List<SyntaxNode> nodes)
|
|
{
|
|
return new ParameterListNode(
|
|
nodes,
|
|
nodes
|
|
.Where(
|
|
node => node is TokenNode tokenNode && tokenNode.Token.Kind != TokenKind.Comma
|
|
)
|
|
.ToList());
|
|
}
|
|
|
|
public StatementListNode StatementList(List<SyntaxNode> nodes)
|
|
{
|
|
return new StatementListNode(nodes);
|
|
}
|
|
|
|
public FunctionInputDescriptionNode FunctionInputDescription(
|
|
TokenNode openingBracket,
|
|
ParameterListNode parameterList,
|
|
TokenNode closingBracket)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
openingBracket,
|
|
parameterList,
|
|
closingBracket
|
|
};
|
|
return new FunctionInputDescriptionNode(children, openingBracket, parameterList, closingBracket);
|
|
}
|
|
|
|
public TokenNode Token(Token token)
|
|
{
|
|
return new TokenNode(token);
|
|
}
|
|
|
|
public SwitchStatementNode SwitchStatement(
|
|
TokenNode switchKeyword,
|
|
ExpressionNode switchExpression,
|
|
List<SwitchCaseNode> cases,
|
|
TokenNode endKeyword,
|
|
List<TokenNode> optionalCommasAfterExpression,
|
|
TokenNode semicolonOrComma = null)
|
|
{
|
|
var children = new List<SyntaxNode> { switchKeyword, switchExpression };
|
|
children.AddRange(optionalCommasAfterExpression);
|
|
children.AddRange(cases);
|
|
children.Add(endKeyword);
|
|
children.Add(semicolonOrComma);
|
|
|
|
return new SwitchStatementNode(
|
|
RemoveNulls(children),
|
|
switchKeyword,
|
|
switchExpression,
|
|
cases,
|
|
endKeyword,
|
|
semicolonOrComma,
|
|
optionalCommasAfterExpression);
|
|
}
|
|
|
|
public SwitchCaseNode SwitchCase(
|
|
TokenNode caseKeyword,
|
|
ExpressionNode caseIdentifier,
|
|
StatementListNode statementList,
|
|
List<TokenNode> optionalCommasAfterIdentifier)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
caseKeyword,
|
|
caseIdentifier
|
|
};
|
|
children.AddRange(optionalCommasAfterIdentifier);
|
|
children.Add(statementList);
|
|
return new SwitchCaseNode(
|
|
RemoveNulls(children),
|
|
caseKeyword,
|
|
caseIdentifier,
|
|
statementList,
|
|
optionalCommasAfterIdentifier);
|
|
}
|
|
|
|
public AssignmentExpressionNode AssignmentExpression(
|
|
ExpressionNode lhs,
|
|
TokenNode assignmentSign,
|
|
ExpressionNode rhs)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
lhs,
|
|
assignmentSign,
|
|
rhs
|
|
};
|
|
return new AssignmentExpressionNode(children, lhs, assignmentSign, rhs);
|
|
}
|
|
|
|
public UnaryPrefixOperationExpressionNode UnaryPrefixOperationExpression(
|
|
TokenNode operation,
|
|
ExpressionNode operand)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
operation,
|
|
operand
|
|
};
|
|
return new UnaryPrefixOperationExpressionNode(children, operation, operand);
|
|
}
|
|
|
|
public UnaryPostfixOperationExpressionNode UnaryPostfixOperationExpression(
|
|
ExpressionNode operand,
|
|
TokenNode operation)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
operand,
|
|
operation
|
|
};
|
|
return new UnaryPostfixOperationExpressionNode(children, operand, operation);
|
|
}
|
|
|
|
public BinaryOperationExpressionNode BinaryOperationExpression(
|
|
ExpressionNode lhs,
|
|
TokenNode operation,
|
|
ExpressionNode rhs)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
lhs,
|
|
operation,
|
|
rhs
|
|
};
|
|
return new BinaryOperationExpressionNode(children, lhs, operation, rhs);
|
|
}
|
|
|
|
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 DoubleQuotedStringLiteralNode DoubleQuotedStringLiteral(
|
|
Token stringLiteral)
|
|
{
|
|
return new DoubleQuotedStringLiteralNode(stringLiteral);
|
|
}
|
|
|
|
public UnquotedStringLiteralNode UnquotedStringLiteral(
|
|
Token stringLiteral)
|
|
{
|
|
return new UnquotedStringLiteralNode(stringLiteral);
|
|
}
|
|
|
|
public ExpressionStatementNode ExpressionStatement(ExpressionNode expression)
|
|
{
|
|
var children = new List<SyntaxNode> {expression};
|
|
return new ExpressionStatementNode(children, expression, null);
|
|
}
|
|
|
|
public ExpressionStatementNode ExpressionStatement(ExpressionNode expression, TokenNode semicolonOrComma)
|
|
{
|
|
var children = new List<SyntaxNode> {expression, semicolonOrComma};
|
|
return new ExpressionStatementNode(children, expression, semicolonOrComma);
|
|
}
|
|
|
|
public CellArrayElementAccessExpressionNode CellArrayElementAccessExpression(
|
|
ExpressionNode cellArray,
|
|
TokenNode openingBrace,
|
|
ArrayElementListNode indices,
|
|
TokenNode closingBrace)
|
|
{
|
|
var children = new List<SyntaxNode> {cellArray, openingBrace, indices, closingBrace};
|
|
return new CellArrayElementAccessExpressionNode(
|
|
children,
|
|
cellArray,
|
|
openingBrace,
|
|
indices,
|
|
closingBrace);
|
|
}
|
|
|
|
public FunctionCallExpressionNode FunctionCallExpression(
|
|
ExpressionNode functionName,
|
|
TokenNode openingBracket,
|
|
FunctionCallParameterListNode parameters,
|
|
TokenNode closingBracket)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
functionName,
|
|
openingBracket,
|
|
parameters,
|
|
closingBracket
|
|
};
|
|
return new FunctionCallExpressionNode(
|
|
children,
|
|
functionName,
|
|
openingBracket,
|
|
parameters,
|
|
closingBracket);
|
|
}
|
|
|
|
public FunctionCallParameterListNode FunctionCallParameterList(List<SyntaxNode> nodes)
|
|
{
|
|
return new FunctionCallParameterListNode(
|
|
nodes,
|
|
nodes
|
|
.OfType<ExpressionNode>()
|
|
.ToList());
|
|
}
|
|
|
|
public ArrayElementListNode ArrayElementList(List<SyntaxNode> nodes)
|
|
{
|
|
return new ArrayElementListNode(
|
|
nodes,
|
|
nodes
|
|
.OfType<ExpressionNode>()
|
|
.ToList());
|
|
}
|
|
|
|
public CompoundNameNode CompoundName(List<SyntaxNode> nodes)
|
|
{
|
|
return new CompoundNameNode(
|
|
nodes,
|
|
nodes
|
|
.OfType<IdentifierNameNode>()
|
|
.ToList());
|
|
}
|
|
|
|
public ArrayLiteralExpressionNode ArrayLiteralExpression(
|
|
TokenNode openingSquareBracket,
|
|
ArrayElementListNode elements,
|
|
TokenNode closingSquareBracket)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
openingSquareBracket,
|
|
elements,
|
|
closingSquareBracket
|
|
};
|
|
return new ArrayLiteralExpressionNode(
|
|
children,
|
|
openingSquareBracket,
|
|
elements,
|
|
closingSquareBracket);
|
|
}
|
|
|
|
public CellArrayLiteralExpressionNode CellArrayLiteralExpression(
|
|
TokenNode openingBrace,
|
|
ArrayElementListNode elements,
|
|
TokenNode closingBrace)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
openingBrace,
|
|
elements,
|
|
closingBrace
|
|
};
|
|
return new CellArrayLiteralExpressionNode(
|
|
children,
|
|
openingBrace,
|
|
elements,
|
|
closingBrace);
|
|
}
|
|
|
|
public EmptyExpressionNode EmptyExpression()
|
|
{
|
|
return new EmptyExpressionNode();
|
|
}
|
|
|
|
public MemberAccessNode MemberAccess(
|
|
SyntaxNode leftOperand,
|
|
TokenNode dot,
|
|
SyntaxNode rightOperand)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
leftOperand,
|
|
dot,
|
|
rightOperand
|
|
};
|
|
return new MemberAccessNode(
|
|
children,
|
|
leftOperand,
|
|
dot,
|
|
rightOperand);
|
|
}
|
|
|
|
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,
|
|
};
|
|
children.AddRange(optionalCommasAfterCondition);
|
|
children.Add(body);
|
|
children.Add(end);
|
|
children.Add(semicolonOrComma);
|
|
return new WhileStatementNode(
|
|
RemoveNulls(children),
|
|
whileKeyword,
|
|
condition,
|
|
optionalCommasAfterCondition,
|
|
body,
|
|
end,
|
|
semicolonOrComma);
|
|
}
|
|
|
|
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
|
|
};
|
|
children.AddRange(optionalCommasAfterCondition);
|
|
children.Add(body);
|
|
children.Add(elseKeyword);
|
|
children.Add(elseBody);
|
|
children.Add(endKeyword);
|
|
|
|
return new IfStatementNode(
|
|
RemoveNulls(children),
|
|
ifKeyword,
|
|
condition,
|
|
optionalCommasAfterCondition,
|
|
body,
|
|
elseKeyword,
|
|
elseBody,
|
|
endKeyword);
|
|
}
|
|
|
|
public ParenthesizedExpressionNode ParenthesizedExpression(
|
|
TokenNode openParen,
|
|
ExpressionNode expression,
|
|
TokenNode closeParen)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
openParen,
|
|
expression,
|
|
closeParen
|
|
};
|
|
return new ParenthesizedExpressionNode(
|
|
children,
|
|
openParen,
|
|
expression,
|
|
closeParen);
|
|
}
|
|
|
|
public ForStatementNode ForStatement(
|
|
TokenNode forKeyword,
|
|
AssignmentExpressionNode forAssignment,
|
|
StatementListNode body,
|
|
TokenNode endKeyword,
|
|
List<TokenNode> optionalCommasAfterAssignment)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
forKeyword,
|
|
forAssignment,
|
|
};
|
|
children.AddRange(optionalCommasAfterAssignment);
|
|
children.Add(body);
|
|
children.Add(endKeyword);
|
|
return new ForStatementNode(
|
|
RemoveNulls(children),
|
|
forKeyword,
|
|
forAssignment,
|
|
body,
|
|
endKeyword,
|
|
optionalCommasAfterAssignment);
|
|
}
|
|
|
|
public IndirectMemberAccessNode IndirectMemberAccess(
|
|
TokenNode openingBracket,
|
|
ExpressionNode indirectMemberName,
|
|
TokenNode closingBracket)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
openingBracket,
|
|
indirectMemberName,
|
|
closingBracket
|
|
};
|
|
return new IndirectMemberAccessNode(
|
|
children,
|
|
openingBracket,
|
|
indirectMemberName,
|
|
closingBracket);
|
|
}
|
|
|
|
public NamedFunctionHandleNode NamedFunctionHandle(
|
|
TokenNode atSign,
|
|
CompoundNameNode functionName)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
atSign,
|
|
functionName
|
|
};
|
|
return new NamedFunctionHandleNode(
|
|
children,
|
|
atSign,
|
|
functionName);
|
|
}
|
|
|
|
public LambdaNode Lambda(
|
|
TokenNode atSign,
|
|
FunctionInputDescriptionNode input,
|
|
ExpressionNode body)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
atSign,
|
|
input,
|
|
body
|
|
};
|
|
return new LambdaNode(
|
|
children,
|
|
atSign,
|
|
input,
|
|
body);
|
|
}
|
|
|
|
public TryCatchStatementNode TryCatchStatement(
|
|
TokenNode tryKeyword,
|
|
StatementListNode tryBody,
|
|
TokenNode catchKeyword,
|
|
StatementListNode catchBody,
|
|
TokenNode endKeyword)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
tryKeyword,
|
|
tryBody,
|
|
catchKeyword,
|
|
catchBody,
|
|
endKeyword
|
|
};
|
|
return new TryCatchStatementNode(
|
|
children,
|
|
tryKeyword,
|
|
tryBody,
|
|
catchKeyword,
|
|
catchBody,
|
|
endKeyword);
|
|
}
|
|
|
|
public TryCatchStatementNode TryCatchStatement(
|
|
TokenNode tryKeyword,
|
|
StatementListNode tryBody,
|
|
TokenNode endKeyword)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
tryKeyword,
|
|
tryBody,
|
|
endKeyword
|
|
};
|
|
return new TryCatchStatementNode(
|
|
children,
|
|
tryKeyword,
|
|
tryBody,
|
|
null,
|
|
null,
|
|
endKeyword);
|
|
}
|
|
|
|
public CommandExpressionNode CommandExpression(
|
|
IdentifierNameNode identifierName,
|
|
List<UnquotedStringLiteralNode> arguments)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
identifierName
|
|
};
|
|
children.AddRange(arguments);
|
|
return new CommandExpressionNode(
|
|
children,
|
|
identifierName,
|
|
arguments);
|
|
}
|
|
|
|
public BaseClassInvokationNode BaseClassInvokation(
|
|
IdentifierNameNode methodName,
|
|
TokenNode atToken,
|
|
ExpressionNode baseClassNameAndArguments)
|
|
{
|
|
var children = new List<SyntaxNode>
|
|
{
|
|
methodName,
|
|
atToken,
|
|
baseClassNameAndArguments
|
|
};
|
|
return new BaseClassInvokationNode(
|
|
children,
|
|
methodName,
|
|
atToken,
|
|
baseClassNameAndArguments);
|
|
}
|
|
}
|
|
} |