2481 lines
88 KiB
C++
2481 lines
88 KiB
C++
#include <mutex>
|
|
#include "../../utils/string.hpp"
|
|
#include "./tree_sitter_utils.hpp"
|
|
#include "./detail.hpp"
|
|
|
|
namespace lsp::language::ast::detail
|
|
{
|
|
void RegisterStatementParsers()
|
|
{
|
|
static std::once_flag once;
|
|
std::call_once(once, [] {
|
|
auto& registry = StatementParserRegistry::Instance();
|
|
|
|
// 直接注册,不需要适配器
|
|
registry.Register("unit", ParseUnitDefinition);
|
|
registry.Register("var_statement", ParseVarStatement);
|
|
registry.Register("static_statement", ParseStaticStatement);
|
|
registry.Register("global_statement", ParseGlobalStatement);
|
|
registry.Register("const_statement", ParseConstStatement);
|
|
registry.Register("assignment_statement", ParseAssignmentStatement);
|
|
registry.Register("expression_statement", ParseExpressionStatement);
|
|
registry.Register("break_statement", ParseBreakStatement);
|
|
registry.Register("continue_statement", ParseContinueStatement);
|
|
registry.Register("return_statement", ParseReturnStatement);
|
|
registry.Register("uses_statement", ParseUsesStatement);
|
|
registry.Register("inherited_statement", ParseInheritedStatement);
|
|
registry.Register("single_suite", ParseSingleSuite);
|
|
registry.Register("block_suite", ParseBlockSuite);
|
|
registry.Register("if_statement", ParseIfStatement);
|
|
registry.Register("for_in_statement", ParseForInStatement);
|
|
registry.Register("for_to_statement", ParseForToStatement);
|
|
registry.Register("while_statement", ParseWhileStatement);
|
|
registry.Register("repeat_statement", ParseRepeatStatement);
|
|
registry.Register("case_statement", ParseCaseStatement);
|
|
registry.Register("try_statement", ParseTryStatement);
|
|
registry.Register("function_declaration_statement", ParseFunctionDeclaration);
|
|
registry.Register("function_definition_statement", ParseFunctionDefinition);
|
|
registry.Register("function_definition_with_overload_statement", ParseFunctionDefinition);
|
|
registry.Register("class_definition_statement", ParseClassDefinition);
|
|
registry.Register("external_method_statement", ParseExternalMethodStatement);
|
|
registry.Register("matrix_iteration_statement", ParseMatrixIterationStatement);
|
|
|
|
registry.Register("anonymous_function_statement",
|
|
[](TSNode n, ParseContext& ctx) -> StatementPtr {
|
|
auto expr = ParseAnonymousFunctionExpression(n, ctx);
|
|
if (!expr)
|
|
return nullptr;
|
|
Location loc = ts::NodeLocation(n);
|
|
auto stmt = MakeNode<ExpressionStatement>();
|
|
stmt->kind = NodeKind::kExpressionStatement;
|
|
stmt->span = loc;
|
|
stmt->expression = std::move(expr);
|
|
return stmt;
|
|
});
|
|
|
|
registry.Register("tslx_open_tag", ParseTSLXOpenTag);
|
|
registry.Register("tslx_close_tag", ParseTSLXCloseTag);
|
|
registry.Register("tslx_output_tag", ParseTSLXOutputTag);
|
|
registry.Register("tslx_expression_tag", ParseTSLXExpressionTag);
|
|
registry.Register("html_self_closing_tag", ParseHTMLSelfClosingTag);
|
|
registry.Register("html_paired_tag", ParseHTMLPairedTag);
|
|
registry.Register("html_comment", ParseHTMLComment);
|
|
});
|
|
}
|
|
|
|
BinaryOperator ParseBinaryOperator(const std::string& op_text)
|
|
{
|
|
static const std::unordered_map<std::string, BinaryOperator, utils::IHasher, utils::IEqualTo> op_map = {
|
|
// Arithmetic
|
|
{ "+", BinaryOperator::kAdd },
|
|
{ "-", BinaryOperator::kSubtract },
|
|
{ "*", BinaryOperator::kMultiply },
|
|
{ "/", BinaryOperator::kDivide },
|
|
{ "\\", BinaryOperator::kIntDivide },
|
|
{ "%", BinaryOperator::kModulo },
|
|
{ "mod", BinaryOperator::kModulo },
|
|
{ "div", BinaryOperator::kIntDivide },
|
|
{ "^", BinaryOperator::kPower },
|
|
{ "~", BinaryOperator::kLogarithm },
|
|
|
|
// Comparison
|
|
{ "=", BinaryOperator::kEqual },
|
|
{ "<>", BinaryOperator::kNotEqual },
|
|
{ ">", BinaryOperator::kGreater },
|
|
{ ">=", BinaryOperator::kGreaterEqual },
|
|
{ "<", BinaryOperator::kLess },
|
|
{ "<=", BinaryOperator::kLessEqual },
|
|
{ ".=", BinaryOperator::kDotEqual },
|
|
{ ".<>", BinaryOperator::kDotNotEqual },
|
|
{ ".>", BinaryOperator::kDotGreater },
|
|
{ ".>=", BinaryOperator::kDotGreaterEqual },
|
|
{ ".<", BinaryOperator::kDotLess },
|
|
{ ".<=", BinaryOperator::kDotLessEqual },
|
|
{ "like", BinaryOperator::kLike },
|
|
{ "is", BinaryOperator::kIs },
|
|
{ "in", BinaryOperator::kIn },
|
|
|
|
// Logical
|
|
{ "or", BinaryOperator::kLogicalOr },
|
|
{ "and", BinaryOperator::kLogicalAnd },
|
|
{ ".||", BinaryOperator::kDotLogicalOr },
|
|
{ "||", BinaryOperator::kDotLogicalOr },
|
|
{ ".&&", BinaryOperator::kDotLogicalAnd },
|
|
{ "&&", BinaryOperator::kDotLogicalAnd },
|
|
|
|
// Bitwise
|
|
{ ".|", BinaryOperator::kBitwiseOr },
|
|
{ ".&", BinaryOperator::kBitwiseAnd },
|
|
{ ".^", BinaryOperator::kBitwiseXor },
|
|
{ "shl", BinaryOperator::kShl },
|
|
{ "shr", BinaryOperator::kShr },
|
|
{ "rol", BinaryOperator::kRol },
|
|
{ "ror", BinaryOperator::kRor },
|
|
|
|
// Matrix
|
|
{ ":*", BinaryOperator::kMatrixMultiply },
|
|
{ ":/", BinaryOperator::kMatrixDivide },
|
|
{ ":\\", BinaryOperator::kMatrixIntDivide },
|
|
{ ":^", BinaryOperator::kMatrixPower },
|
|
{ ":|", BinaryOperator::kMatrixConcat },
|
|
{ "|", BinaryOperator::kMatrixConcatVertical },
|
|
|
|
// Set
|
|
{ "union", BinaryOperator::kUnion },
|
|
{ "union2", BinaryOperator::kUnion2 },
|
|
{ "intersect", BinaryOperator::kIntersect },
|
|
{ "outersect", BinaryOperator::kOutersect },
|
|
{ "minus", BinaryOperator::kMinus },
|
|
|
|
// Other
|
|
{ "$", BinaryOperator::kConcatenation },
|
|
{ "->", BinaryOperator::kRange },
|
|
};
|
|
|
|
auto it = op_map.find(op_text);
|
|
if (it != op_map.end())
|
|
return it->second;
|
|
|
|
return BinaryOperator::kAdd; // 默认值
|
|
}
|
|
|
|
UnaryOperator ParseUnaryOperator(const std::string& op_text)
|
|
{
|
|
static const std::unordered_map<std::string, UnaryOperator, utils::IHasher, utils::IEqualTo> op_map = {
|
|
{ "+", UnaryOperator::kPlus },
|
|
{ "-", UnaryOperator::kMinus },
|
|
{ "not", UnaryOperator::kNot },
|
|
{ ".!", UnaryOperator::kBitwiseNot },
|
|
{ ".!!", UnaryOperator::kDotNot },
|
|
{ "`", UnaryOperator::kMatrixTranspose },
|
|
{ "!", UnaryOperator::kDerivative },
|
|
{ "@", UnaryOperator::kExprAt },
|
|
{ "&", UnaryOperator::kExprRef },
|
|
};
|
|
|
|
auto it = op_map.find(op_text);
|
|
return it != op_map.end() ? it->second : UnaryOperator::kPlus;
|
|
}
|
|
|
|
AssignmentOperator ParseAssignmentOperator(const std::string& op_text)
|
|
{
|
|
static const std::unordered_map<std::string, AssignmentOperator, utils::IHasher, utils::IEqualTo> op_map = {
|
|
{ ":=", AssignmentOperator::kAssign },
|
|
{ "+=", AssignmentOperator::kAddAssign },
|
|
{ "-=", AssignmentOperator::kSubtractAssign },
|
|
{ "*=", AssignmentOperator::kMultiplyAssign },
|
|
{ "/=", AssignmentOperator::kDivideAssign },
|
|
{ "\\=", AssignmentOperator::kIntDivideAssign },
|
|
{ "^=", AssignmentOperator::kPowerAssign },
|
|
{ "~=", AssignmentOperator::kLogarithmAssign },
|
|
{ "%=", AssignmentOperator::kModuloAssign },
|
|
{ "div=", AssignmentOperator::kDivAssign },
|
|
{ "|=", AssignmentOperator::kBitwiseOrAssign },
|
|
{ "&=", AssignmentOperator::kBitwiseAndAssign },
|
|
{ ":*=", AssignmentOperator::kMatrixMultiplyAssign },
|
|
{ ":/=", AssignmentOperator::kMatrixDivideAssign },
|
|
{ ":\\=", AssignmentOperator::kMatrixIntDivideAssign },
|
|
{ ":^=", AssignmentOperator::kMatrixPowerAssign },
|
|
{ ":|=", AssignmentOperator::kMatrixConcatAssign },
|
|
{ "::=", AssignmentOperator::kConcatAssign },
|
|
{ ".|=", AssignmentOperator::kDotBitwiseOrAssign },
|
|
{ ".&=", AssignmentOperator::kDotBitwiseAndAssign },
|
|
{ ".||=", AssignmentOperator::kDotLogicalOrAssign },
|
|
{ ".&&=", AssignmentOperator::kDotLogicalAndAssign },
|
|
{ ".^=", AssignmentOperator::kDotBitwiseXorAssign },
|
|
{ "union=", AssignmentOperator::kUnionAssign },
|
|
{ "union2=", AssignmentOperator::kUnion2Assign },
|
|
{ "intersect=", AssignmentOperator::kIntersectAssign },
|
|
{ "outersect=", AssignmentOperator::kOutersectAssign },
|
|
{ "minus=", AssignmentOperator::kMinusAssign },
|
|
};
|
|
|
|
auto it = op_map.find(op_text);
|
|
return it != op_map.end() ? it->second : AssignmentOperator::kAssign;
|
|
}
|
|
|
|
// ===== 基础辅助函数 =====
|
|
|
|
bool IsSyntaxErrorNode(TSNode node)
|
|
{
|
|
if (ts_node_is_error(node))
|
|
return true;
|
|
|
|
std::string_view type = ts_node_type(node);
|
|
return type == "ERROR" || type == "MISSING";
|
|
}
|
|
|
|
std::vector<ParseError> CollectSyntaxErrors(TSNode node, std::string_view source)
|
|
{
|
|
std::vector<ParseError> errors;
|
|
|
|
if (IsSyntaxErrorNode(node))
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
std::string type = ts_node_type(node);
|
|
|
|
if (ts_node_is_missing(node))
|
|
{
|
|
errors.push_back(ParseError::Missing(loc, type));
|
|
}
|
|
else
|
|
{
|
|
std::string context;
|
|
TSNode parent = ts_node_parent(node);
|
|
if (!ts_node_is_null(parent))
|
|
context = ts_node_type(parent);
|
|
errors.push_back(ParseError::Unexpected(loc, type, context));
|
|
}
|
|
}
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
auto child_errors = CollectSyntaxErrors(child, source);
|
|
errors.insert(errors.end(),
|
|
std::make_move_iterator(child_errors.begin()),
|
|
std::make_move_iterator(child_errors.end()));
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
// ===== 通用解析函数 =====
|
|
|
|
Signature ParseSignature(TSNode node, ParseContext& ctx)
|
|
{
|
|
Signature sig;
|
|
|
|
TSNode params_node = ts_node_child_by_field_name(node, "parameters", 10);
|
|
if (!ts_node_is_null(params_node))
|
|
sig.parameters = ParseParameters(params_node, ctx);
|
|
TSNode return_node = ts_node_child_by_field_name(node, "return_type", 11);
|
|
if (!ts_node_is_null(return_node))
|
|
{
|
|
TSNode type_name_node = ts_node_child_by_field_name(return_node, "type_name", 9);
|
|
if (!ts_node_is_null(type_name_node))
|
|
sig.return_type = TypeAnnotation{ .name = ts::Text(type_name_node, ctx.Source()), .location = ts::NodeLocation(type_name_node) };
|
|
}
|
|
|
|
return sig;
|
|
}
|
|
|
|
std::vector<Parameter> ParseParameters(TSNode params_node, ParseContext& ctx)
|
|
{
|
|
std::vector<Parameter> all_params;
|
|
|
|
uint32_t count = ts_node_child_count(params_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field_name = ts_node_field_name_for_child(params_node, i);
|
|
if (!field_name || std::string_view(field_name) != "parameter")
|
|
continue;
|
|
|
|
TSNode param_node = ts_node_child(params_node, i);
|
|
bool is_var = false;
|
|
bool is_out = false;
|
|
|
|
uint32_t param_count = ts_node_child_count(param_node);
|
|
for (uint32_t j = 0; j < param_count; j++)
|
|
{
|
|
TSNode child = ts_node_child(param_node, j);
|
|
std::string text = ts::Text(child, ctx.Source());
|
|
if (text == "var")
|
|
is_var = true;
|
|
if (text == "out")
|
|
is_out = true;
|
|
}
|
|
|
|
for (uint32_t j = 0; j < param_count; j++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(param_node, j);
|
|
|
|
if (!field || std::string_view(field) != "name")
|
|
continue;
|
|
|
|
TSNode child = ts_node_child(param_node, j);
|
|
|
|
Parameter param;
|
|
param.name = ts::Text(child, ctx.Source());
|
|
param.type = std::nullopt;
|
|
param.is_var = is_var;
|
|
param.is_out = is_out;
|
|
param.location = ts::NodeLocation(child);
|
|
|
|
all_params.push_back(std::move(param));
|
|
}
|
|
|
|
if (!all_params.empty())
|
|
{
|
|
TSNode type_node = ts_node_child_by_field_name(param_node, "type_name", 9);
|
|
if (!ts_node_is_null(type_node))
|
|
all_params.back().type = TypeAnnotation{ .name = ts::Text(type_node, ctx.Source()), .location = ts::NodeLocation(type_node) };
|
|
TSNode default_node = ts_node_child_by_field_name(param_node, "default", 7);
|
|
if (!ts_node_is_null(default_node))
|
|
all_params.back().default_value = ParseExpression(default_node, ctx);
|
|
}
|
|
}
|
|
|
|
return all_params;
|
|
}
|
|
|
|
// ===== 表达式解析 =====
|
|
|
|
ExpressionPtr ParseExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
std::string_view node_type = ts_node_type(node);
|
|
|
|
if (node_type == "expression")
|
|
{
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
if (ts_node_is_named(child))
|
|
return ParseExpression(child, ctx);
|
|
}
|
|
return ctx.ReportNullNode<Expression>(ts::NodeLocation(node), "sub expression");
|
|
}
|
|
|
|
// 二元表达式
|
|
if (node_type == "binary_expression")
|
|
return ParseBinaryExpression(node, ctx);
|
|
|
|
// 一元表达式
|
|
if (node_type == "unary_expression" ||
|
|
node_type == "prefix_increment_expression" ||
|
|
node_type == "prefix_decrement_expression" ||
|
|
node_type == "postfix_increment_expression" ||
|
|
node_type == "postfix_decrement_expression" ||
|
|
node_type == "function_pointer_expression" ||
|
|
node_type == "expr_expression")
|
|
{
|
|
return ParseUnaryExpression(node, ctx);
|
|
}
|
|
|
|
// 三元表达式
|
|
if (node_type == "ternary_expression")
|
|
return ParseTernaryExpression(node, ctx);
|
|
|
|
// 函数调用
|
|
if (node_type == "call")
|
|
return ParseCallExpression(node, ctx);
|
|
|
|
// 属性访问
|
|
if (node_type == "attribute")
|
|
return ParseAttributeExpression(node, ctx);
|
|
|
|
// 下标访问
|
|
if (node_type == "subscript")
|
|
return ParseSubscriptExpression(node, ctx);
|
|
|
|
// 数组
|
|
if (node_type == "array")
|
|
return ParseArrayExpression(node, ctx);
|
|
|
|
// 匿名函数
|
|
if (node_type == "anonymous_function_expression")
|
|
return ParseAnonymousFunctionExpression(node, ctx);
|
|
|
|
// 赋值表达式
|
|
if (node_type == "assignment_expression" || node_type == "augmented_assignment_expression")
|
|
return ParseAssignmentExpression(node, ctx);
|
|
|
|
// 内置表达式
|
|
if (node_type == "echo_expression")
|
|
return ParseEchoExpression(node, ctx);
|
|
if (node_type == "raise_expression")
|
|
return ParseRaiseExpression(node, ctx);
|
|
if (node_type == "new_expression")
|
|
return ParseNewExpression(node, ctx);
|
|
if (node_type == "inherited_expression")
|
|
return ParseInheritedExpression(node, ctx);
|
|
|
|
// TSSQL 选择表达式
|
|
if (node_type == "select_expression" ||
|
|
node_type == "sselect_expression" ||
|
|
node_type == "vselect_expression" ||
|
|
node_type == "mselect_expression" ||
|
|
node_type == "update_expression" ||
|
|
node_type == "delete_expression" ||
|
|
node_type == "insert_expression")
|
|
{
|
|
return ParseTSSQLExpression(node, ctx);
|
|
}
|
|
|
|
// 主表达式(标识符、字面量等)
|
|
return ParsePrimaryExpression(node, ctx);
|
|
}
|
|
|
|
ExpressionPtr ParseTSSQLExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
std::string_view node_type = ts_node_type(node);
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
auto expr = MakeNode<TSSQLExpression>();
|
|
expr->span = loc;
|
|
expr->raw_sql = ts::Text(node, ctx.Source());
|
|
|
|
// 根据节点类型设置SQL类型
|
|
if (node_type == "select_expression")
|
|
expr->sql_type = TSSQLExpressionType::kSelect;
|
|
else if (node_type == "sselect_expression")
|
|
expr->sql_type = TSSQLExpressionType::kSSelect;
|
|
else if (node_type == "vselect_expression")
|
|
expr->sql_type = TSSQLExpressionType::kVSelect;
|
|
else if (node_type == "mselect_expression")
|
|
expr->sql_type = TSSQLExpressionType::kMSelect;
|
|
else if (node_type == "update_expression")
|
|
expr->sql_type = TSSQLExpressionType::kUpdate;
|
|
else if (node_type == "delete_expression")
|
|
expr->sql_type = TSSQLExpressionType::kDelete;
|
|
else if (node_type == "insert_expression")
|
|
expr->sql_type = TSSQLExpressionType::kInsert;
|
|
else
|
|
expr->sql_type = TSSQLExpressionType::kSelect;
|
|
|
|
return expr;
|
|
}
|
|
|
|
ExpressionPtr ParseEchoExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto call = MakeNode<CallExpression>();
|
|
call->kind = NodeKind::kCallExpression;
|
|
call->span = ts::NodeLocation(node);
|
|
|
|
TSNode echo_node = ts_node_child(node, 0);
|
|
auto echo_id = MakeNode<Identifier>();
|
|
echo_id->kind = NodeKind::kIdentifier;
|
|
echo_id->span = ts::NodeLocation(echo_node);
|
|
echo_id->name = "echo";
|
|
echo_id->location = ts::NodeLocation(echo_node);
|
|
|
|
call->callee = std::move(echo_id);
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(node, i);
|
|
if (!field || std::string_view(field) != "argument")
|
|
continue;
|
|
|
|
auto expr = ParseExpression(ts_node_child(node, i), ctx);
|
|
if (expr)
|
|
{
|
|
CallExpression::Argument arg;
|
|
arg.value = std::move(expr);
|
|
call->arguments.push_back(std::move(arg));
|
|
}
|
|
}
|
|
|
|
return call;
|
|
}
|
|
|
|
ExpressionPtr ParseRaiseExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto call = MakeNode<CallExpression>();
|
|
call->kind = NodeKind::kCallExpression;
|
|
call->span = ts::NodeLocation(node);
|
|
|
|
TSNode raise_node = ts_node_child(node, 0);
|
|
auto raise_id = MakeNode<Identifier>();
|
|
raise_id->kind = NodeKind::kIdentifier;
|
|
raise_id->span = ts::NodeLocation(raise_node);
|
|
raise_id->name = "raise";
|
|
raise_id->location = ts::NodeLocation(raise_node);
|
|
|
|
call->callee = std::move(raise_id);
|
|
|
|
TSNode exception_node = ts_node_child_by_field_name(node, "exception", 9);
|
|
if (!ts_node_is_null(exception_node))
|
|
{
|
|
auto expr = ParseExpression(exception_node, ctx);
|
|
if (expr)
|
|
{
|
|
CallExpression::Argument arg;
|
|
arg.value = std::move(expr);
|
|
call->arguments.push_back(std::move(arg));
|
|
}
|
|
}
|
|
return call;
|
|
}
|
|
|
|
ExpressionPtr ParseNewExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto call = MakeNode<CallExpression>();
|
|
call->kind = NodeKind::kCallExpression;
|
|
call->span = ts::NodeLocation(node);
|
|
|
|
TSNode new_node = ts_node_child(node, 0);
|
|
auto new_id = MakeNode<Identifier>();
|
|
new_id->kind = NodeKind::kIdentifier;
|
|
new_id->span = ts::NodeLocation(new_node);
|
|
new_id->name = "new";
|
|
new_id->location = ts::NodeLocation(new_node);
|
|
|
|
call->callee = std::move(new_id);
|
|
|
|
TSNode exception_node = ts_node_child_by_field_name(node, "class", 5);
|
|
if (!ts_node_is_null(exception_node))
|
|
{
|
|
auto expr = ParseExpression(exception_node, ctx);
|
|
if (expr)
|
|
{
|
|
CallExpression::Argument arg;
|
|
arg.value = std::move(expr);
|
|
call->arguments.push_back(std::move(arg));
|
|
}
|
|
}
|
|
|
|
return call;
|
|
}
|
|
|
|
ExpressionPtr ParseInheritedExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto call = MakeNode<CallExpression>();
|
|
call->kind = NodeKind::kCallExpression;
|
|
call->span = ts::NodeLocation(node);
|
|
|
|
TSNode inherited_node = ts_node_child(node, 0);
|
|
auto inherited_id = MakeNode<Identifier>();
|
|
inherited_id->kind = NodeKind::kIdentifier;
|
|
inherited_id->span = ts::NodeLocation(inherited_node);
|
|
inherited_id->name = "inherited";
|
|
inherited_id->location = ts::NodeLocation(inherited_node);
|
|
|
|
call->callee = std::move(inherited_id);
|
|
|
|
TSNode exception_node = ts_node_child_by_field_name(node, "class", 5);
|
|
if (!ts_node_is_null(exception_node))
|
|
{
|
|
auto expr = ParseExpression(exception_node, ctx);
|
|
if (expr)
|
|
{
|
|
CallExpression::Argument arg;
|
|
arg.value = std::move(expr);
|
|
call->arguments.push_back(std::move(arg));
|
|
}
|
|
}
|
|
|
|
return call;
|
|
}
|
|
|
|
ExpressionPtr ParsePrimaryExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
std::string_view node_type = ts_node_type(node);
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
if (node_type == "literal" || node_type == "reserved_keyword")
|
|
{
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
if (ts_node_is_named(child))
|
|
return ParsePrimaryExpression(child, ctx);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// 标识符
|
|
if (node_type == "identifier" || node_type == "type" ||
|
|
node_type == "class" || node_type == "do")
|
|
{
|
|
std::string name = ts::Text(node, ctx.Source());
|
|
auto id = MakeNode<Identifier>();
|
|
id->kind = NodeKind::kIdentifier;
|
|
id->span = loc;
|
|
|
|
id->name = std::move(name);
|
|
return id;
|
|
}
|
|
|
|
// 字面量
|
|
if (node_type == "number")
|
|
{
|
|
auto lit = MakeNode<Literal>();
|
|
lit->kind = NodeKind::kLiteral;
|
|
lit->span = loc;
|
|
lit->literal_kind = LiteralKind::kNumber;
|
|
lit->name = ts::Text(node, ctx.Source());
|
|
lit->location = loc;
|
|
return lit;
|
|
}
|
|
|
|
if (node_type == "string")
|
|
{
|
|
auto lit = MakeNode<Literal>();
|
|
lit->kind = NodeKind::kLiteral;
|
|
lit->span = loc;
|
|
lit->literal_kind = LiteralKind::kString;
|
|
lit->name = ts::Text(node, ctx.Source());
|
|
lit->location = loc;
|
|
return lit;
|
|
}
|
|
|
|
if (node_type == "boolean")
|
|
{
|
|
auto lit = MakeNode<Literal>();
|
|
lit->kind = NodeKind::kLiteral;
|
|
lit->span = loc;
|
|
lit->literal_kind = LiteralKind::kBoolean;
|
|
lit->name = ts::Text(node, ctx.Source());
|
|
lit->location = loc;
|
|
return lit;
|
|
}
|
|
|
|
if (node_type == "nil")
|
|
{
|
|
auto lit = MakeNode<Literal>();
|
|
lit->kind = NodeKind::kLiteral;
|
|
lit->span = loc;
|
|
lit->literal_kind = LiteralKind::kNil;
|
|
lit->name = "nil";
|
|
lit->location = loc;
|
|
return lit;
|
|
}
|
|
|
|
if (node_type == "infinity")
|
|
{
|
|
auto lit = MakeNode<Literal>();
|
|
lit->kind = NodeKind::kLiteral;
|
|
lit->span = loc;
|
|
lit->literal_kind = LiteralKind::kInfinity;
|
|
lit->name = ts::Text(node, ctx.Source());
|
|
lit->location = loc;
|
|
return lit;
|
|
}
|
|
|
|
if (node_type == "ellipsis")
|
|
{
|
|
auto lit = MakeNode<Literal>();
|
|
lit->kind = NodeKind::kLiteral;
|
|
lit->span = loc;
|
|
lit->literal_kind = LiteralKind::kEllipsis;
|
|
lit->name = "...";
|
|
lit->location = loc;
|
|
return lit;
|
|
}
|
|
|
|
// 默认:创建一个标识符表达式
|
|
std::string text = ts::Text(node, ctx.Source());
|
|
if (!text.empty())
|
|
{
|
|
auto id = MakeNode<Identifier>();
|
|
id->kind = NodeKind::kIdentifier;
|
|
id->span = loc;
|
|
|
|
id->name = std::move(text);
|
|
return id;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
ExpressionPtr ParseBinaryExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode left_node = ts_node_child_by_field_name(node, "left", 4);
|
|
TSNode right_node = ts_node_child_by_field_name(node, "right", 5);
|
|
TSNode op_node = ts_node_child_by_field_name(node, "operator", 8);
|
|
|
|
if (ts_node_is_null(left_node))
|
|
return ctx.ReportNullNode<Expression>(loc, "left operand");
|
|
|
|
if (ts_node_is_null(right_node))
|
|
return ctx.ReportNullNode<Expression>(loc, "right operand");
|
|
|
|
auto left = ParseExpression(left_node, ctx);
|
|
auto right = ParseExpression(right_node, ctx);
|
|
|
|
if (!left)
|
|
return ctx.ReportParseFailed<Expression>(loc, "binary_expression", "failed to parse left operand");
|
|
|
|
if (!right)
|
|
return ctx.ReportParseFailed<Expression>(loc, "binary_expression", "failed to parse right operand");
|
|
|
|
std::string op_text;
|
|
if (!ts_node_is_null(op_node))
|
|
op_text = ts::Text(op_node, ctx.Source());
|
|
else
|
|
ctx.RecordMissing(loc, "operator");
|
|
|
|
BinaryOperator op = ParseBinaryOperator(op_text);
|
|
|
|
auto expr = MakeNode<BinaryExpression>();
|
|
expr->kind = NodeKind::kBinaryExpression;
|
|
expr->span = loc;
|
|
|
|
expr->op = op;
|
|
expr->left = std::move(left);
|
|
expr->right = std::move(right);
|
|
return expr;
|
|
}
|
|
|
|
ExpressionPtr ParseUnaryExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
std::string_view node_type = ts_node_type(node);
|
|
|
|
// 前缀自增/自减
|
|
if (node_type == "prefix_increment_expression")
|
|
{
|
|
TSNode arg_node = ts_node_child_by_field_name(node, "argument", 8);
|
|
auto arg = ParseExpression(arg_node, ctx);
|
|
auto expr = MakeNode<PrefixIncrementExpression>();
|
|
expr->kind = NodeKind::kPrefixIncrementExpression;
|
|
expr->span = loc;
|
|
|
|
expr->argument = std::move(arg);
|
|
return expr;
|
|
}
|
|
|
|
if (node_type == "prefix_decrement_expression")
|
|
{
|
|
TSNode arg_node = ts_node_child_by_field_name(node, "argument", 8);
|
|
auto arg = ParseExpression(arg_node, ctx);
|
|
auto expr = MakeNode<PrefixDecrementExpression>();
|
|
expr->kind = NodeKind::kPrefixDecrementExpression;
|
|
expr->span = loc;
|
|
|
|
expr->argument = std::move(arg);
|
|
return expr;
|
|
}
|
|
|
|
// 后缀自增/自减
|
|
if (node_type == "postfix_increment_expression")
|
|
{
|
|
TSNode arg_node = ts_node_child_by_field_name(node, "argument", 8);
|
|
auto arg = ParseExpression(arg_node, ctx);
|
|
auto expr = MakeNode<PostfixIncrementExpression>();
|
|
expr->kind = NodeKind::kPostfixIncrementExpression;
|
|
expr->span = loc;
|
|
|
|
expr->argument = std::move(arg);
|
|
return expr;
|
|
}
|
|
|
|
if (node_type == "postfix_decrement_expression")
|
|
{
|
|
TSNode arg_node = ts_node_child_by_field_name(node, "argument", 8);
|
|
auto arg = ParseExpression(arg_node, ctx);
|
|
auto expr = MakeNode<PostfixDecrementExpression>();
|
|
expr->kind = NodeKind::kPostfixDecrementExpression;
|
|
expr->span = loc;
|
|
|
|
expr->argument = std::move(arg);
|
|
return expr;
|
|
}
|
|
|
|
// 函数指针
|
|
if (node_type == "function_pointer_expression")
|
|
{
|
|
TSNode arg_node = ts_node_child_by_field_name(node, "argument", 8);
|
|
auto arg = ParseExpression(arg_node, ctx);
|
|
auto expr = MakeNode<FunctionPointerExpression>();
|
|
expr->kind = NodeKind::kFunctionPointerExpression;
|
|
expr->span = loc;
|
|
|
|
expr->argument = std::move(arg);
|
|
return expr;
|
|
}
|
|
|
|
// 通用一元表达式
|
|
TSNode op_node = ts_node_child_by_field_name(node, "operator", 8);
|
|
TSNode arg_node = ts_node_child_by_field_name(node, "argument", 8);
|
|
|
|
if (ts_node_is_null(arg_node))
|
|
return ctx.ReportNullNode(ts::NodeLocation(node), "argument");
|
|
|
|
auto arg = ParseExpression(arg_node, ctx);
|
|
if (!arg)
|
|
return ctx.ReportParseFailed(ts::NodeLocation(arg_node), ts_node_type(arg_node), "argument");
|
|
|
|
std::string op_text;
|
|
if (!ts_node_is_null(op_node))
|
|
op_text = ts::Text(op_node, ctx.Source());
|
|
|
|
UnaryOperator op = ParseUnaryOperator(op_text);
|
|
|
|
auto expr = MakeNode<UnaryExpression>();
|
|
expr->kind = NodeKind::kUnaryExpression;
|
|
expr->span = loc;
|
|
|
|
expr->op = op;
|
|
expr->argument = std::move(arg);
|
|
return expr;
|
|
}
|
|
|
|
ExpressionPtr ParseTernaryExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode cond_node = ts_node_child_by_field_name(node, "condition", 9);
|
|
TSNode cons_node = ts_node_child_by_field_name(node, "consequence", 11);
|
|
TSNode alt_node = ts_node_child_by_field_name(node, "alternative", 11);
|
|
|
|
if (ts_node_is_null(cond_node))
|
|
return ctx.ReportNullNode(loc, "condition");
|
|
|
|
if (ts_node_is_null(alt_node))
|
|
return ctx.ReportNullNode(loc, "alternative");
|
|
|
|
auto condition = ParseExpression(cond_node, ctx);
|
|
auto alternative = ParseExpression(alt_node, ctx);
|
|
|
|
ExpressionPtr consequence;
|
|
if (!ts_node_is_null(cons_node))
|
|
consequence = ParseExpression(cons_node, ctx);
|
|
|
|
auto expr = MakeNode<TernaryExpression>();
|
|
expr->kind = NodeKind::kTernaryExpression;
|
|
expr->span = loc;
|
|
|
|
expr->condition = std::move(condition);
|
|
expr->consequence = std::move(consequence);
|
|
expr->alternative = std::move(alternative);
|
|
return expr;
|
|
}
|
|
|
|
ExpressionPtr ParseCallExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto expr = MakeNode<CallExpression>();
|
|
expr->kind = NodeKind::kCallExpression;
|
|
expr->span = ts::NodeLocation(node);
|
|
|
|
TSNode callee_node = ts_node_child_by_field_name(node, "function", 8);
|
|
if (!ts_node_is_null(callee_node))
|
|
{
|
|
auto callee = ParseExpression(callee_node, ctx);
|
|
std::vector<CallExpression::Argument> arguments;
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(node, i);
|
|
if (!field || std::string_view(field) != "argument")
|
|
continue;
|
|
|
|
TSNode argument_node = ts_node_child(node, i);
|
|
|
|
TSNode child = ts_node_child(argument_node, 0);
|
|
std::string_view child_node_type = ts_node_type(child);
|
|
|
|
CallExpression::Argument arg;
|
|
if (child_node_type == "expression")
|
|
{
|
|
arg.value = ParseExpression(child, ctx);
|
|
}
|
|
else if (child_node_type == "named_argument")
|
|
{
|
|
TSNode name_node = ts_node_child_by_field_name(child, "name", 4);
|
|
if (!ts_node_is_null(name_node))
|
|
{
|
|
arg.name = ts::Text(name_node, ctx.Source());
|
|
arg.location = ts::NodeLocation(name_node);
|
|
}
|
|
|
|
TSNode value_node = ts_node_child_by_field_name(child, "value", 5);
|
|
if (!ts_node_is_null(value_node))
|
|
arg.value = ParseExpression(value_node, ctx);
|
|
}
|
|
arguments.push_back(std::move(arg));
|
|
}
|
|
expr->callee = std::move(callee);
|
|
expr->arguments = std::move(arguments);
|
|
}
|
|
return expr;
|
|
}
|
|
|
|
ExpressionPtr ParseAttributeExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto expr = MakeNode<AttributeExpression>();
|
|
expr->kind = NodeKind::kAttributeExpression;
|
|
expr->span = ts::NodeLocation(node);
|
|
|
|
TSNode obj_node = ts_node_child_by_field_name(node, "object", 6);
|
|
TSNode attr_node = ts_node_child_by_field_name(node, "attribute", 9);
|
|
|
|
if (!ts_node_is_null(obj_node))
|
|
{
|
|
auto object = ParseExpression(obj_node, ctx);
|
|
expr->object = std::move(object);
|
|
}
|
|
if (!ts_node_is_null(attr_node))
|
|
{
|
|
expr->name = ts::Text(attr_node, ctx.Source());
|
|
expr->location = ts::NodeLocation(attr_node);
|
|
}
|
|
return expr;
|
|
}
|
|
|
|
ExpressionPtr ParseSubscriptExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode value_node = ts_node_child_by_field_name(node, "value", 5);
|
|
|
|
if (ts_node_is_null(value_node))
|
|
{
|
|
ctx.RecordMissing(loc, "value");
|
|
return nullptr;
|
|
}
|
|
|
|
auto value = ParseExpression(value_node, ctx);
|
|
|
|
if (!value)
|
|
return nullptr;
|
|
|
|
std::vector<SubscriptExpression::Index> indices;
|
|
|
|
TSNode subscript_node = ts_node_child_by_field_name(node, "subscript", 9);
|
|
if (!ts_node_is_null(subscript_node))
|
|
{
|
|
uint32_t count = ts_node_child_count(subscript_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode idx_node = ts_node_child(subscript_node, i);
|
|
if (!ts_node_is_named(idx_node))
|
|
continue;
|
|
|
|
std::string_view idx_type = ts_node_type(idx_node);
|
|
SubscriptExpression::Index idx;
|
|
|
|
if (idx_type == "slice" || idx_type == "range_slice" ||
|
|
idx_type == "start_slice" || idx_type == "end_slice" ||
|
|
idx_type == "step_slice")
|
|
{
|
|
idx.is_slice = true;
|
|
int part = 0;
|
|
uint32_t count = ts_node_child_count(idx_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode slice_child = ts_node_child(idx_node, i);
|
|
if (!ts_node_is_named(slice_child))
|
|
{
|
|
if (ts::Text(slice_child, ctx.Source()) == ":")
|
|
part++;
|
|
continue;
|
|
}
|
|
|
|
auto expr = ParseExpression(slice_child, ctx);
|
|
if (part == 0)
|
|
idx.start = std::move(expr);
|
|
else if (part == 1)
|
|
idx.end = std::move(expr);
|
|
else if (part == 2)
|
|
idx.step = std::move(expr);
|
|
}
|
|
}
|
|
else if (idx_type == "empty_slice")
|
|
{
|
|
idx.is_empty_slice = true;
|
|
}
|
|
else
|
|
{
|
|
idx.start = ParseExpression(idx_node, ctx);
|
|
}
|
|
|
|
indices.push_back(std::move(idx));
|
|
}
|
|
}
|
|
|
|
auto expr = MakeNode<SubscriptExpression>();
|
|
expr->kind = NodeKind::kSubscriptExpression;
|
|
expr->span = loc;
|
|
|
|
expr->value = std::move(value);
|
|
expr->indices = std::move(indices);
|
|
return expr;
|
|
}
|
|
|
|
ExpressionPtr ParseArrayExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
std::vector<ArrayExpression::Element> elements;
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
|
|
std::string_view child_type = ts_node_type(child);
|
|
|
|
if (child_type == "array_element" || child_type == "key_value_pair")
|
|
{
|
|
ArrayExpression::Element elem;
|
|
|
|
TSNode key_node = ts_node_child_by_field_name(child, "key", 3);
|
|
TSNode value_node = ts_node_child_by_field_name(child, "value", 5);
|
|
|
|
if (!ts_node_is_null(key_node))
|
|
{
|
|
elem.key = ParseExpression(key_node, ctx);
|
|
}
|
|
|
|
if (!ts_node_is_null(value_node))
|
|
{
|
|
elem.value = ParseExpression(value_node, ctx);
|
|
}
|
|
else if (ts_node_is_null(key_node))
|
|
{
|
|
elem.value = ParseExpression(child, ctx);
|
|
}
|
|
|
|
elements.push_back(std::move(elem));
|
|
}
|
|
else if (child_type == "parenthesized_array")
|
|
{
|
|
ArrayExpression::Element elem;
|
|
elem.is_nested = true;
|
|
elem.value = ParseArrayExpression(child, ctx);
|
|
elements.push_back(std::move(elem));
|
|
}
|
|
}
|
|
|
|
auto expr = MakeNode<ArrayExpression>();
|
|
expr->kind = NodeKind::kArrayExpression;
|
|
expr->span = loc;
|
|
|
|
expr->elements = std::move(elements);
|
|
return expr;
|
|
}
|
|
|
|
ExpressionPtr ParseAnonymousFunctionExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
Signature sig = ParseSignature(node, ctx);
|
|
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
auto body = ParseBlockSuite(body_node, ctx);
|
|
|
|
auto expr = MakeNode<AnonymousFunctionExpression>();
|
|
expr->kind = NodeKind::kAnonymousFunctionExpression;
|
|
expr->span = loc;
|
|
|
|
expr->signature = std::move(sig);
|
|
expr->body = std::move(body);
|
|
return expr;
|
|
}
|
|
|
|
// ===== 左值解析(用于赋值语句) =====
|
|
|
|
LeftHandSide ParseLeftHandSide(TSNode node, ParseContext& ctx)
|
|
{
|
|
if (ts_node_is_null(node))
|
|
{
|
|
auto id = MakeNode<Identifier>();
|
|
id->kind = NodeKind::kIdentifier;
|
|
id->span = ts::NodeLocation(node);
|
|
|
|
id->name = "";
|
|
return id;
|
|
}
|
|
|
|
std::string_view node_type = ts_node_type(node);
|
|
|
|
// 标识符
|
|
if (node_type == "identifier" || node_type == "type" ||
|
|
node_type == "class" || node_type == "do")
|
|
{
|
|
std::string name = ts::Text(node, ctx.Source());
|
|
Location loc = ts::NodeLocation(node);
|
|
auto id = MakeNode<Identifier>();
|
|
id->kind = NodeKind::kIdentifier;
|
|
id->span = loc;
|
|
|
|
id->name = std::move(name);
|
|
return id;
|
|
}
|
|
|
|
// 属性访问
|
|
if (node_type == "attribute")
|
|
{
|
|
return std::unique_ptr<AttributeExpression>(
|
|
static_cast<AttributeExpression*>(ParseAttributeExpression(node, ctx).release()));
|
|
}
|
|
|
|
// 下标访问
|
|
if (node_type == "subscript")
|
|
{
|
|
return std::unique_ptr<SubscriptExpression>(
|
|
static_cast<SubscriptExpression*>(ParseSubscriptExpression(node, ctx).release()));
|
|
}
|
|
|
|
// 解包模式
|
|
if (node_type == "unpack_pattern")
|
|
{
|
|
return ParseUnpackPattern(node, ctx);
|
|
}
|
|
|
|
auto id = MakeNode<Identifier>();
|
|
id->kind = NodeKind::kIdentifier;
|
|
id->span = ts::NodeLocation(node);
|
|
|
|
id->name = ts::Text(node, ctx.Source());
|
|
return id;
|
|
}
|
|
|
|
std::unique_ptr<UnpackPattern> ParseUnpackPattern(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
std::vector<std::string> names;
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(node, i);
|
|
if (field && std::string_view(field) == "name")
|
|
names.push_back(ts::Text(ts_node_child(node, i), ctx.Source()));
|
|
}
|
|
|
|
auto pattern = MakeNode<UnpackPattern>();
|
|
pattern->kind = NodeKind::kUnpackPattern;
|
|
pattern->span = loc;
|
|
|
|
pattern->names = std::move(names);
|
|
return pattern;
|
|
}
|
|
|
|
// ===== 语句解析 =====
|
|
|
|
StatementPtr ParseStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
if (ts_node_is_null(node))
|
|
return nullptr;
|
|
|
|
std::string node_type = ts_node_type(node);
|
|
|
|
// 查找注册的解析器
|
|
auto parser = StatementParserRegistry::Instance().Get(node_type);
|
|
if (parser)
|
|
return parser(node, ctx);
|
|
|
|
// 默认作为表达式语句处理
|
|
return ParseExpressionStatement(node, ctx);
|
|
}
|
|
|
|
StatementPtr ParseSingleSuite(TSNode node, ParseContext& ctx)
|
|
{
|
|
TSNode child = ts_node_child(node, 0);
|
|
std::string node_type = ts_node_type(child);
|
|
auto parser = StatementParserRegistry::Instance().Get(node_type);
|
|
if (parser)
|
|
return parser(child, ctx);
|
|
return nullptr;
|
|
}
|
|
|
|
StatementPtr ParseBlockSuite(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
std::vector<StatementPtr> statements;
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
|
|
if (ts::IsComment(child))
|
|
continue;
|
|
|
|
auto stmt = ParseStatement(child, ctx);
|
|
if (stmt)
|
|
statements.push_back(std::move(stmt));
|
|
}
|
|
|
|
auto block = MakeNode<BlockStatement>();
|
|
block->kind = NodeKind::kBlockStatement;
|
|
block->span = loc;
|
|
|
|
block->statements = std::move(statements);
|
|
return block;
|
|
}
|
|
|
|
StatementPtr ParseExpressionStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
ExpressionPtr expr = nullptr;
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
if (ts_node_is_named(child))
|
|
{
|
|
expr = ParseExpression(child, ctx);
|
|
break;
|
|
}
|
|
}
|
|
if (!expr)
|
|
return nullptr;
|
|
|
|
auto stmt = MakeNode<ExpressionStatement>();
|
|
stmt->kind = NodeKind::kExpressionStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->expression = std::move(expr);
|
|
return stmt;
|
|
}
|
|
|
|
ExpressionPtr ParseAssignmentExpression(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode left_node = ts_node_child_by_field_name(node, "left", 4);
|
|
TSNode op_node = ts_node_child_by_field_name(node, "operator", 8);
|
|
TSNode right_node = ts_node_child_by_field_name(node, "right", 5);
|
|
|
|
if (ts_node_is_null(left_node) || ts_node_is_null(right_node))
|
|
return nullptr;
|
|
|
|
LeftHandSide left = ParseLeftHandSide(left_node, ctx);
|
|
|
|
AssignmentOperator op = AssignmentOperator::kAssign;
|
|
if (!ts_node_is_null(op_node))
|
|
{
|
|
std::string op_text = ts::Text(op_node, ctx.Source());
|
|
op = ParseAssignmentOperator(op_text);
|
|
}
|
|
|
|
auto right = ParseExpression(right_node, ctx);
|
|
if (!right)
|
|
return nullptr;
|
|
|
|
auto expr = MakeNode<AssignmentExpression>();
|
|
expr->kind = NodeKind::kAssignmentExpression;
|
|
expr->span = loc;
|
|
|
|
expr->left = std::move(left);
|
|
expr->op = op;
|
|
expr->right = std::move(right);
|
|
return expr;
|
|
}
|
|
|
|
StatementPtr ParseAssignmentStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode left_node = ts_node_child_by_field_name(node, "left", 4);
|
|
TSNode op_node = ts_node_child_by_field_name(node, "operator", 8);
|
|
TSNode right_node = ts_node_child_by_field_name(node, "right", 5);
|
|
|
|
if (ts_node_is_null(left_node))
|
|
{
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
std::string_view child_type = ts_node_type(child);
|
|
if (child_type == "assignment_expression" || child_type == "augmented_assignment_expression")
|
|
{
|
|
left_node = ts_node_child_by_field_name(child, "left", 4);
|
|
op_node = ts_node_child_by_field_name(child, "operator", 8);
|
|
right_node = ts_node_child_by_field_name(child, "right", 5);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ts_node_is_null(left_node) || ts_node_is_null(right_node))
|
|
return nullptr;
|
|
|
|
LeftHandSide left = ParseLeftHandSide(left_node, ctx);
|
|
|
|
AssignmentOperator op = AssignmentOperator::kAssign;
|
|
if (!ts_node_is_null(op_node))
|
|
{
|
|
std::string op_text = ts::Text(op_node, ctx.Source());
|
|
op = ParseAssignmentOperator(op_text);
|
|
}
|
|
|
|
auto right = ParseExpression(right_node, ctx);
|
|
if (!right)
|
|
return nullptr;
|
|
|
|
auto stmt = MakeNode<AssignmentStatement>();
|
|
stmt->kind = NodeKind::kAssignmentStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->left = std::move(left);
|
|
stmt->op = op;
|
|
stmt->right = std::move(right);
|
|
return stmt;
|
|
}
|
|
|
|
// ===== 通用声明解析模板 =====
|
|
|
|
template<typename DeclType, typename StmtType>
|
|
StatementPtr ParseDeclarationStatement(TSNode node, ParseContext& ctx, NodeKind decl_kind, NodeKind stmt_kind)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
std::vector<std::unique_ptr<DeclType>> declarations;
|
|
|
|
TSNode decl_node = ts_node_child_by_field_name(node, "declaration", 11);
|
|
if (!ts_node_is_null(decl_node))
|
|
{
|
|
uint32_t count = ts_node_child_count(decl_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(decl_node, i);
|
|
if (!field || std::string_view(field) != "name")
|
|
continue;
|
|
TSNode name_node = ts_node_child(decl_node, i);
|
|
|
|
std::string name = ts::Text(name_node, ctx.Source());
|
|
Location name_loc = ts::NodeLocation(name_node);
|
|
|
|
auto decl = MakeNode<DeclType>();
|
|
decl->kind = decl_kind;
|
|
decl->span = name_loc;
|
|
|
|
decl->name = std::move(name);
|
|
decl->type = std::nullopt;
|
|
decl->initial_value = nullptr;
|
|
declarations.push_back(std::move(decl));
|
|
}
|
|
|
|
TSNode initial_node = ts_node_child_by_field_name(decl_node, "initial_value", 13);
|
|
if (!ts_node_is_null(initial_node))
|
|
declarations.back()->initial_value = ParseExpression(initial_node, ctx);
|
|
|
|
TSNode type_node = ts_node_child_by_field_name(decl_node, "type_name", 9);
|
|
if (!declarations.empty() && !ts_node_is_null(type_node))
|
|
declarations.back()->type = TypeAnnotation{ .name = ts::Text(type_node, ctx.Source()), .location = ts::NodeLocation(type_node) };
|
|
}
|
|
|
|
auto stmt = MakeNode<StmtType>();
|
|
stmt->kind = stmt_kind;
|
|
stmt->span = loc;
|
|
stmt->declarations = std::move(declarations);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseVarStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
return ParseDeclarationStatement<VarDeclaration, VarStatement>(
|
|
node, ctx, NodeKind::kVarDeclaration, NodeKind::kVarStatement);
|
|
}
|
|
|
|
StatementPtr ParseStaticStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
return ParseDeclarationStatement<StaticDeclaration, StaticStatement>(
|
|
node, ctx, NodeKind::kStaticDeclaration, NodeKind::kStaticStatement);
|
|
}
|
|
|
|
StatementPtr ParseGlobalStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
return ParseDeclarationStatement<GlobalDeclaration, GlobalStatement>(
|
|
node, ctx, NodeKind::kGlobalDeclaration, NodeKind::kGlobalStatement);
|
|
}
|
|
|
|
StatementPtr ParseConstStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
|
|
std::string name = ts_node_is_null(name_node) ? "" : ts::Text(name_node, ctx.Source());
|
|
|
|
std::optional<std::string> type_name;
|
|
TSNode type_node = ts_node_child_by_field_name(node, "type_name", 9);
|
|
if (!ts_node_is_null(type_node))
|
|
{
|
|
type_name = ts::Text(type_node, ctx.Source());
|
|
}
|
|
|
|
TSNode value_node = ts_node_child_by_field_name(node, "value", 5);
|
|
auto value = ParseExpression(value_node, ctx);
|
|
|
|
auto stmt = MakeNode<ConstStatement>();
|
|
stmt->kind = NodeKind::kConstStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->name = std::move(name);
|
|
stmt->type_name = type_name;
|
|
stmt->value = std::move(value);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseIfStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
std::vector<IfStatement::Branch> branches;
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
std::string_view node_type = ts_node_type(child);
|
|
if (node_type == "if_clause")
|
|
{
|
|
IfStatement::Branch branch;
|
|
|
|
TSNode cond_node = ts_node_child_by_field_name(child, "condition", 9);
|
|
branch.condition = ParseExpression(cond_node, ctx);
|
|
TSNode cons_node = ts_node_child_by_field_name(child, "consequence", 11);
|
|
branch.body = ParseStatement(cons_node, ctx);
|
|
|
|
branches.push_back(std::move(branch));
|
|
}
|
|
else if (node_type == "else_if_clause")
|
|
{
|
|
IfStatement::Branch branch;
|
|
TSNode cond_node = ts_node_child_by_field_name(child, "condition", 9);
|
|
branch.condition = ParseExpression(cond_node, ctx);
|
|
|
|
TSNode cons_node = ts_node_child_by_field_name(child, "consequence", 11);
|
|
branch.body = ParseStatement(cons_node, ctx);
|
|
|
|
branches.push_back(std::move(branch));
|
|
}
|
|
else if (node_type == "else_clause")
|
|
{
|
|
IfStatement::Branch branch;
|
|
branch.condition = nullptr;
|
|
|
|
TSNode cons_node = ts_node_child_by_field_name(child, "consequence", 11);
|
|
branch.body = ParseStatement(cons_node, ctx);
|
|
|
|
branches.push_back(std::move(branch));
|
|
}
|
|
}
|
|
|
|
auto stmt = MakeNode<IfStatement>();
|
|
stmt->kind = NodeKind::kIfStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->branches = std::move(branches);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseForInStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode key_node = ts_node_child_by_field_name(node, "key", 3);
|
|
TSNode value_node = ts_node_child_by_field_name(node, "value", 5);
|
|
TSNode collection_node = ts_node_child_by_field_name(node, "collection", 10);
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
|
|
std::string key = ts_node_is_null(key_node) ? "" : ts::Text(key_node, ctx.Source());
|
|
std::string value = ts_node_is_null(value_node) ? "" : ts::Text(value_node, ctx.Source());
|
|
auto collection = ParseExpression(collection_node, ctx);
|
|
auto body = ParseStatement(body_node, ctx);
|
|
|
|
auto stmt = MakeNode<ForInStatement>();
|
|
stmt->kind = NodeKind::kForInStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->key = std::move(key);
|
|
stmt->value = std::move(value);
|
|
stmt->collection = std::move(collection);
|
|
stmt->body = std::move(body);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseForToStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode counter_node = ts_node_child_by_field_name(node, "counter", 7);
|
|
TSNode start_node = ts_node_child_by_field_name(node, "start", 5);
|
|
TSNode end_node = ts_node_child_by_field_name(node, "end", 3);
|
|
TSNode direction_node = ts_node_child_by_field_name(node, "direction", 9);
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
|
|
std::string counter = ts_node_is_null(counter_node) ? "" : ts::Text(counter_node, ctx.Source());
|
|
auto start = ParseExpression(start_node, ctx);
|
|
auto end = ParseExpression(end_node, ctx);
|
|
|
|
bool is_downto = false;
|
|
if (!ts_node_is_null(direction_node))
|
|
{
|
|
std::string direction = ts::Text(direction_node, ctx.Source());
|
|
is_downto = (direction == "downto");
|
|
}
|
|
|
|
auto body = ParseStatement(body_node, ctx);
|
|
|
|
auto stmt = MakeNode<ForToStatement>();
|
|
stmt->kind = NodeKind::kForToStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->counter = std::move(counter);
|
|
stmt->start = std::move(start);
|
|
stmt->end = std::move(end);
|
|
stmt->is_downto = is_downto;
|
|
stmt->body = std::move(body);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseWhileStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode condition_node = ts_node_child_by_field_name(node, "condition", 9);
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
|
|
auto condition = ParseExpression(condition_node, ctx);
|
|
auto body = ParseStatement(body_node, ctx);
|
|
|
|
auto stmt = MakeNode<WhileStatement>();
|
|
stmt->kind = NodeKind::kWhileStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->condition = std::move(condition);
|
|
stmt->body = std::move(body);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseRepeatStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode condition_node = ts_node_child_by_field_name(node, "condition", 9);
|
|
|
|
std::vector<StatementPtr> body_statements;
|
|
std::string name = "body";
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(node, i);
|
|
if (!field || std::string_view(field) != "body")
|
|
continue;
|
|
TSNode child = ts_node_child(node, i);
|
|
|
|
auto stmt = ParseStatement(child, ctx);
|
|
if (stmt)
|
|
body_statements.push_back(std::move(stmt));
|
|
}
|
|
|
|
auto condition = ParseExpression(condition_node, ctx);
|
|
|
|
auto stmt = MakeNode<RepeatStatement>();
|
|
stmt->kind = NodeKind::kRepeatStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->body = std::move(body_statements);
|
|
stmt->condition = std::move(condition);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseCaseStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode discriminant_node = ts_node_child_by_field_name(node, "discriminant", 12);
|
|
auto discriminant = ParseExpression(discriminant_node, ctx);
|
|
|
|
std::vector<CaseStatement::Branch> branches;
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(node, i);
|
|
if (!field || std::string_view(field) != "branches")
|
|
continue;
|
|
TSNode branch_node = ts_node_child(node, i);
|
|
|
|
CaseStatement::Branch branch;
|
|
|
|
std::string value = "value";
|
|
uint32_t branch_count = ts_node_child_count(branch_node);
|
|
for (uint32_t j = 0; j < branch_count; j++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(branch_node, j);
|
|
if (!field || value != field)
|
|
continue;
|
|
|
|
TSNode value_node = ts_node_child(branch_node, j);
|
|
auto value = ParseExpression(value_node, ctx);
|
|
if (value)
|
|
branch.values.push_back(std::move(value));
|
|
}
|
|
|
|
TSNode cons_node = ts_node_child_by_field_name(branch_node, "consequence", 11);
|
|
branch.body = ParseStatement(cons_node, ctx);
|
|
|
|
branches.push_back(std::move(branch));
|
|
}
|
|
|
|
StatementPtr default_case = nullptr;
|
|
TSNode default_node = ts_node_child_by_field_name(node, "default", 7);
|
|
if (!ts_node_is_null(default_node))
|
|
{
|
|
auto cons_node = ts_node_child_by_field_name(default_node, "consequence", 11);
|
|
default_case = ParseStatement(cons_node, ctx);
|
|
}
|
|
|
|
auto stmt = MakeNode<CaseStatement>();
|
|
stmt->kind = NodeKind::kCaseStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->discriminant = std::move(discriminant);
|
|
stmt->branches = std::move(branches);
|
|
stmt->default_case = std::move(default_case);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseTryStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
TSNode try_body_node = ts_node_child_by_field_name(node, "try_body", 8);
|
|
TSNode except_body_node = ts_node_child_by_field_name(node, "except_body", 11);
|
|
|
|
auto try_body = ParseStatement(try_body_node, ctx);
|
|
auto except_body = ParseStatement(except_body_node, ctx);
|
|
|
|
auto stmt = MakeNode<TryStatement>();
|
|
stmt->kind = NodeKind::kTryStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->try_body = std::move(try_body);
|
|
stmt->except_body = std::move(except_body);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseBreakStatement(TSNode node, [[maybe_unused]] ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
auto stmt = MakeNode<BreakStatement>();
|
|
stmt->kind = NodeKind::kBreakStatement;
|
|
stmt->span = loc;
|
|
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseContinueStatement(TSNode node, [[maybe_unused]] ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
auto stmt = MakeNode<ContinueStatement>();
|
|
stmt->kind = NodeKind::kContinueStatement;
|
|
stmt->span = loc;
|
|
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseReturnStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
auto stmt = MakeNode<ReturnStatement>();
|
|
stmt->kind = NodeKind::kReturnStatement;
|
|
stmt->span = loc;
|
|
|
|
TSNode value_node = ts_node_child_by_field_name(node, "value", 5);
|
|
if (!ts_node_is_null(value_node))
|
|
{
|
|
auto value = ParseExpression(value_node, ctx);
|
|
stmt->value = std::move(value);
|
|
}
|
|
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseUsesStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
auto uses = MakeNode<UsesStatement>();
|
|
uses->kind = NodeKind::kUsesStatement;
|
|
uses->span = loc;
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(node, i);
|
|
if (!field || std::string_view(field) != "units")
|
|
continue;
|
|
|
|
TSNode child = ts_node_child(node, i);
|
|
uses->units.push_back(std::move(ts::Text(child, ctx.Source())));
|
|
}
|
|
return uses;
|
|
}
|
|
|
|
StatementPtr ParseInheritedStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
ExpressionPtr expr = nullptr;
|
|
|
|
TSNode class_node = ts_node_child_by_field_name(node, "class", 5);
|
|
if (!ts_node_is_null(class_node))
|
|
expr = ParseExpression(class_node, ctx);
|
|
|
|
auto stmt = MakeNode<ExpressionStatement>();
|
|
stmt->kind = NodeKind::kExpressionStatement;
|
|
stmt->span = loc;
|
|
|
|
stmt->expression = std::move(expr);
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseFunctionDeclaration(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto stmt = MakeNode<FunctionDeclaration>();
|
|
stmt->kind = NodeKind::kFunctionDeclaration;
|
|
stmt->span = ts::NodeLocation(node);
|
|
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
|
|
if (!ts_node_is_null(name_node))
|
|
{
|
|
stmt->name = ts::Text(name_node, ctx.Source());
|
|
stmt->location = ts::NodeLocation(name_node);
|
|
}
|
|
|
|
Signature sig = ParseSignature(node, ctx);
|
|
stmt->signature = std::move(sig);
|
|
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseFunctionDefinition(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto stmt = MakeNode<FunctionDefinition>();
|
|
stmt->kind = NodeKind::kFunctionDefinition;
|
|
stmt->span = ts::NodeLocation(node);
|
|
|
|
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
|
|
if (!ts_node_is_null(name_node))
|
|
{
|
|
std::string name = ts::Text(name_node, ctx.Source());
|
|
stmt->name = std::move(name);
|
|
stmt->location = ts::NodeLocation(name_node);
|
|
}
|
|
|
|
Signature sig = ParseSignature(node, ctx);
|
|
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
auto body = ParseStatement(body_node, ctx);
|
|
|
|
std::string_view node_type = ts_node_type(node);
|
|
bool is_overload = (node_type == "function_definition_with_overload_statement");
|
|
|
|
stmt->signature = std::move(sig);
|
|
stmt->body = std::move(body);
|
|
stmt->is_overload = is_overload;
|
|
return stmt;
|
|
}
|
|
|
|
StatementPtr ParseMatrixIterationStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto stmt = MakeNode<WhileStatement>();
|
|
stmt->kind = NodeKind::kWhileStatement;
|
|
stmt->span = ts::NodeLocation(node);
|
|
|
|
TSNode target_node = ts_node_child_by_field_name(node, "target", 6);
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
|
|
auto target = ParseExpression(target_node, ctx);
|
|
auto body = ParseStatement(body_node, ctx);
|
|
stmt->condition = std::move(target);
|
|
stmt->body = std::move(body);
|
|
return stmt;
|
|
}
|
|
|
|
// ===== TSLX 模板解析 =====
|
|
|
|
StatementPtr ParseTSLXOpenTag(TSNode node, [[maybe_unused]] ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
auto block = MakeNode<BlockStatement>();
|
|
block->kind = NodeKind::kBlockStatement;
|
|
block->span = loc;
|
|
|
|
return block;
|
|
}
|
|
|
|
StatementPtr ParseTSLXCloseTag(TSNode node, [[maybe_unused]] ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
auto block = MakeNode<BlockStatement>();
|
|
block->kind = NodeKind::kBlockStatement;
|
|
block->span = loc;
|
|
|
|
return block;
|
|
}
|
|
|
|
StatementPtr ParseTSLXOutputTag(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
std::vector<ExpressionPtr> expressions;
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
|
|
auto expr = ParseExpression(child, ctx);
|
|
if (expr)
|
|
expressions.push_back(std::move(expr));
|
|
}
|
|
|
|
auto block = MakeNode<BlockStatement>();
|
|
block->kind = NodeKind::kBlockStatement;
|
|
block->span = loc;
|
|
|
|
for (auto& expr : expressions)
|
|
{
|
|
auto expr_stmt = MakeNode<ExpressionStatement>();
|
|
expr_stmt->kind = NodeKind::kExpressionStatement;
|
|
expr_stmt->span = expr->span;
|
|
|
|
expr_stmt->expression = std::move(expr);
|
|
block->statements.push_back(std::move(expr_stmt));
|
|
}
|
|
|
|
return block;
|
|
}
|
|
|
|
StatementPtr ParseTSLXExpressionTag(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
std::vector<StatementPtr> statements;
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
|
|
if (ts::IsComment(child))
|
|
continue;
|
|
|
|
auto stmt = ParseStatement(child, ctx);
|
|
if (stmt)
|
|
statements.push_back(std::move(stmt));
|
|
}
|
|
|
|
auto block = MakeNode<BlockStatement>();
|
|
block->kind = NodeKind::kBlockStatement;
|
|
block->span = loc;
|
|
|
|
block->statements = std::move(statements);
|
|
return block;
|
|
}
|
|
|
|
StatementPtr ParseHTMLSelfClosingTag(TSNode node, [[maybe_unused]] ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
auto block = MakeNode<BlockStatement>();
|
|
block->kind = NodeKind::kBlockStatement;
|
|
block->span = loc;
|
|
|
|
return block;
|
|
}
|
|
|
|
StatementPtr ParseHTMLPairedTag(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
std::vector<StatementPtr> content;
|
|
TSNode content_node = ts_node_child_by_field_name(node, "content", 7);
|
|
if (!ts_node_is_null(content_node))
|
|
{
|
|
uint32_t count = ts_node_child_count(content_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(content_node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
|
|
auto stmt = ParseStatement(child, ctx);
|
|
if (stmt)
|
|
content.push_back(std::move(stmt));
|
|
}
|
|
}
|
|
|
|
auto block = MakeNode<BlockStatement>();
|
|
block->kind = NodeKind::kBlockStatement;
|
|
block->span = loc;
|
|
|
|
block->statements = std::move(content);
|
|
return block;
|
|
}
|
|
|
|
StatementPtr ParseHTMLComment(TSNode node, [[maybe_unused]] ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
auto block = MakeNode<BlockStatement>();
|
|
block->kind = NodeKind::kBlockStatement;
|
|
block->span = loc;
|
|
|
|
return block;
|
|
}
|
|
|
|
StatementPtr ParseUnitDefinition(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto unit = MakeNode<UnitDefinition>();
|
|
unit->kind = NodeKind::kUnitDefinition;
|
|
unit->span = ts::NodeLocation(node);
|
|
|
|
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
|
|
if (!ts_node_is_null(name_node))
|
|
{
|
|
unit->name = ts::Text(name_node, ctx.Source());
|
|
unit->location = ts::NodeLocation(name_node);
|
|
}
|
|
|
|
TSNode interface_node = ts_node_child_by_field_name(node, "interface", 9);
|
|
if (!ts_node_is_null(interface_node))
|
|
{
|
|
uint32_t count = ts_node_child_count(interface_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(interface_node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
if (ts::IsComment(child))
|
|
continue;
|
|
|
|
std::string_view child_type = ts_node_type(child);
|
|
if (child_type == "interface")
|
|
continue;
|
|
auto stmt = ParseStatement(child, ctx);
|
|
if (stmt)
|
|
unit->interface_statements.push_back(std::move(stmt));
|
|
}
|
|
}
|
|
|
|
TSNode impl_node = ts_node_child_by_field_name(node, "implementation", 14);
|
|
if (!ts_node_is_null(impl_node))
|
|
{
|
|
uint32_t count = ts_node_child_count(impl_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(impl_node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
if (ts::IsComment(child))
|
|
continue;
|
|
|
|
std::string_view child_type = ts_node_type(child);
|
|
if (child_type == "implementation")
|
|
continue;
|
|
|
|
auto stmt = ParseStatement(child, ctx);
|
|
if (stmt)
|
|
unit->implementation_statements.push_back(std::move(stmt));
|
|
}
|
|
}
|
|
|
|
TSNode init_node = ts_node_child_by_field_name(node, "initialization", 14);
|
|
if (!ts_node_is_null(init_node))
|
|
{
|
|
uint32_t count = ts_node_child_count(init_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(init_node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
if (ts::IsComment(child))
|
|
continue;
|
|
|
|
std::string_view child_type = ts_node_type(child);
|
|
if (child_type == "initialization")
|
|
continue;
|
|
|
|
auto stmt = ParseStatement(child, ctx);
|
|
if (stmt)
|
|
unit->initialization_statements.push_back(std::move(stmt));
|
|
}
|
|
}
|
|
|
|
TSNode final_node = ts_node_child_by_field_name(node, "finalization", 12);
|
|
if (!ts_node_is_null(final_node))
|
|
{
|
|
uint32_t count = ts_node_child_count(final_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(final_node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
if (ts::IsComment(child))
|
|
continue;
|
|
|
|
std::string_view child_type = ts_node_type(child);
|
|
if (child_type == "finalization")
|
|
continue;
|
|
|
|
auto stmt = ParseStatement(child, ctx);
|
|
if (stmt)
|
|
unit->finalization_statements.push_back(std::move(stmt));
|
|
}
|
|
}
|
|
|
|
return unit;
|
|
}
|
|
|
|
// ===== Class成员解析 =====
|
|
|
|
AccessModifier ParseAccessModifier(TSNode node, ParseContext& ctx)
|
|
{
|
|
std::string text = utils::ToLower(ts::Text(node, ctx.Source()));
|
|
|
|
if (text == "public")
|
|
return AccessModifier::kPublic;
|
|
else if (text == "protected")
|
|
return AccessModifier::kProtected;
|
|
else if (text == "private")
|
|
return AccessModifier::kPrivate;
|
|
|
|
return AccessModifier::kPublic;
|
|
}
|
|
|
|
MethodModifier ParseMethodModifier(TSNode node, ParseContext& ctx)
|
|
{
|
|
std::string text = utils::ToLower(ts::Text(node, ctx.Source()));
|
|
|
|
if (text == "virtual")
|
|
return MethodModifier::kVirtual;
|
|
else if (text == "override")
|
|
return MethodModifier::kOverride;
|
|
else if (text == "overload")
|
|
return MethodModifier::kOverload;
|
|
|
|
return MethodModifier::kNone;
|
|
}
|
|
|
|
ReferenceModifier ParseReferenceModifier(TSNode node, ParseContext& ctx)
|
|
{
|
|
std::string text = utils::ToLower(ts::Text(node, ctx.Source()));
|
|
|
|
if (text == "weakref")
|
|
return ReferenceModifier::kWeakRef;
|
|
else if (text == "autoref")
|
|
return ReferenceModifier::kAutoRef;
|
|
|
|
return ReferenceModifier::kNone;
|
|
}
|
|
|
|
std::unique_ptr<MethodDeclaration> ParseMethodDeclaration(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
auto method = MakeNode<MethodDeclaration>();
|
|
method->kind = NodeKind::kMethodDeclaration;
|
|
method->span = loc;
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
std::string_view child_type = ts_node_type(child);
|
|
if (child_type == "class")
|
|
{
|
|
method->is_class_method = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
|
|
if (!ts_node_is_null(name_node))
|
|
{
|
|
std::string name_type = ts_node_type(name_node);
|
|
if (name_type == "operator_overload")
|
|
{
|
|
method->is_operator_overload = true;
|
|
TSNode op_node = ts_node_child_by_field_name(name_node, "operator", 8);
|
|
if (!ts_node_is_null(op_node))
|
|
{
|
|
method->name = ts::Text(op_node, ctx.Source());
|
|
method->location = ts::NodeLocation(op_node);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
method->name = ts::Text(name_node, ctx.Source());
|
|
method->location = ts::NodeLocation(name_node);
|
|
}
|
|
}
|
|
|
|
method->signature = ParseSignature(node, ctx);
|
|
|
|
TSNode modifier_node = ts_node_child_by_field_name(node, "modifier", 8);
|
|
if (!ts_node_is_null(modifier_node))
|
|
method->modifier = ParseMethodModifier(modifier_node, ctx);
|
|
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
if (!ts_node_is_null(body_node))
|
|
method->body = ParseStatement(body_node, ctx);
|
|
|
|
if (utils::ToLower(method->name) == "create")
|
|
method->method_type = MethodType::kConstructor;
|
|
else if (utils::ToLower(method->name) == "destroy")
|
|
method->method_type = MethodType::kDestructor;
|
|
|
|
return method;
|
|
}
|
|
|
|
std::unique_ptr<PropertyDeclaration> ParsePropertyDeclaration(TSNode node, ParseContext& ctx)
|
|
{
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
auto prop = MakeNode<PropertyDeclaration>();
|
|
prop->kind = NodeKind::kPropertyDeclaration;
|
|
prop->span = loc;
|
|
|
|
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
|
|
if (!ts_node_is_null(name_node))
|
|
{
|
|
prop->name = ts::Text(name_node, ctx.Source());
|
|
prop->location = ts::NodeLocation(name_node);
|
|
}
|
|
|
|
TSNode type_node = ts_node_child_by_field_name(node, "type_name", 9);
|
|
if (!ts_node_is_null(type_node))
|
|
prop->type_name = ts::Text(type_node, ctx.Source());
|
|
|
|
TSNode index_node = ts_node_child_by_field_name(node, "index", 5);
|
|
if (!ts_node_is_null(index_node))
|
|
prop->index_value = ts::Text(node, ctx.Source());
|
|
|
|
TSNode accessors_node = ts_node_child_by_field_name(node, "accessors", 9);
|
|
if (!ts_node_is_null(accessors_node))
|
|
{
|
|
TSNode read_node = ts_node_child_by_field_name(accessors_node, "read", 4);
|
|
TSNode write_node = ts_node_child_by_field_name(accessors_node, "write", 5);
|
|
if (!ts_node_is_null(read_node))
|
|
prop->read_accessor = ts::Text(read_node, ctx.Source());
|
|
if (!ts_node_is_null(write_node))
|
|
prop->write_accessor = ts::Text(write_node, ctx.Source());
|
|
}
|
|
|
|
return prop;
|
|
}
|
|
|
|
std::vector<ClassMemberParseResult> ParseClassMember(TSNode node, ParseContext& ctx, AccessModifier current_access, ReferenceModifier current_reference)
|
|
{
|
|
std::vector<ClassMemberParseResult> results;
|
|
std::string_view node_type = ts_node_type(node);
|
|
Location loc = ts::NodeLocation(node);
|
|
|
|
// 如果是访问修饰符,返回新的访问级别
|
|
if (node_type == "access_modifier")
|
|
{
|
|
ClassMemberParseResult result;
|
|
result.access_modifier = ParseAccessModifier(node, ctx);
|
|
results.push_back(std::move(result));
|
|
return results;
|
|
}
|
|
|
|
// 如果是引用修饰符,返回新的引用修饰符
|
|
if (node_type == "reference_modifier")
|
|
{
|
|
ClassMemberParseResult result;
|
|
result.reference_modifier = ParseReferenceModifier(node, ctx);
|
|
results.push_back(std::move(result));
|
|
return results;
|
|
}
|
|
|
|
if (node_type == "variable_declaration")
|
|
{
|
|
bool is_static = false;
|
|
|
|
TSNode variable_node = ts_node_child_by_field_name(node, "variable", 8);
|
|
if (ts_node_is_null(variable_node))
|
|
return results;
|
|
|
|
bool ref_flag = false;
|
|
TSNode ref_node = ts_node_child_by_field_name(node, "ref_modifier", 12);
|
|
if (!ts_node_is_null(ref_node))
|
|
ref_flag = true;
|
|
|
|
TSNode member_var_node = ts_node_child(variable_node, 0);
|
|
if (ts_node_is_null(member_var_node))
|
|
return results;
|
|
|
|
std::string_view child_type = ts_node_type(member_var_node);
|
|
|
|
if (child_type == "static_member_variable")
|
|
is_static = true;
|
|
else if (child_type == "field_declaration")
|
|
is_static = false;
|
|
|
|
if (ts_node_is_null(member_var_node))
|
|
return results;
|
|
|
|
uint32_t count = ts_node_child_count(member_var_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(member_var_node, i);
|
|
if (!field || std::string_view(field) != "name")
|
|
continue;
|
|
|
|
TSNode name_node = ts_node_child(member_var_node, i);
|
|
std::string name = ts::Text(name_node, ctx.Source());
|
|
Location name_loc = ts::NodeLocation(name_node);
|
|
|
|
auto member = MakeNode<ClassMember>();
|
|
member->kind = NodeKind::kClassMember;
|
|
member->span = name_loc;
|
|
member->access_modifier = current_access;
|
|
|
|
if (is_static)
|
|
{
|
|
auto decl = MakeNode<StaticDeclaration>();
|
|
decl->kind = NodeKind::kStaticDeclaration;
|
|
decl->span = name_loc;
|
|
|
|
decl->name = name;
|
|
decl->reference_modifier = ref_flag ? ParseReferenceModifier(ref_node, ctx) : current_reference;
|
|
|
|
member->member = std::move(decl);
|
|
}
|
|
else
|
|
{
|
|
auto decl = MakeNode<FieldDeclaration>();
|
|
decl->kind = NodeKind::kFieldDeclaration;
|
|
decl->span = name_loc;
|
|
|
|
decl->name = name;
|
|
decl->reference_modifier = ref_flag ? ParseReferenceModifier(ref_node, ctx) : current_reference;
|
|
|
|
member->member = std::move(decl);
|
|
}
|
|
|
|
ClassMemberParseResult result;
|
|
result.member = std::move(member);
|
|
results.push_back(std::move(result));
|
|
}
|
|
|
|
ExpressionPtr initial_value;
|
|
TSNode value_node = ts_node_child_by_field_name(member_var_node, "initial_value", 13);
|
|
if (!ts_node_is_null(value_node))
|
|
initial_value = ParseExpression(value_node, ctx);
|
|
|
|
TSNode type_node = ts_node_child_by_field_name(member_var_node, "type_name", 9);
|
|
if (!results.empty())
|
|
{
|
|
auto& last_member = results.back().member;
|
|
|
|
std::visit([&](auto& decl_ptr) {
|
|
using T = std::decay_t<decltype(*decl_ptr)>;
|
|
|
|
if constexpr (std::is_same_v<T, StaticDeclaration> ||
|
|
std::is_same_v<T, FieldDeclaration>)
|
|
{
|
|
if (!ts_node_is_null(type_node))
|
|
decl_ptr->type = TypeAnnotation{ .name = ts::Text(type_node, ctx.Source()), .location = ts::NodeLocation(type_node) };
|
|
decl_ptr->initial_value = std::move(initial_value);
|
|
}
|
|
},
|
|
last_member->member);
|
|
}
|
|
}
|
|
|
|
else if (node_type == "method_declaration_only" ||
|
|
node_type == "method_with_modifier" ||
|
|
node_type == "method_with_implementation")
|
|
{
|
|
auto member = MakeNode<ClassMember>();
|
|
member->kind = NodeKind::kClassMember;
|
|
member->span = loc;
|
|
|
|
member->access_modifier = current_access;
|
|
|
|
auto method = ParseMethodDeclaration(node, ctx);
|
|
member->member = std::move(method);
|
|
|
|
ClassMemberParseResult result;
|
|
result.member = std::move(member);
|
|
results.push_back(std::move(result));
|
|
}
|
|
else if (node_type == "property_declaration")
|
|
{
|
|
auto member = MakeNode<ClassMember>();
|
|
member->kind = NodeKind::kClassMember;
|
|
member->span = loc;
|
|
|
|
member->access_modifier = current_access;
|
|
|
|
auto prop = ParsePropertyDeclaration(node, ctx);
|
|
member->member = std::move(prop);
|
|
|
|
ClassMemberParseResult result;
|
|
result.member = std::move(member);
|
|
results.push_back(std::move(result));
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
StatementPtr ParseClassDefinition(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto class_def = MakeNode<ClassDefinition>();
|
|
class_def->kind = NodeKind::kClassDefinition;
|
|
class_def->span = ts::NodeLocation(node);
|
|
|
|
TSNode name_node = ts_node_child_by_field_name(node, "name", 4);
|
|
if (!ts_node_is_null(name_node))
|
|
{
|
|
class_def->name = ts::Text(name_node, ctx.Source());
|
|
class_def->location = ts::NodeLocation(name_node);
|
|
}
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
const char* field = ts_node_field_name_for_child(node, i);
|
|
if (!field || std::string_view(field) != "parent")
|
|
continue;
|
|
TSNode parent_node = ts_node_child(node, i);
|
|
|
|
std::string parent_name;
|
|
std::string_view parent_type = ts_node_type(parent_node);
|
|
|
|
ClassDefinition::ParentClass parent;
|
|
if (parent_type == "attribute")
|
|
{
|
|
auto attr = ParseAttributeExpression(parent_node, ctx);
|
|
auto attr_expr = dynamic_cast<AttributeExpression*>(attr.get());
|
|
if (!attr_expr->name.empty())
|
|
{
|
|
parent.name = attr_expr->name;
|
|
parent.location = attr_expr->location;
|
|
}
|
|
if (attr_expr->object)
|
|
{
|
|
auto identifier = dynamic_cast<Identifier*>(attr_expr->object.get());
|
|
parent.qualifier = identifier->name;
|
|
parent.qualifier_location = identifier->location;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
parent.name = ts::Text(parent_node, ctx.Source());
|
|
parent.location = ts::NodeLocation(parent_node);
|
|
}
|
|
class_def->parent_classes.push_back(std::move(parent));
|
|
}
|
|
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
if (!ts_node_is_null(body_node))
|
|
{
|
|
AccessModifier current_access = AccessModifier::kPublic;
|
|
ReferenceModifier current_reference = ReferenceModifier::kNone;
|
|
|
|
uint32_t count = ts_node_child_count(body_node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode member_node = ts_node_child(body_node, i);
|
|
if (!ts_node_is_named(member_node))
|
|
continue;
|
|
if (ts::IsComment(member_node))
|
|
continue;
|
|
|
|
std::string member_type = ts_node_type(member_node);
|
|
if (member_type == "class_member")
|
|
{
|
|
uint32_t member_count = ts_node_child_count(member_node);
|
|
for (uint32_t j = 0; j < member_count; j++)
|
|
{
|
|
TSNode cm_child = ts_node_child(member_node, j);
|
|
|
|
if (!ts_node_is_named(cm_child))
|
|
continue;
|
|
|
|
auto results = ParseClassMember(cm_child, ctx, current_access, current_reference);
|
|
for (auto& result : results)
|
|
{
|
|
if (result.access_modifier)
|
|
current_access = result.access_modifier.value();
|
|
else if (result.reference_modifier)
|
|
current_reference = result.reference_modifier.value();
|
|
else if (result.member)
|
|
class_def->members.push_back(std::move(result.member));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
auto results = ParseClassMember(member_node, ctx, current_access, current_reference);
|
|
for (auto& result : results)
|
|
{
|
|
if (result.access_modifier)
|
|
current_access = result.access_modifier.value();
|
|
else if (result.reference_modifier)
|
|
current_reference = result.reference_modifier.value();
|
|
else if (result.member)
|
|
class_def->members.push_back(std::move(result.member));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return class_def;
|
|
}
|
|
|
|
StatementPtr ParseExternalMethodStatement(TSNode node, ParseContext& ctx)
|
|
{
|
|
auto ext_method = MakeNode<ExternalMethodDefinition>();
|
|
ext_method->kind = NodeKind::kExternalMethodDefinition;
|
|
ext_method->span = ts::NodeLocation(node);
|
|
|
|
TSNode class_node = ts_node_child_by_field_name(node, "class_name", 10);
|
|
if (!ts_node_is_null(class_node))
|
|
{
|
|
ext_method->owner_class.name = ts::Text(class_node, ctx.Source());
|
|
ext_method->owner_class.location = ts::NodeLocation(class_node);
|
|
}
|
|
|
|
TSNode op_node = ts_node_child_by_field_name(node, "operator", 8);
|
|
if (!ts_node_is_null(op_node))
|
|
{
|
|
ext_method->is_operator_overload = true;
|
|
ext_method->name = ts::Text(op_node, ctx.Source());
|
|
ext_method->location = ts::NodeLocation(op_node);
|
|
}
|
|
else
|
|
{
|
|
TSNode method_node = ts_node_child_by_field_name(node, "method_name", 11);
|
|
if (!ts_node_is_null(method_node))
|
|
{
|
|
ext_method->name = ts::Text(method_node, ctx.Source());
|
|
ext_method->location = ts::NodeLocation(method_node);
|
|
}
|
|
}
|
|
|
|
uint32_t count = ts_node_child_count(node);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
{
|
|
TSNode child = ts_node_child(node, i);
|
|
if (!ts_node_is_named(child))
|
|
continue;
|
|
|
|
std::string_view child_type = ts_node_type(child);
|
|
if (child_type == "class")
|
|
{
|
|
ext_method->is_class_method = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ext_method->signature = ParseSignature(node, ctx);
|
|
|
|
TSNode modifier_node = ts_node_child_by_field_name(node, "modifier", 8);
|
|
if (!ts_node_is_null(modifier_node))
|
|
ext_method->modifier = ParseMethodModifier(modifier_node, ctx);
|
|
|
|
TSNode body_node = ts_node_child_by_field_name(node, "body", 4);
|
|
if (!ts_node_is_null(body_node))
|
|
ext_method->body = ParseStatement(body_node, ctx);
|
|
|
|
if (utils::ToLower(ext_method->name) == "create")
|
|
ext_method->method_type = MethodType::kConstructor;
|
|
else if (utils::ToLower(ext_method->name) == "destroy")
|
|
ext_method->method_type = MethodType::kDestructor;
|
|
|
|
return ext_method;
|
|
}
|
|
}
|