后台的节点下拉是一张 C/Python 混在一起的 15 条表,整份铺给每种语言。给 C 题选到 只有 Python 有的 list_comprehension、f-string,规则存得进去,判题时拿裸名去比节点 类型,C 的语法树里永远不存在它——「必须使用列表推导式」永远失败、「不能使用 f-string」永远通过,两头都不报错,只有学生受着。反过来 mappings 支持的 do_while、 switch、struct、include 在表里没有,编辑器根本选不到。 标签表改成按语言分组,和判题机 mappings 的键集逐条对齐;保存时校验规则与语言是否 匹配,不匹配给中文提示。C 的 target 从 8 个可用变成 14 个。 C++ 接上了 tree-sitter-cpp,386 道 C++ 题从此能配规则。它继承 tree-sitter-c 的语法, C 那 14 个 target 实测全部通用,另加范围 for、类定义、try-catch、throw、namespace、 模板、lambda、using 共 22 个。调用形态和 C/Python 都不同,一并处理:a.push_back() 和 p->push_back() 是 call_expression + field_expression,不是 Python 的 attribute; std::sort(...) 的 function 是 qualified_identifier 而不是 identifier,所以额外比一次 :: 末段,否则学生写没写 using namespace std 会得到不同判定。 一起收掉的几处: - Java/Golang/JavaScript 配的规则一条都不会跑,题目页却照常把它们渲染成「要求」 挂给学生看。现在后台不给这些语言开 tab,下发给学生的要求也按语言过滤。 - 「出现次数」不填数字存下来是一条恒真规则,描述还退化成光秃秃一个「for 循环」。 切换引擎时给默认值,保存时拦下,读取时整条丢弃。 - 次数规则失败只说「if 条件 出现 2 次 ✗」,学生不知道自己写了几次,补上「当前 N 次」。 旧栈的引擎其实算了这个数,但 checker 只取 describe,算完就扔。 - must_have_nesting 的文案没走标签表,学生看到的是「必须使用 for_loop 嵌套」。 - 运算符文案给的是逻辑名,C 题的学生看到「必须使用 and 运算符」,而 C 里写的是 &&。 语义校验放在 astRulesError() 而不是 zod 的 refine 上:astRulesSchema 同时用于读后台 题目详情,在读路径上抛错会让历史脏数据把整个题目详情打不开。保存前先 pickAstRules() 剔除够不着的分组再校验,否则早年配过 C++ 规则的题会把老师锁死——tab 里看不到那组 规则,保存却被拦下。 生产库那 17 条规则(全是 Python3 的 must_exist_node / count_node)行为不变,逐条实跑 核对过。C++ 的 22 个节点 target、25 个运算符也逐个跑了,没有恒假的哑弹。改了带 wasm 内嵌的 ast.ts,dev 和编译两种形态都验过。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
"postgres": "^3.4.9",
|
||||
"sql.js": "^1.14.2",
|
||||
"tree-sitter-c": "^0.24.1",
|
||||
"tree-sitter-cpp": "^0.23.4",
|
||||
"tree-sitter-python": "^0.25.0",
|
||||
"web-tree-sitter": "^0.26.13",
|
||||
"zod": "^4.4.3"
|
||||
|
||||
Reference in New Issue
Block a user