🐛 fix(ast): support single-variable for-in fallback

normalize single-variable for-in nodes in the deserializer and
rewrite legacy input in test_ast when the bundled parser cannot
generate updated parse tables.

skip known-invalid tsf fixtures in test.sh so batch runs can
continue past syntax errors that the grammar should not accept.
This commit is contained in:
csh
2026-03-06 11:45:53 +08:00
parent 7e61f5b927
commit 32e1eb09db
5 changed files with 577 additions and 45 deletions
+24 -12
View File
@@ -524,6 +524,8 @@ namespace lsp::language::ast::detail
TSNode default_value_node = ts_node_child_by_field_name(param_node, "default_value", 13);
param->default_value = ParseExpression(default_value_node, ctx);
parameters.push_back(std::move(param));
}
return parameters;
@@ -896,6 +898,7 @@ namespace lsp::language::ast::detail
std::string op_text = ts_utils::Text(op_node, ctx.Source());
expr->op = StringToBinaryOperator(op_text);
expr->operator_location = ts_utils::NodeLocation(op_node);
return expr;
}
@@ -1645,11 +1648,11 @@ namespace lsp::language::ast::detail
}
// 检查是否是类方法
uint32_t count = ts_node_child_count(node);
uint32_t count = ts_node_child_count(child);
for (uint32_t i = 0; i < count; i++)
{
TSNode child = ts_node_child(node, i);
std::string_view child_type = ts_node_type(child);
TSNode method_child = ts_node_child(child, i);
std::string_view child_type = ts_node_type(method_child);
if (child_type == "class")
{
ext_method->is_static = true;
@@ -1735,8 +1738,6 @@ namespace lsp::language::ast::detail
for (uint32_t i = 0; i < count; i++)
{
TSNode child = ts_node_child(node, i);
if (!ts_node_is_named(child))
continue;
std::string text = ts_utils::Text(child, ctx.Source());
if (lsp::utils::ToLower(text) == "overload")
{
@@ -1784,8 +1785,6 @@ namespace lsp::language::ast::detail
for (uint32_t i = 0; i < count; i++)
{
TSNode child = ts_node_child(node, i);
if (!ts_node_is_named(child))
continue;
std::string text = ts_utils::Text(child, ctx.Source());
if (lsp::utils::ToLower(text) == "overload")
{
@@ -1882,8 +1881,6 @@ namespace lsp::language::ast::detail
for (uint32_t i = 0; i < count; i++)
{
TSNode child = ts_node_child(node, i);
if (!ts_node_is_named(child))
continue;
std::string text = lsp::utils::ToLower(ts_utils::Text(child, ctx.Source()));
if (text == "define")
@@ -2035,6 +2032,21 @@ namespace lsp::language::ast::detail
stmt->value = ts_utils::Text(value_node, ctx.Source());
stmt->value_location = ts_utils::NodeLocation(value_node);
}
else if (!stmt->key.empty())
{
// Grammar allows `for value in collection do ...`; normalize it into value slot.
stmt->value = stmt->key;
stmt->value_location = stmt->key_location;
stmt->key.clear();
stmt->key_location = {};
}
if (!stmt->key.empty() && !stmt->value.empty() && stmt->key == stmt->value)
{
// Backward-compatible normalization for pre-rewrite parser fallback.
stmt->key.clear();
stmt->key_location = {};
}
TSNode collection_node = ts_node_child_by_field_name(node, "collection", 10);
stmt->collection = ParseExpression(collection_node, ctx);
@@ -2801,9 +2813,9 @@ namespace lsp::language::ast::detail
};
}
TSNode value_node = ts_node_child_by_field_name(node, "value", 5);
if (!ts_node_is_null(value_node))
declarations.back()->initializer = ParseExpression(value_node, ctx);
TSNode initializer_node = ts_node_child_by_field_name(node, "initializer", 11);
if (!ts_node_is_null(initializer_node))
declarations.back()->initializer = ParseExpression(initializer_node, ctx);
}
// 如果只有一个声明,直接返回