# 完整的 TSLX 块匹配规则 ## 基本原则 - 在 `` 之后进入 `tslx_block`,默认所有内容都是文本(`tslx_content`) - Scanner 通过 lookahead 判断 `` **条件**:遇到 `` **行为**:匹配为 `tsl_statement_block` **Token 序列**:`tsl_statement_start_tag` → `statement...` → `tsl_statement_end_tag` **结果**:`tslx_block` 继续 --- ### 规则 2:配对的 `` **条件**:遇到 `` **行为**:匹配为 `tsl_expression_block` **Token 序列**:`tsl_expression_start_tag` → `expression` → `tsl_expression_end_tag` **结果**:`tslx_block` 继续 --- ### 规则 3:未配对的 `` **行为**: - Scanner 通过 lookahead 判断后面没有 `?>` - **`` **行为**: - Scanner 返回 `tsl_expression_start_tag` - Parser 期望 `expression` 和 `tsl_expression_end_tag` - 找不到 `?>` 导致**语法错误** **结果**:Parser 报错 --- ### 规则 5:到达 EOF **条件**:到达文件末尾,且之前没有遇到未配对的 ``: ### 推荐策略(需选择其一): **策略 A:扫描到换行或分号** ``` ,判定为未配对 ``` - 优点:快速判断,符合单行语句的直觉 - 缺点:多行语句可能误判 **策略 B:扫描到下一个 `,判定为未配对 ``` - 优点:支持多行语句 - 缺点:扫描距离可能较长 **策略 C:扫描固定距离(如 1000 字符)** ``` ,判定为未配对 ``` - 优点:性能可控 - 缺点:可能误判超长的配对块 **当前实现**:_[填入你选择的策略]_ --- ## 示例解析 ### 示例 1:未配对的 `" 2. tslx_content "\naaaa\n" 3. tslx_end_tag "" │ ├── tslx_content: "\naaaa\n" │ └── tslx_end_tag: "" 2. tslx_content "\naaaa\n" 3. tsl_statement_start_tag "" 8. tslx_content "\nbbb\n" 9. tslx_end_tag "" ← EOF 位置生成 ``` #### AST 结构: ``` root └── tslx_block ├── tslx_tag: "" ├── tslx_content: "\naaaa\n" ├── tsl_statement_block │ └── expression_statement │ └── call_expression: echo(1) ├── tslx_content: "\nbbb\n" └── tslx_end_tag: (EOF) ``` --- ### 示例 3:未配对的 `" 2. tslx_content "\n" 3. tsl_expression_start_tag "),但遇到 EOF ``` #### 结果: **语法错误**:`` --- ### 示例 4:混合使用 #### 输入: ```typescript text1 text2 text3 " 2. tslx_content "\ntext1\n" 3. tsl_statement_start_tag "" 6. tslx_content "\ntext2\n" 7. tsl_expression_start_tag "" 10. tslx_content "\ntext3\n" 11. tslx_end_tag " prec.right( seq( $.tslx_tag, repeat( choice( $.tslx_content, $._tsl_statement_block, $._tsl_expression_block, $.tslx_end_tag // ❌ 问题:允许 end_tag 后继续匹配 ), ), ), ), ``` ### 建议修改: ```javascript tslx_block: ($) => prec.right( seq( $.tslx_tag, repeat( choice( $.tslx_content, $._tsl_statement_block, $._tsl_expression_block, ), ), $.tslx_end_tag // ✅ 移到 repeat 外面,作为结束标记 ), ), ``` **理由**: - `tslx_end_tag` 是 `tslx_block` 的**终结符**,不应该在循环体内 - 这样确保 `tslx_end_tag` 后不会再匹配 `tslx_content` 等内容 --- ## 核心要点总结 1. ✅ `` → `tsl_statement_start_tag` - 无 `?>` → `tslx_end_tag` 2. ✅ `` 5. ✅ `tslx_end_tag` 在 Grammar 中应该是 `tslx_block` 的**终结符** 6. ✅ EOF 时自动生成 `tslx_end_tag` 来正常结束 `tslx_block`