(s: string, idx: number)
| 299 | nmax?: number; |
| 300 | } |
| 301 | function parseBracesQuant(s: string, idx: number): QuantifierResult { |
| 302 | const start = idx; |
| 303 | idx++; |
| 304 | let num = ""; |
| 305 | while (idx < s.length && /[0-9]/.test(s[idx])) num += s[idx++]; |
| 306 | if (num === "" || idx >= s.length) return { ok: false, next: start }; |
| 307 | const m = parseInt(num, 10); |
| 308 | if (s[idx] === "}") { |
| 309 | idx++; |
| 310 | eatQuantMod(); |
| 311 | return { ok: true, next: idx, type: "exact", m }; |
| 312 | } |
| 313 | if (s[idx] === ",") { |
| 314 | idx++; |
| 315 | let num2 = ""; |
| 316 | while (idx < s.length && /[0-9]/.test(s[idx])) num2 += s[idx++]; |
| 317 | if (idx >= s.length || s[idx] !== "}") return { ok: false, next: start }; |
| 318 | idx++; |
| 319 | eatQuantMod(); |
| 320 | if (num2 === "") return { ok: true, next: idx, type: "open", m }; // {m,} |
| 321 | const nmax = parseInt(num2, 10); |
| 322 | return { ok: true, next: idx, type: "range", m, nmax }; // {m,n} |
| 323 | } |
| 324 | return { ok: false, next: start }; |
| 325 | } |
| 326 | |
| 327 | interface SequenceAnalysis { |
| 328 | base: string; |
no test coverage detected