()
| 650 | |
| 651 | // ----- Unit parsing ----- 单元解析 |
| 652 | function parseUnit(): Unit | null { |
| 653 | const ch: string = next(); |
| 654 | |
| 655 | if (ch === "\\") { |
| 656 | const esc: string = next(); |
| 657 | if (!esc) return null; // Unterminated escape 转义未结束 |
| 658 | if (esc === "b" || esc === "B") |
| 659 | return { glob: "", baseGlob: "", canRepeat: false, min: 0, isLiteral: false, varLen: false }; // word boundary 词边界 |
| 660 | if ("wdsWDS".includes(esc)) |
| 661 | return { glob: "?", baseGlob: "?", canRepeat: true, min: 1, isLiteral: false, varLen: false }; // class-like escapes 类似 \w \d \s |
| 662 | const lit: string = escapeGlobLiteral(esc); // includes '*'/'?' → '?' 其他转义(含 '*'/'?')→ 字面(映射规则里 '*'/'?' → '?' |
| 663 | return { glob: lit, baseGlob: lit, canRepeat: true, min: 1, isLiteral: true, varLen: false }; |
| 664 | } |
| 665 | |
| 666 | if (ch === ".") return { glob: "?", baseGlob: "?", canRepeat: true, min: 1, isLiteral: false, varLen: false }; |
| 667 | if (ch === "[") return parseCharClass(); |
| 668 | if (ch === "(") return parseGroup(); |
| 669 | if (ch === "^" || ch === "$") |
| 670 | return { glob: "", baseGlob: "", canRepeat: false, min: 0, isLiteral: false, varLen: false }; // anchors 锚点零宽 |
| 671 | |
| 672 | // 頂層遇到孤立的關閉符直接判定為無效語法 |
| 673 | if (ch === ")" || ch === "]") { |
| 674 | return null; |
| 675 | } |
| 676 | |
| 677 | // Plain literal character / 普通字面量字符 |
| 678 | const lit: string = escapeGlobLiteral(ch); |
| 679 | return { glob: lit, baseGlob: lit, canRepeat: true, min: 1, isLiteral: true, varLen: false }; |
| 680 | } |
| 681 | |
| 682 | // ----- Quantifiers ----- 数量词应用 |
| 683 | function applyQuantifier(unit: Unit | null): string | null { |
no test coverage detected