| … | … | @@ -0,0 +1,12 @@ |
| 1 | # Dependencies | |
| 2 | node_modules/ | |
| 3 | ||
| 4 | # Editor and OS cruft | |
| 5 | .DS_Store | |
| 6 | *.log | |
| 7 | *.swp | |
| 8 | .vscode/ | |
| 9 | .idea/ | |
| 10 | ||
| 11 | # Test artifacts | |
| 12 | coverage/ |
| … | … | @@ -0,0 +1,57 @@ |
| 1 | #!/usr/bin/env bare | |
| 2 | import process from 'process' | |
| 3 | import { scanStream } from '../lib/scan-stream.js' | |
| 4 | import { TreeReducer } from '../lib/reducers/tree-reducer.js' | |
| 5 | import { MetricsReducer } from '../lib/reducers/metrics-reducer.js' | |
| 6 | import { buildIgnoreMatcher } from '../lib/ignore.js' | |
| 7 | ||
| 8 | const rootDir = process.argv[2] || '.' | |
| 9 | const maxDepth = parseInt(process.argv[3] || '2', 10) | |
| 10 | const extraIgnores = (process.argv[4] || '').split(',').filter(Boolean) | |
| 11 | const shallow = process.argv.includes('--shallow') | |
| 12 | ||
| 13 | console.log('Profile-scan:', rootDir) | |
| 14 | console.log(' maxDepth:', maxDepth) | |
| 15 | console.log(' shallow: ', shallow) | |
| 16 | console.log(' ignore: ', extraIgnores.length ? extraIgnores.join(',') : '(builtins only)') | |
| 17 | console.log() | |
| 18 | ||
| 19 | const ignore = buildIgnoreMatcher(rootDir, extraIgnores) | |
| 20 | ||
| 21 | const source = scanStream(rootDir, { maxDepth, ignore, shallow }) | |
| 22 | const tree = new TreeReducer().attach(source) | |
| 23 | const metrics = new MetricsReducer().attach(source) | |
| 24 | ||
| 25 | await new Promise((resolveP, reject) => { | |
| 26 | source.once('scan-end', resolveP) | |
| 27 | source.once('error', reject) | |
| 28 | }) | |
| 29 | ||
| 30 | const graph = tree.finalize() | |
| 31 | const m = metrics.report() | |
| 32 | ||
| 33 | console.log('=== Results ===') | |
| 34 | console.log(` total duration: ${m.totalDuration}ms`) | |
| 35 | console.log(` modules: ${m.moduleCount}`) | |
| 36 | console.log(` files discovered: ${m.fileCount}`) | |
| 37 | console.log(` files parsed: ${m.parseCount}`) | |
| 38 | console.log(` parse errors: ${m.parseErrors}`) | |
| 39 | console.log(` import edges: ${m.importEdges} (${m.implicitEdges} implicit)`) | |
| 40 | console.log(` bytes read: ${(m.bytesRead / 1024 / 1024).toFixed(2)} MB`) | |
| 41 | console.log(` largest file: ${m.largestFile.path} (${(m.largestFile.size / 1024).toFixed(0)} KB)`) | |
| 42 | console.log() | |
| 43 | console.log(` throughput: ${m.throughputFilesPerSec} files/s, ${m.throughputMBPerSec} MB/s`) | |
| 44 | console.log(` parse time p50: ${m.parseTimeP50}ms`) | |
| 45 | console.log(` parse time p95: ${m.parseTimeP95}ms`) | |
| 46 | console.log(` parse time p99: ${m.parseTimeP99}ms`) | |
| 47 | console.log(` parse time total: ${m.parseTimeTotal}ms`) | |
| 48 | console.log() | |
| 49 | console.log('=== File extensions ===') | |
| 50 | for (const [ext, count] of m.topExtensions) { | |
| 51 | console.log(` ${ext.padEnd(14)} ${count}`) | |
| 52 | } | |
| 53 | console.log() | |
| 54 | console.log('=== Slowest modules ===') | |
| 55 | for (const mod of m.slowestModules) { | |
| 56 | console.log(` ${mod.name.padEnd(30)} ${mod.duration}ms`) | |
| 57 | } |
| … | … | @@ -0,0 +1,460 @@ |
| 1 | #!/usr/bin/env bare | |
| 2 | ||
| 3 | import process from 'process' | |
| 4 | import { resolve } from 'path' | |
| 5 | import { scan } from './lib/scanner.js' | |
| 6 | ||
| 7 | const args = process.argv.slice(2) | |
| 8 | const command = args[0] | |
| 9 | const pretty = args.includes('--pretty') || args.includes('-p') | |
| 10 | ||
| 11 | if (!command || command === '--help' || command === '-h') { | |
| 12 | printUsage() | |
| 13 | process.exit(0) | |
| 14 | } | |
| 15 | ||
| 16 | // Commands that take a module name as args[1] | |
| 17 | const MODULE_COMMANDS = ['module', 'exports', 'deps', 'file', 'imports'] | |
| 18 | const positionalArgs = args.filter(a => !a.startsWith('-') && a !== command) | |
| 19 | const hasModuleArg = MODULE_COMMANDS.includes(command) | |
| 20 | const dir = resolve(hasModuleArg ? (positionalArgs[1] || '.') : (positionalArgs[0] || '.')) | |
| 21 | const opts = {} | |
| 22 | ||
| 23 | if (args.includes('--depth')) { | |
| 24 | const idx = args.indexOf('--depth') | |
| 25 | opts.maxDepth = parseInt(args[idx + 1], 10) || 2 | |
| 26 | } | |
| 27 | ||
| 28 | // --ignore "pattern1,pattern2" — extra ignore patterns (in addition to .codetreeignore | |
| 29 | // and the built-in skip list). Commas separate patterns; use gitignore-style syntax. | |
| 30 | if (args.includes('--ignore')) { | |
| 31 | const idx = args.indexOf('--ignore') | |
| 32 | const raw = args[idx + 1] || '' | |
| 33 | opts.ignore = raw.split(',').map(s => s.trim()).filter(Boolean) | |
| 34 | } | |
| 35 | ||
| 36 | // --shallow — parse only the entry file per module. Drops AST analysis of the | |
| 37 | // rest of the project; keeps module names, deps, and top-level exports. | |
| 38 | // For multi-project recursive scans this is 10-100x faster. | |
| 39 | if (args.includes('--shallow')) { | |
| 40 | opts.shallow = true | |
| 41 | } | |
| 42 | ||
| 43 | // --no-watch — disable fs.watch in serve mode. Useful for huge trees that | |
| 44 | // exceed the inotify watch limit (ENOSPC). Server still serves the snapshot. | |
| 45 | if (args.includes('--no-watch')) { | |
| 46 | opts.watch = false | |
| 47 | } | |
| 48 | ||
| 49 | async function main () { | |
| 50 | switch (command) { | |
| 51 | case 'scan': return cmdScan() | |
| 52 | case 'module': return cmdModule() | |
| 53 | case 'file': return cmdFile() | |
| 54 | case 'exports': return cmdExports() | |
| 55 | case 'deps': return cmdDeps() | |
| 56 | case 'imports': return cmdImports() | |
| 57 | case 'docs': return cmdDocs() | |
| 58 | case 'categories': return cmdCategories() | |
| 59 | case 'summary': return cmdSummary() | |
| 60 | case 'serve': return cmdServe() | |
| 61 | default: | |
| 62 | console.error(`Unknown command: ${command}`) | |
| 63 | printUsage() | |
| 64 | process.exit(1) | |
| 65 | } | |
| 66 | } | |
| 67 | ||
| 68 | async function cmdScan () { | |
| 69 | const tree = await scan(dir, opts) | |
| 70 | output(tree) | |
| 71 | } | |
| 72 | ||
| 73 | async function cmdModule () { | |
| 74 | const name = args[1] | |
| 75 | if (!name) { | |
| 76 | console.error('Usage: codetree module <name> [dir]') | |
| 77 | process.exit(1) | |
| 78 | } | |
| 79 | ||
| 80 | const tree = await scan(dir, opts) | |
| 81 | const mod = tree.modules[name] | |
| 82 | ||
| 83 | if (!mod) { | |
| 84 | console.error(`Module not found: ${name}`) | |
| 85 | console.error(`Available: ${tree.system.modules.join(', ')}`) | |
| 86 | process.exit(1) | |
| 87 | } | |
| 88 | ||
| 89 | output(mod) | |
| 90 | } | |
| 91 | ||
| 92 | async function cmdFile () { | |
| 93 | const filePath = args[1] | |
| 94 | if (!filePath) { | |
| 95 | console.error('Usage: codetree file <path> [dir]') | |
| 96 | process.exit(1) | |
| 97 | } | |
| 98 | ||
| 99 | const tree = await scan(dir, opts) | |
| 100 | ||
| 101 | for (const mod of Object.values(tree.modules)) { | |
| 102 | if (mod.files[filePath]) { | |
| 103 | output(mod.files[filePath]) | |
| 104 | return | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | console.error(`File not found: ${filePath}`) | |
| 109 | process.exit(1) | |
| 110 | } | |
| 111 | ||
| 112 | async function cmdExports () { | |
| 113 | const name = args[1] | |
| 114 | if (!name) { | |
| 115 | console.error('Usage: codetree exports <module> [dir]') | |
| 116 | process.exit(1) | |
| 117 | } | |
| 118 | ||
| 119 | const tree = await scan(dir, opts) | |
| 120 | const mod = tree.modules[name] | |
| 121 | ||
| 122 | if (!mod) { | |
| 123 | console.error(`Module not found: ${name}`) | |
| 124 | process.exit(1) | |
| 125 | } | |
| 126 | ||
| 127 | if (pretty) { | |
| 128 | console.log(`${mod.name}@${mod.version} public API:`) | |
| 129 | for (const name of mod.publicAPI) { | |
| 130 | console.log(` ${name}`) | |
| 131 | } | |
| 132 | console.log() | |
| 133 | console.log('File exports:') | |
| 134 | for (const [file, data] of Object.entries(mod.files)) { | |
| 135 | if (data.exports.length === 0) continue | |
| 136 | console.log(` ${file}:`) | |
| 137 | for (const exp of data.exports) { | |
| 138 | const type = exp.type ? ` (${exp.type})` : '' | |
| 139 | const from = exp.from ? ` from ${exp.from}` : '' | |
| 140 | console.log(` ${exp.name}${type}${from}`) | |
| 141 | } | |
| 142 | } | |
| 143 | } else { | |
| 144 | output({ | |
| 145 | module: mod.name, | |
| 146 | publicAPI: mod.publicAPI, | |
| 147 | fileExports: Object.fromEntries( | |
| 148 | Object.entries(mod.files) | |
| 149 | .filter(([_, f]) => f.exports.length > 0) | |
| 150 | .map(([k, f]) => [k, f.exports]) | |
| 151 | ) | |
| 152 | }) | |
| 153 | } | |
| 154 | } | |
| 155 | ||
| 156 | async function cmdDeps () { | |
| 157 | const name = args[1] | |
| 158 | if (!name) { | |
| 159 | console.error('Usage: codetree deps <module> [dir]') | |
| 160 | process.exit(1) | |
| 161 | } | |
| 162 | ||
| 163 | const tree = await scan(dir, opts) | |
| 164 | const mod = tree.modules[name] | |
| 165 | ||
| 166 | if (!mod) { | |
| 167 | console.error(`Module not found: ${name}`) | |
| 168 | process.exit(1) | |
| 169 | } | |
| 170 | ||
| 171 | if (pretty) { | |
| 172 | console.log(`${mod.name} dependencies:`) | |
| 173 | for (const [dep, ver] of Object.entries(mod.dependencies)) { | |
| 174 | const isLocal = tree.modules[dep] ? ' (local)' : '' | |
| 175 | console.log(` ${dep}: ${ver}${isLocal}`) | |
| 176 | } | |
| 177 | console.log() | |
| 178 | ||
| 179 | // Reverse deps | |
| 180 | const reverseDeps = [] | |
| 181 | for (const [otherName, otherMod] of Object.entries(tree.modules)) { | |
| 182 | if (otherMod.dependencies[name]) { | |
| 183 | reverseDeps.push(otherName) | |
| 184 | } | |
| 185 | } | |
| 186 | if (reverseDeps.length > 0) { | |
| 187 | console.log(`Used by:`) | |
| 188 | for (const rd of reverseDeps) { | |
| 189 | console.log(` ${rd}`) | |
| 190 | } | |
| 191 | } | |
| 192 | } else { | |
| 193 | const reverseDeps = [] | |
| 194 | for (const [otherName, otherMod] of Object.entries(tree.modules)) { | |
| 195 | if (otherMod.dependencies[name]) reverseDeps.push(otherName) | |
| 196 | } | |
| 197 | output({ | |
| 198 | module: mod.name, | |
| 199 | dependencies: mod.dependencies, | |
| 200 | usedBy: reverseDeps | |
| 201 | }) | |
| 202 | } | |
| 203 | } | |
| 204 | ||
| 205 | async function cmdImports () { | |
| 206 | const name = args[1] | |
| 207 | if (!name) { | |
| 208 | console.error('Usage: codetree imports <module> [dir]') | |
| 209 | process.exit(1) | |
| 210 | } | |
| 211 | ||
| 212 | const tree = await scan(dir, opts) | |
| 213 | const mod = tree.modules[name] | |
| 214 | ||
| 215 | if (!mod) { | |
| 216 | console.error(`Module not found: ${name}`) | |
| 217 | console.error(`Available: ${tree.system.modules.join(', ')}`) | |
| 218 | process.exit(1) | |
| 219 | } | |
| 220 | ||
| 221 | if (!mod.importGraph) { | |
| 222 | console.error('No import graph data (no local imports found)') | |
| 223 | process.exit(1) | |
| 224 | } | |
| 225 | ||
| 226 | if (pretty) { | |
| 227 | const graph = mod.importGraph | |
| 228 | console.log(`${mod.name} — internal architecture\n`) | |
| 229 | ||
| 230 | // Directory dependency matrix | |
| 231 | const dirs = Object.keys(graph.directories).sort() | |
| 232 | if (dirs.length > 0) { | |
| 233 | console.log('Directory dependency matrix:') | |
| 234 | for (const srcDir of dirs) { | |
| 235 | const targets = graph.directoryMatrix[srcDir] | |
| 236 | if (!targets) continue | |
| 237 | const pairs = Object.entries(targets) | |
| 238 | .filter(([tgt]) => tgt !== srcDir) | |
| 239 | .sort((a, b) => b[1] - a[1]) | |
| 240 | if (pairs.length === 0) continue | |
| 241 | const targetStr = pairs.map(([tgt, count]) => `${tgt} (${count})`).join(', ') | |
| 242 | console.log(` ${srcDir} -> ${targetStr}`) | |
| 243 | } | |
| 244 | console.log() | |
| 245 | ||
| 246 | // Directory stats | |
| 247 | console.log('Directory stats:') | |
| 248 | for (const d of dirs) { | |
| 249 | const s = graph.directories[d] | |
| 250 | console.log(` ${d}: ${s.files} files, fan-in ${s.incomingEdges}, fan-out ${s.outgoingEdges}, internal ${s.internalEdges}`) | |
| 251 | } | |
| 252 | console.log() | |
| 253 | } | |
| 254 | ||
| 255 | // Sub-modules | |
| 256 | if (mod.subModules && Object.keys(mod.subModules).length > 0) { | |
| 257 | console.log('Discovered sub-modules:') | |
| 258 | const sorted = Object.entries(mod.subModules).sort((a, b) => b[1].fanIn - a[1].fanIn) | |
| 259 | for (const [dir, sm] of sorted) { | |
| 260 | const idx = sm.indexFile ? ' [index.js]' : '' | |
| 261 | const reexp = sm.hasReExports ? ' [re-exports]' : '' | |
| 262 | console.log(` ${dir}${idx}${reexp}`) | |
| 263 | console.log(` ${sm.files.length} files, fan-in ${sm.fanIn}, fan-out ${sm.fanOut}, cohesion ${sm.cohesion}`) | |
| 264 | if (sm.publicExports.length > 0) { | |
| 265 | console.log(` exports: ${sm.publicExports.join(', ')}`) | |
| 266 | } | |
| 267 | } | |
| 268 | } | |
| 269 | } else { | |
| 270 | output({ | |
| 271 | module: mod.name, | |
| 272 | importGraph: mod.importGraph, | |
| 273 | subModules: mod.subModules | |
| 274 | }) | |
| 275 | } | |
| 276 | } | |
| 277 | ||
| 278 | async function cmdDocs () { | |
| 279 | const tree = await scan(dir, opts) | |
| 280 | ||
| 281 | if (!tree.docCruft) { | |
| 282 | console.error('No documentation found') | |
| 283 | process.exit(1) | |
| 284 | } | |
| 285 | ||
| 286 | const cruft = tree.docCruft | |
| 287 | ||
| 288 | if (pretty) { | |
| 289 | console.log(`Documentation cruft report\n`) | |
| 290 | console.log(`Total: ${cruft.summary.totalDocs} docs, ${cruft.summary.totalLines} lines`) | |
| 291 | console.log(`Fresh (score <= 0.3): ${cruft.summary.freshDocs}`) | |
| 292 | console.log(`Stale (score > 0.5): ${cruft.summary.staleDocs}`) | |
| 293 | console.log(`References: ${cruft.summary.validReferences} valid, ${cruft.summary.missingReferences} missing`) | |
| 294 | console.log() | |
| 295 | ||
| 296 | for (const doc of cruft.docs) { | |
| 297 | if (doc.references.total === 0 && doc.staleness.score < 0.3) continue | |
| 298 | ||
| 299 | const icon = doc.staleness.score > 0.5 ? 'STALE' : doc.staleness.score > 0.3 ? 'WARN ' : 'FRESH' | |
| 300 | console.log(`${icon} ${doc.path} (${doc.lines} lines, modified ${doc.lastModified}, score ${doc.staleness.score})`) | |
| 301 | ||
| 302 | if (doc.references.missing > 0) { | |
| 303 | const missing = doc.references.details.filter(d => d.status === 'missing') | |
| 304 | for (const m of missing.slice(0, 5)) { | |
| 305 | console.log(` missing: ${m.ref} (${m.type}, line ${m.line})`) | |
| 306 | } | |
| 307 | if (missing.length > 5) { | |
| 308 | console.log(` ... and ${missing.length - 5} more`) | |
| 309 | } | |
| 310 | } | |
| 311 | } | |
| 312 | } else { | |
| 313 | output(cruft) | |
| 314 | } | |
| 315 | } | |
| 316 | ||
| 317 | async function cmdCategories () { | |
| 318 | const tree = await scan(dir, opts) | |
| 319 | ||
| 320 | // Build the same category mapping the visualization uses — see render.js initGraph(). | |
| 321 | // Start with SYSTEM.md categories (if any), then fall back to shared-dep clustering. | |
| 322 | const categories = tree.categories || {} | |
| 323 | const moduleToCategory = {} | |
| 324 | for (const [cat, mods] of Object.entries(categories)) { | |
| 325 | for (const m of mods) moduleToCategory[m] = cat | |
| 326 | } | |
| 327 | ||
| 328 | const shared = tree.system.sharedDeps || {} | |
| 329 | const depToMostShared = {} | |
| 330 | for (const [dep, users] of Object.entries(shared)) { | |
| 331 | for (const u of users) { | |
| 332 | const prev = depToMostShared[u] | |
| 333 | if (!prev || users.length > shared[prev].length) depToMostShared[u] = dep | |
| 334 | } | |
| 335 | } | |
| 336 | for (const name of tree.system.modules) { | |
| 337 | if (moduleToCategory[name]) continue | |
| 338 | const topDep = depToMostShared[name] | |
| 339 | moduleToCategory[name] = topDep ? (topDep + ' users') : 'Other' | |
| 340 | } | |
| 341 | ||
| 342 | // Invert for display: category → [modules] | |
| 343 | const byCategory = {} | |
| 344 | for (const [name, cat] of Object.entries(moduleToCategory)) { | |
| 345 | if (!byCategory[cat]) byCategory[cat] = [] | |
| 346 | byCategory[cat].push(name) | |
| 347 | } | |
| 348 | ||
| 349 | if (pretty) { | |
| 350 | console.log(`Module categories for ${tree.root}\n`) | |
| 351 | const sorted = Object.entries(byCategory).sort((a, b) => b[1].length - a[1].length) | |
| 352 | for (const [cat, names] of sorted) { | |
| 353 | console.log(` ${cat} (${names.length})`) | |
| 354 | for (const n of names.sort()) console.log(` ${n}`) | |
| 355 | } | |
| 356 | console.log() | |
| 357 | const specNames = new Set() | |
| 358 | for (const mods of Object.values(categories)) for (const m of mods) specNames.add(m) | |
| 359 | const total = Object.keys(moduleToCategory).length | |
| 360 | const fromSpec = [...Object.keys(moduleToCategory)].filter(m => specNames.has(m)).length | |
| 361 | const autoDerived = total - fromSpec | |
| 362 | console.log(`Source: ${fromSpec} from SYSTEM.md, ${autoDerived} auto-derived from shared dependencies`) | |
| 363 | } else { | |
| 364 | output({ | |
| 365 | source: Object.keys(categories).length > 0 ? 'mixed' : 'auto', | |
| 366 | fromSystemMd: categories, | |
| 367 | assignments: moduleToCategory, | |
| 368 | byCategory | |
| 369 | }) | |
| 370 | } | |
| 371 | } | |
| 372 | ||
| 373 | async function cmdSummary () { | |
| 374 | const tree = await scan(dir, opts) | |
| 375 | ||
| 376 | console.log(`Scanned: ${tree.root}`) | |
| 377 | console.log(`Modules: ${tree.system.modules.length}`) | |
| 378 | console.log() | |
| 379 | ||
| 380 | for (const name of tree.system.modules) { | |
| 381 | const mod = tree.modules[name] | |
| 382 | const fileCount = Object.keys(mod.files).length | |
| 383 | const exportCount = mod.publicAPI.length | |
| 384 | const deps = Object.keys(mod.dependencies).length | |
| 385 | ||
| 386 | let classCount = 0 | |
| 387 | let methodCount = 0 | |
| 388 | for (const file of Object.values(mod.files)) { | |
| 389 | if (file.classes) { | |
| 390 | classCount += file.classes.length | |
| 391 | for (const cls of file.classes) { | |
| 392 | methodCount += cls.methods.length + cls.getters.length | |
| 393 | } | |
| 394 | } | |
| 395 | } | |
| 396 | ||
| 397 | console.log(` ${name}@${mod.version}`) | |
| 398 | console.log(` ${fileCount} files, ${exportCount} exports, ${classCount} classes, ${methodCount} members, ${deps} deps`) | |
| 399 | } | |
| 400 | ||
| 401 | console.log() | |
| 402 | const sharedCount = Object.keys(tree.system.sharedDeps || {}).length | |
| 403 | console.log(`Shared dependencies: ${sharedCount}`) | |
| 404 | } | |
| 405 | ||
| 406 | async function cmdServe () { | |
| 407 | // Defer to server module | |
| 408 | const { startServer } = await import('./lib/server.js') | |
| 409 | const tree = await scan(dir, opts) | |
| 410 | const port = parseInt(args.find(a => /^\d{4,5}$/.test(a)) || '9078', 10) | |
| 411 | const prefixIdx = args.indexOf('--prefix') | |
| 412 | const prefix = prefixIdx >= 0 ? args[prefixIdx + 1] : '' | |
| 413 | startServer(tree, { port, prefix, ignore: opts.ignore, graph: tree.__graph, watch: opts.watch }) | |
| 414 | } | |
| 415 | ||
| 416 | function output (data) { | |
| 417 | console.log(JSON.stringify(data, null, pretty ? 2 : undefined)) | |
| 418 | } | |
| 419 | ||
| 420 | function printUsage () { | |
| 421 | console.log(`codetree — structural code scanner | |
| 422 | ||
| 423 | Usage: | |
| 424 | codetree scan [dir] Full scan, outputs JSON tree | |
| 425 | codetree module <name> [dir] Show one module's structure | |
| 426 | codetree file <path> [dir] Show one file's structure | |
| 427 | codetree exports <module> [dir] List public API surface | |
| 428 | codetree deps <module> [dir] Show dependency chain | |
| 429 | codetree imports <module> [dir] Show internal import graph and sub-modules | |
| 430 | codetree docs [dir] Documentation cruft report | |
| 431 | codetree categories [dir] Show module categorization (SYSTEM.md + auto) | |
| 432 | codetree summary [dir] Human-readable overview | |
| 433 | codetree serve [dir] [port] Start HTTP visualization | |
| 434 | ||
| 435 | Options: | |
| 436 | --pretty, -p Pretty-print JSON / human-readable output | |
| 437 | --depth <n> Max directory depth for project discovery (default: 2) | |
| 438 | --ignore <patterns> Extra ignore patterns, comma-separated, gitignore-style | |
| 439 | --shallow Only parse each module's entry file (no cross-file analysis). | |
| 440 | 10-100x faster for multi-project/recursive scans. | |
| 441 | ||
| 442 | Ignore sources (merged, in this order): | |
| 443 | built-in defaults (node_modules, .git, vendor, .pear-git, .claude, build, dist) | |
| 444 | .codetreeignore file at scan root | |
| 445 | any directory containing a .codetree-private marker | |
| 446 | --ignore CLI flag (this takes effect last) | |
| 447 | ||
| 448 | Examples: | |
| 449 | codetree scan . Scan current directory | |
| 450 | codetree summary ../hyper-fleeky Summarize all modules | |
| 451 | codetree exports hyper-orgs -p Show hyper-orgs public API | |
| 452 | codetree imports pear-git -p Show pear-git internal architecture | |
| 453 | codetree docs ../pear-git -p Find stale documentation | |
| 454 | codetree serve . 9078 Serve visualization on port 9078`) | |
| 455 | } | |
| 456 | ||
| 457 | main().catch(err => { | |
| 458 | console.error(err.message || err) | |
| 459 | process.exit(1) | |
| 460 | }) |
| … | … | @@ -0,0 +1,313 @@ |
| 1 | import { readFileSync, readdirSync, statSync, existsSync } from 'fs' | |
| 2 | import { join, relative, resolve, extname } from 'path' | |
| 3 | ||
| 4 | /** | |
| 5 | * Detect documentation cruft by scanning all markdown files and | |
| 6 | * cross-referencing their code references against the built tree. | |
| 7 | * | |
| 8 | * @param {string} rootDir - Project root directory | |
| 9 | * @param {object} tree - Built code tree from buildTree() | |
| 10 | * @param {Function} [ignore] - Ignore matcher from scanner.js | |
| 11 | * @returns {object} Doc cruft report with per-doc details and summary | |
| 12 | */ | |
| 13 | export function detectDocCruft (rootDir, tree, ignore) { | |
| 14 | const root = resolve(rootDir) | |
| 15 | const ig = ignore || (() => false) | |
| 16 | const mdFiles = findMarkdownFiles(root, ig) | |
| 17 | ||
| 18 | // Build lookup indexes from the tree for fast cross-referencing | |
| 19 | const index = buildCodeIndex(tree) | |
| 20 | ||
| 21 | const docs = [] | |
| 22 | let totalMissing = 0 | |
| 23 | let totalValid = 0 | |
| 24 | ||
| 25 | for (const mdPath of mdFiles) { | |
| 26 | const relPath = relative(root, mdPath) | |
| 27 | let content | |
| 28 | try { content = readFileSync(mdPath, 'utf-8') } catch { continue } | |
| 29 | ||
| 30 | const lines = content.split('\n') | |
| 31 | let mtime | |
| 32 | try { mtime = statSync(mdPath).mtimeMs } catch { mtime = 0 } | |
| 33 | ||
| 34 | // Extract code references | |
| 35 | const refs = extractReferences(content, relPath) | |
| 36 | ||
| 37 | // Cross-reference each against the code tree | |
| 38 | const details = [] | |
| 39 | let valid = 0 | |
| 40 | let missing = 0 | |
| 41 | ||
| 42 | for (const ref of refs) { | |
| 43 | const status = resolveReference(ref, index, root) | |
| 44 | details.push({ ref: ref.value, type: ref.type, status, line: ref.line }) | |
| 45 | if (status === 'valid') valid++ | |
| 46 | else missing++ | |
| 47 | } | |
| 48 | ||
| 49 | totalValid += valid | |
| 50 | totalMissing += missing | |
| 51 | ||
| 52 | // Staleness score: weighted combination of missing refs and age | |
| 53 | const total = valid + missing | |
| 54 | const missingRatio = total > 0 ? missing / total : 0 | |
| 55 | const ageDays = (Date.now() - mtime) / (1000 * 60 * 60 * 24) | |
| 56 | const ageFactor = Math.min(ageDays / 90, 1) // caps at 90 days | |
| 57 | const score = Math.round((missingRatio * 0.6 + ageFactor * 0.4) * 100) / 100 | |
| 58 | ||
| 59 | docs.push({ | |
| 60 | path: relPath, | |
| 61 | lines: lines.length, | |
| 62 | lastModified: new Date(mtime).toISOString().split('T')[0], | |
| 63 | references: { total, valid, missing, details }, | |
| 64 | staleness: { score, missingRatio: Math.round(missingRatio * 100) / 100, ageDays: Math.round(ageDays) } | |
| 65 | }) | |
| 66 | } | |
| 67 | ||
| 68 | // Sort by staleness score descending (most stale first) | |
| 69 | docs.sort((a, b) => b.staleness.score - a.staleness.score) | |
| 70 | ||
| 71 | const staleDocs = docs.filter(d => d.staleness.score > 0.5).length | |
| 72 | const freshDocs = docs.filter(d => d.staleness.score <= 0.3).length | |
| 73 | ||
| 74 | return { | |
| 75 | docs, | |
| 76 | summary: { | |
| 77 | totalDocs: docs.length, | |
| 78 | totalLines: docs.reduce((sum, d) => sum + d.lines, 0), | |
| 79 | freshDocs, | |
| 80 | staleDocs, | |
| 81 | validReferences: totalValid, | |
| 82 | missingReferences: totalMissing | |
| 83 | } | |
| 84 | } | |
| 85 | } | |
| 86 | ||
| 87 | // --- Markdown file discovery --- | |
| 88 | ||
| 89 | function findMarkdownFiles (root, ignore) { | |
| 90 | const files = [] | |
| 91 | walkForMd(root, files, 0, 6, ignore) | |
| 92 | return files | |
| 93 | } | |
| 94 | ||
| 95 | function walkForMd (dir, files, depth, maxDepth, ignore) { | |
| 96 | if (depth >= maxDepth) return | |
| 97 | ||
| 98 | let entries | |
| 99 | try { entries = readdirSync(dir) } catch { return } | |
| 100 | ||
| 101 | for (const entry of entries) { | |
| 102 | const full = join(dir, entry) | |
| 103 | if (ignore(full)) continue | |
| 104 | ||
| 105 | let stat | |
| 106 | try { stat = statSync(full) } catch { continue } | |
| 107 | ||
| 108 | if (stat.isDirectory()) { | |
| 109 | walkForMd(full, files, depth + 1, maxDepth, ignore) | |
| 110 | } else if (entry.endsWith('.md')) { | |
| 111 | files.push(full) | |
| 112 | } | |
| 113 | } | |
| 114 | } | |
| 115 | ||
| 116 | // --- Code index construction --- | |
| 117 | ||
| 118 | function buildCodeIndex (tree) { | |
| 119 | const filePaths = new Set() | |
| 120 | const classNames = new Set() | |
| 121 | const functionNames = new Set() | |
| 122 | const exportNames = new Set() | |
| 123 | ||
| 124 | for (const mod of Object.values(tree.modules)) { | |
| 125 | for (const [filePath, file] of Object.entries(mod.files)) { | |
| 126 | // Index file paths (both package-relative and with module prefix) | |
| 127 | filePaths.add(filePath) | |
| 128 | if (mod.path !== '.') filePaths.add(mod.path + '/' + filePath) | |
| 129 | ||
| 130 | if (file.classes) { | |
| 131 | for (const cls of file.classes) classNames.add(cls.name) | |
| 132 | } | |
| 133 | if (file.functions) { | |
| 134 | for (const fn of file.functions) functionNames.add(fn.name) | |
| 135 | } | |
| 136 | if (file.exports) { | |
| 137 | for (const exp of file.exports) { | |
| 138 | if (exp.name && exp.name !== '*' && exp.name !== 'default') exportNames.add(exp.name) | |
| 139 | if (exp.localName) exportNames.add(exp.localName) | |
| 140 | } | |
| 141 | } | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | return { filePaths, classNames, functionNames, exportNames } | |
| 146 | } | |
| 147 | ||
| 148 | // --- Reference extraction from markdown --- | |
| 149 | ||
| 150 | function extractReferences (content, docPath) { | |
| 151 | const refs = [] | |
| 152 | const lines = content.split('\n') | |
| 153 | const seen = new Set() | |
| 154 | ||
| 155 | for (let i = 0; i < lines.length; i++) { | |
| 156 | const line = lines[i] | |
| 157 | const lineNum = i + 1 | |
| 158 | ||
| 159 | // Backtick identifiers: `SomeClass`, `lib/foo.js`, `someFunction()` | |
| 160 | const backtickPattern = /`([^`\n]+)`/g | |
| 161 | let m | |
| 162 | while ((m = backtickPattern.exec(line)) !== null) { | |
| 163 | const val = m[1].trim() | |
| 164 | if (val.length < 2 || val.length > 120) continue | |
| 165 | if (seen.has(val)) continue | |
| 166 | seen.add(val) | |
| 167 | ||
| 168 | const type = classifyReference(val) | |
| 169 | if (type) refs.push({ value: val, type, line: lineNum }) | |
| 170 | } | |
| 171 | ||
| 172 | // Markdown links to other files: [text](path.md) or [text](./path) | |
| 173 | const linkPattern = /\[([^\]]*)\]\(([^)]+)\)/g | |
| 174 | while ((m = linkPattern.exec(line)) !== null) { | |
| 175 | const target = m[2].trim() | |
| 176 | if (target.startsWith('http://') || target.startsWith('https://')) continue | |
| 177 | if (target.startsWith('#')) continue // anchor links | |
| 178 | if (seen.has('link:' + target)) continue | |
| 179 | seen.add('link:' + target) | |
| 180 | refs.push({ value: target, type: 'doc-link', line: lineNum }) | |
| 181 | } | |
| 182 | } | |
| 183 | ||
| 184 | // Code blocks: extract class names, imports, function names | |
| 185 | // Recognize code blocks in any language we support. Leaving the language tag optional | |
| 186 | // (and not restricting to js) lets us extract references from GDScript, C++, and GLSL | |
| 187 | // snippets embedded in docs too. | |
| 188 | const codeBlockPattern = /```(?:js|javascript|typescript|ts|gdscript|gd|cpp|c\+\+|c|glsl)?\n([\s\S]*?)```/g | |
| 189 | let block | |
| 190 | while ((block = codeBlockPattern.exec(content)) !== null) { | |
| 191 | const code = block[1] | |
| 192 | const blockStartLine = content.slice(0, block.index).split('\n').length | |
| 193 | ||
| 194 | // import { X, Y } from 'module' | |
| 195 | const importPattern = /import\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g | |
| 196 | let imp | |
| 197 | while ((imp = importPattern.exec(code)) !== null) { | |
| 198 | const names = imp[1].split(',').map(n => n.trim()).filter(Boolean) | |
| 199 | for (const name of names) { | |
| 200 | if (seen.has(name)) continue | |
| 201 | seen.add(name) | |
| 202 | refs.push({ value: name, type: 'class-or-function', line: blockStartLine }) | |
| 203 | } | |
| 204 | } | |
| 205 | ||
| 206 | // new ClassName( | |
| 207 | const ctorPattern = /new\s+([A-Z]\w+)\s*\(/g | |
| 208 | let ctor | |
| 209 | while ((ctor = ctorPattern.exec(code)) !== null) { | |
| 210 | if (seen.has(ctor[1])) continue | |
| 211 | seen.add(ctor[1]) | |
| 212 | refs.push({ value: ctor[1], type: 'class', line: blockStartLine }) | |
| 213 | } | |
| 214 | } | |
| 215 | ||
| 216 | return refs | |
| 217 | } | |
| 218 | ||
| 219 | const KNOWN_EXTENSIONS = new Set([ | |
| 220 | 'js', 'mjs', 'cjs', 'json', | |
| 221 | 'gd', 'gdshader', 'tscn', 'tres', | |
| 222 | 'cpp', 'cc', 'cxx', 'c', 'h', 'hpp', 'hh', 'hxx', | |
| 223 | 'glsl', 'vert', 'frag', 'comp', | |
| 224 | 'md', 'txt', 'yaml', 'yml', 'toml' | |
| 225 | ]) | |
| 226 | ||
| 227 | function classifyReference (val) { | |
| 228 | // File path: contains / or ends in a known source extension | |
| 229 | const extMatch = val.match(/\.(\w{1,8})$/) | |
| 230 | const hasKnownExt = extMatch && KNOWN_EXTENSIONS.has(extMatch[1].toLowerCase()) | |
| 231 | if (val.includes('/') || hasKnownExt) { | |
| 232 | // Skip things that look like URLs, semver, or shell commands | |
| 233 | if (val.includes('://') || /^\d+\.\d+/.test(val)) return null | |
| 234 | if (val.startsWith('npm ') || val.startsWith('git ')) return null | |
| 235 | return 'filepath' | |
| 236 | } | |
| 237 | ||
| 238 | // Class name: starts with uppercase letter | |
| 239 | if (/^[A-Z][a-zA-Z0-9]+$/.test(val)) return 'class' | |
| 240 | ||
| 241 | // Function/method call: ends with () | |
| 242 | if (val.endsWith('()') || val.endsWith('(...)')) { | |
| 243 | return 'function' | |
| 244 | } | |
| 245 | ||
| 246 | // Property access: contains . like server.authManager | |
| 247 | if (/^[a-z]\w+\.\w+/.test(val)) return 'property' | |
| 248 | ||
| 249 | // Identifier: lowercase camelCase or snake_case, at least 4 chars to avoid noise | |
| 250 | if (/^[a-z_]\w{3,}$/.test(val) && !isCommonWord(val)) return 'identifier' | |
| 251 | ||
| 252 | return null | |
| 253 | } | |
| 254 | ||
| 255 | function isCommonWord (val) { | |
| 256 | const common = new Set([ | |
| 257 | 'true', 'false', 'null', 'undefined', 'async', 'await', 'const', 'function', | |
| 258 | 'return', 'export', 'import', 'class', 'this', 'super', 'default', 'string', | |
| 259 | 'number', 'boolean', 'object', 'array', 'error', 'open', 'closed', 'pending', | |
| 260 | 'active', 'admin', 'read', 'write', 'owner', 'mirror', 'user', 'name', 'value', | |
| 261 | 'type', 'status', 'title', 'body', 'path', 'data', 'test', 'node', 'bare', | |
| 262 | 'main', 'HEAD', 'master', 'refs' | |
| 263 | ]) | |
| 264 | return common.has(val) | |
| 265 | } | |
| 266 | ||
| 267 | // --- Cross-referencing --- | |
| 268 | ||
| 269 | function resolveReference (ref, index, root) { | |
| 270 | switch (ref.type) { | |
| 271 | case 'filepath': { | |
| 272 | // Clean up: remove trailing slashes, leading ./ | |
| 273 | let cleaned = ref.value.replace(/^\.\//, '').replace(/\/$/, '') | |
| 274 | // Strip method call suffixes like lib/auth.js:authenticate() | |
| 275 | cleaned = cleaned.replace(/:\w+\(.*\)$/, '') | |
| 276 | // Check against indexed file paths | |
| 277 | if (index.filePaths.has(cleaned)) return 'valid' | |
| 278 | // Check if directory exists on disk | |
| 279 | const absPath = resolve(root, cleaned) | |
| 280 | if (existsSync(absPath)) return 'valid' | |
| 281 | return 'missing' | |
| 282 | } | |
| 283 | ||
| 284 | case 'class': | |
| 285 | return index.classNames.has(ref.value) || index.exportNames.has(ref.value) ? 'valid' : 'missing' | |
| 286 | ||
| 287 | case 'function': { | |
| 288 | const name = ref.value.replace(/\(.*\)$/, '') | |
| 289 | return index.functionNames.has(name) || index.exportNames.has(name) ? 'valid' : 'missing' | |
| 290 | } | |
| 291 | ||
| 292 | case 'class-or-function': | |
| 293 | return (index.classNames.has(ref.value) || index.functionNames.has(ref.value) || index.exportNames.has(ref.value)) | |
| 294 | ? 'valid' : 'missing' | |
| 295 | ||
| 296 | case 'property': | |
| 297 | case 'identifier': | |
| 298 | // For identifiers, check if they appear as any known symbol | |
| 299 | return (index.classNames.has(ref.value) || index.functionNames.has(ref.value) || index.exportNames.has(ref.value)) | |
| 300 | ? 'valid' : 'unknown' | |
| 301 | ||
| 302 | case 'doc-link': { | |
| 303 | // Check if linked document exists on disk (relative to the doc's directory or root) | |
| 304 | const target = ref.value.replace(/^\.\//, '') | |
| 305 | const absPath = resolve(root, target) | |
| 306 | if (existsSync(absPath)) return 'valid' | |
| 307 | return 'missing' | |
| 308 | } | |
| 309 | ||
| 310 | default: | |
| 311 | return 'unknown' | |
| 312 | } | |
| 313 | } |
| … | … | @@ -0,0 +1,281 @@ |
| 1 | import { readFileSync, existsSync, readdirSync, statSync } from 'fs' | |
| 2 | import { resolve, join, basename, relative } from 'path' | |
| 3 | ||
| 4 | /** | |
| 5 | * Parse spec files and SYSTEM.md to extract documented claims. | |
| 6 | * Returns claims linked to module names that the validator can check | |
| 7 | * against the code tree. | |
| 8 | */ | |
| 9 | ||
| 10 | export function parseSpecs (specDir) { | |
| 11 | const result = { | |
| 12 | system: null, | |
| 13 | modules: {} | |
| 14 | } | |
| 15 | ||
| 16 | if (!existsSync(specDir)) return result | |
| 17 | ||
| 18 | // Parse SYSTEM.md | |
| 19 | const systemPath = join(specDir, 'SYSTEM.md') | |
| 20 | if (existsSync(systemPath)) { | |
| 21 | result.system = parseSystemSpec(readFileSync(systemPath, 'utf-8')) | |
| 22 | } | |
| 23 | ||
| 24 | // Parse module specs | |
| 25 | const modulesDir = join(specDir, 'modules') | |
| 26 | if (existsSync(modulesDir) && statSync(modulesDir).isDirectory()) { | |
| 27 | for (const file of readdirSync(modulesDir)) { | |
| 28 | if (!file.endsWith('.md')) continue | |
| 29 | const content = readFileSync(join(modulesDir, file), 'utf-8') | |
| 30 | const spec = parseModuleSpec(content, file) | |
| 31 | if (spec.name) { | |
| 32 | result.modules[spec.name] = spec | |
| 33 | } | |
| 34 | } | |
| 35 | } | |
| 36 | ||
| 37 | return result | |
| 38 | } | |
| 39 | ||
| 40 | // --- System spec parser --- | |
| 41 | ||
| 42 | function parseSystemSpec (content) { | |
| 43 | const spec = { | |
| 44 | lastVerified: null, | |
| 45 | modules: [], // { name, location, purpose, category } | |
| 46 | categories: {}, // category -> [module names] | |
| 47 | builtItems: [], | |
| 48 | missingItems: [] | |
| 49 | } | |
| 50 | ||
| 51 | // Last verified date | |
| 52 | const verifiedMatch = content.match(/\*\*Last verified:\*\*\s*(\d{4}-\d{2}-\d{2})/) | |
| 53 | if (verifiedMatch) spec.lastVerified = verifiedMatch[1] | |
| 54 | ||
| 55 | // Module inventory from markdown tables, grouped by category headers | |
| 56 | // Categories are ### headings above the tables | |
| 57 | const sections = content.split(/^### /m) | |
| 58 | let currentCategory = 'Uncategorized' | |
| 59 | ||
| 60 | for (const section of sections) { | |
| 61 | const categoryMatch = section.match(/^([^\n]+)/) | |
| 62 | if (categoryMatch && !section.startsWith('#')) { | |
| 63 | currentCategory = categoryMatch[1].trim().replace(/\s*\(.*\)/, '') | |
| 64 | } | |
| 65 | ||
| 66 | const tablePattern = /\|\s*\*\*(\w[\w-]*)\*\*\s*\|\s*`([^`]*)`\s*\|\s*([^|]+)\|/g | |
| 67 | let match | |
| 68 | while ((match = tablePattern.exec(section)) !== null) { | |
| 69 | const name = match[1] | |
| 70 | spec.modules.push({ | |
| 71 | name, | |
| 72 | location: match[2].trim(), | |
| 73 | purpose: match[3].trim(), | |
| 74 | category: currentCategory | |
| 75 | }) | |
| 76 | if (!spec.categories[currentCategory]) spec.categories[currentCategory] = [] | |
| 77 | spec.categories[currentCategory].push(name) | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | // Built items (checkmarks) | |
| 82 | const builtPattern = /- ✅\s*(.+)/g | |
| 83 | let builtMatch | |
| 84 | while ((builtMatch = builtPattern.exec(content)) !== null) { | |
| 85 | spec.builtItems.push(builtMatch[1].trim()) | |
| 86 | } | |
| 87 | ||
| 88 | // Missing items (x marks) | |
| 89 | const missingPattern = /- ❌\s*(.+)/g | |
| 90 | let missingMatch | |
| 91 | while ((missingMatch = missingPattern.exec(content)) !== null) { | |
| 92 | spec.missingItems.push(missingMatch[1].trim()) | |
| 93 | } | |
| 94 | ||
| 95 | return spec | |
| 96 | } | |
| 97 | ||
| 98 | // --- Module spec parser --- | |
| 99 | ||
| 100 | function parseModuleSpec (content, filename) { | |
| 101 | const spec = { | |
| 102 | name: null, | |
| 103 | filename, | |
| 104 | location: null, | |
| 105 | testCount: null, | |
| 106 | sourceVerified: null, | |
| 107 | fileLOC: {}, // filename -> claimed LOC | |
| 108 | description: null, | |
| 109 | notDescription: [], | |
| 110 | dependencies: [], | |
| 111 | dependents: [], | |
| 112 | claimedMethods: [], | |
| 113 | claimedGetters: [], | |
| 114 | claimedExports: [], | |
| 115 | claimedConstructorParams: [], | |
| 116 | roleInSystem: null | |
| 117 | } | |
| 118 | ||
| 119 | // Module name from title: "# hyper-orgs -- Module Spec" | |
| 120 | const titleMatch = content.match(/^#\s+(\S+)\s+--/m) | |
| 121 | if (titleMatch) spec.name = titleMatch[1] | |
| 122 | ||
| 123 | // Location | |
| 124 | const locMatch = content.match(/\*\*Location:\*\*\s*`([^`]+)`/) | |
| 125 | if (locMatch) spec.location = locMatch[1].replace(/\/$/, '') | |
| 126 | ||
| 127 | // Test count | |
| 128 | const testMatch = content.match(/\*\*Tests:\*\*\s*(\d+)\s*pass/) | |
| 129 | if (testMatch) spec.testCount = parseInt(testMatch[1], 10) | |
| 130 | ||
| 131 | // Source verified date + LOC claims | |
| 132 | const verifiedMatch = content.match(/\*\*Source verified:\*\*\s*(\d{4}-\d{2}-\d{2})\s*\(([^)]+)\)/) | |
| 133 | if (verifiedMatch) { | |
| 134 | spec.sourceVerified = verifiedMatch[1] | |
| 135 | // Parse "hyper-orgs.js 637 LOC, schema.js 515 LOC" | |
| 136 | const locParts = verifiedMatch[2].split(',') | |
| 137 | for (const part of locParts) { | |
| 138 | const locPartMatch = part.trim().match(/(\S+)\s+(\d+)\s+LOC/) | |
| 139 | if (locPartMatch) { | |
| 140 | spec.fileLOC[locPartMatch[1]] = parseInt(locPartMatch[2], 10) | |
| 141 | } | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | // Description (## What it is) | |
| 146 | const whatMatch = content.match(/## What it is\n\n([\s\S]*?)(?=\n## |\n---|\n$)/) | |
| 147 | if (whatMatch) spec.description = whatMatch[1].trim() | |
| 148 | ||
| 149 | // Not description (## What it is NOT) | |
| 150 | const notSection = content.match(/## What it is NOT\n\n([\s\S]*?)(?=\n## |\n---|\n$)/) | |
| 151 | if (notSection) { | |
| 152 | const lines = notSection[1].split('\n').filter(l => l.startsWith('- ')) | |
| 153 | spec.notDescription = lines.map(l => l.replace(/^- /, '').trim()) | |
| 154 | } | |
| 155 | ||
| 156 | // Dependencies section | |
| 157 | const depSection = content.match(/## Dependencies\n\n([\s\S]*?)(?=\n## |\n$)/) | |
| 158 | if (depSection) { | |
| 159 | const lines = depSection[1].split('\n').filter(l => l.startsWith('- ')) | |
| 160 | for (const line of lines) { | |
| 161 | const depMatch = line.match(/`([^`]+)`/) | |
| 162 | if (depMatch) spec.dependencies.push(depMatch[1]) | |
| 163 | } | |
| 164 | } | |
| 165 | ||
| 166 | // Dependents section | |
| 167 | const deptsSection = content.match(/## What depends on this\n\n([\s\S]*?)(?=\n## |\n$)/) | |
| 168 | if (deptsSection) { | |
| 169 | const lines = deptsSection[1].split('\n').filter(l => l.startsWith('- ')) | |
| 170 | for (const line of lines) { | |
| 171 | const deptMatch = line.match(/\*\*([^*]+)\*\*/) | |
| 172 | if (deptMatch) spec.dependents.push(deptMatch[1]) | |
| 173 | } | |
| 174 | } | |
| 175 | ||
| 176 | // Role in pear-git | |
| 177 | const roleSection = content.match(/## Role in pear-git\n\n([\s\S]*?)(?=\n## |\n$)/) | |
| 178 | if (roleSection) spec.roleInSystem = roleSection[1].trim() | |
| 179 | ||
| 180 | // Extract method names from API code block | |
| 181 | const apiBlock = content.match(/## API[^\n]*\n\n```js\n([\s\S]*?)```/) | |
| 182 | if (apiBlock) { | |
| 183 | const code = apiBlock[1] | |
| 184 | ||
| 185 | // Method calls: await orgs.methodName( or orgs.methodName( | |
| 186 | const methodPattern = /(?:await\s+)?\w+\.(\w+)\s*\(/g | |
| 187 | let m | |
| 188 | while ((m = methodPattern.exec(code)) !== null) { | |
| 189 | const name = m[1] | |
| 190 | if (!spec.claimedMethods.includes(name) && name !== 'ready' && name !== 'close') { | |
| 191 | spec.claimedMethods.push(name) | |
| 192 | } | |
| 193 | } | |
| 194 | ||
| 195 | // Properties: orgs.key / keyHex / ... | |
| 196 | const propPattern = /\w+\.(\w+)\s*[/\n]/g | |
| 197 | while ((m = propPattern.exec(code)) !== null) { | |
| 198 | if (!spec.claimedGetters.includes(m[1])) { | |
| 199 | spec.claimedGetters.push(m[1]) | |
| 200 | } | |
| 201 | } | |
| 202 | ||
| 203 | // Constructor: new ClassName(param1, { ... }) | |
| 204 | const ctorMatch = code.match(/new\s+(\w+)\s*\(([^)]*)\)/) | |
| 205 | if (ctorMatch) { | |
| 206 | spec.claimedExports.push(ctorMatch[1]) | |
| 207 | // Extract param names | |
| 208 | const params = ctorMatch[2].split(',').map(p => p.trim().replace(/[{}\s].*/g, '')).filter(Boolean) | |
| 209 | spec.claimedConstructorParams = params | |
| 210 | } | |
| 211 | ||
| 212 | // Import: import { X } from 'module' | |
| 213 | const importMatch = code.match(/import\s*\{([^}]+)\}\s*from/) | |
| 214 | if (importMatch) { | |
| 215 | const names = importMatch[1].split(',').map(n => n.trim()) | |
| 216 | for (const n of names) { | |
| 217 | if (!spec.claimedExports.includes(n)) spec.claimedExports.push(n) | |
| 218 | } | |
| 219 | } | |
| 220 | } | |
| 221 | ||
| 222 | return spec | |
| 223 | } | |
| 224 | ||
| 225 | /** | |
| 226 | * Scan a directory for all doc sources — specs, READMEs, JSDoc. | |
| 227 | * Returns a unified doc inventory. | |
| 228 | */ | |
| 229 | export function findAllDocs (rootDir) { | |
| 230 | const docs = { | |
| 231 | specs: [], // spec/modules/*.md | |
| 232 | system: null, // spec/SYSTEM.md | |
| 233 | readmes: [], // */README.md | |
| 234 | specDir: null | |
| 235 | } | |
| 236 | ||
| 237 | // Look for spec directory in common locations | |
| 238 | const specLocations = [ | |
| 239 | join(rootDir, 'spec'), | |
| 240 | join(rootDir, 'docs', 'spec') | |
| 241 | ] | |
| 242 | ||
| 243 | // Also check each module for its own spec dir | |
| 244 | try { | |
| 245 | for (const entry of readdirSync(rootDir)) { | |
| 246 | const specPath = join(rootDir, entry, 'spec') | |
| 247 | if (existsSync(specPath) && statSync(specPath).isDirectory()) { | |
| 248 | specLocations.push(specPath) | |
| 249 | } | |
| 250 | } | |
| 251 | } catch {} | |
| 252 | ||
| 253 | for (const specDir of specLocations) { | |
| 254 | if (!existsSync(specDir)) continue | |
| 255 | docs.specDir = specDir | |
| 256 | ||
| 257 | const systemPath = join(specDir, 'SYSTEM.md') | |
| 258 | if (existsSync(systemPath)) docs.system = systemPath | |
| 259 | ||
| 260 | const modulesDir = join(specDir, 'modules') | |
| 261 | if (existsSync(modulesDir)) { | |
| 262 | try { | |
| 263 | for (const f of readdirSync(modulesDir)) { | |
| 264 | if (f.endsWith('.md')) docs.specs.push(join(modulesDir, f)) | |
| 265 | } | |
| 266 | } catch {} | |
| 267 | } | |
| 268 | } | |
| 269 | ||
| 270 | // Find READMEs | |
| 271 | try { | |
| 272 | for (const entry of readdirSync(rootDir)) { | |
| 273 | const readmePath = join(rootDir, entry, 'README.md') | |
| 274 | if (existsSync(readmePath)) { | |
| 275 | docs.readmes.push({ module: entry, path: readmePath }) | |
| 276 | } | |
| 277 | } | |
| 278 | } catch {} | |
| 279 | ||
| 280 | return docs | |
| 281 | } |
| … | … | @@ -0,0 +1,79 @@ |
| 1 | import { watch, statSync } from 'fs' | |
| 2 | import { EventEmitter } from 'events' | |
| 3 | import { resolve, relative, join } from 'path' | |
| 4 | ||
| 5 | /** | |
| 6 | * Wraps fs.watch for a project root and emits normalized `change` events. | |
| 7 | * | |
| 8 | * Honors the ignore matcher — hidden files don't produce events. | |
| 9 | * | |
| 10 | * const w = new FsWatcher(rootDir, ignore) | |
| 11 | * w.on('change', path => ...) | |
| 12 | * w.on('remove', path => ...) | |
| 13 | * w.close() | |
| 14 | * | |
| 15 | * There are no timers here. bare-fs.watch is inotify-backed on Linux; every | |
| 16 | * event is a real filesystem push from the kernel. | |
| 17 | */ | |
| 18 | export class FsWatcher extends EventEmitter { | |
| 19 | constructor (rootDir, ignore, opts = {}) { | |
| 20 | super() | |
| 21 | this.rootDir = resolve(rootDir) | |
| 22 | this.ignore = ignore || (() => false) | |
| 23 | this._debounce = new Map() // path -> timer? No — we batch via a set. | |
| 24 | this._pending = new Set() // coalesce rapid-fire events | |
| 25 | this._flushScheduled = false | |
| 26 | this._closed = false | |
| 27 | ||
| 28 | try { | |
| 29 | this._handle = watch(this.rootDir, { recursive: true }, (eventType, filename) => { | |
| 30 | if (this._closed || !filename) return | |
| 31 | // fs.watch gives a path relative to the watched root. Normalize to absolute. | |
| 32 | const abs = join(this.rootDir, filename) | |
| 33 | if (this.ignore(abs)) return | |
| 34 | this._enqueue(abs) | |
| 35 | }) | |
| 36 | // Errors from the underlying watcher (ENOSPC mid-stream, EBADF, etc.) | |
| 37 | // must be caught — without a listener Node crashes the process. | |
| 38 | this._handle.on('error', err => { | |
| 39 | // Mark closed so we stop trying to enqueue events | |
| 40 | this._closed = true | |
| 41 | queueMicrotask(() => this.emit('error', err)) | |
| 42 | }) | |
| 43 | } catch (err) { | |
| 44 | // Watching failed at construction (platform limit, permission, etc.). Emit error | |
| 45 | // instead of crashing — server can still serve the initial tree. | |
| 46 | queueMicrotask(() => this.emit('error', err)) | |
| 47 | } | |
| 48 | } | |
| 49 | ||
| 50 | // Coalesce bursts of events on the same path into a single `change` emission. | |
| 51 | // Many editors rewrite files via temp + rename, which fires 2-3 events in | |
| 52 | // the same tick. Batching with queueMicrotask merges them without a timer. | |
| 53 | _enqueue (abs) { | |
| 54 | this._pending.add(abs) | |
| 55 | if (this._flushScheduled) return | |
| 56 | this._flushScheduled = true | |
| 57 | queueMicrotask(() => this._flush()) | |
| 58 | } | |
| 59 | ||
| 60 | _flush () { | |
| 61 | this._flushScheduled = false | |
| 62 | for (const abs of this._pending) { | |
| 63 | let exists = true | |
| 64 | try { statSync(abs) } catch { exists = false } | |
| 65 | const relPath = relative(this.rootDir, abs) | |
| 66 | if (exists) this.emit('change', { absPath: abs, relPath }) | |
| 67 | else this.emit('remove', { absPath: abs, relPath }) | |
| 68 | } | |
| 69 | this._pending.clear() | |
| 70 | } | |
| 71 | ||
| 72 | close () { | |
| 73 | this._closed = true | |
| 74 | if (this._handle) { | |
| 75 | try { this._handle.close() } catch {} | |
| 76 | this._handle = null | |
| 77 | } | |
| 78 | } | |
| 79 | } |
| … | … | @@ -0,0 +1,192 @@ |
| 1 | import { readFileSync, existsSync, readdirSync, statSync, lstatSync } from 'fs' | |
| 2 | import { join, relative, resolve, basename } from 'path' | |
| 3 | ||
| 4 | /** | |
| 5 | * Directory ignore system. | |
| 6 | * | |
| 7 | * Consolidates the previously-scattered skip logic in traverse/lang/doc-cruft/server | |
| 8 | * into one matcher that all scan sites share. | |
| 9 | * | |
| 10 | * Pattern sources (in precedence order): | |
| 11 | * 1. Built-in defaults (node_modules, .git, etc.) | |
| 12 | * 2. .codetreeignore at rootDir (gitignore subset) | |
| 13 | * 3. Nested .codetree-private markers (any dir containing this file is fully hidden) | |
| 14 | * 4. extraPatterns (from --ignore CLI flag) | |
| 15 | * | |
| 16 | * Usage: | |
| 17 | * const ignore = buildIgnoreMatcher(rootDir, ['*.secrets']) | |
| 18 | * if (ignore(absolutePath)) continue // skip | |
| 19 | */ | |
| 20 | ||
| 21 | const BUILTIN_PATTERNS = [ | |
| 22 | 'node_modules', | |
| 23 | '.git', | |
| 24 | '.pear-git', | |
| 25 | '.claude', | |
| 26 | 'vendor', // codetree's own vendor dir + pear-git's | |
| 27 | 'thirdparty', // C++ convention | |
| 28 | 'third_party', // alternate spelling (Google / Chromium / etc.) | |
| 29 | 'deps', // common dep bundle name | |
| 30 | 'build', | |
| 31 | 'dist', | |
| 32 | '.DS_Store' | |
| 33 | ] | |
| 34 | ||
| 35 | const PRIVATE_MARKER = '.codetree-private' | |
| 36 | const IGNORE_FILE = '.codetreeignore' | |
| 37 | const PRIVATE_SCAN_MAX_DEPTH = 8 | |
| 38 | ||
| 39 | export function buildIgnoreMatcher (rootDir, extraPatterns = []) { | |
| 40 | const root = resolve(rootDir) | |
| 41 | ||
| 42 | // Collect patterns from all sources | |
| 43 | const patterns = [...BUILTIN_PATTERNS] | |
| 44 | ||
| 45 | const ignoreFile = join(root, IGNORE_FILE) | |
| 46 | if (existsSync(ignoreFile)) { | |
| 47 | try { | |
| 48 | const content = readFileSync(ignoreFile, 'utf-8') | |
| 49 | for (const line of content.split('\n')) { | |
| 50 | const trimmed = line.trim() | |
| 51 | if (!trimmed || trimmed.startsWith('#')) continue | |
| 52 | patterns.push(trimmed) | |
| 53 | } | |
| 54 | } catch {} | |
| 55 | } | |
| 56 | ||
| 57 | for (const p of extraPatterns) { | |
| 58 | if (p && !p.startsWith('#')) patterns.push(p.trim()) | |
| 59 | } | |
| 60 | ||
| 61 | const compiled = patterns.map(p => compilePattern(p, root)).filter(Boolean) | |
| 62 | ||
| 63 | // Pre-scan for .codetree-private markers — any dir containing this file becomes a | |
| 64 | // full-subtree exclusion prefix. | |
| 65 | const privatePrefixes = findPrivateMarkers(root) | |
| 66 | ||
| 67 | return function ignore (absPath) { | |
| 68 | // Exclude anything under a privately-marked directory | |
| 69 | for (const prefix of privatePrefixes) { | |
| 70 | if (absPath === prefix || absPath.startsWith(prefix + '/')) return true | |
| 71 | } | |
| 72 | ||
| 73 | // Check each compiled pattern | |
| 74 | const rel = relative(root, absPath) | |
| 75 | if (rel === '' || rel.startsWith('..')) return false // outside the scan root | |
| 76 | const name = basename(absPath) | |
| 77 | ||
| 78 | for (const c of compiled) { | |
| 79 | if (c.test(rel, name)) return true | |
| 80 | } | |
| 81 | ||
| 82 | return false | |
| 83 | } | |
| 84 | } | |
| 85 | ||
| 86 | // --- Pattern compilation --- | |
| 87 | // | |
| 88 | // Supports a practical subset of gitignore: | |
| 89 | // name → matches a dir/file named "name" at ANY depth | |
| 90 | // name/ → matches a DIR named "name" at any depth | |
| 91 | // /name → matches a dir/file named "name" only at rootDir | |
| 92 | // path/to/name → matches at that exact relative path (anchored to rootDir) | |
| 93 | // name*.ext → simple glob: * in name segment matches anything except / | |
| 94 | // # comment → skipped by caller | |
| 95 | // (negation !foo → not yet supported in v1) | |
| 96 | ||
| 97 | function compilePattern (rawPattern, root) { | |
| 98 | let pattern = rawPattern.trim() | |
| 99 | if (!pattern) return null | |
| 100 | if (pattern.startsWith('!')) return null // v1: no negation | |
| 101 | if (pattern.startsWith('#')) return null | |
| 102 | ||
| 103 | const dirOnly = pattern.endsWith('/') | |
| 104 | if (dirOnly) pattern = pattern.slice(0, -1) | |
| 105 | ||
| 106 | const anchored = pattern.startsWith('/') | |
| 107 | if (anchored) pattern = pattern.slice(1) | |
| 108 | ||
| 109 | // No slash (and not anchored) → name-only pattern, matches at any depth | |
| 110 | const nameOnly = !anchored && !pattern.includes('/') | |
| 111 | ||
| 112 | const regex = globToRegex(pattern) | |
| 113 | ||
| 114 | return { | |
| 115 | raw: rawPattern, | |
| 116 | dirOnly, | |
| 117 | test (relPath, name) { | |
| 118 | // For a dirOnly pattern we can't reliably tell from the relPath whether the | |
| 119 | // target is a directory; callers that know should pass the dirOnly check. | |
| 120 | // In practice dirOnly is mostly a documentation hint here; real behavior is | |
| 121 | // that dir exclusion propagates via prefix matching below. | |
| 122 | ||
| 123 | if (nameOnly) { | |
| 124 | // Match if ANY segment of relPath equals the pattern | |
| 125 | const segments = relPath.split('/') | |
| 126 | for (const seg of segments) { | |
| 127 | if (regex.test(seg)) return true | |
| 128 | } | |
| 129 | return false | |
| 130 | } | |
| 131 | ||
| 132 | if (anchored) { | |
| 133 | // Exact match against relPath, or prefix match if target is under this path | |
| 134 | if (regex.test(relPath)) return true | |
| 135 | if (relPath.startsWith(pattern + '/')) return true | |
| 136 | return false | |
| 137 | } | |
| 138 | ||
| 139 | // Path with slash but not anchored → match against any suffix of relPath | |
| 140 | if (regex.test(relPath)) return true | |
| 141 | const segs = relPath.split('/') | |
| 142 | for (let i = 1; i < segs.length; i++) { | |
| 143 | const suffix = segs.slice(i).join('/') | |
| 144 | if (regex.test(suffix)) return true | |
| 145 | } | |
| 146 | return false | |
| 147 | } | |
| 148 | } | |
| 149 | } | |
| 150 | ||
| 151 | function globToRegex (pattern) { | |
| 152 | // Escape regex specials, then re-enable * as wildcard (not crossing /) | |
| 153 | let re = '' | |
| 154 | for (const ch of pattern) { | |
| 155 | if (ch === '*') re += '[^/]*' | |
| 156 | else if (ch === '?') re += '[^/]' | |
| 157 | else if ('.+^$(){}|\\[]'.includes(ch)) re += '\\' + ch | |
| 158 | else re += ch | |
| 159 | } | |
| 160 | return new RegExp('^' + re + '$') | |
| 161 | } | |
| 162 | ||
| 163 | // --- .codetree-private discovery --- | |
| 164 | ||
| 165 | function findPrivateMarkers (root) { | |
| 166 | const prefixes = [] | |
| 167 | scan(root, 0) | |
| 168 | return prefixes | |
| 169 | ||
| 170 | function scan (dir, depth) { | |
| 171 | if (depth > PRIVATE_SCAN_MAX_DEPTH) return | |
| 172 | let entries | |
| 173 | try { entries = readdirSync(dir) } catch { return } | |
| 174 | ||
| 175 | // Check this dir first | |
| 176 | if (entries.includes(PRIVATE_MARKER)) { | |
| 177 | prefixes.push(dir) | |
| 178 | return // don't recurse into a private dir — the whole subtree is excluded | |
| 179 | } | |
| 180 | ||
| 181 | // Quick built-in prune before recursing (avoids descending into node_modules etc.) | |
| 182 | for (const entry of entries) { | |
| 183 | if (BUILTIN_PATTERNS.includes(entry)) continue | |
| 184 | if (entry.startsWith('.')) continue | |
| 185 | const full = join(dir, entry) | |
| 186 | let stat | |
| 187 | try { stat = lstatSync(full) } catch { continue } | |
| 188 | if (!stat.isDirectory() || stat.isSymbolicLink()) continue | |
| 189 | scan(full, depth + 1) | |
| 190 | } | |
| 191 | } | |
| 192 | } |
| … | … | @@ -0,0 +1,591 @@ |
| 1 | import { existsSync, readdirSync, statSync, readFileSync } from 'fs' | |
| 2 | import { join, dirname, resolve, extname, relative } from 'path' | |
| 3 | ||
| 4 | import { parseFile as parseJS } from './parsers/js.js' | |
| 5 | import { parseFile as parseGDScript } from './parsers/gdscript.js' | |
| 6 | import { parseFile as parseCpp } from './parsers/cpp.js' | |
| 7 | import { parseFile as parseGLSL } from './parsers/glsl.js' | |
| 8 | ||
| 9 | /** | |
| 10 | * Language registry. | |
| 11 | * | |
| 12 | * The single source of truth for all language-specific behavior. | |
| 13 | * Replaces hardcoded assumptions that were previously scattered across | |
| 14 | * traverse.js and tree.js. | |
| 15 | * | |
| 16 | * Adding a new language = add one descriptor to LANGUAGES below. | |
| 17 | */ | |
| 18 | ||
| 19 | // --- JS language descriptor --- | |
| 20 | ||
| 21 | const JS = { | |
| 22 | id: 'js', | |
| 23 | extensions: ['.js', '.mjs', '.cjs'], | |
| 24 | projectMarkers: ['package.json'], | |
| 25 | submoduleMarkers: ['package.json'], | |
| 26 | defaultEntries: ['index.js', 'index.mjs'], | |
| 27 | ||
| 28 | parse: parseJS, | |
| 29 | ||
| 30 | extractImports (source) { | |
| 31 | const specs = [] | |
| 32 | ||
| 33 | // ESM: import ... from 'specifier' | |
| 34 | const esmPattern = /(?:import|export)\s+.*?\s+from\s+['"]([^'"]+)['"]/g | |
| 35 | let match | |
| 36 | while ((match = esmPattern.exec(source)) !== null) specs.push(match[1]) | |
| 37 | ||
| 38 | // ESM: import 'specifier' (side-effect) | |
| 39 | const sideEffect = /import\s+['"]([^'"]+)['"]/g | |
| 40 | while ((match = sideEffect.exec(source)) !== null) { | |
| 41 | if (!specs.includes(match[1])) specs.push(match[1]) | |
| 42 | } | |
| 43 | ||
| 44 | // CJS: require('specifier') | |
| 45 | const cjsPattern = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g | |
| 46 | while ((match = cjsPattern.exec(source)) !== null) { | |
| 47 | if (!specs.includes(match[1])) specs.push(match[1]) | |
| 48 | } | |
| 49 | ||
| 50 | return specs | |
| 51 | }, | |
| 52 | ||
| 53 | // Resolve a relative import to an absolute file path (or null). | |
| 54 | // For JS, only relative imports participate in the local graph. | |
| 55 | resolveImport (fromFile, specifier /* ctx unused for JS */) { | |
| 56 | if (!specifier.startsWith('.')) return null | |
| 57 | ||
| 58 | const dir = dirname(fromFile) | |
| 59 | const target = resolve(dir, specifier) | |
| 60 | ||
| 61 | // Exact file | |
| 62 | if (existsSync(target) && statSync(target).isFile()) return target | |
| 63 | ||
| 64 | // Try extensions | |
| 65 | for (const ext of ['.js', '.mjs', '.cjs', '.json']) { | |
| 66 | const withExt = target + ext | |
| 67 | if (existsSync(withExt) && statSync(withExt).isFile()) return withExt | |
| 68 | } | |
| 69 | ||
| 70 | // Try index.js in directory | |
| 71 | if (existsSync(target) && statSync(target).isDirectory()) { | |
| 72 | const idx = join(target, 'index.js') | |
| 73 | if (existsSync(idx)) return idx | |
| 74 | } | |
| 75 | ||
| 76 | return null | |
| 77 | } | |
| 78 | } | |
| 79 | ||
| 80 | // --- GDScript language descriptor --- | |
| 81 | ||
| 82 | const GDScript = { | |
| 83 | id: 'gdscript', | |
| 84 | extensions: ['.gd'], | |
| 85 | projectMarkers: ['project.godot'], | |
| 86 | submoduleMarkers: ['plugin.cfg', 'project.godot'], | |
| 87 | defaultEntries: [], // Godot projects have no single entry point | |
| 88 | ||
| 89 | parse: parseGDScript, | |
| 90 | ||
| 91 | extractImports (source) { | |
| 92 | // preload("res://path") or preload('res://path') | |
| 93 | const specs = [] | |
| 94 | const preloadPattern = /preload\s*\(\s*['"]([^'"]+)['"]\s*\)/g | |
| 95 | let match | |
| 96 | while ((match = preloadPattern.exec(source)) !== null) { | |
| 97 | specs.push(match[1]) | |
| 98 | } | |
| 99 | // load("res://path") — runtime load, still a real dependency | |
| 100 | const loadPattern = /\bload\s*\(\s*['"]([^'"]+)['"]\s*\)/g | |
| 101 | while ((match = loadPattern.exec(source)) !== null) { | |
| 102 | if (!specs.includes(match[1])) specs.push(match[1]) | |
| 103 | } | |
| 104 | return specs | |
| 105 | }, | |
| 106 | ||
| 107 | // Resolve a GDScript import. | |
| 108 | // - class_name: specifiers map through the registry to an absolute path | |
| 109 | // - res:// paths resolve to projectRoot + path | |
| 110 | // - relative paths resolve from the including file's directory | |
| 111 | resolveImport (fromFile, specifier, ctx) { | |
| 112 | // Implicit class_name references — look up in the registry | |
| 113 | if (specifier.startsWith('class_name:')) { | |
| 114 | const className = specifier.slice('class_name:'.length) | |
| 115 | const regPath = ctx && ctx.classNameRegistry && ctx.classNameRegistry[className] | |
| 116 | if (regPath) { | |
| 117 | const full = resolve(ctx.rootDir, regPath) | |
| 118 | if (existsSync(full) && statSync(full).isFile()) return full | |
| 119 | } | |
| 120 | return null | |
| 121 | } | |
| 122 | ||
| 123 | if (specifier.startsWith('res://')) { | |
| 124 | const rest = specifier.slice('res://'.length) | |
| 125 | const root = (ctx && ctx.rootDir) || dirname(fromFile) | |
| 126 | const full = resolve(root, rest) | |
| 127 | if (existsSync(full) && statSync(full).isFile()) return full | |
| 128 | return null | |
| 129 | } | |
| 130 | ||
| 131 | if (specifier.startsWith('.') || !specifier.includes('://')) { | |
| 132 | const dir = dirname(fromFile) | |
| 133 | const target = resolve(dir, specifier) | |
| 134 | if (existsSync(target) && statSync(target).isFile()) return target | |
| 135 | } | |
| 136 | ||
| 137 | return null | |
| 138 | }, | |
| 139 | ||
| 140 | // GDScript-specific: find implicit class_name references in the source. | |
| 141 | // Returns an array of synthetic `class_name:X` specifiers for class names | |
| 142 | // that exist in the project's registry. Called after extractImports(). | |
| 143 | extractImplicitImports (source, ctx) { | |
| 144 | if (!ctx || !ctx.classNameRegistry) return [] | |
| 145 | const registry = ctx.classNameRegistry | |
| 146 | const found = new Set() | |
| 147 | ||
| 148 | // Patterns that reveal a type reference to a global class_name: | |
| 149 | // extends ClassName | |
| 150 | // var x: ClassName / const x: ClassName | |
| 151 | // : ClassName = / -> ClassName : (function return type) | |
| 152 | // ClassName.new() | |
| 153 | // ClassName.STATIC_MEMBER | |
| 154 | // func f(arg: ClassName, ...) | |
| 155 | // | |
| 156 | // Capture any identifier that starts with a capital letter after the relevant | |
| 157 | // keyword or punctuation, then filter by the registry. | |
| 158 | const patterns = [ | |
| 159 | /\bextends\s+([A-Z][\w]*)\b/g, | |
| 160 | /:\s*([A-Z][\w]*)(?:\s*[=,)\]}\n])/g, | |
| 161 | /->\s*([A-Z][\w]*)\s*:/g, | |
| 162 | /\b([A-Z][\w]*)\s*\.\s*new\s*\(/g | |
| 163 | ] | |
| 164 | ||
| 165 | for (const p of patterns) { | |
| 166 | let m | |
| 167 | while ((m = p.exec(source)) !== null) { | |
| 168 | const name = m[1] | |
| 169 | if (registry[name]) found.add(name) | |
| 170 | } | |
| 171 | } | |
| 172 | ||
| 173 | return [...found].map(name => 'class_name:' + name) | |
| 174 | } | |
| 175 | } | |
| 176 | ||
| 177 | // --- C++ language descriptor --- | |
| 178 | ||
| 179 | const Cpp = { | |
| 180 | id: 'cpp', | |
| 181 | extensions: ['.cpp', '.cc', '.cxx', '.c', '.h', '.hpp', '.hh', '.hxx'], | |
| 182 | projectMarkers: ['SConstruct', 'CMakeLists.txt'], | |
| 183 | submoduleMarkers: ['SConstruct', 'CMakeLists.txt'], | |
| 184 | defaultEntries: [], | |
| 185 | ||
| 186 | parse: parseCpp, | |
| 187 | ||
| 188 | extractImports (source) { | |
| 189 | // #include "local.h" — quoted only. System <...> includes are skipped. | |
| 190 | const specs = [] | |
| 191 | const pattern = /^\s*#\s*include\s+"([^"]+)"/gm | |
| 192 | let match | |
| 193 | while ((match = pattern.exec(source)) !== null) { | |
| 194 | specs.push(match[1]) | |
| 195 | } | |
| 196 | return specs | |
| 197 | }, | |
| 198 | ||
| 199 | resolveImport (fromFile, specifier, ctx) { | |
| 200 | // Try relative to the including file's directory first | |
| 201 | const fromDir = dirname(fromFile) | |
| 202 | const relTarget = resolve(fromDir, specifier) | |
| 203 | if (existsSync(relTarget) && statSync(relTarget).isFile()) return relTarget | |
| 204 | ||
| 205 | // Then try the pre-built header map (convention-based include paths) | |
| 206 | if (ctx && ctx.headerMap) { | |
| 207 | if (specifier.includes('/')) { | |
| 208 | // path-qualified specifier: try each include root + specifier | |
| 209 | for (const root of ctx.includeRoots || []) { | |
| 210 | const full = resolve(root, specifier) | |
| 211 | if (existsSync(full) && statSync(full).isFile()) return full | |
| 212 | } | |
| 213 | } else { | |
| 214 | // bare filename: direct lookup in header map | |
| 215 | const abs = ctx.headerMap[specifier] | |
| 216 | if (abs && existsSync(abs) && statSync(abs).isFile()) return abs | |
| 217 | } | |
| 218 | } | |
| 219 | ||
| 220 | return null | |
| 221 | } | |
| 222 | } | |
| 223 | ||
| 224 | // --- GLSL language descriptor --- | |
| 225 | // GLSL shaders have no project structure of their own — they piggyback on whatever | |
| 226 | // project contains them (Godot .gdshader or C++ GDExtension .glsl). No projectMarkers. | |
| 227 | ||
| 228 | const GLSL = { | |
| 229 | id: 'glsl', | |
| 230 | extensions: ['.glsl', '.gdshader', '.vert', '.frag', '.comp'], | |
| 231 | projectMarkers: [], // shaders never define a project alone | |
| 232 | submoduleMarkers: [], | |
| 233 | defaultEntries: [], | |
| 234 | ||
| 235 | parse: parseGLSL, | |
| 236 | ||
| 237 | extractImports (source) { | |
| 238 | // #include is uncommon but possible (Godot gdshader, some glsl preprocessors) | |
| 239 | const specs = [] | |
| 240 | const pattern = /^\s*#\s*include\s+["<]([^">]+)[">]/gm | |
| 241 | let match | |
| 242 | while ((match = pattern.exec(source)) !== null) { | |
| 243 | specs.push(match[1]) | |
| 244 | } | |
| 245 | return specs | |
| 246 | }, | |
| 247 | ||
| 248 | resolveImport (fromFile, specifier) { | |
| 249 | if (specifier.startsWith('.') || !specifier.includes('://')) { | |
| 250 | const target = resolve(dirname(fromFile), specifier) | |
| 251 | if (existsSync(target) && statSync(target).isFile()) return target | |
| 252 | } | |
| 253 | return null | |
| 254 | } | |
| 255 | } | |
| 256 | ||
| 257 | // --- Language registry --- | |
| 258 | // Order matters for detectProject(): most-specific markers first. | |
| 259 | // project.godot, SConstruct and CMakeLists.txt are more distinctive than package.json — | |
| 260 | // a Godot or GDExtension project may also have package.json (for dev tools) and we want | |
| 261 | // to classify it by its primary nature. | |
| 262 | ||
| 263 | const LANGUAGES = [GDScript, Cpp, JS, GLSL] | |
| 264 | ||
| 265 | const EXT_TO_LANG = (() => { | |
| 266 | const map = new Map() | |
| 267 | for (const lang of LANGUAGES) { | |
| 268 | for (const ext of lang.extensions) map.set(ext, lang) | |
| 269 | } | |
| 270 | return map | |
| 271 | })() | |
| 272 | ||
| 273 | // --- Public API --- | |
| 274 | ||
| 275 | /** | |
| 276 | * Map a file path to its language descriptor, or null if no registered language claims it. | |
| 277 | */ | |
| 278 | export function getLang (filePath) { | |
| 279 | const ext = extname(filePath) | |
| 280 | return EXT_TO_LANG.get(ext) || null | |
| 281 | } | |
| 282 | ||
| 283 | /** | |
| 284 | * True if any registered language claims this file's extension. | |
| 285 | * Replaces hardcoded .js/.mjs/.cjs checks. | |
| 286 | */ | |
| 287 | export function isSourceFile (filePath) { | |
| 288 | return EXT_TO_LANG.has(extname(filePath)) | |
| 289 | } | |
| 290 | ||
| 291 | /** | |
| 292 | * Detect what type of project lives at rootDir by scanning for marker files. | |
| 293 | * Returns { type, languages: [langId,...] } — the primary project type plus | |
| 294 | * any other languages whose files are present. | |
| 295 | */ | |
| 296 | export function detectProject (rootDir) { | |
| 297 | const markers = [] | |
| 298 | ||
| 299 | for (const lang of LANGUAGES) { | |
| 300 | for (const marker of lang.projectMarkers || []) { | |
| 301 | if (existsSync(join(rootDir, marker))) { | |
| 302 | markers.push({ type: lang.id, marker }) | |
| 303 | } | |
| 304 | } | |
| 305 | } | |
| 306 | ||
| 307 | // Primary type: first marker found. | |
| 308 | const primary = markers[0] || { type: 'unknown', marker: null } | |
| 309 | ||
| 310 | return { | |
| 311 | type: primary.type, | |
| 312 | marker: primary.marker, | |
| 313 | languages: [...new Set(markers.map(m => m.type))] | |
| 314 | } | |
| 315 | } | |
| 316 | ||
| 317 | /** | |
| 318 | * Find module boundaries within a project. | |
| 319 | * | |
| 320 | * For JS projects this means: directories containing package.json. | |
| 321 | * Other languages will plug in their own boundary detection. | |
| 322 | * | |
| 323 | * Returns: array of directory paths (absolute) representing module roots. | |
| 324 | */ | |
| 325 | export function findModuleBoundaries (rootDir, projectType, opts = {}) { | |
| 326 | const maxDepth = opts.maxDepth || 2 | |
| 327 | const ignore = opts.ignore || (() => false) | |
| 328 | const roots = [] | |
| 329 | ||
| 330 | let markers | |
| 331 | const lang = LANGUAGES.find(l => l.id === projectType) | |
| 332 | if (lang) { | |
| 333 | markers = lang.submoduleMarkers || lang.projectMarkers || [] | |
| 334 | } else { | |
| 335 | // Unknown root (e.g. a parent directory of several projects). Scan for | |
| 336 | // any registered project marker — this makes codetree useful for monorepos | |
| 337 | // that aren't themselves a single project. | |
| 338 | markers = [] | |
| 339 | for (const l of LANGUAGES) { | |
| 340 | for (const m of l.projectMarkers || []) markers.push(m) | |
| 341 | } | |
| 342 | } | |
| 343 | ||
| 344 | if (markers.length === 0) return [rootDir] | |
| 345 | ||
| 346 | // Root is always a module if it has any marker | |
| 347 | if (markers.some(m => existsSync(join(rootDir, m)))) { | |
| 348 | roots.push(rootDir) | |
| 349 | } | |
| 350 | ||
| 351 | scanForModuleMarkers(rootDir, markers, roots, 0, maxDepth, ignore) | |
| 352 | return roots | |
| 353 | } | |
| 354 | ||
| 355 | function scanForModuleMarkers (dir, markers, roots, depth, maxDepth, ignore) { | |
| 356 | if (depth >= maxDepth) return | |
| 357 | ||
| 358 | let entries | |
| 359 | try { entries = readdirSync(dir) } catch { return } | |
| 360 | ||
| 361 | for (const entry of entries) { | |
| 362 | // test/ directories aren't module roots — they're tests inside a module. | |
| 363 | // Other skips come from the ignore matcher. | |
| 364 | if (entry === 'test') continue | |
| 365 | const full = join(dir, entry) | |
| 366 | if (ignore(full)) continue | |
| 367 | ||
| 368 | let stat | |
| 369 | try { stat = statSync(full) } catch { continue } | |
| 370 | if (!stat.isDirectory()) continue | |
| 371 | ||
| 372 | if (markers.some(m => existsSync(join(full, m)))) { | |
| 373 | roots.push(full) | |
| 374 | } | |
| 375 | ||
| 376 | scanForModuleMarkers(full, markers, roots, depth + 1, maxDepth, ignore) | |
| 377 | } | |
| 378 | } | |
| 379 | ||
| 380 | /** | |
| 381 | * Build a resolution context for a project. | |
| 382 | * | |
| 383 | * This is a language-specific data structure needed for import resolution. | |
| 384 | * For JS: import maps (from package.json) — currently not populated here because | |
| 385 | * JS resolution uses only relative paths. | |
| 386 | * For GDScript (future): class_name registry. | |
| 387 | * For C++ (future): header name → absolute path map. | |
| 388 | */ | |
| 389 | export function buildResolutionContext (rootDir, projectType, ignore, opts = {}) { | |
| 390 | const ig = ignore || (() => false) | |
| 391 | const ctx = { projectType, rootDir, ignore: ig, shallow: !!opts.shallow } | |
| 392 | ||
| 393 | // Shallow scans don't resolve internal imports — skip the expensive project-wide | |
| 394 | // pre-scans (class_name registry, C++ header map). These are the single biggest | |
| 395 | // cost in buildResolutionContext for large projects. | |
| 396 | if (opts.shallow) return ctx | |
| 397 | ||
| 398 | if (projectType === 'gdscript') { | |
| 399 | // Scan every .gd file in the project for `class_name X` declarations. | |
| 400 | // This builds the global class registry that GDScript uses for implicit imports | |
| 401 | // (type references like `extends Foo` or `var x: Foo` don't need an explicit preload | |
| 402 | // when Foo is a class_name somewhere else in the project). | |
| 403 | ctx.classNameRegistry = buildGDScriptClassNameRegistry(rootDir, ig) | |
| 404 | } | |
| 405 | ||
| 406 | if (projectType === 'cpp') { | |
| 407 | // Build header-name → absolute-path map by scanning conventional include roots. | |
| 408 | // This is a convention-based alternative to parsing SConstruct/CMakeLists.txt for CPPPATH. | |
| 409 | const { headerMap, includeRoots } = buildCppHeaderMap(rootDir, ig) | |
| 410 | ctx.headerMap = headerMap | |
| 411 | ctx.includeRoots = includeRoots | |
| 412 | } | |
| 413 | ||
| 414 | return ctx | |
| 415 | } | |
| 416 | ||
| 417 | // --- C++ header map --- | |
| 418 | ||
| 419 | function buildCppHeaderMap (rootDir, ignore) { | |
| 420 | const headerMap = {} | |
| 421 | const includeRoots = [] | |
| 422 | ||
| 423 | // Always consider the root itself | |
| 424 | includeRoots.push(rootDir) | |
| 425 | ||
| 426 | // Find conventional include roots | |
| 427 | scanForIncludeRoots(rootDir, rootDir, includeRoots, 0, 3, ignore) | |
| 428 | ||
| 429 | // Walk each include root and build the header map | |
| 430 | for (const root of includeRoots) { | |
| 431 | scanForHeaders(root, root, headerMap, 0, 6, ignore) | |
| 432 | } | |
| 433 | ||
| 434 | return { headerMap, includeRoots } | |
| 435 | } | |
| 436 | ||
| 437 | function scanForIncludeRoots (dir, rootDir, roots, depth, maxDepth, ignore) { | |
| 438 | if (depth >= maxDepth) return | |
| 439 | ||
| 440 | let entries | |
| 441 | try { entries = readdirSync(dir) } catch { return } | |
| 442 | ||
| 443 | for (const entry of entries) { | |
| 444 | if (entry.startsWith('.')) continue | |
| 445 | const full = join(dir, entry) | |
| 446 | if (ignore(full)) continue | |
| 447 | ||
| 448 | let stat | |
| 449 | try { stat = statSync(full) } catch { continue } | |
| 450 | if (!stat.isDirectory()) continue | |
| 451 | ||
| 452 | // Standard C++ include conventions | |
| 453 | if (entry === 'include' || entry === 'src' || entry === 'thirdparty') { | |
| 454 | roots.push(full) | |
| 455 | // Also look for <lib>/include patterns inside these | |
| 456 | const subInclude = join(full, 'include') | |
| 457 | try { | |
| 458 | if (existsSync(subInclude) && statSync(subInclude).isDirectory()) { | |
| 459 | roots.push(subInclude) | |
| 460 | } | |
| 461 | } catch {} | |
| 462 | } | |
| 463 | ||
| 464 | // Recurse into thirdparty/{lib}/include patterns | |
| 465 | if (depth < maxDepth - 1) { | |
| 466 | scanForIncludeRoots(full, rootDir, roots, depth + 1, maxDepth, ignore) | |
| 467 | } | |
| 468 | } | |
| 469 | } | |
| 470 | ||
| 471 | const HEADER_EXTS = new Set(['.h', '.hpp', '.hh', '.hxx']) | |
| 472 | ||
| 473 | function scanForHeaders (dir, root, headerMap, depth, maxDepth, ignore) { | |
| 474 | if (depth >= maxDepth) return | |
| 475 | ||
| 476 | let entries | |
| 477 | try { entries = readdirSync(dir) } catch { return } | |
| 478 | ||
| 479 | for (const entry of entries) { | |
| 480 | if (entry.startsWith('.')) continue | |
| 481 | const full = join(dir, entry) | |
| 482 | if (ignore(full)) continue | |
| 483 | ||
| 484 | let stat | |
| 485 | try { stat = statSync(full) } catch { continue } | |
| 486 | ||
| 487 | if (stat.isDirectory()) { | |
| 488 | scanForHeaders(full, root, headerMap, depth + 1, maxDepth, ignore) | |
| 489 | } else { | |
| 490 | const ext = extname(entry) | |
| 491 | if (HEADER_EXTS.has(ext)) { | |
| 492 | // Bare filename is the key; if collision, prefer first found (innermost include root wins) | |
| 493 | if (!headerMap[entry]) headerMap[entry] = full | |
| 494 | } | |
| 495 | } | |
| 496 | } | |
| 497 | } | |
| 498 | ||
| 499 | function buildGDScriptClassNameRegistry (rootDir, ignore) { | |
| 500 | const registry = {} | |
| 501 | scanForGDClassNames(rootDir, rootDir, registry, 0, 10, ignore) | |
| 502 | return registry | |
| 503 | } | |
| 504 | ||
| 505 | function scanForGDClassNames (dir, rootDir, registry, depth, maxDepth, ignore) { | |
| 506 | if (depth >= maxDepth) return | |
| 507 | ||
| 508 | let entries | |
| 509 | try { entries = readdirSync(dir) } catch { return } | |
| 510 | ||
| 511 | for (const entry of entries) { | |
| 512 | if (entry.startsWith('.')) continue | |
| 513 | const full = join(dir, entry) | |
| 514 | if (ignore(full)) continue | |
| 515 | ||
| 516 | let stat | |
| 517 | try { stat = statSync(full) } catch { continue } | |
| 518 | ||
| 519 | if (stat.isDirectory()) { | |
| 520 | scanForGDClassNames(full, rootDir, registry, depth + 1, maxDepth, ignore) | |
| 521 | } else if (entry.endsWith('.gd')) { | |
| 522 | // Only read the first ~500 bytes — class_name must be at the top per GDScript convention | |
| 523 | try { | |
| 524 | const fd = readFileSync(full, 'utf-8') | |
| 525 | const head = fd.slice(0, 500) | |
| 526 | const match = head.match(/^\s*class_name\s+([A-Za-z_][\w]*)/m) | |
| 527 | if (match) { | |
| 528 | registry[match[1]] = relative(rootDir, full) | |
| 529 | } | |
| 530 | } catch {} | |
| 531 | } | |
| 532 | } | |
| 533 | } | |
| 534 | ||
| 535 | /** | |
| 536 | * Read a project's metadata file (language-appropriate). | |
| 537 | * For JS: package.json. For Godot: project.godot. For C++: SConstruct (skipped). | |
| 538 | */ | |
| 539 | export function readProjectMeta (dir, projectType) { | |
| 540 | if (projectType === 'js') { | |
| 541 | const pkgPath = join(dir, 'package.json') | |
| 542 | try { return JSON.parse(readFileSync(pkgPath, 'utf-8')) } | |
| 543 | catch { return null } | |
| 544 | } | |
| 545 | return null | |
| 546 | } | |
| 547 | ||
| 548 | /** | |
| 549 | * Resolve a project's entry point (language-appropriate). | |
| 550 | */ | |
| 551 | export function resolveEntry (pkgDir, meta, projectType) { | |
| 552 | const lang = LANGUAGES.find(l => l.id === projectType) | |
| 553 | if (!lang) return null | |
| 554 | ||
| 555 | if (projectType === 'js' && meta) { | |
| 556 | // exports field first | |
| 557 | if (meta.exports) { | |
| 558 | const entry = resolveJSExportsEntry(meta.exports) | |
| 559 | if (entry) { | |
| 560 | const full = resolve(pkgDir, entry) | |
| 561 | if (existsSync(full)) return full | |
| 562 | } | |
| 563 | } | |
| 564 | // main field | |
| 565 | if (meta.main) { | |
| 566 | const full = resolve(pkgDir, meta.main) | |
| 567 | if (existsSync(full)) return full | |
| 568 | } | |
| 569 | } | |
| 570 | ||
| 571 | // Fall back to language default entry names | |
| 572 | for (const name of lang.defaultEntries || []) { | |
| 573 | const full = resolve(pkgDir, name) | |
| 574 | if (existsSync(full)) return full | |
| 575 | } | |
| 576 | ||
| 577 | return null | |
| 578 | } | |
| 579 | ||
| 580 | function resolveJSExportsEntry (exports) { | |
| 581 | if (typeof exports === 'string') return exports | |
| 582 | if (typeof exports === 'object' && exports !== null) { | |
| 583 | const dot = exports['.'] | |
| 584 | if (!dot) return null | |
| 585 | if (typeof dot === 'string') return dot | |
| 586 | if (typeof dot === 'object') { | |
| 587 | return dot.bare || dot.import || dot.require || dot.default || null | |
| 588 | } | |
| 589 | } | |
| 590 | return null | |
| 591 | } |
| … | … | @@ -0,0 +1,220 @@ |
| 1 | import { EventEmitter } from 'events' | |
| 2 | import { readFileSync } from 'fs' | |
| 3 | import { relative } from 'path' | |
| 4 | import { FsWatcher } from './fs-watcher.js' | |
| 5 | import { getLang, isSourceFile } from './lang.js' | |
| 6 | ||
| 7 | /** | |
| 8 | * LiveStore — holds the current tree + broadcasts deltas. | |
| 9 | * | |
| 10 | * Built on the push model: file changes come in as fs.watch events, get | |
| 11 | * re-parsed, and emit new file-parsed events into a live event stream. All | |
| 12 | * connected clients (SSE consumers) receive the delta. | |
| 13 | * | |
| 14 | * Initial state replay: a newly-connected client receives the events that | |
| 15 | * would rebuild the current tree — no full JSON dump needed. | |
| 16 | * | |
| 17 | * The store does NOT own the tree directly. It holds the graph produced by | |
| 18 | * the initial scan and replays events to new subscribers. Incremental updates | |
| 19 | * from the watcher amend the graph in place and emit the corresponding events. | |
| 20 | */ | |
| 21 | export class LiveStore extends EventEmitter { | |
| 22 | constructor (graph, opts = {}) { | |
| 23 | super() | |
| 24 | this.graph = graph | |
| 25 | this.rootDir = graph.root | |
| 26 | this.resolutionContext = graph.resolutionContext || { ignore: () => false, projectType: graph.projectType } | |
| 27 | this.ignore = this.resolutionContext.ignore | |
| 28 | this._watcher = null | |
| 29 | this._history = [] // append-only log of live events for replay | |
| 30 | this._enabledWatcher = opts.watch !== false | |
| 31 | } | |
| 32 | ||
| 33 | start () { | |
| 34 | if (!this._enabledWatcher) return | |
| 35 | this._watcher = new FsWatcher(this.rootDir, this.ignore) | |
| 36 | this._watcher.on('change', e => this._onChange(e)) | |
| 37 | this._watcher.on('remove', e => this._onRemove(e)) | |
| 38 | // Watcher failures (ENOSPC, EMFILE, EACCES) are recoverable — the snapshot | |
| 39 | // is still served, just no live updates. Log and degrade rather than crash. | |
| 40 | this._watcher.on('error', err => { | |
| 41 | this.watcherError = err | |
| 42 | console.warn('[live-store] fs.watch disabled:', err.code || err.message) | |
| 43 | }) | |
| 44 | } | |
| 45 | ||
| 46 | stop () { | |
| 47 | if (this._watcher) { | |
| 48 | this._watcher.close() | |
| 49 | this._watcher = null | |
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | // --- Subscription --- | |
| 54 | ||
| 55 | /** | |
| 56 | * Attach a subscriber. Called with every historic event (to rebuild state), | |
| 57 | * then with every future live event as it fires. | |
| 58 | * | |
| 59 | * Returns an unsubscribe function. | |
| 60 | */ | |
| 61 | subscribe (handler) { | |
| 62 | // Replay history (snapshot of the current state as events) | |
| 63 | for (const ev of this._history) handler(ev) | |
| 64 | this.on('event', handler) | |
| 65 | return () => this.off('event', handler) | |
| 66 | } | |
| 67 | ||
| 68 | // --- Initial state replay --- | |
| 69 | ||
| 70 | /** | |
| 71 | * Seed the history from the initial graph. Converts the already-built tree | |
| 72 | * back into the event sequence that would reconstruct it. A new subscriber | |
| 73 | * then receives these as their "bootstrap" before live events start. | |
| 74 | */ | |
| 75 | seedFromGraph () { | |
| 76 | const g = this.graph | |
| 77 | this._log({ | |
| 78 | type: 'scan-start', | |
| 79 | root: g.root, | |
| 80 | projectType: g.projectType, | |
| 81 | languages: g.languages, | |
| 82 | shallow: g.shallow || false | |
| 83 | }) | |
| 84 | for (const [name, mod] of g.modules) { | |
| 85 | this._log({ | |
| 86 | type: 'module-start', | |
| 87 | name, | |
| 88 | version: mod.version, | |
| 89 | path: mod.path, | |
| 90 | absPath: mod.absPath, | |
| 91 | entry: mod.entry, | |
| 92 | projectType: mod.projectType, | |
| 93 | dependencies: mod.dependencies, | |
| 94 | devDependencies: mod.devDependencies, | |
| 95 | importMaps: mod.importMaps, | |
| 96 | testCommand: mod.testCommand, | |
| 97 | // mod.type is JS module type ('commonjs'/'module') — avoid the name | |
| 98 | // collision with the SSE event type. | |
| 99 | moduleType: mod.type | |
| 100 | }) | |
| 101 | for (const [relInPkg, fileInfo] of mod.files) { | |
| 102 | this._log({ | |
| 103 | type: 'file-discovered', | |
| 104 | modName: name, | |
| 105 | absPath: fileInfo.absPath, | |
| 106 | relPath: fileInfo.relPath, | |
| 107 | relInPkg, | |
| 108 | size: fileInfo.size || 0 | |
| 109 | }) | |
| 110 | if (fileInfo.parsed) { | |
| 111 | this._log({ | |
| 112 | type: 'file-parsed', | |
| 113 | modName: name, | |
| 114 | relInPkg, | |
| 115 | relPath: fileInfo.relPath, | |
| 116 | parsed: fileInfo.parsed | |
| 117 | }) | |
| 118 | } | |
| 119 | for (const imp of fileInfo.localImports || []) { | |
| 120 | this._log({ | |
| 121 | type: 'import-edge', | |
| 122 | modName: name, | |
| 123 | fromRelInPkg: relInPkg, | |
| 124 | specifier: imp.specifier, | |
| 125 | resolvedRelPath: imp.resolved, | |
| 126 | implicit: !!imp.implicit | |
| 127 | }) | |
| 128 | } | |
| 129 | } | |
| 130 | this._log({ type: 'module-end', name }) | |
| 131 | } | |
| 132 | this._log({ type: 'scan-end', root: g.root }) | |
| 133 | } | |
| 134 | ||
| 135 | _log (ev) { | |
| 136 | this._history.push(ev) | |
| 137 | this.emit('event', ev) | |
| 138 | } | |
| 139 | ||
| 140 | // --- Change handlers --- | |
| 141 | ||
| 142 | _onChange (e) { | |
| 143 | // Which module does this file belong to? Find by absPath prefix. | |
| 144 | const modEntry = this._findModuleForPath(e.absPath) | |
| 145 | if (!modEntry) return // file in a dir we don't track (test output, new repo, etc.) | |
| 146 | ||
| 147 | const [modName, mod] = modEntry | |
| 148 | const relInPkg = relative(mod.absPath, e.absPath) | |
| 149 | ||
| 150 | // Non-source files get a lightweight change event but no re-parse | |
| 151 | if (!isSourceFile(e.absPath)) { | |
| 152 | this._log({ type: 'file-changed', modName, absPath: e.absPath, relPath: e.relPath, relInPkg }) | |
| 153 | return | |
| 154 | } | |
| 155 | ||
| 156 | // Read + parse the file; emit file-parsed so subscribers can update their tree | |
| 157 | let source | |
| 158 | try { source = readFileSync(e.absPath, 'utf-8') } catch { return } | |
| 159 | ||
| 160 | const lang = getLang(e.absPath) | |
| 161 | if (!lang) return | |
| 162 | ||
| 163 | let parsed | |
| 164 | try { parsed = lang.parse(source, relInPkg) } | |
| 165 | catch (err) { parsed = { error: err.message, filePath: relInPkg } } | |
| 166 | ||
| 167 | // Update the in-memory graph for future subscribers / replay | |
| 168 | let fileInfo = mod.files.get(relInPkg) | |
| 169 | const isNew = !fileInfo | |
| 170 | if (isNew) { | |
| 171 | fileInfo = { | |
| 172 | absPath: e.absPath, | |
| 173 | relPath: e.relPath, | |
| 174 | relInPkg, | |
| 175 | size: source.length, | |
| 176 | localImports: [], | |
| 177 | parsed: null | |
| 178 | } | |
| 179 | mod.files.set(relInPkg, fileInfo) | |
| 180 | this.graph.files.set(e.relPath, fileInfo) | |
| 181 | this._log({ | |
| 182 | type: 'file-discovered', | |
| 183 | modName, absPath: e.absPath, relPath: e.relPath, relInPkg, size: source.length | |
| 184 | }) | |
| 185 | } | |
| 186 | fileInfo.parsed = parsed | |
| 187 | fileInfo.size = source.length | |
| 188 | ||
| 189 | this._log({ type: 'file-parsed', modName, relInPkg, relPath: e.relPath, parsed }) | |
| 190 | } | |
| 191 | ||
| 192 | _onRemove (e) { | |
| 193 | const modEntry = this._findModuleForPath(e.absPath) | |
| 194 | if (!modEntry) return | |
| 195 | const [modName, mod] = modEntry | |
| 196 | const relInPkg = relative(mod.absPath, e.absPath) | |
| 197 | ||
| 198 | if (mod.files.has(relInPkg)) { | |
| 199 | mod.files.delete(relInPkg) | |
| 200 | this.graph.files.delete(e.relPath) | |
| 201 | this._log({ type: 'file-removed', modName, relPath: e.relPath, relInPkg }) | |
| 202 | } | |
| 203 | } | |
| 204 | ||
| 205 | _findModuleForPath (absPath) { | |
| 206 | // Linear scan — fine for now. Modules are typically <100. If this grows | |
| 207 | // we can index by prefix. | |
| 208 | let bestEntry = null | |
| 209 | let bestLen = -1 | |
| 210 | for (const [name, mod] of this.graph.modules) { | |
| 211 | if (absPath === mod.absPath || absPath.startsWith(mod.absPath + '/')) { | |
| 212 | if (mod.absPath.length > bestLen) { | |
| 213 | bestEntry = [name, mod] | |
| 214 | bestLen = mod.absPath.length | |
| 215 | } | |
| 216 | } | |
| 217 | } | |
| 218 | return bestEntry | |
| 219 | } | |
| 220 | } |
| … | … | @@ -0,0 +1,461 @@ |
| 1 | import { parser } from '../../vendor/lezer-cpp/lezer-cpp.mjs' | |
| 2 | ||
| 3 | /** | |
| 4 | * C++ parser — walks the Lezer concrete syntax tree to extract: | |
| 5 | * - #include "local.h" → imports (quoted, not <angle-bracket>) | |
| 6 | * - class / struct definitions → classes with methods, inheritance | |
| 7 | * - free functions → functions | |
| 8 | * - namespaces → namespaces array | |
| 9 | * - enums → enums array | |
| 10 | * - typedef / using aliases → constants | |
| 11 | * - #define macros → constants | |
| 12 | */ | |
| 13 | ||
| 14 | export function parseFile (source, filePath) { | |
| 15 | let tree | |
| 16 | try { tree = parser.parse(source) } | |
| 17 | catch (err) { return { error: err.message, filePath } } | |
| 18 | ||
| 19 | const result = { | |
| 20 | filePath, | |
| 21 | imports: [], | |
| 22 | exports: [], | |
| 23 | classes: [], | |
| 24 | functions: [], | |
| 25 | constants: [], | |
| 26 | namespaces: [], | |
| 27 | enums: [] | |
| 28 | } | |
| 29 | ||
| 30 | // Out-of-line definitions (Class::method) may appear before their class; track them | |
| 31 | // and merge into the class if we encounter it. | |
| 32 | const outOfLineMethods = {} // className -> [method,...] | |
| 33 | ||
| 34 | const cursor = tree.cursor() | |
| 35 | if (cursor.firstChild()) { | |
| 36 | do { | |
| 37 | visitTopLevel(cursor, source, result, outOfLineMethods) | |
| 38 | } while (cursor.nextSibling()) | |
| 39 | } | |
| 40 | ||
| 41 | // Attach any out-of-line methods to their classes (class may have been visited earlier) | |
| 42 | for (const cls of result.classes) { | |
| 43 | const extra = outOfLineMethods[cls.name] | |
| 44 | if (extra) { | |
| 45 | for (const m of extra) cls.methods.push(m) | |
| 46 | } | |
| 47 | } | |
| 48 | ||
| 49 | return result | |
| 50 | } | |
| 51 | ||
| 52 | function visitTopLevel (cursor, source, result, outOfLineMethods) { | |
| 53 | switch (cursor.name) { | |
| 54 | case 'PreprocDirective': | |
| 55 | handlePreproc(cursor, source, result) | |
| 56 | return | |
| 57 | ||
| 58 | case 'NamespaceDefinition': | |
| 59 | handleNamespace(cursor, source, result, outOfLineMethods) | |
| 60 | return | |
| 61 | ||
| 62 | case 'ClassSpecifier': | |
| 63 | case 'StructSpecifier': { | |
| 64 | const cls = extractClass(cursor, source, cursor.name === 'StructSpecifier' ? 'struct' : 'class') | |
| 65 | if (cls) { | |
| 66 | result.classes.push(cls) | |
| 67 | result.exports.push({ name: cls.name, type: cls.kind }) | |
| 68 | } | |
| 69 | return | |
| 70 | } | |
| 71 | ||
| 72 | case 'FunctionDefinition': | |
| 73 | handleFunctionDefinition(cursor, source, result, outOfLineMethods) | |
| 74 | return | |
| 75 | ||
| 76 | case 'EnumSpecifier': | |
| 77 | handleEnum(cursor, source, result) | |
| 78 | return | |
| 79 | ||
| 80 | case 'TypeDefinition': | |
| 81 | case 'AliasDeclaration': { | |
| 82 | const name = findTypeIdentifier(cursor, source) | |
| 83 | if (name) result.constants.push({ name, kind: 'typedef' }) | |
| 84 | return | |
| 85 | } | |
| 86 | ||
| 87 | case 'Declaration': | |
| 88 | // GDCLASS(Name, Base); lives here. We can ignore most declarations but | |
| 89 | // preserve top-level function declarations. | |
| 90 | handleDeclaration(cursor, source, result) | |
| 91 | return | |
| 92 | } | |
| 93 | } | |
| 94 | ||
| 95 | // --- #include handling --- | |
| 96 | ||
| 97 | function handlePreproc (cursor, source, result) { | |
| 98 | // #include followed by either SystemLibString (<...>) or String ("...") | |
| 99 | if (!cursor.firstChild()) return | |
| 100 | let isInclude = false | |
| 101 | try { | |
| 102 | do { | |
| 103 | if (cursor.name === '#include') isInclude = true | |
| 104 | else if (isInclude && cursor.name === 'String') { | |
| 105 | // Quoted include — local dependency | |
| 106 | const text = source.slice(cursor.from, cursor.to).replace(/^["<]|[">]$/g, '') | |
| 107 | result.imports.push({ specifier: text, names: [] }) | |
| 108 | } | |
| 109 | // SystemLibString (<...>) is skipped — system headers don't participate in the local graph | |
| 110 | } while (cursor.nextSibling()) | |
| 111 | } finally { | |
| 112 | cursor.parent() | |
| 113 | } | |
| 114 | } | |
| 115 | ||
| 116 | // --- Namespace --- | |
| 117 | ||
| 118 | function handleNamespace (cursor, source, result, outOfLineMethods) { | |
| 119 | if (!cursor.firstChild()) return | |
| 120 | let nsName = null | |
| 121 | try { | |
| 122 | do { | |
| 123 | if (cursor.name === 'Identifier' && !nsName) { | |
| 124 | const text = source.slice(cursor.from, cursor.to) | |
| 125 | if (text !== 'namespace') nsName = text | |
| 126 | } else if (cursor.name === 'CompoundStatement') { | |
| 127 | // Walk the body as if it were top-level | |
| 128 | if (cursor.firstChild()) { | |
| 129 | do { visitTopLevel(cursor, source, result, outOfLineMethods) } while (cursor.nextSibling()) | |
| 130 | cursor.parent() | |
| 131 | } | |
| 132 | } | |
| 133 | } while (cursor.nextSibling()) | |
| 134 | } finally { | |
| 135 | cursor.parent() | |
| 136 | } | |
| 137 | if (nsName && !result.namespaces.includes(nsName)) result.namespaces.push(nsName) | |
| 138 | } | |
| 139 | ||
| 140 | // --- Class / struct --- | |
| 141 | ||
| 142 | function extractClass (cursor, source, kind) { | |
| 143 | const cls = { | |
| 144 | name: null, | |
| 145 | kind, | |
| 146 | extends: null, | |
| 147 | line: getLine(source, cursor.from), | |
| 148 | methods: [], | |
| 149 | getters: [], | |
| 150 | staticMethods: [], | |
| 151 | constructor: null | |
| 152 | } | |
| 153 | ||
| 154 | if (!cursor.firstChild()) return null | |
| 155 | try { | |
| 156 | do { | |
| 157 | if (cursor.name === 'TypeIdentifier' && !cls.name) { | |
| 158 | cls.name = source.slice(cursor.from, cursor.to) | |
| 159 | } else if (cursor.name === 'BaseClassClause') { | |
| 160 | cls.extends = extractBaseClass(cursor, source) | |
| 161 | } else if (cursor.name === 'FieldDeclarationList') { | |
| 162 | extractFieldDeclarations(cursor, source, cls) | |
| 163 | } | |
| 164 | } while (cursor.nextSibling()) | |
| 165 | } finally { | |
| 166 | cursor.parent() | |
| 167 | } | |
| 168 | ||
| 169 | return cls.name ? cls : null | |
| 170 | } | |
| 171 | ||
| 172 | function extractBaseClass (cursor, source) { | |
| 173 | // BaseClassClause contains Access + TypeIdentifier (or just TypeIdentifier) | |
| 174 | if (!cursor.firstChild()) return null | |
| 175 | try { | |
| 176 | do { | |
| 177 | if (cursor.name === 'TypeIdentifier') { | |
| 178 | return source.slice(cursor.from, cursor.to) | |
| 179 | } | |
| 180 | } while (cursor.nextSibling()) | |
| 181 | } finally { | |
| 182 | cursor.parent() | |
| 183 | } | |
| 184 | return null | |
| 185 | } | |
| 186 | ||
| 187 | function extractFieldDeclarations (cursor, source, cls) { | |
| 188 | if (!cursor.firstChild()) return | |
| 189 | let currentAccess = 'private' // default for class, public for struct — not enforced here | |
| 190 | try { | |
| 191 | do { | |
| 192 | if (cursor.name === 'AccessSpecifier') { | |
| 193 | const text = source.slice(cursor.from, cursor.to) | |
| 194 | if (text.startsWith('public')) currentAccess = 'public' | |
| 195 | else if (text.startsWith('protected')) currentAccess = 'protected' | |
| 196 | else currentAccess = 'private' | |
| 197 | } else if (cursor.name === 'FieldDeclaration' || cursor.name === 'FunctionDefinition') { | |
| 198 | const isStatic = hasChildWithText(cursor, source, 'static') | |
| 199 | const decl = extractFieldOrMethod(cursor, source, cls.name) | |
| 200 | if (decl) { | |
| 201 | decl.access = currentAccess | |
| 202 | if (decl.isMethod) { | |
| 203 | const m = { name: decl.name, params: decl.params, line: decl.line } | |
| 204 | if (isStatic) { | |
| 205 | m.static = true | |
| 206 | cls.staticMethods.push(m) | |
| 207 | } else if (decl.name === cls.name) { | |
| 208 | cls.constructor = m | |
| 209 | } else { | |
| 210 | cls.methods.push(m) | |
| 211 | } | |
| 212 | } | |
| 213 | // Data fields: not separately tracked in the common interface; could add to state later | |
| 214 | } | |
| 215 | } | |
| 216 | } while (cursor.nextSibling()) | |
| 217 | } finally { | |
| 218 | cursor.parent() | |
| 219 | } | |
| 220 | } | |
| 221 | ||
| 222 | function hasChildWithText (cursor, source, text) { | |
| 223 | if (!cursor.firstChild()) return false | |
| 224 | try { | |
| 225 | do { | |
| 226 | const t = source.slice(cursor.from, cursor.to) | |
| 227 | if (t === text) return true | |
| 228 | } while (cursor.nextSibling()) | |
| 229 | } finally { | |
| 230 | cursor.parent() | |
| 231 | } | |
| 232 | return false | |
| 233 | } | |
| 234 | ||
| 235 | function extractFieldOrMethod (cursor, source, className) { | |
| 236 | // FieldDeclaration may contain a FunctionDeclarator (method) or just an identifier (data field). | |
| 237 | // FunctionDefinition contains a FunctionDeclarator + CompoundStatement (inline method body). | |
| 238 | // Return types like `Foo*` wrap the FunctionDeclarator in a PointerDeclarator — recurse through those. | |
| 239 | let name = null | |
| 240 | let params = [] | |
| 241 | let isMethod = false | |
| 242 | const line = getLine(source, cursor.from) | |
| 243 | ||
| 244 | function visit () { | |
| 245 | if (!cursor.firstChild()) return | |
| 246 | try { | |
| 247 | do { | |
| 248 | if (cursor.name === 'FunctionDeclarator') { | |
| 249 | isMethod = true | |
| 250 | const fd = extractFunctionDeclarator(cursor, source) | |
| 251 | if (fd) { name = fd.name; params = fd.params } | |
| 252 | } else if (cursor.name === 'PointerDeclarator' || cursor.name === 'ReferenceDeclarator') { | |
| 253 | // Recurse: `Foo* create()` or `Foo& create()` | |
| 254 | visit() | |
| 255 | } else if ((cursor.name === 'FieldIdentifier' || cursor.name === 'Identifier') && !name) { | |
| 256 | name = source.slice(cursor.from, cursor.to) | |
| 257 | } | |
| 258 | } while (cursor.nextSibling()) | |
| 259 | } finally { | |
| 260 | cursor.parent() | |
| 261 | } | |
| 262 | } | |
| 263 | ||
| 264 | visit() | |
| 265 | ||
| 266 | if (!name) return null | |
| 267 | return { name, params, isMethod, line } | |
| 268 | } | |
| 269 | ||
| 270 | function extractFunctionDeclarator (cursor, source) { | |
| 271 | let name = null | |
| 272 | const params = [] | |
| 273 | let classPart = null // for scoped names like ClassName::method | |
| 274 | ||
| 275 | if (!cursor.firstChild()) return null | |
| 276 | try { | |
| 277 | do { | |
| 278 | if (cursor.name === 'Identifier' && !name) { | |
| 279 | name = source.slice(cursor.from, cursor.to) | |
| 280 | } else if (cursor.name === 'FieldIdentifier' && !name) { | |
| 281 | name = source.slice(cursor.from, cursor.to) | |
| 282 | } else if (cursor.name === 'ScopedIdentifier') { | |
| 283 | // ClassName::method — extract both halves | |
| 284 | const parts = extractScoped(cursor, source) | |
| 285 | if (parts) { classPart = parts.ns; name = parts.name } | |
| 286 | } else if (cursor.name === 'ParameterList') { | |
| 287 | extractParameterList(cursor, source, params) | |
| 288 | } | |
| 289 | } while (cursor.nextSibling()) | |
| 290 | } finally { | |
| 291 | cursor.parent() | |
| 292 | } | |
| 293 | ||
| 294 | if (!name) return null | |
| 295 | return { name, params, classPart } | |
| 296 | } | |
| 297 | ||
| 298 | function extractScoped (cursor, source) { | |
| 299 | // ScopedIdentifier: NamespaceIdentifier :: Identifier | |
| 300 | let ns = null | |
| 301 | let name = null | |
| 302 | if (!cursor.firstChild()) return null | |
| 303 | try { | |
| 304 | do { | |
| 305 | if (cursor.name === 'NamespaceIdentifier' && !ns) { | |
| 306 | ns = source.slice(cursor.from, cursor.to) | |
| 307 | } else if (cursor.name === 'Identifier') { | |
| 308 | name = source.slice(cursor.from, cursor.to) | |
| 309 | } | |
| 310 | } while (cursor.nextSibling()) | |
| 311 | } finally { | |
| 312 | cursor.parent() | |
| 313 | } | |
| 314 | return (ns && name) ? { ns, name } : null | |
| 315 | } | |
| 316 | ||
| 317 | function extractParameterList (cursor, source, params) { | |
| 318 | if (!cursor.firstChild()) return | |
| 319 | try { | |
| 320 | do { | |
| 321 | if (cursor.name === 'ParameterDeclaration') { | |
| 322 | // Get last Identifier as param name (after the type) | |
| 323 | const pName = lastIdentifier(cursor, source) | |
| 324 | if (pName) params.push(pName) | |
| 325 | } | |
| 326 | } while (cursor.nextSibling()) | |
| 327 | } finally { | |
| 328 | cursor.parent() | |
| 329 | } | |
| 330 | } | |
| 331 | ||
| 332 | function lastIdentifier (cursor, source) { | |
| 333 | let name = null | |
| 334 | if (!cursor.firstChild()) return null | |
| 335 | try { | |
| 336 | do { | |
| 337 | if (cursor.name === 'Identifier') { | |
| 338 | name = source.slice(cursor.from, cursor.to) | |
| 339 | } | |
| 340 | } while (cursor.nextSibling()) | |
| 341 | } finally { | |
| 342 | cursor.parent() | |
| 343 | } | |
| 344 | return name | |
| 345 | } | |
| 346 | ||
| 347 | // --- Free function / out-of-line method definitions --- | |
| 348 | ||
| 349 | function handleFunctionDefinition (cursor, source, result, outOfLineMethods) { | |
| 350 | // FunctionDefinition = return-type + FunctionDeclarator + CompoundStatement | |
| 351 | if (!cursor.firstChild()) return | |
| 352 | let fd = null | |
| 353 | const line = getLine(source, cursor.from) | |
| 354 | try { | |
| 355 | do { | |
| 356 | if (cursor.name === 'FunctionDeclarator') { | |
| 357 | fd = extractFunctionDeclarator(cursor, source) | |
| 358 | } | |
| 359 | } while (cursor.nextSibling()) | |
| 360 | } finally { | |
| 361 | cursor.parent() | |
| 362 | } | |
| 363 | ||
| 364 | if (!fd) return | |
| 365 | ||
| 366 | if (fd.classPart) { | |
| 367 | // Out-of-line method: buffer until we process its class | |
| 368 | if (!outOfLineMethods[fd.classPart]) outOfLineMethods[fd.classPart] = [] | |
| 369 | outOfLineMethods[fd.classPart].push({ name: fd.name, params: fd.params, line }) | |
| 370 | } else { | |
| 371 | result.functions.push({ name: fd.name, params: fd.params, line }) | |
| 372 | } | |
| 373 | } | |
| 374 | ||
| 375 | // --- Enum --- | |
| 376 | ||
| 377 | function handleEnum (cursor, source, result) { | |
| 378 | let name = null | |
| 379 | const values = [] | |
| 380 | if (!cursor.firstChild()) return | |
| 381 | try { | |
| 382 | do { | |
| 383 | if (cursor.name === 'TypeIdentifier' && !name) { | |
| 384 | name = source.slice(cursor.from, cursor.to) | |
| 385 | } else if (cursor.name === 'EnumeratorList') { | |
| 386 | if (cursor.firstChild()) { | |
| 387 | do { | |
| 388 | if (cursor.name === 'Enumerator') { | |
| 389 | const v = firstIdentifier(cursor, source) | |
| 390 | if (v) values.push(v) | |
| 391 | } | |
| 392 | } while (cursor.nextSibling()) | |
| 393 | cursor.parent() | |
| 394 | } | |
| 395 | } | |
| 396 | } while (cursor.nextSibling()) | |
| 397 | } finally { | |
| 398 | cursor.parent() | |
| 399 | } | |
| 400 | if (name) result.enums.push({ name, values }) | |
| 401 | } | |
| 402 | ||
| 403 | // --- Declarations (catches #define macros via TypeDefinition, GDCLASS, etc.) --- | |
| 404 | ||
| 405 | function handleDeclaration (cursor, source, result) { | |
| 406 | // Most non-function declarations are global variables or forward declarations. | |
| 407 | // We care about free function declarations (not definitions) at top level. | |
| 408 | if (!cursor.firstChild()) return | |
| 409 | let fd = null | |
| 410 | const line = getLine(source, cursor.from) | |
| 411 | try { | |
| 412 | do { | |
| 413 | if (cursor.name === 'FunctionDeclarator') { | |
| 414 | fd = extractFunctionDeclarator(cursor, source) | |
| 415 | } | |
| 416 | } while (cursor.nextSibling()) | |
| 417 | } finally { | |
| 418 | cursor.parent() | |
| 419 | } | |
| 420 | ||
| 421 | if (fd && !fd.classPart) { | |
| 422 | // Only add if not already defined (avoid double-counting with definitions) | |
| 423 | if (!result.functions.find(f => f.name === fd.name)) { | |
| 424 | result.functions.push({ name: fd.name, params: fd.params, line }) | |
| 425 | } | |
| 426 | } | |
| 427 | } | |
| 428 | ||
| 429 | // --- Helpers --- | |
| 430 | ||
| 431 | function findTypeIdentifier (cursor, source) { | |
| 432 | if (!cursor.firstChild()) return null | |
| 433 | try { | |
| 434 | do { | |
| 435 | if (cursor.name === 'TypeIdentifier') { | |
| 436 | return source.slice(cursor.from, cursor.to) | |
| 437 | } | |
| 438 | } while (cursor.nextSibling()) | |
| 439 | } finally { | |
| 440 | cursor.parent() | |
| 441 | } | |
| 442 | return null | |
| 443 | } | |
| 444 | ||
| 445 | function firstIdentifier (cursor, source) { | |
| 446 | if (!cursor.firstChild()) return null | |
| 447 | try { | |
| 448 | do { | |
| 449 | if (cursor.name === 'Identifier') { | |
| 450 | return source.slice(cursor.from, cursor.to) | |
| 451 | } | |
| 452 | } while (cursor.nextSibling()) | |
| 453 | } finally { | |
| 454 | cursor.parent() | |
| 455 | } | |
| 456 | return null | |
| 457 | } | |
| 458 | ||
| 459 | function getLine (source, offset) { | |
| 460 | return source.slice(0, offset).split('\n').length | |
| 461 | } |
| … | … | @@ -0,0 +1,288 @@ |
| 1 | import { parser } from '../../vendor/lezer-gdscript/lezer-gdscript.mjs' | |
| 2 | ||
| 3 | /** | |
| 4 | * GDScript parser — walks the Lezer concrete syntax tree to extract: | |
| 5 | * - class_name (treated as the file's exported class) | |
| 6 | * - extends (base class) | |
| 7 | * - signals (GDScript-specific) | |
| 8 | * - functions / methods | |
| 9 | * - constants and variables | |
| 10 | * - preload() calls → imports | |
| 11 | * | |
| 12 | * A .gd file IS a class (the class_name declares its global identity). | |
| 13 | * Top-level funcs are methods of that class; top-level vars are its state. | |
| 14 | */ | |
| 15 | ||
| 16 | export function parseFile (source, filePath) { | |
| 17 | let tree | |
| 18 | try { tree = parser.parse(source) } | |
| 19 | catch (err) { return { error: err.message, filePath } } | |
| 20 | ||
| 21 | const result = { | |
| 22 | filePath, | |
| 23 | imports: [], | |
| 24 | exports: [], | |
| 25 | classes: [], | |
| 26 | functions: [], | |
| 27 | constants: [], | |
| 28 | signals: [], | |
| 29 | enums: [] | |
| 30 | } | |
| 31 | ||
| 32 | // Single implicit class for the file — filled in as we walk | |
| 33 | const fileClass = { | |
| 34 | name: null, // filled from class_name, or file basename | |
| 35 | extends: null, | |
| 36 | line: 1, | |
| 37 | methods: [], | |
| 38 | getters: [], | |
| 39 | staticMethods: [], | |
| 40 | constructor: null | |
| 41 | } | |
| 42 | ||
| 43 | const cursor = tree.cursor() | |
| 44 | ||
| 45 | // Walk only top-level statements inside Script | |
| 46 | if (cursor.firstChild()) { | |
| 47 | do { | |
| 48 | visitTopLevel(cursor, source, fileClass, result) | |
| 49 | } while (cursor.nextSibling()) | |
| 50 | } | |
| 51 | ||
| 52 | // Default name from filename if no class_name found | |
| 53 | if (!fileClass.name) { | |
| 54 | const base = filePath.split('/').pop().replace(/\.gd$/, '') | |
| 55 | fileClass.name = base | |
| 56 | } | |
| 57 | ||
| 58 | // Emit the class unless the file is clearly not a class (no name, no body) | |
| 59 | if (fileClass.methods.length > 0 || fileClass.getters.length > 0 || | |
| 60 | fileClass.staticMethods.length > 0 || fileClass.extends || result.exports.length > 0) { | |
| 61 | result.classes.push(fileClass) | |
| 62 | } | |
| 63 | ||
| 64 | return result | |
| 65 | } | |
| 66 | ||
| 67 | function visitTopLevel (cursor, source, fileClass, result) { | |
| 68 | const name = cursor.name | |
| 69 | ||
| 70 | // SimpleStatement wraps most top-level statements | |
| 71 | if (name === 'SimpleStatement' || name === 'SmallStatement') { | |
| 72 | if (cursor.firstChild()) { | |
| 73 | do { visitTopLevel(cursor, source, fileClass, result) } while (cursor.nextSibling()) | |
| 74 | cursor.parent() | |
| 75 | } | |
| 76 | return | |
| 77 | } | |
| 78 | ||
| 79 | // CompoundStatement wraps function/class bodies | |
| 80 | if (name === 'CompoundStatement') { | |
| 81 | if (cursor.firstChild()) { | |
| 82 | do { visitTopLevel(cursor, source, fileClass, result) } while (cursor.nextSibling()) | |
| 83 | cursor.parent() | |
| 84 | } | |
| 85 | return | |
| 86 | } | |
| 87 | ||
| 88 | // class_name → file's class name + exported as a class | |
| 89 | if (name === 'ClassNameStatement') { | |
| 90 | const ident = identifierText(cursor, source) | |
| 91 | if (ident) { | |
| 92 | fileClass.name = ident | |
| 93 | fileClass.line = getLine(source, cursor.from) | |
| 94 | result.exports.push({ name: ident, type: 'class' }) | |
| 95 | } | |
| 96 | return | |
| 97 | } | |
| 98 | ||
| 99 | // extends → base class | |
| 100 | if (name === 'ExtendsStatement') { | |
| 101 | const ident = identifierText(cursor, source) | |
| 102 | if (ident) fileClass.extends = ident | |
| 103 | return | |
| 104 | } | |
| 105 | ||
| 106 | // signal → signals array | |
| 107 | if (name === 'SignalStatement') { | |
| 108 | const sig = extractSignal(cursor, source) | |
| 109 | if (sig) result.signals.push(sig) | |
| 110 | return | |
| 111 | } | |
| 112 | ||
| 113 | // func / static func → method | |
| 114 | if (name === 'FunctionNode') { | |
| 115 | const fn = extractFunction(cursor, source) | |
| 116 | if (fn) { | |
| 117 | // Check if preceded by a "static" keyword (GDScript puts static before func) | |
| 118 | const isStatic = isPrecededByStatic(source, cursor.from) | |
| 119 | if (isStatic) fn.static = true | |
| 120 | if (fn.name === '_init') { | |
| 121 | fileClass.constructor = { params: fn.params, line: fn.line } | |
| 122 | } else if (isStatic) { | |
| 123 | fileClass.staticMethods.push(fn) | |
| 124 | } else { | |
| 125 | fileClass.methods.push(fn) | |
| 126 | } | |
| 127 | } | |
| 128 | return | |
| 129 | } | |
| 130 | ||
| 131 | // AssignmentExpressionNode wraps var/const declarations | |
| 132 | if (name === 'AssignmentExpressionNode') { | |
| 133 | extractAssignment(cursor, source, result) | |
| 134 | return | |
| 135 | } | |
| 136 | } | |
| 137 | ||
| 138 | // --- Helpers --- | |
| 139 | ||
| 140 | function identifierText (cursor, source) { | |
| 141 | if (!cursor.firstChild()) return null | |
| 142 | try { | |
| 143 | do { | |
| 144 | if (cursor.name === 'Identifier') { | |
| 145 | const text = source.slice(cursor.from, cursor.to) | |
| 146 | // Skip keyword-like identifiers | |
| 147 | if (text !== 'class_name' && text !== 'extends' && text !== 'signal' && | |
| 148 | text !== 'func' && text !== 'var' && text !== 'const' && text !== 'enum') { | |
| 149 | return text | |
| 150 | } | |
| 151 | } | |
| 152 | } while (cursor.nextSibling()) | |
| 153 | } finally { | |
| 154 | cursor.parent() | |
| 155 | } | |
| 156 | return null | |
| 157 | } | |
| 158 | ||
| 159 | function extractSignal (cursor, source) { | |
| 160 | const sig = { name: null, params: [] } | |
| 161 | if (!cursor.firstChild()) return null | |
| 162 | try { | |
| 163 | do { | |
| 164 | if (cursor.name === 'Identifier' && !sig.name) { | |
| 165 | const text = source.slice(cursor.from, cursor.to) | |
| 166 | if (text !== 'signal') sig.name = text | |
| 167 | } else if (cursor.name === 'CallParamsExpressionNode') { | |
| 168 | sig.params = extractParamsFromCall(cursor, source) | |
| 169 | } | |
| 170 | } while (cursor.nextSibling()) | |
| 171 | } finally { | |
| 172 | cursor.parent() | |
| 173 | } | |
| 174 | return sig.name ? sig : null | |
| 175 | } | |
| 176 | ||
| 177 | function extractFunction (cursor, source) { | |
| 178 | const fn = { name: null, params: [], line: getLine(source, cursor.from) } | |
| 179 | if (!cursor.firstChild()) return null | |
| 180 | try { | |
| 181 | do { | |
| 182 | if (cursor.name === 'Identifier' && !fn.name) { | |
| 183 | const text = source.slice(cursor.from, cursor.to) | |
| 184 | if (text !== 'func' && text !== 'static') fn.name = text | |
| 185 | } else if (cursor.name === 'CallParamsParameterNode') { | |
| 186 | fn.params = extractParamsFromCall(cursor, source) | |
| 187 | } | |
| 188 | } while (cursor.nextSibling()) | |
| 189 | } finally { | |
| 190 | cursor.parent() | |
| 191 | } | |
| 192 | return fn.name ? fn : null | |
| 193 | } | |
| 194 | ||
| 195 | function extractParamsFromCall (cursor, source) { | |
| 196 | // cursor is at CallParamsParameterNode or CallParamsExpressionNode | |
| 197 | const params = [] | |
| 198 | if (!cursor.firstChild()) return params | |
| 199 | try { | |
| 200 | do { | |
| 201 | if (cursor.name === 'ParameterNode' || cursor.name === 'AssignmentExpressionNode') { | |
| 202 | // Grab first identifier as param name | |
| 203 | const paramName = firstIdentifier(cursor, source) | |
| 204 | if (paramName) params.push(paramName) | |
| 205 | } | |
| 206 | } while (cursor.nextSibling()) | |
| 207 | } finally { | |
| 208 | cursor.parent() | |
| 209 | } | |
| 210 | return params | |
| 211 | } | |
| 212 | ||
| 213 | function firstIdentifier (cursor, source) { | |
| 214 | if (!cursor.firstChild()) return null | |
| 215 | try { | |
| 216 | do { | |
| 217 | if (cursor.name === 'Identifier') { | |
| 218 | return source.slice(cursor.from, cursor.to) | |
| 219 | } | |
| 220 | } while (cursor.nextSibling()) | |
| 221 | } finally { | |
| 222 | cursor.parent() | |
| 223 | } | |
| 224 | return null | |
| 225 | } | |
| 226 | ||
| 227 | function extractAssignment (cursor, source, result) { | |
| 228 | // AssignmentExpressionNode may contain VariableNode, ConstantNode, and/or PreloadExpressionNode | |
| 229 | if (!cursor.firstChild()) return | |
| 230 | try { | |
| 231 | do { | |
| 232 | if (cursor.name === 'VariableNode' || cursor.name === 'ConstantNode') { | |
| 233 | const kind = cursor.name === 'ConstantNode' ? 'const' : 'var' | |
| 234 | const ident = firstIdentifier(cursor, source) | |
| 235 | if (ident) result.constants.push({ name: ident, kind }) | |
| 236 | } else if (cursor.name === 'PreloadExpressionNode') { | |
| 237 | const path = extractPreloadPath(cursor, source) | |
| 238 | if (path) result.imports.push({ specifier: path, names: [] }) | |
| 239 | } | |
| 240 | } while (cursor.nextSibling()) | |
| 241 | } finally { | |
| 242 | cursor.parent() | |
| 243 | } | |
| 244 | } | |
| 245 | ||
| 246 | function extractPreloadPath (cursor, source) { | |
| 247 | // Find LiteralExpressionNode within CallParamsExpressionNode | |
| 248 | if (!cursor.firstChild()) return null | |
| 249 | try { | |
| 250 | do { | |
| 251 | if (cursor.name === 'CallParamsExpressionNode') { | |
| 252 | const lit = findLiteralInCall(cursor, source) | |
| 253 | if (lit) { | |
| 254 | // Strip quotes | |
| 255 | return lit.replace(/^['"]|['"]$/g, '') | |
| 256 | } | |
| 257 | } | |
| 258 | } while (cursor.nextSibling()) | |
| 259 | } finally { | |
| 260 | cursor.parent() | |
| 261 | } | |
| 262 | return null | |
| 263 | } | |
| 264 | ||
| 265 | function findLiteralInCall (cursor, source) { | |
| 266 | if (!cursor.firstChild()) return null | |
| 267 | try { | |
| 268 | do { | |
| 269 | if (cursor.name === 'LiteralExpressionNode') { | |
| 270 | return source.slice(cursor.from, cursor.to) | |
| 271 | } | |
| 272 | } while (cursor.nextSibling()) | |
| 273 | } finally { | |
| 274 | cursor.parent() | |
| 275 | } | |
| 276 | return null | |
| 277 | } | |
| 278 | ||
| 279 | function isPrecededByStatic (source, from) { | |
| 280 | // Look backwards from `from` for the word 'static' before 'func' | |
| 281 | // GDScript: `static func` — static appears on same line, before func | |
| 282 | const before = source.slice(Math.max(0, from - 60), from) | |
| 283 | return /\bstatic\s*$/.test(before) || /\bstatic\s+\n?\s*$/.test(before) | |
| 284 | } | |
| 285 | ||
| 286 | function getLine (source, offset) { | |
| 287 | return source.slice(0, offset).split('\n').length | |
| 288 | } |
| … | … | @@ -0,0 +1,296 @@ |
| 1 | import { parse } from '../../vendor/glsl-parser/glsl-parser.mjs' | |
| 2 | ||
| 3 | /** | |
| 4 | * GLSL parser — walks the @shaderfrog/glsl-parser AST to extract: | |
| 5 | * - Functions (void main, helpers) | |
| 6 | * - Uniforms (regular uniform vars + uniform blocks) | |
| 7 | * - Buffers (readonly/writeonly storage buffers) | |
| 8 | * - Push constants (uniform blocks with push_constant layout) | |
| 9 | * - Structs → classes | |
| 10 | * - #defines → constants | |
| 11 | * | |
| 12 | * GLSL has no import system in the general case (dc-terrain shaders are monolithic), | |
| 13 | * so imports[] is always empty. Godot .gdshader files may use `#include` but those | |
| 14 | * are engine-specific and not modeled here yet. | |
| 15 | */ | |
| 16 | ||
| 17 | export function parseFile (source, filePath) { | |
| 18 | // Always return these empty arrays so downstream consumers can `.length` safely even | |
| 19 | // on parse failure. | |
| 20 | const result = { | |
| 21 | filePath, | |
| 22 | imports: [], | |
| 23 | exports: [], | |
| 24 | classes: [], | |
| 25 | functions: [], | |
| 26 | constants: [], | |
| 27 | uniforms: [], | |
| 28 | buffers: [], | |
| 29 | pushConstants: [] | |
| 30 | } | |
| 31 | ||
| 32 | // Godot .gdshader files are a GLSL superset with editor hints that standard GLSL | |
| 33 | // doesn't accept (e.g. `uniform sampler3D foo : filter_linear, repeat_enable;`). | |
| 34 | // Strip these hints — they're purely presentational, not part of the shader logic. | |
| 35 | const isGdShader = filePath && filePath.endsWith('.gdshader') | |
| 36 | const processed = isGdShader ? stripGodotShaderHints(source) : source | |
| 37 | ||
| 38 | // The parser emits warnings to console.warn for unknown identifiers (e.g. GLSL builtins | |
| 39 | // like gl_GlobalInvocationID). Silence them during structural extraction. | |
| 40 | const origWarn = console.warn | |
| 41 | console.warn = () => {} | |
| 42 | let ast | |
| 43 | try { ast = parse(processed) } | |
| 44 | catch (err) { | |
| 45 | console.warn = origWarn | |
| 46 | result.error = err.message | |
| 47 | return result | |
| 48 | } | |
| 49 | console.warn = origWarn | |
| 50 | ||
| 51 | if (!ast || !ast.program) return result | |
| 52 | ||
| 53 | for (const node of ast.program) { | |
| 54 | switch (node.type) { | |
| 55 | case 'preprocessor': | |
| 56 | handlePreprocessor(node, result) | |
| 57 | break | |
| 58 | case 'declaration_statement': | |
| 59 | handleDeclarationStatement(node, result) | |
| 60 | break | |
| 61 | case 'function': | |
| 62 | handleFunction(node, result) | |
| 63 | break | |
| 64 | } | |
| 65 | } | |
| 66 | ||
| 67 | return result | |
| 68 | } | |
| 69 | ||
| 70 | // --- Preprocessor (#define, #include) --- | |
| 71 | ||
| 72 | function handlePreprocessor (node, result) { | |
| 73 | const line = node.line || '' | |
| 74 | ||
| 75 | // #define NAME value — extract as constant | |
| 76 | const defMatch = line.match(/^\s*#\s*define\s+(\w+)\b/) | |
| 77 | if (defMatch) { | |
| 78 | result.constants.push({ name: defMatch[1], kind: 'define' }) | |
| 79 | return | |
| 80 | } | |
| 81 | ||
| 82 | // #include "path" (Godot .gdshader style) — capture as import | |
| 83 | const incMatch = line.match(/^\s*#\s*include\s+["<]([^">]+)[">]/) | |
| 84 | if (incMatch) { | |
| 85 | result.imports.push({ specifier: incMatch[1], names: [] }) | |
| 86 | } | |
| 87 | } | |
| 88 | ||
| 89 | // --- Declaration statements (uniforms, buffers, structs, layout) --- | |
| 90 | ||
| 91 | function handleDeclarationStatement (node, result) { | |
| 92 | const decl = node.declaration | |
| 93 | if (!decl) return | |
| 94 | ||
| 95 | switch (decl.type) { | |
| 96 | case 'interface_declarator': | |
| 97 | handleInterfaceDeclarator(decl, result) | |
| 98 | return | |
| 99 | case 'declarator_list': | |
| 100 | handleDeclaratorList(decl, result) | |
| 101 | return | |
| 102 | case 'qualifier_declarator': | |
| 103 | // layout-only decls like `layout(local_size_x=256) in;` — no extraction needed | |
| 104 | return | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | function handleInterfaceDeclarator (decl, result) { | |
| 109 | // Used for: buffer blocks, uniform blocks, push constants | |
| 110 | const qualTokens = extractQualifierTokens(decl.qualifiers || []) | |
| 111 | const hasLayout = (decl.qualifiers || []).some(q => q.type === 'layout_qualifier') | |
| 112 | const layoutIds = extractLayoutIds(decl.qualifiers || []) | |
| 113 | ||
| 114 | const blockName = decl.interface_type && decl.interface_type.identifier | |
| 115 | ? decl.interface_type.identifier | |
| 116 | : null | |
| 117 | const instanceName = decl.identifier && decl.identifier.identifier | |
| 118 | ? decl.identifier.identifier | |
| 119 | : null | |
| 120 | ||
| 121 | if (!blockName) return | |
| 122 | ||
| 123 | const isBuffer = qualTokens.includes('buffer') | |
| 124 | const isUniform = qualTokens.includes('uniform') | |
| 125 | const isPushConstant = layoutIds.some(id => id === 'push_constant') | |
| 126 | const isReadonly = qualTokens.includes('readonly') | |
| 127 | const isWriteonly = qualTokens.includes('writeonly') | |
| 128 | ||
| 129 | const entry = { | |
| 130 | name: blockName, | |
| 131 | instance: instanceName, | |
| 132 | binding: layoutIdValue(layoutIds, 'binding'), | |
| 133 | set: layoutIdValue(layoutIds, 'set'), | |
| 134 | std: layoutIds.find(id => id === 'std140' || id === 'std430') || null | |
| 135 | } | |
| 136 | if (isReadonly) entry.readonly = true | |
| 137 | if (isWriteonly) entry.writeonly = true | |
| 138 | ||
| 139 | if (isPushConstant) { | |
| 140 | result.pushConstants.push(entry) | |
| 141 | } else if (isBuffer) { | |
| 142 | result.buffers.push(entry) | |
| 143 | } else if (isUniform) { | |
| 144 | result.uniforms.push(entry) | |
| 145 | } | |
| 146 | } | |
| 147 | ||
| 148 | function handleDeclaratorList (decl, result) { | |
| 149 | // Could be: | |
| 150 | // - struct declaration: specifier.type === 'struct' | |
| 151 | // - uniform sampler2D u_tex; | |
| 152 | // - in/out variables | |
| 153 | // - regular global variables | |
| 154 | const specType = decl.specified_type && decl.specified_type.specifier | |
| 155 | const quals = (decl.specified_type && decl.specified_type.qualifiers) || [] | |
| 156 | const qualTokens = extractQualifierTokens(quals) | |
| 157 | ||
| 158 | // Struct declaration | |
| 159 | if (specType && specType.specifier && specType.specifier.type === 'struct') { | |
| 160 | const structNode = specType.specifier | |
| 161 | const structName = structNode.typeName && structNode.typeName.identifier | |
| 162 | ? structNode.typeName.identifier | |
| 163 | : null | |
| 164 | if (structName) { | |
| 165 | const cls = { | |
| 166 | name: structName, | |
| 167 | kind: 'struct', | |
| 168 | extends: null, | |
| 169 | line: null, | |
| 170 | methods: [], | |
| 171 | getters: [], | |
| 172 | staticMethods: [], | |
| 173 | constructor: null, | |
| 174 | fields: extractStructFields(structNode) | |
| 175 | } | |
| 176 | result.classes.push(cls) | |
| 177 | result.exports.push({ name: structName, type: 'struct' }) | |
| 178 | } | |
| 179 | return | |
| 180 | } | |
| 181 | ||
| 182 | // Regular variable declaration (uniform float u_time, in vec3 pos, etc.) | |
| 183 | const declarations = decl.declarations || [] | |
| 184 | for (const d of declarations) { | |
| 185 | if (d.type === 'declaration' && d.identifier && d.identifier.identifier) { | |
| 186 | const name = d.identifier.identifier | |
| 187 | const typeToken = specType && specType.specifier && specType.specifier.token | |
| 188 | ? specType.specifier.token | |
| 189 | : null | |
| 190 | if (qualTokens.includes('uniform')) { | |
| 191 | result.uniforms.push({ name, type: typeToken, binding: null, set: null }) | |
| 192 | } else if (qualTokens.includes('in') || qualTokens.includes('out')) { | |
| 193 | result.constants.push({ name, kind: qualTokens.includes('out') ? 'out' : 'in' }) | |
| 194 | } else { | |
| 195 | result.constants.push({ name, kind: 'var' }) | |
| 196 | } | |
| 197 | } | |
| 198 | } | |
| 199 | } | |
| 200 | ||
| 201 | function extractStructFields (structNode) { | |
| 202 | const fields = [] | |
| 203 | for (const d of structNode.declarations || []) { | |
| 204 | if (d.type !== 'struct_declaration') continue | |
| 205 | const sd = d.declaration | |
| 206 | if (!sd || !sd.declarations) continue | |
| 207 | for (const q of sd.declarations) { | |
| 208 | if (q.type === 'quantified_identifier' && q.identifier) { | |
| 209 | fields.push(q.identifier.identifier) | |
| 210 | } | |
| 211 | } | |
| 212 | } | |
| 213 | return fields | |
| 214 | } | |
| 215 | ||
| 216 | // --- Function definitions --- | |
| 217 | ||
| 218 | function handleFunction (node, result) { | |
| 219 | const proto = node.prototype | |
| 220 | if (!proto || !proto.header) return | |
| 221 | const header = proto.header | |
| 222 | const name = header.name && header.name.identifier ? header.name.identifier : null | |
| 223 | if (!name) return | |
| 224 | ||
| 225 | const params = [] | |
| 226 | const pl = proto.parameters || [] | |
| 227 | for (const p of pl) { | |
| 228 | if (p.type === 'parameter_declaration' && p.declaration && p.declaration.identifier) { | |
| 229 | params.push(p.declaration.identifier.identifier) | |
| 230 | } | |
| 231 | } | |
| 232 | ||
| 233 | result.functions.push({ name, params }) | |
| 234 | // GLSL `void main()` is the shader's entry point — export it so downstream tools | |
| 235 | // can tell entry shaders from helpers. | |
| 236 | if (name === 'main') result.exports.push({ name: 'main', type: 'function' }) | |
| 237 | } | |
| 238 | ||
| 239 | // --- Helpers --- | |
| 240 | ||
| 241 | function extractQualifierTokens (quals) { | |
| 242 | const tokens = [] | |
| 243 | for (const q of quals) { | |
| 244 | if (q.type === 'keyword' && q.token) tokens.push(q.token) | |
| 245 | } | |
| 246 | return tokens | |
| 247 | } | |
| 248 | ||
| 249 | function extractLayoutIds (quals) { | |
| 250 | const ids = [] | |
| 251 | for (const q of quals) { | |
| 252 | if (q.type !== 'layout_qualifier') continue | |
| 253 | for (const lq of q.qualifiers || []) { | |
| 254 | if (lq.type === 'layout_qualifier_id' && lq.identifier && lq.identifier.identifier) { | |
| 255 | const key = lq.identifier.identifier | |
| 256 | const value = lq.expression && lq.expression.token ? lq.expression.token : null | |
| 257 | ids.push(value ? key + '=' + value : key) | |
| 258 | } | |
| 259 | } | |
| 260 | } | |
| 261 | return ids | |
| 262 | } | |
| 263 | ||
| 264 | function layoutIdValue (ids, key) { | |
| 265 | const match = ids.find(id => id.startsWith(key + '=')) | |
| 266 | if (!match) return null | |
| 267 | return match.slice(key.length + 1) | |
| 268 | } | |
| 269 | ||
| 270 | // --- Godot .gdshader preprocessing --- | |
| 271 | ||
| 272 | function stripGodotShaderHints (source) { | |
| 273 | // Remove: | |
| 274 | // shader_type spatial; / shader_type canvas_item; / etc. (top-of-file directive) | |
| 275 | // render_mode foo, bar; (mode modifiers) | |
| 276 | // uniform T name : hint_name, other_hint; (editor hints) | |
| 277 | // uniform T name : hint_name, other_hint = default; (same with default) | |
| 278 | let s = source | |
| 279 | ||
| 280 | // shader_type line | |
| 281 | s = s.replace(/^\s*shader_type\s+\w+\s*;/gm, '') | |
| 282 | ||
| 283 | // render_mode line (may span across commas) | |
| 284 | s = s.replace(/^\s*render_mode\s+[^;]+;/gm, '') | |
| 285 | ||
| 286 | // Uniform hints: `uniform T name : hint, hint_range(0.0, 1.0) = 0.5;` | |
| 287 | // Strip the `: <hints>` portion while preserving any `= default` value. | |
| 288 | // Process line by line to avoid greedy matches spanning multiple uniforms. | |
| 289 | s = s.split('\n').map(line => { | |
| 290 | const m = line.match(/^(\s*uniform\s+[^;=:]+?)\s*:\s*([\s\S]+?)(\s*(?:=[^;]*)?;)\s*$/) | |
| 291 | if (!m) return line | |
| 292 | return m[1] + m[3] | |
| 293 | }).join('\n') | |
| 294 | ||
| 295 | return s | |
| 296 | } |
| … | … | @@ -0,0 +1,491 @@ |
| 1 | import { parse as acornParse } from '../../vendor/acorn/dist/acorn.mjs' | |
| 2 | ||
| 3 | const PARSE_OPTS = { | |
| 4 | ecmaVersion: 'latest', | |
| 5 | sourceType: 'module', | |
| 6 | locations: true, | |
| 7 | ranges: true, | |
| 8 | allowHashBang: true | |
| 9 | } | |
| 10 | ||
| 11 | const CJS_PARSE_OPTS = { | |
| 12 | ...PARSE_OPTS, | |
| 13 | sourceType: 'script' | |
| 14 | } | |
| 15 | ||
| 16 | export function parseFile (source, filePath) { | |
| 17 | const comments = [] | |
| 18 | const isESM = !filePath || !filePath.endsWith('.cjs') | |
| 19 | const opts = { | |
| 20 | ...(isESM ? PARSE_OPTS : CJS_PARSE_OPTS), | |
| 21 | onComment: comments | |
| 22 | } | |
| 23 | ||
| 24 | let ast | |
| 25 | try { | |
| 26 | ast = acornParse(source, opts) | |
| 27 | } catch (err) { | |
| 28 | // Fall back to script mode if module parse fails (CJS files) | |
| 29 | try { | |
| 30 | ast = acornParse(source, { ...CJS_PARSE_OPTS, onComment: comments }) | |
| 31 | } catch { | |
| 32 | return { error: err.message, filePath } | |
| 33 | } | |
| 34 | } | |
| 35 | ||
| 36 | const result = { | |
| 37 | filePath, | |
| 38 | imports: [], | |
| 39 | exports: [], | |
| 40 | classes: [], | |
| 41 | functions: [], | |
| 42 | constants: [], | |
| 43 | state: [], | |
| 44 | errorContracts: [], | |
| 45 | delegates: [] | |
| 46 | } | |
| 47 | ||
| 48 | const commentMap = buildCommentMap(comments) | |
| 49 | ||
| 50 | for (const node of ast.body) { | |
| 51 | switch (node.type) { | |
| 52 | case 'ImportDeclaration': | |
| 53 | result.imports.push(extractImport(node)) | |
| 54 | break | |
| 55 | ||
| 56 | case 'ExportNamedDeclaration': | |
| 57 | extractNamedExport(node, result, commentMap) | |
| 58 | break | |
| 59 | ||
| 60 | case 'ExportDefaultDeclaration': | |
| 61 | extractDefaultExport(node, result, commentMap) | |
| 62 | break | |
| 63 | ||
| 64 | case 'ExportAllDeclaration': | |
| 65 | result.exports.push({ | |
| 66 | name: '*', | |
| 67 | from: node.source ? node.source.value : null | |
| 68 | }) | |
| 69 | break | |
| 70 | ||
| 71 | case 'ClassDeclaration': | |
| 72 | if (node.id) { | |
| 73 | result.classes.push(extractClass(node, commentMap)) | |
| 74 | } | |
| 75 | break | |
| 76 | ||
| 77 | case 'FunctionDeclaration': | |
| 78 | if (node.id) { | |
| 79 | result.functions.push(extractFunction(node, commentMap)) | |
| 80 | } | |
| 81 | break | |
| 82 | ||
| 83 | case 'VariableDeclaration': | |
| 84 | extractConstants(node, result, commentMap) | |
| 85 | break | |
| 86 | ||
| 87 | // CJS: module.exports = ... | |
| 88 | case 'ExpressionStatement': | |
| 89 | extractCJSExport(node, result, commentMap) | |
| 90 | break | |
| 91 | } | |
| 92 | } | |
| 93 | ||
| 94 | // Walk full AST for state, errors, delegation | |
| 95 | walkDeep(ast, result) | |
| 96 | ||
| 97 | return result | |
| 98 | } | |
| 99 | ||
| 100 | // --- Comment mapping --- | |
| 101 | ||
| 102 | function buildCommentMap (comments) { | |
| 103 | // Map: endLine -> comment text (for block comments / JSDoc) | |
| 104 | const map = [] | |
| 105 | for (const c of comments) { | |
| 106 | if (c.type === 'Block' && c.value.startsWith('*')) { | |
| 107 | map.push({ | |
| 108 | text: '/*' + c.value + '*/', | |
| 109 | endLine: c.loc.end.line, | |
| 110 | start: c.start, | |
| 111 | end: c.end | |
| 112 | }) | |
| 113 | } | |
| 114 | } | |
| 115 | return map | |
| 116 | } | |
| 117 | ||
| 118 | function findJSDoc (commentMap, node) { | |
| 119 | if (!node.loc) return null | |
| 120 | const nodeLine = node.loc.start.line | |
| 121 | for (const c of commentMap) { | |
| 122 | // JSDoc comment ends on the line before or same line as the node | |
| 123 | if (c.endLine >= nodeLine - 2 && c.endLine < nodeLine) { | |
| 124 | return c.text | |
| 125 | } | |
| 126 | } | |
| 127 | return null | |
| 128 | } | |
| 129 | ||
| 130 | // --- Import extraction --- | |
| 131 | ||
| 132 | function extractImport (node) { | |
| 133 | const result = { | |
| 134 | specifier: node.source.value, | |
| 135 | names: [] | |
| 136 | } | |
| 137 | for (const spec of node.specifiers) { | |
| 138 | switch (spec.type) { | |
| 139 | case 'ImportSpecifier': | |
| 140 | result.names.push(spec.imported.name) | |
| 141 | break | |
| 142 | case 'ImportDefaultSpecifier': | |
| 143 | result.names.push(spec.local.name) | |
| 144 | break | |
| 145 | case 'ImportNamespaceSpecifier': | |
| 146 | result.names.push('* as ' + spec.local.name) | |
| 147 | break | |
| 148 | } | |
| 149 | } | |
| 150 | return result | |
| 151 | } | |
| 152 | ||
| 153 | // --- Export extraction --- | |
| 154 | ||
| 155 | function extractNamedExport (node, result, commentMap) { | |
| 156 | // Re-export: export { X } from './file.js' | |
| 157 | if (node.source) { | |
| 158 | for (const spec of node.specifiers) { | |
| 159 | result.exports.push({ | |
| 160 | name: spec.exported.name || spec.exported.value, | |
| 161 | from: node.source.value | |
| 162 | }) | |
| 163 | } | |
| 164 | return | |
| 165 | } | |
| 166 | ||
| 167 | // export class X { ... } | |
| 168 | if (node.declaration) { | |
| 169 | const decl = node.declaration | |
| 170 | switch (decl.type) { | |
| 171 | case 'ClassDeclaration': { | |
| 172 | const cls = extractClass(decl, commentMap) | |
| 173 | result.classes.push(cls) | |
| 174 | result.exports.push({ name: cls.name, type: 'class' }) | |
| 175 | break | |
| 176 | } | |
| 177 | case 'FunctionDeclaration': { | |
| 178 | const fn = extractFunction(decl, commentMap) | |
| 179 | result.functions.push(fn) | |
| 180 | result.exports.push({ name: fn.name, type: 'function' }) | |
| 181 | break | |
| 182 | } | |
| 183 | case 'VariableDeclaration': { | |
| 184 | extractConstants(decl, result, commentMap) | |
| 185 | for (const d of decl.declarations) { | |
| 186 | if (d.id && d.id.name) { | |
| 187 | result.exports.push({ name: d.id.name, type: 'const' }) | |
| 188 | } | |
| 189 | } | |
| 190 | break | |
| 191 | } | |
| 192 | } | |
| 193 | return | |
| 194 | } | |
| 195 | ||
| 196 | // export { X, Y } | |
| 197 | for (const spec of node.specifiers) { | |
| 198 | result.exports.push({ | |
| 199 | name: spec.exported.name || spec.exported.value | |
| 200 | }) | |
| 201 | } | |
| 202 | } | |
| 203 | ||
| 204 | function extractDefaultExport (node, result, commentMap) { | |
| 205 | const decl = node.declaration | |
| 206 | if (decl.type === 'ClassDeclaration' && decl.id) { | |
| 207 | const cls = extractClass(decl, commentMap) | |
| 208 | result.classes.push(cls) | |
| 209 | result.exports.push({ name: 'default', type: 'class', localName: cls.name }) | |
| 210 | } else if (decl.type === 'FunctionDeclaration' && decl.id) { | |
| 211 | const fn = extractFunction(decl, commentMap) | |
| 212 | result.functions.push(fn) | |
| 213 | result.exports.push({ name: 'default', type: 'function', localName: fn.name }) | |
| 214 | } else { | |
| 215 | result.exports.push({ name: 'default', type: decl.type }) | |
| 216 | } | |
| 217 | } | |
| 218 | ||
| 219 | function extractCJSExport (node, result, commentMap) { | |
| 220 | const expr = node.expression | |
| 221 | if (!expr || expr.type !== 'AssignmentExpression') return | |
| 222 | ||
| 223 | const left = expr.left | |
| 224 | if (!left || left.type !== 'MemberExpression') return | |
| 225 | ||
| 226 | // module.exports = class X { ... } | |
| 227 | const isModuleExports = left.object && | |
| 228 | left.object.name === 'module' && | |
| 229 | left.property && left.property.name === 'exports' | |
| 230 | ||
| 231 | // exports.X = ... | |
| 232 | const isExportsProp = left.object && | |
| 233 | left.object.name === 'exports' && | |
| 234 | left.property | |
| 235 | ||
| 236 | if (isModuleExports) { | |
| 237 | const right = expr.right | |
| 238 | if (right.type === 'ClassExpression' || right.type === 'ClassDeclaration') { | |
| 239 | const cls = extractClass(right, commentMap) | |
| 240 | result.classes.push(cls) | |
| 241 | result.exports.push({ name: 'default', type: 'class', localName: cls.name, cjs: true }) | |
| 242 | } else if (right.type === 'FunctionExpression' || right.type === 'FunctionDeclaration') { | |
| 243 | const fn = extractFunction(right, commentMap) | |
| 244 | result.functions.push(fn) | |
| 245 | result.exports.push({ name: 'default', type: 'function', localName: fn.name, cjs: true }) | |
| 246 | } else { | |
| 247 | result.exports.push({ name: 'default', type: right.type, cjs: true }) | |
| 248 | } | |
| 249 | } else if (isExportsProp) { | |
| 250 | const name = left.property.name || left.property.value | |
| 251 | result.exports.push({ name, cjs: true }) | |
| 252 | } | |
| 253 | } | |
| 254 | ||
| 255 | // --- Class extraction --- | |
| 256 | ||
| 257 | function extractClass (node, commentMap) { | |
| 258 | const cls = { | |
| 259 | name: node.id ? node.id.name : '(anonymous)', | |
| 260 | extends: node.superClass ? nodeToString(node.superClass) : null, | |
| 261 | line: node.loc ? node.loc.start.line : null, | |
| 262 | constructor: null, | |
| 263 | methods: [], | |
| 264 | getters: [], | |
| 265 | staticMethods: [], | |
| 266 | jsdoc: findJSDoc(commentMap, node) | |
| 267 | } | |
| 268 | ||
| 269 | if (!node.body || !node.body.body) return cls | |
| 270 | ||
| 271 | for (const member of node.body.body) { | |
| 272 | if (member.type === 'MethodDefinition') { | |
| 273 | const name = member.key.name || member.key.value || '(computed)' | |
| 274 | const jsdoc = findJSDoc(commentMap, member) | |
| 275 | ||
| 276 | if (member.kind === 'constructor') { | |
| 277 | cls.constructor = { | |
| 278 | params: extractParams(member.value.params), | |
| 279 | line: member.loc ? member.loc.start.line : null, | |
| 280 | jsdoc | |
| 281 | } | |
| 282 | } else if (member.kind === 'get') { | |
| 283 | cls.getters.push({ name, static: member.static || false, line: member.loc ? member.loc.start.line : null }) | |
| 284 | } else if (member.kind === 'set') { | |
| 285 | cls.getters.push({ name, kind: 'set', static: member.static || false }) | |
| 286 | } else if (member.static) { | |
| 287 | cls.staticMethods.push({ | |
| 288 | name, | |
| 289 | params: extractParams(member.value.params), | |
| 290 | async: member.value.async || false, | |
| 291 | line: member.loc ? member.loc.start.line : null, | |
| 292 | jsdoc | |
| 293 | }) | |
| 294 | } else { | |
| 295 | cls.methods.push({ | |
| 296 | name, | |
| 297 | params: extractParams(member.value.params), | |
| 298 | async: member.value.async || false, | |
| 299 | generator: member.value.generator || false, | |
| 300 | line: member.loc ? member.loc.start.line : null, | |
| 301 | jsdoc | |
| 302 | }) | |
| 303 | } | |
| 304 | } else if (member.type === 'PropertyDefinition') { | |
| 305 | // Class fields (public or private) | |
| 306 | const name = member.key.name || member.key.value || '(computed)' | |
| 307 | cls.methods.push({ | |
| 308 | name, | |
| 309 | kind: 'field', | |
| 310 | static: member.static || false | |
| 311 | }) | |
| 312 | } | |
| 313 | } | |
| 314 | ||
| 315 | return cls | |
| 316 | } | |
| 317 | ||
| 318 | // --- Function extraction --- | |
| 319 | ||
| 320 | function extractFunction (node, commentMap) { | |
| 321 | return { | |
| 322 | name: node.id ? node.id.name : '(anonymous)', | |
| 323 | params: extractParams(node.params), | |
| 324 | async: node.async || false, | |
| 325 | generator: node.generator || false, | |
| 326 | line: node.loc ? node.loc.start.line : null, | |
| 327 | jsdoc: findJSDoc(commentMap, node) | |
| 328 | } | |
| 329 | } | |
| 330 | ||
| 331 | // --- Constants --- | |
| 332 | ||
| 333 | function extractConstants (node, result, commentMap) { | |
| 334 | for (const decl of node.declarations) { | |
| 335 | if (!decl.id) continue | |
| 336 | ||
| 337 | if (decl.id.type === 'Identifier') { | |
| 338 | const entry = { | |
| 339 | name: decl.id.name, | |
| 340 | kind: node.kind, | |
| 341 | jsdoc: findJSDoc(commentMap, node) | |
| 342 | } | |
| 343 | ||
| 344 | // If the init is a class or function, extract it | |
| 345 | if (decl.init) { | |
| 346 | if (decl.init.type === 'ClassExpression') { | |
| 347 | const cls = extractClass(decl.init, commentMap) | |
| 348 | cls.name = cls.name === '(anonymous)' ? decl.id.name : cls.name | |
| 349 | result.classes.push(cls) | |
| 350 | entry.type = 'class' | |
| 351 | } else if (decl.init.type === 'ArrowFunctionExpression' || decl.init.type === 'FunctionExpression') { | |
| 352 | result.functions.push({ | |
| 353 | name: decl.id.name, | |
| 354 | params: extractParams(decl.init.params), | |
| 355 | async: decl.init.async || false, | |
| 356 | generator: decl.init.generator || false, | |
| 357 | arrow: decl.init.type === 'ArrowFunctionExpression', | |
| 358 | jsdoc: findJSDoc(commentMap, node) | |
| 359 | }) | |
| 360 | entry.type = 'function' | |
| 361 | } | |
| 362 | } | |
| 363 | ||
| 364 | result.constants.push(entry) | |
| 365 | } | |
| 366 | } | |
| 367 | } | |
| 368 | ||
| 369 | // --- Deep walk for state, errors, delegation --- | |
| 370 | ||
| 371 | function walkDeep (ast, result) { | |
| 372 | const stateFields = new Set() | |
| 373 | const delegateCalls = new Map() // field -> Set of methods | |
| 374 | const errors = [] | |
| 375 | ||
| 376 | walk(ast, (node) => { | |
| 377 | // this._field = ... (in constructor or methods) | |
| 378 | if ( | |
| 379 | node.type === 'AssignmentExpression' && | |
| 380 | node.left.type === 'MemberExpression' && | |
| 381 | node.left.object.type === 'ThisExpression' && | |
| 382 | node.left.property.type === 'Identifier' && | |
| 383 | node.left.property.name.startsWith('_') | |
| 384 | ) { | |
| 385 | stateFields.add(node.left.property.name) | |
| 386 | } | |
| 387 | ||
| 388 | // throw new Error('...') | |
| 389 | if ( | |
| 390 | node.type === 'ThrowStatement' && | |
| 391 | node.argument && | |
| 392 | node.argument.type === 'NewExpression' && | |
| 393 | node.argument.callee && | |
| 394 | node.argument.callee.name === 'Error' && | |
| 395 | node.argument.arguments.length > 0 | |
| 396 | ) { | |
| 397 | const arg = node.argument.arguments[0] | |
| 398 | if (arg.type === 'Literal') { | |
| 399 | errors.push(arg.value) | |
| 400 | } else if (arg.type === 'TemplateLiteral') { | |
| 401 | errors.push(templateToPattern(arg)) | |
| 402 | } | |
| 403 | } | |
| 404 | ||
| 405 | // this._field.method() — delegation | |
| 406 | if ( | |
| 407 | node.type === 'CallExpression' && | |
| 408 | node.callee.type === 'MemberExpression' && | |
| 409 | node.callee.object.type === 'MemberExpression' && | |
| 410 | node.callee.object.object.type === 'ThisExpression' && | |
| 411 | node.callee.object.property.type === 'Identifier' && | |
| 412 | node.callee.object.property.name.startsWith('_') && | |
| 413 | node.callee.property.type === 'Identifier' | |
| 414 | ) { | |
| 415 | const field = node.callee.object.property.name | |
| 416 | const method = node.callee.property.name | |
| 417 | if (!delegateCalls.has(field)) delegateCalls.set(field, new Set()) | |
| 418 | delegateCalls.get(field).add(method) | |
| 419 | } | |
| 420 | }) | |
| 421 | ||
| 422 | result.state = Array.from(stateFields) | |
| 423 | result.errorContracts = errors | |
| 424 | ||
| 425 | for (const [field, methods] of delegateCalls) { | |
| 426 | result.delegates.push({ | |
| 427 | field, | |
| 428 | methods: Array.from(methods) | |
| 429 | }) | |
| 430 | } | |
| 431 | } | |
| 432 | ||
| 433 | // --- Helpers --- | |
| 434 | ||
| 435 | function extractParams (params) { | |
| 436 | return params.map(paramToString) | |
| 437 | } | |
| 438 | ||
| 439 | function paramToString (param) { | |
| 440 | switch (param.type) { | |
| 441 | case 'Identifier': | |
| 442 | return param.name | |
| 443 | case 'AssignmentPattern': | |
| 444 | return paramToString(param.left) | |
| 445 | case 'RestElement': | |
| 446 | return '...' + paramToString(param.argument) | |
| 447 | case 'ObjectPattern': | |
| 448 | return '{ ' + param.properties.map(p => { | |
| 449 | if (p.type === 'RestElement') return '...' + paramToString(p.argument) | |
| 450 | return p.key.name || p.key.value || '(computed)' | |
| 451 | }).join(', ') + ' }' | |
| 452 | case 'ArrayPattern': | |
| 453 | return '[' + param.elements.map(e => e ? paramToString(e) : '').join(', ') + ']' | |
| 454 | default: | |
| 455 | return '(?)' | |
| 456 | } | |
| 457 | } | |
| 458 | ||
| 459 | function nodeToString (node) { | |
| 460 | if (node.type === 'Identifier') return node.name | |
| 461 | if (node.type === 'MemberExpression') { | |
| 462 | return nodeToString(node.object) + '.' + (node.property.name || node.property.value) | |
| 463 | } | |
| 464 | return '(?)' | |
| 465 | } | |
| 466 | ||
| 467 | function templateToPattern (node) { | |
| 468 | let out = '' | |
| 469 | for (let i = 0; i < node.quasis.length; i++) { | |
| 470 | out += node.quasis[i].value.raw | |
| 471 | if (i < node.expressions.length) { | |
| 472 | out += '${...}' | |
| 473 | } | |
| 474 | } | |
| 475 | return out | |
| 476 | } | |
| 477 | ||
| 478 | function walk (node, fn) { | |
| 479 | if (!node || typeof node !== 'object') return | |
| 480 | fn(node) | |
| 481 | for (const key of Object.keys(node)) { | |
| 482 | const val = node[key] | |
| 483 | if (Array.isArray(val)) { | |
| 484 | for (const child of val) { | |
| 485 | if (child && typeof child.type === 'string') walk(child, fn) | |
| 486 | } | |
| 487 | } else if (val && typeof val.type === 'string') { | |
| 488 | walk(val, fn) | |
| 489 | } | |
| 490 | } | |
| 491 | } |
| … | … | @@ -0,0 +1,110 @@ |
| 1 | /** | |
| 2 | * MetricsReducer — subscribes to scan-stream events and records counts + timing | |
| 3 | * derived purely from event timestamps at boundaries. No setInterval, no sampling. | |
| 4 | * | |
| 5 | * Attach alongside TreeReducer to profile a scan without touching the scan code. | |
| 6 | */ | |
| 7 | export class MetricsReducer { | |
| 8 | constructor () { | |
| 9 | this.scanStart = null | |
| 10 | this.scanEnd = null | |
| 11 | this.moduleCount = 0 | |
| 12 | this.fileCount = 0 | |
| 13 | this.parseCount = 0 | |
| 14 | this.parseErrors = 0 | |
| 15 | this.importEdges = 0 | |
| 16 | this.implicitEdges = 0 | |
| 17 | this.moduleTimings = [] // [{ name, startedAt, endedAt, duration }] | |
| 18 | this._currentModule = null | |
| 19 | this.bytesRead = 0 | |
| 20 | this.largestFile = { path: null, size: 0 } | |
| 21 | this.filesByExt = {} // ext -> count | |
| 22 | this.parseTimeTotal = 0 // sum of time between file-discovered and file-parsed for the SAME file | |
| 23 | this._pendingParse = new Map() // relPath -> discoveredAt | |
| 24 | this.parseDurations = [] // per-file parse durations (ms) for percentiles | |
| 25 | } | |
| 26 | ||
| 27 | attach (emitter) { | |
| 28 | emitter.on('scan-start', () => { this.scanStart = Date.now() }) | |
| 29 | emitter.on('module-start', e => { | |
| 30 | this.moduleCount++ | |
| 31 | this._currentModule = { name: e.name, startedAt: Date.now() } | |
| 32 | }) | |
| 33 | emitter.on('file-discovered', e => { | |
| 34 | this.fileCount++ | |
| 35 | this.bytesRead += e.size | |
| 36 | if (e.size > this.largestFile.size) { | |
| 37 | this.largestFile = { path: e.relPath, size: e.size } | |
| 38 | } | |
| 39 | const dotIdx = e.relInPkg.lastIndexOf('.') | |
| 40 | const ext = dotIdx > 0 ? e.relInPkg.slice(dotIdx) : '(none)' | |
| 41 | this.filesByExt[ext] = (this.filesByExt[ext] || 0) + 1 | |
| 42 | this._pendingParse.set(e.relPath, Date.now()) | |
| 43 | }) | |
| 44 | emitter.on('file-parsed', e => { | |
| 45 | this.parseCount++ | |
| 46 | if (e.parsed && e.parsed.error) this.parseErrors++ | |
| 47 | const startedAt = this._pendingParse.get(e.relPath) | |
| 48 | if (startedAt) { | |
| 49 | const dur = Date.now() - startedAt | |
| 50 | this.parseTimeTotal += dur | |
| 51 | this.parseDurations.push(dur) | |
| 52 | this._pendingParse.delete(e.relPath) | |
| 53 | } | |
| 54 | }) | |
| 55 | emitter.on('import-edge', e => { | |
| 56 | this.importEdges++ | |
| 57 | if (e.implicit) this.implicitEdges++ | |
| 58 | }) | |
| 59 | emitter.on('module-end', () => { | |
| 60 | if (this._currentModule) { | |
| 61 | const endedAt = Date.now() | |
| 62 | this.moduleTimings.push({ | |
| 63 | name: this._currentModule.name, | |
| 64 | startedAt: this._currentModule.startedAt, | |
| 65 | endedAt, | |
| 66 | duration: endedAt - this._currentModule.startedAt | |
| 67 | }) | |
| 68 | this._currentModule = null | |
| 69 | } | |
| 70 | }) | |
| 71 | emitter.on('scan-end', () => { this.scanEnd = Date.now() }) | |
| 72 | return this | |
| 73 | } | |
| 74 | ||
| 75 | report () { | |
| 76 | const duration = this.scanEnd - this.scanStart | |
| 77 | const slowestModules = [...this.moduleTimings] | |
| 78 | .sort((a, b) => b.duration - a.duration) | |
| 79 | .slice(0, 5) | |
| 80 | ||
| 81 | const sortedParses = [...this.parseDurations].sort((a, b) => a - b) | |
| 82 | const p50 = sortedParses[Math.floor(sortedParses.length * 0.5)] || 0 | |
| 83 | const p95 = sortedParses[Math.floor(sortedParses.length * 0.95)] || 0 | |
| 84 | const p99 = sortedParses[Math.floor(sortedParses.length * 0.99)] || 0 | |
| 85 | ||
| 86 | const topExts = Object.entries(this.filesByExt) | |
| 87 | .sort((a, b) => b[1] - a[1]) | |
| 88 | .slice(0, 10) | |
| 89 | ||
| 90 | return { | |
| 91 | totalDuration: duration, | |
| 92 | moduleCount: this.moduleCount, | |
| 93 | fileCount: this.fileCount, | |
| 94 | parseCount: this.parseCount, | |
| 95 | parseErrors: this.parseErrors, | |
| 96 | importEdges: this.importEdges, | |
| 97 | implicitEdges: this.implicitEdges, | |
| 98 | bytesRead: this.bytesRead, | |
| 99 | largestFile: this.largestFile, | |
| 100 | parseTimeP50: p50, | |
| 101 | parseTimeP95: p95, | |
| 102 | parseTimeP99: p99, | |
| 103 | parseTimeTotal: this.parseTimeTotal, | |
| 104 | throughputFilesPerSec: (this.fileCount * 1000 / duration).toFixed(1), | |
| 105 | throughputMBPerSec: ((this.bytesRead / 1024 / 1024) * 1000 / duration).toFixed(1), | |
| 106 | slowestModules, | |
| 107 | topExtensions: topExts | |
| 108 | } | |
| 109 | } | |
| 110 | } |
| … | … | @@ -0,0 +1,109 @@ |
| 1 | /** | |
| 2 | * TreeReducer — subscribes to scan-stream events and builds the same graph | |
| 3 | * structure that walkGraph() used to return synchronously. | |
| 4 | * | |
| 5 | * Stateful. Apply events in order. Call .finalize() after scan-end to get | |
| 6 | * the same shape as before: { modules, files, root, dirTree, projectType, | |
| 7 | * languages, resolutionContext }. | |
| 8 | * | |
| 9 | * Each reducer is a single subscriber — different reducers (doc-cruft, | |
| 10 | * metrics, UI updaters) can listen to the same event source in parallel. | |
| 11 | */ | |
| 12 | export class TreeReducer { | |
| 13 | constructor () { | |
| 14 | this.root = null | |
| 15 | this.projectType = null | |
| 16 | this.languages = [] | |
| 17 | this.resolutionContext = null | |
| 18 | this.modules = new Map() // modName -> mod | |
| 19 | this.files = new Map() // rootRelPath -> fileInfo | |
| 20 | this.dirTree = null | |
| 21 | } | |
| 22 | ||
| 23 | /** Attach this reducer to a scan-stream emitter. */ | |
| 24 | attach (emitter) { | |
| 25 | emitter.on('scan-start', e => this.onScanStart(e)) | |
| 26 | emitter.on('module-start', e => this.onModuleStart(e)) | |
| 27 | emitter.on('file-discovered', e => this.onFileDiscovered(e)) | |
| 28 | emitter.on('file-parsed', e => this.onFileParsed(e)) | |
| 29 | emitter.on('import-edge', e => this.onImportEdge(e)) | |
| 30 | emitter.on('scan-end', e => this.onScanEnd(e)) | |
| 31 | return this | |
| 32 | } | |
| 33 | ||
| 34 | onScanStart (e) { | |
| 35 | this.root = e.root | |
| 36 | this.projectType = e.projectType | |
| 37 | this.languages = e.languages | |
| 38 | this.resolutionContext = e.resolutionContext | |
| 39 | } | |
| 40 | ||
| 41 | onModuleStart (e) { | |
| 42 | this.modules.set(e.name, { | |
| 43 | name: e.name, | |
| 44 | version: e.version, | |
| 45 | path: e.path, | |
| 46 | absPath: e.absPath, | |
| 47 | entry: e.entry, | |
| 48 | dependencies: e.dependencies, | |
| 49 | devDependencies: e.devDependencies, | |
| 50 | importMaps: e.importMaps, | |
| 51 | testCommand: e.testCommand, | |
| 52 | type: e.type, | |
| 53 | projectType: e.projectType, | |
| 54 | files: new Map() | |
| 55 | }) | |
| 56 | } | |
| 57 | ||
| 58 | onFileDiscovered (e) { | |
| 59 | // Intentionally NOT retaining e.source. That was the main memory leak that | |
| 60 | // OOM'd recursive scans. Downstream consumers can re-read from absPath | |
| 61 | // via /api/file if they actually need the bytes. | |
| 62 | const fileInfo = { | |
| 63 | absPath: e.absPath, | |
| 64 | relPath: e.relPath, | |
| 65 | relInPkg: e.relInPkg, | |
| 66 | size: e.size, | |
| 67 | localImports: [], | |
| 68 | parsed: null // filled by onFileParsed | |
| 69 | } | |
| 70 | this.files.set(e.relPath, fileInfo) | |
| 71 | const mod = this.modules.get(e.modName) | |
| 72 | if (mod) mod.files.set(e.relInPkg, fileInfo) | |
| 73 | } | |
| 74 | ||
| 75 | onFileParsed (e) { | |
| 76 | const mod = this.modules.get(e.modName) | |
| 77 | if (!mod) return | |
| 78 | const file = mod.files.get(e.relInPkg) | |
| 79 | if (!file) return | |
| 80 | file.parsed = e.parsed | |
| 81 | } | |
| 82 | ||
| 83 | onImportEdge (e) { | |
| 84 | const mod = this.modules.get(e.modName) | |
| 85 | if (!mod) return | |
| 86 | const file = mod.files.get(e.fromRelInPkg) | |
| 87 | if (!file) return | |
| 88 | const edge = { specifier: e.specifier, resolved: e.resolvedRelPath } | |
| 89 | if (e.implicit) edge.implicit = true | |
| 90 | file.localImports.push(edge) | |
| 91 | } | |
| 92 | ||
| 93 | onScanEnd (e) { | |
| 94 | this.dirTree = e.dirTree | |
| 95 | } | |
| 96 | ||
| 97 | /** Return the graph in the shape walkGraph() used to produce. */ | |
| 98 | finalize () { | |
| 99 | return { | |
| 100 | modules: this.modules, | |
| 101 | files: this.files, | |
| 102 | root: this.root, | |
| 103 | dirTree: this.dirTree, | |
| 104 | projectType: this.projectType, | |
| 105 | languages: this.languages, | |
| 106 | resolutionContext: this.resolutionContext | |
| 107 | } | |
| 108 | } | |
| 109 | } |
| … | … | @@ -0,0 +1,3525 @@ |
| 1 | export function renderPage (tree, prefix) { | |
| 2 | const treeJSON = JSON.stringify(tree) | |
| 3 | const apiPrefix = prefix || '' | |
| 4 | ||
| 5 | return `<!DOCTYPE html> | |
| 6 | <html lang="en"> | |
| 7 | <head> | |
| 8 | <meta charset="utf-8"> | |
| 9 | <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| 10 | <title>codetree — ${tree.system.modules.length} modules</title> | |
| 11 | <style> | |
| 12 | * { margin: 0; padding: 0; box-sizing: border-box; } | |
| 13 | body { | |
| 14 | font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace; | |
| 15 | font-size: 13px; | |
| 16 | line-height: 1.5; | |
| 17 | background: #0d1117; | |
| 18 | color: #c9d1d9; | |
| 19 | } | |
| 20 | #app { display: flex; height: 100vh; } | |
| 21 | ||
| 22 | /* Resizable panels */ | |
| 23 | .panel { | |
| 24 | overflow-y: auto; | |
| 25 | flex-shrink: 0; | |
| 26 | position: relative; | |
| 27 | min-width: 100px; | |
| 28 | } | |
| 29 | .resize-handle { | |
| 30 | width: 6px; | |
| 31 | height: 100%; | |
| 32 | cursor: col-resize; | |
| 33 | z-index: 30; | |
| 34 | background: #21262d; | |
| 35 | flex-shrink: 0; | |
| 36 | transition: background 0.15s; | |
| 37 | } | |
| 38 | .resize-handle:hover, .resize-handle.dragging { | |
| 39 | background: #58a6ff; | |
| 40 | } | |
| 41 | ||
| 42 | #sidebar { | |
| 43 | width: 340px; | |
| 44 | border-right: 1px solid #21262d; | |
| 45 | padding: 12px; | |
| 46 | padding-right: 16px; /* extra space so scrollbar doesn't cover resize handle */ | |
| 47 | overflow-y: auto; | |
| 48 | overflow-x: hidden; | |
| 49 | } | |
| 50 | #sidebar::-webkit-scrollbar { width: 6px; } | |
| 51 | #sidebar::-webkit-scrollbar-track { background: transparent; } | |
| 52 | #sidebar::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; } | |
| 53 | #sidebar::-webkit-scrollbar-thumb:hover { background: #484f58; } | |
| 54 | #main { | |
| 55 | flex: 1; | |
| 56 | overflow-y: auto; | |
| 57 | padding: 16px 24px; | |
| 58 | position: relative; | |
| 59 | min-width: 200px; | |
| 60 | } | |
| 61 | #right-panel { | |
| 62 | width: 360px; | |
| 63 | border-left: 1px solid #21262d; | |
| 64 | padding: 12px; | |
| 65 | padding-left: 16px; | |
| 66 | overflow-y: auto; | |
| 67 | overflow-x: hidden; | |
| 68 | display: none; | |
| 69 | } | |
| 70 | #right-panel.active { display: block; } | |
| 71 | #right-panel::-webkit-scrollbar { width: 6px; } | |
| 72 | #right-panel::-webkit-scrollbar-track { background: transparent; } | |
| 73 | #right-panel::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; } | |
| 74 | #right-panel::-webkit-scrollbar-thumb:hover { background: #484f58; } | |
| 75 | #right-panel h2 { font-size: 14px; color: #58a6ff; margin-bottom: 8px; } | |
| 76 | .val-summary { | |
| 77 | display: flex; gap: 12px; margin-bottom: 12px; padding: 8px; | |
| 78 | background: #161b22; border-radius: 6px; font-size: 12px; | |
| 79 | } | |
| 80 | .val-pass { color: #3fb950; } | |
| 81 | .val-fail { color: #ff7b72; } | |
| 82 | .val-warn { color: #d29922; } | |
| 83 | .val-count { font-weight: bold; font-size: 16px; display: block; } | |
| 84 | .val-check { | |
| 85 | padding: 6px 8px; | |
| 86 | margin: 2px 0; | |
| 87 | border-radius: 4px; | |
| 88 | font-size: 11px; | |
| 89 | line-height: 1.4; | |
| 90 | border-left: 3px solid transparent; | |
| 91 | } | |
| 92 | .val-check.pass { border-left-color: #3fb950; background: #0d1f12; } | |
| 93 | .val-check.fail { border-left-color: #ff7b72; background: #2d1014; } | |
| 94 | .val-check.warn { border-left-color: #d29922; background: #2d2200; } | |
| 95 | .val-check .val-claim { color: #c9d1d9; } | |
| 96 | .val-check .val-detail { color: #8b949e; font-size: 10px; margin-top: 2px; } | |
| 97 | .val-check .val-icon { margin-right: 4px; } | |
| 98 | .val-section { margin-top: 12px; } | |
| 99 | .val-section h3 { | |
| 100 | font-size: 12px; color: #8b949e; margin-bottom: 4px; | |
| 101 | text-transform: uppercase; letter-spacing: 0.5px; | |
| 102 | } | |
| 103 | .val-toggle { | |
| 104 | font-size: 11px; color: #58a6ff; cursor: pointer; float: right; | |
| 105 | } | |
| 106 | .val-filter { display: flex; gap: 4px; margin-bottom: 8px; } | |
| 107 | .val-filter button { | |
| 108 | font-size: 10px; padding: 2px 8px; border-radius: 4px; cursor: pointer; | |
| 109 | font-family: inherit; border: 1px solid #30363d; background: #161b22; color: #8b949e; | |
| 110 | } | |
| 111 | .val-filter button.active { border-color: #58a6ff; color: #58a6ff; } | |
| 112 | ||
| 113 | /* File viewer */ | |
| 114 | .file-viewer { | |
| 115 | background: #0d1117; | |
| 116 | border: 1px solid #21262d; | |
| 117 | border-radius: 6px; | |
| 118 | overflow: auto; | |
| 119 | max-height: calc(100vh - 120px); | |
| 120 | font-size: 12px; | |
| 121 | line-height: 1.6; | |
| 122 | margin-top: 8px; | |
| 123 | } | |
| 124 | #right-panel .file-viewer { | |
| 125 | max-height: calc(100vh - 100px); | |
| 126 | } | |
| 127 | .file-viewer table { border-collapse: collapse; width: 100%; } | |
| 128 | .file-viewer tr:hover { background: #161b22; } | |
| 129 | .file-viewer tr.highlight { background: #1a2a3a; } | |
| 130 | .file-viewer tr.highlight .line-no { color: #00e5ff; } | |
| 131 | .file-viewer .line-no { | |
| 132 | padding: 0 12px 0 8px; | |
| 133 | text-align: right; | |
| 134 | color: #484f58; | |
| 135 | user-select: none; | |
| 136 | vertical-align: top; | |
| 137 | white-space: nowrap; | |
| 138 | width: 1px; | |
| 139 | border-right: 1px solid #21262d; | |
| 140 | } | |
| 141 | .file-viewer .line-code { | |
| 142 | padding: 0 8px; | |
| 143 | white-space: pre; | |
| 144 | font-family: 'SF Mono', 'Fira Code', monospace; | |
| 145 | color: #c9d1d9; | |
| 146 | } | |
| 147 | .file-viewer-header { | |
| 148 | display: flex; | |
| 149 | justify-content: space-between; | |
| 150 | align-items: center; | |
| 151 | padding: 6px 12px; | |
| 152 | background: #161b22; | |
| 153 | border-bottom: 1px solid #21262d; | |
| 154 | border-radius: 6px 6px 0 0; | |
| 155 | font-size: 12px; | |
| 156 | } | |
| 157 | .file-viewer-header .fv-path { color: #58a6ff; } | |
| 158 | .file-viewer-header .fv-info { color: #8b949e; } | |
| 159 | ||
| 160 | /* Syntax colors (basic) */ | |
| 161 | .syn-kw { color: #ff7b72; } | |
| 162 | .syn-str { color: #a5d6ff; } | |
| 163 | .syn-num { color: #79c0ff; } | |
| 164 | .syn-cmt { color: #8b949e; font-style: italic; } | |
| 165 | .syn-fn { color: #d2a8ff; } | |
| 166 | .syn-cls { color: #ffa657; } | |
| 167 | h1 { font-size: 16px; color: #58a6ff; margin-bottom: 8px; } | |
| 168 | h2 { font-size: 14px; color: #8b949e; margin-bottom: 6px; font-weight: normal; } | |
| 169 | ||
| 170 | /* Tabs */ | |
| 171 | .tabs { | |
| 172 | display: flex; | |
| 173 | gap: 2px; | |
| 174 | margin-bottom: 10px; | |
| 175 | border-bottom: 1px solid #21262d; | |
| 176 | padding-bottom: 0; | |
| 177 | } | |
| 178 | .tab { | |
| 179 | padding: 5px 14px; | |
| 180 | cursor: pointer; | |
| 181 | color: #8b949e; | |
| 182 | border: 1px solid transparent; | |
| 183 | border-bottom: none; | |
| 184 | border-radius: 6px 6px 0 0; | |
| 185 | font-family: inherit; | |
| 186 | font-size: 12px; | |
| 187 | background: none; | |
| 188 | } | |
| 189 | .tab:hover { color: #c9d1d9; } | |
| 190 | .tab.active { | |
| 191 | color: #c9d1d9; | |
| 192 | background: #161b22; | |
| 193 | border-color: #21262d; | |
| 194 | position: relative; | |
| 195 | } | |
| 196 | .tab.active::after { | |
| 197 | content: ''; | |
| 198 | position: absolute; | |
| 199 | bottom: -1px; | |
| 200 | left: 0; | |
| 201 | right: 0; | |
| 202 | height: 1px; | |
| 203 | background: #161b22; | |
| 204 | } | |
| 205 | .tab-content { display: none; } | |
| 206 | .tab-content.active { display: block; } | |
| 207 | ||
| 208 | .search { | |
| 209 | width: 100%; | |
| 210 | padding: 6px 10px; | |
| 211 | background: #161b22; | |
| 212 | border: 1px solid #30363d; | |
| 213 | border-radius: 6px; | |
| 214 | color: #c9d1d9; | |
| 215 | font-family: inherit; | |
| 216 | font-size: 13px; | |
| 217 | margin-bottom: 12px; | |
| 218 | } | |
| 219 | .search:focus { outline: none; border-color: #58a6ff; } | |
| 220 | ||
| 221 | /* Tree */ | |
| 222 | .tree { list-style: none; } | |
| 223 | .tree ul { list-style: none; padding-left: 16px; } | |
| 224 | .tree li { position: relative; } | |
| 225 | .tree-header { | |
| 226 | display: flex; | |
| 227 | align-items: center; | |
| 228 | gap: 8px; | |
| 229 | padding: 6px 8px; | |
| 230 | border-bottom: 1px solid #21262d; | |
| 231 | background: #161b22; | |
| 232 | position: sticky; | |
| 233 | top: 0; | |
| 234 | z-index: 1; | |
| 235 | } | |
| 236 | .tree-header .tree-up { | |
| 237 | background: #21262d; | |
| 238 | border: 1px solid #30363d; | |
| 239 | color: #c9d1d9; | |
| 240 | cursor: pointer; | |
| 241 | font-family: inherit; | |
| 242 | font-size: 11px; | |
| 243 | padding: 2px 8px; | |
| 244 | border-radius: 3px; | |
| 245 | } | |
| 246 | .tree-header .tree-up:hover { background: #30363d; } | |
| 247 | .tree-header .tree-path { | |
| 248 | color: #8b949e; | |
| 249 | font-size: 11px; | |
| 250 | white-space: nowrap; | |
| 251 | overflow: hidden; | |
| 252 | text-overflow: ellipsis; | |
| 253 | flex: 1; | |
| 254 | } | |
| 255 | .node { | |
| 256 | display: flex; | |
| 257 | align-items: center; | |
| 258 | padding: 2px 4px; | |
| 259 | cursor: pointer; | |
| 260 | border-radius: 4px; | |
| 261 | gap: 6px; | |
| 262 | white-space: nowrap; | |
| 263 | } | |
| 264 | .node:hover { background: #161b22; } | |
| 265 | .node.selected { background: #1f2937; } | |
| 266 | .toggle { | |
| 267 | width: 14px; height: 14px; | |
| 268 | display: inline-flex; align-items: center; justify-content: center; | |
| 269 | color: #484f58; font-size: 10px; flex-shrink: 0; | |
| 270 | } | |
| 271 | .icon { width: 16px; text-align: center; flex-shrink: 0; } | |
| 272 | .name { color: #c9d1d9; } | |
| 273 | .badge { | |
| 274 | font-size: 10px; padding: 0 5px; border-radius: 10px; | |
| 275 | background: #21262d; color: #8b949e; | |
| 276 | } | |
| 277 | .collapsed > ul { display: none; } | |
| 278 | /* Validation badges on nodes */ | |
| 279 | .val-badge { | |
| 280 | font-size: 9px; | |
| 281 | padding: 1px 5px; | |
| 282 | border-radius: 4px; | |
| 283 | margin-left: 3px; | |
| 284 | font-weight: bold; | |
| 285 | } | |
| 286 | .val-badge-fail { background: #ff7b72; color: #0d1117; } | |
| 287 | .val-badge-warn { background: #d29922; color: #0d1117; } | |
| 288 | .val-badge-pass { background: #3fb950; color: #0d1117; } | |
| 289 | .val-badge-none { background: #21262d; color: #8b949e; } | |
| 290 | ||
| 291 | .node.selected-module { | |
| 292 | background: #0a2a3a !important; | |
| 293 | border: 1px solid #00e5ff; | |
| 294 | margin: 1px 0; | |
| 295 | } | |
| 296 | .node.selected-module .name { color: #00e5ff !important; font-weight: bold; } | |
| 297 | .node.selected-module::after { | |
| 298 | content: 'SELECTED'; | |
| 299 | font-size: 9px; | |
| 300 | padding: 1px 5px; | |
| 301 | border-radius: 4px; | |
| 302 | background: #00e5ff; | |
| 303 | color: #0d1117; | |
| 304 | margin-left: 6px; | |
| 305 | font-weight: bold; | |
| 306 | } | |
| 307 | .node.dep-highlight { | |
| 308 | background: #1a3a0a !important; | |
| 309 | border: 1px solid #39ff14; | |
| 310 | margin: 1px 0; | |
| 311 | } | |
| 312 | .node.dep-highlight .name { color: #39ff14 !important; font-weight: bold; } | |
| 313 | .node.dep-highlight::after { | |
| 314 | content: 'DEP'; | |
| 315 | font-size: 9px; | |
| 316 | padding: 1px 5px; | |
| 317 | border-radius: 4px; | |
| 318 | background: #39ff14; | |
| 319 | color: #0d1117; | |
| 320 | margin-left: 6px; | |
| 321 | font-weight: bold; | |
| 322 | } | |
| 323 | .node.used-by-highlight { | |
| 324 | background: #3a3a0a !important; | |
| 325 | border: 1px solid #ffff00; | |
| 326 | margin: 1px 0; | |
| 327 | } | |
| 328 | .node.used-by-highlight .name { color: #ffff00 !important; font-weight: bold; } | |
| 329 | .node.used-by-highlight::after { | |
| 330 | content: 'USES THIS'; | |
| 331 | font-size: 9px; | |
| 332 | padding: 1px 5px; | |
| 333 | border-radius: 4px; | |
| 334 | background: #ffff00; | |
| 335 | color: #0d1117; | |
| 336 | margin-left: 6px; | |
| 337 | font-weight: bold; | |
| 338 | } | |
| 339 | .icon-module { color: #f0883e; } | |
| 340 | .icon-file { color: #8b949e; } | |
| 341 | .icon-class { color: #d2a8ff; } | |
| 342 | .icon-method { color: #79c0ff; } | |
| 343 | .icon-getter { color: #7ee787; } | |
| 344 | .icon-function { color: #79c0ff; } | |
| 345 | .icon-const { color: #ffa657; } | |
| 346 | .icon-export { color: #3fb950; } | |
| 347 | ||
| 348 | /* Detail panel */ | |
| 349 | .detail { margin-bottom: 16px; } | |
| 350 | .detail h3 { | |
| 351 | font-size: 13px; color: #58a6ff; margin-bottom: 4px; | |
| 352 | border-bottom: 1px solid #21262d; padding-bottom: 4px; | |
| 353 | } | |
| 354 | .detail pre { | |
| 355 | background: #161b22; padding: 8px 12px; border-radius: 6px; | |
| 356 | overflow-x: auto; margin: 4px 0 8px; | |
| 357 | } | |
| 358 | .detail code { font-family: inherit; } | |
| 359 | .tag { | |
| 360 | display: inline-block; font-size: 11px; padding: 1px 6px; | |
| 361 | border-radius: 4px; margin: 1px 2px; | |
| 362 | } | |
| 363 | .tag-async { background: #1f3a2d; color: #7ee787; } | |
| 364 | .tag-static { background: #2d1f3a; color: #d2a8ff; } | |
| 365 | .tag-generator { background: #3a2d1f; color: #ffa657; } | |
| 366 | .tag-arrow { background: #1f2d3a; color: #79c0ff; } | |
| 367 | .stats { | |
| 368 | display: flex; gap: 16px; padding: 8px 0; | |
| 369 | border-bottom: 1px solid #21262d; margin-bottom: 12px; | |
| 370 | color: #8b949e; font-size: 12px; | |
| 371 | } | |
| 372 | .stat-value { color: #c9d1d9; font-weight: bold; } | |
| 373 | ||
| 374 | /* Graph */ | |
| 375 | #graph-container { | |
| 376 | position: absolute; | |
| 377 | top: 0; left: 0; right: 0; bottom: 0; | |
| 378 | display: none; | |
| 379 | overflow: hidden; | |
| 380 | } | |
| 381 | #graph-container.active { display: block; } | |
| 382 | #graph-svg { width: 100%; height: 100%; cursor: grab; } | |
| 383 | #graph-svg.dragging { cursor: grabbing; } | |
| 384 | .graph-node { cursor: pointer; } | |
| 385 | .graph-node circle { transition: opacity 0.2s; } | |
| 386 | .graph-node.dimmed circle { opacity: 0.15; } | |
| 387 | .graph-node.dimmed text { opacity: 0.15; } | |
| 388 | .graph-node.focused circle { stroke: #f0883e; stroke-width: 3; filter: drop-shadow(0 0 6px rgba(240,136,62,0.5)); } | |
| 389 | .graph-node text { | |
| 390 | font-family: 'SF Mono', monospace; | |
| 391 | fill: #c9d1d9; | |
| 392 | pointer-events: none; | |
| 393 | } | |
| 394 | .graph-edge { stroke: #30363d; stroke-width: 1.2; fill: none; marker-end: url(#arrowhead); } | |
| 395 | .graph-edge.dimmed { stroke: #161b22; stroke-width: 0.5; } | |
| 396 | .graph-edge.dep-of { stroke: #58a6ff; stroke-width: 2; } | |
| 397 | .graph-edge.depends-on { stroke: #3fb950; stroke-width: 2; } | |
| 398 | .graph-legend { | |
| 399 | position: absolute; | |
| 400 | bottom: 12px; left: 12px; | |
| 401 | background: #161b22; | |
| 402 | border: 1px solid #30363d; | |
| 403 | border-radius: 6px; | |
| 404 | padding: 8px 12px; | |
| 405 | font-size: 11px; | |
| 406 | color: #8b949e; | |
| 407 | pointer-events: none; | |
| 408 | } | |
| 409 | .graph-legend .leg-item { display: flex; align-items: center; gap: 6px; padding: 2px 0; } | |
| 410 | .graph-legend .leg-line { width: 20px; height: 2px; display: inline-block; } | |
| 411 | .graph-controls { | |
| 412 | position: absolute; | |
| 413 | top: 12px; right: 12px; | |
| 414 | display: flex; gap: 4px; | |
| 415 | } | |
| 416 | .graph-controls button { | |
| 417 | background: #161b22; border: 1px solid #30363d; border-radius: 4px; | |
| 418 | color: #c9d1d9; font-size: 14px; width: 28px; height: 28px; | |
| 419 | cursor: pointer; font-family: inherit; display: flex; align-items: center; justify-content: center; | |
| 420 | } | |
| 421 | .graph-controls button:hover { background: #21262d; } | |
| 422 | .graph-tooltip { | |
| 423 | position: absolute; | |
| 424 | background: #161b22; | |
| 425 | border: 1px solid #30363d; | |
| 426 | border-radius: 6px; | |
| 427 | padding: 8px 12px; | |
| 428 | font-size: 12px; | |
| 429 | pointer-events: none; | |
| 430 | display: none; | |
| 431 | z-index: 10; | |
| 432 | max-width: 320px; | |
| 433 | line-height: 1.6; | |
| 434 | } | |
| 435 | .graph-tooltip .tt-deps { color: #58a6ff; } | |
| 436 | .graph-tooltip .tt-used { color: #3fb950; } | |
| 437 | ||
| 438 | /* Graph settings panel */ | |
| 439 | .graph-settings { | |
| 440 | position: absolute; | |
| 441 | bottom: 12px; right: 12px; | |
| 442 | background: #161b22; | |
| 443 | border: 1px solid #30363d; | |
| 444 | border-radius: 6px; | |
| 445 | padding: 10px 14px; | |
| 446 | font-size: 11px; | |
| 447 | color: #8b949e; | |
| 448 | z-index: 5; | |
| 449 | max-width: 240px; | |
| 450 | } | |
| 451 | .graph-settings h4 { color: #c9d1d9; margin-bottom: 6px; font-size: 11px; } | |
| 452 | .gs-row { | |
| 453 | display: flex; align-items: center; gap: 6px; | |
| 454 | padding: 3px 0; | |
| 455 | } | |
| 456 | .gs-row label { flex: 1; cursor: pointer; } | |
| 457 | .gs-row select, .gs-row input[type=range] { | |
| 458 | background: #0d1117; border: 1px solid #30363d; border-radius: 3px; | |
| 459 | color: #c9d1d9; font-size: 10px; padding: 2px 4px; font-family: inherit; | |
| 460 | } | |
| 461 | .gs-row select { width: 100px; } | |
| 462 | .gs-row input[type=range] { width: 80px; accent-color: #58a6ff; } | |
| 463 | .gs-row input[type=checkbox] { accent-color: #58a6ff; } | |
| 464 | .gs-divider { border-top: 1px solid #21262d; margin: 6px 0; } | |
| 465 | ||
| 466 | /* Category regions */ | |
| 467 | .graph-region { | |
| 468 | fill-opacity: 0.12; | |
| 469 | stroke-opacity: 0.5; | |
| 470 | stroke-width: 2; | |
| 471 | } | |
| 472 | .graph-region-label { | |
| 473 | font-size: 14px; | |
| 474 | fill-opacity: 0.9; | |
| 475 | font-weight: bold; | |
| 476 | pointer-events: none; | |
| 477 | text-shadow: 0 0 8px #0d1117, 0 0 16px #0d1117; | |
| 478 | } | |
| 479 | ||
| 480 | /* Edge labels on hover */ | |
| 481 | .edge-hover-label { | |
| 482 | font-size: 9px; | |
| 483 | fill: #58a6ff; | |
| 484 | pointer-events: none; | |
| 485 | display: none; | |
| 486 | } | |
| 487 | .edge-hover-label.visible { display: block; } | |
| 488 | .graph-breadcrumb { | |
| 489 | position: absolute; | |
| 490 | top: 12px; left: 12px; | |
| 491 | display: flex; gap: 4px; align-items: center; | |
| 492 | font-size: 13px; z-index: 5; | |
| 493 | } | |
| 494 | .graph-breadcrumb span { | |
| 495 | color: #8b949e; cursor: pointer; padding: 4px 8px; | |
| 496 | background: #161b22; border: 1px solid #30363d; border-radius: 4px; | |
| 497 | } | |
| 498 | .graph-breadcrumb span:hover { color: #c9d1d9; border-color: #58a6ff; } | |
| 499 | .graph-breadcrumb span.current { color: #00e5ff; border-color: #00e5ff; cursor: default; } | |
| 500 | .graph-breadcrumb .sep { background: none; border: none; color: #484f58; cursor: default; padding: 0; } | |
| 501 | </style> | |
| 502 | </head> | |
| 503 | <body> | |
| 504 | <div id="app"> | |
| 505 | <div id="sidebar" class="panel"> | |
| 506 | <h1 style="display:flex;justify-content:space-between;align-items:center">codetree</h1> | |
| 507 | <div class="tabs"> | |
| 508 | <button class="tab main-tab active" data-tab="tree">Tree</button> | |
| 509 | <button class="tab main-tab" data-tab="graph">Graph</button> | |
| 510 | <button class="tab main-tab" data-tab="validate">Validate</button> | |
| 511 | </div> | |
| 512 | <input class="search" id="search" type="text" placeholder="Filter modules, files, symbols..."> | |
| 513 | <div style="display:flex;gap:4px;margin-bottom:8px"> | |
| 514 | <button style="background:#161b22;border:1px solid #30363d;border-radius:4px;color:#8b949e;font-size:10px;padding:2px 8px;cursor:pointer;font-family:inherit" onclick="expandAll()">Expand All</button> | |
| 515 | <button style="background:#161b22;border:1px solid #30363d;border-radius:4px;color:#8b949e;font-size:10px;padding:2px 8px;cursor:pointer;font-family:inherit" onclick="collapseAll()">Collapse All</button> | |
| 516 | </div> | |
| 517 | <div id="tree-root"></div> | |
| 518 | </div> | |
| 519 | <div id="resize-left" class="resize-handle"></div> | |
| 520 | <div id="main"> | |
| 521 | <div id="detail"> | |
| 522 | <div class="stats" id="stats"></div> | |
| 523 | <div id="detail-content"> | |
| 524 | <h2>Select a node to view details</h2> | |
| 525 | </div> | |
| 526 | </div> | |
| 527 | <div id="graph-container"> | |
| 528 | <svg id="graph-svg"> | |
| 529 | <defs> | |
| 530 | <marker id="arrowhead" viewBox="0 0 10 7" refX="10" refY="3.5" | |
| 531 | markerWidth="8" markerHeight="6" orient="auto-start-reverse"> | |
| 532 | <polygon points="0 0, 10 3.5, 0 7" fill="#30363d" /> | |
| 533 | </marker> | |
| 534 | <marker id="arrowhead-blue" viewBox="0 0 10 7" refX="10" refY="3.5" | |
| 535 | markerWidth="8" markerHeight="6" orient="auto-start-reverse"> | |
| 536 | <polygon points="0 0, 10 3.5, 0 7" fill="#58a6ff" /> | |
| 537 | </marker> | |
| 538 | <marker id="arrowhead-green" viewBox="0 0 10 7" refX="10" refY="3.5" | |
| 539 | markerWidth="8" markerHeight="6" orient="auto-start-reverse"> | |
| 540 | <polygon points="0 0, 10 3.5, 0 7" fill="#3fb950" /> | |
| 541 | </marker> | |
| 542 | </defs> | |
| 543 | </svg> | |
| 544 | <div class="graph-breadcrumb" id="graph-breadcrumb"></div> | |
| 545 | <div class="graph-controls"> | |
| 546 | <button id="zoom-in" title="Zoom in">+</button> | |
| 547 | <button id="zoom-out" title="Zoom out">-</button> | |
| 548 | <button id="zoom-reset" title="Reset view">R</button> | |
| 549 | </div> | |
| 550 | <div class="graph-legend"> | |
| 551 | <div class="leg-item"><span class="leg-line" style="background:#58a6ff"></span> depends on (selected)</div> | |
| 552 | <div class="leg-item"><span class="leg-line" style="background:#3fb950"></span> used by (selected)</div> | |
| 553 | <div class="leg-item"><span class="leg-line" style="background:#30363d"></span> other dependency</div> | |
| 554 | <div style="margin-top:4px; font-size:10px">Click to focus. Double-click to drill in. Scroll to zoom. Drag to pan.</div> | |
| 555 | </div> | |
| 556 | <div class="graph-tooltip" id="graph-tooltip"></div> | |
| 557 | </div> | |
| 558 | </div> | |
| 559 | <div id="resize-right" class="resize-handle" style="display:none"></div> | |
| 560 | <div id="right-panel" class="panel" style="width:360px;border-left:1px solid #21262d;display:none;overflow-y:auto;padding:12px 12px 12px 16px"> | |
| 561 | <div id="right-panel-tabs" style="display:flex;gap:2px;margin-bottom:8px;border-bottom:1px solid #21262d"> | |
| 562 | <button class="tab active" data-rp="structure" onclick="switchRightPanel("structure")">Structure</button> | |
| 563 | <button class="tab" data-rp="validation" onclick="switchRightPanel("validation")">Validation</button> | |
| 564 | <button class="tab" data-rp="docs" onclick="switchRightPanel("docs")">Docs</button> | |
| 565 | </div> | |
| 566 | <div id="rp-structure" style="display:block"> | |
| 567 | <div id="structure-content"><h2 style="color:#8b949e">Select a file to see structure</h2></div> | |
| 568 | </div> | |
| 569 | <div id="rp-validation" style="display:none"> | |
| 570 | <div id="val-content">No validation data.</div> | |
| 571 | </div> | |
| 572 | <div id="rp-docs" style="display:none"> | |
| 573 | <div id="docs-content"><h2 style="color:#8b949e">No spec file for this module</h2></div> | |
| 574 | </div> | |
| 575 | </div> | |
| 576 | </div> | |
| 577 | ||
| 578 | <script> | |
| 579 | const tree = ${treeJSON}; | |
| 580 | const API = '${apiPrefix}'; | |
| 581 | let currentTab = 'tree' | |
| 582 | ||
| 583 | // ====== TAB SWITCHING ====== | |
| 584 | document.querySelectorAll('.main-tab').forEach(tab => { | |
| 585 | tab.addEventListener('click', () => { | |
| 586 | document.querySelectorAll('.main-tab').forEach(t => t.classList.remove('active')) | |
| 587 | tab.classList.add('active') | |
| 588 | currentTab = tab.dataset.tab | |
| 589 | ||
| 590 | const detail = document.getElementById('detail') | |
| 591 | const graphContainer = document.getElementById('graph-container') | |
| 592 | const valPanel = document.getElementById('right-panel') | |
| 593 | ||
| 594 | // In graph mode, hide the detail/file-viewer panel — right panel handles everything | |
| 595 | detail.style.display = currentTab === 'graph' ? 'none' : '' | |
| 596 | graphContainer.classList.toggle('active', currentTab === 'graph') | |
| 597 | ||
| 598 | const rightPanel = document.getElementById('right-panel') | |
| 599 | const resizeRight = document.getElementById('resize-right') | |
| 600 | if (currentTab === 'validate') { | |
| 601 | // Validate tab = open right panel with validation, keep current center view | |
| 602 | rightPanel.style.display = 'block' | |
| 603 | resizeRight.style.display = '' | |
| 604 | if (!valInitialized) initValidation() | |
| 605 | switchRightPanel('validation') | |
| 606 | // Don't change center content — revert to previous tab's center | |
| 607 | detail.style.display = '' | |
| 608 | graphContainer.classList.remove('active') | |
| 609 | } else if (currentTab === 'graph') { | |
| 610 | if (!graphInitialized) { initGraph(); updateBreadcrumb() } | |
| 611 | } | |
| 612 | }) | |
| 613 | }) | |
| 614 | ||
| 615 | // ====== TREE VIEW (File Manager) ====== | |
| 616 | // | |
| 617 | // Flat current-path view. Mirrors the graph: shows ONLY what's at the current | |
| 618 | // location. Click a directory → descend; click a module → focus + show | |
| 619 | // details panel. Stays in sync with the graph (rebuildGraph calls buildTree). | |
| 620 | // | |
| 621 | // The previous implementation built a full nested DOM for every module + every | |
| 622 | // file at page load, which made monorepo-scale scans crawl. This avoids that | |
| 623 | // entirely — at any moment we only have N items in the DOM where N is the | |
| 624 | // number of children at the current path (typically 5-50). | |
| 625 | let selectedTreeNode = null | |
| 626 | ||
| 627 | function buildTree () { | |
| 628 | const root = document.getElementById('tree-root') | |
| 629 | root.innerHTML = '' | |
| 630 | ||
| 631 | if (!tree.dirTree) { | |
| 632 | // No dirTree (e.g. very small scan with no children) — fallback to flat module list. | |
| 633 | const ul = el('ul', { className: 'tree' }) | |
| 634 | for (const name of tree.system.modules) { | |
| 635 | ul.appendChild(buildModuleNode(name, tree.modules[name])) | |
| 636 | } | |
| 637 | root.appendChild(ul) | |
| 638 | updateStats() | |
| 639 | return | |
| 640 | } | |
| 641 | ||
| 642 | const path = (typeof getCurrentPath === 'function') ? getCurrentPath() : '' | |
| 643 | const items = (typeof getNodesAtPath === 'function') | |
| 644 | ? getNodesAtPath(path) | |
| 645 | : tree.dirTree.children.filter(c => c.type !== 'file').map(c => ({ | |
| 646 | name: c.module || c.name, | |
| 647 | type: c.module ? 'module' : 'dir', | |
| 648 | dirEntry: c, | |
| 649 | mod: c.module ? tree.modules[c.module] : null | |
| 650 | })) | |
| 651 | ||
| 652 | // Header: up button + path | |
| 653 | const header = el('div', { className: 'tree-header' }) | |
| 654 | if (path) { | |
| 655 | const upBtn = el('button', { className: 'tree-up', textContent: '↑ ..', title: 'Go up' }) | |
| 656 | upBtn.addEventListener('click', () => navigateGraph(graphStack.length - 1)) | |
| 657 | header.appendChild(upBtn) | |
| 658 | } | |
| 659 | const pathLabel = el('div', { className: 'tree-path' }) | |
| 660 | pathLabel.textContent = path ? '/' + path : '/' | |
| 661 | header.appendChild(pathLabel) | |
| 662 | root.appendChild(header) | |
| 663 | ||
| 664 | // Flat list of items at this path | |
| 665 | const ul = el('ul', { className: 'tree' }) | |
| 666 | for (const item of items) { | |
| 667 | ul.appendChild(buildPathItemNode(item)) | |
| 668 | } | |
| 669 | root.appendChild(ul) | |
| 670 | updateStats() | |
| 671 | ||
| 672 | // Click background to deselect | |
| 673 | root.addEventListener('click', (e) => { | |
| 674 | if (e.target === root || e.target === ul) deselectAll() | |
| 675 | }) | |
| 676 | } | |
| 677 | ||
| 678 | function buildPathItemNode (item) { | |
| 679 | const li = el('li') | |
| 680 | const node = el('div', { className: 'node', 'data-type': item.type, 'data-name': item.name }) | |
| 681 | ||
| 682 | if (item.type === 'dir') { | |
| 683 | node.innerHTML = '<span class="icon" style="color:#8b949e">D</span>' + | |
| 684 | '<span class="name" style="color:#8b949e">' + item.name + '/</span>' + | |
| 685 | '<span class="badge">' + (item.packageCount || 0) + ' pkg</span>' | |
| 686 | node.addEventListener('click', (e) => { | |
| 687 | e.stopPropagation() | |
| 688 | descendIntoDir(item.name) | |
| 689 | }) | |
| 690 | } else { | |
| 691 | const mod = item.mod | |
| 692 | const fileCount = mod ? Object.keys(mod.files).length : 0 | |
| 693 | node.innerHTML = '<span class="icon icon-module">M</span>' + | |
| 694 | '<span class="name">' + item.name + '</span>' + | |
| 695 | '<span class="badge">' + (mod ? mod.version : '?') + '</span>' + | |
| 696 | '<span class="badge">' + fileCount + ' files</span>' + | |
| 697 | (mod ? '<span class="badge">' + mod.publicAPI.length + ' exports</span>' : '') + | |
| 698 | valBadgeHTML(item.name) | |
| 699 | node.addEventListener('click', (e) => { | |
| 700 | e.stopPropagation() | |
| 701 | if (mod) selectModule(item.name, mod, node) | |
| 702 | }) | |
| 703 | } | |
| 704 | ||
| 705 | li.appendChild(node) | |
| 706 | return li | |
| 707 | } | |
| 708 | ||
| 709 | function deselectAll () { | |
| 710 | if (selectedTreeNode) { | |
| 711 | selectedTreeNode.classList.remove('selected-module') | |
| 712 | } | |
| 713 | selectedTreeNode = null | |
| 714 | document.querySelectorAll('.dep-highlight, .used-by-highlight, .selected-module').forEach(el => { | |
| 715 | el.classList.remove('dep-highlight', 'used-by-highlight', 'selected-module') | |
| 716 | }) | |
| 717 | document.getElementById('detail-content').innerHTML = '<h2>Select a node to view details</h2>' | |
| 718 | document.getElementById('right-panel').style.display = 'none' | |
| 719 | document.getElementById('resize-right').style.display = 'none' | |
| 720 | } | |
| 721 | ||
| 722 | function buildDirNode (dirEntry) { | |
| 723 | // Is this a module directory? | |
| 724 | if (dirEntry.module && tree.modules[dirEntry.module]) { | |
| 725 | return buildModuleNode(dirEntry.module, tree.modules[dirEntry.module], dirEntry) | |
| 726 | } | |
| 727 | ||
| 728 | // Plain directory | |
| 729 | const li = el('li', { className: 'collapsed' }) | |
| 730 | const hasChildren = dirEntry.children && dirEntry.children.length > 0 | |
| 731 | const node = el('div', { className: 'node', 'data-type': 'dir', 'data-name': dirEntry.name }) | |
| 732 | node.innerHTML = '<span class="toggle">' + (hasChildren ? '+' : ' ') + '</span>' + | |
| 733 | '<span class="icon" style="color:#8b949e">D</span>' + | |
| 734 | '<span class="name" style="color:#8b949e">' + dirEntry.name + '/</span>' | |
| 735 | li.appendChild(node) | |
| 736 | ||
| 737 | // Lazy child population: build the child DOM only on first expansion. For a | |
| 738 | // recursive monorepo scan this avoids creating tens of thousands of DOM | |
| 739 | // elements at page load (the reason the page was sluggish). | |
| 740 | let childrenBuilt = false | |
| 741 | function buildChildrenIfNeeded () { | |
| 742 | if (childrenBuilt || !hasChildren) return | |
| 743 | childrenBuilt = true | |
| 744 | const childUl = el('ul') | |
| 745 | for (const child of dirEntry.children) { | |
| 746 | if (child.type === 'dir' || child.type === 'module-dir') { | |
| 747 | childUl.appendChild(buildDirNode(child)) | |
| 748 | } | |
| 749 | } | |
| 750 | for (const child of dirEntry.children) { | |
| 751 | if (child.type === 'file') { | |
| 752 | childUl.appendChild(buildFileNode(child.path, child, null)) | |
| 753 | } | |
| 754 | } | |
| 755 | li.appendChild(childUl) | |
| 756 | } | |
| 757 | ||
| 758 | node.addEventListener('click', (e) => { | |
| 759 | e.stopPropagation() | |
| 760 | if (!hasChildren) return | |
| 761 | if (li.classList.contains('collapsed')) { | |
| 762 | buildChildrenIfNeeded() // build on first expand | |
| 763 | li.classList.remove('collapsed') | |
| 764 | node.querySelector('.toggle').textContent = '-' | |
| 765 | } else { | |
| 766 | li.classList.add('collapsed') | |
| 767 | node.querySelector('.toggle').textContent = '+' | |
| 768 | } | |
| 769 | }) | |
| 770 | ||
| 771 | return li | |
| 772 | } | |
| 773 | ||
| 774 | function buildModuleNode (name, mod, dirEntry) { | |
| 775 | const li = el('li', { className: 'collapsed' }) | |
| 776 | const fileCount = Object.keys(mod.files).length | |
| 777 | const node = el('div', { className: 'node', 'data-type': 'module', 'data-name': name }) | |
| 778 | node.innerHTML = '<span class="toggle">+</span><span class="icon icon-module">M</span>' + | |
| 779 | '<span class="name">' + name + '</span>' + | |
| 780 | '<span class="badge">' + mod.version + '</span>' + | |
| 781 | '<span class="badge">' + fileCount + ' files</span>' + | |
| 782 | '<span class="badge">' + mod.publicAPI.length + ' exports</span>' + | |
| 783 | valBadgeHTML(name) | |
| 784 | li.appendChild(node) | |
| 785 | ||
| 786 | const childUl = el('ul') | |
| 787 | ||
| 788 | // Merge non-JS files from dirTree into file list | |
| 789 | const allFiles = Object.assign({}, mod.files) | |
| 790 | if (dirEntry && dirEntry.children) { | |
| 791 | addDirTreeFiles(dirEntry, '', allFiles) | |
| 792 | } | |
| 793 | ||
| 794 | // Show files grouped by directory structure within the module | |
| 795 | const byDir = groupFilesByDir(allFiles) | |
| 796 | for (const [dir, files] of byDir) { | |
| 797 | if (dir === '.') { | |
| 798 | // Root-level files | |
| 799 | for (const [path, file] of files) { | |
| 800 | childUl.appendChild(buildFileNode(path, file, name)) | |
| 801 | } | |
| 802 | } else { | |
| 803 | // Subdirectory | |
| 804 | const dirLi = el('li', { className: 'collapsed' }) | |
| 805 | const dirNode = el('div', { className: 'node', 'data-type': 'dir' }) | |
| 806 | dirNode.innerHTML = '<span class="toggle">+</span>' + | |
| 807 | '<span class="icon" style="color:#8b949e">D</span>' + | |
| 808 | '<span class="name" style="color:#8b949e">' + dir + '/</span>' + | |
| 809 | '<span class="badge">' + files.length + '</span>' | |
| 810 | dirLi.appendChild(dirNode) | |
| 811 | ||
| 812 | const subUl = el('ul') | |
| 813 | for (const [path, file] of files) { | |
| 814 | subUl.appendChild(buildFileNode(path, file, name)) | |
| 815 | } | |
| 816 | dirLi.appendChild(subUl) | |
| 817 | ||
| 818 | dirNode.addEventListener('click', (e) => { | |
| 819 | e.stopPropagation() | |
| 820 | dirLi.classList.toggle('collapsed') | |
| 821 | dirNode.querySelector('.toggle').textContent = dirLi.classList.contains('collapsed') ? '+' : '-' | |
| 822 | }) | |
| 823 | ||
| 824 | childUl.appendChild(dirLi) | |
| 825 | } | |
| 826 | } | |
| 827 | ||
| 828 | li.appendChild(childUl) | |
| 829 | node.addEventListener('click', (e) => { | |
| 830 | e.stopPropagation() | |
| 831 | if (selectedTreeNode === node) { | |
| 832 | // Second click: deselect + collapse | |
| 833 | deselectAll() | |
| 834 | li.classList.add('collapsed') | |
| 835 | node.querySelector('.toggle').textContent = '+' | |
| 836 | } else { | |
| 837 | // First click: select + expand | |
| 838 | li.classList.remove('collapsed') | |
| 839 | node.querySelector('.toggle').textContent = '-' | |
| 840 | selectModule(name, mod, node) | |
| 841 | } | |
| 842 | }) | |
| 843 | return li | |
| 844 | } | |
| 845 | ||
| 846 | function selectModule (name, mod, nodeEl) { | |
| 847 | deselectAll() | |
| 848 | selectedTreeNode = nodeEl | |
| 849 | nodeEl.classList.add('selected-module') | |
| 850 | showDetail('module', { name, mod }) | |
| 851 | highlightTreeDeps(name) | |
| 852 | showValidationForModule(name) | |
| 853 | } | |
| 854 | ||
| 855 | function addDirTreeFiles (dirNode, prefix, allFiles) { | |
| 856 | if (!dirNode.children) return | |
| 857 | for (const child of dirNode.children) { | |
| 858 | if (child.type === 'file') { | |
| 859 | const key = prefix ? prefix + '/' + child.name : child.name | |
| 860 | if (!allFiles[key]) { | |
| 861 | allFiles[key] = { name: child.name, ext: child.ext, size: child.size, role: null } | |
| 862 | } | |
| 863 | } else if (child.type === 'dir' && !['node_modules', '.git', 'vendor'].includes(child.name)) { | |
| 864 | const subPrefix = prefix ? prefix + '/' + child.name : child.name | |
| 865 | addDirTreeFiles(child, subPrefix, allFiles) | |
| 866 | } | |
| 867 | } | |
| 868 | } | |
| 869 | ||
| 870 | function groupFilesByDir (files) { | |
| 871 | const dirs = new Map() | |
| 872 | const entries = Object.entries(files).sort(([a], [b]) => a.localeCompare(b)) | |
| 873 | ||
| 874 | for (const [path, file] of entries) { | |
| 875 | const parts = path.split('/') | |
| 876 | const dir = parts.length > 1 ? parts.slice(0, -1).join('/') : '.' | |
| 877 | if (!dirs.has(dir)) dirs.set(dir, []) | |
| 878 | dirs.get(dir).push([path, file]) | |
| 879 | } | |
| 880 | ||
| 881 | // Sort: root first, then alphabetical | |
| 882 | const sorted = new Map() | |
| 883 | if (dirs.has('.')) sorted.set('.', dirs.get('.')) | |
| 884 | for (const [dir, files] of [...dirs].sort(([a], [b]) => a.localeCompare(b))) { | |
| 885 | if (dir !== '.') sorted.set(dir, files) | |
| 886 | } | |
| 887 | return sorted | |
| 888 | } | |
| 889 | ||
| 890 | function buildFileNode (path, file, moduleName) { | |
| 891 | const li = el('li', { className: 'collapsed' }) | |
| 892 | const fileName = path.includes('/') ? path.split('/').pop() : path | |
| 893 | ||
| 894 | // file might be a parsed JS file (with classes/functions) or a raw dirTree file entry | |
| 895 | const isParsed = file.exports || file.classes || file.functions || file.signals || file.uniforms || file.buffers | |
| 896 | const hasChildren = isParsed && ((file.classes && file.classes.length > 0) || (file.functions && file.functions.length > 0) || (file.signals && file.signals.length > 0)) | |
| 897 | ||
| 898 | const counts = [] | |
| 899 | if (file.classes) counts.push(file.classes.length + ' cls') | |
| 900 | if (file.functions) counts.push(file.functions.length + ' fn') | |
| 901 | ||
| 902 | const ext = fileName.includes('.') ? fileName.split('.').pop() : '' | |
| 903 | const icon = fileIcon(ext, file.role) | |
| 904 | ||
| 905 | const node = el('div', { className: 'node', 'data-type': 'file', 'data-name': path }) | |
| 906 | node.innerHTML = '<span class="toggle">' + (hasChildren ? '+' : ' ') + '</span>' + | |
| 907 | '<span class="icon" style="color:' + icon.color + '">' + icon.char + '</span>' + | |
| 908 | '<span class="name">' + fileName + '</span>' + | |
| 909 | (counts.length ? '<span class="badge">' + counts.join(', ') + '</span>' : '') + | |
| 910 | (file.size ? '<span class="badge" style="color:#484f58">' + formatSize(file.size) + '</span>' : '') | |
| 911 | li.appendChild(node) | |
| 912 | ||
| 913 | if (hasChildren) { | |
| 914 | const childUl = el('ul') | |
| 915 | if (file.classes) for (const cls of file.classes) childUl.appendChild(buildClassNode(cls)) | |
| 916 | if (file.functions) for (const fn of file.functions) childUl.appendChild(buildFunctionNode(fn)) | |
| 917 | li.appendChild(childUl) | |
| 918 | } | |
| 919 | ||
| 920 | node.addEventListener('click', (e) => { | |
| 921 | e.stopPropagation() | |
| 922 | if (hasChildren) { | |
| 923 | li.classList.toggle('collapsed') | |
| 924 | node.querySelector('.toggle').textContent = li.classList.contains('collapsed') ? '+' : '-' | |
| 925 | } | |
| 926 | currentFileContext = { path, moduleName } | |
| 927 | const modPath = moduleName ? tree.modules[moduleName].path + '/' : '' | |
| 928 | loadFileViewer(modPath + path, moduleName) | |
| 929 | if (isParsed) showStructurePanel(path, file, moduleName) | |
| 930 | }) | |
| 931 | return li | |
| 932 | } | |
| 933 | ||
| 934 | function fileIcon (ext, role) { | |
| 935 | const icons = { | |
| 936 | js: { char: 'JS', color: '#f0db4f' }, | |
| 937 | mjs: { char: 'JS', color: '#f0db4f' }, | |
| 938 | cjs: { char: 'CJ', color: '#f0db4f' }, | |
| 939 | json: { char: '{}', color: '#8b949e' }, | |
| 940 | md: { char: 'MD', color: '#58a6ff' }, | |
| 941 | yml: { char: 'YM', color: '#ff7b72' }, | |
| 942 | yaml: { char: 'YM', color: '#ff7b72' }, | |
| 943 | toml: { char: 'TM', color: '#ffa657' }, | |
| 944 | sh: { char: 'SH', color: '#3fb950' }, | |
| 945 | c: { char: 'C', color: '#79c0ff' }, | |
| 946 | h: { char: 'H', color: '#79c0ff' }, | |
| 947 | txt: { char: 'TX', color: '#8b949e' }, | |
| 948 | lock: { char: 'LK', color: '#484f58' }, | |
| 949 | css: { char: 'CS', color: '#d2a8ff' }, | |
| 950 | html: { char: 'HT', color: '#f0883e' } | |
| 951 | } | |
| 952 | if (role === 'entry') return { char: 'E', color: '#f0883e' } | |
| 953 | return icons[ext] || { char: ext.slice(0, 2).toUpperCase() || 'F', color: '#484f58' } | |
| 954 | } | |
| 955 | ||
| 956 | function formatSize (bytes) { | |
| 957 | if (bytes < 1024) return bytes + 'B' | |
| 958 | if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + 'KB' | |
| 959 | return (bytes / 1024 / 1024).toFixed(1) + 'MB' | |
| 960 | } | |
| 961 | ||
| 962 | // Track current file context for source viewing | |
| 963 | let currentFileContext = null // { path, moduleName } | |
| 964 | ||
| 965 | function buildClassNode (cls) { | |
| 966 | const li = el('li', { className: 'collapsed' }) | |
| 967 | const memberCount = (cls.methods ? cls.methods.length : 0) + (cls.getters ? cls.getters.length : 0) | |
| 968 | const node = el('div', { className: 'node', 'data-type': 'class', 'data-name': cls.name }) | |
| 969 | node.innerHTML = '<span class="toggle">' + (memberCount > 0 ? '+' : ' ') + '</span>' + | |
| 970 | '<span class="icon icon-class">C</span>' + | |
| 971 | '<span class="name">' + cls.name + '</span>' + | |
| 972 | (cls.extends ? '<span class="badge">extends ' + cls.extends + '</span>' : '') + | |
| 973 | '<span class="badge">' + memberCount + ' members</span>' | |
| 974 | li.appendChild(node) | |
| 975 | ||
| 976 | if (memberCount > 0) { | |
| 977 | const childUl = el('ul') | |
| 978 | if (cls.constructor) { | |
| 979 | const cLi = el('li') | |
| 980 | const cNode = el('div', { className: 'node' }) | |
| 981 | cNode.innerHTML = '<span class="toggle"> </span><span class="icon icon-method">f</span>' + | |
| 982 | '<span class="name">constructor(' + cls.constructor.params.join(', ') + ')</span>' | |
| 983 | cNode.addEventListener('click', (e) => { | |
| 984 | e.stopPropagation() | |
| 985 | if (currentFileContext && cls.constructor.line) { | |
| 986 | const modPath = currentFileContext.moduleName ? tree.modules[currentFileContext.moduleName].path + '/' : '' | |
| 987 | loadFileViewer(modPath + currentFileContext.path, currentFileContext.moduleName, cls.constructor.line) | |
| 988 | } else { | |
| 989 | showDetail('constructor', { cls, constructor: cls.constructor }) | |
| 990 | } | |
| 991 | }) | |
| 992 | cLi.appendChild(cNode) | |
| 993 | childUl.appendChild(cLi) | |
| 994 | } | |
| 995 | if (cls.getters) for (const g of cls.getters) { | |
| 996 | const gLi = el('li') | |
| 997 | const gNode = el('div', { className: 'node' }) | |
| 998 | gNode.innerHTML = '<span class="toggle"> </span><span class="icon icon-getter">g</span><span class="name">get ' + g.name + '</span>' | |
| 999 | gLi.appendChild(gNode) | |
| 1000 | childUl.appendChild(gLi) | |
| 1001 | } | |
| 1002 | if (cls.methods) for (const m of cls.methods) { | |
| 1003 | if (m.kind === 'field') continue | |
| 1004 | const mLi = el('li') | |
| 1005 | const mNode = el('div', { className: 'node', 'data-name': m.name }) | |
| 1006 | const tags = (m.async ? '<span class="tag tag-async">async</span>' : '') + | |
| 1007 | (m.generator ? '<span class="tag tag-generator">*</span>' : '') | |
| 1008 | mNode.innerHTML = '<span class="toggle"> </span><span class="icon icon-method">f</span>' + | |
| 1009 | '<span class="name">' + m.name + '(' + m.params.join(', ') + ')</span>' + tags | |
| 1010 | mNode.addEventListener('click', (e) => { | |
| 1011 | e.stopPropagation() | |
| 1012 | if (currentFileContext && m.line) { | |
| 1013 | const modPath = currentFileContext.moduleName ? tree.modules[currentFileContext.moduleName].path + '/' : '' | |
| 1014 | loadFileViewer(modPath + currentFileContext.path, currentFileContext.moduleName, m.line) | |
| 1015 | } else { | |
| 1016 | showDetail('method', { cls, method: m }) | |
| 1017 | } | |
| 1018 | }) | |
| 1019 | mLi.appendChild(mNode) | |
| 1020 | childUl.appendChild(mLi) | |
| 1021 | } | |
| 1022 | li.appendChild(childUl) | |
| 1023 | } | |
| 1024 | ||
| 1025 | node.addEventListener('click', (e) => { | |
| 1026 | e.stopPropagation() | |
| 1027 | if (memberCount > 0) { | |
| 1028 | li.classList.toggle('collapsed') | |
| 1029 | node.querySelector('.toggle').textContent = li.classList.contains('collapsed') ? '+' : '-' | |
| 1030 | } | |
| 1031 | if (currentFileContext && cls.line) { | |
| 1032 | const modPath = currentFileContext.moduleName ? tree.modules[currentFileContext.moduleName].path + '/' : '' | |
| 1033 | loadFileViewer(modPath + currentFileContext.path, currentFileContext.moduleName, cls.line) | |
| 1034 | } else { | |
| 1035 | showDetail('class', { cls }) | |
| 1036 | } | |
| 1037 | }) | |
| 1038 | return li | |
| 1039 | } | |
| 1040 | ||
| 1041 | function buildFunctionNode (fn) { | |
| 1042 | const li = el('li') | |
| 1043 | const tags = (fn.async ? '<span class="tag tag-async">async</span>' : '') + | |
| 1044 | (fn.arrow ? '<span class="tag tag-arrow">=></span>' : '') | |
| 1045 | const node = el('div', { className: 'node', 'data-name': fn.name }) | |
| 1046 | node.innerHTML = '<span class="toggle"> </span><span class="icon icon-function">f</span>' + | |
| 1047 | '<span class="name">' + fn.name + '(' + fn.params.join(', ') + ')</span>' + tags | |
| 1048 | node.addEventListener('click', (e) => { | |
| 1049 | e.stopPropagation() | |
| 1050 | if (currentFileContext && fn.line) { | |
| 1051 | const modPath = currentFileContext.moduleName ? tree.modules[currentFileContext.moduleName].path + '/' : '' | |
| 1052 | loadFileViewer(modPath + currentFileContext.path, currentFileContext.moduleName, fn.line) | |
| 1053 | } else { | |
| 1054 | showDetail('function', { fn }) | |
| 1055 | } | |
| 1056 | }) | |
| 1057 | li.appendChild(node) | |
| 1058 | return li | |
| 1059 | } | |
| 1060 | ||
| 1061 | // ====== DETAIL PANEL ====== | |
| 1062 | function showDetail (type, data) { | |
| 1063 | const panel = document.getElementById('detail-content') | |
| 1064 | let html = '' | |
| 1065 | switch (type) { | |
| 1066 | case 'module': { | |
| 1067 | const { name, mod } = data | |
| 1068 | html = '<h2>' + name + '@' + mod.version + '</h2>' | |
| 1069 | html += '<div class="detail"><h3>Public API</h3><pre><code>' + (mod.publicAPI.join('\\n') || '(none)') + '</code></pre></div>' | |
| 1070 | html += '<div class="detail"><h3>Dependencies</h3><pre><code>' + (Object.entries(mod.dependencies).map(([k,v]) => k + ': ' + v).join('\\n') || '(none)') + '</code></pre></div>' | |
| 1071 | if (mod.importMaps && Object.keys(mod.importMaps).length > 0) { | |
| 1072 | html += '<div class="detail"><h3>Import Maps</h3><pre><code>' + JSON.stringify(mod.importMaps, null, 2) + '</code></pre></div>' | |
| 1073 | } | |
| 1074 | if (mod.testCommand) html += '<div class="detail"><h3>Test</h3><pre><code>' + mod.testCommand + '</code></pre></div>' | |
| 1075 | break | |
| 1076 | } | |
| 1077 | case 'file': { | |
| 1078 | const { path, file, moduleName } = data | |
| 1079 | const modPath = moduleName ? tree.modules[moduleName].path + '/' : '' | |
| 1080 | html = '<h2>' + moduleName + '/' + path + '</h2><div class="badge">' + file.role + '</div>' | |
| 1081 | html += ' <span class="badge" style="cursor:pointer;color:#58a6ff;border:1px solid #58a6ff" onclick="loadFileViewer("' + modPath + path + '","' + (moduleName||'') + '")">View Source</span>' | |
| 1082 | if (file.imports && file.imports.length) html += '<div class="detail"><h3>Imports</h3><pre><code>' + file.imports.map(i => i.names.join(', ') + ' from ' + i.specifier).join('\\n') + '</code></pre></div>' | |
| 1083 | if (file.exports && file.exports.length) html += '<div class="detail"><h3>Exports</h3><pre><code>' + file.exports.map(e => e.name + (e.type ? ' (' + e.type + ')' : '') + (e.from ? ' from ' + e.from : '')).join('\\n') + '</code></pre></div>' | |
| 1084 | if (file.state && file.state.length) html += '<div class="detail"><h3>State</h3><pre><code>' + file.state.join('\\n') + '</code></pre></div>' | |
| 1085 | if (file.delegates && file.delegates.length) html += '<div class="detail"><h3>Delegation</h3><pre><code>' + file.delegates.map(d => d.field + ' -> ' + d.methods.join(', ')).join('\\n') + '</code></pre></div>' | |
| 1086 | if (file.errorContracts && file.errorContracts.length) html += '<div class="detail"><h3>Errors</h3><pre><code>' + file.errorContracts.join('\\n') + '</code></pre></div>' | |
| 1087 | break | |
| 1088 | } | |
| 1089 | case 'class': { | |
| 1090 | const { cls } = data | |
| 1091 | html = '<h2>class ' + cls.name + (cls.extends ? ' extends ' + cls.extends : '') + '</h2>' | |
| 1092 | html += sourceLink(cls.line) | |
| 1093 | if (cls.jsdoc) html += '<div class="detail"><h3>JSDoc</h3><pre><code>' + escapeHtml(cls.jsdoc) + '</code></pre></div>' | |
| 1094 | if (cls.constructor) html += '<div class="detail"><h3>Constructor</h3><pre><code>constructor(' + cls.constructor.params.join(', ') + ')</code></pre></div>' | |
| 1095 | html += '<div class="detail"><h3>Methods (' + cls.methods.length + ')</h3><pre><code>' + cls.methods.filter(m => m.kind !== 'field').map(m => (m.async ? 'async ' : '') + m.name + '(' + m.params.join(', ') + ')' + (m.line ? ' :' + m.line : '')).join('\\n') + '</code></pre></div>' | |
| 1096 | if (cls.getters && cls.getters.length) html += '<div class="detail"><h3>Getters (' + cls.getters.length + ')</h3><pre><code>' + cls.getters.map(g => 'get ' + g.name + (g.line ? ' :' + g.line : '')).join('\\n') + '</code></pre></div>' | |
| 1097 | break | |
| 1098 | } | |
| 1099 | case 'method': case 'constructor': { | |
| 1100 | const m = data.method || data.constructor | |
| 1101 | const label = data.method ? data.method.name : 'constructor' | |
| 1102 | html = '<h2>' + data.cls.name + '.' + label + '</h2>' | |
| 1103 | html += sourceLink(m.line) | |
| 1104 | html += '<pre><code>' + (m.async ? 'async ' : '') + label + '(' + m.params.join(', ') + ')</code></pre>' | |
| 1105 | if (m.jsdoc) html += '<div class="detail"><h3>JSDoc</h3><pre><code>' + escapeHtml(m.jsdoc) + '</code></pre></div>' | |
| 1106 | break | |
| 1107 | } | |
| 1108 | case 'function': { | |
| 1109 | const { fn } = data | |
| 1110 | html = '<h2>' + fn.name + '</h2>' | |
| 1111 | html += sourceLink(fn.line) | |
| 1112 | html += '<pre><code>' + (fn.async ? 'async ' : '') + fn.name + '(' + fn.params.join(', ') + ')</code></pre>' | |
| 1113 | if (fn.jsdoc) html += '<div class="detail"><h3>JSDoc</h3><pre><code>' + escapeHtml(fn.jsdoc) + '</code></pre></div>' | |
| 1114 | break | |
| 1115 | } | |
| 1116 | case 'rawFile': { | |
| 1117 | const { path, file } = data | |
| 1118 | const ext = path.includes('.') ? path.split('.').pop() : '' | |
| 1119 | html = '<h2>' + path + '</h2>' | |
| 1120 | html += '<div class="badge">' + ext + '</div>' | |
| 1121 | if (file.size) html += ' <span class="badge">' + formatSize(file.size) + '</span>' | |
| 1122 | break | |
| 1123 | } | |
| 1124 | } | |
| 1125 | panel.innerHTML = html | |
| 1126 | } | |
| 1127 | ||
| 1128 | // ====== GRAPH VIEW ====== | |
| 1129 | let graphInitialized = false | |
| 1130 | const graphNodes = [] | |
| 1131 | const graphEdges = [] | |
| 1132 | let focusedNode = null | |
| 1133 | let zoom = 1, panX = 0, panY = 0 | |
| 1134 | let isPanning = false, panStartX = 0, panStartY = 0 | |
| 1135 | let graphGroup = null | |
| 1136 | ||
| 1137 | // --- Path-based navigation --- | |
| 1138 | // | |
| 1139 | // The graph shows ONLY what's at the current location in the directory tree. | |
| 1140 | // Navigate down by clicking a directory node; navigate up via the breadcrumb. | |
| 1141 | // This keeps each view bounded (typically 5-50 nodes) so force-directed | |
| 1142 | // simulation stays fast and the graph stays readable. | |
| 1143 | ||
| 1144 | function getCurrentPath () { | |
| 1145 | // Path entries on the graphStack accumulate as the user descends. | |
| 1146 | return graphStack.filter(e => e.type === 'path').map(e => e.name).join('/') | |
| 1147 | } | |
| 1148 | ||
| 1149 | function findDirTreeNode (path) { | |
| 1150 | if (!path) return tree.dirTree | |
| 1151 | const parts = path.split('/') | |
| 1152 | let node = tree.dirTree | |
| 1153 | for (const part of parts) { | |
| 1154 | if (!node.children) return null | |
| 1155 | const next = node.children.find(c => c.name === part) | |
| 1156 | if (!next) return null | |
| 1157 | node = next | |
| 1158 | } | |
| 1159 | return node | |
| 1160 | } | |
| 1161 | ||
| 1162 | function countPackagesUnder (dirEntry) { | |
| 1163 | let count = 0 | |
| 1164 | function visit (n) { | |
| 1165 | if (n.module) count++ | |
| 1166 | if (n.children) for (const c of n.children) visit(c) | |
| 1167 | } | |
| 1168 | visit(dirEntry) | |
| 1169 | return count | |
| 1170 | } | |
| 1171 | ||
| 1172 | // Returns: array of { name, type: 'dir'|'module', mod?, dirEntry, packageCount? } | |
| 1173 | // Each entry is one node to render at the current location. | |
| 1174 | function getNodesAtPath (path) { | |
| 1175 | const node = findDirTreeNode(path) | |
| 1176 | if (!node || !node.children) return [] | |
| 1177 | const result = [] | |
| 1178 | for (const child of node.children) { | |
| 1179 | if (child.type === 'file') continue | |
| 1180 | if (child.module && tree.modules[child.module]) { | |
| 1181 | result.push({ | |
| 1182 | name: child.module, | |
| 1183 | type: 'module', | |
| 1184 | dirEntry: child, | |
| 1185 | mod: tree.modules[child.module] | |
| 1186 | }) | |
| 1187 | } else if (child.children && child.children.length > 0) { | |
| 1188 | // Pure directory with content | |
| 1189 | result.push({ | |
| 1190 | name: child.name, | |
| 1191 | type: 'dir', | |
| 1192 | dirEntry: child, | |
| 1193 | mod: null, | |
| 1194 | packageCount: countPackagesUnder(child) | |
| 1195 | }) | |
| 1196 | } | |
| 1197 | } | |
| 1198 | return result | |
| 1199 | } | |
| 1200 | ||
| 1201 | // Click handler for a directory node: descend into it. | |
| 1202 | window.descendIntoDir = function (dirName) { | |
| 1203 | graphStack.push({ type: 'path', name: dirName, label: dirName }) | |
| 1204 | rebuildGraph() | |
| 1205 | syncTreeWithGraph() | |
| 1206 | } | |
| 1207 | ||
| 1208 | function initGraph () { | |
| 1209 | graphInitialized = true | |
| 1210 | const svg = document.getElementById('graph-svg') | |
| 1211 | const rect = svg.getBoundingClientRect() | |
| 1212 | const W = rect.width | |
| 1213 | const H = rect.height | |
| 1214 | const cx = W / 2 | |
| 1215 | const cy = H / 2 | |
| 1216 | ||
| 1217 | // Compute category groups | |
| 1218 | const categories = tree.categories || {} | |
| 1219 | const moduleToCategory = {} | |
| 1220 | for (const [cat, mods] of Object.entries(categories)) { | |
| 1221 | for (const m of mods) moduleToCategory[m] = cat | |
| 1222 | } | |
| 1223 | ||
| 1224 | if (gfx.groupBy === 'deps') { | |
| 1225 | // Override: cluster by most-shared dependency | |
| 1226 | for (const k of Object.keys(moduleToCategory)) delete moduleToCategory[k] | |
| 1227 | const shared = tree.system.sharedDeps || {} | |
| 1228 | const topDeps = Object.entries(shared).sort((a, b) => b[1].length - a[1].length).slice(0, 6) | |
| 1229 | for (const [dep, users] of topDeps) { | |
| 1230 | for (const u of users) { | |
| 1231 | if (!moduleToCategory[u]) moduleToCategory[u] = dep + ' users' | |
| 1232 | } | |
| 1233 | } | |
| 1234 | for (const name of tree.system.modules) { | |
| 1235 | if (!moduleToCategory[name]) moduleToCategory[name] = 'Other' | |
| 1236 | } | |
| 1237 | } else { | |
| 1238 | // Default: use SYSTEM.md categories (already in moduleToCategory). | |
| 1239 | // Uncategorized modules fall back to shared-dependency clustering — the | |
| 1240 | // strongest data-driven signal we have for relatedness without hardcoded | |
| 1241 | // module names. If no shared dep covers a module, it lands in "Other". | |
| 1242 | const shared = tree.system.sharedDeps || {} | |
| 1243 | const depToMostShared = {} | |
| 1244 | for (const [dep, users] of Object.entries(shared)) { | |
| 1245 | for (const u of users) { | |
| 1246 | const prev = depToMostShared[u] | |
| 1247 | if (!prev || users.length > shared[prev].length) depToMostShared[u] = dep | |
| 1248 | } | |
| 1249 | } | |
| 1250 | for (const name of tree.system.modules) { | |
| 1251 | if (moduleToCategory[name]) continue | |
| 1252 | const topDep = depToMostShared[name] | |
| 1253 | moduleToCategory[name] = topDep ? (topDep + ' users') : 'Other' | |
| 1254 | } | |
| 1255 | } | |
| 1256 | ||
| 1257 | const categoryColors = {} | |
| 1258 | const catColorList = ['#58a6ff', '#3fb950', '#d2a8ff', '#f0883e', '#ff7b72', '#ffa657', '#79c0ff', '#f778ba'] | |
| 1259 | let catIdx = 0 | |
| 1260 | for (const cat of Object.keys(categories)) { | |
| 1261 | categoryColors[cat] = catColorList[catIdx % catColorList.length] | |
| 1262 | catIdx++ | |
| 1263 | } | |
| 1264 | ||
| 1265 | // Build nodes for what's at the current path. This is the file-manager | |
| 1266 | // model: each level of the dir tree is a separate, bounded view. | |
| 1267 | const items = getNodesAtPath(getCurrentPath()) | |
| 1268 | const nameToIdx = {} | |
| 1269 | ||
| 1270 | // Categorization keeps the existing semantic data: | |
| 1271 | // • SYSTEM.md categories (curated, e.g. "Crypto & Identity") | |
| 1272 | // • Global shared-deps fallback (e.g. "hyperswarm users") | |
| 1273 | // Pure directory nodes (no module entry) get a synthetic "Directories" | |
| 1274 | // category so they cluster together visually. | |
| 1275 | // | |
| 1276 | // Only categories that actually apply to VISIBLE items are kept — labels | |
| 1277 | // for off-screen modules don't pollute the legend. | |
| 1278 | const catGroups = {} | |
| 1279 | for (let i = 0; i < items.length; i++) { | |
| 1280 | const item = items[i] | |
| 1281 | let cat | |
| 1282 | if (item.type === 'dir') { | |
| 1283 | cat = 'Directories' | |
| 1284 | } else { | |
| 1285 | cat = (gfx.groupBy !== 'none' ? moduleToCategory[item.name] : null) || 'Other' | |
| 1286 | } | |
| 1287 | if (!catGroups[cat]) catGroups[cat] = [] | |
| 1288 | catGroups[cat].push(i) | |
| 1289 | } | |
| 1290 | const catList = Object.keys(catGroups) | |
| 1291 | ||
| 1292 | for (let i = 0; i < items.length; i++) { | |
| 1293 | const item = items[i] | |
| 1294 | const isDir = item.type === 'dir' | |
| 1295 | const name = item.name | |
| 1296 | const mod = item.mod | |
| 1297 | ||
| 1298 | const fileCount = mod ? Object.keys(mod.files).length : 0 | |
| 1299 | let memberCount = 0 | |
| 1300 | if (mod) { | |
| 1301 | for (const f of Object.values(mod.files)) { | |
| 1302 | if (f.classes) for (const c of f.classes) memberCount += c.methods.length + (c.getters ? c.getters.length : 0) | |
| 1303 | } | |
| 1304 | } | |
| 1305 | ||
| 1306 | const cat = isDir ? 'Directories' : (moduleToCategory[name] || 'Other') | |
| 1307 | const catI = catList.indexOf(cat) | |
| 1308 | const group = catGroups[cat] | |
| 1309 | const posInGroup = group.indexOf(i) | |
| 1310 | ||
| 1311 | // Position: spread categories around the center | |
| 1312 | const spaceMult = 0.5 + (gfx.spacing / 100) * 2 | |
| 1313 | const catAngle = (catI / catList.length) * Math.PI * 2 - Math.PI / 2 | |
| 1314 | const catRadius = (Math.min(W, H) * 0.2 + catList.length * 8) * spaceMult | |
| 1315 | const catCx = cx + Math.cos(catAngle) * catRadius | |
| 1316 | const catCy = cy + Math.sin(catAngle) * catRadius | |
| 1317 | const nodeAngle = (posInGroup / group.length) * Math.PI * 2 | |
| 1318 | const nodeRadius = Math.min(80, 20 + group.length * 10) * (0.7 + spaceMult * 0.3) | |
| 1319 | ||
| 1320 | // Dir nodes get a different size (based on how much they contain) and color. | |
| 1321 | const exportCount = mod ? mod.publicAPI.length : 0 | |
| 1322 | const r = isDir | |
| 1323 | ? Math.max(20, Math.min(50, 12 + Math.sqrt(item.packageCount) * 4)) | |
| 1324 | : calcNodeSize({ memberCount, usedBy: [], mod, exportCount }) | |
| 1325 | ||
| 1326 | graphNodes.push({ | |
| 1327 | idx: i, name, mod, | |
| 1328 | type: isDir ? 'dir' : 'module', | |
| 1329 | packageCount: item.packageCount, | |
| 1330 | dirEntry: item.dirEntry, | |
| 1331 | x: catCx + Math.cos(nodeAngle) * nodeRadius, | |
| 1332 | y: catCy + Math.sin(nodeAngle) * nodeRadius, | |
| 1333 | vx: 0, vy: 0, | |
| 1334 | r, | |
| 1335 | fileCount, memberCount, | |
| 1336 | exportCount, | |
| 1337 | color: isDir ? '#484f58' : (categoryColors[cat] || moduleColor(name)), | |
| 1338 | category: cat | |
| 1339 | }) | |
| 1340 | nameToIdx[name] = i | |
| 1341 | } | |
| 1342 | ||
| 1343 | // Build edges between visible MODULE nodes only. (Dir-to-dir aggregated edges | |
| 1344 | // are a future enhancement; for now keep it simple.) | |
| 1345 | for (let i = 0; i < graphNodes.length; i++) { | |
| 1346 | const n = graphNodes[i] | |
| 1347 | if (!n.mod) continue | |
| 1348 | for (const dep of Object.keys(n.mod.dependencies)) { | |
| 1349 | if (nameToIdx[dep] !== undefined) { | |
| 1350 | graphEdges.push({ source: i, target: nameToIdx[dep] }) | |
| 1351 | } | |
| 1352 | } | |
| 1353 | } | |
| 1354 | ||
| 1355 | for (const n of graphNodes) { | |
| 1356 | n.dependsOn = graphEdges.filter(e => e.source === n.idx).map(e => e.target) | |
| 1357 | n.usedBy = graphEdges.filter(e => e.target === n.idx).map(e => e.source) | |
| 1358 | // Recalc size now that usedBy is known | |
| 1359 | n.r = calcNodeSize(n) | |
| 1360 | } | |
| 1361 | ||
| 1362 | // SVG structure | |
| 1363 | const defs = svg.querySelector('defs').outerHTML | |
| 1364 | svg.innerHTML = defs + '<g id="graph-world"><g id="graph-regions"></g><g id="graph-edges"></g><g id="graph-nodes"></g></g>' | |
| 1365 | ||
| 1366 | // Draw category region backgrounds. Categories are now derived from the | |
| 1367 | // VISIBLE items only (see visibleCategoryFor above), so labels at any path | |
| 1368 | // accurately reflect what's in the bubble. Bubbles appear at root + any | |
| 1369 | // sub-path with mixed dirs/packages. | |
| 1370 | if (gfx.showRegions && gfx.groupBy !== 'none' && catList.length > 1) { | |
| 1371 | const regionGroup = document.getElementById('graph-regions') | |
| 1372 | for (const cat of catList) { | |
| 1373 | if (cat === 'Other' && catGroups[cat].length < 2) continue | |
| 1374 | const nodes = catGroups[cat].map(i => graphNodes[i]) | |
| 1375 | const color = categoryColors[cat] || '#484f58' | |
| 1376 | ||
| 1377 | // Compute bounding circle | |
| 1378 | let avgX = 0, avgY = 0 | |
| 1379 | for (const n of nodes) { avgX += n.x; avgY += n.y } | |
| 1380 | avgX /= nodes.length; avgY /= nodes.length | |
| 1381 | let maxDist = 0 | |
| 1382 | for (const n of nodes) { | |
| 1383 | const d = Math.sqrt((n.x - avgX) ** 2 + (n.y - avgY) ** 2) + n.r | |
| 1384 | if (d > maxDist) maxDist = d | |
| 1385 | } | |
| 1386 | ||
| 1387 | const region = document.createElementNS('http://www.w3.org/2000/svg', 'circle') | |
| 1388 | region.classList.add('graph-region') | |
| 1389 | region.setAttribute('cx', avgX) | |
| 1390 | region.setAttribute('cy', avgY) | |
| 1391 | region.setAttribute('r', maxDist + 30) | |
| 1392 | region.setAttribute('fill', color) | |
| 1393 | region.setAttribute('stroke', color) | |
| 1394 | region.dataset.cat = cat | |
| 1395 | regionGroup.appendChild(region) | |
| 1396 | ||
| 1397 | // Label with background rect for readability | |
| 1398 | const labelG = document.createElementNS('http://www.w3.org/2000/svg', 'g') | |
| 1399 | labelG.classList.add('graph-region-label') | |
| 1400 | labelG.dataset.cat = cat | |
| 1401 | ||
| 1402 | const labelBg = document.createElementNS('http://www.w3.org/2000/svg', 'rect') | |
| 1403 | labelBg.setAttribute('fill', '#0d1117') | |
| 1404 | labelBg.setAttribute('fill-opacity', '0.8') | |
| 1405 | labelBg.setAttribute('rx', '4') | |
| 1406 | const textWidth = cat.length * 8 + 16 | |
| 1407 | labelBg.setAttribute('x', avgX - textWidth / 2) | |
| 1408 | labelBg.setAttribute('y', avgY - maxDist - 28) | |
| 1409 | labelBg.setAttribute('width', textWidth) | |
| 1410 | labelBg.setAttribute('height', 22) | |
| 1411 | labelG.appendChild(labelBg) | |
| 1412 | ||
| 1413 | const label = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 1414 | label.textContent = cat | |
| 1415 | label.setAttribute('x', avgX) | |
| 1416 | label.setAttribute('y', avgY - maxDist - 12) | |
| 1417 | label.setAttribute('text-anchor', 'middle') | |
| 1418 | label.setAttribute('fill', color) | |
| 1419 | label.setAttribute('font-size', '13') | |
| 1420 | label.setAttribute('font-weight', 'bold') | |
| 1421 | labelG.appendChild(label) | |
| 1422 | ||
| 1423 | regionGroup.appendChild(labelG) | |
| 1424 | } | |
| 1425 | } | |
| 1426 | graphGroup = document.getElementById('graph-world') | |
| 1427 | const edgeGroup = document.getElementById('graph-edges') | |
| 1428 | const nodeGroup = document.getElementById('graph-nodes') | |
| 1429 | ||
| 1430 | // Draw edges as lines with arrows | |
| 1431 | for (const edge of graphEdges) { | |
| 1432 | const line = document.createElementNS('http://www.w3.org/2000/svg', 'line') | |
| 1433 | line.classList.add('graph-edge') | |
| 1434 | line.dataset.source = edge.source | |
| 1435 | line.dataset.target = edge.target | |
| 1436 | edgeGroup.appendChild(line) | |
| 1437 | edge.el = line | |
| 1438 | } | |
| 1439 | ||
| 1440 | // Draw nodes | |
| 1441 | for (let i = 0; i < graphNodes.length; i++) { | |
| 1442 | const n = graphNodes[i] | |
| 1443 | const g = document.createElementNS('http://www.w3.org/2000/svg', 'g') | |
| 1444 | g.classList.add('graph-node') | |
| 1445 | g.dataset.idx = i | |
| 1446 | ||
| 1447 | // Validation ring (outer glow) | |
| 1448 | const valStatus = getModuleValidation(n.name) | |
| 1449 | if (valStatus) { | |
| 1450 | const ring = document.createElementNS('http://www.w3.org/2000/svg', 'circle') | |
| 1451 | ring.setAttribute('r', n.r + 4) | |
| 1452 | ring.setAttribute('fill', 'none') | |
| 1453 | const ringColor = valStatus.fail > 0 ? '#ff7b72' : valStatus.warn > 0 ? '#d29922' : '#3fb950' | |
| 1454 | ring.setAttribute('stroke', ringColor) | |
| 1455 | ring.setAttribute('stroke-width', '2.5') | |
| 1456 | ring.setAttribute('stroke-dasharray', valStatus.fail > 0 ? 'none' : '4,3') | |
| 1457 | ring.setAttribute('opacity', '0.7') | |
| 1458 | g.appendChild(ring) | |
| 1459 | } | |
| 1460 | ||
| 1461 | const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle') | |
| 1462 | circle.setAttribute('r', n.r) | |
| 1463 | circle.setAttribute('fill', n.color) | |
| 1464 | circle.setAttribute('stroke', '#30363d') | |
| 1465 | circle.setAttribute('stroke-width', '1.5') | |
| 1466 | g.appendChild(circle) | |
| 1467 | ||
| 1468 | const text = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 1469 | text.textContent = n.name | |
| 1470 | text.setAttribute('dy', n.r + 14) | |
| 1471 | text.setAttribute('text-anchor', 'middle') | |
| 1472 | text.setAttribute('font-size', '11') | |
| 1473 | if (!gfx.showLabels) text.style.display = 'none' | |
| 1474 | g.appendChild(text) | |
| 1475 | n.labelEl = text | |
| 1476 | ||
| 1477 | // Validation count below name | |
| 1478 | if (valStatus && (valStatus.fail > 0 || valStatus.warn > 0)) { | |
| 1479 | const valText = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 1480 | const parts = [] | |
| 1481 | if (valStatus.fail > 0) parts.push(valStatus.fail + 'F') | |
| 1482 | if (valStatus.warn > 0) parts.push(valStatus.warn + 'W') | |
| 1483 | valText.textContent = parts.join(' ') | |
| 1484 | valText.setAttribute('dy', n.r + 25) | |
| 1485 | valText.setAttribute('text-anchor', 'middle') | |
| 1486 | valText.setAttribute('font-size', '9') | |
| 1487 | valText.setAttribute('fill', valStatus.fail > 0 ? '#ff7b72' : '#d29922') | |
| 1488 | g.appendChild(valText) | |
| 1489 | } | |
| 1490 | ||
| 1491 | // Inner label: "Nm" for module member count, "Np" for dir's package count | |
| 1492 | const countText = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 1493 | countText.textContent = n.type === 'dir' ? (n.packageCount + 'p') : (n.memberCount + 'm') | |
| 1494 | countText.setAttribute('dy', '4') | |
| 1495 | countText.setAttribute('text-anchor', 'middle') | |
| 1496 | countText.setAttribute('font-size', '9') | |
| 1497 | countText.setAttribute('fill', n.type === 'dir' ? '#c9d1d9' : '#0d1117') | |
| 1498 | countText.setAttribute('font-weight', 'bold') | |
| 1499 | g.appendChild(countText) | |
| 1500 | ||
| 1501 | nodeGroup.appendChild(g) | |
| 1502 | n.el = g | |
| 1503 | ||
| 1504 | // Node drag | |
| 1505 | let dragStarted = false | |
| 1506 | let didDrag = false | |
| 1507 | g.addEventListener('mousedown', (e) => { | |
| 1508 | dragStarted = true | |
| 1509 | didDrag = false | |
| 1510 | n.fixed = true | |
| 1511 | e.stopPropagation() | |
| 1512 | e.preventDefault() | |
| 1513 | }) | |
| 1514 | ||
| 1515 | // Click behaviour depends on node type: | |
| 1516 | // directory → descend into it (single click) | |
| 1517 | // module → toggle focus (single click), drill into files (double click) | |
| 1518 | g.addEventListener('click', (e) => { | |
| 1519 | e.stopPropagation() | |
| 1520 | if (didDrag) return | |
| 1521 | if (n.type === 'dir') { | |
| 1522 | descendIntoDir(n.name) | |
| 1523 | return | |
| 1524 | } | |
| 1525 | if (focusedNode === i) { | |
| 1526 | unfocusAll() | |
| 1527 | document.getElementById('right-panel').style.display = 'none' | |
| 1528 | document.getElementById('resize-right').style.display = 'none' | |
| 1529 | } else { | |
| 1530 | focusModule(i) | |
| 1531 | showGraphModulePanel(n.name, n.mod) | |
| 1532 | } | |
| 1533 | }) | |
| 1534 | g.addEventListener('dblclick', (e) => { | |
| 1535 | e.stopPropagation() | |
| 1536 | if (n.type === 'dir') { | |
| 1537 | descendIntoDir(n.name) | |
| 1538 | } else { | |
| 1539 | drillIntoModule(n.name) | |
| 1540 | } | |
| 1541 | }) | |
| 1542 | ||
| 1543 | // Hover tooltip | |
| 1544 | g.addEventListener('mouseenter', () => showTooltip(n)) | |
| 1545 | g.addEventListener('mouseleave', hideTooltip) | |
| 1546 | } | |
| 1547 | ||
| 1548 | // --- Zoom / Pan --- | |
| 1549 | function updateTransform () { | |
| 1550 | graphGroup.setAttribute('transform', | |
| 1551 | 'translate(' + panX.toFixed(1) + ',' + panY.toFixed(1) + ') scale(' + zoom.toFixed(3) + ')') | |
| 1552 | } | |
| 1553 | ||
| 1554 | // Scroll to zoom | |
| 1555 | svg.addEventListener('wheel', (e) => { | |
| 1556 | e.preventDefault() | |
| 1557 | const delta = e.deltaY > 0 ? 0.9 : 1.1 | |
| 1558 | const newZoom = Math.max(0.1, Math.min(5, zoom * delta)) | |
| 1559 | // Zoom toward cursor | |
| 1560 | const svgRect = svg.getBoundingClientRect() | |
| 1561 | const mx = e.clientX - svgRect.left | |
| 1562 | const my = e.clientY - svgRect.top | |
| 1563 | panX = mx - (mx - panX) * (newZoom / zoom) | |
| 1564 | panY = my - (my - panY) * (newZoom / zoom) | |
| 1565 | zoom = newZoom | |
| 1566 | updateTransform() | |
| 1567 | }, { passive: false }) | |
| 1568 | ||
| 1569 | // Pan with mouse drag on background | |
| 1570 | svg.addEventListener('mousedown', (e) => { | |
| 1571 | if (e.target === svg || e.target.tagName === 'line') { | |
| 1572 | isPanning = true | |
| 1573 | panStartX = e.clientX - panX | |
| 1574 | panStartY = e.clientY - panY | |
| 1575 | svg.classList.add('dragging') | |
| 1576 | } | |
| 1577 | }) | |
| 1578 | ||
| 1579 | document.addEventListener('mousemove', (e) => { | |
| 1580 | const tooltip = document.getElementById('graph-tooltip') | |
| 1581 | tooltip.style.left = (e.clientX + 14) + 'px' | |
| 1582 | tooltip.style.top = (e.clientY + 14) + 'px' | |
| 1583 | ||
| 1584 | if (isPanning) { | |
| 1585 | panX = e.clientX - panStartX | |
| 1586 | panY = e.clientY - panStartY | |
| 1587 | updateTransform() | |
| 1588 | return | |
| 1589 | } | |
| 1590 | ||
| 1591 | // Node dragging (transform mouse coords to graph space) | |
| 1592 | for (const n of graphNodes) { | |
| 1593 | if (n.fixed) { | |
| 1594 | const svgRect = svg.getBoundingClientRect() | |
| 1595 | n.x = (e.clientX - svgRect.left - panX) / zoom | |
| 1596 | n.y = (e.clientY - svgRect.top - panY) / zoom | |
| 1597 | didDrag = true | |
| 1598 | } | |
| 1599 | } | |
| 1600 | }) | |
| 1601 | ||
| 1602 | document.addEventListener('mouseup', () => { | |
| 1603 | isPanning = false | |
| 1604 | svg.classList.remove('dragging') | |
| 1605 | for (const n of graphNodes) n.fixed = false | |
| 1606 | }) | |
| 1607 | ||
| 1608 | // Click background to unfocus | |
| 1609 | svg.addEventListener('click', (e) => { | |
| 1610 | if (e.target === svg) unfocusAll() | |
| 1611 | }) | |
| 1612 | ||
| 1613 | // Zoom buttons | |
| 1614 | document.getElementById('zoom-in').addEventListener('click', () => { | |
| 1615 | zoom = Math.min(5, zoom * 1.3) | |
| 1616 | updateTransform() | |
| 1617 | }) | |
| 1618 | document.getElementById('zoom-out').addEventListener('click', () => { | |
| 1619 | zoom = Math.max(0.1, zoom * 0.7) | |
| 1620 | updateTransform() | |
| 1621 | }) | |
| 1622 | document.getElementById('zoom-reset').addEventListener('click', () => { | |
| 1623 | zoom = 1; panX = 0; panY = 0 | |
| 1624 | updateTransform() | |
| 1625 | unfocusAll() | |
| 1626 | }) | |
| 1627 | ||
| 1628 | // --- Force simulation (label-aware) --- | |
| 1629 | // Estimate label width per node | |
| 1630 | for (const n of graphNodes) { | |
| 1631 | n.labelW = n.name.length * 7 + n.r * 2 + 10 | |
| 1632 | } | |
| 1633 | ||
| 1634 | // Simulation control: alpha cools the system over time. Below SIM_FREEZE | |
| 1635 | // the simulation halts entirely. Without this, an N-node graph runs O(N^2) | |
| 1636 | // every frame forever — at 400+ nodes that's 80k+ pair calcs per frame | |
| 1637 | // and the graph "explodes" visually because forces never settle. | |
| 1638 | let simAlpha = 1.0 | |
| 1639 | const SIM_DECAY = 0.985 // multiplies each frame, ~300 frames to settle | |
| 1640 | const SIM_FREEZE = 0.02 // stop simulating below this | |
| 1641 | let simRafId = null | |
| 1642 | ||
| 1643 | // Re-heat on user interaction (drag, focus, restart). Cheap public hook. | |
| 1644 | window.restartSim = function (alpha) { | |
| 1645 | simAlpha = alpha != null ? alpha : Math.max(simAlpha, 0.6) | |
| 1646 | if (simRafId === null) simRafId = requestAnimationFrame(simulate) | |
| 1647 | } | |
| 1648 | ||
| 1649 | function simulate () { | |
| 1650 | simRafId = null | |
| 1651 | const a = simAlpha | |
| 1652 | ||
| 1653 | const attraction = 0.003 * a | |
| 1654 | const damping = 0.85 | |
| 1655 | const centerForce = 0.006 * a | |
| 1656 | ||
| 1657 | // Category-aware forces: same group attracts, different group repels more | |
| 1658 | for (let i = 0; i < graphNodes.length; i++) { | |
| 1659 | for (let j = i + 1; j < graphNodes.length; j++) { | |
| 1660 | const na = graphNodes[i], nb = graphNodes[j] | |
| 1661 | let dx = nb.x - na.x, dy = nb.y - na.y | |
| 1662 | let dist = Math.sqrt(dx * dx + dy * dy) || 1 | |
| 1663 | const sameGroup = na.category && nb.category && na.category === nb.category | |
| 1664 | const minDist = (na.labelW + nb.labelW) / 2 + (sameGroup ? 5 : 30) | |
| 1665 | ||
| 1666 | let force | |
| 1667 | if (dist < minDist) { | |
| 1668 | // Overlap: push apart (stronger for different groups) | |
| 1669 | force = (minDist - dist) * (sameGroup ? 0.06 : 0.15) | |
| 1670 | } else if (sameGroup && dist > 80) { | |
| 1671 | // Same group but far apart: pull together | |
| 1672 | force = -(dist - 80) * 0.002 | |
| 1673 | } else { | |
| 1674 | // General repulsion (stronger between groups) | |
| 1675 | force = (sameGroup ? 1000 : 3000) / (dist * dist) | |
| 1676 | } | |
| 1677 | force *= a | |
| 1678 | const fx = (dx / dist) * force, fy = (dy / dist) * force | |
| 1679 | if (!na.fixed) { na.vx -= fx; na.vy -= fy } | |
| 1680 | if (!nb.fixed) { nb.vx += fx; nb.vy += fy } | |
| 1681 | } | |
| 1682 | } | |
| 1683 | ||
| 1684 | for (const edge of graphEdges) { | |
| 1685 | const na = graphNodes[edge.source], nb = graphNodes[edge.target] | |
| 1686 | const dx = nb.x - na.x, dy = nb.y - na.y | |
| 1687 | const dist = Math.sqrt(dx * dx + dy * dy) || 1 | |
| 1688 | const force = (dist - 180) * attraction | |
| 1689 | const fx = (dx / dist) * force, fy = (dy / dist) * force | |
| 1690 | if (!na.fixed) { na.vx += fx; na.vy += fy } | |
| 1691 | if (!nb.fixed) { nb.vx -= fx; nb.vy -= fy } | |
| 1692 | } | |
| 1693 | ||
| 1694 | for (const n of graphNodes) { | |
| 1695 | if (n.fixed) continue | |
| 1696 | n.vx += (cx - n.x) * centerForce | |
| 1697 | n.vy += (cy - n.y) * centerForce | |
| 1698 | n.vx *= damping; n.vy *= damping | |
| 1699 | n.x += n.vx; n.y += n.vy | |
| 1700 | } | |
| 1701 | ||
| 1702 | // Update positions | |
| 1703 | for (const n of graphNodes) { | |
| 1704 | n.el.setAttribute('transform', 'translate(' + n.x.toFixed(1) + ',' + n.y.toFixed(1) + ')') | |
| 1705 | } | |
| 1706 | for (const edge of graphEdges) { | |
| 1707 | const a = graphNodes[edge.source], b = graphNodes[edge.target] | |
| 1708 | // Shorten line so arrow doesn't overlap circle | |
| 1709 | const dx = b.x - a.x, dy = b.y - a.y | |
| 1710 | const dist = Math.sqrt(dx * dx + dy * dy) || 1 | |
| 1711 | const offsetA = a.r + 2, offsetB = b.r + 6 | |
| 1712 | edge.el.setAttribute('x1', (a.x + dx / dist * offsetA).toFixed(1)) | |
| 1713 | edge.el.setAttribute('y1', (a.y + dy / dist * offsetA).toFixed(1)) | |
| 1714 | edge.el.setAttribute('x2', (b.x - dx / dist * offsetB).toFixed(1)) | |
| 1715 | edge.el.setAttribute('y2', (b.y - dy / dist * offsetB).toFixed(1)) | |
| 1716 | } | |
| 1717 | ||
| 1718 | // Update region positions to follow their nodes | |
| 1719 | if (gfx.showRegions) { | |
| 1720 | document.querySelectorAll('.graph-region').forEach(region => { | |
| 1721 | const cat = region.dataset.cat | |
| 1722 | const group = catGroups[cat] | |
| 1723 | if (!group) return | |
| 1724 | const nodes = group.map(i => graphNodes[i]) | |
| 1725 | let ax = 0, ay = 0 | |
| 1726 | for (const n of nodes) { ax += n.x; ay += n.y } | |
| 1727 | ax /= nodes.length; ay /= nodes.length | |
| 1728 | let maxDist = 0 | |
| 1729 | for (const n of nodes) { | |
| 1730 | const d = Math.sqrt((n.x - ax) ** 2 + (n.y - ay) ** 2) + n.r | |
| 1731 | if (d > maxDist) maxDist = d | |
| 1732 | } | |
| 1733 | region.setAttribute('cx', ax) | |
| 1734 | region.setAttribute('cy', ay) | |
| 1735 | region.setAttribute('r', maxDist + 30) | |
| 1736 | }) | |
| 1737 | document.querySelectorAll('g.graph-region-label').forEach(labelG => { | |
| 1738 | const cat = labelG.dataset.cat | |
| 1739 | const region = document.querySelector('.graph-region[data-cat="' + cat + '"]') | |
| 1740 | if (!region) return | |
| 1741 | const rcx = parseFloat(region.getAttribute('cx')) | |
| 1742 | const rcy = parseFloat(region.getAttribute('cy')) | |
| 1743 | const rr = parseFloat(region.getAttribute('r')) | |
| 1744 | const textEl = labelG.querySelector('text') | |
| 1745 | const bgEl = labelG.querySelector('rect') | |
| 1746 | if (textEl) { | |
| 1747 | textEl.setAttribute('x', rcx) | |
| 1748 | textEl.setAttribute('y', rcy - rr - 12) | |
| 1749 | } | |
| 1750 | if (bgEl) { | |
| 1751 | const tw = parseFloat(bgEl.getAttribute('width')) | |
| 1752 | bgEl.setAttribute('x', rcx - tw / 2) | |
| 1753 | bgEl.setAttribute('y', rcy - rr - 28) | |
| 1754 | } | |
| 1755 | }) | |
| 1756 | } | |
| 1757 | ||
| 1758 | // Decay alpha and decide whether to keep simulating | |
| 1759 | simAlpha *= SIM_DECAY | |
| 1760 | if (simAlpha > SIM_FREEZE) { | |
| 1761 | simRafId = requestAnimationFrame(simulate) | |
| 1762 | } else { | |
| 1763 | simAlpha = 0 // frozen — restartSim() will re-heat | |
| 1764 | simRafId = null | |
| 1765 | } | |
| 1766 | } | |
| 1767 | ||
| 1768 | // For large graphs, skip force simulation entirely. The O(N^2) pairwise | |
| 1769 | // calculation per frame becomes unworkable above ~150 nodes (90k+ ops | |
| 1770 | // per frame). The initial category-ring layout is good enough; users can | |
| 1771 | // drag nodes to refine. Edges still render; nodes are just static. | |
| 1772 | // | |
| 1773 | // Adjust BIG_GRAPH_THRESHOLD if your machine is faster/slower. | |
| 1774 | const BIG_GRAPH_THRESHOLD = 150 | |
| 1775 | if (graphNodes.length > BIG_GRAPH_THRESHOLD) { | |
| 1776 | simAlpha = 0 | |
| 1777 | // Render once to position elements at their initial coordinates | |
| 1778 | for (const n of graphNodes) { | |
| 1779 | n.el.setAttribute('transform', 'translate(' + n.x.toFixed(1) + ',' + n.y.toFixed(1) + ')') | |
| 1780 | } | |
| 1781 | for (const edge of graphEdges) { | |
| 1782 | const na = graphNodes[edge.source], nb = graphNodes[edge.target] | |
| 1783 | const dx = nb.x - na.x, dy = nb.y - na.y | |
| 1784 | const dist = Math.sqrt(dx * dx + dy * dy) || 1 | |
| 1785 | const offsetA = na.r + 2, offsetB = nb.r + 6 | |
| 1786 | edge.el.setAttribute('x1', (na.x + dx / dist * offsetA).toFixed(1)) | |
| 1787 | edge.el.setAttribute('y1', (na.y + dy / dist * offsetA).toFixed(1)) | |
| 1788 | edge.el.setAttribute('x2', (nb.x - dx / dist * offsetB).toFixed(1)) | |
| 1789 | edge.el.setAttribute('y2', (nb.y - dy / dist * offsetB).toFixed(1)) | |
| 1790 | } | |
| 1791 | } else { | |
| 1792 | simRafId = requestAnimationFrame(simulate) | |
| 1793 | } | |
| 1794 | showGraphSettings() | |
| 1795 | } | |
| 1796 | ||
| 1797 | // --- Focus a module: highlight its connections --- | |
| 1798 | function focusModule (idx) { | |
| 1799 | focusedNode = idx | |
| 1800 | const n = graphNodes[idx] | |
| 1801 | const connected = new Set([idx]) | |
| 1802 | for (const t of n.dependsOn) connected.add(t) | |
| 1803 | for (const s of n.usedBy) connected.add(s) | |
| 1804 | ||
| 1805 | // Dim all nodes | |
| 1806 | for (const node of graphNodes) { | |
| 1807 | node.el.classList.toggle('dimmed', !connected.has(node.idx)) | |
| 1808 | node.el.classList.toggle('focused', node.idx === idx) | |
| 1809 | } | |
| 1810 | ||
| 1811 | // Color edges | |
| 1812 | for (const edge of graphEdges) { | |
| 1813 | const isDepOf = edge.source === idx // focused depends on target | |
| 1814 | const isUsedBy = edge.target === idx // source depends on focused | |
| 1815 | const isConnected = isDepOf || isUsedBy | |
| 1816 | ||
| 1817 | edge.el.classList.toggle('dimmed', !isConnected) | |
| 1818 | edge.el.classList.toggle('depends-on', isDepOf) | |
| 1819 | edge.el.classList.toggle('dep-of', isUsedBy) | |
| 1820 | ||
| 1821 | // Arrow color | |
| 1822 | if (isDepOf) edge.el.setAttribute('marker-end', 'url(#arrowhead-green)') | |
| 1823 | else if (isUsedBy) edge.el.setAttribute('marker-end', 'url(#arrowhead-blue)') | |
| 1824 | else edge.el.setAttribute('marker-end', 'url(#arrowhead)') | |
| 1825 | } | |
| 1826 | ||
| 1827 | // Show detail | |
| 1828 | showDetail('module', { name: n.name, mod: n.mod }) | |
| 1829 | ||
| 1830 | // Also show connections in detail panel | |
| 1831 | const panel = document.getElementById('detail-content') | |
| 1832 | let extra = '' | |
| 1833 | if (n.dependsOn.length > 0) { | |
| 1834 | extra += '<div class="detail"><h3 style="color:#3fb950">Depends on (' + n.dependsOn.length + ')</h3><pre><code>' | |
| 1835 | extra += n.dependsOn.map(t => graphNodes[t].name).join('\\n') | |
| 1836 | extra += '</code></pre></div>' | |
| 1837 | } | |
| 1838 | if (n.usedBy.length > 0) { | |
| 1839 | extra += '<div class="detail"><h3 style="color:#58a6ff">Used by (' + n.usedBy.length + ')</h3><pre><code>' | |
| 1840 | extra += n.usedBy.map(s => graphNodes[s].name).join('\\n') | |
| 1841 | extra += '</code></pre></div>' | |
| 1842 | } | |
| 1843 | if (extra) panel.innerHTML += extra | |
| 1844 | } | |
| 1845 | ||
| 1846 | function unfocusAll () { | |
| 1847 | focusedNode = null | |
| 1848 | for (const node of graphNodes) { | |
| 1849 | node.el.classList.remove('dimmed', 'focused') | |
| 1850 | } | |
| 1851 | for (const edge of graphEdges) { | |
| 1852 | edge.el.classList.remove('dimmed', 'depends-on', 'dep-of') | |
| 1853 | edge.el.setAttribute('marker-end', 'url(#arrowhead)') | |
| 1854 | } | |
| 1855 | } | |
| 1856 | ||
| 1857 | function showTooltip (n) { | |
| 1858 | const tooltip = document.getElementById('graph-tooltip') | |
| 1859 | const depsOn = n.dependsOn.map(t => graphNodes[t].name) | |
| 1860 | const usedBy = n.usedBy.map(s => graphNodes[s].name) | |
| 1861 | tooltip.innerHTML = '<strong>' + n.name + '</strong> ' + n.mod.version + | |
| 1862 | '<br>' + n.fileCount + ' files, ' + n.memberCount + ' members, ' + n.mod.publicAPI.length + ' exports' + | |
| 1863 | (depsOn.length ? '<br><span class="tt-deps">depends on: ' + depsOn.join(', ') + '</span>' : '') + | |
| 1864 | (usedBy.length ? '<br><span class="tt-used">used by: ' + usedBy.join(', ') + '</span>' : '') + | |
| 1865 | (n.mod.publicAPI.length ? '<br>API: ' + n.mod.publicAPI.slice(0, 6).join(', ') + (n.mod.publicAPI.length > 6 ? '...' : '') : '') | |
| 1866 | tooltip.style.display = 'block' | |
| 1867 | } | |
| 1868 | ||
| 1869 | function hideTooltip () { | |
| 1870 | document.getElementById('graph-tooltip').style.display = 'none' | |
| 1871 | } | |
| 1872 | ||
| 1873 | function moduleColor (name) { | |
| 1874 | const colors = ['#f0883e', '#58a6ff', '#d2a8ff', '#7ee787', '#ff7b72', '#79c0ff', | |
| 1875 | '#ffa657', '#3fb950', '#bc8cff', '#f778ba', '#56d364', '#79c0ff'] | |
| 1876 | let hash = 0 | |
| 1877 | for (let i = 0; i < name.length; i++) hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0 | |
| 1878 | return colors[Math.abs(hash) % colors.length] | |
| 1879 | } | |
| 1880 | ||
| 1881 | // ====== GRAPH DRILL-DOWN ====== | |
| 1882 | let graphLevel = 'system' // 'system' | 'module' | 'file' | |
| 1883 | let graphStack = [] // breadcrumb trail | |
| 1884 | ||
| 1885 | function updateBreadcrumb () { | |
| 1886 | const bc = document.getElementById('graph-breadcrumb') | |
| 1887 | let html = '<span onclick="navigateGraph(0)">System</span>' | |
| 1888 | for (let i = 0; i < graphStack.length; i++) { | |
| 1889 | html += '<span class="sep">></span>' | |
| 1890 | const isFinal = i === graphStack.length - 1 | |
| 1891 | html += '<span class="' + (isFinal ? 'current' : '') + '" onclick="navigateGraph(' + (i + 1) + ')">' + graphStack[i].label + '</span>' | |
| 1892 | } | |
| 1893 | bc.innerHTML = html | |
| 1894 | } | |
| 1895 | ||
| 1896 | // Expose for onclick | |
| 1897 | window.navigateGraph = function (level) { | |
| 1898 | if (level === 0) { | |
| 1899 | graphStack = [] | |
| 1900 | graphLevel = 'system' | |
| 1901 | rebuildGraph() | |
| 1902 | syncTreeWithGraph() | |
| 1903 | } else if (level <= graphStack.length) { | |
| 1904 | graphStack = graphStack.slice(0, level) | |
| 1905 | const entry = graphStack[graphStack.length - 1] | |
| 1906 | if (entry.type === 'module') drillIntoModule(entry.name, true) | |
| 1907 | else if (entry.type === 'file') drillIntoFile(entry.moduleName, entry.name, true) | |
| 1908 | else if (entry.type === 'path') { rebuildGraph(); syncTreeWithGraph() } | |
| 1909 | } | |
| 1910 | } | |
| 1911 | ||
| 1912 | function rebuildGraph () { | |
| 1913 | graphInitialized = false | |
| 1914 | graphNodes.length = 0 | |
| 1915 | graphEdges.length = 0 | |
| 1916 | focusedNode = null | |
| 1917 | zoom = 1; panX = 0; panY = 0 | |
| 1918 | initGraph() | |
| 1919 | updateBreadcrumb() | |
| 1920 | // Note: tree sidebar is NOT re-synced here. Sliders (spacing, forceStrength, | |
| 1921 | // groupBy) call rebuildGraph many times per second; tree sync would make | |
| 1922 | // them chug. Call syncTreeWithGraph() instead when the PATH changes. | |
| 1923 | } | |
| 1924 | ||
| 1925 | // Throttle full rebuilds (e.g. groupBy change) to one per animation frame. | |
| 1926 | let pendingRebuild = false | |
| 1927 | function scheduleRebuild () { | |
| 1928 | if (pendingRebuild) return | |
| 1929 | pendingRebuild = true | |
| 1930 | requestAnimationFrame(() => { | |
| 1931 | pendingRebuild = false | |
| 1932 | if (graphStack.length === 0) { | |
| 1933 | rebuildGraph() | |
| 1934 | } else { | |
| 1935 | const top = graphStack[0] | |
| 1936 | if (top.type === 'module') drillIntoModule(top.name, true) | |
| 1937 | else rebuildGraph() | |
| 1938 | } | |
| 1939 | }) | |
| 1940 | } | |
| 1941 | ||
| 1942 | // Fast reposition: recompute node coordinates from the current gfx.spacing | |
| 1943 | // value and update SVG transforms. No teardown, no rebuild. Throttled to rAF | |
| 1944 | // so a slider drag becomes one repaint per frame regardless of how many | |
| 1945 | // oninput events fire. | |
| 1946 | let pendingReposition = false | |
| 1947 | function repositionForSpacing () { | |
| 1948 | if (pendingReposition) return | |
| 1949 | pendingReposition = true | |
| 1950 | requestAnimationFrame(() => { | |
| 1951 | pendingReposition = false | |
| 1952 | if (graphNodes.length === 0) return | |
| 1953 | ||
| 1954 | const svg = document.getElementById('graph-svg') | |
| 1955 | const rect = svg.getBoundingClientRect() | |
| 1956 | const W = rect.width, H = rect.height | |
| 1957 | const cx = W / 2, cy = H / 2 | |
| 1958 | const spaceMult = 0.5 + (gfx.spacing / 100) * 2 | |
| 1959 | ||
| 1960 | // Re-derive cat groups from current node categories | |
| 1961 | const catGroups = {} | |
| 1962 | for (const n of graphNodes) { | |
| 1963 | if (!catGroups[n.category]) catGroups[n.category] = [] | |
| 1964 | catGroups[n.category].push(n) | |
| 1965 | } | |
| 1966 | const catList = Object.keys(catGroups) | |
| 1967 | ||
| 1968 | for (const n of graphNodes) { | |
| 1969 | const catI = catList.indexOf(n.category) | |
| 1970 | const group = catGroups[n.category] | |
| 1971 | const posInGroup = group.indexOf(n) | |
| 1972 | const catAngle = (catI / catList.length) * Math.PI * 2 - Math.PI / 2 | |
| 1973 | const catRadius = (Math.min(W, H) * 0.2 + catList.length * 8) * spaceMult | |
| 1974 | const nodeAngle = (posInGroup / group.length) * Math.PI * 2 | |
| 1975 | const nodeRadius = Math.min(80, 20 + group.length * 10) * (0.7 + spaceMult * 0.3) | |
| 1976 | n.x = cx + Math.cos(catAngle) * catRadius + Math.cos(nodeAngle) * nodeRadius | |
| 1977 | n.y = cy + Math.sin(catAngle) * catRadius + Math.sin(nodeAngle) * nodeRadius | |
| 1978 | n.vx = 0; n.vy = 0 | |
| 1979 | if (n.el) n.el.setAttribute('transform', 'translate(' + n.x.toFixed(1) + ',' + n.y.toFixed(1) + ')') | |
| 1980 | } | |
| 1981 | ||
| 1982 | for (const edge of graphEdges) { | |
| 1983 | const na = graphNodes[edge.source], nb = graphNodes[edge.target] | |
| 1984 | const dx = nb.x - na.x, dy = nb.y - na.y | |
| 1985 | const dist = Math.sqrt(dx * dx + dy * dy) || 1 | |
| 1986 | const offsetA = na.r + 2, offsetB = nb.r + 6 | |
| 1987 | if (edge.el) { | |
| 1988 | edge.el.setAttribute('x1', (na.x + dx / dist * offsetA).toFixed(1)) | |
| 1989 | edge.el.setAttribute('y1', (na.y + dy / dist * offsetA).toFixed(1)) | |
| 1990 | edge.el.setAttribute('x2', (nb.x - dx / dist * offsetB).toFixed(1)) | |
| 1991 | edge.el.setAttribute('y2', (nb.y - dy / dist * offsetB).toFixed(1)) | |
| 1992 | } | |
| 1993 | } | |
| 1994 | ||
| 1995 | // Re-heat the simulation if it was running, so any post-spacing forces | |
| 1996 | // settle naturally instead of snapping. No-op if sim is permanently off | |
| 1997 | // (large-graph case). | |
| 1998 | if (typeof window.restartSim === 'function') window.restartSim(0.4) | |
| 1999 | }) | |
| 2000 | } | |
| 2001 | ||
| 2002 | // Re-sync the file-tree sidebar with the current graph location. Called on | |
| 2003 | // path navigation, not on slider tweaks. | |
| 2004 | function syncTreeWithGraph () { | |
| 2005 | buildTree() | |
| 2006 | } | |
| 2007 | ||
| 2008 | // --- Toggle state --- | |
| 2009 | // Graph settings — all toggleable | |
| 2010 | const gfx = { | |
| 2011 | showLabels: true, | |
| 2012 | dimTests: false, | |
| 2013 | showRegions: true, // category background regions | |
| 2014 | sizeBy: 'members', // 'members' | 'deps' | 'exports' | |
| 2015 | groupBy: 'category', // 'category' | 'deps' | 'none' | |
| 2016 | forceStrength: 0, // 0 = hierarchy, 100 = force | |
| 2017 | spacing: 50, // 0 = tight, 100 = max spread | |
| 2018 | showEdgeLabels: false, // show import names on edges | |
| 2019 | labelPos: 'below', // 'below' | 'right' | 'radial' | |
| 2020 | } | |
| 2021 | let expandedNodes = new Set() | |
| 2022 | ||
| 2023 | function drillIntoModule (moduleName, fromNav) { | |
| 2024 | const mod = tree.modules[moduleName] | |
| 2025 | if (!mod) return | |
| 2026 | ||
| 2027 | // If the module came from a shallow scan, fetch the deep version on demand. | |
| 2028 | // Marker: shallow-scanned modules have only ~1 entry in files (the entry file) | |
| 2029 | // and tree.shallow === true. Avoid re-fetching once we've already loaded deep. | |
| 2030 | if (tree.shallow && !mod.__deepLoaded && Object.keys(mod.files).length <= 1) { | |
| 2031 | fetch(API + '/api/deep-scan?module=' + encodeURIComponent(moduleName)) | |
| 2032 | .then(r => r.json()) | |
| 2033 | .then(data => { | |
| 2034 | if (data && data.mod) { | |
| 2035 | // Replace the placeholder with the full module data, mark loaded, | |
| 2036 | // then re-enter drillIntoModule to render with the new data. | |
| 2037 | data.mod.__deepLoaded = true | |
| 2038 | tree.modules[moduleName] = data.mod | |
| 2039 | drillIntoModule(moduleName, fromNav) | |
| 2040 | } | |
| 2041 | }) | |
| 2042 | .catch(() => {}) | |
| 2043 | // Render a "loading" stub immediately so user sees feedback | |
| 2044 | } | |
| 2045 | ||
| 2046 | if (!fromNav) { | |
| 2047 | graphStack = [{ type: 'module', name: moduleName, label: moduleName }] | |
| 2048 | } | |
| 2049 | graphLevel = 'module' | |
| 2050 | expandedNodes.clear() | |
| 2051 | ||
| 2052 | const svg = document.getElementById('graph-svg') | |
| 2053 | const rect = svg.getBoundingClientRect() | |
| 2054 | const W = rect.width, H = rect.height | |
| 2055 | const cx = W / 2, cy = H / 2 | |
| 2056 | ||
| 2057 | graphNodes.length = 0 | |
| 2058 | graphEdges.length = 0 | |
| 2059 | focusedNode = null | |
| 2060 | zoom = 1; panX = 0; panY = 0 | |
| 2061 | ||
| 2062 | // Build file nodes with import-depth based radial layout | |
| 2063 | const files = Object.entries(mod.files) | |
| 2064 | const nameToIdx = {} | |
| 2065 | const fileData = [] | |
| 2066 | ||
| 2067 | for (let i = 0; i < files.length; i++) { | |
| 2068 | const [path, file] = files[i] | |
| 2069 | nameToIdx[path] = i | |
| 2070 | let memberCount = 0 | |
| 2071 | if (file.classes) for (const c of file.classes) memberCount += c.methods.length + (c.getters ? c.getters.length : 0) | |
| 2072 | if (file.functions) memberCount += file.functions.length | |
| 2073 | let exportCount = file.exports ? file.exports.length : 0 | |
| 2074 | fileData.push({ path, file, memberCount, exportCount, role: file.role || 'lib' }) | |
| 2075 | } | |
| 2076 | ||
| 2077 | // Build edge list first to compute depths | |
| 2078 | const edgeList = [] | |
| 2079 | for (let i = 0; i < files.length; i++) { | |
| 2080 | const file = fileData[i].file | |
| 2081 | if (!file.imports) continue | |
| 2082 | for (const imp of file.imports) { | |
| 2083 | for (let j = 0; j < files.length; j++) { | |
| 2084 | if (i === j) continue | |
| 2085 | const tp = fileData[j].path | |
| 2086 | if (imp.specifier.endsWith(tp) || imp.specifier === './' + tp || | |
| 2087 | tp.endsWith(imp.specifier.replace('./', ''))) { | |
| 2088 | edgeList.push({ source: i, target: j, labels: imp.names || [] }) | |
| 2089 | } | |
| 2090 | } | |
| 2091 | } | |
| 2092 | } | |
| 2093 | ||
| 2094 | // BFS from entry to compute depth | |
| 2095 | const entryIdx = fileData.findIndex(f => f.role === 'entry') | |
| 2096 | const depth = new Array(files.length).fill(-1) | |
| 2097 | if (entryIdx >= 0) { | |
| 2098 | depth[entryIdx] = 0 | |
| 2099 | const queue = [entryIdx] | |
| 2100 | while (queue.length > 0) { | |
| 2101 | const cur = queue.shift() | |
| 2102 | for (const e of edgeList) { | |
| 2103 | if (e.source === cur && depth[e.target] === -1) { | |
| 2104 | depth[e.target] = depth[cur] + 1 | |
| 2105 | queue.push(e.target) | |
| 2106 | } | |
| 2107 | } | |
| 2108 | } | |
| 2109 | } | |
| 2110 | // Assign unvisited nodes (tests, disconnected) to outer ring | |
| 2111 | const maxDepth = Math.max(1, ...depth.filter(d => d >= 0)) | |
| 2112 | for (let i = 0; i < depth.length; i++) { | |
| 2113 | if (depth[i] === -1) depth[i] = maxDepth + (fileData[i].role === 'test' ? 1 : 0) + 1 | |
| 2114 | } | |
| 2115 | ||
| 2116 | // Group by depth | |
| 2117 | const byDepth = {} | |
| 2118 | for (let i = 0; i < files.length; i++) { | |
| 2119 | const d = depth[i] | |
| 2120 | if (!byDepth[d]) byDepth[d] = [] | |
| 2121 | byDepth[d].push(i) | |
| 2122 | } | |
| 2123 | ||
| 2124 | const depthLevels = Object.keys(byDepth).map(Number).sort((a, b) => a - b) | |
| 2125 | ||
| 2126 | // Estimate label width: ~7px per char | |
| 2127 | function labelWidth (name) { | |
| 2128 | const short = name.includes('/') ? name.split('/').pop() : name | |
| 2129 | return short.length * 7 + 30 // text + padding + node radius | |
| 2130 | } | |
| 2131 | ||
| 2132 | // Compute hierarchy positions (top-down layered) | |
| 2133 | const rowHeight = 90 | |
| 2134 | const startY = 60 | |
| 2135 | ||
| 2136 | for (const d of depthLevels) { | |
| 2137 | const group = byDepth[d] | |
| 2138 | const widths = group.map(i => labelWidth(fileData[i].path)) | |
| 2139 | const totalWidth = widths.reduce((a, b) => a + b, 0) + (group.length - 1) * 20 | |
| 2140 | let xPos = cx - totalWidth / 2 | |
| 2141 | ||
| 2142 | for (let j = 0; j < group.length; j++) { | |
| 2143 | const i = group[j] | |
| 2144 | const fd = fileData[i] | |
| 2145 | const nodeR = Math.max(8, Math.min(30, 6 + Math.sqrt(fd.memberCount) * 2.5)) | |
| 2146 | const w = widths[j] | |
| 2147 | const hx = xPos + w / 2 | |
| 2148 | const hy = startY + d * rowHeight | |
| 2149 | ||
| 2150 | graphNodes.push({ | |
| 2151 | idx: i, name: fd.path, path: fd.path, file: fd.file, moduleName, | |
| 2152 | x: hx, y: hy, | |
| 2153 | hierX: hx, hierY: hy, // stored hierarchy position | |
| 2154 | vx: 0, vy: 0, | |
| 2155 | r: nodeR, | |
| 2156 | labelW: w, | |
| 2157 | memberCount: fd.memberCount, | |
| 2158 | exportCount: fd.exportCount, | |
| 2159 | depth: d, | |
| 2160 | color: roleColor(fd.role), | |
| 2161 | role: fd.role, | |
| 2162 | dependsOn: [], usedBy: [] | |
| 2163 | }) | |
| 2164 | xPos += w + 20 | |
| 2165 | } | |
| 2166 | } | |
| 2167 | ||
| 2168 | // Build edges with label info | |
| 2169 | for (const e of edgeList) { | |
| 2170 | graphEdges.push({ source: e.source, target: e.target, labels: e.labels }) | |
| 2171 | graphNodes[e.source].dependsOn.push(e.target) | |
| 2172 | graphNodes[e.target].usedBy.push(e.source) | |
| 2173 | } | |
| 2174 | ||
| 2175 | renderSubGraph(svg, cx, cy, W, H, 'file') | |
| 2176 | showGraphSettings() | |
| 2177 | updateBreadcrumb() | |
| 2178 | } | |
| 2179 | ||
| 2180 | function showGraphSettings () { | |
| 2181 | let panel = document.getElementById('graph-settings') | |
| 2182 | if (!panel) { | |
| 2183 | panel = document.createElement('div') | |
| 2184 | panel.id = 'graph-settings' | |
| 2185 | panel.className = 'graph-settings' | |
| 2186 | document.getElementById('graph-container').appendChild(panel) | |
| 2187 | } | |
| 2188 | ||
| 2189 | panel.innerHTML = | |
| 2190 | '<h4>Layout</h4>' + | |
| 2191 | '<div class="gs-row"><label>Hierarchy</label>' + | |
| 2192 | '<input type="range" min="0" max="100" value="' + gfx.forceStrength + '" oninput="gfxSet("forceStrength",+this.value)">' + | |
| 2193 | '<label>Force</label></div>' + | |
| 2194 | ||
| 2195 | '<div class="gs-row"><label>Spacing</label>' + | |
| 2196 | '<input type="range" min="0" max="100" value="' + gfx.spacing + '" oninput="gfxSet("spacing",+this.value)">' + | |
| 2197 | '</div>' + | |
| 2198 | ||
| 2199 | '<div class="gs-divider"></div><h4>Grouping</h4>' + | |
| 2200 | '<div class="gs-row"><label>Group by</label>' + | |
| 2201 | '<select onchange="gfxSet("groupBy",this.value)">' + | |
| 2202 | '<option value="category"' + (gfx.groupBy === 'category' ? ' selected' : '') + '>Spec Categories</option>' + | |
| 2203 | '<option value="deps"' + (gfx.groupBy === 'deps' ? ' selected' : '') + '>Shared Dependencies</option>' + | |
| 2204 | '<option value="none"' + (gfx.groupBy === 'none' ? ' selected' : '') + '>None</option>' + | |
| 2205 | '</select></div>' + | |
| 2206 | '<div class="gs-row"><input type="checkbox"' + (gfx.showRegions ? ' checked' : '') + ' onchange="gfxSet("showRegions",this.checked)"><label>Show region backgrounds</label></div>' + | |
| 2207 | ||
| 2208 | '<div class="gs-divider"></div><h4>Node Size</h4>' + | |
| 2209 | '<div class="gs-row"><label>Size by</label>' + | |
| 2210 | '<select onchange="gfxSet("sizeBy",this.value)">' + | |
| 2211 | '<option value="members"' + (gfx.sizeBy === 'members' ? ' selected' : '') + '>Member Count</option>' + | |
| 2212 | '<option value="deps"' + (gfx.sizeBy === 'deps' ? ' selected' : '') + '>Dependents (who uses this)</option>' + | |
| 2213 | '<option value="exports"' + (gfx.sizeBy === 'exports' ? ' selected' : '') + '>Export Count</option>' + | |
| 2214 | '</select></div>' + | |
| 2215 | ||
| 2216 | '<div class="gs-divider"></div><h4>Labels</h4>' + | |
| 2217 | '<div class="gs-row"><label>Position</label>' + | |
| 2218 | '<select onchange="gfxSet("labelPos",this.value)">' + | |
| 2219 | '<option value="below"' + (gfx.labelPos === 'below' ? ' selected' : '') + '>Below</option>' + | |
| 2220 | '<option value="right"' + (gfx.labelPos === 'right' ? ' selected' : '') + '>Right</option>' + | |
| 2221 | '<option value="radial"' + (gfx.labelPos === 'radial' ? ' selected' : '') + '>Radial (outward)</option>' + | |
| 2222 | '</select></div>' + | |
| 2223 | '<div class="gs-row"><input type="checkbox"' + (gfx.showEdgeLabels ? ' checked' : '') + ' onchange="gfxSet("showEdgeLabels",this.checked)"><label>Show edge import names</label></div>' + | |
| 2224 | '<div class="gs-row"><input type="checkbox"' + (gfx.showLabels ? ' checked' : '') + ' onchange="gfxSet("showLabels",this.checked)"><label>Show node labels</label></div>' + | |
| 2225 | '<div class="gs-row"><input type="checkbox"' + (gfx.dimTests ? ' checked' : '') + ' onchange="gfxSet("dimTests",this.checked)"><label>Dim test files</label></div>' | |
| 2226 | } | |
| 2227 | ||
| 2228 | window.gfxSet = function (key, value) { | |
| 2229 | gfx[key] = value | |
| 2230 | ||
| 2231 | // Immediate effects | |
| 2232 | if (key === 'forceStrength' && value === 0) { | |
| 2233 | for (const n of graphNodes) { | |
| 2234 | if (n.hierX !== undefined) { n.x = n.hierX; n.y = n.hierY; n.vx = 0; n.vy = 0 } | |
| 2235 | } | |
| 2236 | } | |
| 2237 | if (key === 'showLabels') { | |
| 2238 | for (const n of graphNodes) { | |
| 2239 | if (n.labelEl) n.labelEl.style.display = value ? '' : 'none' | |
| 2240 | } | |
| 2241 | } | |
| 2242 | if (key === 'dimTests') { | |
| 2243 | for (const n of graphNodes) { | |
| 2244 | if (n.role === 'test') n.el.style.opacity = value ? '0.2' : '1' | |
| 2245 | } | |
| 2246 | } | |
| 2247 | if (key === 'showEdgeLabels') { | |
| 2248 | document.querySelectorAll('.edge-label').forEach(el => { | |
| 2249 | el.style.display = value ? '' : 'none' | |
| 2250 | }) | |
| 2251 | } | |
| 2252 | if (key === 'showRegions') { | |
| 2253 | document.querySelectorAll('.graph-region, .graph-region-label').forEach(el => { | |
| 2254 | el.style.display = value ? '' : 'none' | |
| 2255 | }) | |
| 2256 | } | |
| 2257 | ||
| 2258 | // Recalculate node sizes | |
| 2259 | if (key === 'sizeBy') { | |
| 2260 | for (const n of graphNodes) { | |
| 2261 | const newR = calcNodeSize(n) | |
| 2262 | n.r = newR | |
| 2263 | const circle = n.el.querySelector('circle') | |
| 2264 | if (circle) circle.setAttribute('r', newR) | |
| 2265 | // Update label position | |
| 2266 | if (n.labelEl) n.labelEl.setAttribute('dy', newR + 14) | |
| 2267 | } | |
| 2268 | } | |
| 2269 | ||
| 2270 | // Spacing change: repositions existing nodes based on the new value. No | |
| 2271 | // SVG teardown, no force sim rebuild. Just compute new x/y for each node | |
| 2272 | // (the calculation that initGraph would do) and update the transform. | |
| 2273 | // Slider input is decoupled from graph rebuild — input updates state, | |
| 2274 | // state change triggers a cheap repaint. | |
| 2275 | if (key === 'spacing') { | |
| 2276 | repositionForSpacing() | |
| 2277 | } | |
| 2278 | // Regroup actually changes which nodes are in which group, so it needs | |
| 2279 | // a real rebuild. Still throttled to rAF so rapid changes coalesce. | |
| 2280 | if (key === 'groupBy') { | |
| 2281 | scheduleRebuild() | |
| 2282 | } | |
| 2283 | ||
| 2284 | // Update label positions | |
| 2285 | if (key === 'labelPos') updateLabelPositions() | |
| 2286 | ||
| 2287 | // DON'T call showGraphSettings() here. It rebuilds the entire settings | |
| 2288 | // panel HTML — including the slider input element. If the user is mid-drag, | |
| 2289 | // their pointer capture is on the soon-to-be-destroyed input, so the | |
| 2290 | // browser cancels the drag after one tick. That was the "barely slides" | |
| 2291 | // regression. Settings panel only needs to re-render on initial graph | |
| 2292 | // build (which still calls showGraphSettings). | |
| 2293 | } | |
| 2294 | ||
| 2295 | function calcNodeSize (n) { | |
| 2296 | let val = 0 | |
| 2297 | if (gfx.sizeBy === 'members') val = n.memberCount || 0 | |
| 2298 | else if (gfx.sizeBy === 'deps') val = (n.usedBy ? n.usedBy.length : 0) * 5 | |
| 2299 | else if (gfx.sizeBy === 'exports') val = (n.mod ? n.mod.publicAPI.length : (n.exportCount || 0)) * 3 | |
| 2300 | return Math.max(8, Math.min(35, 6 + Math.sqrt(val) * 2)) | |
| 2301 | } | |
| 2302 | ||
| 2303 | function updateLabelPositions () { | |
| 2304 | const cx = document.getElementById('graph-svg').getBoundingClientRect().width / 2 | |
| 2305 | const cy = document.getElementById('graph-svg').getBoundingClientRect().height / 2 | |
| 2306 | ||
| 2307 | for (const n of graphNodes) { | |
| 2308 | if (!n.labelEl) continue | |
| 2309 | if (gfx.labelPos === 'below') { | |
| 2310 | n.labelEl.setAttribute('dy', n.r + 14) | |
| 2311 | n.labelEl.setAttribute('dx', '0') | |
| 2312 | n.labelEl.setAttribute('text-anchor', 'middle') | |
| 2313 | } else if (gfx.labelPos === 'right') { | |
| 2314 | n.labelEl.setAttribute('dy', '4') | |
| 2315 | n.labelEl.setAttribute('dx', n.r + 6) | |
| 2316 | n.labelEl.setAttribute('text-anchor', 'start') | |
| 2317 | } else if (gfx.labelPos === 'radial') { | |
| 2318 | // Point outward from center | |
| 2319 | const dx = n.x - cx | |
| 2320 | const dy = n.y - cy | |
| 2321 | const angle = Math.atan2(dy, dx) | |
| 2322 | const dist = n.r + 10 | |
| 2323 | n.labelEl.setAttribute('dy', Math.sin(angle) * dist + 4) | |
| 2324 | n.labelEl.setAttribute('dx', Math.cos(angle) * dist) | |
| 2325 | n.labelEl.setAttribute('text-anchor', Math.cos(angle) > 0.3 ? 'start' : Math.cos(angle) < -0.3 ? 'end' : 'middle') | |
| 2326 | } | |
| 2327 | } | |
| 2328 | } | |
| 2329 | ||
| 2330 | function drillIntoFile (moduleName, filePath, fromNav) { | |
| 2331 | const mod = tree.modules[moduleName] | |
| 2332 | if (!mod || !mod.files[filePath]) return | |
| 2333 | const file = mod.files[filePath] | |
| 2334 | ||
| 2335 | if (!fromNav) { | |
| 2336 | if (graphStack.length === 0 || graphStack[graphStack.length - 1].type !== 'module') { | |
| 2337 | graphStack = [{ type: 'module', name: moduleName, label: moduleName }] | |
| 2338 | } | |
| 2339 | graphStack.push({ type: 'file', name: filePath, moduleName, label: filePath.split('/').pop() }) | |
| 2340 | } | |
| 2341 | graphLevel = 'file' | |
| 2342 | ||
| 2343 | const svg = document.getElementById('graph-svg') | |
| 2344 | const rect = svg.getBoundingClientRect() | |
| 2345 | const W = rect.width, H = rect.height | |
| 2346 | const cx = W / 2, cy = H / 2 | |
| 2347 | ||
| 2348 | graphNodes.length = 0 | |
| 2349 | graphEdges.length = 0 | |
| 2350 | focusedNode = null | |
| 2351 | zoom = 1; panX = 0; panY = 0 | |
| 2352 | ||
| 2353 | // Build nodes: classes, functions, constants | |
| 2354 | let idx = 0 | |
| 2355 | const items = [] | |
| 2356 | ||
| 2357 | if (file.classes) for (const cls of file.classes) { | |
| 2358 | items.push({ type: 'class', name: cls.name, data: cls, memberCount: cls.methods.length + (cls.getters ? cls.getters.length : 0), color: '#d2a8ff' }) | |
| 2359 | } | |
| 2360 | if (file.functions) for (const fn of file.functions) { | |
| 2361 | items.push({ type: 'function', name: fn.name, data: fn, memberCount: 0, color: '#79c0ff' }) | |
| 2362 | } | |
| 2363 | if (file.constants) for (const c of file.constants) { | |
| 2364 | if (c.type === 'class' || c.type === 'function') continue | |
| 2365 | items.push({ type: 'const', name: c.name, data: c, memberCount: 0, color: '#ffa657' }) | |
| 2366 | } | |
| 2367 | ||
| 2368 | for (let i = 0; i < items.length; i++) { | |
| 2369 | const item = items[i] | |
| 2370 | const angle = (i / items.length) * Math.PI * 2 | |
| 2371 | const radius = Math.min(W, H) * 0.25 | |
| 2372 | ||
| 2373 | graphNodes.push({ | |
| 2374 | idx: i, name: item.name, itemType: item.type, data: item.data, | |
| 2375 | x: cx + Math.cos(angle) * radius, | |
| 2376 | y: cy + Math.sin(angle) * radius, | |
| 2377 | vx: 0, vy: 0, | |
| 2378 | r: Math.max(8, Math.min(25, 8 + Math.sqrt(item.memberCount) * 3)), | |
| 2379 | memberCount: item.memberCount, | |
| 2380 | color: item.color, | |
| 2381 | dependsOn: [], usedBy: [] | |
| 2382 | }) | |
| 2383 | } | |
| 2384 | ||
| 2385 | // Edges: delegation relationships | |
| 2386 | if (file.delegates) { | |
| 2387 | for (const del of file.delegates) { | |
| 2388 | // Find source class (the one with the delegate field) | |
| 2389 | const srcIdx = graphNodes.findIndex(n => n.itemType === 'class' && n.data.state && n.data.state.includes(del.field)) | |
| 2390 | if (srcIdx < 0) continue | |
| 2391 | // No target in same file usually, but mark delegation as self-edge label | |
| 2392 | } | |
| 2393 | } | |
| 2394 | ||
| 2395 | renderSubGraph(svg, cx, cy, W, H, 'item') | |
| 2396 | updateBreadcrumb() | |
| 2397 | } | |
| 2398 | ||
| 2399 | function renderSubGraph (svg, cx, cy, W, H, nodeType) { | |
| 2400 | const defs = svg.querySelector('defs').outerHTML | |
| 2401 | svg.innerHTML = defs + '<g id="graph-world"><g id="graph-edges"></g><g id="graph-edge-labels"></g><g id="graph-nodes"></g><g id="graph-expanded"></g></g>' | |
| 2402 | graphGroup = document.getElementById('graph-world') | |
| 2403 | const edgeGroup = document.getElementById('graph-edges') | |
| 2404 | const labelGroup = document.getElementById('graph-edge-labels') | |
| 2405 | const nodeGroup = document.getElementById('graph-nodes') | |
| 2406 | ||
| 2407 | // Draw edges with labels | |
| 2408 | for (const edge of graphEdges) { | |
| 2409 | const line = document.createElementNS('http://www.w3.org/2000/svg', 'line') | |
| 2410 | line.classList.add('graph-edge') | |
| 2411 | edgeGroup.appendChild(line) | |
| 2412 | edge.el = line | |
| 2413 | ||
| 2414 | // Edge label showing imported names | |
| 2415 | if (edge.labels && edge.labels.length > 0) { | |
| 2416 | const label = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 2417 | label.classList.add('edge-label') | |
| 2418 | label.textContent = edge.labels.slice(0, 3).join(', ') + (edge.labels.length > 3 ? '...' : '') | |
| 2419 | label.setAttribute('font-size', '9') | |
| 2420 | label.setAttribute('fill', '#484f58') | |
| 2421 | label.setAttribute('text-anchor', 'middle') | |
| 2422 | label.style.display = gfx.showLabels ? '' : 'none' | |
| 2423 | labelGroup.appendChild(label) | |
| 2424 | edge.labelEl = label | |
| 2425 | } | |
| 2426 | } | |
| 2427 | ||
| 2428 | // Draw nodes | |
| 2429 | for (let i = 0; i < graphNodes.length; i++) { | |
| 2430 | const n = graphNodes[i] | |
| 2431 | const g = document.createElementNS('http://www.w3.org/2000/svg', 'g') | |
| 2432 | g.classList.add('graph-node') | |
| 2433 | ||
| 2434 | // Shape by role/type | |
| 2435 | if (nodeType === 'file' && n.role === 'entry') { | |
| 2436 | // Diamond for entry | |
| 2437 | const d = n.r | |
| 2438 | const poly = document.createElementNS('http://www.w3.org/2000/svg', 'polygon') | |
| 2439 | poly.setAttribute('points', '0,-'+d+' '+d+',0 0,'+d+' -'+d+',0') | |
| 2440 | poly.setAttribute('fill', n.color) | |
| 2441 | poly.setAttribute('stroke', '#30363d') | |
| 2442 | poly.setAttribute('stroke-width', '1.5') | |
| 2443 | g.appendChild(poly) | |
| 2444 | } else if (nodeType === 'file' && n.role === 'test') { | |
| 2445 | // Square for test | |
| 2446 | const s = n.r * 0.8 | |
| 2447 | const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect') | |
| 2448 | rect.setAttribute('x', -s); rect.setAttribute('y', -s) | |
| 2449 | rect.setAttribute('width', s*2); rect.setAttribute('height', s*2) | |
| 2450 | rect.setAttribute('rx', '3') | |
| 2451 | rect.setAttribute('fill', n.color) | |
| 2452 | rect.setAttribute('stroke', '#30363d') | |
| 2453 | rect.setAttribute('stroke-width', '1.5') | |
| 2454 | g.appendChild(rect) | |
| 2455 | } else { | |
| 2456 | // Circle for everything else | |
| 2457 | const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle') | |
| 2458 | circle.setAttribute('r', n.r) | |
| 2459 | circle.setAttribute('fill', n.color) | |
| 2460 | circle.setAttribute('stroke', '#30363d') | |
| 2461 | circle.setAttribute('stroke-width', '1.5') | |
| 2462 | g.appendChild(circle) | |
| 2463 | } | |
| 2464 | ||
| 2465 | // Label | |
| 2466 | const text = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 2467 | const shortName = n.name.includes('/') ? n.name.split('/').pop() : n.name | |
| 2468 | text.textContent = shortName | |
| 2469 | text.setAttribute('dy', n.r + 14) | |
| 2470 | text.setAttribute('text-anchor', 'middle') | |
| 2471 | text.setAttribute('font-size', '11') | |
| 2472 | g.appendChild(text) | |
| 2473 | ||
| 2474 | // Member count inside node | |
| 2475 | if (n.memberCount > 0) { | |
| 2476 | const ct = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 2477 | ct.textContent = n.memberCount | |
| 2478 | ct.setAttribute('dy', '4') | |
| 2479 | ct.setAttribute('text-anchor', 'middle') | |
| 2480 | ct.setAttribute('font-size', '9') | |
| 2481 | ct.setAttribute('fill', '#0d1117') | |
| 2482 | ct.setAttribute('font-weight', 'bold') | |
| 2483 | g.appendChild(ct) | |
| 2484 | } | |
| 2485 | ||
| 2486 | // Dim tests if toggle is on | |
| 2487 | if (gfx.dimTests && n.role === 'test') g.style.opacity = '0.2' | |
| 2488 | ||
| 2489 | nodeGroup.appendChild(g) | |
| 2490 | n.el = g | |
| 2491 | ||
| 2492 | // Drag | |
| 2493 | let didDrag = false | |
| 2494 | g.addEventListener('mousedown', (e) => { | |
| 2495 | n.fixed = true; didDrag = false | |
| 2496 | e.stopPropagation(); e.preventDefault() | |
| 2497 | }) | |
| 2498 | ||
| 2499 | g.addEventListener('click', (e) => { | |
| 2500 | e.stopPropagation() | |
| 2501 | if (didDrag) return | |
| 2502 | ||
| 2503 | if (nodeType === 'file') { | |
| 2504 | currentFileContext = { path: n.path, moduleName: n.moduleName } | |
| 2505 | // In graph mode: show structure in right panel, load file source in docs tab | |
| 2506 | if (n.file && (n.file.classes || n.file.functions || n.file.exports)) { | |
| 2507 | showStructurePanel(n.path, n.file, n.moduleName) | |
| 2508 | } | |
| 2509 | // Load file source into docs tab | |
| 2510 | const modPath = n.moduleName ? tree.modules[n.moduleName].path + '/' : '' | |
| 2511 | loadFileIntoDocsTab(modPath + n.path) | |
| 2512 | toggleExpandNode(n, i) | |
| 2513 | } else if (n.itemType === 'class') { | |
| 2514 | showGraphItemPanel('class', n.data, n.name) | |
| 2515 | } else if (n.itemType === 'function') { | |
| 2516 | showGraphItemPanel('function', n.data, n.name) | |
| 2517 | } | |
| 2518 | focusModule(i) | |
| 2519 | }) | |
| 2520 | ||
| 2521 | g.addEventListener('dblclick', (e) => { | |
| 2522 | e.stopPropagation() | |
| 2523 | if (nodeType === 'file' && n.file) { | |
| 2524 | drillIntoFile(n.moduleName, n.path) | |
| 2525 | } | |
| 2526 | }) | |
| 2527 | ||
| 2528 | g.addEventListener('mouseenter', () => { | |
| 2529 | const tooltip = document.getElementById('graph-tooltip') | |
| 2530 | let html = '<strong>' + n.name + '</strong>' | |
| 2531 | if (n.role) html += ' <span style="color:' + n.color + '">' + n.role + '</span>' | |
| 2532 | if (n.memberCount) html += '<br>' + n.memberCount + ' members' | |
| 2533 | if (n.exportCount) html += ', ' + n.exportCount + ' exports' | |
| 2534 | if (n.file && n.file.classes) { | |
| 2535 | html += '<br>Classes: ' + n.file.classes.map(c => c.name).join(', ') | |
| 2536 | } | |
| 2537 | if (n.file && n.file.functions) { | |
| 2538 | html += '<br>Functions: ' + n.file.functions.slice(0, 5).map(f => f.name).join(', ') | |
| 2539 | if (n.file.functions.length > 5) html += '...' | |
| 2540 | } | |
| 2541 | if (n.itemType) html += '<br>type: ' + n.itemType | |
| 2542 | if (n.data && n.data.params) html += '<br>params: ' + n.data.params.join(', ') | |
| 2543 | html += '<br><em style="color:#484f58">click to expand, dblclick to drill in</em>' | |
| 2544 | tooltip.innerHTML = html | |
| 2545 | tooltip.style.display = 'block' | |
| 2546 | }) | |
| 2547 | g.addEventListener('mouseleave', hideTooltip) | |
| 2548 | } | |
| 2549 | ||
| 2550 | // Pan/zoom handler | |
| 2551 | const svgEl = document.getElementById('graph-svg') | |
| 2552 | const moveHandler = (e) => { | |
| 2553 | const tooltip = document.getElementById('graph-tooltip') | |
| 2554 | tooltip.style.left = (e.clientX + 14) + 'px' | |
| 2555 | tooltip.style.top = (e.clientY + 14) + 'px' | |
| 2556 | ||
| 2557 | if (isPanning) { | |
| 2558 | panX = e.clientX - panStartX | |
| 2559 | panY = e.clientY - panStartY | |
| 2560 | graphGroup.setAttribute('transform', 'translate(' + panX.toFixed(1) + ',' + panY.toFixed(1) + ') scale(' + zoom.toFixed(3) + ')') | |
| 2561 | return | |
| 2562 | } | |
| 2563 | for (const nd of graphNodes) { | |
| 2564 | if (nd.fixed) { | |
| 2565 | const sr = svgEl.getBoundingClientRect() | |
| 2566 | nd.x = (e.clientX - sr.left - panX) / zoom | |
| 2567 | nd.y = (e.clientY - sr.top - panY) / zoom | |
| 2568 | didDrag = true | |
| 2569 | } | |
| 2570 | } | |
| 2571 | } | |
| 2572 | document.removeEventListener('mousemove', graphMoveHandler) | |
| 2573 | document.addEventListener('mousemove', moveHandler) | |
| 2574 | graphMoveHandler = moveHandler | |
| 2575 | ||
| 2576 | // Force simulation — blends hierarchy pull vs force physics via slider | |
| 2577 | function sim () { | |
| 2578 | const damp = 0.8 | |
| 2579 | const t = gfx.forceStrength / 100 // 0 = pure hierarchy, 1 = full force | |
| 2580 | const hierPull = 1 - t // how strongly to pull toward hierarchy positions | |
| 2581 | ||
| 2582 | // Hierarchy spring: pull toward stored hierarchy positions | |
| 2583 | if (hierPull > 0.01) { | |
| 2584 | for (const n of graphNodes) { | |
| 2585 | if (n.fixed || n.hierX === undefined) continue | |
| 2586 | n.vx += (n.hierX - n.x) * hierPull * 0.15 | |
| 2587 | n.vy += (n.hierY - n.y) * hierPull * 0.15 | |
| 2588 | } | |
| 2589 | } | |
| 2590 | ||
| 2591 | // Force physics (scaled by t) | |
| 2592 | if (t > 0.01) { | |
| 2593 | // Label-aware repulsion | |
| 2594 | for (let i = 0; i < graphNodes.length; i++) { | |
| 2595 | for (let j = i + 1; j < graphNodes.length; j++) { | |
| 2596 | const a = graphNodes[i], b = graphNodes[j] | |
| 2597 | let dx = b.x - a.x, dy = b.y - a.y | |
| 2598 | let dist = Math.sqrt(dx * dx + dy * dy) || 1 | |
| 2599 | const minDist = (a.labelW || a.r * 2) / 2 + (b.labelW || b.r * 2) / 2 + 15 | |
| 2600 | if (dist < minDist) { | |
| 2601 | const f = (minDist - dist) * 0.08 * t | |
| 2602 | if (!a.fixed) { a.vx -= (dx/dist)*f; a.vy -= (dy/dist)*f } | |
| 2603 | if (!b.fixed) { b.vx += (dx/dist)*f; b.vy += (dy/dist)*f } | |
| 2604 | } | |
| 2605 | } | |
| 2606 | } | |
| 2607 | ||
| 2608 | // Edge attraction | |
| 2609 | for (const edge of graphEdges) { | |
| 2610 | const a = graphNodes[edge.source], b = graphNodes[edge.target] | |
| 2611 | const dx = b.x-a.x, dy = b.y-a.y, dist = Math.sqrt(dx*dx+dy*dy)||1 | |
| 2612 | if (dist > 180) { | |
| 2613 | const f = (dist - 180) * 0.001 * t | |
| 2614 | if (!a.fixed) { a.vx += (dx/dist)*f; a.vy += (dy/dist)*f } | |
| 2615 | if (!b.fixed) { b.vx -= (dx/dist)*f; b.vy -= (dy/dist)*f } | |
| 2616 | } | |
| 2617 | } | |
| 2618 | } | |
| 2619 | ||
| 2620 | // Always: overlap prevention (even in hierarchy mode) | |
| 2621 | for (let i = 0; i < graphNodes.length; i++) { | |
| 2622 | for (let j = i + 1; j < graphNodes.length; j++) { | |
| 2623 | const a = graphNodes[i], b = graphNodes[j] | |
| 2624 | let dx = b.x - a.x, dy = b.y - a.y | |
| 2625 | let dist = Math.sqrt(dx * dx + dy * dy) || 1 | |
| 2626 | const minDist = (a.labelW || a.r * 2) / 2 + (b.labelW || b.r * 2) / 2 + 10 | |
| 2627 | if (dist < minDist) { | |
| 2628 | const f = (minDist - dist) * 0.02 | |
| 2629 | if (!a.fixed) { a.vx -= (dx/dist)*f; a.vy -= (dy/dist)*f } | |
| 2630 | if (!b.fixed) { b.vx += (dx/dist)*f; b.vy += (dy/dist)*f } | |
| 2631 | } | |
| 2632 | } | |
| 2633 | } | |
| 2634 | ||
| 2635 | for (const n of graphNodes) { | |
| 2636 | if (n.fixed) continue | |
| 2637 | n.vx *= damp; n.vy *= damp | |
| 2638 | n.x += n.vx; n.y += n.vy | |
| 2639 | } | |
| 2640 | ||
| 2641 | // Update SVG | |
| 2642 | for (const n of graphNodes) { | |
| 2643 | n.el.setAttribute('transform', 'translate('+n.x.toFixed(1)+','+n.y.toFixed(1)+')') | |
| 2644 | } | |
| 2645 | for (const edge of graphEdges) { | |
| 2646 | const a = graphNodes[edge.source], b = graphNodes[edge.target] | |
| 2647 | const dx=b.x-a.x, dy=b.y-a.y, dist=Math.sqrt(dx*dx+dy*dy)||1 | |
| 2648 | const x1 = a.x+dx/dist*(a.r+2), y1 = a.y+dy/dist*(a.r+2) | |
| 2649 | const x2 = b.x-dx/dist*(b.r+6), y2 = b.y-dy/dist*(b.r+6) | |
| 2650 | edge.el.setAttribute('x1', x1.toFixed(1)) | |
| 2651 | edge.el.setAttribute('y1', y1.toFixed(1)) | |
| 2652 | edge.el.setAttribute('x2', x2.toFixed(1)) | |
| 2653 | edge.el.setAttribute('y2', y2.toFixed(1)) | |
| 2654 | // Position label at midpoint | |
| 2655 | if (edge.labelEl) { | |
| 2656 | edge.labelEl.setAttribute('x', ((x1+x2)/2).toFixed(1)) | |
| 2657 | edge.labelEl.setAttribute('y', ((y1+y2)/2 - 4).toFixed(1)) | |
| 2658 | } | |
| 2659 | } | |
| 2660 | ||
| 2661 | // Update expanded satellite positions | |
| 2662 | for (const n of graphNodes) { | |
| 2663 | if (n.satellites) { | |
| 2664 | for (const sat of n.satellites) { | |
| 2665 | sat.el.setAttribute('transform', 'translate('+(n.x+sat.ox).toFixed(1)+','+(n.y+sat.oy).toFixed(1)+')') | |
| 2666 | } | |
| 2667 | } | |
| 2668 | } | |
| 2669 | ||
| 2670 | requestAnimationFrame(sim) | |
| 2671 | } | |
| 2672 | sim() | |
| 2673 | } | |
| 2674 | ||
| 2675 | // --- Expand node in-place: show classes/methods as satellites --- | |
| 2676 | function toggleExpandNode (n, idx) { | |
| 2677 | const expandGroup = document.getElementById('graph-expanded') | |
| 2678 | if (!expandGroup) return | |
| 2679 | ||
| 2680 | if (expandedNodes.has(idx)) { | |
| 2681 | // Collapse | |
| 2682 | expandedNodes.delete(idx) | |
| 2683 | if (n.satellites) { | |
| 2684 | for (const sat of n.satellites) sat.el.remove() | |
| 2685 | n.satellites = null | |
| 2686 | } | |
| 2687 | return | |
| 2688 | } | |
| 2689 | ||
| 2690 | expandedNodes.add(idx) | |
| 2691 | const file = n.file | |
| 2692 | if (!file) return | |
| 2693 | ||
| 2694 | const items = [] | |
| 2695 | if (file.classes) for (const cls of file.classes) { | |
| 2696 | items.push({ name: cls.name, type: 'class', sub: cls.methods.slice(0, 5).map(m => m.name) }) | |
| 2697 | } | |
| 2698 | if (file.functions) for (const fn of file.functions) { | |
| 2699 | items.push({ name: fn.name, type: 'fn' }) | |
| 2700 | } | |
| 2701 | ||
| 2702 | if (items.length === 0) return | |
| 2703 | ||
| 2704 | n.satellites = [] | |
| 2705 | const satRadius = n.r + 35 | |
| 2706 | ||
| 2707 | for (let i = 0; i < items.length; i++) { | |
| 2708 | const item = items[i] | |
| 2709 | const angle = (i / items.length) * Math.PI * 2 - Math.PI / 2 | |
| 2710 | const ox = Math.cos(angle) * satRadius | |
| 2711 | const oy = Math.sin(angle) * satRadius | |
| 2712 | ||
| 2713 | const g = document.createElementNS('http://www.w3.org/2000/svg', 'g') | |
| 2714 | g.classList.add('graph-node') | |
| 2715 | ||
| 2716 | const r = item.type === 'class' ? 6 : 4 | |
| 2717 | const color = item.type === 'class' ? '#d2a8ff' : '#79c0ff' | |
| 2718 | const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle') | |
| 2719 | circle.setAttribute('r', r) | |
| 2720 | circle.setAttribute('fill', color) | |
| 2721 | circle.setAttribute('stroke', '#30363d') | |
| 2722 | circle.setAttribute('stroke-width', '1') | |
| 2723 | g.appendChild(circle) | |
| 2724 | ||
| 2725 | const text = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 2726 | text.textContent = item.name | |
| 2727 | text.setAttribute('dx', r + 4) | |
| 2728 | text.setAttribute('dy', '3') | |
| 2729 | text.setAttribute('font-size', '9') | |
| 2730 | text.setAttribute('fill', color) | |
| 2731 | g.appendChild(text) | |
| 2732 | ||
| 2733 | // Show methods as sub-text for classes | |
| 2734 | if (item.sub && item.sub.length > 0) { | |
| 2735 | for (let si = 0; si < item.sub.length; si++) { | |
| 2736 | const st = document.createElementNS('http://www.w3.org/2000/svg', 'text') | |
| 2737 | st.textContent = '.' + item.sub[si] + '()' | |
| 2738 | st.setAttribute('dx', r + 8) | |
| 2739 | st.setAttribute('dy', (si + 1) * 11 + 3) | |
| 2740 | st.setAttribute('font-size', '8') | |
| 2741 | st.setAttribute('fill', '#484f58') | |
| 2742 | g.appendChild(st) | |
| 2743 | } | |
| 2744 | } | |
| 2745 | ||
| 2746 | expandGroup.appendChild(g) | |
| 2747 | n.satellites.push({ el: g, ox, oy }) | |
| 2748 | } | |
| 2749 | } | |
| 2750 | ||
| 2751 | let graphMoveHandler = () => {} | |
| 2752 | ||
| 2753 | function roleColor (role) { | |
| 2754 | const colors = { entry: '#f0883e', lib: '#58a6ff', schema: '#d2a8ff', test: '#7ee787', bin: '#ff7b72', script: '#ffa657' } | |
| 2755 | return colors[role] || '#8b949e' | |
| 2756 | } | |
| 2757 | ||
| 2758 | // ====== FILE VIEWER ====== | |
| 2759 | async function loadFileViewer (filePath, moduleName, scrollToLine) { | |
| 2760 | const panel = document.getElementById('detail-content') | |
| 2761 | panel.innerHTML = '<h2>Loading...</h2>' | |
| 2762 | ||
| 2763 | try { | |
| 2764 | const resp = await fetch(API + '/api/file?path=' + encodeURIComponent(filePath)) | |
| 2765 | const data = await resp.json() | |
| 2766 | if (data.error) { | |
| 2767 | panel.innerHTML = '<h2>Error</h2><pre>' + escapeHtml(data.error) + '</pre>' | |
| 2768 | return | |
| 2769 | } | |
| 2770 | ||
| 2771 | const lines = data.content.split('\\n') | |
| 2772 | let html = '<div class="file-viewer-header">' | |
| 2773 | html += '<span class="fv-path">' + (moduleName ? moduleName + '/' : '') + data.path + '</span>' | |
| 2774 | html += '<span class="fv-info">' + lines.length + ' lines</span>' | |
| 2775 | html += '</div>' | |
| 2776 | html += '<div class="file-viewer"><table>' | |
| 2777 | ||
| 2778 | for (let i = 0; i < lines.length; i++) { | |
| 2779 | const lineNum = i + 1 | |
| 2780 | const highlighted = scrollToLine && lineNum === scrollToLine ? ' highlight' : '' | |
| 2781 | html += '<tr id="L' + lineNum + '" class="' + highlighted + '">' | |
| 2782 | html += '<td class="line-no">' + lineNum + '</td>' | |
| 2783 | html += '<td class="line-code">' + syntaxHighlight(escapeHtml(lines[i])) + '</td>' | |
| 2784 | html += '</tr>' | |
| 2785 | } | |
| 2786 | ||
| 2787 | html += '</table></div>' | |
| 2788 | panel.innerHTML = html | |
| 2789 | ||
| 2790 | // Scroll to highlighted line | |
| 2791 | if (scrollToLine) { | |
| 2792 | const row = document.getElementById('L' + scrollToLine) | |
| 2793 | if (row) row.scrollIntoView({ block: 'center', behavior: 'smooth' }) | |
| 2794 | } | |
| 2795 | } catch (err) { | |
| 2796 | panel.innerHTML = '<h2>Error</h2><pre>' + escapeHtml(err.message) + '</pre>' | |
| 2797 | } | |
| 2798 | } | |
| 2799 | ||
| 2800 | var synCmt = new RegExp('(' + '/' + '/.*$)') | |
| 2801 | var synStr = new RegExp("("[^&]*"|'[^&]*'|'[^']*'|" + '"[^"]*")', 'g') | |
| 2802 | var synKw = new RegExp('\\\\b(import|export|from|const|let|var|function|class|extends|return|if|else|for|while|switch|case|break|continue|new|this|async|await|throw|try|catch|typeof|instanceof|default|yield)\\\\b', 'g') | |
| 2803 | var synNum = new RegExp('\\\\b(\\\\d+\\\\.?\\\\d*)\\\\b', 'g') | |
| 2804 | var synFn = new RegExp('\\\\b([a-zA-Z_]\\\\w*)\\\\s*\\\\(', 'g') | |
| 2805 | ||
| 2806 | function syntaxHighlight (line) { | |
| 2807 | line = line.replace(synCmt, '<span class="syn-cmt">$1</span>') | |
| 2808 | line = line.replace(synStr, '<span class="syn-str">$1</span>') | |
| 2809 | line = line.replace(synKw, '<span class="syn-kw">$1</span>') | |
| 2810 | line = line.replace(synNum, '<span class="syn-num">$1</span>') | |
| 2811 | line = line.replace(synFn, '<span class="syn-fn">$1</span>(') | |
| 2812 | return line | |
| 2813 | } | |
| 2814 | ||
| 2815 | // ====== GRAPH -> RIGHT PANEL INTEGRATION ====== | |
| 2816 | function showGraphModulePanel (name, mod) { | |
| 2817 | const rp = document.getElementById('right-panel') | |
| 2818 | rp.style.display = 'block' | |
| 2819 | document.getElementById('resize-right').style.display = '' | |
| 2820 | ||
| 2821 | // Show structure tab with module overview | |
| 2822 | const panel = document.getElementById('structure-content') | |
| 2823 | let html = '<h2 style="font-size:13px;color:#f0883e;margin-bottom:8px">' + name + ' <span style="color:#8b949e">' + mod.version + '</span></h2>' | |
| 2824 | ||
| 2825 | // Public API | |
| 2826 | if (mod.publicAPI.length > 0) { | |
| 2827 | html += '<div class="detail"><h3>Public API (' + mod.publicAPI.length + ')</h3>' | |
| 2828 | for (const exp of mod.publicAPI) { | |
| 2829 | html += '<div style="padding:1px 0;font-size:12px;color:#3fb950">' + exp + '</div>' | |
| 2830 | } | |
| 2831 | html += '</div>' | |
| 2832 | } | |
| 2833 | ||
| 2834 | // Dependencies (local only) | |
| 2835 | const localDeps = Object.entries(mod.dependencies).filter(([d]) => tree.modules[d]) | |
| 2836 | const externalDeps = Object.entries(mod.dependencies).filter(([d]) => !tree.modules[d]) | |
| 2837 | if (localDeps.length > 0) { | |
| 2838 | html += '<div class="detail"><h3 style="color:#3fb950">Local Dependencies</h3>' | |
| 2839 | for (const [dep, ver] of localDeps) { | |
| 2840 | html += '<div style="padding:1px 0;font-size:12px"><span style="color:#58a6ff">' + dep + '</span> <span style="color:#484f58">' + ver + '</span></div>' | |
| 2841 | } | |
| 2842 | html += '</div>' | |
| 2843 | } | |
| 2844 | if (externalDeps.length > 0) { | |
| 2845 | html += '<div class="detail"><h3>External Dependencies (' + externalDeps.length + ')</h3>' | |
| 2846 | for (const [dep, ver] of externalDeps) { | |
| 2847 | html += '<div style="padding:1px 0;font-size:11px;color:#8b949e">' + dep + ' ' + ver + '</div>' | |
| 2848 | } | |
| 2849 | html += '</div>' | |
| 2850 | } | |
| 2851 | ||
| 2852 | // Files overview | |
| 2853 | const files = Object.entries(mod.files) | |
| 2854 | html += '<div class="detail"><h3>Files (' + files.length + ')</h3>' | |
| 2855 | for (const [path, file] of files) { | |
| 2856 | const counts = [] | |
| 2857 | if (file.classes) counts.push(file.classes.length + ' cls') | |
| 2858 | if (file.functions) counts.push(file.functions.length + ' fn') | |
| 2859 | html += '<div style="padding:1px 0;font-size:11px"><span style="color:#8b949e">' + path + '</span>' + | |
| 2860 | (counts.length ? ' <span style="color:#484f58">' + counts.join(', ') + '</span>' : '') + '</div>' | |
| 2861 | } | |
| 2862 | html += '</div>' | |
| 2863 | ||
| 2864 | // Test command | |
| 2865 | if (mod.testCommand) { | |
| 2866 | html += '<div class="detail"><h3>Test</h3><pre style="font-size:11px"><code>' + mod.testCommand + '</code></pre></div>' | |
| 2867 | } | |
| 2868 | ||
| 2869 | panel.innerHTML = html | |
| 2870 | switchRightPanel('structure') | |
| 2871 | ||
| 2872 | // Also populate validation if available | |
| 2873 | if (tree.validation && tree.validation.modules[name]) { | |
| 2874 | renderValidation(name) | |
| 2875 | } | |
| 2876 | ||
| 2877 | // Load spec file into docs tab | |
| 2878 | loadSpecForModule(name) | |
| 2879 | } | |
| 2880 | ||
| 2881 | function showGraphItemPanel (type, data, name) { | |
| 2882 | const rp = document.getElementById('right-panel') | |
| 2883 | rp.style.display = 'block' | |
| 2884 | document.getElementById('resize-right').style.display = '' | |
| 2885 | ||
| 2886 | const panel = document.getElementById('structure-content') | |
| 2887 | let html = '' | |
| 2888 | ||
| 2889 | if (type === 'class') { | |
| 2890 | const cls = data | |
| 2891 | html = '<h2 style="font-size:13px;color:#d2a8ff;margin-bottom:8px">class ' + cls.name + (cls.extends ? ' <span style="color:#8b949e">extends ' + cls.extends + '</span>' : '') + '</h2>' | |
| 2892 | ||
| 2893 | if (cls.jsdoc) { | |
| 2894 | html += '<div class="detail"><h3>JSDoc</h3><pre style="font-size:11px"><code>' + escapeHtml(cls.jsdoc) + '</code></pre></div>' | |
| 2895 | } | |
| 2896 | ||
| 2897 | if (cls.constructor) { | |
| 2898 | html += '<div class="detail"><h3 style="color:#ffa657">Constructor</h3>' | |
| 2899 | html += '<div style="font-size:12px">constructor(' + cls.constructor.params.join(', ') + ')</div>' | |
| 2900 | if (cls.constructor.jsdoc) html += '<pre style="font-size:10px;margin-top:4px"><code>' + escapeHtml(cls.constructor.jsdoc) + '</code></pre>' | |
| 2901 | html += '</div>' | |
| 2902 | } | |
| 2903 | ||
| 2904 | if (cls.getters && cls.getters.length > 0) { | |
| 2905 | html += '<div class="detail"><h3>Getters (' + cls.getters.length + ')</h3>' | |
| 2906 | for (const g of cls.getters) html += '<div style="padding:1px 0;font-size:11px"><span style="color:#7ee787">get</span> ' + g.name + '</div>' | |
| 2907 | html += '</div>' | |
| 2908 | } | |
| 2909 | ||
| 2910 | html += '<div class="detail"><h3>Methods (' + cls.methods.filter(m => m.kind !== 'field').length + ')</h3>' | |
| 2911 | for (const m of cls.methods) { | |
| 2912 | if (m.kind === 'field') continue | |
| 2913 | const tags = m.async ? ' <span style="color:#7ee787;font-size:9px">async</span>' : '' | |
| 2914 | const lineRef = m.line ? ' <span style="color:#484f58;font-size:9px;cursor:pointer" onclick="scrollFileToLine(' + m.line + ')">:' + m.line + '</span>' : '' | |
| 2915 | html += '<div style="padding:2px 0;font-size:11px"><span style="color:#79c0ff">' + m.name + '</span>(' + m.params.join(', ') + ')' + tags + lineRef | |
| 2916 | if (m.jsdoc) html += '<div style="font-size:9px;color:#484f58;margin:2px 0 4px;padding-left:8px">' + escapeHtml(m.jsdoc).slice(0, 120) + (m.jsdoc.length > 120 ? '...' : '') + '</div>' | |
| 2917 | html += '</div>' | |
| 2918 | } | |
| 2919 | html += '</div>' | |
| 2920 | } else if (type === 'function') { | |
| 2921 | const fn = data | |
| 2922 | html = '<h2 style="font-size:13px;color:#79c0ff;margin-bottom:8px">' + fn.name + '</h2>' | |
| 2923 | const tags = (fn.async ? 'async ' : '') + (fn.arrow ? '=> ' : '') | |
| 2924 | html += '<pre style="font-size:12px"><code>' + tags + fn.name + '(' + fn.params.join(', ') + ')</code></pre>' | |
| 2925 | if (fn.jsdoc) { | |
| 2926 | html += '<div class="detail"><h3>JSDoc</h3><pre style="font-size:11px"><code>' + escapeHtml(fn.jsdoc) + '</code></pre></div>' | |
| 2927 | } | |
| 2928 | } | |
| 2929 | ||
| 2930 | panel.innerHTML = html | |
| 2931 | switchRightPanel('structure') | |
| 2932 | ||
| 2933 | // Also load file source into docs tab scrolled to the item | |
| 2934 | if (currentFileContext && data.line) { | |
| 2935 | const modPath = currentFileContext.moduleName ? tree.modules[currentFileContext.moduleName].path + '/' : '' | |
| 2936 | loadFileIntoDocsTab(modPath + currentFileContext.path, data.line) | |
| 2937 | } | |
| 2938 | } | |
| 2939 | ||
| 2940 | // ====== DOCS LOADING ====== | |
| 2941 | async function loadSpecForModule (moduleName) { | |
| 2942 | const docsPanel = document.getElementById('docs-content') | |
| 2943 | ||
| 2944 | // Build candidate spec locations. Prefer the discovered specDir (from scanner.js | |
| 2945 | // findAllDocs()) — this is the project's actual spec directory, not a hardcoded path. | |
| 2946 | const specPaths = [] | |
| 2947 | if (tree.docs && tree.docs.specDir) { | |
| 2948 | // specDir is absolute; convert to project-relative for the /api/file endpoint | |
| 2949 | const rel = tree.docs.specDir.startsWith(tree.root) | |
| 2950 | ? tree.docs.specDir.slice(tree.root.length + 1) | |
| 2951 | : tree.docs.specDir | |
| 2952 | specPaths.push(rel + '/modules/' + moduleName + '.md') | |
| 2953 | } | |
| 2954 | // Conventional fallbacks (no hardcoded project names) | |
| 2955 | specPaths.push( | |
| 2956 | 'spec/modules/' + moduleName + '.md', | |
| 2957 | 'docs/spec/modules/' + moduleName + '.md', | |
| 2958 | moduleName + '/README.md' | |
| 2959 | ) | |
| 2960 | ||
| 2961 | for (const specPath of specPaths) { | |
| 2962 | try { | |
| 2963 | const resp = await fetch(API + '/api/file?path=' + encodeURIComponent(specPath)) | |
| 2964 | const data = await resp.json() | |
| 2965 | if (data.error) continue | |
| 2966 | ||
| 2967 | let html = '<h2 style="font-size:12px;color:#58a6ff;margin-bottom:4px">' + specPath + '</h2>' | |
| 2968 | html += '<div class="file-viewer" style="max-height:calc(100vh - 100px);font-size:11px"><table>' | |
| 2969 | const lines = data.content.split('\\n') | |
| 2970 | for (let i = 0; i < lines.length; i++) { | |
| 2971 | html += '<tr><td class="line-no">' + (i + 1) + '</td><td class="line-code">' + renderMarkdownLine(escapeHtml(lines[i])) + '</td></tr>' | |
| 2972 | } | |
| 2973 | html += '</table></div>' | |
| 2974 | docsPanel.innerHTML = html | |
| 2975 | return | |
| 2976 | } catch {} | |
| 2977 | } | |
| 2978 | ||
| 2979 | docsPanel.innerHTML = '<h2 style="color:#8b949e">No spec file found for ' + moduleName + '</h2>' + | |
| 2980 | '<p style="color:#484f58;font-size:11px">Searched:<br>' + specPaths.join('<br>') + '</p>' | |
| 2981 | } | |
| 2982 | ||
| 2983 | function renderMarkdownLine (line) { | |
| 2984 | // Minimal markdown rendering for spec files | |
| 2985 | if (line.startsWith('# ')) return '<span style="color:#58a6ff;font-weight:bold;font-size:14px">' + line.slice(2) + '</span>' | |
| 2986 | if (line.startsWith('## ')) return '<span style="color:#58a6ff;font-weight:bold;font-size:13px">' + line.slice(3) + '</span>' | |
| 2987 | if (line.startsWith('### ')) return '<span style="color:#58a6ff;font-size:12px">' + line.slice(4) + '</span>' | |
| 2988 | if (line.startsWith('- ')) return '<span style="color:#8b949e"> </span>' + line.slice(2) | |
| 2989 | if (line.startsWith('**') && line.includes(':**')) { | |
| 2990 | return line.replace(/\*\*([^*]+)\*\*/g, '<span style="color:#ffa657;font-weight:bold">$1</span>') | |
| 2991 | } | |
| 2992 | // Inline code (use char code to avoid backtick in template literal) | |
| 2993 | var bt = String.fromCharCode(96) | |
| 2994 | var inlineCodeRe = new RegExp(bt + '([^' + bt + ']+)' + bt, 'g') | |
| 2995 | line = line.replace(inlineCodeRe, '<span style="color:#79c0ff;background:#161b22;padding:0 3px;border-radius:2px">$1</span>') | |
| 2996 | // Bold | |
| 2997 | line = line.replace(new RegExp('\\\\*\\\\*([^*]+)\\\\*\\\\*', 'g'), '<span style="font-weight:bold">$1</span>') | |
| 2998 | return line | |
| 2999 | } | |
| 3000 | ||
| 3001 | async function loadFileIntoDocsTab (filePath, scrollToLine) { | |
| 3002 | const docsPanel = document.getElementById('docs-content') | |
| 3003 | try { | |
| 3004 | const resp = await fetch(API + '/api/file?path=' + encodeURIComponent(filePath)) | |
| 3005 | const data = await resp.json() | |
| 3006 | if (data.error) { | |
| 3007 | docsPanel.innerHTML = '<p style="color:#ff7b72">' + data.error + '</p>' | |
| 3008 | return | |
| 3009 | } | |
| 3010 | const lines = data.content.split('\\n') | |
| 3011 | let html = '<h2 style="font-size:12px;color:#58a6ff;margin-bottom:4px">' + data.path + ' <span style="color:#484f58">' + lines.length + ' lines</span></h2>' | |
| 3012 | html += '<div class="file-viewer" style="max-height:calc(100vh - 100px)"><table>' | |
| 3013 | for (let i = 0; i < lines.length; i++) { | |
| 3014 | const lineNum = i + 1 | |
| 3015 | const hl = scrollToLine && lineNum === scrollToLine ? ' highlight' : '' | |
| 3016 | html += '<tr id="DL' + lineNum + '" class="' + hl + '"><td class="line-no">' + lineNum + '</td><td class="line-code">' + syntaxHighlight(escapeHtml(lines[i])) + '</td></tr>' | |
| 3017 | } | |
| 3018 | html += '</table></div>' | |
| 3019 | docsPanel.innerHTML = html | |
| 3020 | if (scrollToLine) { | |
| 3021 | var row = document.getElementById('DL' + scrollToLine) | |
| 3022 | if (row) row.scrollIntoView({ block: 'center' }) | |
| 3023 | } | |
| 3024 | } catch (err) { | |
| 3025 | docsPanel.innerHTML = '<p style="color:#ff7b72">' + err.message + '</p>' | |
| 3026 | } | |
| 3027 | } | |
| 3028 | ||
| 3029 | // ====== RIGHT PANEL TABS ====== | |
| 3030 | let rightPanelTab = 'structure' | |
| 3031 | ||
| 3032 | window.switchRightPanel = function (tab) { | |
| 3033 | rightPanelTab = tab | |
| 3034 | document.getElementById('rp-structure').style.display = tab === 'structure' ? 'block' : 'none' | |
| 3035 | document.getElementById('rp-validation').style.display = tab === 'validation' ? 'block' : 'none' | |
| 3036 | document.getElementById('rp-docs').style.display = tab === 'docs' ? 'block' : 'none' | |
| 3037 | document.querySelectorAll('#right-panel-tabs .tab').forEach(t => { | |
| 3038 | t.classList.toggle('active', t.dataset.rp === tab) | |
| 3039 | }) | |
| 3040 | } | |
| 3041 | ||
| 3042 | function showStructurePanel (filePath, file, moduleName) { | |
| 3043 | const panel = document.getElementById('structure-content') | |
| 3044 | const rp = document.getElementById('right-panel') | |
| 3045 | rp.style.display = 'block' | |
| 3046 | document.getElementById('resize-right').style.display = '' | |
| 3047 | switchRightPanel('structure') | |
| 3048 | ||
| 3049 | let html = '<h2 style="font-size:13px;color:#58a6ff;margin-bottom:8px">' + (filePath.includes('/') ? filePath.split('/').pop() : filePath) + '</h2>' | |
| 3050 | ||
| 3051 | if (file.role) html += '<span class="badge" style="margin-bottom:8px;display:inline-block">' + file.role + '</span> ' | |
| 3052 | ||
| 3053 | // Exports | |
| 3054 | if (file.exports && file.exports.length > 0) { | |
| 3055 | html += '<div class="detail"><h3>Exports (' + file.exports.length + ')</h3>' | |
| 3056 | for (const e of file.exports) { | |
| 3057 | const type = e.type ? ' <span style="color:#8b949e">(' + e.type + ')</span>' : '' | |
| 3058 | const from = e.from ? ' <span style="color:#484f58">from ' + e.from + '</span>' : '' | |
| 3059 | html += '<div style="padding:1px 0;font-size:12px"><span style="color:#3fb950">' + e.name + '</span>' + type + from + '</div>' | |
| 3060 | } | |
| 3061 | html += '</div>' | |
| 3062 | } | |
| 3063 | ||
| 3064 | // Imports | |
| 3065 | if (file.imports && file.imports.length > 0) { | |
| 3066 | html += '<div class="detail"><h3>Imports (' + file.imports.length + ')</h3>' | |
| 3067 | for (const i of file.imports) { | |
| 3068 | html += '<div style="padding:1px 0;font-size:12px"><span style="color:#79c0ff">' + i.names.join(', ') + '</span> <span style="color:#484f58">from</span> <span style="color:#8b949e">' + i.specifier + '</span></div>' | |
| 3069 | } | |
| 3070 | html += '</div>' | |
| 3071 | } | |
| 3072 | ||
| 3073 | // Classes | |
| 3074 | if (file.classes && file.classes.length > 0) { | |
| 3075 | for (const cls of file.classes) { | |
| 3076 | html += '<div class="detail"><h3 style="color:#d2a8ff">class ' + cls.name + (cls.extends ? ' extends ' + cls.extends : '') + '</h3>' | |
| 3077 | if (cls.constructor) { | |
| 3078 | html += '<div style="padding:2px 0;font-size:11px;color:#ffa657">constructor(' + cls.constructor.params.join(', ') + ')</div>' | |
| 3079 | } | |
| 3080 | if (cls.getters && cls.getters.length > 0) { | |
| 3081 | html += '<div style="margin-top:4px;font-size:10px;color:#484f58;text-transform:uppercase">Getters</div>' | |
| 3082 | for (const g of cls.getters) { | |
| 3083 | html += '<div style="padding:1px 0;font-size:11px"><span style="color:#7ee787">get</span> ' + g.name + '</div>' | |
| 3084 | } | |
| 3085 | } | |
| 3086 | html += '<div style="margin-top:4px;font-size:10px;color:#484f58;text-transform:uppercase">Methods (' + cls.methods.filter(m => m.kind !== 'field').length + ')</div>' | |
| 3087 | for (const m of cls.methods) { | |
| 3088 | if (m.kind === 'field') continue | |
| 3089 | const tags = (m.async ? '<span style="color:#7ee787;font-size:9px"> async</span>' : '') | |
| 3090 | const lineRef = m.line ? ' <span style="color:#484f58;font-size:9px;cursor:pointer" onclick="scrollFileToLine(' + m.line + ')">:' + m.line + '</span>' : '' | |
| 3091 | html += '<div style="padding:1px 0;font-size:11px"><span style="color:#79c0ff">' + m.name + '</span>(' + m.params.join(', ') + ')' + tags + lineRef + '</div>' | |
| 3092 | } | |
| 3093 | html += '</div>' | |
| 3094 | } | |
| 3095 | } | |
| 3096 | ||
| 3097 | // Functions | |
| 3098 | if (file.functions && file.functions.length > 0) { | |
| 3099 | html += '<div class="detail"><h3>Functions (' + file.functions.length + ')</h3>' | |
| 3100 | for (const fn of file.functions) { | |
| 3101 | const tags = (fn.async ? '<span style="color:#7ee787;font-size:9px"> async</span>' : '') + | |
| 3102 | (fn.arrow ? '<span style="color:#79c0ff;font-size:9px"> =></span>' : '') | |
| 3103 | const lineRef = fn.line ? ' <span style="color:#484f58;font-size:9px;cursor:pointer" onclick="scrollFileToLine(' + fn.line + ')">:' + fn.line + '</span>' : '' | |
| 3104 | html += '<div style="padding:1px 0;font-size:11px"><span style="color:#79c0ff">' + fn.name + '</span>(' + fn.params.join(', ') + ')' + tags + lineRef + '</div>' | |
| 3105 | } | |
| 3106 | html += '</div>' | |
| 3107 | } | |
| 3108 | ||
| 3109 | // State | |
| 3110 | if (file.state && file.state.length > 0) { | |
| 3111 | html += '<div class="detail"><h3>State</h3>' | |
| 3112 | for (const s of file.state) html += '<div style="padding:1px 0;font-size:11px;color:#ffa657">' + s + '</div>' | |
| 3113 | html += '</div>' | |
| 3114 | } | |
| 3115 | ||
| 3116 | // Delegation | |
| 3117 | if (file.delegates && file.delegates.length > 0) { | |
| 3118 | html += '<div class="detail"><h3>Delegation</h3>' | |
| 3119 | for (const d of file.delegates) { | |
| 3120 | html += '<div style="padding:1px 0;font-size:11px">' + d.field + ' <span style="color:#484f58">-></span> ' + d.methods.join(', ') + '</div>' | |
| 3121 | } | |
| 3122 | html += '</div>' | |
| 3123 | } | |
| 3124 | ||
| 3125 | // Errors | |
| 3126 | if (file.errorContracts && file.errorContracts.length > 0) { | |
| 3127 | html += '<div class="detail"><h3>Error Contracts (' + file.errorContracts.length + ')</h3>' | |
| 3128 | for (const e of file.errorContracts) { | |
| 3129 | html += '<div style="padding:1px 0;font-size:11px;color:#ff7b72">' + escapeHtml(e) + '</div>' | |
| 3130 | } | |
| 3131 | html += '</div>' | |
| 3132 | } | |
| 3133 | ||
| 3134 | // GDScript signals | |
| 3135 | if (file.signals && file.signals.length > 0) { | |
| 3136 | html += '<div class="detail"><h3>Signals (' + file.signals.length + ')</h3>' | |
| 3137 | for (const sig of file.signals) { | |
| 3138 | html += '<div style="padding:1px 0;font-size:11px;color:#f0883e">' + | |
| 3139 | escapeHtml(sig.name) + '(' + (sig.params || []).map(escapeHtml).join(', ') + ')</div>' | |
| 3140 | } | |
| 3141 | html += '</div>' | |
| 3142 | } | |
| 3143 | ||
| 3144 | // Enums (GDScript, C++) | |
| 3145 | if (file.enums && file.enums.length > 0) { | |
| 3146 | html += '<div class="detail"><h3>Enums (' + file.enums.length + ')</h3>' | |
| 3147 | for (const e of file.enums) { | |
| 3148 | html += '<div style="padding:2px 0;font-size:11px"><span style="color:#d2a8ff">' + escapeHtml(e.name) + '</span>' | |
| 3149 | if (e.values && e.values.length > 0) { | |
| 3150 | html += '<span style="color:#8b949e"> { ' + e.values.slice(0, 6).map(escapeHtml).join(', ') + | |
| 3151 | (e.values.length > 6 ? ', ...' : '') + ' }</span>' | |
| 3152 | } | |
| 3153 | html += '</div>' | |
| 3154 | } | |
| 3155 | html += '</div>' | |
| 3156 | } | |
| 3157 | ||
| 3158 | // C++ namespaces | |
| 3159 | if (file.namespaces && file.namespaces.length > 0) { | |
| 3160 | html += '<div class="detail"><h3>Namespaces</h3>' | |
| 3161 | html += '<div style="padding:2px 0;font-size:11px;color:#79c0ff">' + | |
| 3162 | file.namespaces.map(escapeHtml).join(', ') + '</div>' | |
| 3163 | html += '</div>' | |
| 3164 | } | |
| 3165 | ||
| 3166 | // GLSL shader resources | |
| 3167 | if (file.uniforms && file.uniforms.length > 0) { | |
| 3168 | html += '<div class="detail"><h3>Uniforms (' + file.uniforms.length + ')</h3>' | |
| 3169 | for (const u of file.uniforms) { | |
| 3170 | const binding = u.set !== null && u.binding !== null | |
| 3171 | ? ' <span style="color:#8b949e">(set=' + u.set + ', binding=' + u.binding + ')</span>' | |
| 3172 | : (u.type ? ' <span style="color:#8b949e">' + escapeHtml(u.type) + '</span>' : '') | |
| 3173 | html += '<div style="padding:1px 0;font-size:11px;color:#3fb950">' + | |
| 3174 | escapeHtml(u.name) + binding + '</div>' | |
| 3175 | } | |
| 3176 | html += '</div>' | |
| 3177 | } | |
| 3178 | ||
| 3179 | if (file.buffers && file.buffers.length > 0) { | |
| 3180 | html += '<div class="detail"><h3>Buffers (' + file.buffers.length + ')</h3>' | |
| 3181 | for (const b of file.buffers) { | |
| 3182 | const mode = b.readonly ? 'RO' : b.writeonly ? 'WO' : 'RW' | |
| 3183 | html += '<div style="padding:1px 0;font-size:11px;color:#ffa657">' + | |
| 3184 | escapeHtml(b.name) + ' <span style="color:#8b949e">' + mode + | |
| 3185 | ' (set=' + (b.set || '?') + ', binding=' + (b.binding || '?') + ')</span></div>' | |
| 3186 | } | |
| 3187 | html += '</div>' | |
| 3188 | } | |
| 3189 | ||
| 3190 | if (file.pushConstants && file.pushConstants.length > 0) { | |
| 3191 | html += '<div class="detail"><h3>Push Constants (' + file.pushConstants.length + ')</h3>' | |
| 3192 | for (const p of file.pushConstants) { | |
| 3193 | html += '<div style="padding:1px 0;font-size:11px;color:#d2a8ff">' + escapeHtml(p.name) + '</div>' | |
| 3194 | } | |
| 3195 | html += '</div>' | |
| 3196 | } | |
| 3197 | ||
| 3198 | if (!file.exports && !file.classes && !file.functions && !file.signals && !file.uniforms && !file.buffers) { | |
| 3199 | html += '<p style="color:#8b949e;font-size:12px">No structural data</p>' | |
| 3200 | } | |
| 3201 | ||
| 3202 | panel.innerHTML = html | |
| 3203 | } | |
| 3204 | ||
| 3205 | window.scrollFileToLine = function (line) { | |
| 3206 | const row = document.getElementById('L' + line) | |
| 3207 | if (row) { | |
| 3208 | // Clear previous highlights | |
| 3209 | document.querySelectorAll('.file-viewer tr.highlight').forEach(r => r.classList.remove('highlight')) | |
| 3210 | row.classList.add('highlight') | |
| 3211 | row.scrollIntoView({ block: 'center', behavior: 'smooth' }) | |
| 3212 | } | |
| 3213 | } | |
| 3214 | ||
| 3215 | // ====== VALIDATION PANEL ====== | |
| 3216 | let valInitialized = false | |
| 3217 | let valFilter = 'all' // 'all' | 'fail' | 'warn' | 'pass' | |
| 3218 | ||
| 3219 | function initValidation () { | |
| 3220 | valInitialized = true | |
| 3221 | const panel = document.getElementById('val-content') | |
| 3222 | const v = tree.validation | |
| 3223 | ||
| 3224 | if (!v) { | |
| 3225 | panel.innerHTML = '<p style="color:#8b949e">No spec directory found. Place specs in a <code>spec/</code> directory with <code>SYSTEM.md</code> and <code>modules/*.md</code> files.</p>' | |
| 3226 | return | |
| 3227 | } | |
| 3228 | ||
| 3229 | renderValidation(null) // show all | |
| 3230 | } | |
| 3231 | ||
| 3232 | function renderValidation (moduleName) { | |
| 3233 | const panel = document.getElementById('val-content') | |
| 3234 | const v = tree.validation | |
| 3235 | if (!v) return | |
| 3236 | ||
| 3237 | let html = '' | |
| 3238 | ||
| 3239 | // Summary bar | |
| 3240 | html += '<div class="val-summary">' | |
| 3241 | html += '<div class="val-pass"><span class="val-count">' + v.summary.pass + '</span>pass</div>' | |
| 3242 | html += '<div class="val-fail"><span class="val-count">' + v.summary.fail + '</span>fail</div>' | |
| 3243 | html += '<div class="val-warn"><span class="val-count">' + v.summary.warn + '</span>warn</div>' | |
| 3244 | html += '<div style="color:#8b949e"><span class="val-count">' + v.summary.total + '</span>total</div>' | |
| 3245 | html += '</div>' | |
| 3246 | ||
| 3247 | // Filter buttons | |
| 3248 | html += '<div class="val-filter">' | |
| 3249 | html += '<button class="' + (valFilter === 'all' ? 'active' : '') + '" onclick="setValFilter("all")">All</button>' | |
| 3250 | html += '<button class="' + (valFilter === 'fail' ? 'active' : '') + '" onclick="setValFilter("fail")">Fails</button>' | |
| 3251 | html += '<button class="' + (valFilter === 'warn' ? 'active' : '') + '" onclick="setValFilter("warn")">Warns</button>' | |
| 3252 | html += '<button class="' + (valFilter === 'pass' ? 'active' : '') + '" onclick="setValFilter("pass")">Pass</button>' | |
| 3253 | html += '</div>' | |
| 3254 | ||
| 3255 | // System checks | |
| 3256 | if (v.system && (!moduleName || moduleName === 'system')) { | |
| 3257 | const checks = filterChecks(v.system.checks) | |
| 3258 | if (checks.length > 0) { | |
| 3259 | html += '<div class="val-section"><h3>System</h3>' | |
| 3260 | html += renderChecks(checks) | |
| 3261 | html += '</div>' | |
| 3262 | } | |
| 3263 | } | |
| 3264 | ||
| 3265 | // Module checks | |
| 3266 | const modules = moduleName && moduleName !== 'system' | |
| 3267 | ? [[moduleName, v.modules[moduleName]]] | |
| 3268 | : Object.entries(v.modules) | |
| 3269 | ||
| 3270 | for (const [name, modReport] of modules) { | |
| 3271 | if (!modReport) continue | |
| 3272 | const checks = filterChecks(modReport.checks) | |
| 3273 | if (checks.length === 0) continue | |
| 3274 | ||
| 3275 | const failCount = modReport.checks.filter(c => c.status === 'fail').length | |
| 3276 | const warnCount = modReport.checks.filter(c => c.status === 'warn').length | |
| 3277 | const passCount = modReport.checks.filter(c => c.status === 'pass').length | |
| 3278 | ||
| 3279 | html += '<div class="val-section">' | |
| 3280 | html += '<h3 onclick="renderValidation("' + name + '")" style="cursor:pointer">' | |
| 3281 | html += name | |
| 3282 | html += ' <span class="val-pass">' + passCount + '</span>' | |
| 3283 | if (failCount) html += ' <span class="val-fail">' + failCount + ' fail</span>' | |
| 3284 | if (warnCount) html += ' <span class="val-warn">' + warnCount + ' warn</span>' | |
| 3285 | html += '</h3>' | |
| 3286 | html += renderChecks(checks) | |
| 3287 | html += '</div>' | |
| 3288 | } | |
| 3289 | ||
| 3290 | // Back button if filtered to one module | |
| 3291 | if (moduleName) { | |
| 3292 | html += '<div style="margin-top:12px"><button style="background:#161b22;border:1px solid #30363d;border-radius:4px;color:#58a6ff;padding:4px 12px;cursor:pointer;font-family:inherit;font-size:11px" onclick="renderValidation(null)">Show all modules</button></div>' | |
| 3293 | } | |
| 3294 | ||
| 3295 | panel.innerHTML = html | |
| 3296 | } | |
| 3297 | ||
| 3298 | function filterChecks (checks) { | |
| 3299 | if (valFilter === 'all') return checks | |
| 3300 | return checks.filter(c => c.status === valFilter) | |
| 3301 | } | |
| 3302 | ||
| 3303 | function renderChecks (checks) { | |
| 3304 | let html = '' | |
| 3305 | for (const c of checks) { | |
| 3306 | const icon = c.status === 'pass' ? '✓' : c.status === 'fail' ? '✗' : '⚠' | |
| 3307 | html += '<div class="val-check ' + c.status + '">' | |
| 3308 | html += '<span class="val-icon">' + icon + '</span>' | |
| 3309 | html += '<span class="val-claim">' + escapeHtml(c.claim) + '</span>' | |
| 3310 | if (c.detail) html += '<div class="val-detail">' + escapeHtml(c.detail) + '</div>' | |
| 3311 | html += '</div>' | |
| 3312 | } | |
| 3313 | return html | |
| 3314 | } | |
| 3315 | ||
| 3316 | window.setValFilter = function (f) { | |
| 3317 | valFilter = f | |
| 3318 | renderValidation(null) | |
| 3319 | } | |
| 3320 | ||
| 3321 | // Expose for onclick in rendered HTML | |
| 3322 | window.renderValidation = renderValidation | |
| 3323 | ||
| 3324 | // Also update validation when clicking modules in tree view | |
| 3325 | function showValidationForModule (name) { | |
| 3326 | if (tree.validation && tree.validation.modules[name]) { | |
| 3327 | document.getElementById('right-panel').style.display = 'block' | |
| 3328 | document.getElementById('resize-right').style.display = '' | |
| 3329 | switchRightPanel('validation') | |
| 3330 | renderValidation(name) | |
| 3331 | } | |
| 3332 | } | |
| 3333 | ||
| 3334 | // ====== TREE EXPAND/COLLAPSE ====== | |
| 3335 | window.expandAll = function () { | |
| 3336 | document.querySelectorAll('#tree-root li.collapsed').forEach(li => { | |
| 3337 | li.classList.remove('collapsed') | |
| 3338 | const toggle = li.querySelector(':scope > .node .toggle') | |
| 3339 | if (toggle) toggle.textContent = '-' | |
| 3340 | }) | |
| 3341 | } | |
| 3342 | ||
| 3343 | window.collapseAll = function () { | |
| 3344 | document.querySelectorAll('#tree-root li').forEach(li => { | |
| 3345 | if (li.querySelector('ul')) { | |
| 3346 | li.classList.add('collapsed') | |
| 3347 | const toggle = li.querySelector(':scope > .node .toggle') | |
| 3348 | if (toggle) toggle.textContent = '+' | |
| 3349 | } | |
| 3350 | }) | |
| 3351 | } | |
| 3352 | ||
| 3353 | // ====== VALIDATION HELPERS ====== | |
| 3354 | function getModuleValidation (name) { | |
| 3355 | if (!tree.validation || !tree.validation.modules[name]) return null | |
| 3356 | const checks = tree.validation.modules[name].checks | |
| 3357 | return { | |
| 3358 | pass: checks.filter(c => c.status === 'pass').length, | |
| 3359 | fail: checks.filter(c => c.status === 'fail').length, | |
| 3360 | warn: checks.filter(c => c.status === 'warn').length, | |
| 3361 | total: checks.length | |
| 3362 | } | |
| 3363 | } | |
| 3364 | ||
| 3365 | function valBadgeHTML (name) { | |
| 3366 | const v = getModuleValidation(name) | |
| 3367 | if (!v) return '<span class="val-badge val-badge-none">no spec</span>' | |
| 3368 | if (v.fail > 0) return '<span class="val-badge val-badge-fail">' + v.fail + ' fail</span>' + (v.warn > 0 ? '<span class="val-badge val-badge-warn">' + v.warn + ' warn</span>' : '') | |
| 3369 | if (v.warn > 0) return '<span class="val-badge val-badge-warn">' + v.warn + ' warn</span>' | |
| 3370 | return '<span class="val-badge val-badge-pass">' + v.pass + ' ok</span>' | |
| 3371 | } | |
| 3372 | ||
| 3373 | // ====== TREE DEP HIGHLIGHTING ====== | |
| 3374 | function highlightTreeDeps (moduleName) { | |
| 3375 | // Clear previous highlights | |
| 3376 | document.querySelectorAll('.dep-highlight, .used-by-highlight, .selected-module').forEach(el => { | |
| 3377 | el.classList.remove('dep-highlight', 'used-by-highlight', 'selected-module') | |
| 3378 | }) | |
| 3379 | ||
| 3380 | const mod = tree.modules[moduleName] | |
| 3381 | if (!mod) return | |
| 3382 | ||
| 3383 | // Find local deps (modules that exist in the scan) | |
| 3384 | const localDeps = new Set() | |
| 3385 | for (const dep of Object.keys(mod.dependencies)) { | |
| 3386 | if (tree.modules[dep]) localDeps.add(dep) | |
| 3387 | } | |
| 3388 | ||
| 3389 | // Find reverse deps (modules that depend on this one) | |
| 3390 | const usedBy = new Set() | |
| 3391 | for (const [otherName, otherMod] of Object.entries(tree.modules)) { | |
| 3392 | if (otherName === moduleName) continue | |
| 3393 | if (otherMod.dependencies[moduleName]) usedBy.add(otherName) | |
| 3394 | } | |
| 3395 | ||
| 3396 | // Highlight matching module nodes in the tree | |
| 3397 | document.querySelectorAll('#tree-root .node[data-type="module"]').forEach(node => { | |
| 3398 | const name = node.dataset.name | |
| 3399 | if (name === moduleName) node.classList.add('selected-module') | |
| 3400 | else if (localDeps.has(name)) node.classList.add('dep-highlight') | |
| 3401 | else if (usedBy.has(name)) node.classList.add('used-by-highlight') | |
| 3402 | }) | |
| 3403 | } | |
| 3404 | ||
| 3405 | // ====== SEARCH ====== | |
| 3406 | document.getElementById('search').addEventListener('input', (e) => { | |
| 3407 | const q = e.target.value.toLowerCase() | |
| 3408 | const nodes = document.querySelectorAll('#tree-root .node') | |
| 3409 | for (const node of nodes) { | |
| 3410 | const name = (node.dataset.name || '').toLowerCase() | |
| 3411 | const text = node.textContent.toLowerCase() | |
| 3412 | const match = !q || name.includes(q) || text.includes(q) | |
| 3413 | node.parentElement.style.display = match ? '' : 'none' | |
| 3414 | if (match && q) { | |
| 3415 | let parent = node.parentElement.parentElement | |
| 3416 | while (parent) { | |
| 3417 | if (parent.classList && parent.classList.contains('collapsed')) { | |
| 3418 | parent.classList.remove('collapsed') | |
| 3419 | const toggle = parent.querySelector(':scope > .node .toggle') | |
| 3420 | if (toggle) toggle.textContent = '-' | |
| 3421 | } | |
| 3422 | parent = parent.parentElement | |
| 3423 | } | |
| 3424 | } | |
| 3425 | } | |
| 3426 | }) | |
| 3427 | ||
| 3428 | // ====== STATS ====== | |
| 3429 | function updateStats () { | |
| 3430 | const stats = document.getElementById('stats') | |
| 3431 | let totalFiles = 0, totalClasses = 0, totalMethods = 0, totalExports = 0 | |
| 3432 | for (const mod of Object.values(tree.modules)) { | |
| 3433 | totalFiles += Object.keys(mod.files).length | |
| 3434 | totalExports += mod.publicAPI.length | |
| 3435 | for (const file of Object.values(mod.files)) { | |
| 3436 | if (file.classes) { | |
| 3437 | totalClasses += file.classes.length | |
| 3438 | for (const cls of file.classes) totalMethods += cls.methods.length + (cls.getters ? cls.getters.length : 0) | |
| 3439 | } | |
| 3440 | } | |
| 3441 | } | |
| 3442 | stats.innerHTML = | |
| 3443 | '<span><span class="stat-value">' + tree.system.modules.length + '</span> modules</span>' + | |
| 3444 | '<span><span class="stat-value">' + totalFiles + '</span> files</span>' + | |
| 3445 | '<span><span class="stat-value">' + totalClasses + '</span> classes</span>' + | |
| 3446 | '<span><span class="stat-value">' + totalMethods + '</span> members</span>' + | |
| 3447 | '<span><span class="stat-value">' + totalExports + '</span> exports</span>' | |
| 3448 | } | |
| 3449 | ||
| 3450 | // ====== HELPERS ====== | |
| 3451 | function el (tag, attrs) { | |
| 3452 | const e = document.createElement(tag) | |
| 3453 | if (attrs) for (const [k, v] of Object.entries(attrs)) { | |
| 3454 | if (k.startsWith('data-')) e.setAttribute(k, v) | |
| 3455 | else e[k] = v | |
| 3456 | } | |
| 3457 | return e | |
| 3458 | } | |
| 3459 | function sourceLink (line) { | |
| 3460 | if (!currentFileContext) return '' | |
| 3461 | const modPath = currentFileContext.moduleName ? tree.modules[currentFileContext.moduleName].path + '/' : '' | |
| 3462 | const fullPath = modPath + currentFileContext.path | |
| 3463 | return '<span class="badge" style="cursor:pointer;color:#58a6ff;border:1px solid #58a6ff;margin-bottom:8px;display:inline-block" ' + | |
| 3464 | 'onclick="loadFileViewer("' + fullPath + '","' + (currentFileContext.moduleName || '') + '",' + (line || 'null') + ')">' + | |
| 3465 | 'View Source' + (line ? ' :' + line : '') + '</span> ' | |
| 3466 | } | |
| 3467 | ||
| 3468 | // Expose for onclick attributes | |
| 3469 | window.loadFileViewer = loadFileViewer | |
| 3470 | ||
| 3471 | function roleIcon (role) { | |
| 3472 | return ({ entry: 'E', lib: 'L', test: 'T', schema: 'S', bin: 'B', script: 'X', example: 'x' })[role] || 'F' | |
| 3473 | } | |
| 3474 | function escapeHtml (s) { | |
| 3475 | return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') | |
| 3476 | } | |
| 3477 | ||
| 3478 | // ====== RESIZABLE PANELS ====== | |
| 3479 | function initResizable () { | |
| 3480 | makeResizable('resize-left', 'sidebar', 'right') | |
| 3481 | makeResizable('resize-right', 'right-panel', 'left') | |
| 3482 | } | |
| 3483 | ||
| 3484 | function makeResizable (handleId, panelId, side) { | |
| 3485 | const handle = document.getElementById(handleId) | |
| 3486 | const panel = document.getElementById(panelId) | |
| 3487 | if (!handle || !panel) return | |
| 3488 | ||
| 3489 | let startX, startW | |
| 3490 | ||
| 3491 | handle.addEventListener('mousedown', (e) => { | |
| 3492 | e.preventDefault() | |
| 3493 | e.stopPropagation() | |
| 3494 | startX = e.clientX | |
| 3495 | startW = panel.offsetWidth | |
| 3496 | handle.classList.add('dragging') | |
| 3497 | document.body.style.cursor = 'col-resize' | |
| 3498 | document.body.style.userSelect = 'none' | |
| 3499 | ||
| 3500 | const onMove = (e) => { | |
| 3501 | const dx = e.clientX - startX | |
| 3502 | const newW = side === 'right' ? startW + dx : startW - dx | |
| 3503 | panel.style.width = Math.max(150, Math.min(800, newW)) + 'px' | |
| 3504 | } | |
| 3505 | ||
| 3506 | const onUp = () => { | |
| 3507 | handle.classList.remove('dragging') | |
| 3508 | document.body.style.cursor = '' | |
| 3509 | document.body.style.userSelect = '' | |
| 3510 | document.removeEventListener('mousemove', onMove) | |
| 3511 | document.removeEventListener('mouseup', onUp) | |
| 3512 | } | |
| 3513 | ||
| 3514 | document.addEventListener('mousemove', onMove) | |
| 3515 | document.addEventListener('mouseup', onUp) | |
| 3516 | }) | |
| 3517 | } | |
| 3518 | ||
| 3519 | // ====== INIT ====== | |
| 3520 | buildTree() | |
| 3521 | initResizable() | |
| 3522 | </script> | |
| 3523 | </body> | |
| 3524 | </html>` | |
| 3525 | } |
| … | … | @@ -0,0 +1,311 @@ |
| 1 | import { EventEmitter } from 'events' | |
| 2 | import { readFileSync, readdirSync, statSync } from 'fs' | |
| 3 | import { resolve, relative, join, basename, dirname } from 'path' | |
| 4 | ||
| 5 | import { | |
| 6 | detectProject, | |
| 7 | findModuleBoundaries, | |
| 8 | buildResolutionContext, | |
| 9 | readProjectMeta, | |
| 10 | resolveEntry, | |
| 11 | getLang, | |
| 12 | isSourceFile | |
| 13 | } from './lang.js' | |
| 14 | import { buildIgnoreMatcher } from './ignore.js' | |
| 15 | ||
| 16 | /** | |
| 17 | * Walk a project and emit events describing what was found. | |
| 18 | * | |
| 19 | * This is the push-based core of the scanner. Multiple consumers can | |
| 20 | * subscribe to different events without forcing a second walk. | |
| 21 | * | |
| 22 | * const source = scanStream(rootDir, opts) | |
| 23 | * source.on('file-parsed', e => ...) | |
| 24 | * source.on('scan-end', e => ...) | |
| 25 | * | |
| 26 | * Events (all payload objects): | |
| 27 | * scan-start { root, projectType, languages, resolutionContext } | |
| 28 | * module-start { name, version, path, absPath, entry, meta, projectType, | |
| 29 | * dependencies, devDependencies, importMaps, testCommand, type } | |
| 30 | * file-discovered { modName, absPath, relPath, relInPkg, source, size } | |
| 31 | * file-parsed { modName, relInPkg, relPath, parsed } | |
| 32 | * import-edge { modName, fromRelInPkg, specifier, resolvedRelPath, implicit } | |
| 33 | * module-end { name } | |
| 34 | * scan-end { root, moduleCount, fileCount, dirTree } | |
| 35 | * error Error | |
| 36 | * | |
| 37 | * The emitter returned from this function starts work on the next tick, giving | |
| 38 | * callers a chance to attach listeners before the first event fires. | |
| 39 | * | |
| 40 | * There are NO timers anywhere in this file. Every async boundary is a | |
| 41 | * promise/microtask or a listener callback. | |
| 42 | */ | |
| 43 | export function scanStream (rootDir, opts = {}) { | |
| 44 | const emitter = new EventEmitter() | |
| 45 | const root = resolve(rootDir) | |
| 46 | ||
| 47 | // Defer the walk so callers can attach listeners first. queueMicrotask is | |
| 48 | // push-based — no setTimeout, no Promise.resolve().then hack. | |
| 49 | queueMicrotask(() => runScan(emitter, root, opts)) | |
| 50 | ||
| 51 | return emitter | |
| 52 | } | |
| 53 | ||
| 54 | function runScan (emitter, root, opts) { | |
| 55 | try { | |
| 56 | const ignore = opts.ignore || buildIgnoreMatcher(root) | |
| 57 | const shallow = !!opts.shallow | |
| 58 | const project = detectProject(root) | |
| 59 | const resolutionContext = buildResolutionContext(root, project.type, ignore, { shallow }) | |
| 60 | resolutionContext.ignore = ignore | |
| 61 | ||
| 62 | emitter.emit('scan-start', { | |
| 63 | root, | |
| 64 | projectType: project.type, | |
| 65 | languages: project.languages, | |
| 66 | shallow, | |
| 67 | resolutionContext | |
| 68 | }) | |
| 69 | ||
| 70 | const moduleDirs = findModuleBoundaries(root, project.type, { | |
| 71 | maxDepth: opts.maxDepth || 2, | |
| 72 | ignore | |
| 73 | }) | |
| 74 | ||
| 75 | let moduleCount = 0 | |
| 76 | let fileCount = 0 | |
| 77 | const moduleAbsPaths = new Set(moduleDirs) | |
| 78 | ||
| 79 | for (const pkgDir of moduleDirs) { | |
| 80 | // Each module may be its own project type (monorepo case) | |
| 81 | const modProject = detectProject(pkgDir) | |
| 82 | const modType = modProject.type !== 'unknown' ? modProject.type : project.type | |
| 83 | const meta = readProjectMeta(pkgDir, modType) | |
| 84 | if (modType === 'js' && !meta) continue | |
| 85 | ||
| 86 | const modName = (meta && meta.name) || basename(pkgDir) | |
| 87 | const entry = resolveEntry(pkgDir, meta, modType) | |
| 88 | ||
| 89 | emitter.emit('module-start', { | |
| 90 | name: modName, | |
| 91 | version: (meta && meta.version) || '0.0.0', | |
| 92 | path: relative(root, pkgDir) || '.', | |
| 93 | absPath: pkgDir, | |
| 94 | entry, | |
| 95 | meta, | |
| 96 | projectType: modType, | |
| 97 | dependencies: (meta && meta.dependencies) || {}, | |
| 98 | devDependencies: (meta && meta.devDependencies) || {}, | |
| 99 | importMaps: (meta && meta.imports) || {}, | |
| 100 | testCommand: meta && meta.scripts && meta.scripts.test ? meta.scripts.test : null, | |
| 101 | type: (meta && meta.type) || 'commonjs' | |
| 102 | }) | |
| 103 | ||
| 104 | if (shallow) { | |
| 105 | // Shallow mode: parse ONLY the entry file (if any). No import resolution, | |
| 106 | // no scanDir recursion, no cross-file analysis. This gives the UI enough | |
| 107 | // to show every module + its public API without paying the full parse cost. | |
| 108 | if (entry) { | |
| 109 | fileCount += parseOneFile(emitter, entry, pkgDir, modName, root, ignore) | |
| 110 | } | |
| 111 | } else { | |
| 112 | // Deep mode: walk entry + recursively scan module root, resolve imports. | |
| 113 | const childModulePaths = new Set( | |
| 114 | moduleDirs.filter(d => d !== pkgDir && d.startsWith(pkgDir + '/')) | |
| 115 | ) | |
| 116 | const visited = new Set() | |
| 117 | ||
| 118 | if (entry) { | |
| 119 | fileCount += walkFile(emitter, entry, pkgDir, modName, visited, root, ignore, resolutionContext) | |
| 120 | } | |
| 121 | fileCount += scanDir(emitter, pkgDir, pkgDir, modName, visited, root, ignore, resolutionContext, childModulePaths) | |
| 122 | } | |
| 123 | ||
| 124 | emitter.emit('module-end', { name: modName }) | |
| 125 | moduleCount++ | |
| 126 | } | |
| 127 | ||
| 128 | // Always build dirTree, even in shallow mode — the FS walk is cheap (just | |
| 129 | // readdir+stat) compared to parsing, and the UI tree view needs structure. | |
| 130 | // Without it the sidebar collapses to a flat list which is unreadable | |
| 131 | // for monorepo-scale scans. | |
| 132 | const dirTree = buildDirTree(root, moduleAbsPaths, ignore) | |
| 133 | ||
| 134 | emitter.emit('scan-end', { root, moduleCount, fileCount, dirTree, shallow }) | |
| 135 | } catch (err) { | |
| 136 | emitter.emit('error', err) | |
| 137 | } | |
| 138 | } | |
| 139 | ||
| 140 | // Parse a single file (used by shallow mode). Emits file-discovered + file-parsed | |
| 141 | // but does NOT follow imports or recurse. | |
| 142 | function parseOneFile (emitter, filePath, pkgDir, modName, root, ignore) { | |
| 143 | if (ignore(filePath)) return 0 | |
| 144 | let source | |
| 145 | try { source = readFileSync(filePath, 'utf-8') } catch { return 0 } | |
| 146 | const size = source.length | |
| 147 | if (size > MAX_PARSE_SIZE) return 0 | |
| 148 | ||
| 149 | const relPath = relative(root, filePath) | |
| 150 | const relInPkg = relative(pkgDir, filePath) | |
| 151 | ||
| 152 | emitter.emit('file-discovered', { modName, absPath: filePath, relPath, relInPkg, size }) | |
| 153 | ||
| 154 | const lang = getLang(filePath) | |
| 155 | if (!lang) return 1 | |
| 156 | ||
| 157 | try { | |
| 158 | const parsed = lang.parse(source, relInPkg) | |
| 159 | emitter.emit('file-parsed', { modName, relInPkg, relPath, parsed }) | |
| 160 | } catch (err) { | |
| 161 | emitter.emit('file-parsed', { modName, relInPkg, relPath, parsed: { error: err.message, filePath: relInPkg } }) | |
| 162 | } | |
| 163 | return 1 | |
| 164 | } | |
| 165 | ||
| 166 | // --- Walking --- | |
| 167 | ||
| 168 | // Skip parsing files larger than this. Generated bindings and minified bundles | |
| 169 | // are almost always uninteresting for structural analysis, and their ASTs are | |
| 170 | // the dominant memory cost on large recursive scans. | |
| 171 | const MAX_PARSE_SIZE = 200 * 1024 // 200 KB | |
| 172 | ||
| 173 | function walkFile (emitter, filePath, pkgDir, modName, visited, root, ignore, ctx) { | |
| 174 | if (visited.has(filePath)) return 0 | |
| 175 | visited.add(filePath) | |
| 176 | if (ignore(filePath)) return 0 | |
| 177 | ||
| 178 | let source, size | |
| 179 | try { | |
| 180 | source = readFileSync(filePath, 'utf-8') | |
| 181 | size = source.length | |
| 182 | } catch { | |
| 183 | return 0 | |
| 184 | } | |
| 185 | ||
| 186 | const relPath = relative(root, filePath) | |
| 187 | const relInPkg = relative(pkgDir, filePath) | |
| 188 | ||
| 189 | // For oversized files, emit the discovery event so the tree knows the file | |
| 190 | // exists, but skip parsing + import resolution. Saves memory and CPU. | |
| 191 | if (size > MAX_PARSE_SIZE) { | |
| 192 | emitter.emit('file-discovered', { modName, absPath: filePath, relPath, relInPkg, size }) | |
| 193 | emitter.emit('file-parsed', { modName, relInPkg, relPath, parsed: { error: 'file too large to parse', filePath: relInPkg } }) | |
| 194 | return 1 | |
| 195 | } | |
| 196 | ||
| 197 | // Deliberately do NOT include source in the event — subscribers that actually | |
| 198 | // need the bytes can readFileSync from absPath. Sending source by default | |
| 199 | // means every listener retains it, which blew up memory on recursive scans. | |
| 200 | emitter.emit('file-discovered', { | |
| 201 | modName, absPath: filePath, relPath, relInPkg, size | |
| 202 | }) | |
| 203 | ||
| 204 | const lang = getLang(filePath) | |
| 205 | if (!lang) return 1 | |
| 206 | ||
| 207 | // Parse eagerly and emit. (Workers and mtime cache are future optimizations | |
| 208 | // that plug in here — they just change who produces the file-parsed event.) | |
| 209 | try { | |
| 210 | const parsed = lang.parse(source, relInPkg) | |
| 211 | emitter.emit('file-parsed', { modName, relInPkg, relPath, parsed }) | |
| 212 | } catch (err) { | |
| 213 | emitter.emit('file-parsed', { modName, relInPkg, relPath, parsed: { error: err.message, filePath: relInPkg } }) | |
| 214 | } | |
| 215 | ||
| 216 | // Resolve imports (explicit + implicit) and emit edges for each. | |
| 217 | let count = 1 | |
| 218 | const explicit = lang.extractImports(source) | |
| 219 | for (const spec of explicit) { | |
| 220 | const resolved = lang.resolveImport(filePath, spec, ctx) | |
| 221 | if (!resolved) continue | |
| 222 | emitter.emit('import-edge', { | |
| 223 | modName, | |
| 224 | fromRelInPkg: relInPkg, | |
| 225 | specifier: spec, | |
| 226 | resolvedRelPath: relative(root, resolved), | |
| 227 | implicit: false | |
| 228 | }) | |
| 229 | count += walkFile(emitter, resolved, pkgDir, modName, visited, root, ignore, ctx) | |
| 230 | } | |
| 231 | ||
| 232 | if (lang.extractImplicitImports) { | |
| 233 | const implicit = lang.extractImplicitImports(source, ctx) | |
| 234 | for (const spec of implicit) { | |
| 235 | const resolved = lang.resolveImport(filePath, spec, ctx) | |
| 236 | if (!resolved || resolved === filePath) continue | |
| 237 | emitter.emit('import-edge', { | |
| 238 | modName, | |
| 239 | fromRelInPkg: relInPkg, | |
| 240 | specifier: spec, | |
| 241 | resolvedRelPath: relative(root, resolved), | |
| 242 | implicit: true | |
| 243 | }) | |
| 244 | count += walkFile(emitter, resolved, pkgDir, modName, visited, root, ignore, ctx) | |
| 245 | } | |
| 246 | } | |
| 247 | ||
| 248 | return count | |
| 249 | } | |
| 250 | ||
| 251 | function scanDir (emitter, dir, pkgDir, modName, visited, root, ignore, ctx, childModulePaths) { | |
| 252 | let entries | |
| 253 | try { entries = readdirSync(dir) } catch { return 0 } | |
| 254 | ||
| 255 | let count = 0 | |
| 256 | for (const entry of entries) { | |
| 257 | if (entry.startsWith('.')) continue | |
| 258 | const full = join(dir, entry) | |
| 259 | if (ignore(full)) continue | |
| 260 | if (childModulePaths && childModulePaths.has(full)) continue | |
| 261 | ||
| 262 | let stat | |
| 263 | try { stat = statSync(full) } catch { continue } | |
| 264 | ||
| 265 | if (stat.isDirectory()) { | |
| 266 | count += scanDir(emitter, full, pkgDir, modName, visited, root, ignore, ctx, childModulePaths) | |
| 267 | } else if (isSourceFile(full)) { | |
| 268 | count += walkFile(emitter, full, pkgDir, modName, visited, root, ignore, ctx) | |
| 269 | } | |
| 270 | } | |
| 271 | return count | |
| 272 | } | |
| 273 | ||
| 274 | // --- Directory tree --- | |
| 275 | ||
| 276 | function buildDirTree (root, moduleAbsPaths, ignore) { | |
| 277 | return walkDir(root, root, moduleAbsPaths, 0, 8, ignore) | |
| 278 | } | |
| 279 | ||
| 280 | function walkDir (dir, root, moduleAbsPaths, depth, maxDepth, ignore) { | |
| 281 | const name = basename(dir) | |
| 282 | const relPath = relative(root, dir) || '.' | |
| 283 | const node = { | |
| 284 | name: depth === 0 ? basename(root) : name, | |
| 285 | path: relPath, | |
| 286 | type: moduleAbsPaths.has(dir) ? 'module-dir' : 'dir', | |
| 287 | children: [] | |
| 288 | } | |
| 289 | if (moduleAbsPaths.has(dir)) node.module = basename(dir) | |
| 290 | ||
| 291 | if (depth >= maxDepth) return node | |
| 292 | ||
| 293 | let entries | |
| 294 | try { entries = readdirSync(dir).sort() } catch { return node } | |
| 295 | ||
| 296 | // Only collect directories. File entries were a huge bloat in the dirTree | |
| 297 | // payload (33 MB for /storage/projects/code/) and aren't used by the sidebar | |
| 298 | // anymore — files for a focused module come from /api/file on demand. | |
| 299 | for (const entry of entries) { | |
| 300 | const full = join(dir, entry) | |
| 301 | if (ignore(full)) continue | |
| 302 | let stat | |
| 303 | try { stat = statSync(full) } catch { continue } | |
| 304 | if (!stat.isDirectory()) continue | |
| 305 | ||
| 306 | const child = walkDir(full, root, moduleAbsPaths, depth + 1, maxDepth, ignore) | |
| 307 | if (child.children.length > 0 || child.module) node.children.push(child) | |
| 308 | } | |
| 309 | ||
| 310 | return node | |
| 311 | } |
| … | … | @@ -0,0 +1,108 @@ |
| 1 | import { existsSync } from 'fs' | |
| 2 | import { resolve, join } from 'path' | |
| 3 | ||
| 4 | import { scanStream } from './scan-stream.js' | |
| 5 | import { TreeReducer } from './reducers/tree-reducer.js' | |
| 6 | import { buildTree } from './tree.js' | |
| 7 | import { parseSpecs, findAllDocs } from './doc-parser.js' | |
| 8 | import { validate } from './validator.js' | |
| 9 | import { detectDocCruft } from './doc-cruft.js' | |
| 10 | import { buildIgnoreMatcher } from './ignore.js' | |
| 11 | ||
| 12 | // Re-export for consumers that want the push-based source directly | |
| 13 | export { scanStream } from './scan-stream.js' | |
| 14 | export { TreeReducer } from './reducers/tree-reducer.js' | |
| 15 | ||
| 16 | /** | |
| 17 | * Scan a directory and produce the complete code tree + validation report. | |
| 18 | * | |
| 19 | * Internally this composes scanStream() with a TreeReducer. Other consumers | |
| 20 | * (UI updaters, metrics, doc-cruft) can attach their own listeners to the | |
| 21 | * stream — that's the whole point of the refactor. This function is one | |
| 22 | * convenience consumer that returns the fully-built tree. | |
| 23 | * | |
| 24 | * opts: | |
| 25 | * maxDepth: number — project-discovery depth (default 2) | |
| 26 | * ignore: string[] — extra ignore patterns (from --ignore CLI flag) | |
| 27 | * shallow: boolean — if true, only parse the entry file per module. | |
| 28 | * No cross-file analysis, no doc-cruft, no | |
| 29 | * resolution context. Orders of magnitude faster | |
| 30 | * for multi-project / recursive scans. | |
| 31 | */ | |
| 32 | export async function scan (rootDir, opts = {}) { | |
| 33 | // Build ignore matcher up front so every scan stage uses the same predicate. | |
| 34 | const ignore = buildIgnoreMatcher(rootDir, opts.ignore || []) | |
| 35 | const shallow = !!opts.shallow | |
| 36 | ||
| 37 | // Drive the event source and reduce events into a graph. | |
| 38 | const graph = await new Promise((resolve, reject) => { | |
| 39 | const source = scanStream(rootDir, { ...opts, ignore, shallow }) | |
| 40 | const tree = new TreeReducer().attach(source) | |
| 41 | source.once('scan-end', () => resolve(tree.finalize())) | |
| 42 | source.once('error', reject) | |
| 43 | }) | |
| 44 | ||
| 45 | const tree = buildTree(graph) | |
| 46 | ||
| 47 | // Mark the tree so consumers know whether data is complete or shallow. | |
| 48 | tree.shallow = shallow | |
| 49 | ||
| 50 | // Attach the live graph as a non-enumerable property so consumers that need | |
| 51 | // the incremental-update state (e.g. LiveStore in server.js) can reach it, | |
| 52 | // but JSON serialization ignores it. | |
| 53 | Object.defineProperty(tree, '__graph', { value: graph, enumerable: false }) | |
| 54 | ||
| 55 | // Doc cruft walks every .md file and cross-references against the tree. | |
| 56 | // Skip in shallow mode — it's one of the most expensive steps and the | |
| 57 | // tree doesn't have the structural detail needed for meaningful checks. | |
| 58 | if (!shallow) { | |
| 59 | tree.docCruft = detectDocCruft(rootDir, tree, ignore) | |
| 60 | } | |
| 61 | ||
| 62 | // Find and validate specs at the scan root (preserves existing behavior). | |
| 63 | const docs = findAllDocs(rootDir) | |
| 64 | let validation = null | |
| 65 | let categories = null | |
| 66 | if (docs.specDir) { | |
| 67 | const specs = parseSpecs(docs.specDir) | |
| 68 | validation = validate(tree, specs) | |
| 69 | if (specs.system && specs.system.categories) { | |
| 70 | categories = { ...specs.system.categories } | |
| 71 | } | |
| 72 | } | |
| 73 | ||
| 74 | // Aggregate categories from spec/SYSTEM.md files nested INSIDE any discovered | |
| 75 | // module. For a high-level scan like /storage/projects/code/, the curated | |
| 76 | // SYSTEM.md sits 4+ levels deep (e.g. hypercore-kb/hyper-fleeky/pear-git-v3/ | |
| 77 | // spec/SYSTEM.md). Without this, the bubbles in the graph would lose all the | |
| 78 | // semantic categories that were carefully defined in those spec files. | |
| 79 | if (!categories) categories = {} | |
| 80 | for (const mod of Object.values(tree.modules)) { | |
| 81 | const modAbs = resolve(rootDir, mod.path) | |
| 82 | const candidates = [join(modAbs, 'spec'), join(modAbs, 'docs', 'spec')] | |
| 83 | for (const sd of candidates) { | |
| 84 | if (!existsSync(join(sd, 'SYSTEM.md'))) continue | |
| 85 | try { | |
| 86 | const innerSpecs = parseSpecs(sd) | |
| 87 | if (innerSpecs.system && innerSpecs.system.categories) { | |
| 88 | for (const [cat, mods] of Object.entries(innerSpecs.system.categories)) { | |
| 89 | if (!categories[cat]) categories[cat] = [] | |
| 90 | for (const m of mods) { | |
| 91 | if (!categories[cat].includes(m)) categories[cat].push(m) | |
| 92 | } | |
| 93 | } | |
| 94 | } | |
| 95 | } catch {} | |
| 96 | } | |
| 97 | } | |
| 98 | ||
| 99 | tree.validation = validation | |
| 100 | tree.categories = Object.keys(categories).length > 0 ? categories : null | |
| 101 | tree.docs = { | |
| 102 | specDir: docs.specDir || null, | |
| 103 | specCount: docs.specs.length, | |
| 104 | readmeCount: docs.readmes.length | |
| 105 | } | |
| 106 | ||
| 107 | return tree | |
| 108 | } |
| … | … | @@ -0,0 +1,207 @@ |
| 1 | import http from 'http' | |
| 2 | import { gzipSync } from 'zlib' | |
| 3 | import { readFileSync } from 'fs' | |
| 4 | import { resolve } from 'path' | |
| 5 | import { renderPage } from './render.js' | |
| 6 | import { buildIgnoreMatcher } from './ignore.js' | |
| 7 | import { LiveStore } from './live-store.js' | |
| 8 | ||
| 9 | export function startServer (tree, opts = {}) { | |
| 10 | const port = opts.port || 9078 | |
| 11 | const prefix = opts.prefix || '' | |
| 12 | const page = renderPage(tree, prefix) | |
| 13 | const rootDir = tree.root | |
| 14 | ||
| 15 | // Rebuild the ignore matcher so /api/file enforces the same hiding rules at runtime | |
| 16 | // as the scan did at tree-build time. A file that wasn't in the tree won't have a | |
| 17 | // request generated by the UI, but a crafted request could reach /api/file directly. | |
| 18 | const ignore = buildIgnoreMatcher(rootDir, opts.ignore || []) | |
| 19 | ||
| 20 | // Live store — subscribable event stream fed by fs.watch. opts.watch === false | |
| 21 | // disables it (useful for one-shot CLI serve, or when the inotify limit | |
| 22 | // would be exceeded by recursive watching of a huge tree). | |
| 23 | const live = opts.graph | |
| 24 | ? new LiveStore(opts.graph, { watch: opts.watch !== false }) | |
| 25 | : null | |
| 26 | if (live) { | |
| 27 | live.seedFromGraph() | |
| 28 | live.start() | |
| 29 | } | |
| 30 | ||
| 31 | // --- Response helpers --- | |
| 32 | ||
| 33 | // Compress the body with gzip if the client sent Accept-Encoding: gzip. | |
| 34 | // Only compresses when the payload is worth it (>1KB). Below that the | |
| 35 | // gzip overhead isn't worth the CPU. | |
| 36 | function send (req, res, status, contentType, body) { | |
| 37 | const accept = (req.headers['accept-encoding'] || '').toLowerCase() | |
| 38 | const acceptsGzip = accept.includes('gzip') | |
| 39 | const buf = typeof body === 'string' ? Buffer.from(body) : body | |
| 40 | ||
| 41 | if (acceptsGzip && buf.length > 1024) { | |
| 42 | const compressed = gzipSync(buf) | |
| 43 | res.writeHead(status, { | |
| 44 | 'content-type': contentType, | |
| 45 | 'content-encoding': 'gzip', | |
| 46 | 'vary': 'Accept-Encoding' | |
| 47 | }) | |
| 48 | res.end(compressed) | |
| 49 | } else { | |
| 50 | res.writeHead(status, { 'content-type': contentType }) | |
| 51 | res.end(buf) | |
| 52 | } | |
| 53 | } | |
| 54 | ||
| 55 | function sendJSON (req, res, status, obj) { | |
| 56 | send(req, res, status, 'application/json', JSON.stringify(obj)) | |
| 57 | } | |
| 58 | ||
| 59 | const server = http.createServer((req, res) => { | |
| 60 | // Strip prefix from URL | |
| 61 | let reqUrl = req.url | |
| 62 | if (prefix && reqUrl.startsWith(prefix)) { | |
| 63 | reqUrl = reqUrl.slice(prefix.length) || '/' | |
| 64 | } | |
| 65 | const [url, query] = reqUrl.split('?') | |
| 66 | ||
| 67 | if (url === '/' || url === '/index.html') { | |
| 68 | send(req, res, 200, 'text/html; charset=utf-8', page) | |
| 69 | return | |
| 70 | } | |
| 71 | ||
| 72 | if (url === '/api/tree') { | |
| 73 | sendJSON(req, res, 200, tree) | |
| 74 | return | |
| 75 | } | |
| 76 | ||
| 77 | // Server-Sent Events stream: replay current state as events, then push | |
| 78 | // live events (file changes detected by fs.watch) as they happen. | |
| 79 | // | |
| 80 | // Clients: `new EventSource('/codetree/api/events')` and attach | |
| 81 | // onmessage / addEventListener handlers per event type. | |
| 82 | if (url === '/api/events') { | |
| 83 | if (!live) { | |
| 84 | sendJSON(req, res, 503, { error: 'Live event stream not available (no graph attached)' }) | |
| 85 | return | |
| 86 | } | |
| 87 | res.writeHead(200, { | |
| 88 | 'content-type': 'text/event-stream', | |
| 89 | 'cache-control': 'no-cache', | |
| 90 | 'connection': 'keep-alive', | |
| 91 | 'x-accel-buffering': 'no' // disable proxy buffering (nginx/apache) | |
| 92 | }) | |
| 93 | ||
| 94 | const write = (ev) => { | |
| 95 | // SSE frame: `event: <type>\ndata: <json>\n\n` | |
| 96 | res.write('event: ' + ev.type + '\n') | |
| 97 | res.write('data: ' + JSON.stringify(ev) + '\n\n') | |
| 98 | } | |
| 99 | ||
| 100 | const unsubscribe = live.subscribe(write) | |
| 101 | ||
| 102 | // Flush on disconnect | |
| 103 | req.on('close', unsubscribe) | |
| 104 | req.on('error', unsubscribe) | |
| 105 | return | |
| 106 | } | |
| 107 | ||
| 108 | // Lazy deep scan of a single module. Used by the UI when the user drills | |
| 109 | // into a module that was originally captured shallow (only entry file | |
| 110 | // parsed). Returns the fully-parsed module suitable for replacing the | |
| 111 | // shallow placeholder client-side. | |
| 112 | // | |
| 113 | // GET /api/deep-scan?module=<name> | |
| 114 | if (url === '/api/deep-scan' && query) { | |
| 115 | const params = new URLSearchParams(query) | |
| 116 | const name = params.get('module') | |
| 117 | if (!name) { | |
| 118 | sendJSON(req, res, 400, { error: 'module parameter required' }) | |
| 119 | return | |
| 120 | } | |
| 121 | const placeholder = tree.modules[name] | |
| 122 | if (!placeholder) { | |
| 123 | sendJSON(req, res, 404, { error: 'Module not found: ' + name }) | |
| 124 | return | |
| 125 | } | |
| 126 | ||
| 127 | // Resolve the module's filesystem path and security-check it. | |
| 128 | const modAbsPath = resolve(rootDir, placeholder.path) | |
| 129 | if (!modAbsPath.startsWith(rootDir)) { | |
| 130 | sendJSON(req, res, 403, { error: 'Access denied' }) | |
| 131 | return | |
| 132 | } | |
| 133 | if (ignore(modAbsPath)) { | |
| 134 | sendJSON(req, res, 404, { error: 'Module path is ignored' }) | |
| 135 | return | |
| 136 | } | |
| 137 | ||
| 138 | // Lazy-import scan() + buildTree() to avoid pulling them at server boot. | |
| 139 | ;(async () => { | |
| 140 | try { | |
| 141 | const { scan } = await import('./scanner.js') | |
| 142 | const deep = await scan(modAbsPath, { ignore: opts.ignore || [], shallow: false }) | |
| 143 | // Return only the module entry (the new tree's root module). Strip | |
| 144 | // big sub-trees the client doesn't need. | |
| 145 | const deepMod = deep.modules[name] || deep.modules[Object.keys(deep.modules)[0]] | |
| 146 | sendJSON(req, res, 200, { name, mod: deepMod }) | |
| 147 | } catch (err) { | |
| 148 | sendJSON(req, res, 500, { error: err.message || String(err) }) | |
| 149 | } | |
| 150 | })() | |
| 151 | return | |
| 152 | } | |
| 153 | ||
| 154 | if (url.startsWith('/api/module/')) { | |
| 155 | const name = decodeURIComponent(url.slice('/api/module/'.length)) | |
| 156 | const mod = tree.modules[name] | |
| 157 | if (mod) { | |
| 158 | sendJSON(req, res, 200, mod) | |
| 159 | } else { | |
| 160 | sendJSON(req, res, 404, { error: 'Module not found' }) | |
| 161 | } | |
| 162 | return | |
| 163 | } | |
| 164 | ||
| 165 | // File contents API: /api/file?path=relative/path.js | |
| 166 | if (url === '/api/file' && query) { | |
| 167 | const params = new URLSearchParams(query) | |
| 168 | const filePath = params.get('path') | |
| 169 | if (!filePath) { | |
| 170 | sendJSON(req, res, 400, { error: 'path parameter required' }) | |
| 171 | return | |
| 172 | } | |
| 173 | ||
| 174 | // Security: prevent directory traversal | |
| 175 | const absPath = resolve(rootDir, filePath) | |
| 176 | if (!absPath.startsWith(rootDir)) { | |
| 177 | sendJSON(req, res, 403, { error: 'Access denied' }) | |
| 178 | return | |
| 179 | } | |
| 180 | ||
| 181 | // Security: honor the ignore matcher — hidden files are not readable. | |
| 182 | if (ignore(absPath)) { | |
| 183 | sendJSON(req, res, 404, { error: 'File not found: ' + filePath }) | |
| 184 | return | |
| 185 | } | |
| 186 | ||
| 187 | try { | |
| 188 | const content = readFileSync(absPath, 'utf-8') | |
| 189 | sendJSON(req, res, 200, { path: filePath, content, lines: content.split('\n').length }) | |
| 190 | } catch (err) { | |
| 191 | sendJSON(req, res, 404, { error: 'File not found: ' + filePath }) | |
| 192 | } | |
| 193 | return | |
| 194 | } | |
| 195 | ||
| 196 | res.writeHead(404, { 'content-type': 'text/plain' }) | |
| 197 | res.end('Not found') | |
| 198 | }) | |
| 199 | ||
| 200 | server.listen(port, () => { | |
| 201 | console.log(`codetree visualization: http://localhost:${port}`) | |
| 202 | console.log(`API: http://localhost:${port}/api/tree`) | |
| 203 | console.log(`${tree.system.modules.length} modules loaded`) | |
| 204 | }) | |
| 205 | ||
| 206 | return server | |
| 207 | } |
| … | … | @@ -0,0 +1,24 @@ |
| 1 | import { scanStream } from './scan-stream.js' | |
| 2 | import { TreeReducer } from './reducers/tree-reducer.js' | |
| 3 | ||
| 4 | /** | |
| 5 | * walkGraph — build a graph of modules and files for a project root. | |
| 6 | * | |
| 7 | * This is now a thin wrapper around scan-stream + TreeReducer. The returned | |
| 8 | * shape is identical to the pre-refactor API so existing consumers (buildTree, | |
| 9 | * tests) keep working unchanged. | |
| 10 | * | |
| 11 | * Callers who want push-based incremental updates should use scanStream() | |
| 12 | * directly and attach their own reducer/listener. | |
| 13 | * | |
| 14 | * Returns: { modules, files, root, dirTree, projectType, languages, resolutionContext } | |
| 15 | */ | |
| 16 | export async function walkGraph (rootDir, opts = {}) { | |
| 17 | return new Promise((resolve, reject) => { | |
| 18 | const source = scanStream(rootDir, opts) | |
| 19 | const tree = new TreeReducer().attach(source) | |
| 20 | ||
| 21 | source.once('scan-end', () => resolve(tree.finalize())) | |
| 22 | source.once('error', reject) | |
| 23 | }) | |
| 24 | } |
| … | … | @@ -0,0 +1,326 @@ |
| 1 | import { basename, dirname } from 'path' | |
| 2 | ||
| 3 | /** | |
| 4 | * Build the complete JSON tree from a walk graph. | |
| 5 | * Combines traverse output (module/file structure) with parser output (AST analysis). | |
| 6 | */ | |
| 7 | export function buildTree (graph) { | |
| 8 | const tree = { | |
| 9 | generated: new Date().toISOString(), | |
| 10 | root: graph.root, | |
| 11 | projectType: graph.projectType || 'unknown', | |
| 12 | languages: graph.languages || [], | |
| 13 | system: { | |
| 14 | modules: [], | |
| 15 | dependencies: {} | |
| 16 | }, | |
| 17 | modules: {}, | |
| 18 | dirTree: graph.dirTree || null | |
| 19 | } | |
| 20 | ||
| 21 | for (const [name, mod] of graph.modules) { | |
| 22 | tree.system.modules.push(name) | |
| 23 | ||
| 24 | // Build dependency list (only local/known deps) | |
| 25 | const deps = [] | |
| 26 | for (const dep of Object.keys(mod.dependencies)) { | |
| 27 | deps.push(dep) | |
| 28 | } | |
| 29 | if (deps.length > 0) { | |
| 30 | tree.system.dependencies[name] = deps | |
| 31 | } | |
| 32 | ||
| 33 | // Build module entry | |
| 34 | const moduleEntry = { | |
| 35 | path: mod.path, | |
| 36 | name: mod.name, | |
| 37 | version: mod.version, | |
| 38 | type: mod.type, | |
| 39 | entry: mod.entry ? basename(mod.entry) : null, | |
| 40 | dependencies: mod.dependencies, | |
| 41 | importMaps: Object.keys(mod.importMaps).length > 0 ? mod.importMaps : undefined, | |
| 42 | testCommand: mod.testCommand, | |
| 43 | publicAPI: [], | |
| 44 | files: {} | |
| 45 | } | |
| 46 | ||
| 47 | // Build file entries from the parsed results already attached by scan-stream | |
| 48 | // via the file-parsed event. This used to re-parse every file here, which | |
| 49 | // was a ~2x CPU waste and caused OOM on large recursive scans. | |
| 50 | for (const [relInPkg, fileInfo] of mod.files) { | |
| 51 | const parsed = fileInfo.parsed | |
| 52 | if (!parsed || parsed.error) continue | |
| 53 | ||
| 54 | const fileEntry = { | |
| 55 | role: classifyRole(relInPkg), | |
| 56 | imports: parsed.imports, | |
| 57 | exports: parsed.exports, | |
| 58 | localImports: fileInfo.localImports || [] | |
| 59 | } | |
| 60 | ||
| 61 | // Add structural data only if present (some fields are language-specific — may be undefined) | |
| 62 | if (parsed.classes && parsed.classes.length > 0) fileEntry.classes = parsed.classes | |
| 63 | if (parsed.functions && parsed.functions.length > 0) fileEntry.functions = parsed.functions | |
| 64 | if (parsed.constants && parsed.constants.length > 0) fileEntry.constants = parsed.constants | |
| 65 | if (parsed.state && parsed.state.length > 0) fileEntry.state = parsed.state | |
| 66 | if (parsed.errorContracts && parsed.errorContracts.length > 0) fileEntry.errorContracts = parsed.errorContracts | |
| 67 | if (parsed.delegates && parsed.delegates.length > 0) fileEntry.delegates = parsed.delegates | |
| 68 | // Language-specific additional fields | |
| 69 | if (parsed.signals && parsed.signals.length > 0) fileEntry.signals = parsed.signals | |
| 70 | if (parsed.enums && parsed.enums.length > 0) fileEntry.enums = parsed.enums | |
| 71 | if (parsed.namespaces && parsed.namespaces.length > 0) fileEntry.namespaces = parsed.namespaces | |
| 72 | if (parsed.uniforms && parsed.uniforms.length > 0) fileEntry.uniforms = parsed.uniforms | |
| 73 | if (parsed.buffers && parsed.buffers.length > 0) fileEntry.buffers = parsed.buffers | |
| 74 | ||
| 75 | moduleEntry.files[relInPkg] = fileEntry | |
| 76 | } | |
| 77 | ||
| 78 | // Compute import graph (aggregates per-file localImports into directory-level architecture) | |
| 79 | moduleEntry.importGraph = computeImportGraph(moduleEntry) | |
| 80 | ||
| 81 | // Discover sub-modules from import graph (directory clusters that act as internal modules) | |
| 82 | moduleEntry.subModules = discoverSubModules(moduleEntry) | |
| 83 | ||
| 84 | // Compute public API from entry file | |
| 85 | const entryKey = mod.entry ? findEntryKey(mod, moduleEntry.files) : null | |
| 86 | if (entryKey && moduleEntry.files[entryKey]) { | |
| 87 | moduleEntry.publicAPI = computePublicAPI(moduleEntry.files[entryKey]) | |
| 88 | } | |
| 89 | ||
| 90 | tree.modules[name] = moduleEntry | |
| 91 | } | |
| 92 | ||
| 93 | // Sort module list | |
| 94 | tree.system.modules.sort() | |
| 95 | ||
| 96 | // Compute shared dependencies | |
| 97 | tree.system.sharedDeps = computeSharedDeps(tree) | |
| 98 | ||
| 99 | return tree | |
| 100 | } | |
| 101 | ||
| 102 | // --- File role classification --- | |
| 103 | ||
| 104 | function classifyRole (relPath) { | |
| 105 | // JS conventions | |
| 106 | if (relPath === 'index.js' || relPath === 'index.mjs') return 'entry' | |
| 107 | if (relPath.startsWith('test/') || relPath.endsWith('.test.js')) return 'test' | |
| 108 | if (relPath.includes('schema')) return 'schema' | |
| 109 | if (relPath.startsWith('bin/')) return 'bin' | |
| 110 | ||
| 111 | // Godot conventions | |
| 112 | if (relPath.startsWith('autoloads/')) return 'autoload' | |
| 113 | if (relPath.startsWith('scenes/')) return 'scene' | |
| 114 | if (relPath.startsWith('addons/')) return 'addon' | |
| 115 | ||
| 116 | // C++ conventions | |
| 117 | if (relPath.startsWith('include/') || relPath.endsWith('.h') || relPath.endsWith('.hpp')) return 'header' | |
| 118 | if (relPath.startsWith('src/')) return 'source' | |
| 119 | if (relPath.startsWith('thirdparty/') || relPath.startsWith('vendor/')) return 'thirdparty' | |
| 120 | ||
| 121 | // Shader conventions | |
| 122 | if (relPath.startsWith('shaders/') || relPath.endsWith('.glsl') || relPath.endsWith('.gdshader')) return 'shader' | |
| 123 | ||
| 124 | // Shared | |
| 125 | if (relPath.startsWith('lib/')) return 'lib' | |
| 126 | if (relPath.startsWith('scripts/')) return 'script' | |
| 127 | if (relPath.startsWith('examples/') || relPath.startsWith('example/')) return 'example' | |
| 128 | ||
| 129 | return 'lib' | |
| 130 | } | |
| 131 | ||
| 132 | // --- Entry point matching --- | |
| 133 | ||
| 134 | function findEntryKey (mod, files) { | |
| 135 | const entryBase = mod.entry ? basename(mod.entry) : 'index.js' | |
| 136 | ||
| 137 | // Try exact match | |
| 138 | if (files[entryBase]) return entryBase | |
| 139 | ||
| 140 | // Try index.js | |
| 141 | if (files['index.js']) return 'index.js' | |
| 142 | ||
| 143 | return null | |
| 144 | } | |
| 145 | ||
| 146 | // --- Public API computation --- | |
| 147 | ||
| 148 | function computePublicAPI (entryFile) { | |
| 149 | const api = [] | |
| 150 | for (const exp of entryFile.exports) { | |
| 151 | if (exp.name === '*') continue // Skip star re-exports for now | |
| 152 | api.push(exp.name) | |
| 153 | } | |
| 154 | return api | |
| 155 | } | |
| 156 | ||
| 157 | // --- Import graph aggregation --- | |
| 158 | ||
| 159 | function computeImportGraph (moduleEntry) { | |
| 160 | const modPath = moduleEntry.path | |
| 161 | const edges = [] | |
| 162 | const dirEdgeCounts = {} // 'srcDir\0tgtDir' -> count | |
| 163 | const dirFiles = {} // dir -> Set of file paths | |
| 164 | ||
| 165 | // Build lookup: root-relative resolved path -> package-relative file key | |
| 166 | const resolvedToKey = new Map() | |
| 167 | for (const filePath of Object.keys(moduleEntry.files)) { | |
| 168 | // root-relative = modPath/filePath (or just filePath if modPath is '.') | |
| 169 | const rootRel = modPath === '.' ? filePath : modPath + '/' + filePath | |
| 170 | resolvedToKey.set(rootRel, filePath) | |
| 171 | } | |
| 172 | ||
| 173 | for (const [filePath, file] of Object.entries(moduleEntry.files)) { | |
| 174 | if (!file.localImports || file.localImports.length === 0) continue | |
| 175 | ||
| 176 | const srcDir = fileDir(filePath) | |
| 177 | if (!dirFiles[srcDir]) dirFiles[srcDir] = new Set() | |
| 178 | dirFiles[srcDir].add(filePath) | |
| 179 | ||
| 180 | for (const imp of file.localImports) { | |
| 181 | // Convert root-relative resolved path to package-relative key | |
| 182 | const targetKey = resolvedToKey.get(imp.resolved) | |
| 183 | if (!targetKey) continue | |
| 184 | ||
| 185 | // Find imported symbol names by matching specifier against parsed imports | |
| 186 | const names = [] | |
| 187 | if (file.imports) { | |
| 188 | const match = file.imports.find(i => i.specifier === imp.specifier) | |
| 189 | if (match) names.push(...match.names) | |
| 190 | } | |
| 191 | ||
| 192 | edges.push({ from: filePath, to: targetKey, names }) | |
| 193 | ||
| 194 | const tgtDir = fileDir(targetKey) | |
| 195 | if (!dirFiles[tgtDir]) dirFiles[tgtDir] = new Set() | |
| 196 | dirFiles[tgtDir].add(targetKey) | |
| 197 | ||
| 198 | // Aggregate directory-level edge | |
| 199 | const pairKey = srcDir + '\0' + tgtDir | |
| 200 | dirEdgeCounts[pairKey] = (dirEdgeCounts[pairKey] || 0) + 1 | |
| 201 | } | |
| 202 | } | |
| 203 | ||
| 204 | // Build directoryMatrix from aggregated pair counts | |
| 205 | const directoryMatrix = {} | |
| 206 | for (const [pairKey, count] of Object.entries(dirEdgeCounts)) { | |
| 207 | const [srcDir, tgtDir] = pairKey.split('\0') | |
| 208 | if (!directoryMatrix[srcDir]) directoryMatrix[srcDir] = {} | |
| 209 | directoryMatrix[srcDir][tgtDir] = count | |
| 210 | } | |
| 211 | ||
| 212 | // Build per-directory stats | |
| 213 | const directories = {} | |
| 214 | const allDirs = new Set(Object.keys(dirFiles)) | |
| 215 | ||
| 216 | for (const dir of allDirs) { | |
| 217 | let internalEdges = 0 | |
| 218 | let incomingEdges = 0 | |
| 219 | let outgoingEdges = 0 | |
| 220 | ||
| 221 | // Count edges from this dir (outgoing + internal) | |
| 222 | for (const [pairKey, count] of Object.entries(dirEdgeCounts)) { | |
| 223 | const [src, tgt] = pairKey.split('\0') | |
| 224 | if (src === dir && tgt === dir) internalEdges += count | |
| 225 | else if (src === dir && tgt !== dir) outgoingEdges += count | |
| 226 | else if (tgt === dir && src !== dir) incomingEdges += count | |
| 227 | } | |
| 228 | ||
| 229 | directories[dir] = { | |
| 230 | files: dirFiles[dir] ? dirFiles[dir].size : 0, | |
| 231 | internalEdges, | |
| 232 | incomingEdges, | |
| 233 | outgoingEdges | |
| 234 | } | |
| 235 | } | |
| 236 | ||
| 237 | return { edges, directoryMatrix, directories } | |
| 238 | } | |
| 239 | ||
| 240 | function fileDir (filePath) { | |
| 241 | const dir = dirname(filePath) | |
| 242 | return dir === '.' ? '.' : dir | |
| 243 | } | |
| 244 | ||
| 245 | // --- Sub-module discovery --- | |
| 246 | ||
| 247 | function discoverSubModules (moduleEntry) { | |
| 248 | const graph = moduleEntry.importGraph | |
| 249 | if (!graph) return {} | |
| 250 | ||
| 251 | const subModules = {} | |
| 252 | ||
| 253 | for (const [dir, stats] of Object.entries(graph.directories)) { | |
| 254 | if (dir === '.') continue // root dir is the module itself, not a sub-module | |
| 255 | if (stats.files < 2) continue // single-file dirs aren't sub-modules | |
| 256 | ||
| 257 | // Check for an index file with re-exports (strong signal). | |
| 258 | // Try common index filenames — language-agnostic lookup. | |
| 259 | const INDEX_CANDIDATES = ['index.js', 'index.mjs', 'index.cjs', 'mod.rs', '__init__.py'] | |
| 260 | let indexKey = null | |
| 261 | let indexFile = null | |
| 262 | for (const candidate of INDEX_CANDIDATES) { | |
| 263 | const key = dir + '/' + candidate | |
| 264 | if (moduleEntry.files[key]) { | |
| 265 | indexKey = key | |
| 266 | indexFile = moduleEntry.files[key] | |
| 267 | break | |
| 268 | } | |
| 269 | } | |
| 270 | const hasIndex = indexFile && indexFile.exports && indexFile.exports.length > 0 | |
| 271 | const hasReExports = hasIndex && indexFile.exports.some(e => e.from) | |
| 272 | ||
| 273 | // Collect files belonging to this directory | |
| 274 | const files = [] | |
| 275 | for (const filePath of Object.keys(moduleEntry.files)) { | |
| 276 | if (fileDir(filePath) === dir) files.push(filePath) | |
| 277 | } | |
| 278 | ||
| 279 | // Compute public exports (from index.js if it exists, otherwise union of all exports) | |
| 280 | const publicExports = [] | |
| 281 | if (hasIndex) { | |
| 282 | for (const exp of indexFile.exports) { | |
| 283 | if (exp.name !== '*') publicExports.push(exp.name) | |
| 284 | } | |
| 285 | } | |
| 286 | ||
| 287 | // Cohesion: ratio of internal edges to total edges involving this directory | |
| 288 | const totalEdges = stats.internalEdges + stats.incomingEdges + stats.outgoingEdges | |
| 289 | const cohesion = totalEdges > 0 ? stats.internalEdges / totalEdges : 0 | |
| 290 | ||
| 291 | subModules[dir] = { | |
| 292 | indexFile: hasIndex ? indexKey : null, | |
| 293 | hasReExports, | |
| 294 | files, | |
| 295 | publicExports, | |
| 296 | fanIn: stats.incomingEdges, | |
| 297 | fanOut: stats.outgoingEdges, | |
| 298 | cohesion: Math.round(cohesion * 100) / 100 | |
| 299 | } | |
| 300 | } | |
| 301 | ||
| 302 | return subModules | |
| 303 | } | |
| 304 | ||
| 305 | // --- Shared dependency analysis --- | |
| 306 | ||
| 307 | function computeSharedDeps (tree) { | |
| 308 | const depUsers = {} // dep -> [modules that use it] | |
| 309 | ||
| 310 | for (const [name, mod] of Object.entries(tree.modules)) { | |
| 311 | for (const dep of Object.keys(mod.dependencies || {})) { | |
| 312 | if (!depUsers[dep]) depUsers[dep] = [] | |
| 313 | depUsers[dep].push(name) | |
| 314 | } | |
| 315 | } | |
| 316 | ||
| 317 | // Only include deps used by 2+ modules | |
| 318 | const shared = {} | |
| 319 | for (const [dep, users] of Object.entries(depUsers)) { | |
| 320 | if (users.length >= 2) { | |
| 321 | shared[dep] = users.sort() | |
| 322 | } | |
| 323 | } | |
| 324 | ||
| 325 | return shared | |
| 326 | } |
| … | … | @@ -0,0 +1,493 @@ |
| 1 | import { readFileSync, statSync } from 'fs' | |
| 2 | import { join, resolve } from 'path' | |
| 3 | ||
| 4 | /** | |
| 5 | * Validate spec claims against the code tree. | |
| 6 | * Returns a validation report with pass/fail/warn per claim. | |
| 7 | */ | |
| 8 | ||
| 9 | export function validate (tree, specs) { | |
| 10 | const report = { | |
| 11 | system: null, | |
| 12 | modules: {}, | |
| 13 | docFreshness: null, | |
| 14 | summary: { pass: 0, fail: 0, warn: 0, total: 0 } | |
| 15 | } | |
| 16 | ||
| 17 | // Validate system spec (pass module specs for cross-level checks) | |
| 18 | if (specs.system) { | |
| 19 | report.system = validateSystem(tree, specs.system, specs) | |
| 20 | tally(report.summary, report.system.checks) | |
| 21 | } | |
| 22 | ||
| 23 | // Validate each module spec | |
| 24 | for (const [name, spec] of Object.entries(specs.modules)) { | |
| 25 | const mod = findModule(tree, spec) | |
| 26 | report.modules[name] = validateModule(tree, mod, spec) | |
| 27 | tally(report.summary, report.modules[name].checks) | |
| 28 | } | |
| 29 | ||
| 30 | // Validate documentation freshness (from doc cruft detection) | |
| 31 | if (tree.docCruft) { | |
| 32 | report.docFreshness = validateDocFreshness(tree.docCruft) | |
| 33 | tally(report.summary, report.docFreshness.checks) | |
| 34 | } | |
| 35 | ||
| 36 | return report | |
| 37 | } | |
| 38 | ||
| 39 | // --- System-level validation --- | |
| 40 | ||
| 41 | function validateSystem (tree, systemSpec, specs) { | |
| 42 | const result = { checks: [] } | |
| 43 | ||
| 44 | // Check: each documented module exists in the code tree | |
| 45 | for (const docMod of systemSpec.modules) { | |
| 46 | const found = tree.modules[docMod.name] | |
| 47 | const locationMatch = found && found.path && docMod.location.includes(found.path) | |
| 48 | ||
| 49 | result.checks.push({ | |
| 50 | level: 'system', | |
| 51 | canonicity: 'code-canonical', | |
| 52 | claim: 'Module "' + docMod.name + '" exists at ' + docMod.location, | |
| 53 | status: found ? (locationMatch ? 'pass' : 'warn') : 'fail', | |
| 54 | expected: docMod.location, | |
| 55 | actual: found ? found.path : null, | |
| 56 | detail: !found ? 'Module not found in scan' : | |
| 57 | (!locationMatch ? 'Location mismatch: spec says ' + docMod.location + ', found at ' + found.path : null) | |
| 58 | }) | |
| 59 | } | |
| 60 | ||
| 61 | // Check: modules in code that aren't documented | |
| 62 | const documentedNames = new Set(systemSpec.modules.map(m => m.name)) | |
| 63 | for (const name of tree.system.modules) { | |
| 64 | if (!documentedNames.has(name)) { | |
| 65 | result.checks.push({ | |
| 66 | level: 'system', | |
| 67 | claim: 'Module "' + name + '" is documented in SYSTEM.md', | |
| 68 | status: 'warn', | |
| 69 | detail: 'Module exists in code but not documented in system spec' | |
| 70 | }) | |
| 71 | } | |
| 72 | } | |
| 73 | ||
| 74 | // --- Cross-level: orchestrator integration --- | |
| 75 | // Find the orchestrator (pear-git-v3 or the "Applications" module) | |
| 76 | // Find the orchestrator — the module whose purpose STARTS with "Orchestrator" or "Mounts all" | |
| 77 | const orchestrators = systemSpec.modules.filter(m => | |
| 78 | m.purpose && (m.purpose.startsWith('Orchestrator') || m.purpose.startsWith('Mounts all')) | |
| 79 | ) | |
| 80 | ||
| 81 | for (const orch of orchestrators) { | |
| 82 | const orchMod = tree.modules[orch.name] | |
| 83 | if (!orchMod) continue | |
| 84 | ||
| 85 | const orchDeps = new Set(Object.keys(orchMod.dependencies)) | |
| 86 | ||
| 87 | // Every module in the system spec should be either: | |
| 88 | // 1. A dependency of the orchestrator | |
| 89 | // 2. A dependency of a dependency (transitive) | |
| 90 | // 3. Explicitly marked as "not yet integrated" or "external" | |
| 91 | for (const docMod of systemSpec.modules) { | |
| 92 | if (docMod.name === orch.name) continue | |
| 93 | if (docMod.location === 'external' || docMod.location.includes('npm dep')) continue | |
| 94 | ||
| 95 | const isDirectDep = orchDeps.has(docMod.name) | |
| 96 | ||
| 97 | // Check transitive: is it a dep of any of the orchestrator's deps? (2 levels deep) | |
| 98 | let isTransitive = false | |
| 99 | let transitiveVia = null | |
| 100 | if (!isDirectDep) { | |
| 101 | for (const depName of orchDeps) { | |
| 102 | const depMod = tree.modules[depName] | |
| 103 | if (!depMod) continue | |
| 104 | if (depMod.dependencies[docMod.name]) { | |
| 105 | isTransitive = true | |
| 106 | transitiveVia = depName | |
| 107 | break | |
| 108 | } | |
| 109 | // 2nd level | |
| 110 | for (const dep2Name of Object.keys(depMod.dependencies)) { | |
| 111 | const dep2Mod = tree.modules[dep2Name] | |
| 112 | if (dep2Mod && dep2Mod.dependencies[docMod.name]) { | |
| 113 | isTransitive = true | |
| 114 | transitiveVia = depName + ' -> ' + dep2Name | |
| 115 | break | |
| 116 | } | |
| 117 | } | |
| 118 | if (isTransitive) break | |
| 119 | } | |
| 120 | } | |
| 121 | ||
| 122 | if (!isDirectDep && !isTransitive) { | |
| 123 | result.checks.push({ | |
| 124 | level: 'system', | |
| 125 | claim: orch.name + ' integrates "' + docMod.name + '"', | |
| 126 | status: 'fail', | |
| 127 | detail: 'SYSTEM.md lists "' + docMod.name + '" as part of the system but ' + orch.name + ' does not depend on it (direct or transitive). Purpose: ' + (docMod.purpose || '').slice(0, 100) | |
| 128 | }) | |
| 129 | } else { | |
| 130 | result.checks.push({ | |
| 131 | level: 'system', | |
| 132 | claim: orch.name + ' integrates "' + docMod.name + '"', | |
| 133 | status: 'pass', | |
| 134 | detail: isDirectDep ? 'Direct dependency' : 'Transitive via ' + transitiveVia | |
| 135 | }) | |
| 136 | } | |
| 137 | } | |
| 138 | } | |
| 139 | ||
| 140 | // --- Cross-level: dependency bidirectional consistency --- | |
| 141 | // If module A's spec says "depends on B", and B's spec says "depended on by A", | |
| 142 | // check that both match the actual code | |
| 143 | for (const docMod of systemSpec.modules) { | |
| 144 | const mod = tree.modules[docMod.name] | |
| 145 | if (!mod) continue | |
| 146 | ||
| 147 | // Check if module has any local deps that aren't in the system spec | |
| 148 | for (const dep of Object.keys(mod.dependencies)) { | |
| 149 | const depInSystem = systemSpec.modules.find(m => m.name === dep) | |
| 150 | const depInCode = tree.modules[dep] | |
| 151 | if (depInCode && !depInSystem) { | |
| 152 | result.checks.push({ | |
| 153 | level: 'system', | |
| 154 | claim: '"' + docMod.name + '" dependency "' + dep + '" is in system spec', | |
| 155 | status: 'warn', | |
| 156 | detail: docMod.name + ' depends on ' + dep + ' (found in code) but ' + dep + ' is not documented in SYSTEM.md' | |
| 157 | }) | |
| 158 | } | |
| 159 | } | |
| 160 | } | |
| 161 | ||
| 162 | // --- Cross-level: module spec dependency consistency --- | |
| 163 | // Check that each module spec's "Dependencies" and "What depends on this" | |
| 164 | // sections match actual code | |
| 165 | if (specs && specs.modules) { | |
| 166 | for (const [name, modSpec] of Object.entries(specs.modules)) { | |
| 167 | const mod = findModuleBySpec(tree, modSpec) | |
| 168 | if (!mod) continue | |
| 169 | ||
| 170 | // Spec says "X depends on this" — verify X actually depends on this module | |
| 171 | for (const dependent of modSpec.dependents) { | |
| 172 | const depMod = tree.modules[dependent] | |
| 173 | if (!depMod) { | |
| 174 | result.checks.push({ | |
| 175 | level: 'system', | |
| 176 | claim: '"' + dependent + '" depends on "' + name + '" (per ' + name + ' spec)', | |
| 177 | status: 'warn', | |
| 178 | detail: 'Module spec for ' + name + ' claims ' + dependent + ' depends on it, but ' + dependent + ' not found in scan' | |
| 179 | }) | |
| 180 | continue | |
| 181 | } | |
| 182 | const actuallyDepends = depMod.dependencies[name] !== undefined | |
| 183 | result.checks.push({ | |
| 184 | level: 'system', | |
| 185 | claim: '"' + dependent + '" depends on "' + name + '"', | |
| 186 | status: actuallyDepends ? 'pass' : 'fail', | |
| 187 | detail: actuallyDepends ? null : name + ' spec says ' + dependent + ' depends on it, but ' + dependent + '/package.json does not list ' + name + ' as a dependency' | |
| 188 | }) | |
| 189 | } | |
| 190 | } | |
| 191 | } | |
| 192 | ||
| 193 | return result | |
| 194 | } | |
| 195 | ||
| 196 | function findModuleBySpec (tree, spec) { | |
| 197 | if (tree.modules[spec.name]) return tree.modules[spec.name] | |
| 198 | if (spec.location) { | |
| 199 | for (const mod of Object.values(tree.modules)) { | |
| 200 | if (spec.location.includes(mod.path)) return mod | |
| 201 | } | |
| 202 | } | |
| 203 | return null | |
| 204 | } | |
| 205 | ||
| 206 | // --- Module-level validation --- | |
| 207 | ||
| 208 | function validateModule (tree, mod, spec) { | |
| 209 | const result = { | |
| 210 | specFile: spec.filename, | |
| 211 | checks: [] | |
| 212 | } | |
| 213 | ||
| 214 | if (!mod) { | |
| 215 | result.checks.push({ | |
| 216 | level: 'module', | |
| 217 | canonicity: 'code-canonical', | |
| 218 | claim: 'Module "' + spec.name + '" exists', | |
| 219 | status: 'fail', | |
| 220 | detail: 'Spec references module at ' + spec.location + ' but it was not found in the scan' | |
| 221 | }) | |
| 222 | return result | |
| 223 | } | |
| 224 | ||
| 225 | // --- LOC checks --- | |
| 226 | for (const [filename, claimedLOC] of Object.entries(spec.fileLOC)) { | |
| 227 | // Find the file in the module | |
| 228 | const filePath = findFileInModule(mod, filename) | |
| 229 | if (!filePath) { | |
| 230 | result.checks.push({ | |
| 231 | level: 'file', | |
| 232 | canonicity: 'code-canonical', | |
| 233 | claim: 'File "' + filename + '" exists', | |
| 234 | status: 'fail', | |
| 235 | detail: 'Spec claims ' + filename + ' has ' + claimedLOC + ' LOC but file not found' | |
| 236 | }) | |
| 237 | continue | |
| 238 | } | |
| 239 | ||
| 240 | const file = mod.files[filePath] | |
| 241 | if (!file) continue | |
| 242 | ||
| 243 | // Count actual LOC by finding the source | |
| 244 | const absPath = resolve(tree.root, mod.path, filePath) | |
| 245 | let actualLOC = null | |
| 246 | try { | |
| 247 | const source = readFileSync(absPath, 'utf-8') | |
| 248 | actualLOC = source.split('\n').length | |
| 249 | } catch {} | |
| 250 | ||
| 251 | if (actualLOC !== null) { | |
| 252 | const drift = Math.abs(actualLOC - claimedLOC) | |
| 253 | const driftPct = (drift / claimedLOC * 100).toFixed(0) | |
| 254 | result.checks.push({ | |
| 255 | level: 'file', | |
| 256 | canonicity: 'code-canonical', | |
| 257 | claim: filename + ' has ' + claimedLOC + ' LOC', | |
| 258 | status: drift === 0 ? 'pass' : drift < 20 ? 'warn' : 'fail', | |
| 259 | expected: claimedLOC, | |
| 260 | actual: actualLOC, | |
| 261 | detail: drift > 0 ? 'LOC drifted by ' + drift + ' lines (' + driftPct + '%). Spec says ' + claimedLOC + ', actual is ' + actualLOC : null | |
| 262 | }) | |
| 263 | } | |
| 264 | } | |
| 265 | ||
| 266 | // --- Source verified staleness --- | |
| 267 | if (spec.sourceVerified) { | |
| 268 | const verifiedDate = new Date(spec.sourceVerified) | |
| 269 | let newestMtime = 0 | |
| 270 | for (const filePath of Object.keys(mod.files)) { | |
| 271 | try { | |
| 272 | const absPath = resolve(tree.root, mod.path, filePath) | |
| 273 | const stat = statSync(absPath) | |
| 274 | if (stat.mtimeMs > newestMtime) newestMtime = stat.mtimeMs | |
| 275 | } catch {} | |
| 276 | } | |
| 277 | if (newestMtime > 0) { | |
| 278 | const codeDate = new Date(newestMtime) | |
| 279 | const stale = codeDate > verifiedDate | |
| 280 | result.checks.push({ | |
| 281 | level: 'module', | |
| 282 | claim: 'Source verified on ' + spec.sourceVerified, | |
| 283 | status: stale ? 'warn' : 'pass', | |
| 284 | expected: spec.sourceVerified, | |
| 285 | actual: codeDate.toISOString().split('T')[0], | |
| 286 | detail: stale ? 'Code modified on ' + codeDate.toISOString().split('T')[0] + ', after spec verified on ' + spec.sourceVerified : null | |
| 287 | }) | |
| 288 | } | |
| 289 | } | |
| 290 | ||
| 291 | // --- Dependency checks --- | |
| 292 | for (const dep of spec.dependencies) { | |
| 293 | const hasDep = mod.dependencies[dep] !== undefined | |
| 294 | result.checks.push({ | |
| 295 | level: 'module', | |
| 296 | canonicity: 'code-canonical', | |
| 297 | claim: 'Depends on ' + dep, | |
| 298 | status: hasDep ? 'pass' : 'fail', | |
| 299 | detail: !hasDep ? 'Spec claims dependency on ' + dep + ' but not found in package.json' : null | |
| 300 | }) | |
| 301 | } | |
| 302 | ||
| 303 | // Check reverse: deps in package.json not documented | |
| 304 | for (const dep of Object.keys(mod.dependencies)) { | |
| 305 | // Only check local/known deps | |
| 306 | if (!tree.modules[dep]) continue | |
| 307 | if (!spec.dependencies.includes(dep)) { | |
| 308 | result.checks.push({ | |
| 309 | level: 'module', | |
| 310 | claim: 'Dependency "' + dep + '" is documented', | |
| 311 | status: 'warn', | |
| 312 | detail: 'package.json depends on ' + dep + ' but spec does not mention it' | |
| 313 | }) | |
| 314 | } | |
| 315 | } | |
| 316 | ||
| 317 | // --- Export checks --- | |
| 318 | for (const claimedExport of spec.claimedExports) { | |
| 319 | const found = mod.publicAPI.includes(claimedExport) | |
| 320 | result.checks.push({ | |
| 321 | level: 'module', | |
| 322 | canonicity: 'code-canonical', | |
| 323 | claim: 'Exports "' + claimedExport + '"', | |
| 324 | status: found ? 'pass' : 'fail', | |
| 325 | detail: !found ? 'Spec claims export "' + claimedExport + '" but not found in public API: [' + mod.publicAPI.join(', ') + ']' : null | |
| 326 | }) | |
| 327 | } | |
| 328 | ||
| 329 | // Undocumented exports | |
| 330 | for (const exp of mod.publicAPI) { | |
| 331 | if (!spec.claimedExports.includes(exp)) { | |
| 332 | result.checks.push({ | |
| 333 | level: 'module', | |
| 334 | claim: 'Export "' + exp + '" is documented', | |
| 335 | status: 'warn', | |
| 336 | detail: 'Module exports "' + exp + '" but spec does not document it' | |
| 337 | }) | |
| 338 | } | |
| 339 | } | |
| 340 | ||
| 341 | // --- Method checks --- | |
| 342 | const allMethods = getAllMethods(mod) | |
| 343 | for (const method of spec.claimedMethods) { | |
| 344 | const found = allMethods.has(method) | |
| 345 | result.checks.push({ | |
| 346 | level: 'method', | |
| 347 | canonicity: 'code-canonical', | |
| 348 | claim: 'Method "' + method + '" exists', | |
| 349 | status: found ? 'pass' : 'fail', | |
| 350 | detail: !found ? 'Spec documents method "' + method + '" but not found in any class' : null | |
| 351 | }) | |
| 352 | } | |
| 353 | ||
| 354 | // Undocumented methods (only for primary class) | |
| 355 | const primaryClass = findPrimaryClass(mod, spec) | |
| 356 | if (primaryClass && spec.claimedMethods.length > 0) { | |
| 357 | for (const m of primaryClass.methods) { | |
| 358 | if (m.kind === 'field') continue | |
| 359 | if (m.name.startsWith('_')) continue // skip private | |
| 360 | if (!spec.claimedMethods.includes(m.name) && m.name !== 'ready' && m.name !== 'close' && m.name !== 'sync') { | |
| 361 | result.checks.push({ | |
| 362 | level: 'method', | |
| 363 | canonicity: 'code-canonical', | |
| 364 | claim: 'Method "' + m.name + '" is documented', | |
| 365 | status: 'warn', | |
| 366 | detail: 'Class has public method "' + m.name + '(' + m.params.join(', ') + ')" but spec does not document it' | |
| 367 | }) | |
| 368 | } | |
| 369 | } | |
| 370 | } | |
| 371 | ||
| 372 | // --- Getter checks --- | |
| 373 | for (const getter of spec.claimedGetters) { | |
| 374 | const found = allGetters(mod).has(getter) | |
| 375 | result.checks.push({ | |
| 376 | level: 'method', | |
| 377 | canonicity: 'code-canonical', | |
| 378 | claim: 'Getter "' + getter + '" exists', | |
| 379 | status: found ? 'pass' : 'fail', | |
| 380 | detail: !found ? 'Spec documents getter "' + getter + '" but not found' : null | |
| 381 | }) | |
| 382 | } | |
| 383 | ||
| 384 | return result | |
| 385 | } | |
| 386 | ||
| 387 | // --- Documentation freshness validation --- | |
| 388 | ||
| 389 | function validateDocFreshness (docCruft) { | |
| 390 | const result = { checks: [] } | |
| 391 | ||
| 392 | for (const doc of docCruft.docs) { | |
| 393 | // Skip docs with no code references (pure prose) | |
| 394 | if (doc.references.total === 0) continue | |
| 395 | ||
| 396 | const missingRatio = doc.references.missing / doc.references.total | |
| 397 | let status = 'pass' | |
| 398 | if (missingRatio > 0.3) status = 'fail' | |
| 399 | else if (missingRatio > 0.1) status = 'warn' | |
| 400 | ||
| 401 | result.checks.push({ | |
| 402 | level: 'doc', | |
| 403 | canonicity: 'narrative', | |
| 404 | claim: doc.path + ' references are current', | |
| 405 | status, | |
| 406 | detail: doc.references.missing + ' of ' + doc.references.total + ' code references missing. Last modified ' + doc.lastModified + ' (staleness ' + doc.staleness.score + ')', | |
| 407 | docPath: doc.path | |
| 408 | }) | |
| 409 | } | |
| 410 | ||
| 411 | return result | |
| 412 | } | |
| 413 | ||
| 414 | // --- Helpers --- | |
| 415 | ||
| 416 | function findModule (tree, spec) { | |
| 417 | // Try by name first | |
| 418 | if (tree.modules[spec.name]) return tree.modules[spec.name] | |
| 419 | ||
| 420 | // Try by location path | |
| 421 | if (spec.location) { | |
| 422 | for (const mod of Object.values(tree.modules)) { | |
| 423 | if (spec.location.includes(mod.path) || mod.path.includes(spec.location)) { | |
| 424 | return mod | |
| 425 | } | |
| 426 | } | |
| 427 | } | |
| 428 | ||
| 429 | return null | |
| 430 | } | |
| 431 | ||
| 432 | function findFileInModule (mod, filename) { | |
| 433 | // Exact match | |
| 434 | if (mod.files[filename]) return filename | |
| 435 | ||
| 436 | // Try with lib/ prefix | |
| 437 | if (mod.files['lib/' + filename]) return 'lib/' + filename | |
| 438 | ||
| 439 | // Search by basename | |
| 440 | for (const path of Object.keys(mod.files)) { | |
| 441 | if (path.endsWith('/' + filename) || path === filename) return path | |
| 442 | } | |
| 443 | ||
| 444 | return null | |
| 445 | } | |
| 446 | ||
| 447 | function getAllMethods (mod) { | |
| 448 | const methods = new Set() | |
| 449 | for (const file of Object.values(mod.files)) { | |
| 450 | if (file.classes) { | |
| 451 | for (const cls of file.classes) { | |
| 452 | for (const m of cls.methods) methods.add(m.name) | |
| 453 | } | |
| 454 | } | |
| 455 | if (file.functions) { | |
| 456 | for (const fn of file.functions) methods.add(fn.name) | |
| 457 | } | |
| 458 | } | |
| 459 | return methods | |
| 460 | } | |
| 461 | ||
| 462 | function allGetters (mod) { | |
| 463 | const getters = new Set() | |
| 464 | for (const file of Object.values(mod.files)) { | |
| 465 | if (file.classes) { | |
| 466 | for (const cls of file.classes) { | |
| 467 | if (cls.getters) for (const g of cls.getters) getters.add(g.name) | |
| 468 | } | |
| 469 | } | |
| 470 | } | |
| 471 | return getters | |
| 472 | } | |
| 473 | ||
| 474 | function findPrimaryClass (mod, spec) { | |
| 475 | // Find the main exported class | |
| 476 | for (const file of Object.values(mod.files)) { | |
| 477 | if (file.classes) { | |
| 478 | for (const cls of file.classes) { | |
| 479 | if (spec.claimedExports.includes(cls.name)) return cls | |
| 480 | } | |
| 481 | } | |
| 482 | } | |
| 483 | return null | |
| 484 | } | |
| 485 | ||
| 486 | function tally (summary, checks) { | |
| 487 | for (const c of checks) { | |
| 488 | summary.total++ | |
| 489 | if (c.status === 'pass') summary.pass++ | |
| 490 | else if (c.status === 'fail') summary.fail++ | |
| 491 | else if (c.status === 'warn') summary.warn++ | |
| 492 | } | |
| 493 | } |
| … | … | @@ -0,0 +1,1111 @@ |
| 1 | { | |
| 2 | "name": "codetree", | |
| 3 | "version": "0.1.0", | |
| 4 | "lockfileVersion": 3, | |
| 5 | "requires": true, | |
| 6 | "packages": { | |
| 7 | "": { | |
| 8 | "name": "codetree", | |
| 9 | "version": "0.1.0", | |
| 10 | "dependencies": { | |
| 11 | "paparam": "^1.8.6" | |
| 12 | }, | |
| 13 | "bin": { | |
| 14 | "codetree": "index.js" | |
| 15 | }, | |
| 16 | "devDependencies": { | |
| 17 | "brittle": "^3.0.0" | |
| 18 | }, | |
| 19 | "optionalDependencies": { | |
| 20 | "bare-events": "^2.5.0", | |
| 21 | "bare-fs": "^4.5.0", | |
| 22 | "bare-http1": "^4.0.0", | |
| 23 | "bare-path": "^3.0.0", | |
| 24 | "bare-process": "^3.0.0", | |
| 25 | "bare-url": "^2.3.2", | |
| 26 | "bare-zlib": "^1.3.0" | |
| 27 | } | |
| 28 | }, | |
| 29 | "node_modules/@jridgewell/resolve-uri": { | |
| 30 | "version": "3.1.2", | |
| 31 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", | |
| 32 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", | |
| 33 | "dev": true, | |
| 34 | "license": "MIT", | |
| 35 | "engines": { | |
| 36 | "node": ">=6.0.0" | |
| 37 | } | |
| 38 | }, | |
| 39 | "node_modules/@jridgewell/sourcemap-codec": { | |
| 40 | "version": "1.5.5", | |
| 41 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", | |
| 42 | "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", | |
| 43 | "dev": true, | |
| 44 | "license": "MIT" | |
| 45 | }, | |
| 46 | "node_modules/@jridgewell/trace-mapping": { | |
| 47 | "version": "0.3.31", | |
| 48 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", | |
| 49 | "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", | |
| 50 | "dev": true, | |
| 51 | "license": "MIT", | |
| 52 | "dependencies": { | |
| 53 | "@jridgewell/resolve-uri": "^3.1.0", | |
| 54 | "@jridgewell/sourcemap-codec": "^1.4.14" | |
| 55 | } | |
| 56 | }, | |
| 57 | "node_modules/@types/istanbul-lib-coverage": { | |
| 58 | "version": "2.0.6", | |
| 59 | "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", | |
| 60 | "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", | |
| 61 | "dev": true, | |
| 62 | "license": "MIT" | |
| 63 | }, | |
| 64 | "node_modules/b4a": { | |
| 65 | "version": "1.8.0", | |
| 66 | "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", | |
| 67 | "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==", | |
| 68 | "devOptional": true, | |
| 69 | "license": "Apache-2.0", | |
| 70 | "peerDependencies": { | |
| 71 | "react-native-b4a": "*" | |
| 72 | }, | |
| 73 | "peerDependenciesMeta": { | |
| 74 | "react-native-b4a": { | |
| 75 | "optional": true | |
| 76 | } | |
| 77 | } | |
| 78 | }, | |
| 79 | "node_modules/bare-abort": { | |
| 80 | "version": "2.0.13", | |
| 81 | "resolved": "https://registry.npmjs.org/bare-abort/-/bare-abort-2.0.13.tgz", | |
| 82 | "integrity": "sha512-zdc8l88eB11Jsz5rDd6sCAgv2kUFXgdrZWoMlgU6JMkfAi1/uuGFC3IEHswKbIRQTk5H3T5CMuechsXYxiaHlQ==", | |
| 83 | "dev": true, | |
| 84 | "license": "Apache-2.0" | |
| 85 | }, | |
| 86 | "node_modules/bare-addon-resolve": { | |
| 87 | "version": "1.10.0", | |
| 88 | "resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.10.0.tgz", | |
| 89 | "integrity": "sha512-sSd0jieRJlDaODOzj0oe0RjFVC1QI0ZIjGIdPkbrTXsdVVtENg14c+lHHAhHwmWCZ2nQlMhy8jA3Y5LYPc/isA==", | |
| 90 | "dev": true, | |
| 91 | "license": "Apache-2.0", | |
| 92 | "dependencies": { | |
| 93 | "bare-module-resolve": "^1.10.0", | |
| 94 | "bare-semver": "^1.0.0" | |
| 95 | }, | |
| 96 | "peerDependencies": { | |
| 97 | "bare-url": "*" | |
| 98 | }, | |
| 99 | "peerDependenciesMeta": { | |
| 100 | "bare-url": { | |
| 101 | "optional": true | |
| 102 | } | |
| 103 | } | |
| 104 | }, | |
| 105 | "node_modules/bare-ansi-escapes": { | |
| 106 | "version": "2.2.3", | |
| 107 | "resolved": "https://registry.npmjs.org/bare-ansi-escapes/-/bare-ansi-escapes-2.2.3.tgz", | |
| 108 | "integrity": "sha512-02ES4/E2RbrtZSnHJ9LntBhYkLA6lPpSEeP8iqS3MccBIVhVBlEmruF1I7HZqx5Q8aiTeYfQVeqmrU9YO2yYoQ==", | |
| 109 | "dev": true, | |
| 110 | "license": "Apache-2.0", | |
| 111 | "dependencies": { | |
| 112 | "bare-stream": "^2.6.5" | |
| 113 | }, | |
| 114 | "peerDependencies": { | |
| 115 | "bare-buffer": "*" | |
| 116 | }, | |
| 117 | "peerDependenciesMeta": { | |
| 118 | "bare-buffer": { | |
| 119 | "optional": true | |
| 120 | } | |
| 121 | } | |
| 122 | }, | |
| 123 | "node_modules/bare-assert": { | |
| 124 | "version": "1.2.0", | |
| 125 | "resolved": "https://registry.npmjs.org/bare-assert/-/bare-assert-1.2.0.tgz", | |
| 126 | "integrity": "sha512-c6uvgvTJBspTDxtVnPgrBKmLgcpW3Fp72NVKDLg6oT4QjQbhGtvrkHMhGYMK1sh4vjBHOBmuUalyt9hSzV37fQ==", | |
| 127 | "dev": true, | |
| 128 | "license": "Apache-2.0", | |
| 129 | "dependencies": { | |
| 130 | "bare-inspect": "^3.1.2" | |
| 131 | } | |
| 132 | }, | |
| 133 | "node_modules/bare-bundle": { | |
| 134 | "version": "1.10.0", | |
| 135 | "resolved": "https://registry.npmjs.org/bare-bundle/-/bare-bundle-1.10.0.tgz", | |
| 136 | "integrity": "sha512-4LVlnJAHr00Hh6Vu6ZUJS38rcEtJT3b3vChXSsBsJ2mk1TN0lQ+gzd+Dw5L0aV7uqDZv84smuwW+O02X7PfDlw==", | |
| 137 | "dev": true, | |
| 138 | "license": "Apache-2.0", | |
| 139 | "peerDependencies": { | |
| 140 | "bare-buffer": "*", | |
| 141 | "bare-url": "*" | |
| 142 | }, | |
| 143 | "peerDependenciesMeta": { | |
| 144 | "bare-buffer": { | |
| 145 | "optional": true | |
| 146 | }, | |
| 147 | "bare-url": { | |
| 148 | "optional": true | |
| 149 | } | |
| 150 | } | |
| 151 | }, | |
| 152 | "node_modules/bare-cov": { | |
| 153 | "version": "1.2.1", | |
| 154 | "resolved": "https://registry.npmjs.org/bare-cov/-/bare-cov-1.2.1.tgz", | |
| 155 | "integrity": "sha512-SHNqb/WG9udUEj8m5qGSehoUQ9o0Xzv8nrf4HIdmG+KNU/XdhPLhTP5VPrHnSAMAXhAzEB4Q+2IYZ0x9qPzN1g==", | |
| 156 | "dev": true, | |
| 157 | "license": "Apache-2.0", | |
| 158 | "dependencies": { | |
| 159 | "bare-fs": "^4.1.2", | |
| 160 | "bare-inspector": "^4.0.1", | |
| 161 | "bare-path": "^3.0.0", | |
| 162 | "bare-process": "^4.2.1", | |
| 163 | "bare-url": "^2.1.5", | |
| 164 | "bare-v8-to-istanbul": "^1.0.2", | |
| 165 | "picomatch": "^4.0.2", | |
| 166 | "which-runtime": "^1.2.1" | |
| 167 | } | |
| 168 | }, | |
| 169 | "node_modules/bare-cov/node_modules/bare-process": { | |
| 170 | "version": "4.4.1", | |
| 171 | "resolved": "https://registry.npmjs.org/bare-process/-/bare-process-4.4.1.tgz", | |
| 172 | "integrity": "sha512-JfcTtymq6akqM2bdyTsP4A4GYJceBzb91k/ECmFps75uFf6uO33SM1bOZsRAqyRXExabsQJLn5S41NBl8HTM4A==", | |
| 173 | "dev": true, | |
| 174 | "license": "Apache-2.0", | |
| 175 | "dependencies": { | |
| 176 | "bare-abort": "^2.0.13", | |
| 177 | "bare-env": "^3.0.0", | |
| 178 | "bare-events": "^2.3.1", | |
| 179 | "bare-hrtime": "^2.0.0", | |
| 180 | "bare-os": "^3.7.1", | |
| 181 | "bare-signals": "^4.0.0", | |
| 182 | "bare-stdio": "^1.0.1" | |
| 183 | } | |
| 184 | }, | |
| 185 | "node_modules/bare-cov/node_modules/bare-signals": { | |
| 186 | "version": "4.2.0", | |
| 187 | "resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-4.2.0.tgz", | |
| 188 | "integrity": "sha512-fNHMOdQIlYuTvMB3Oh9Apk99hLKn351+Ir8vz+khiPTcOqIyGG4uWWjdLTzxWdYGsA0eT+We3y0K74hjj2nq7A==", | |
| 189 | "dev": true, | |
| 190 | "license": "Apache-2.0", | |
| 191 | "dependencies": { | |
| 192 | "bare-events": "^2.5.3", | |
| 193 | "bare-os": "^3.3.1" | |
| 194 | }, | |
| 195 | "engines": { | |
| 196 | "bare": ">=1.7.0" | |
| 197 | } | |
| 198 | }, | |
| 199 | "node_modules/bare-crypto": { | |
| 200 | "version": "1.13.4", | |
| 201 | "resolved": "https://registry.npmjs.org/bare-crypto/-/bare-crypto-1.13.4.tgz", | |
| 202 | "integrity": "sha512-JiCZ5l2YOG1y8J7yy1BCAKTCZrPnHLb7pDRIdurBTOn5oIwBQDIv8iH5Pl2V85vzjl1NZXRfNY4HZLsE942jJA==", | |
| 203 | "dev": true, | |
| 204 | "license": "Apache-2.0", | |
| 205 | "dependencies": { | |
| 206 | "bare-assert": "^1.2.0", | |
| 207 | "bare-stream": "^2.6.3" | |
| 208 | }, | |
| 209 | "peerDependencies": { | |
| 210 | "bare-buffer": "*" | |
| 211 | }, | |
| 212 | "peerDependenciesMeta": { | |
| 213 | "bare-buffer": { | |
| 214 | "optional": true | |
| 215 | } | |
| 216 | } | |
| 217 | }, | |
| 218 | "node_modules/bare-debug-log": { | |
| 219 | "version": "2.0.0", | |
| 220 | "resolved": "https://registry.npmjs.org/bare-debug-log/-/bare-debug-log-2.0.0.tgz", | |
| 221 | "integrity": "sha512-Vi42PkMQsNV9PUpx2Gl1hikshx5O9FzMJ6o9Nnopseg7qLBBK7Nl31d0RHcfwLEAfmcPApytpc0ZFfq68u22FQ==", | |
| 222 | "dev": true, | |
| 223 | "license": "Apache-2.0", | |
| 224 | "dependencies": { | |
| 225 | "bare-os": "^3.0.1" | |
| 226 | } | |
| 227 | }, | |
| 228 | "node_modules/bare-dns": { | |
| 229 | "version": "2.1.4", | |
| 230 | "resolved": "https://registry.npmjs.org/bare-dns/-/bare-dns-2.1.4.tgz", | |
| 231 | "integrity": "sha512-abwjHmpWqSRNB7V5615QxPH92L71AVzFm/kKTs8VYiNTAi2xVdonpv0BjJ0hwXLwomoW+xsSOPjW6PZPO14asg==", | |
| 232 | "devOptional": true, | |
| 233 | "license": "Apache-2.0", | |
| 234 | "engines": { | |
| 235 | "bare": ">=1.7.0" | |
| 236 | } | |
| 237 | }, | |
| 238 | "node_modules/bare-encoding": { | |
| 239 | "version": "1.0.3", | |
| 240 | "resolved": "https://registry.npmjs.org/bare-encoding/-/bare-encoding-1.0.3.tgz", | |
| 241 | "integrity": "sha512-Kqf+t/azs13lUeyK4Tb7ha4wdLRXKWCXQ8w1rVmt7KtoPCPdHD/Xwt7LBIsCSwwGglrcmblo5VOLa5avkJqULA==", | |
| 242 | "dev": true, | |
| 243 | "license": "Apache-2.0", | |
| 244 | "peerDependencies": { | |
| 245 | "bare-buffer": "*" | |
| 246 | }, | |
| 247 | "peerDependenciesMeta": { | |
| 248 | "bare-buffer": { | |
| 249 | "optional": true | |
| 250 | } | |
| 251 | } | |
| 252 | }, | |
| 253 | "node_modules/bare-env": { | |
| 254 | "version": "3.0.0", | |
| 255 | "resolved": "https://registry.npmjs.org/bare-env/-/bare-env-3.0.0.tgz", | |
| 256 | "integrity": "sha512-0u964P5ZLAxTi+lW4Kjp7YRJQ5gZr9ycYOtjLxsSrupgMz3sn5Z9n4SH/JIifHwvadsf1brA2JAjP+9IOWwTiw==", | |
| 257 | "devOptional": true, | |
| 258 | "license": "Apache-2.0", | |
| 259 | "dependencies": { | |
| 260 | "bare-os": "^3.0.1" | |
| 261 | } | |
| 262 | }, | |
| 263 | "node_modules/bare-events": { | |
| 264 | "version": "2.8.2", | |
| 265 | "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", | |
| 266 | "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", | |
| 267 | "devOptional": true, | |
| 268 | "license": "Apache-2.0", | |
| 269 | "peerDependencies": { | |
| 270 | "bare-abort-controller": "*" | |
| 271 | }, | |
| 272 | "peerDependenciesMeta": { | |
| 273 | "bare-abort-controller": { | |
| 274 | "optional": true | |
| 275 | } | |
| 276 | } | |
| 277 | }, | |
| 278 | "node_modules/bare-format": { | |
| 279 | "version": "1.0.2", | |
| 280 | "resolved": "https://registry.npmjs.org/bare-format/-/bare-format-1.0.2.tgz", | |
| 281 | "integrity": "sha512-GswdhnOnP9QtwRbrf4wLApw5widkaLMsLe2XOs35fQD2YfEN1ApoGka+cZ7PfvzxMgfYXmMhj/2OGlVn5/Dxgw==", | |
| 282 | "dev": true, | |
| 283 | "license": "Apache-2.0", | |
| 284 | "dependencies": { | |
| 285 | "bare-inspect": "^3.0.0" | |
| 286 | } | |
| 287 | }, | |
| 288 | "node_modules/bare-fs": { | |
| 289 | "version": "4.7.0", | |
| 290 | "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.0.tgz", | |
| 291 | "integrity": "sha512-xzqKsCFxAek9aezYhjJuJRXBIaYlg/0OGDTZp+T8eYmYMlm66cs6cYko02drIyjN2CBbi+I6L7YfXyqpqtKRXA==", | |
| 292 | "devOptional": true, | |
| 293 | "license": "Apache-2.0", | |
| 294 | "dependencies": { | |
| 295 | "bare-events": "^2.5.4", | |
| 296 | "bare-path": "^3.0.0", | |
| 297 | "bare-stream": "^2.6.4", | |
| 298 | "bare-url": "^2.2.2", | |
| 299 | "fast-fifo": "^1.3.2" | |
| 300 | }, | |
| 301 | "engines": { | |
| 302 | "bare": ">=1.16.0" | |
| 303 | }, | |
| 304 | "peerDependencies": { | |
| 305 | "bare-buffer": "*" | |
| 306 | }, | |
| 307 | "peerDependenciesMeta": { | |
| 308 | "bare-buffer": { | |
| 309 | "optional": true | |
| 310 | } | |
| 311 | } | |
| 312 | }, | |
| 313 | "node_modules/bare-hrtime": { | |
| 314 | "version": "2.1.1", | |
| 315 | "resolved": "https://registry.npmjs.org/bare-hrtime/-/bare-hrtime-2.1.1.tgz", | |
| 316 | "integrity": "sha512-VMb3tHo05gsnbu3OXTmkDiwTjMlOsbQmKoysKqKEyR09m77TuDrYFbj3Q5GGk10dAKsUHrnXmwCaeJqzVpB5ZA==", | |
| 317 | "devOptional": true, | |
| 318 | "license": "Apache-2.0" | |
| 319 | }, | |
| 320 | "node_modules/bare-http-parser": { | |
| 321 | "version": "1.1.3", | |
| 322 | "resolved": "https://registry.npmjs.org/bare-http-parser/-/bare-http-parser-1.1.3.tgz", | |
| 323 | "integrity": "sha512-+dhVvQi6brHq14L/XHNRQ+TLuVE76VjRmMt61wVEtS+Od8xUslfMHWJN/ZjIIt3RtTG6vPuA+x9cOh7KrkBJsA==", | |
| 324 | "devOptional": true, | |
| 325 | "license": "Apache-2.0" | |
| 326 | }, | |
| 327 | "node_modules/bare-http1": { | |
| 328 | "version": "4.5.6", | |
| 329 | "resolved": "https://registry.npmjs.org/bare-http1/-/bare-http1-4.5.6.tgz", | |
| 330 | "integrity": "sha512-31OAwMkSU+z1VuUOCk65hx3aWQgzCfH/zQ6LGxbJtmiy2Czsw0+uvOBM9YkqaL6zUSTSYG2pLbL0v/TjME3Buw==", | |
| 331 | "devOptional": true, | |
| 332 | "license": "Apache-2.0", | |
| 333 | "dependencies": { | |
| 334 | "bare-events": "^2.6.0", | |
| 335 | "bare-http-parser": "^1.1.1", | |
| 336 | "bare-stream": "^2.10.0", | |
| 337 | "bare-tcp": "^2.2.0" | |
| 338 | }, | |
| 339 | "peerDependencies": { | |
| 340 | "bare-buffer": "*", | |
| 341 | "bare-url": "*" | |
| 342 | }, | |
| 343 | "peerDependenciesMeta": { | |
| 344 | "bare-buffer": { | |
| 345 | "optional": true | |
| 346 | }, | |
| 347 | "bare-url": { | |
| 348 | "optional": true | |
| 349 | } | |
| 350 | } | |
| 351 | }, | |
| 352 | "node_modules/bare-https": { | |
| 353 | "version": "2.1.3", | |
| 354 | "resolved": "https://registry.npmjs.org/bare-https/-/bare-https-2.1.3.tgz", | |
| 355 | "integrity": "sha512-0TI/mJXQGYXmG7UUyWEG+KCJusayIAQLywUjFAskDoKuxfqVnGF+M/mTMrEV8J64DaIdU+5x761FvgmT7M68tA==", | |
| 356 | "dev": true, | |
| 357 | "license": "Apache-2.0", | |
| 358 | "dependencies": { | |
| 359 | "bare-http1": "^4.4.0", | |
| 360 | "bare-tcp": "^2.2.0", | |
| 361 | "bare-tls": "^2.0.0" | |
| 362 | } | |
| 363 | }, | |
| 364 | "node_modules/bare-inspect": { | |
| 365 | "version": "3.1.4", | |
| 366 | "resolved": "https://registry.npmjs.org/bare-inspect/-/bare-inspect-3.1.4.tgz", | |
| 367 | "integrity": "sha512-jfW5KRA84o3REpI6Vr4nbvMn+hqVAw8GU1mMdRwUsY5yJovQamxYeKGVKGqdzs+8ZbG4jRzGUXP/3Ji/DnqfPg==", | |
| 368 | "dev": true, | |
| 369 | "license": "Apache-2.0", | |
| 370 | "dependencies": { | |
| 371 | "bare-ansi-escapes": "^2.1.0", | |
| 372 | "bare-type": "^1.0.0" | |
| 373 | }, | |
| 374 | "engines": { | |
| 375 | "bare": ">=1.18.0" | |
| 376 | } | |
| 377 | }, | |
| 378 | "node_modules/bare-inspector": { | |
| 379 | "version": "4.0.3", | |
| 380 | "resolved": "https://registry.npmjs.org/bare-inspector/-/bare-inspector-4.0.3.tgz", | |
| 381 | "integrity": "sha512-yYk6+7tTVKJKHOja5+QBn989ETv8oVsmwoH0nCM+QYC6w5MC03GC4aQNK+lipAZSz1EaAj42WZ8Wewjpy0L9TA==", | |
| 382 | "dev": true, | |
| 383 | "license": "Apache-2.0", | |
| 384 | "dependencies": { | |
| 385 | "bare-events": "^2.1.0", | |
| 386 | "bare-http1": "^4.0.0", | |
| 387 | "bare-stream": "^2.0.0", | |
| 388 | "bare-url": "^2.0.0", | |
| 389 | "bare-ws": "^2.0.0" | |
| 390 | }, | |
| 391 | "engines": { | |
| 392 | "bare": ">=1.2.0" | |
| 393 | }, | |
| 394 | "peerDependencies": { | |
| 395 | "bare-tcp": "*" | |
| 396 | }, | |
| 397 | "peerDependenciesMeta": { | |
| 398 | "bare-tcp": { | |
| 399 | "optional": true | |
| 400 | } | |
| 401 | } | |
| 402 | }, | |
| 403 | "node_modules/bare-module": { | |
| 404 | "version": "6.1.3", | |
| 405 | "resolved": "https://registry.npmjs.org/bare-module/-/bare-module-6.1.3.tgz", | |
| 406 | "integrity": "sha512-5XWsVHsvtWMH4tK4DQWgpNTV0t/sg3ZrAaQLIxrwjrS5+u8Q9vEgc/zQ4QaDPWDse/y/5h+d+YG1Q0JfSMt0zA==", | |
| 407 | "dev": true, | |
| 408 | "license": "Apache-2.0", | |
| 409 | "dependencies": { | |
| 410 | "bare-bundle": "^1.3.0", | |
| 411 | "bare-module-lexer": "^1.0.0", | |
| 412 | "bare-module-resolve": "^1.8.0", | |
| 413 | "bare-path": "^3.0.0", | |
| 414 | "bare-url": "^2.0.1" | |
| 415 | }, | |
| 416 | "engines": { | |
| 417 | "bare": ">=1.23.0" | |
| 418 | }, | |
| 419 | "peerDependencies": { | |
| 420 | "bare-buffer": "*" | |
| 421 | }, | |
| 422 | "peerDependenciesMeta": { | |
| 423 | "bare-buffer": { | |
| 424 | "optional": true | |
| 425 | } | |
| 426 | } | |
| 427 | }, | |
| 428 | "node_modules/bare-module-lexer": { | |
| 429 | "version": "1.4.7", | |
| 430 | "resolved": "https://registry.npmjs.org/bare-module-lexer/-/bare-module-lexer-1.4.7.tgz", | |
| 431 | "integrity": "sha512-0klU4eMsjh/wcxi8FdHmNom2j2F4kmkXOhyJFL9qTaSFp2lE3m6BtbKgMHY8R5miqC9r8/IfA8wzXnC5Os14WA==", | |
| 432 | "dev": true, | |
| 433 | "license": "Apache-2.0", | |
| 434 | "dependencies": { | |
| 435 | "require-addon": "^1.0.2" | |
| 436 | }, | |
| 437 | "peerDependencies": { | |
| 438 | "bare-buffer": "*" | |
| 439 | }, | |
| 440 | "peerDependenciesMeta": { | |
| 441 | "bare-buffer": { | |
| 442 | "optional": true | |
| 443 | } | |
| 444 | } | |
| 445 | }, | |
| 446 | "node_modules/bare-module-resolve": { | |
| 447 | "version": "1.12.1", | |
| 448 | "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.12.1.tgz", | |
| 449 | "integrity": "sha512-hbmAPyFpEq8FoZMd5sFO3u6MC5feluWoGE8YKlA8fCrl6mNtx68Wjg4DTiDJcqRJaovTvOYKfYngoBUnbaT7eg==", | |
| 450 | "dev": true, | |
| 451 | "license": "Apache-2.0", | |
| 452 | "dependencies": { | |
| 453 | "bare-semver": "^1.0.0" | |
| 454 | }, | |
| 455 | "peerDependencies": { | |
| 456 | "bare-url": "*" | |
| 457 | }, | |
| 458 | "peerDependenciesMeta": { | |
| 459 | "bare-url": { | |
| 460 | "optional": true | |
| 461 | } | |
| 462 | } | |
| 463 | }, | |
| 464 | "node_modules/bare-net": { | |
| 465 | "version": "2.3.1", | |
| 466 | "resolved": "https://registry.npmjs.org/bare-net/-/bare-net-2.3.1.tgz", | |
| 467 | "integrity": "sha512-MypSqDKpDU2Xt7FIfazn5yGvRnV09gFcIPHGWstW0gxuzA4tucTcwJSZeos97C4F89vtU5oGwXDN/HrGN6Y4Jw==", | |
| 468 | "dev": true, | |
| 469 | "license": "Apache-2.0", | |
| 470 | "dependencies": { | |
| 471 | "bare-events": "^2.2.2", | |
| 472 | "bare-pipe": "^4.0.0", | |
| 473 | "bare-stream": "^2.0.0", | |
| 474 | "bare-tcp": "^2.0.0" | |
| 475 | } | |
| 476 | }, | |
| 477 | "node_modules/bare-os": { | |
| 478 | "version": "3.8.7", | |
| 479 | "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.7.tgz", | |
| 480 | "integrity": "sha512-G4Gr1UsGeEy2qtDTZwL7JFLo2wapUarz7iTMcYcMFdS89AIQuBoyjgXZz0Utv7uHs3xA9LckhVbeBi8lEQrC+w==", | |
| 481 | "devOptional": true, | |
| 482 | "license": "Apache-2.0", | |
| 483 | "engines": { | |
| 484 | "bare": ">=1.14.0" | |
| 485 | } | |
| 486 | }, | |
| 487 | "node_modules/bare-path": { | |
| 488 | "version": "3.0.0", | |
| 489 | "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", | |
| 490 | "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", | |
| 491 | "devOptional": true, | |
| 492 | "license": "Apache-2.0", | |
| 493 | "dependencies": { | |
| 494 | "bare-os": "^3.0.1" | |
| 495 | } | |
| 496 | }, | |
| 497 | "node_modules/bare-pipe": { | |
| 498 | "version": "4.1.5", | |
| 499 | "resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-4.1.5.tgz", | |
| 500 | "integrity": "sha512-6OfxaG8JSkRh3Gc4hzHRsxNt+yu2PpN7lrv1V+T78GdknWQkVGwiEvu4m+1nbfk8cMVQ0TGxRvQ90XA4rhnTuw==", | |
| 501 | "dev": true, | |
| 502 | "license": "Apache-2.0", | |
| 503 | "dependencies": { | |
| 504 | "bare-events": "^2.0.0", | |
| 505 | "bare-stream": "^2.0.0" | |
| 506 | }, | |
| 507 | "engines": { | |
| 508 | "bare": ">=1.16.0" | |
| 509 | } | |
| 510 | }, | |
| 511 | "node_modules/bare-process": { | |
| 512 | "version": "3.1.1", | |
| 513 | "resolved": "https://registry.npmjs.org/bare-process/-/bare-process-3.1.1.tgz", | |
| 514 | "integrity": "sha512-lK9QBQT7PbPunay3Ee1gO45ANoXiObozh6y2nn8eK9MZ+zQwYw/XVWkQ4ixPb5v9/U/cHrAHYOXkwoN8wjPkVw==", | |
| 515 | "license": "Apache-2.0", | |
| 516 | "optional": true, | |
| 517 | "dependencies": { | |
| 518 | "bare-env": "^3.0.0", | |
| 519 | "bare-events": "^2.3.1", | |
| 520 | "bare-hrtime": "^2.0.0", | |
| 521 | "bare-os": "^3.0.1", | |
| 522 | "bare-pipe": "^3.1.0", | |
| 523 | "bare-signals": "^3.0.0", | |
| 524 | "bare-tty": "^4.0.0" | |
| 525 | } | |
| 526 | }, | |
| 527 | "node_modules/bare-process/node_modules/bare-pipe": { | |
| 528 | "version": "3.3.8", | |
| 529 | "resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-3.3.8.tgz", | |
| 530 | "integrity": "sha512-X8Ulz/os6LR/cF5HBljq/tJ0NP7eNGjiripZF53EMtgkhJ9FVl1/WLZxwvUvcqbR82Ywaq6KYM+A6zS7DGPPUw==", | |
| 531 | "license": "Apache-2.0", | |
| 532 | "optional": true, | |
| 533 | "dependencies": { | |
| 534 | "bare-events": "^2.0.0", | |
| 535 | "bare-stream": "^2.0.0" | |
| 536 | } | |
| 537 | }, | |
| 538 | "node_modules/bare-semver": { | |
| 539 | "version": "1.0.3", | |
| 540 | "resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.3.tgz", | |
| 541 | "integrity": "sha512-HS/A30bi2+PiRJfU6R4+Kp+6KeLSCSByjYM2iiobOKzLAvtu1CT+S8xWfiU7wz0erknjkUoC+yXy108tzIuP5Q==", | |
| 542 | "dev": true, | |
| 543 | "license": "Apache-2.0" | |
| 544 | }, | |
| 545 | "node_modules/bare-signals": { | |
| 546 | "version": "3.0.2", | |
| 547 | "resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-3.0.2.tgz", | |
| 548 | "integrity": "sha512-Jy0teXMTG+BPW/nJXIvd1ZY3Bnt0I/TL00Dd5T16JvY5dUK6GMsKSRW+YipGRMQssam+L/pBvSbHV6WsI3D9Qw==", | |
| 549 | "license": "Apache-2.0", | |
| 550 | "optional": true, | |
| 551 | "dependencies": { | |
| 552 | "bare-events": "^2.0.0", | |
| 553 | "bare-os": "^3.0.1" | |
| 554 | } | |
| 555 | }, | |
| 556 | "node_modules/bare-stdio": { | |
| 557 | "version": "1.0.2", | |
| 558 | "resolved": "https://registry.npmjs.org/bare-stdio/-/bare-stdio-1.0.2.tgz", | |
| 559 | "integrity": "sha512-3WJDqtvVGP4f+j68kyEC05umOYNwKJ1xG+YAXL8yZ605WgNqiRhVaFq+mVIhBt2eKNp7pa5vCQdhOt1pNh79SA==", | |
| 560 | "dev": true, | |
| 561 | "license": "Apache-2.0", | |
| 562 | "dependencies": { | |
| 563 | "bare-fs": "^4.5.2", | |
| 564 | "bare-pipe": "^4.1.5", | |
| 565 | "bare-tty": "^5.0.3" | |
| 566 | } | |
| 567 | }, | |
| 568 | "node_modules/bare-stdio/node_modules/bare-signals": { | |
| 569 | "version": "4.2.0", | |
| 570 | "resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-4.2.0.tgz", | |
| 571 | "integrity": "sha512-fNHMOdQIlYuTvMB3Oh9Apk99hLKn351+Ir8vz+khiPTcOqIyGG4uWWjdLTzxWdYGsA0eT+We3y0K74hjj2nq7A==", | |
| 572 | "dev": true, | |
| 573 | "license": "Apache-2.0", | |
| 574 | "dependencies": { | |
| 575 | "bare-events": "^2.5.3", | |
| 576 | "bare-os": "^3.3.1" | |
| 577 | }, | |
| 578 | "engines": { | |
| 579 | "bare": ">=1.7.0" | |
| 580 | } | |
| 581 | }, | |
| 582 | "node_modules/bare-stdio/node_modules/bare-tty": { | |
| 583 | "version": "5.1.0", | |
| 584 | "resolved": "https://registry.npmjs.org/bare-tty/-/bare-tty-5.1.0.tgz", | |
| 585 | "integrity": "sha512-EZLvW4A+XiJgI3TW+e1pMME9PIJsfEXe/DA/WSKzIkq/v7Yarpv/rvG6Z5pGnpo4V/Bd+qopwnCLSR71hMMBYA==", | |
| 586 | "dev": true, | |
| 587 | "license": "Apache-2.0", | |
| 588 | "dependencies": { | |
| 589 | "bare-events": "^2.2.0", | |
| 590 | "bare-signals": "^4.0.0", | |
| 591 | "bare-stream": "^2.0.0" | |
| 592 | }, | |
| 593 | "engines": { | |
| 594 | "bare": ">=1.16.0" | |
| 595 | } | |
| 596 | }, | |
| 597 | "node_modules/bare-stream": { | |
| 598 | "version": "2.13.0", | |
| 599 | "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.0.tgz", | |
| 600 | "integrity": "sha512-3zAJRZMDFGjdn+RVnNpF9kuELw+0Fl3lpndM4NcEOhb9zwtSo/deETfuIwMSE5BXanA0FrN1qVjffGwAg2Y7EA==", | |
| 601 | "devOptional": true, | |
| 602 | "license": "Apache-2.0", | |
| 603 | "dependencies": { | |
| 604 | "streamx": "^2.25.0", | |
| 605 | "teex": "^1.0.1" | |
| 606 | }, | |
| 607 | "peerDependencies": { | |
| 608 | "bare-abort-controller": "*", | |
| 609 | "bare-buffer": "*", | |
| 610 | "bare-events": "*" | |
| 611 | }, | |
| 612 | "peerDependenciesMeta": { | |
| 613 | "bare-abort-controller": { | |
| 614 | "optional": true | |
| 615 | }, | |
| 616 | "bare-buffer": { | |
| 617 | "optional": true | |
| 618 | }, | |
| 619 | "bare-events": { | |
| 620 | "optional": true | |
| 621 | } | |
| 622 | } | |
| 623 | }, | |
| 624 | "node_modules/bare-stylize": { | |
| 625 | "version": "0.0.1", | |
| 626 | "resolved": "https://registry.npmjs.org/bare-stylize/-/bare-stylize-0.0.1.tgz", | |
| 627 | "integrity": "sha512-l3MjmIl476bWijYWf3RbE+osl4iuXSOMudzp0vAqzIK7gPgn/+G3oAxp8Oin9CFF911KBP0LO9kts8Ci8mGZaQ==", | |
| 628 | "dev": true, | |
| 629 | "license": "Apache-2.0", | |
| 630 | "dependencies": { | |
| 631 | "bare-ansi-escapes": "^2.2.3", | |
| 632 | "bare-process": "^4.2.1" | |
| 633 | } | |
| 634 | }, | |
| 635 | "node_modules/bare-stylize/node_modules/bare-process": { | |
| 636 | "version": "4.4.1", | |
| 637 | "resolved": "https://registry.npmjs.org/bare-process/-/bare-process-4.4.1.tgz", | |
| 638 | "integrity": "sha512-JfcTtymq6akqM2bdyTsP4A4GYJceBzb91k/ECmFps75uFf6uO33SM1bOZsRAqyRXExabsQJLn5S41NBl8HTM4A==", | |
| 639 | "dev": true, | |
| 640 | "license": "Apache-2.0", | |
| 641 | "dependencies": { | |
| 642 | "bare-abort": "^2.0.13", | |
| 643 | "bare-env": "^3.0.0", | |
| 644 | "bare-events": "^2.3.1", | |
| 645 | "bare-hrtime": "^2.0.0", | |
| 646 | "bare-os": "^3.7.1", | |
| 647 | "bare-signals": "^4.0.0", | |
| 648 | "bare-stdio": "^1.0.1" | |
| 649 | } | |
| 650 | }, | |
| 651 | "node_modules/bare-stylize/node_modules/bare-signals": { | |
| 652 | "version": "4.2.0", | |
| 653 | "resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-4.2.0.tgz", | |
| 654 | "integrity": "sha512-fNHMOdQIlYuTvMB3Oh9Apk99hLKn351+Ir8vz+khiPTcOqIyGG4uWWjdLTzxWdYGsA0eT+We3y0K74hjj2nq7A==", | |
| 655 | "dev": true, | |
| 656 | "license": "Apache-2.0", | |
| 657 | "dependencies": { | |
| 658 | "bare-events": "^2.5.3", | |
| 659 | "bare-os": "^3.3.1" | |
| 660 | }, | |
| 661 | "engines": { | |
| 662 | "bare": ">=1.7.0" | |
| 663 | } | |
| 664 | }, | |
| 665 | "node_modules/bare-subprocess": { | |
| 666 | "version": "5.2.3", | |
| 667 | "resolved": "https://registry.npmjs.org/bare-subprocess/-/bare-subprocess-5.2.3.tgz", | |
| 668 | "integrity": "sha512-07wwswlV7M3sC9IykbZRZ/jHAkrXFWVLqdBWGv1y0ojCimtRD9hGwxdHmR5FUFmDUZLNsBmTYJNQqgio5+A85Q==", | |
| 669 | "dev": true, | |
| 670 | "license": "Apache-2.0", | |
| 671 | "dependencies": { | |
| 672 | "bare-env": "^3.0.0", | |
| 673 | "bare-events": "^2.5.4", | |
| 674 | "bare-os": "^3.0.1", | |
| 675 | "bare-pipe": "^4.0.0", | |
| 676 | "bare-url": "^2.2.2" | |
| 677 | }, | |
| 678 | "engines": { | |
| 679 | "bare": ">=1.7.0" | |
| 680 | }, | |
| 681 | "peerDependencies": { | |
| 682 | "bare-buffer": "*" | |
| 683 | }, | |
| 684 | "peerDependenciesMeta": { | |
| 685 | "bare-buffer": { | |
| 686 | "optional": true | |
| 687 | } | |
| 688 | } | |
| 689 | }, | |
| 690 | "node_modules/bare-tcp": { | |
| 691 | "version": "2.2.7", | |
| 692 | "resolved": "https://registry.npmjs.org/bare-tcp/-/bare-tcp-2.2.7.tgz", | |
| 693 | "integrity": "sha512-rjpqNQ2cOCkNo3NeYA/W4GTK3DRkl8sDHO3uos+AEswUjLC8XXMQF8WrJCSjlIowCbS6NUVxKE92X5RGXjyefg==", | |
| 694 | "devOptional": true, | |
| 695 | "license": "Apache-2.0", | |
| 696 | "dependencies": { | |
| 697 | "bare-dns": "^2.0.4", | |
| 698 | "bare-events": "^2.5.4", | |
| 699 | "bare-stream": "^2.6.4" | |
| 700 | }, | |
| 701 | "engines": { | |
| 702 | "bare": ">=1.16.0" | |
| 703 | } | |
| 704 | }, | |
| 705 | "node_modules/bare-tls": { | |
| 706 | "version": "2.2.3", | |
| 707 | "resolved": "https://registry.npmjs.org/bare-tls/-/bare-tls-2.2.3.tgz", | |
| 708 | "integrity": "sha512-dPYBGEXtgLceRFMfGaF2/rqR86/xMxMyrM9ootO/gaRKL/z2uNHJs7aP7IOBtnJF8eUCt5qwMzbKfrKgDIxPLg==", | |
| 709 | "dev": true, | |
| 710 | "license": "Apache-2.0", | |
| 711 | "dependencies": { | |
| 712 | "bare-net": "^2.0.1", | |
| 713 | "bare-stream": "^2.6.4" | |
| 714 | }, | |
| 715 | "engines": { | |
| 716 | "bare": ">=1.7.0" | |
| 717 | } | |
| 718 | }, | |
| 719 | "node_modules/bare-tty": { | |
| 720 | "version": "4.0.2", | |
| 721 | "resolved": "https://registry.npmjs.org/bare-tty/-/bare-tty-4.0.2.tgz", | |
| 722 | "integrity": "sha512-MfNtmUx/FhZZKn+IAe9Sai5mYFg/m+LBF1pSY56cjX6j2vQFEnm8NNsWryiyB85haYeN7tDh66WTcbUDJnBVtQ==", | |
| 723 | "license": "Apache-2.0", | |
| 724 | "optional": true, | |
| 725 | "dependencies": { | |
| 726 | "bare-events": "^2.2.0", | |
| 727 | "bare-signals": "^3.0.0", | |
| 728 | "bare-stream": "^2.0.0" | |
| 729 | } | |
| 730 | }, | |
| 731 | "node_modules/bare-type": { | |
| 732 | "version": "1.1.0", | |
| 733 | "resolved": "https://registry.npmjs.org/bare-type/-/bare-type-1.1.0.tgz", | |
| 734 | "integrity": "sha512-LdtnnEEYldOc87Dr4GpsKnStStZk3zfgoEMXy8yvEZkXrcCv9RtYDrUYWFsBQHtaB0s1EUWmcvS6XmEZYIj3Bw==", | |
| 735 | "dev": true, | |
| 736 | "license": "Apache-2.0", | |
| 737 | "engines": { | |
| 738 | "bare": ">=1.2.0" | |
| 739 | } | |
| 740 | }, | |
| 741 | "node_modules/bare-url": { | |
| 742 | "version": "2.4.0", | |
| 743 | "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.0.tgz", | |
| 744 | "integrity": "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA==", | |
| 745 | "devOptional": true, | |
| 746 | "license": "Apache-2.0", | |
| 747 | "peer": true, | |
| 748 | "dependencies": { | |
| 749 | "bare-path": "^3.0.0" | |
| 750 | } | |
| 751 | }, | |
| 752 | "node_modules/bare-utils": { | |
| 753 | "version": "1.6.0", | |
| 754 | "resolved": "https://registry.npmjs.org/bare-utils/-/bare-utils-1.6.0.tgz", | |
| 755 | "integrity": "sha512-WhQEIkkAxkSnW7u1QgrI0AfNm5JpMruETXeYsb5qnkBJ0TTfNKygZmsh6rkoHBANaV+C/7Jed7bJP9OmEHG7rQ==", | |
| 756 | "dev": true, | |
| 757 | "license": "Apache-2.0", | |
| 758 | "dependencies": { | |
| 759 | "bare-debug-log": "^2.0.0", | |
| 760 | "bare-encoding": "^1.0.0", | |
| 761 | "bare-format": "^1.0.0", | |
| 762 | "bare-inspect": "^3.0.0", | |
| 763 | "bare-stylize": "^0.0.1", | |
| 764 | "bare-type": "^1.0.6" | |
| 765 | } | |
| 766 | }, | |
| 767 | "node_modules/bare-v8-to-istanbul": { | |
| 768 | "version": "1.0.2", | |
| 769 | "resolved": "https://registry.npmjs.org/bare-v8-to-istanbul/-/bare-v8-to-istanbul-1.0.2.tgz", | |
| 770 | "integrity": "sha512-CM0wPgyQtXTQ7h4q8NjbTZ/FH5he0Jkiwgpq0lFZZA5tkVZzmQ/9ul4R7E+cNlGZJIZlQZ9v4CwbgVaFG3zOAA==", | |
| 771 | "dev": true, | |
| 772 | "license": "Apache-2.0", | |
| 773 | "dependencies": { | |
| 774 | "bare-assert": "^1.0.2", | |
| 775 | "bare-fs": "^4.1.2", | |
| 776 | "bare-module": "^6.1.2", | |
| 777 | "bare-path": "^3.0.0", | |
| 778 | "bare-process": "^4.2.0", | |
| 779 | "bare-url": "^2.1.5", | |
| 780 | "bare-utils": "^1.2.0", | |
| 781 | "v8-to-istanbul": "^9.3.0", | |
| 782 | "which-runtime": "^1.2.1" | |
| 783 | } | |
| 784 | }, | |
| 785 | "node_modules/bare-v8-to-istanbul/node_modules/bare-process": { | |
| 786 | "version": "4.4.1", | |
| 787 | "resolved": "https://registry.npmjs.org/bare-process/-/bare-process-4.4.1.tgz", | |
| 788 | "integrity": "sha512-JfcTtymq6akqM2bdyTsP4A4GYJceBzb91k/ECmFps75uFf6uO33SM1bOZsRAqyRXExabsQJLn5S41NBl8HTM4A==", | |
| 789 | "dev": true, | |
| 790 | "license": "Apache-2.0", | |
| 791 | "dependencies": { | |
| 792 | "bare-abort": "^2.0.13", | |
| 793 | "bare-env": "^3.0.0", | |
| 794 | "bare-events": "^2.3.1", | |
| 795 | "bare-hrtime": "^2.0.0", | |
| 796 | "bare-os": "^3.7.1", | |
| 797 | "bare-signals": "^4.0.0", | |
| 798 | "bare-stdio": "^1.0.1" | |
| 799 | } | |
| 800 | }, | |
| 801 | "node_modules/bare-v8-to-istanbul/node_modules/bare-signals": { | |
| 802 | "version": "4.2.0", | |
| 803 | "resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-4.2.0.tgz", | |
| 804 | "integrity": "sha512-fNHMOdQIlYuTvMB3Oh9Apk99hLKn351+Ir8vz+khiPTcOqIyGG4uWWjdLTzxWdYGsA0eT+We3y0K74hjj2nq7A==", | |
| 805 | "dev": true, | |
| 806 | "license": "Apache-2.0", | |
| 807 | "dependencies": { | |
| 808 | "bare-events": "^2.5.3", | |
| 809 | "bare-os": "^3.3.1" | |
| 810 | }, | |
| 811 | "engines": { | |
| 812 | "bare": ">=1.7.0" | |
| 813 | } | |
| 814 | }, | |
| 815 | "node_modules/bare-ws": { | |
| 816 | "version": "2.1.0", | |
| 817 | "resolved": "https://registry.npmjs.org/bare-ws/-/bare-ws-2.1.0.tgz", | |
| 818 | "integrity": "sha512-2gEWlPK9iyBchACdIY6oQXgmDz3KLrChdwrPgmU3IVXOFTnxTqSUT27WE/+izd4QojHj/SsqDkQiD2HDvuTdAA==", | |
| 819 | "dev": true, | |
| 820 | "license": "Apache-2.0", | |
| 821 | "dependencies": { | |
| 822 | "bare-crypto": "^1.2.0", | |
| 823 | "bare-events": "^2.3.1", | |
| 824 | "bare-http1": "^4.0.0", | |
| 825 | "bare-https": "^2.0.0", | |
| 826 | "bare-stream": "^2.1.2" | |
| 827 | }, | |
| 828 | "peerDependencies": { | |
| 829 | "bare-buffer": "*", | |
| 830 | "bare-url": "*" | |
| 831 | }, | |
| 832 | "peerDependenciesMeta": { | |
| 833 | "bare-buffer": { | |
| 834 | "optional": true | |
| 835 | }, | |
| 836 | "bare-url": { | |
| 837 | "optional": true | |
| 838 | } | |
| 839 | } | |
| 840 | }, | |
| 841 | "node_modules/bare-zlib": { | |
| 842 | "version": "1.3.3", | |
| 843 | "resolved": "https://registry.npmjs.org/bare-zlib/-/bare-zlib-1.3.3.tgz", | |
| 844 | "integrity": "sha512-rXNczo+SQg6cn20olmh/mUiGeJK9maipFH/zI/QwYgwhEmOns1R7fl1GV5apNO+aAp4x2d4uUa7HLhO4mhOnBQ==", | |
| 845 | "license": "Apache-2.0", | |
| 846 | "optional": true, | |
| 847 | "dependencies": { | |
| 848 | "bare-stream": "^2.0.0" | |
| 849 | } | |
| 850 | }, | |
| 851 | "node_modules/brittle": { | |
| 852 | "version": "3.19.1", | |
| 853 | "resolved": "https://registry.npmjs.org/brittle/-/brittle-3.19.1.tgz", | |
| 854 | "integrity": "sha512-4Ted1Mt9o9B6oIA6ImJJCtB/Fv++ZO3IDNQgRcHOXWSYGRUidgxchaGrUBaRn+4mlneXrgInPkCPzi0jO8qKbA==", | |
| 855 | "dev": true, | |
| 856 | "license": "Apache-2.0", | |
| 857 | "dependencies": { | |
| 858 | "b4a": "^1.6.0", | |
| 859 | "bare-assert": "^1.0.2", | |
| 860 | "bare-cov": "^1.1.0", | |
| 861 | "bare-fs": "^4.1.6", | |
| 862 | "bare-os": "^3.6.1", | |
| 863 | "bare-path": "^3.0.0", | |
| 864 | "bare-process": "^4.2.1", | |
| 865 | "bare-subprocess": "^5.0.0", | |
| 866 | "bare-url": "^2.1.6", | |
| 867 | "error-stack-parser": "^2.1.4", | |
| 868 | "globbie": "^1.0.2", | |
| 869 | "paparam": "^1.6.2", | |
| 870 | "same-object": "^1.0.2", | |
| 871 | "test-tmp": "^1.4.0", | |
| 872 | "tmatch": "^5.0.0" | |
| 873 | }, | |
| 874 | "bin": { | |
| 875 | "brittle": "bin/node.js", | |
| 876 | "brittle-bare": "bin/bare.js", | |
| 877 | "brittle-node": "bin/node.js", | |
| 878 | "brittle-pear": "bin/pear.js" | |
| 879 | } | |
| 880 | }, | |
| 881 | "node_modules/brittle/node_modules/bare-process": { | |
| 882 | "version": "4.4.1", | |
| 883 | "resolved": "https://registry.npmjs.org/bare-process/-/bare-process-4.4.1.tgz", | |
| 884 | "integrity": "sha512-JfcTtymq6akqM2bdyTsP4A4GYJceBzb91k/ECmFps75uFf6uO33SM1bOZsRAqyRXExabsQJLn5S41NBl8HTM4A==", | |
| 885 | "dev": true, | |
| 886 | "license": "Apache-2.0", | |
| 887 | "dependencies": { | |
| 888 | "bare-abort": "^2.0.13", | |
| 889 | "bare-env": "^3.0.0", | |
| 890 | "bare-events": "^2.3.1", | |
| 891 | "bare-hrtime": "^2.0.0", | |
| 892 | "bare-os": "^3.7.1", | |
| 893 | "bare-signals": "^4.0.0", | |
| 894 | "bare-stdio": "^1.0.1" | |
| 895 | } | |
| 896 | }, | |
| 897 | "node_modules/brittle/node_modules/bare-signals": { | |
| 898 | "version": "4.2.0", | |
| 899 | "resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-4.2.0.tgz", | |
| 900 | "integrity": "sha512-fNHMOdQIlYuTvMB3Oh9Apk99hLKn351+Ir8vz+khiPTcOqIyGG4uWWjdLTzxWdYGsA0eT+We3y0K74hjj2nq7A==", | |
| 901 | "dev": true, | |
| 902 | "license": "Apache-2.0", | |
| 903 | "dependencies": { | |
| 904 | "bare-events": "^2.5.3", | |
| 905 | "bare-os": "^3.3.1" | |
| 906 | }, | |
| 907 | "engines": { | |
| 908 | "bare": ">=1.7.0" | |
| 909 | } | |
| 910 | }, | |
| 911 | "node_modules/convert-source-map": { | |
| 912 | "version": "2.0.0", | |
| 913 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", | |
| 914 | "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", | |
| 915 | "dev": true, | |
| 916 | "license": "MIT" | |
| 917 | }, | |
| 918 | "node_modules/error-stack-parser": { | |
| 919 | "version": "2.1.4", | |
| 920 | "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", | |
| 921 | "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", | |
| 922 | "dev": true, | |
| 923 | "license": "MIT", | |
| 924 | "dependencies": { | |
| 925 | "stackframe": "^1.3.4" | |
| 926 | } | |
| 927 | }, | |
| 928 | "node_modules/events-universal": { | |
| 929 | "version": "1.0.1", | |
| 930 | "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", | |
| 931 | "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", | |
| 932 | "devOptional": true, | |
| 933 | "license": "Apache-2.0", | |
| 934 | "dependencies": { | |
| 935 | "bare-events": "^2.7.0" | |
| 936 | } | |
| 937 | }, | |
| 938 | "node_modules/fast-fifo": { | |
| 939 | "version": "1.3.2", | |
| 940 | "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", | |
| 941 | "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", | |
| 942 | "devOptional": true, | |
| 943 | "license": "MIT" | |
| 944 | }, | |
| 945 | "node_modules/globbie": { | |
| 946 | "version": "1.0.3", | |
| 947 | "resolved": "https://registry.npmjs.org/globbie/-/globbie-1.0.3.tgz", | |
| 948 | "integrity": "sha512-hcryJmKcftf82xfBWTWxuUITWIIoYO3ec104V17SMHGFl6VLbm1d1Ju9LX9L+jyJTwICpemX/dmPI/HGYoKr1A==", | |
| 949 | "dev": true, | |
| 950 | "license": "Apache-2.0", | |
| 951 | "dependencies": { | |
| 952 | "bare-fs": "^4.1.2", | |
| 953 | "bare-path": "^3.0.0", | |
| 954 | "bare-process": "^4.2.1", | |
| 955 | "picomatch": "^4.0.2" | |
| 956 | } | |
| 957 | }, | |
| 958 | "node_modules/globbie/node_modules/bare-process": { | |
| 959 | "version": "4.4.1", | |
| 960 | "resolved": "https://registry.npmjs.org/bare-process/-/bare-process-4.4.1.tgz", | |
| 961 | "integrity": "sha512-JfcTtymq6akqM2bdyTsP4A4GYJceBzb91k/ECmFps75uFf6uO33SM1bOZsRAqyRXExabsQJLn5S41NBl8HTM4A==", | |
| 962 | "dev": true, | |
| 963 | "license": "Apache-2.0", | |
| 964 | "dependencies": { | |
| 965 | "bare-abort": "^2.0.13", | |
| 966 | "bare-env": "^3.0.0", | |
| 967 | "bare-events": "^2.3.1", | |
| 968 | "bare-hrtime": "^2.0.0", | |
| 969 | "bare-os": "^3.7.1", | |
| 970 | "bare-signals": "^4.0.0", | |
| 971 | "bare-stdio": "^1.0.1" | |
| 972 | } | |
| 973 | }, | |
| 974 | "node_modules/globbie/node_modules/bare-signals": { | |
| 975 | "version": "4.2.0", | |
| 976 | "resolved": "https://registry.npmjs.org/bare-signals/-/bare-signals-4.2.0.tgz", | |
| 977 | "integrity": "sha512-fNHMOdQIlYuTvMB3Oh9Apk99hLKn351+Ir8vz+khiPTcOqIyGG4uWWjdLTzxWdYGsA0eT+We3y0K74hjj2nq7A==", | |
| 978 | "dev": true, | |
| 979 | "license": "Apache-2.0", | |
| 980 | "dependencies": { | |
| 981 | "bare-events": "^2.5.3", | |
| 982 | "bare-os": "^3.3.1" | |
| 983 | }, | |
| 984 | "engines": { | |
| 985 | "bare": ">=1.7.0" | |
| 986 | } | |
| 987 | }, | |
| 988 | "node_modules/paparam": { | |
| 989 | "version": "1.10.1", | |
| 990 | "resolved": "https://registry.npmjs.org/paparam/-/paparam-1.10.1.tgz", | |
| 991 | "integrity": "sha512-viyQI64VIja0Za3njIzhoEP8ZVkgPowhZPuG0E96NwBfYJ6ZIyrrlhWGtFPkdN7eYLl2L8CTWL+wla0evm1KKQ==", | |
| 992 | "license": "Apache-2.0" | |
| 993 | }, | |
| 994 | "node_modules/picomatch": { | |
| 995 | "version": "4.0.4", | |
| 996 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", | |
| 997 | "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", | |
| 998 | "dev": true, | |
| 999 | "license": "MIT", | |
| 1000 | "engines": { | |
| 1001 | "node": ">=12" | |
| 1002 | }, | |
| 1003 | "funding": { | |
| 1004 | "url": "https://github.com/sponsors/jonschlinkert" | |
| 1005 | } | |
| 1006 | }, | |
| 1007 | "node_modules/require-addon": { | |
| 1008 | "version": "1.2.0", | |
| 1009 | "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.2.0.tgz", | |
| 1010 | "integrity": "sha512-VNPDZlYgIYQwWp9jMTzljx+k0ZtatKlcvOhktZ/anNPI3dQ9NXk7cq2U4iJ1wd9IrytRnYhyEocFWbkdPb+MYA==", | |
| 1011 | "dev": true, | |
| 1012 | "license": "Apache-2.0", | |
| 1013 | "dependencies": { | |
| 1014 | "bare-addon-resolve": "^1.3.0" | |
| 1015 | }, | |
| 1016 | "engines": { | |
| 1017 | "bare": ">=1.10.0" | |
| 1018 | } | |
| 1019 | }, | |
| 1020 | "node_modules/same-object": { | |
| 1021 | "version": "1.0.2", | |
| 1022 | "resolved": "https://registry.npmjs.org/same-object/-/same-object-1.0.2.tgz", | |
| 1023 | "integrity": "sha512-csHWhvUsLbIOHDM/nP+KHWM+BLPsIzWkFa8HbzaI0G7BqKXgx+7FJpKTGgLXyz5amfdY2OVBcmXTqYOMEk04og==", | |
| 1024 | "dev": true, | |
| 1025 | "license": "MIT" | |
| 1026 | }, | |
| 1027 | "node_modules/stackframe": { | |
| 1028 | "version": "1.3.4", | |
| 1029 | "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", | |
| 1030 | "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", | |
| 1031 | "dev": true, | |
| 1032 | "license": "MIT" | |
| 1033 | }, | |
| 1034 | "node_modules/streamx": { | |
| 1035 | "version": "2.25.0", | |
| 1036 | "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", | |
| 1037 | "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", | |
| 1038 | "devOptional": true, | |
| 1039 | "license": "MIT", | |
| 1040 | "dependencies": { | |
| 1041 | "events-universal": "^1.0.0", | |
| 1042 | "fast-fifo": "^1.3.2", | |
| 1043 | "text-decoder": "^1.1.0" | |
| 1044 | } | |
| 1045 | }, | |
| 1046 | "node_modules/teex": { | |
| 1047 | "version": "1.0.1", | |
| 1048 | "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", | |
| 1049 | "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", | |
| 1050 | "devOptional": true, | |
| 1051 | "license": "MIT", | |
| 1052 | "dependencies": { | |
| 1053 | "streamx": "^2.12.5" | |
| 1054 | } | |
| 1055 | }, | |
| 1056 | "node_modules/test-tmp": { | |
| 1057 | "version": "1.4.0", | |
| 1058 | "resolved": "https://registry.npmjs.org/test-tmp/-/test-tmp-1.4.0.tgz", | |
| 1059 | "integrity": "sha512-GVggxGg+jXqP2Wbju50JVLo+9E+nIOPPyWqgr63EbOnNItIKu1cEbJpTWAJeflnyGqXOtcMI7ijHRp88GUkfDA==", | |
| 1060 | "dev": true, | |
| 1061 | "license": "MIT", | |
| 1062 | "dependencies": { | |
| 1063 | "bare-fs": "^4.0.1", | |
| 1064 | "bare-os": "^3.3.0", | |
| 1065 | "bare-path": "^3.0.0" | |
| 1066 | } | |
| 1067 | }, | |
| 1068 | "node_modules/text-decoder": { | |
| 1069 | "version": "1.2.7", | |
| 1070 | "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", | |
| 1071 | "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", | |
| 1072 | "devOptional": true, | |
| 1073 | "license": "Apache-2.0", | |
| 1074 | "dependencies": { | |
| 1075 | "b4a": "^1.6.4" | |
| 1076 | } | |
| 1077 | }, | |
| 1078 | "node_modules/tmatch": { | |
| 1079 | "version": "5.0.0", | |
| 1080 | "resolved": "https://registry.npmjs.org/tmatch/-/tmatch-5.0.0.tgz", | |
| 1081 | "integrity": "sha512-Ib9OtBkpHn07tXP04SlN1SYRxFgTk6wSM2EBmjjxug4u5RXPRVLkdFJSS1PmrQidaSB8Lru9nRtViQBsbxzE5Q==", | |
| 1082 | "dev": true, | |
| 1083 | "license": "ISC", | |
| 1084 | "engines": { | |
| 1085 | "node": ">=8" | |
| 1086 | } | |
| 1087 | }, | |
| 1088 | "node_modules/v8-to-istanbul": { | |
| 1089 | "version": "9.3.0", | |
| 1090 | "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", | |
| 1091 | "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", | |
| 1092 | "dev": true, | |
| 1093 | "license": "ISC", | |
| 1094 | "dependencies": { | |
| 1095 | "@jridgewell/trace-mapping": "^0.3.12", | |
| 1096 | "@types/istanbul-lib-coverage": "^2.0.1", | |
| 1097 | "convert-source-map": "^2.0.0" | |
| 1098 | }, | |
| 1099 | "engines": { | |
| 1100 | "node": ">=10.12.0" | |
| 1101 | } | |
| 1102 | }, | |
| 1103 | "node_modules/which-runtime": { | |
| 1104 | "version": "1.3.2", | |
| 1105 | "resolved": "https://registry.npmjs.org/which-runtime/-/which-runtime-1.3.2.tgz", | |
| 1106 | "integrity": "sha512-5kwCfWml7+b2NO7KrLMhYihjRx0teKkd3yGp1Xk5Vaf2JGdSh+rgVhEALAD9c/59dP+YwJHXoEO7e8QPy7gOkw==", | |
| 1107 | "dev": true, | |
| 1108 | "license": "Apache-2.0" | |
| 1109 | } | |
| 1110 | } | |
| 1111 | } |
| … | … | @@ -0,0 +1,38 @@ |
| 1 | { | |
| 2 | "name": "codetree", | |
| 3 | "version": "0.1.0", | |
| 4 | "description": "Structural code scanner — recursive mind map of a codebase", | |
| 5 | "type": "module", | |
| 6 | "main": "index.js", | |
| 7 | "bin": { | |
| 8 | "codetree": "./index.js" | |
| 9 | }, | |
| 10 | "scripts": { | |
| 11 | "test": "brittle test/*.test.js" | |
| 12 | }, | |
| 13 | "imports": { | |
| 14 | "fs": { "bare": "bare-fs", "default": "fs" }, | |
| 15 | "fs/*": { "bare": "bare-fs/*", "default": "fs/*" }, | |
| 16 | "path": { "bare": "bare-path", "default": "path" }, | |
| 17 | "url": { "bare": "bare-url", "default": "url" }, | |
| 18 | "process": { "bare": "bare-process", "default": "process" }, | |
| 19 | "http": { "bare": "bare-http1", "default": "http" }, | |
| 20 | "events": { "bare": "bare-events", "default": "events" }, | |
| 21 | "zlib": { "bare": "bare-zlib", "default": "zlib" } | |
| 22 | }, | |
| 23 | "dependencies": { | |
| 24 | "paparam": "^1.8.6" | |
| 25 | }, | |
| 26 | "optionalDependencies": { | |
| 27 | "bare-fs": "^4.5.0", | |
| 28 | "bare-path": "^3.0.0", | |
| 29 | "bare-process": "^3.0.0", | |
| 30 | "bare-url": "^2.3.2", | |
| 31 | "bare-http1": "^4.0.0", | |
| 32 | "bare-events": "^2.5.0", | |
| 33 | "bare-zlib": "^1.3.0" | |
| 34 | }, | |
| 35 | "devDependencies": { | |
| 36 | "brittle": "^3.0.0" | |
| 37 | } | |
| 38 | } |
| … | … | @@ -0,0 +1,113 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { parseFile } from '../lib/parsers/cpp.js' | |
| 3 | ||
| 4 | test('cpp: includes — local vs system', (t) => { | |
| 5 | const src = `#include <godot_cpp/classes/node3d.hpp> | |
| 6 | #include <memory> | |
| 7 | #include "dc_density.h" | |
| 8 | #include "dc_octree.h" | |
| 9 | ||
| 10 | int main() { return 0; } | |
| 11 | ` | |
| 12 | ||
| 13 | const result = parseFile(src, 'main.cpp') | |
| 14 | t.is(result.imports.length, 2, '2 local includes (system ones skipped)') | |
| 15 | t.is(result.imports[0].specifier, 'dc_density.h', 'first local include') | |
| 16 | t.is(result.imports[1].specifier, 'dc_octree.h', 'second local include') | |
| 17 | }) | |
| 18 | ||
| 19 | test('cpp: class with methods, inheritance, access specifiers', (t) => { | |
| 20 | const src = `class DCTerrain : public Node3D { | |
| 21 | public: | |
| 22 | void set_resolution(int res); | |
| 23 | int get_resolution() const; | |
| 24 | static DCTerrain* create(); | |
| 25 | protected: | |
| 26 | static void _bind_methods(); | |
| 27 | private: | |
| 28 | int _resolution = 256; | |
| 29 | }; | |
| 30 | ` | |
| 31 | ||
| 32 | const result = parseFile(src, 'dc_terrain.h') | |
| 33 | t.is(result.classes.length, 1, '1 class') | |
| 34 | const cls = result.classes[0] | |
| 35 | t.is(cls.name, 'DCTerrain', 'class name') | |
| 36 | t.is(cls.extends, 'Node3D', 'base class') | |
| 37 | t.is(cls.kind, 'class', 'kind is class') | |
| 38 | ||
| 39 | const methodNames = cls.methods.map(m => m.name) | |
| 40 | t.ok(methodNames.includes('set_resolution'), 'set_resolution method') | |
| 41 | t.ok(methodNames.includes('get_resolution'), 'get_resolution method') | |
| 42 | ||
| 43 | const staticNames = cls.staticMethods.map(m => m.name) | |
| 44 | t.ok(staticNames.includes('create'), 'create static method') | |
| 45 | t.ok(staticNames.includes('_bind_methods'), '_bind_methods static method') | |
| 46 | }) | |
| 47 | ||
| 48 | test('cpp: namespaces', (t) => { | |
| 49 | const src = `namespace dc { | |
| 50 | ||
| 51 | class Foo { | |
| 52 | public: | |
| 53 | void bar(); | |
| 54 | }; | |
| 55 | ||
| 56 | } // namespace dc | |
| 57 | ` | |
| 58 | ||
| 59 | const result = parseFile(src, 'foo.h') | |
| 60 | t.ok(result.namespaces.includes('dc'), 'dc namespace captured') | |
| 61 | t.is(result.classes.length, 1, 'class inside namespace still found') | |
| 62 | }) | |
| 63 | ||
| 64 | test('cpp: struct parsed as class with kind=struct', (t) => { | |
| 65 | const src = `struct Point { | |
| 66 | int x; | |
| 67 | int y; | |
| 68 | void translate(int dx, int dy); | |
| 69 | }; | |
| 70 | ` | |
| 71 | ||
| 72 | const result = parseFile(src, 'point.h') | |
| 73 | t.is(result.classes.length, 1, '1 struct') | |
| 74 | t.is(result.classes[0].kind, 'struct', 'kind is struct') | |
| 75 | t.is(result.classes[0].name, 'Point', 'struct name') | |
| 76 | }) | |
| 77 | ||
| 78 | test('cpp: enum', (t) => { | |
| 79 | const src = `enum class State { IDLE, RUNNING, DONE }; | |
| 80 | enum Mode { READ, WRITE }; | |
| 81 | ` | |
| 82 | ||
| 83 | const result = parseFile(src, 'state.h') | |
| 84 | t.is(result.enums.length, 2, '2 enums') | |
| 85 | t.is(result.enums[0].name, 'State', 'first enum') | |
| 86 | t.ok(result.enums[0].values.includes('IDLE'), 'IDLE value') | |
| 87 | t.ok(result.enums[0].values.includes('RUNNING'), 'RUNNING value') | |
| 88 | }) | |
| 89 | ||
| 90 | test('cpp: out-of-line method definitions merge back into class', (t) => { | |
| 91 | const src = `class Foo { | |
| 92 | public: | |
| 93 | void bar(); | |
| 94 | void baz(); | |
| 95 | }; | |
| 96 | ||
| 97 | void Foo::bar() { | |
| 98 | // implementation | |
| 99 | } | |
| 100 | ||
| 101 | void Foo::baz() { | |
| 102 | // implementation | |
| 103 | } | |
| 104 | ` | |
| 105 | ||
| 106 | const result = parseFile(src, 'foo.cpp') | |
| 107 | t.is(result.classes.length, 1, '1 class') | |
| 108 | // Out-of-line definitions merge into class methods | |
| 109 | const methodNames = result.classes[0].methods.map(m => m.name) | |
| 110 | t.ok(methodNames.includes('bar'), 'bar method') | |
| 111 | t.ok(methodNames.includes('baz'), 'baz method') | |
| 112 | t.is(result.functions.length, 0, 'no free functions (all are methods)') | |
| 113 | }) |
| … | … | @@ -0,0 +1,98 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { parseFile } from '../lib/parsers/gdscript.js' | |
| 3 | ||
| 4 | test('gdscript: class_name + extends + methods + signals', (t) => { | |
| 5 | const src = `class_name KeetFeed | |
| 6 | extends Node | |
| 7 | ||
| 8 | signal room_selected(room_id: String) | |
| 9 | signal message_received(data: Dictionary) | |
| 10 | ||
| 11 | @export var max_messages: int = 100 | |
| 12 | const MAX_CACHED := 100 | |
| 13 | ||
| 14 | func _ready() -> void: | |
| 15 | pass | |
| 16 | ||
| 17 | func send_message(text: String, room_id: String) -> bool: | |
| 18 | return false | |
| 19 | ||
| 20 | static func create_from_config(config: Dictionary) -> KeetFeed: | |
| 21 | return null | |
| 22 | ` | |
| 23 | ||
| 24 | const result = parseFile(src, 'keet_feed.gd') | |
| 25 | ||
| 26 | t.is(result.error, undefined, 'no parse error') | |
| 27 | t.is(result.classes.length, 1, '1 class') | |
| 28 | ||
| 29 | const cls = result.classes[0] | |
| 30 | t.is(cls.name, 'KeetFeed', 'class_name becomes class name') | |
| 31 | t.is(cls.extends, 'Node', 'extends parsed') | |
| 32 | ||
| 33 | t.is(cls.methods.length, 2, '2 instance methods') | |
| 34 | const methodNames = cls.methods.map(m => m.name) | |
| 35 | t.ok(methodNames.includes('_ready'), '_ready method') | |
| 36 | t.ok(methodNames.includes('send_message'), 'send_message method') | |
| 37 | ||
| 38 | t.is(cls.staticMethods.length, 1, '1 static method') | |
| 39 | t.is(cls.staticMethods[0].name, 'create_from_config', 'static method name') | |
| 40 | ||
| 41 | t.is(result.signals.length, 2, '2 signals') | |
| 42 | t.is(result.signals[0].name, 'room_selected', 'first signal') | |
| 43 | ||
| 44 | t.is(result.exports.length, 1, '1 export (the class_name)') | |
| 45 | t.is(result.exports[0].name, 'KeetFeed', 'export name matches class_name') | |
| 46 | ||
| 47 | t.ok(result.constants.length >= 2, 'has var + const constants') | |
| 48 | }) | |
| 49 | ||
| 50 | test('gdscript: preload() extraction', (t) => { | |
| 51 | const src = `class_name Game | |
| 52 | extends Node | |
| 53 | ||
| 54 | const PlayerScene := preload("res://scenes/player/player.tscn") | |
| 55 | const EnemyScene: PackedScene = preload("res://scenes/enemies/enemy.tscn") | |
| 56 | ||
| 57 | func _ready() -> void: | |
| 58 | pass | |
| 59 | ` | |
| 60 | ||
| 61 | const result = parseFile(src, 'game.gd') | |
| 62 | t.is(result.imports.length, 2, '2 preload imports') | |
| 63 | t.is(result.imports[0].specifier, 'res://scenes/player/player.tscn', 'first preload path') | |
| 64 | t.is(result.imports[1].specifier, 'res://scenes/enemies/enemy.tscn', 'second preload path') | |
| 65 | }) | |
| 66 | ||
| 67 | test('gdscript: handles file without class_name', (t) => { | |
| 68 | const src = `extends RefCounted | |
| 69 | ||
| 70 | func util_function(x: int) -> int: | |
| 71 | return x * 2 | |
| 72 | ` | |
| 73 | ||
| 74 | const result = parseFile(src, 'util.gd') | |
| 75 | t.is(result.error, undefined, 'no parse error') | |
| 76 | // Class name should default to filename (without .gd) | |
| 77 | if (result.classes.length > 0) { | |
| 78 | t.is(result.classes[0].name, 'util', 'class name defaults to filename') | |
| 79 | } | |
| 80 | }) | |
| 81 | ||
| 82 | test('gdscript: constructor (_init)', (t) => { | |
| 83 | const src = `class_name MyClass | |
| 84 | extends Node | |
| 85 | ||
| 86 | func _init(name: String) -> void: | |
| 87 | pass | |
| 88 | ||
| 89 | func do_thing(): | |
| 90 | pass | |
| 91 | ` | |
| 92 | ||
| 93 | const result = parseFile(src, 'my_class.gd') | |
| 94 | const cls = result.classes[0] | |
| 95 | t.ok(cls.constructor, 'has constructor') | |
| 96 | t.is(cls.constructor.params.length, 1, 'constructor param count') | |
| 97 | t.is(cls.methods.length, 1, '_init is not counted as a regular method') | |
| 98 | }) |
| … | … | @@ -0,0 +1,105 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { parseFile } from '../lib/parsers/glsl.js' | |
| 3 | ||
| 4 | test('glsl: compute shader with buffers and push constants', (t) => { | |
| 5 | const src = `#version 450 | |
| 6 | ||
| 7 | layout(local_size_x = 256) in; | |
| 8 | layout(set = 0, binding = 0, std430) readonly buffer DensityBuf { float density[]; }; | |
| 9 | layout(set = 0, binding = 1, std430) writeonly buffer EdgeBuf { uint edges[]; }; | |
| 10 | layout(push_constant) uniform PushConstants { uint grid_size; float iso_level; } pc; | |
| 11 | ||
| 12 | void main() { | |
| 13 | uint idx = 0u; | |
| 14 | } | |
| 15 | ` | |
| 16 | ||
| 17 | const result = parseFile(src, 'compute.glsl') | |
| 18 | t.is(result.error, undefined, 'no parse error') | |
| 19 | ||
| 20 | t.is(result.buffers.length, 2, '2 buffers') | |
| 21 | t.is(result.buffers[0].name, 'DensityBuf', 'first buffer name') | |
| 22 | t.ok(result.buffers[0].readonly, 'first buffer is readonly') | |
| 23 | t.ok(result.buffers[1].writeonly, 'second buffer is writeonly') | |
| 24 | t.is(result.buffers[0].binding, '0', 'binding captured') | |
| 25 | t.is(result.buffers[0].set, '0', 'set captured') | |
| 26 | ||
| 27 | t.is(result.pushConstants.length, 1, '1 push constant block') | |
| 28 | t.is(result.pushConstants[0].name, 'PushConstants', 'push constant name') | |
| 29 | ||
| 30 | t.ok(result.functions.find(f => f.name === 'main'), 'main function found') | |
| 31 | t.ok(result.exports.find(e => e.name === 'main'), 'main is exported (shader entry)') | |
| 32 | }) | |
| 33 | ||
| 34 | test('glsl: regular uniforms', (t) => { | |
| 35 | const src = `#version 330 | |
| 36 | ||
| 37 | uniform float u_time; | |
| 38 | uniform sampler2D u_texture; | |
| 39 | uniform vec3 u_color; | |
| 40 | ||
| 41 | void main() { } | |
| 42 | ` | |
| 43 | ||
| 44 | const result = parseFile(src, 'frag.glsl') | |
| 45 | t.is(result.uniforms.length, 3, '3 uniforms') | |
| 46 | const names = result.uniforms.map(u => u.name) | |
| 47 | t.ok(names.includes('u_time'), 'u_time uniform') | |
| 48 | t.ok(names.includes('u_texture'), 'u_texture uniform') | |
| 49 | t.ok(names.includes('u_color'), 'u_color uniform') | |
| 50 | }) | |
| 51 | ||
| 52 | test('glsl: #define becomes constant', (t) => { | |
| 53 | const src = `#define THREADS 256 | |
| 54 | #define MAX_ITERATIONS 100 | |
| 55 | ||
| 56 | void main() { } | |
| 57 | ` | |
| 58 | ||
| 59 | const result = parseFile(src, 'compute.glsl') | |
| 60 | const names = result.constants.map(c => c.name) | |
| 61 | t.ok(names.includes('THREADS'), 'THREADS define captured') | |
| 62 | t.ok(names.includes('MAX_ITERATIONS'), 'MAX_ITERATIONS define captured') | |
| 63 | }) | |
| 64 | ||
| 65 | test('glsl: struct becomes a class with kind=struct', (t) => { | |
| 66 | const src = `struct Vertex { | |
| 67 | vec3 position; | |
| 68 | vec3 normal; | |
| 69 | vec2 uv; | |
| 70 | }; | |
| 71 | ||
| 72 | void main() { } | |
| 73 | ` | |
| 74 | ||
| 75 | const result = parseFile(src, 'vert.glsl') | |
| 76 | t.is(result.classes.length, 1, '1 struct') | |
| 77 | t.is(result.classes[0].name, 'Vertex', 'struct name') | |
| 78 | t.is(result.classes[0].kind, 'struct', 'kind is struct') | |
| 79 | }) | |
| 80 | ||
| 81 | test('glsl: Godot .gdshader hint syntax is stripped', (t) => { | |
| 82 | const src = `shader_type spatial; | |
| 83 | render_mode unshaded, cull_disabled; | |
| 84 | ||
| 85 | uniform float density_scale : hint_range(0.0, 20.0) = 8.0; | |
| 86 | uniform sampler3D cloud_density : filter_linear_mipmap, repeat_enable; | |
| 87 | ||
| 88 | void fragment() { | |
| 89 | ALBEDO = vec3(1.0); | |
| 90 | } | |
| 91 | ` | |
| 92 | ||
| 93 | const result = parseFile(src, 'cloud.gdshader') | |
| 94 | t.is(result.error, undefined, 'no parse error after hint stripping') | |
| 95 | t.is(result.uniforms.length, 2, '2 uniforms despite hints') | |
| 96 | t.ok(result.functions.find(f => f.name === 'fragment'), 'fragment function') | |
| 97 | }) | |
| 98 | ||
| 99 | test('glsl: parse error returns empty structure (no crash)', (t) => { | |
| 100 | const src = `this is not valid glsl !!!` | |
| 101 | const result = parseFile(src, 'broken.glsl') | |
| 102 | t.ok(result.error, 'error reported') | |
| 103 | t.is(result.functions.length, 0, 'functions is still an empty array') | |
| 104 | t.is(result.classes.length, 0, 'classes is still an empty array') | |
| 105 | }) |
| … | … | @@ -0,0 +1,115 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { mkdirSync, writeFileSync, rmSync, existsSync } from 'fs' | |
| 3 | import { join, dirname, resolve } from 'path' | |
| 4 | import { fileURLToPath } from 'url' | |
| 5 | import { buildIgnoreMatcher } from '../lib/ignore.js' | |
| 6 | ||
| 7 | const HERE = dirname(fileURLToPath(import.meta.url)) | |
| 8 | const FIXTURE = resolve(HERE, 'fixtures-ignore') | |
| 9 | ||
| 10 | function setupFixture () { | |
| 11 | if (existsSync(FIXTURE)) rmSync(FIXTURE, { recursive: true, force: true }) | |
| 12 | mkdirSync(FIXTURE, { recursive: true }) | |
| 13 | return FIXTURE | |
| 14 | } | |
| 15 | ||
| 16 | function mk (root, relPath, content = '') { | |
| 17 | const full = join(root, relPath) | |
| 18 | mkdirSync(dirname(full), { recursive: true }) | |
| 19 | writeFileSync(full, content) | |
| 20 | return full | |
| 21 | } | |
| 22 | ||
| 23 | test('ignore: built-in defaults skip node_modules/.git/vendor/etc', (t) => { | |
| 24 | const root = setupFixture() | |
| 25 | const ignore = buildIgnoreMatcher(root) | |
| 26 | ||
| 27 | t.ok(ignore(join(root, 'node_modules')), 'node_modules hidden') | |
| 28 | t.ok(ignore(join(root, 'node_modules/foo/index.js')), 'file under node_modules hidden') | |
| 29 | t.ok(ignore(join(root, '.git/HEAD')), '.git contents hidden') | |
| 30 | t.ok(ignore(join(root, 'vendor')), 'vendor hidden') | |
| 31 | t.ok(ignore(join(root, 'build/output.js')), 'build hidden') | |
| 32 | t.absent(ignore(join(root, 'src/index.js')), 'src/ not hidden') | |
| 33 | ||
| 34 | rmSync(root, { recursive: true, force: true }) | |
| 35 | }) | |
| 36 | ||
| 37 | test('ignore: .codetreeignore file at rootDir', (t) => { | |
| 38 | const root = setupFixture() | |
| 39 | mk(root, '.codetreeignore', '# comment line\nsecrets\nclients/*.key\nbackup/\n') | |
| 40 | const ignore = buildIgnoreMatcher(root) | |
| 41 | ||
| 42 | t.ok(ignore(join(root, 'secrets')), 'pattern "secrets" hides dir') | |
| 43 | t.ok(ignore(join(root, 'foo/secrets/bar.txt')), 'name pattern matches at any depth') | |
| 44 | t.ok(ignore(join(root, 'clients/acme.key')), 'glob pattern works') | |
| 45 | t.ok(ignore(join(root, 'backup')), 'trailing-slash dir pattern') | |
| 46 | t.absent(ignore(join(root, 'public/index.html')), 'unrelated path not hidden') | |
| 47 | t.absent(ignore(join(root, 'clients/readme.md')), 'non-matching glob not hidden') | |
| 48 | ||
| 49 | rmSync(root, { recursive: true, force: true }) | |
| 50 | }) | |
| 51 | ||
| 52 | test('ignore: .codetree-private marker hides whole subtree', (t) => { | |
| 53 | const root = setupFixture() | |
| 54 | mk(root, 'public/foo.js') | |
| 55 | mk(root, 'private-work/.codetree-private') | |
| 56 | mk(root, 'private-work/src/secret.js') | |
| 57 | mk(root, 'private-work/docs/plan.md') | |
| 58 | ||
| 59 | const ignore = buildIgnoreMatcher(root) | |
| 60 | ||
| 61 | t.absent(ignore(join(root, 'public/foo.js')), 'public path visible') | |
| 62 | t.ok(ignore(join(root, 'private-work')), 'marked dir itself hidden') | |
| 63 | t.ok(ignore(join(root, 'private-work/src/secret.js')), 'file deep under marker hidden') | |
| 64 | t.ok(ignore(join(root, 'private-work/docs/plan.md')), 'another file deep under marker hidden') | |
| 65 | ||
| 66 | rmSync(root, { recursive: true, force: true }) | |
| 67 | }) | |
| 68 | ||
| 69 | test('ignore: --ignore flag patterns', (t) => { | |
| 70 | const root = setupFixture() | |
| 71 | const ignore = buildIgnoreMatcher(root, ['my-custom', 'tmp-*']) | |
| 72 | ||
| 73 | t.ok(ignore(join(root, 'my-custom')), 'extra pattern applied') | |
| 74 | t.ok(ignore(join(root, 'some/path/my-custom')), 'extra pattern matches at any depth') | |
| 75 | t.ok(ignore(join(root, 'tmp-scratch')), 'glob in extra pattern works') | |
| 76 | t.absent(ignore(join(root, 'normal')), 'unrelated not hidden') | |
| 77 | ||
| 78 | rmSync(root, { recursive: true, force: true }) | |
| 79 | }) | |
| 80 | ||
| 81 | test('ignore: .codetreeignore + --ignore stack', (t) => { | |
| 82 | const root = setupFixture() | |
| 83 | mk(root, '.codetreeignore', 'from-file\n') | |
| 84 | const ignore = buildIgnoreMatcher(root, ['from-flag']) | |
| 85 | ||
| 86 | t.ok(ignore(join(root, 'from-file')), 'file pattern applied') | |
| 87 | t.ok(ignore(join(root, 'from-flag')), 'flag pattern applied') | |
| 88 | t.ok(ignore(join(root, 'node_modules')), 'built-in still applied') | |
| 89 | ||
| 90 | rmSync(root, { recursive: true, force: true }) | |
| 91 | }) | |
| 92 | ||
| 93 | test('ignore: anchored / pattern matches only at root', (t) => { | |
| 94 | const root = setupFixture() | |
| 95 | mk(root, '.codetreeignore', '/top-only\n') | |
| 96 | const ignore = buildIgnoreMatcher(root) | |
| 97 | ||
| 98 | t.ok(ignore(join(root, 'top-only')), 'anchored matches at root') | |
| 99 | t.ok(ignore(join(root, 'top-only/child.js')), 'contents under anchored also hidden') | |
| 100 | t.absent(ignore(join(root, 'nested/top-only')), 'anchored does NOT match deeper') | |
| 101 | ||
| 102 | rmSync(root, { recursive: true, force: true }) | |
| 103 | }) | |
| 104 | ||
| 105 | test('ignore: comments and blank lines in .codetreeignore', (t) => { | |
| 106 | const root = setupFixture() | |
| 107 | mk(root, '.codetreeignore', '# this is a comment\n\n \nlegit\n') | |
| 108 | const ignore = buildIgnoreMatcher(root) | |
| 109 | ||
| 110 | t.ok(ignore(join(root, 'legit')), 'valid pattern applied') | |
| 111 | t.absent(ignore(join(root, '# this is a comment')), 'comments not treated as patterns') | |
| 112 | t.absent(ignore(join(root, 'unrelated')), 'unrelated not hidden') | |
| 113 | ||
| 114 | rmSync(root, { recursive: true, force: true }) | |
| 115 | }) |
| … | … | @@ -0,0 +1,85 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { writeFileSync, mkdirSync, rmSync, existsSync } from 'fs' | |
| 3 | import { join, resolve, dirname } from 'path' | |
| 4 | import { fileURLToPath } from 'url' | |
| 5 | import { LiveStore } from '../lib/live-store.js' | |
| 6 | import { scanStream } from '../lib/scan-stream.js' | |
| 7 | import { TreeReducer } from '../lib/reducers/tree-reducer.js' | |
| 8 | ||
| 9 | const HERE = dirname(fileURLToPath(import.meta.url)) | |
| 10 | const FIXTURE = resolve(HERE, 'fixtures-live') | |
| 11 | ||
| 12 | function setup () { | |
| 13 | if (existsSync(FIXTURE)) rmSync(FIXTURE, { recursive: true, force: true }) | |
| 14 | mkdirSync(FIXTURE, { recursive: true }) | |
| 15 | writeFileSync(join(FIXTURE, 'package.json'), JSON.stringify({ name: 'fixture-live', version: '0.1.0', main: 'index.js' })) | |
| 16 | writeFileSync(join(FIXTURE, 'index.js'), 'export const x = 1\n') | |
| 17 | } | |
| 18 | ||
| 19 | async function buildGraph () { | |
| 20 | return new Promise((resolveP, reject) => { | |
| 21 | const src = scanStream(FIXTURE) | |
| 22 | const tree = new TreeReducer().attach(src) | |
| 23 | src.once('scan-end', () => resolveP(tree.finalize())) | |
| 24 | src.once('error', reject) | |
| 25 | }) | |
| 26 | } | |
| 27 | ||
| 28 | test('live-store: subscribe receives current state on attach', async (t) => { | |
| 29 | setup() | |
| 30 | const graph = await buildGraph() | |
| 31 | const store = new LiveStore(graph, { watch: false }) | |
| 32 | store.seedFromGraph() | |
| 33 | ||
| 34 | const events = [] | |
| 35 | store.subscribe(ev => events.push(ev.type)) | |
| 36 | ||
| 37 | t.is(events[0], 'scan-start', 'first replayed event is scan-start') | |
| 38 | t.ok(events.includes('module-start'), 'module-start replayed') | |
| 39 | t.ok(events.includes('file-discovered'), 'file-discovered replayed') | |
| 40 | t.ok(events.includes('file-parsed'), 'file-parsed replayed') | |
| 41 | t.is(events[events.length - 1], 'scan-end', 'last replayed event is scan-end') | |
| 42 | ||
| 43 | store.stop() | |
| 44 | rmSync(FIXTURE, { recursive: true, force: true }) | |
| 45 | }) | |
| 46 | ||
| 47 | test('live-store: late subscribers also get full state', async (t) => { | |
| 48 | setup() | |
| 49 | const graph = await buildGraph() | |
| 50 | const store = new LiveStore(graph, { watch: false }) | |
| 51 | store.seedFromGraph() | |
| 52 | ||
| 53 | // First subscriber | |
| 54 | const first = [] | |
| 55 | store.subscribe(ev => first.push(ev.type)) | |
| 56 | ||
| 57 | // Second subscriber attaches AFTER seeding — must still get the full replay | |
| 58 | const second = [] | |
| 59 | store.subscribe(ev => second.push(ev.type)) | |
| 60 | ||
| 61 | t.is(first.length, second.length, 'both subscribers see same number of events') | |
| 62 | t.alike(first, second, 'event sequences match') | |
| 63 | ||
| 64 | store.stop() | |
| 65 | rmSync(FIXTURE, { recursive: true, force: true }) | |
| 66 | }) | |
| 67 | ||
| 68 | test('live-store: module-start payload uses moduleType not type for JS module flavor', async (t) => { | |
| 69 | setup() | |
| 70 | const graph = await buildGraph() | |
| 71 | const store = new LiveStore(graph, { watch: false }) | |
| 72 | store.seedFromGraph() | |
| 73 | ||
| 74 | let modStart = null | |
| 75 | store.subscribe(ev => { | |
| 76 | if (ev.type === 'module-start' && !modStart) modStart = ev | |
| 77 | }) | |
| 78 | ||
| 79 | t.ok(modStart, 'got module-start event') | |
| 80 | t.is(modStart.type, 'module-start', 'event type is preserved (no name collision)') | |
| 81 | t.ok('moduleType' in modStart, 'JS module type carried as moduleType field') | |
| 82 | ||
| 83 | store.stop() | |
| 84 | rmSync(FIXTURE, { recursive: true, force: true }) | |
| 85 | }) |
| … | … | @@ -0,0 +1,256 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { readFileSync } from 'fs' | |
| 3 | import { resolve, dirname } from 'path' | |
| 4 | import { fileURLToPath } from 'url' | |
| 5 | import { parseFile } from '../lib/parsers/js.js' | |
| 6 | ||
| 7 | const HERE = dirname(fileURLToPath(import.meta.url)) | |
| 8 | const ROOT = resolve(HERE, '../../') | |
| 9 | ||
| 10 | function readSource (rel) { | |
| 11 | return readFileSync(resolve(ROOT, rel), 'utf-8') | |
| 12 | } | |
| 13 | ||
| 14 | test('parser: hyper-orgs/index.js re-exports', (t) => { | |
| 15 | const source = readSource('hyper-orgs/index.js') | |
| 16 | const result = parseFile(source, 'hyper-orgs/index.js') | |
| 17 | ||
| 18 | t.absent(result.error, 'no parse error') | |
| 19 | t.is(result.exports.length, 4, '4 re-exports') | |
| 20 | ||
| 21 | const names = result.exports.map(e => e.name) | |
| 22 | t.ok(names.includes('HyperOrgs'), 'exports HyperOrgs') | |
| 23 | t.ok(names.includes('orgsSchema'), 'exports orgsSchema') | |
| 24 | t.ok(names.includes('RESERVED_NAMES'), 'exports RESERVED_NAMES') | |
| 25 | t.ok(names.includes('validateName'), 'exports validateName') | |
| 26 | ||
| 27 | // All are re-exports from other files | |
| 28 | const hyperOrgsExport = result.exports.find(e => e.name === 'HyperOrgs') | |
| 29 | t.is(hyperOrgsExport.from, './lib/hyper-orgs.js', 'HyperOrgs from lib/hyper-orgs.js') | |
| 30 | ||
| 31 | const schemaExports = result.exports.filter(e => e.from === './lib/schema.js') | |
| 32 | t.is(schemaExports.length, 3, '3 exports from schema.js') | |
| 33 | }) | |
| 34 | ||
| 35 | test('parser: hyper-orgs/lib/hyper-orgs.js class structure', (t) => { | |
| 36 | const source = readSource('hyper-orgs/lib/hyper-orgs.js') | |
| 37 | const result = parseFile(source, 'hyper-orgs/lib/hyper-orgs.js') | |
| 38 | ||
| 39 | t.absent(result.error, 'no parse error') | |
| 40 | ||
| 41 | // Imports | |
| 42 | t.is(result.imports.length, 2, '2 imports') | |
| 43 | const roomImport = result.imports.find(i => i.specifier === 'hyper-rooms') | |
| 44 | t.ok(roomImport, 'imports from hyper-rooms') | |
| 45 | t.ok(roomImport.names.includes('Room'), 'imports Room') | |
| 46 | ||
| 47 | const schemaImport = result.imports.find(i => i.specifier === './schema.js') | |
| 48 | t.ok(schemaImport, 'imports from ./schema.js') | |
| 49 | ||
| 50 | // Exports | |
| 51 | t.is(result.exports.length, 1, '1 export') | |
| 52 | t.is(result.exports[0].name, 'HyperOrgs', 'exports HyperOrgs') | |
| 53 | t.is(result.exports[0].type, 'class', 'export type is class') | |
| 54 | ||
| 55 | // Class | |
| 56 | t.is(result.classes.length, 1, '1 class') | |
| 57 | const cls = result.classes[0] | |
| 58 | t.is(cls.name, 'HyperOrgs', 'class name') | |
| 59 | t.absent(cls.extends, 'does not extend anything') | |
| 60 | ||
| 61 | // Constructor | |
| 62 | t.ok(cls.constructor, 'has constructor') | |
| 63 | t.is(cls.constructor.params.length, 2, 'constructor has 2 params') | |
| 64 | t.is(cls.constructor.params[0], 'corestore', 'first param is corestore') | |
| 65 | t.is(cls.constructor.params[1], 'options', 'second param is options') | |
| 66 | t.ok(cls.constructor.jsdoc, 'constructor has JSDoc') | |
| 67 | ||
| 68 | // Methods | |
| 69 | const methodNames = cls.methods.map(m => m.name) | |
| 70 | t.ok(methodNames.includes('ready'), 'has ready()') | |
| 71 | t.ok(methodNames.includes('create'), 'has create()') | |
| 72 | t.ok(methodNames.includes('get'), 'has get()') | |
| 73 | t.ok(methodNames.includes('update'), 'has update()') | |
| 74 | t.ok(methodNames.includes('delete'), 'has delete()') | |
| 75 | t.ok(methodNames.includes('list'), 'has list()') | |
| 76 | t.ok(methodNames.includes('checkAccess'), 'has checkAccess()') | |
| 77 | t.ok(methodNames.includes('addMember'), 'has addMember()') | |
| 78 | t.ok(methodNames.includes('addResource'), 'has addResource()') | |
| 79 | t.ok(methodNames.includes('createGrant'), 'has createGrant()') | |
| 80 | t.ok(methodNames.includes('createInvite'), 'has createInvite()') | |
| 81 | t.ok(methodNames.includes('addWriter'), 'has addWriter()') | |
| 82 | ||
| 83 | // Async methods | |
| 84 | const createMethod = cls.methods.find(m => m.name === 'create') | |
| 85 | t.ok(createMethod.async, 'create is async') | |
| 86 | t.is(createMethod.params.length, 3, 'create has 3 params') | |
| 87 | t.is(createMethod.params[0], 'name', 'create param 1: name') | |
| 88 | t.is(createMethod.params[1], 'type', 'create param 2: type') | |
| 89 | t.is(createMethod.params[2], 'data', 'create param 3: data') | |
| 90 | ||
| 91 | // Getters | |
| 92 | const getterNames = cls.getters.map(g => g.name) | |
| 93 | t.ok(getterNames.includes('key'), 'has key getter') | |
| 94 | t.ok(getterNames.includes('keyHex'), 'has keyHex getter') | |
| 95 | t.ok(getterNames.includes('writable'), 'has writable getter') | |
| 96 | t.ok(getterNames.includes('view'), 'has view getter') | |
| 97 | t.ok(getterNames.includes('base'), 'has base getter') | |
| 98 | t.ok(getterNames.includes('room'), 'has room getter') | |
| 99 | ||
| 100 | // State | |
| 101 | t.ok(result.state.includes('_room'), 'has _room state') | |
| 102 | ||
| 103 | // Delegation | |
| 104 | t.ok(result.delegates.length > 0, 'has delegation patterns') | |
| 105 | const roomDelegate = result.delegates.find(d => d.field === '_room') | |
| 106 | t.ok(roomDelegate, 'delegates to _room') | |
| 107 | t.ok(roomDelegate.methods.includes('ready'), 'delegates ready to _room') | |
| 108 | t.ok(roomDelegate.methods.includes('close'), 'delegates close to _room') | |
| 109 | ||
| 110 | // Error contracts | |
| 111 | t.ok(result.errorContracts.length > 0, 'has error contracts') | |
| 112 | }) | |
| 113 | ||
| 114 | test('parser: pear-git-v3 handler factory pattern', (t) => { | |
| 115 | const source = readSource('pear-git-v3/lib/handlers/orgs.js') | |
| 116 | const result = parseFile(source, 'pear-git-v3/lib/handlers/orgs.js') | |
| 117 | ||
| 118 | t.absent(result.error, 'no parse error') | |
| 119 | ||
| 120 | // Should have an exported function (the handler factory) | |
| 121 | const exportedFns = result.exports.filter(e => e.type === 'function') | |
| 122 | t.ok(exportedFns.length > 0, 'has exported function(s)') | |
| 123 | }) | |
| 124 | ||
| 125 | test('parser: CJS module (hyper-sync)', (t) => { | |
| 126 | const source = readSource('hyper-sync/index.js') | |
| 127 | const result = parseFile(source, 'hyper-sync/index.js') | |
| 128 | ||
| 129 | t.absent(result.error, 'no parse error') | |
| 130 | ||
| 131 | // Should detect CJS exports | |
| 132 | const hasExport = result.exports.length > 0 | |
| 133 | t.ok(hasExport, 'detected CJS exports') | |
| 134 | ||
| 135 | // Should detect a class | |
| 136 | t.ok(result.classes.length > 0, 'found class(es)') | |
| 137 | }) | |
| 138 | ||
| 139 | test('parser: JSDoc comment attachment', (t) => { | |
| 140 | const source = ` | |
| 141 | /** | |
| 142 | * Does something useful. | |
| 143 | * @param {string} name - the name | |
| 144 | * @returns {boolean} | |
| 145 | */ | |
| 146 | export function doSomething (name) { | |
| 147 | return true | |
| 148 | } | |
| 149 | ||
| 150 | /** | |
| 151 | * A useful class. | |
| 152 | */ | |
| 153 | export class MyClass { | |
| 154 | /** | |
| 155 | * Create one. | |
| 156 | * @param {object} opts | |
| 157 | */ | |
| 158 | constructor (opts) { | |
| 159 | this._opts = opts | |
| 160 | } | |
| 161 | ||
| 162 | /** | |
| 163 | * Run it. | |
| 164 | * @param {number} n | |
| 165 | */ | |
| 166 | async run (n) { | |
| 167 | return n | |
| 168 | } | |
| 169 | } | |
| 170 | ` | |
| 171 | const result = parseFile(source, 'test.js') | |
| 172 | ||
| 173 | t.absent(result.error, 'no parse error') | |
| 174 | ||
| 175 | const fn = result.functions.find(f => f.name === 'doSomething') | |
| 176 | t.ok(fn, 'found doSomething') | |
| 177 | t.ok(fn.jsdoc, 'function has JSDoc') | |
| 178 | t.ok(fn.jsdoc.includes('@param'), 'JSDoc has @param') | |
| 179 | ||
| 180 | const cls = result.classes.find(c => c.name === 'MyClass') | |
| 181 | t.ok(cls, 'found MyClass') | |
| 182 | t.ok(cls.jsdoc, 'class has JSDoc') | |
| 183 | t.ok(cls.constructor.jsdoc, 'constructor has JSDoc') | |
| 184 | ||
| 185 | const runMethod = cls.methods.find(m => m.name === 'run') | |
| 186 | t.ok(runMethod, 'found run method') | |
| 187 | t.ok(runMethod.jsdoc, 'method has JSDoc') | |
| 188 | }) | |
| 189 | ||
| 190 | test('parser: destructured params', (t) => { | |
| 191 | const source = ` | |
| 192 | export function handler ({ name, type, ...rest }) { | |
| 193 | return { name, type } | |
| 194 | } | |
| 195 | ||
| 196 | export function multi (a, [b, c], { d }) { | |
| 197 | return a | |
| 198 | } | |
| 199 | ` | |
| 200 | const result = parseFile(source, 'test.js') | |
| 201 | ||
| 202 | const handler = result.functions.find(f => f.name === 'handler') | |
| 203 | t.ok(handler, 'found handler') | |
| 204 | t.is(handler.params[0], '{ name, type, ...rest }', 'destructured params preserved') | |
| 205 | ||
| 206 | const multi = result.functions.find(f => f.name === 'multi') | |
| 207 | t.ok(multi, 'found multi') | |
| 208 | t.is(multi.params[0], 'a', 'simple param') | |
| 209 | t.is(multi.params[1], '[b, c]', 'array destructured') | |
| 210 | t.is(multi.params[2], '{ d }', 'object destructured') | |
| 211 | }) | |
| 212 | ||
| 213 | test('parser: arrow functions as const', (t) => { | |
| 214 | const source = ` | |
| 215 | export const add = (a, b) => a + b | |
| 216 | export const fetchData = async (url) => { | |
| 217 | return fetch(url) | |
| 218 | } | |
| 219 | ` | |
| 220 | const result = parseFile(source, 'test.js') | |
| 221 | ||
| 222 | t.is(result.functions.length, 2, '2 functions') | |
| 223 | ||
| 224 | const add = result.functions.find(f => f.name === 'add') | |
| 225 | t.ok(add, 'found add') | |
| 226 | t.ok(add.arrow, 'is arrow function') | |
| 227 | t.is(add.params.length, 2, '2 params') | |
| 228 | ||
| 229 | const fetchData = result.functions.find(f => f.name === 'fetchData') | |
| 230 | t.ok(fetchData, 'found fetchData') | |
| 231 | t.ok(fetchData.async, 'is async') | |
| 232 | t.ok(fetchData.arrow, 'is arrow function') | |
| 233 | }) | |
| 234 | ||
| 235 | test('parser: error contracts from template literals', (t) => { | |
| 236 | const source = ` | |
| 237 | export function validate (name) { | |
| 238 | if (!name) throw new Error('Name is required') | |
| 239 | if (name.length > 64) throw new Error(\`Name too long: \${name.length}\`) | |
| 240 | } | |
| 241 | ` | |
| 242 | const result = parseFile(source, 'test.js') | |
| 243 | ||
| 244 | t.is(result.errorContracts.length, 2, '2 error contracts') | |
| 245 | t.is(result.errorContracts[0], 'Name is required', 'literal error') | |
| 246 | t.ok(result.errorContracts[1].includes('Name too long'), 'template error') | |
| 247 | }) | |
| 248 | ||
| 249 | test('parser: export all (*)', (t) => { | |
| 250 | const source = `export * from './utils.js'` | |
| 251 | const result = parseFile(source, 'test.js') | |
| 252 | ||
| 253 | t.is(result.exports.length, 1, '1 export') | |
| 254 | t.is(result.exports[0].name, '*', 'star export') | |
| 255 | t.is(result.exports[0].from, './utils.js', 'from source') | |
| 256 | }) |
| … | … | @@ -0,0 +1,134 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { resolve, dirname } from 'path' | |
| 3 | import { fileURLToPath } from 'url' | |
| 4 | import { scanStream } from '../lib/scan-stream.js' | |
| 5 | import { TreeReducer } from '../lib/reducers/tree-reducer.js' | |
| 6 | ||
| 7 | const HERE = dirname(fileURLToPath(import.meta.url)) | |
| 8 | const HYPER_FLEEKY = resolve(HERE, '../../') | |
| 9 | ||
| 10 | test('scan-stream: emits scan-start before any other event', async (t) => { | |
| 11 | const seen = [] | |
| 12 | const target = resolve(HYPER_FLEEKY, 'hyper-orgs') | |
| 13 | await new Promise((resolveP, reject) => { | |
| 14 | const src = scanStream(target) | |
| 15 | for (const ev of ['scan-start', 'module-start', 'file-discovered', 'file-parsed', 'import-edge', 'module-end', 'scan-end']) { | |
| 16 | src.on(ev, () => { if (!seen.includes(ev)) seen.push(ev) }) | |
| 17 | } | |
| 18 | src.once('scan-end', resolveP) | |
| 19 | src.once('error', reject) | |
| 20 | }) | |
| 21 | ||
| 22 | t.is(seen[0], 'scan-start', 'scan-start fires first') | |
| 23 | t.ok(seen.includes('module-start'), 'module-start fired') | |
| 24 | t.ok(seen.includes('file-discovered'), 'file-discovered fired') | |
| 25 | t.ok(seen.includes('file-parsed'), 'file-parsed fired') | |
| 26 | t.is(seen[seen.length - 1], 'scan-end', 'scan-end fires last') | |
| 27 | }) | |
| 28 | ||
| 29 | test('scan-stream: caller can attach listeners before walk starts', async (t) => { | |
| 30 | // The walk is deferred via queueMicrotask, so listeners attached synchronously | |
| 31 | // after scanStream() returns must still see scan-start. | |
| 32 | const src = scanStream(resolve(HYPER_FLEEKY, 'hyper-orgs')) | |
| 33 | let gotStart = false | |
| 34 | ||
| 35 | await new Promise((resolve) => { | |
| 36 | src.on('scan-start', () => { gotStart = true }) | |
| 37 | src.once('scan-end', resolve) | |
| 38 | }) | |
| 39 | ||
| 40 | t.ok(gotStart, 'listeners attached after scanStream() still see scan-start') | |
| 41 | }) | |
| 42 | ||
| 43 | test('scan-stream: TreeReducer rebuilds the same shape as walkGraph', async (t) => { | |
| 44 | const target = resolve(HYPER_FLEEKY, 'hyper-orgs') | |
| 45 | const graph = await new Promise((resolveP, reject) => { | |
| 46 | const src = scanStream(target) | |
| 47 | const tree = new TreeReducer().attach(src) | |
| 48 | src.once('scan-end', () => resolveP(tree.finalize())) | |
| 49 | src.once('error', reject) | |
| 50 | }) | |
| 51 | ||
| 52 | t.ok(graph.modules.size === 1, '1 module') | |
| 53 | t.ok(graph.modules.has('hyper-orgs'), 'has hyper-orgs') | |
| 54 | t.ok(graph.root.endsWith('hyper-orgs'), 'root is correct') | |
| 55 | t.is(graph.projectType, 'js', 'project type detected') | |
| 56 | ||
| 57 | const mod = graph.modules.get('hyper-orgs') | |
| 58 | t.ok(mod.entry, 'has entry') | |
| 59 | t.ok(mod.files.size > 0, 'has files') | |
| 60 | }) | |
| 61 | ||
| 62 | test('scan-stream: multiple subscribers see the same events', async (t) => { | |
| 63 | let aCount = 0 | |
| 64 | let bCount = 0 | |
| 65 | ||
| 66 | const target = resolve(HYPER_FLEEKY, 'hyper-orgs') | |
| 67 | await new Promise((resolveP) => { | |
| 68 | const src = scanStream(target) | |
| 69 | src.on('file-discovered', () => aCount++) | |
| 70 | src.on('file-discovered', () => bCount++) | |
| 71 | src.once('scan-end', resolveP) | |
| 72 | }) | |
| 73 | ||
| 74 | t.is(aCount, bCount, 'both subscribers received same number of events') | |
| 75 | t.ok(aCount > 0, 'at least one file event fired') | |
| 76 | }) | |
| 77 | ||
| 78 | test('scan-stream: shallow mode skips internal files and import resolution', async (t) => { | |
| 79 | // hyper-orgs has several files in lib/; shallow mode should only emit events | |
| 80 | // for the entry file (index.js) and emit no import edges. | |
| 81 | const target = resolve(HYPER_FLEEKY, 'hyper-orgs') | |
| 82 | const discoveredFiles = [] | |
| 83 | const edges = [] | |
| 84 | let shallowFlag = null | |
| 85 | ||
| 86 | await new Promise((resolveP) => { | |
| 87 | const src = scanStream(target, { shallow: true }) | |
| 88 | src.on('scan-start', e => { shallowFlag = e.shallow }) | |
| 89 | src.on('file-discovered', e => discoveredFiles.push(e.relInPkg)) | |
| 90 | src.on('import-edge', e => edges.push(e)) | |
| 91 | src.once('scan-end', resolveP) | |
| 92 | }) | |
| 93 | ||
| 94 | t.is(shallowFlag, true, 'scan-start carries shallow: true') | |
| 95 | t.is(edges.length, 0, 'no import edges in shallow mode') | |
| 96 | t.ok(discoveredFiles.length <= 2, `at most 2 files discovered (got ${discoveredFiles.length}: ${discoveredFiles.join(', ')})`) | |
| 97 | // The entry file should be among the discovered files | |
| 98 | t.ok(discoveredFiles.some(f => f === 'index.js'), 'entry file (index.js) discovered') | |
| 99 | }) | |
| 100 | ||
| 101 | test('scan-stream: shallow mode is fast on a multi-module scan', async (t) => { | |
| 102 | // Rough timing assertion — shallow scans of a multi-project root should | |
| 103 | // complete in well under 10s. This is the whole reason shallow exists. | |
| 104 | const start = Date.now() | |
| 105 | let moduleCount = 0 | |
| 106 | ||
| 107 | await new Promise((resolveP) => { | |
| 108 | const src = scanStream(HYPER_FLEEKY, { shallow: true, maxDepth: 1 }) | |
| 109 | src.on('module-start', () => moduleCount++) | |
| 110 | src.once('scan-end', resolveP) | |
| 111 | }) | |
| 112 | ||
| 113 | const duration = Date.now() - start | |
| 114 | t.ok(moduleCount > 10, `found ${moduleCount} modules`) | |
| 115 | t.ok(duration < 10000, `shallow scan completed in ${duration}ms (< 10s)`) | |
| 116 | }) | |
| 117 | ||
| 118 | test('scan-stream: emits import-edge events for resolved local imports', async (t) => { | |
| 119 | const edges = [] | |
| 120 | ||
| 121 | const target = resolve(HYPER_FLEEKY, 'hyper-orgs') | |
| 122 | await new Promise((resolveP) => { | |
| 123 | const src = scanStream(target) | |
| 124 | src.on('import-edge', e => edges.push(e)) | |
| 125 | src.once('scan-end', resolveP) | |
| 126 | }) | |
| 127 | ||
| 128 | t.ok(edges.length > 0, `at least one import edge (got ${edges.length})`) | |
| 129 | for (const e of edges) { | |
| 130 | t.ok(e.fromRelInPkg, 'edge has from') | |
| 131 | t.ok(e.resolvedRelPath, 'edge has resolved path') | |
| 132 | t.ok(e.specifier, 'edge has specifier') | |
| 133 | } | |
| 134 | }) |
| … | … | @@ -0,0 +1,97 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { resolve, dirname } from 'path' | |
| 3 | import { fileURLToPath } from 'url' | |
| 4 | import { walkGraph } from '../lib/traverse.js' | |
| 5 | ||
| 6 | const HERE = dirname(fileURLToPath(import.meta.url)) | |
| 7 | const HYPER_FLEEKY = resolve(HERE, '../../') | |
| 8 | ||
| 9 | test('traverse: hyper-orgs module', async (t) => { | |
| 10 | const graph = await walkGraph(resolve(HYPER_FLEEKY, 'hyper-orgs')) | |
| 11 | ||
| 12 | t.is(graph.modules.size, 1, '1 module found') | |
| 13 | t.ok(graph.modules.has('hyper-orgs'), 'found hyper-orgs') | |
| 14 | ||
| 15 | const mod = graph.modules.get('hyper-orgs') | |
| 16 | t.is(mod.version, '0.2.0', 'correct version') | |
| 17 | t.ok(mod.entry.endsWith('index.js'), 'entry is index.js') | |
| 18 | t.ok(mod.dependencies['hyper-rooms'], 'depends on hyper-rooms') | |
| 19 | t.is(mod.testCommand, 'brittle test/*.test.js', 'test command') | |
| 20 | t.is(mod.type, 'module', 'ESM module') | |
| 21 | ||
| 22 | // Files | |
| 23 | t.ok(mod.files.has('index.js'), 'has index.js') | |
| 24 | t.ok(mod.files.has('lib/hyper-orgs.js'), 'has lib/hyper-orgs.js') | |
| 25 | t.ok(mod.files.has('lib/schema.js'), 'has lib/schema.js') | |
| 26 | ||
| 27 | // File is parsed (source no longer retained — see TreeReducer.onFileDiscovered) | |
| 28 | const indexFile = mod.files.get('index.js') | |
| 29 | t.ok(indexFile.parsed, 'index.js has parsed result') | |
| 30 | t.ok(indexFile.parsed.exports.length > 0, 'index.js has exports') | |
| 31 | }) | |
| 32 | ||
| 33 | test('traverse: hyper-orgs file relationships', async (t) => { | |
| 34 | const graph = await walkGraph(resolve(HYPER_FLEEKY, 'hyper-orgs')) | |
| 35 | const mod = graph.modules.get('hyper-orgs') | |
| 36 | ||
| 37 | // index.js imports from lib/ | |
| 38 | const indexFile = mod.files.get('index.js') | |
| 39 | t.ok(indexFile.localImports.length > 0, 'index.js has local imports') | |
| 40 | ||
| 41 | const importPaths = indexFile.localImports.map(i => i.specifier) | |
| 42 | t.ok(importPaths.includes('./lib/hyper-orgs.js'), 'imports from lib/hyper-orgs.js') | |
| 43 | t.ok(importPaths.includes('./lib/schema.js'), 'imports from lib/schema.js') | |
| 44 | ||
| 45 | // lib/hyper-orgs.js imports from schema.js | |
| 46 | const mainFile = mod.files.get('lib/hyper-orgs.js') | |
| 47 | const mainImports = mainFile.localImports.map(i => i.specifier) | |
| 48 | t.ok(mainImports.includes('./schema.js'), 'hyper-orgs.js imports schema.js') | |
| 49 | }) | |
| 50 | ||
| 51 | test('traverse: hyper-deploy import maps', async (t) => { | |
| 52 | const graph = await walkGraph(resolve(HYPER_FLEEKY, 'hyper-deploy')) | |
| 53 | ||
| 54 | t.ok(graph.modules.size >= 1, 'found module(s)') | |
| 55 | ||
| 56 | const mod = graph.modules.get('hyper-deploy') | |
| 57 | if (!mod) { | |
| 58 | // Might be named differently | |
| 59 | const first = graph.modules.values().next().value | |
| 60 | t.ok(first.importMaps, 'module has importMaps field') | |
| 61 | return | |
| 62 | } | |
| 63 | ||
| 64 | t.ok(mod.importMaps, 'has import maps') | |
| 65 | // hyper-deploy uses #fs, #path, #os import maps | |
| 66 | const hasImportMap = Object.keys(mod.importMaps).length > 0 | |
| 67 | t.ok(hasImportMap, 'import maps are populated') | |
| 68 | }) | |
| 69 | ||
| 70 | test('traverse: multi-module scan', async (t) => { | |
| 71 | // Scan a directory containing multiple modules | |
| 72 | const graph = await walkGraph(HYPER_FLEEKY, { maxDepth: 1 }) | |
| 73 | ||
| 74 | // Should find multiple modules | |
| 75 | t.ok(graph.modules.size > 5, `found ${graph.modules.size} modules`) | |
| 76 | ||
| 77 | // Check some known modules exist | |
| 78 | const names = Array.from(graph.modules.keys()) | |
| 79 | t.comment(`found modules: ${names.slice(0, 10).join(', ')}...`) | |
| 80 | ||
| 81 | // Each module should have files | |
| 82 | for (const [name, mod] of graph.modules) { | |
| 83 | t.ok(mod.files.size > 0, `${name} has ${mod.files.size} files`) | |
| 84 | } | |
| 85 | }) | |
| 86 | ||
| 87 | test('traverse: CJS module (hyper-sync)', async (t) => { | |
| 88 | const graph = await walkGraph(resolve(HYPER_FLEEKY, 'hyper-sync')) | |
| 89 | ||
| 90 | t.ok(graph.modules.size >= 1, 'found module') | |
| 91 | ||
| 92 | const mod = graph.modules.get('hyper-sync') | |
| 93 | if (mod) { | |
| 94 | t.is(mod.type, 'commonjs', 'detected as commonjs (no type field)') | |
| 95 | t.ok(mod.files.has('index.js'), 'has index.js') | |
| 96 | } | |
| 97 | }) |
| … | … | @@ -0,0 +1,126 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { resolve, dirname } from 'path' | |
| 3 | import { fileURLToPath } from 'url' | |
| 4 | import { scan } from '../lib/scanner.js' | |
| 5 | ||
| 6 | const HERE = dirname(fileURLToPath(import.meta.url)) | |
| 7 | const HYPER_FLEEKY = resolve(HERE, '../../') | |
| 8 | ||
| 9 | test('tree: single module (hyper-orgs)', async (t) => { | |
| 10 | const tree = await scan(resolve(HYPER_FLEEKY, 'hyper-orgs')) | |
| 11 | ||
| 12 | t.ok(tree.generated, 'has timestamp') | |
| 13 | t.ok(tree.root, 'has root path') | |
| 14 | ||
| 15 | // System level | |
| 16 | t.ok(tree.system.modules.includes('hyper-orgs'), 'module listed') | |
| 17 | t.ok(tree.system.dependencies['hyper-orgs'], 'has dependencies') | |
| 18 | ||
| 19 | // Module level | |
| 20 | const mod = tree.modules['hyper-orgs'] | |
| 21 | t.ok(mod, 'module entry exists') | |
| 22 | t.is(mod.name, 'hyper-orgs', 'correct name') | |
| 23 | t.is(mod.version, '0.2.0', 'correct version') | |
| 24 | t.is(mod.type, 'module', 'ESM') | |
| 25 | t.is(mod.entry, 'index.js', 'entry point') | |
| 26 | t.ok(mod.testCommand, 'has test command') | |
| 27 | ||
| 28 | // Public API | |
| 29 | t.ok(mod.publicAPI.includes('HyperOrgs'), 'public API has HyperOrgs') | |
| 30 | t.ok(mod.publicAPI.includes('orgsSchema'), 'public API has orgsSchema') | |
| 31 | t.ok(mod.publicAPI.includes('validateName'), 'public API has validateName') | |
| 32 | t.ok(mod.publicAPI.includes('RESERVED_NAMES'), 'public API has RESERVED_NAMES') | |
| 33 | ||
| 34 | // Files | |
| 35 | t.ok(mod.files['index.js'], 'has index.js') | |
| 36 | t.is(mod.files['index.js'].role, 'entry', 'index.js is entry') | |
| 37 | t.ok(mod.files['lib/hyper-orgs.js'], 'has lib/hyper-orgs.js') | |
| 38 | t.is(mod.files['lib/hyper-orgs.js'].role, 'lib', 'hyper-orgs.js is lib') | |
| 39 | t.ok(mod.files['lib/schema.js'], 'has lib/schema.js') | |
| 40 | t.is(mod.files['lib/schema.js'].role, 'schema', 'schema.js is schema') | |
| 41 | }) | |
| 42 | ||
| 43 | test('tree: file-level detail (hyper-orgs/lib/hyper-orgs.js)', async (t) => { | |
| 44 | const tree = await scan(resolve(HYPER_FLEEKY, 'hyper-orgs')) | |
| 45 | const file = tree.modules['hyper-orgs'].files['lib/hyper-orgs.js'] | |
| 46 | ||
| 47 | // Imports | |
| 48 | t.ok(file.imports.length > 0, 'has imports') | |
| 49 | const roomImport = file.imports.find(i => i.specifier === 'hyper-rooms') | |
| 50 | t.ok(roomImport, 'imports hyper-rooms') | |
| 51 | ||
| 52 | // Exports | |
| 53 | t.is(file.exports.length, 1, '1 export') | |
| 54 | t.is(file.exports[0].name, 'HyperOrgs', 'exports HyperOrgs') | |
| 55 | t.is(file.exports[0].type, 'class', 'type is class') | |
| 56 | ||
| 57 | // Class structure | |
| 58 | t.ok(file.classes, 'has classes') | |
| 59 | t.is(file.classes.length, 1, '1 class') | |
| 60 | ||
| 61 | const cls = file.classes[0] | |
| 62 | t.is(cls.name, 'HyperOrgs', 'class name') | |
| 63 | t.ok(cls.constructor, 'has constructor') | |
| 64 | t.ok(cls.methods.length > 10, `has ${cls.methods.length} methods`) | |
| 65 | t.ok(cls.getters.length > 3, `has ${cls.getters.length} getters`) | |
| 66 | ||
| 67 | // State and delegation | |
| 68 | t.ok(file.state, 'has state') | |
| 69 | t.ok(file.state.includes('_room'), 'state includes _room') | |
| 70 | t.ok(file.delegates, 'has delegates') | |
| 71 | t.ok(file.delegates.length > 0, 'has delegation patterns') | |
| 72 | ||
| 73 | // Error contracts | |
| 74 | t.ok(file.errorContracts, 'has error contracts') | |
| 75 | t.ok(file.errorContracts.length > 0, 'has specific errors') | |
| 76 | }) | |
| 77 | ||
| 78 | test('tree: multi-module scan with shared deps', async (t) => { | |
| 79 | const tree = await scan(HYPER_FLEEKY, { maxDepth: 1 }) | |
| 80 | ||
| 81 | // System level | |
| 82 | t.ok(tree.system.modules.length > 10, `${tree.system.modules.length} modules`) | |
| 83 | ||
| 84 | // Shared deps | |
| 85 | t.ok(tree.system.sharedDeps, 'has shared deps') | |
| 86 | const sharedNames = Object.keys(tree.system.sharedDeps) | |
| 87 | t.ok(sharedNames.length > 0, `${sharedNames.length} shared deps`) | |
| 88 | t.comment(`shared deps: ${sharedNames.slice(0, 5).join(', ')}...`) | |
| 89 | ||
| 90 | // Verify some modules have parsed file data | |
| 91 | const orgs = tree.modules['hyper-orgs'] | |
| 92 | if (orgs) { | |
| 93 | t.ok(orgs.files['lib/hyper-orgs.js'].classes, 'hyper-orgs has parsed class data') | |
| 94 | } | |
| 95 | ||
| 96 | const issues = tree.modules['hyper-issues'] | |
| 97 | if (issues) { | |
| 98 | t.ok(issues.publicAPI.length > 0, `hyper-issues has public API: ${issues.publicAPI.join(', ')}`) | |
| 99 | } | |
| 100 | }) | |
| 101 | ||
| 102 | test('tree: dependency graph is populated', async (t) => { | |
| 103 | const tree = await scan(HYPER_FLEEKY, { maxDepth: 1 }) | |
| 104 | ||
| 105 | const depsEntries = Object.entries(tree.system.dependencies) | |
| 106 | t.ok(depsEntries.length > 0, `${depsEntries.length} modules have deps`) | |
| 107 | ||
| 108 | // hyper-orgs depends on hyper-rooms | |
| 109 | const orgDeps = tree.system.dependencies['hyper-orgs'] | |
| 110 | if (orgDeps) { | |
| 111 | t.ok(orgDeps.includes('hyper-rooms'), 'hyper-orgs -> hyper-rooms') | |
| 112 | } | |
| 113 | }) | |
| 114 | ||
| 115 | test('tree: file roles are correctly classified', async (t) => { | |
| 116 | const tree = await scan(resolve(HYPER_FLEEKY, 'hyper-orgs')) | |
| 117 | const files = tree.modules['hyper-orgs'].files | |
| 118 | ||
| 119 | t.is(files['index.js'].role, 'entry', 'index.js = entry') | |
| 120 | t.is(files['lib/hyper-orgs.js'].role, 'lib', 'lib/*.js = lib') | |
| 121 | t.is(files['lib/schema.js'].role, 'schema', 'schema.js = schema') | |
| 122 | ||
| 123 | // Check for test files if they exist | |
| 124 | const testFiles = Object.entries(files).filter(([_, f]) => f.role === 'test') | |
| 125 | t.comment(`test files: ${testFiles.length}`) | |
| 126 | }) |
| … | … | @@ -0,0 +1,98 @@ |
| 1 | import { test } from 'brittle' | |
| 2 | import { resolve, dirname } from 'path' | |
| 3 | import { fileURLToPath } from 'url' | |
| 4 | import { scan } from '../lib/scanner.js' | |
| 5 | import { parseSpecs } from '../lib/doc-parser.js' | |
| 6 | import { validate } from '../lib/validator.js' | |
| 7 | ||
| 8 | const HERE = dirname(fileURLToPath(import.meta.url)) | |
| 9 | const HYPER_FLEEKY = resolve(HERE, '../../') | |
| 10 | const SPEC_DIR = resolve(HYPER_FLEEKY, 'pear-git-v3/spec') | |
| 11 | ||
| 12 | test('doc-parser: parse hyper-orgs module spec', (t) => { | |
| 13 | const specs = parseSpecs(SPEC_DIR) | |
| 14 | ||
| 15 | t.ok(specs.modules['hyper-orgs'], 'found hyper-orgs spec') | |
| 16 | ||
| 17 | const spec = specs.modules['hyper-orgs'] | |
| 18 | t.is(spec.location, 'hyper-fleeky/hyper-orgs', 'location parsed') | |
| 19 | t.is(spec.testCount, 29, 'test count parsed') | |
| 20 | t.is(spec.sourceVerified, '2026-04-10', 'source verified date parsed') | |
| 21 | t.ok(spec.fileLOC['hyper-orgs.js'], 'LOC claim for hyper-orgs.js') | |
| 22 | t.is(spec.fileLOC['hyper-orgs.js'], 637, 'LOC = 637') | |
| 23 | t.ok(spec.fileLOC['schema.js'], 'LOC claim for schema.js') | |
| 24 | ||
| 25 | t.ok(spec.description, 'has description') | |
| 26 | t.ok(spec.dependencies.includes('hyper-rooms'), 'dependency on hyper-rooms') | |
| 27 | t.ok(spec.dependents.includes('pear-git-v3'), 'dependent pear-git-v3') | |
| 28 | ||
| 29 | t.ok(spec.claimedExports.includes('HyperOrgs'), 'claims HyperOrgs export') | |
| 30 | t.ok(spec.claimedMethods.length > 10, spec.claimedMethods.length + ' claimed methods') | |
| 31 | t.ok(spec.claimedMethods.includes('create'), 'claims create method') | |
| 32 | t.ok(spec.claimedMethods.includes('checkAccess'), 'claims checkAccess method') | |
| 33 | }) | |
| 34 | ||
| 35 | test('doc-parser: parse SYSTEM.md', (t) => { | |
| 36 | const specs = parseSpecs(SPEC_DIR) | |
| 37 | ||
| 38 | t.ok(specs.system, 'system spec parsed') | |
| 39 | t.is(specs.system.lastVerified, '2026-04-12', 'last verified date') | |
| 40 | t.ok(specs.system.modules.length > 5, specs.system.modules.length + ' modules documented') | |
| 41 | ||
| 42 | const orgsEntry = specs.system.modules.find(m => m.name === 'hyper-orgs') | |
| 43 | t.ok(orgsEntry, 'hyper-orgs in system module list') | |
| 44 | t.ok(orgsEntry.location.includes('hyper-orgs'), 'location includes hyper-orgs') | |
| 45 | t.ok(orgsEntry.purpose, 'has purpose') | |
| 46 | ||
| 47 | t.ok(specs.system.builtItems.length > 0, 'has built items') | |
| 48 | t.ok(specs.system.missingItems.length > 0, 'has missing items') | |
| 49 | }) | |
| 50 | ||
| 51 | test('validator: hyper-orgs spec vs code', async (t) => { | |
| 52 | const tree = await scan(HYPER_FLEEKY, { maxDepth: 1 }) | |
| 53 | const specs = parseSpecs(SPEC_DIR) | |
| 54 | const report = validate(tree, specs) | |
| 55 | ||
| 56 | t.ok(report.modules['hyper-orgs'], 'has hyper-orgs validation') | |
| 57 | ||
| 58 | const modReport = report.modules['hyper-orgs'] | |
| 59 | t.ok(modReport.checks.length > 0, modReport.checks.length + ' checks performed') | |
| 60 | ||
| 61 | // Print the report for inspection | |
| 62 | for (const check of modReport.checks) { | |
| 63 | const icon = check.status === 'pass' ? 'PASS' : check.status === 'fail' ? 'FAIL' : 'WARN' | |
| 64 | t.comment(icon + ': ' + check.claim + (check.detail ? ' — ' + check.detail : '')) | |
| 65 | } | |
| 66 | ||
| 67 | // Should have some passes (the module exists, deps are correct) | |
| 68 | const passes = modReport.checks.filter(c => c.status === 'pass') | |
| 69 | t.ok(passes.length > 0, passes.length + ' checks passed') | |
| 70 | }) | |
| 71 | ||
| 72 | test('validator: system spec vs code', async (t) => { | |
| 73 | const tree = await scan(HYPER_FLEEKY, { maxDepth: 1 }) | |
| 74 | const specs = parseSpecs(SPEC_DIR) | |
| 75 | const report = validate(tree, specs) | |
| 76 | ||
| 77 | t.ok(report.system, 'has system validation') | |
| 78 | t.ok(report.system.checks.length > 0, report.system.checks.length + ' system checks') | |
| 79 | ||
| 80 | for (const check of report.system.checks) { | |
| 81 | const icon = check.status === 'pass' ? 'PASS' : check.status === 'fail' ? 'FAIL' : 'WARN' | |
| 82 | t.comment(icon + ': ' + check.claim + (check.detail ? ' — ' + check.detail : '')) | |
| 83 | } | |
| 84 | }) | |
| 85 | ||
| 86 | test('validator: summary counts', async (t) => { | |
| 87 | const tree = await scan(HYPER_FLEEKY, { maxDepth: 1 }) | |
| 88 | const specs = parseSpecs(SPEC_DIR) | |
| 89 | const report = validate(tree, specs) | |
| 90 | ||
| 91 | t.comment('Total: ' + report.summary.total + ' checks') | |
| 92 | t.comment('Pass: ' + report.summary.pass) | |
| 93 | t.comment('Fail: ' + report.summary.fail) | |
| 94 | t.comment('Warn: ' + report.summary.warn) | |
| 95 | ||
| 96 | t.ok(report.summary.total > 0, 'has checks') | |
| 97 | t.ok(report.summary.pass > 0, 'some passed') | |
| 98 | }) |
| … | … | @@ -0,0 +1,954 @@ |
| 1 | ## 8.15.0 (2025-06-08) | |
| 2 | ||
| 3 | ### New features | |
| 4 | ||
| 5 | Support `using` and `await using` syntax. | |
| 6 | ||
| 7 | The `AnyNode` type is now defined in such a way that plugins can extend it. | |
| 8 | ||
| 9 | ### Bug fixes | |
| 10 | ||
| 11 | Fix an issue where the `bigint` property of literal nodes for non-decimal bigints had the wrong format. | |
| 12 | ||
| 13 | The `acorn` CLI tool no longer crashes when emitting a tree that contains a bigint. | |
| 14 | ||
| 15 | ## 8.14.1 (2025-03-05) | |
| 16 | ||
| 17 | ### Bug fixes | |
| 18 | ||
| 19 | Fix an issue where `await` expressions in class field initializers were inappropriately allowed. | |
| 20 | ||
| 21 | Properly allow await inside an async arrow function inside a class field initializer. | |
| 22 | ||
| 23 | Mention the source file name in syntax error messages when given. | |
| 24 | ||
| 25 | Properly add an empty `attributes` property to every form of `ExportNamedDeclaration`. | |
| 26 | ||
| 27 | ## 8.14.0 (2024-10-27) | |
| 28 | ||
| 29 | ### New features | |
| 30 | ||
| 31 | Support ES2025 import attributes. | |
| 32 | ||
| 33 | Support ES2025 RegExp modifiers. | |
| 34 | ||
| 35 | ### Bug fixes | |
| 36 | ||
| 37 | Support some missing Unicode properties. | |
| 38 | ||
| 39 | ## 8.13.0 (2024-10-16) | |
| 40 | ||
| 41 | ### New features | |
| 42 | ||
| 43 | Upgrade to Unicode 16.0. | |
| 44 | ||
| 45 | ## 8.12.1 (2024-07-03) | |
| 46 | ||
| 47 | ### Bug fixes | |
| 48 | ||
| 49 | Fix a regression that caused Acorn to no longer run on Node versions <8.10. | |
| 50 | ||
| 51 | ## 8.12.0 (2024-06-14) | |
| 52 | ||
| 53 | ### New features | |
| 54 | ||
| 55 | Support ES2025 duplicate capture group names in regular expressions. | |
| 56 | ||
| 57 | ### Bug fixes | |
| 58 | ||
| 59 | Include `VariableDeclarator` in the `AnyNode` type so that walker objects can refer to it without getting a type error. | |
| 60 | ||
| 61 | Properly raise a parse error for invalid `for`/`of` statements using `async` as binding name. | |
| 62 | ||
| 63 | Properly recognize \"use strict\" when preceded by a string with an escaped newline. | |
| 64 | ||
| 65 | Mark the `Parser` constructor as protected, not private, so plugins can extend it without type errors. | |
| 66 | ||
| 67 | Fix a bug where some invalid `delete` expressions were let through when the operand was parenthesized and `preserveParens` was enabled. | |
| 68 | ||
| 69 | Properly normalize line endings in raw strings of invalid template tokens. | |
| 70 | ||
| 71 | Properly track line numbers for escaped newlines in strings. | |
| 72 | ||
| 73 | Fix a bug that broke line number accounting after a template literal with invalid escape sequences. | |
| 74 | ||
| 75 | ## 8.11.3 (2023-12-29) | |
| 76 | ||
| 77 | ### Bug fixes | |
| 78 | ||
| 79 | Add `Function` and `Class` to the `AggregateType` type, so that they can be used in walkers without raising a type error. | |
| 80 | ||
| 81 | Make sure `onToken` get an `import` keyword token when parsing `import.meta`. | |
| 82 | ||
| 83 | Fix a bug where `.loc.start` could be undefined for `new.target` `meta` nodes. | |
| 84 | ||
| 85 | ## 8.11.2 (2023-10-27) | |
| 86 | ||
| 87 | ### Bug fixes | |
| 88 | ||
| 89 | Fix a bug that caused regular expressions after colon tokens to not be properly tokenized in some circumstances. | |
| 90 | ||
| 91 | ## 8.11.1 (2023-10-26) | |
| 92 | ||
| 93 | ### Bug fixes | |
| 94 | ||
| 95 | Fix a regression where `onToken` would receive 'name' tokens for 'new' keyword tokens. | |
| 96 | ||
| 97 | ## 8.11.0 (2023-10-26) | |
| 98 | ||
| 99 | ### Bug fixes | |
| 100 | ||
| 101 | Fix an issue where tokenizing (without parsing) an object literal with a property named `class` or `function` could, in some circumstance, put the tokenizer into an invalid state. | |
| 102 | ||
| 103 | Fix an issue where a slash after a call to a propery named the same as some keywords would be tokenized as a regular expression. | |
| 104 | ||
| 105 | ### New features | |
| 106 | ||
| 107 | Upgrade to Unicode 15.1. | |
| 108 | ||
| 109 | Use a set of new, much more precise, TypeScript types. | |
| 110 | ||
| 111 | ## 8.10.0 (2023-07-05) | |
| 112 | ||
| 113 | ### New features | |
| 114 | ||
| 115 | Add a `checkPrivateFields` option that disables strict checking of private property use. | |
| 116 | ||
| 117 | ## 8.9.0 (2023-06-16) | |
| 118 | ||
| 119 | ### Bug fixes | |
| 120 | ||
| 121 | Forbid dynamic import after `new`, even when part of a member expression. | |
| 122 | ||
| 123 | ### New features | |
| 124 | ||
| 125 | Add Unicode properties for ES2023. | |
| 126 | ||
| 127 | Add support for the `v` flag to regular expressions. | |
| 128 | ||
| 129 | ## 8.8.2 (2023-01-23) | |
| 130 | ||
| 131 | ### Bug fixes | |
| 132 | ||
| 133 | Fix a bug that caused `allowHashBang` to be set to false when not provided, even with `ecmaVersion >= 14`. | |
| 134 | ||
| 135 | Fix an exception when passing no option object to `parse` or `new Parser`. | |
| 136 | ||
| 137 | Fix incorrect parse error on `if (0) let\n[astral identifier char]`. | |
| 138 | ||
| 139 | ## 8.8.1 (2022-10-24) | |
| 140 | ||
| 141 | ### Bug fixes | |
| 142 | ||
| 143 | Make type for `Comment` compatible with estree types. | |
| 144 | ||
| 145 | ## 8.8.0 (2022-07-21) | |
| 146 | ||
| 147 | ### Bug fixes | |
| 148 | ||
| 149 | Allow parentheses around spread args in destructuring object assignment. | |
| 150 | ||
| 151 | Fix an issue where the tree contained `directive` properties in when parsing with a language version that doesn't support them. | |
| 152 | ||
| 153 | ### New features | |
| 154 | ||
| 155 | Support hashbang comments by default in ECMAScript 2023 and later. | |
| 156 | ||
| 157 | ## 8.7.1 (2021-04-26) | |
| 158 | ||
| 159 | ### Bug fixes | |
| 160 | ||
| 161 | Stop handling `"use strict"` directives in ECMAScript versions before 5. | |
| 162 | ||
| 163 | Fix an issue where duplicate quoted export names in `export *` syntax were incorrectly checked. | |
| 164 | ||
| 165 | Add missing type for `tokTypes`. | |
| 166 | ||
| 167 | ## 8.7.0 (2021-12-27) | |
| 168 | ||
| 169 | ### New features | |
| 170 | ||
| 171 | Support quoted export names. | |
| 172 | ||
| 173 | Upgrade to Unicode 14. | |
| 174 | ||
| 175 | Add support for Unicode 13 properties in regular expressions. | |
| 176 | ||
| 177 | ### Bug fixes | |
| 178 | ||
| 179 | Use a loop to find line breaks, because the existing regexp search would overrun the end of the searched range and waste a lot of time in minified code. | |
| 180 | ||
| 181 | ## 8.6.0 (2021-11-18) | |
| 182 | ||
| 183 | ### Bug fixes | |
| 184 | ||
| 185 | Fix a bug where an object literal with multiple `__proto__` properties would incorrectly be accepted if a later property value held an assigment. | |
| 186 | ||
| 187 | ### New features | |
| 188 | ||
| 189 | Support class private fields with the `in` operator. | |
| 190 | ||
| 191 | ## 8.5.0 (2021-09-06) | |
| 192 | ||
| 193 | ### Bug fixes | |
| 194 | ||
| 195 | Improve context-dependent tokenization in a number of corner cases. | |
| 196 | ||
| 197 | Fix location tracking after a 0x2028 or 0x2029 character in a string literal (which before did not increase the line number). | |
| 198 | ||
| 199 | Fix an issue where arrow function bodies in for loop context would inappropriately consume `in` operators. | |
| 200 | ||
| 201 | Fix wrong end locations stored on SequenceExpression nodes. | |
| 202 | ||
| 203 | Implement restriction that `for`/`of` loop LHS can't start with `let`. | |
| 204 | ||
| 205 | ### New features | |
| 206 | ||
| 207 | Add support for ES2022 class static blocks. | |
| 208 | ||
| 209 | Allow multiple input files to be passed to the CLI tool. | |
| 210 | ||
| 211 | ## 8.4.1 (2021-06-24) | |
| 212 | ||
| 213 | ### Bug fixes | |
| 214 | ||
| 215 | Fix a bug where `allowAwaitOutsideFunction` would allow `await` in class field initializers, and setting `ecmaVersion` to 13 or higher would allow top-level await in non-module sources. | |
| 216 | ||
| 217 | ## 8.4.0 (2021-06-11) | |
| 218 | ||
| 219 | ### New features | |
| 220 | ||
| 221 | A new option, `allowSuperOutsideMethod`, can be used to suppress the error when `super` is used in the wrong context. | |
| 222 | ||
| 223 | ## 8.3.0 (2021-05-31) | |
| 224 | ||
| 225 | ### New features | |
| 226 | ||
| 227 | Default `allowAwaitOutsideFunction` to true for ECMAScript 2022 an higher. | |
| 228 | ||
| 229 | Add support for the `d` ([indices](https://github.com/tc39/proposal-regexp-match-indices)) regexp flag. | |
| 230 | ||
| 231 | ## 8.2.4 (2021-05-04) | |
| 232 | ||
| 233 | ### Bug fixes | |
| 234 | ||
| 235 | Fix spec conformity in corner case 'for await (async of ...)'. | |
| 236 | ||
| 237 | ## 8.2.3 (2021-05-04) | |
| 238 | ||
| 239 | ### Bug fixes | |
| 240 | ||
| 241 | Fix an issue where the library couldn't parse 'for (async of ...)'. | |
| 242 | ||
| 243 | Fix a bug in UTF-16 decoding that would read characters incorrectly in some circumstances. | |
| 244 | ||
| 245 | ## 8.2.2 (2021-04-29) | |
| 246 | ||
| 247 | ### Bug fixes | |
| 248 | ||
| 249 | Fix a bug where a class field initialized to an async arrow function wouldn't allow await inside it. Same issue existed for generator arrow functions with yield. | |
| 250 | ||
| 251 | ## 8.2.1 (2021-04-24) | |
| 252 | ||
| 253 | ### Bug fixes | |
| 254 | ||
| 255 | Fix a regression introduced in 8.2.0 where static or async class methods with keyword names fail to parse. | |
| 256 | ||
| 257 | ## 8.2.0 (2021-04-24) | |
| 258 | ||
| 259 | ### New features | |
| 260 | ||
| 261 | Add support for ES2022 class fields and private methods. | |
| 262 | ||
| 263 | ## 8.1.1 (2021-04-12) | |
| 264 | ||
| 265 | ### Various | |
| 266 | ||
| 267 | Stop shipping source maps in the NPM package. | |
| 268 | ||
| 269 | ## 8.1.0 (2021-03-09) | |
| 270 | ||
| 271 | ### Bug fixes | |
| 272 | ||
| 273 | Fix a spurious error in nested destructuring arrays. | |
| 274 | ||
| 275 | ### New features | |
| 276 | ||
| 277 | Expose `allowAwaitOutsideFunction` in CLI interface. | |
| 278 | ||
| 279 | Make `allowImportExportAnywhere` also apply to `import.meta`. | |
| 280 | ||
| 281 | ## 8.0.5 (2021-01-25) | |
| 282 | ||
| 283 | ### Bug fixes | |
| 284 | ||
| 285 | Adjust package.json to work with Node 12.16.0 and 13.0-13.6. | |
| 286 | ||
| 287 | ## 8.0.4 (2020-10-05) | |
| 288 | ||
| 289 | ### Bug fixes | |
| 290 | ||
| 291 | Make `await x ** y` an error, following the spec. | |
| 292 | ||
| 293 | Fix potentially exponential regular expression. | |
| 294 | ||
| 295 | ## 8.0.3 (2020-10-02) | |
| 296 | ||
| 297 | ### Bug fixes | |
| 298 | ||
| 299 | Fix a wasteful loop during `Parser` creation when setting `ecmaVersion` to `"latest"`. | |
| 300 | ||
| 301 | ## 8.0.2 (2020-09-30) | |
| 302 | ||
| 303 | ### Bug fixes | |
| 304 | ||
| 305 | Make the TypeScript types reflect the current allowed values for `ecmaVersion`. | |
| 306 | ||
| 307 | Fix another regexp/division tokenizer issue. | |
| 308 | ||
| 309 | ## 8.0.1 (2020-08-12) | |
| 310 | ||
| 311 | ### Bug fixes | |
| 312 | ||
| 313 | Provide the correct value in the `version` export. | |
| 314 | ||
| 315 | ## 8.0.0 (2020-08-12) | |
| 316 | ||
| 317 | ### Bug fixes | |
| 318 | ||
| 319 | Disallow expressions like `(a = b) = c`. | |
| 320 | ||
| 321 | Make non-octal escape sequences a syntax error in strict mode. | |
| 322 | ||
| 323 | ### New features | |
| 324 | ||
| 325 | The package can now be loaded directly as an ECMAScript module in node 13+. | |
| 326 | ||
| 327 | Update to the set of Unicode properties from ES2021. | |
| 328 | ||
| 329 | ### Breaking changes | |
| 330 | ||
| 331 | The `ecmaVersion` option is now required. For the moment, omitting it will still work with a warning, but that will change in a future release. | |
| 332 | ||
| 333 | Some changes to method signatures that may be used by plugins. | |
| 334 | ||
| 335 | ## 7.4.0 (2020-08-03) | |
| 336 | ||
| 337 | ### New features | |
| 338 | ||
| 339 | Add support for logical assignment operators. | |
| 340 | ||
| 341 | Add support for numeric separators. | |
| 342 | ||
| 343 | ## 7.3.1 (2020-06-11) | |
| 344 | ||
| 345 | ### Bug fixes | |
| 346 | ||
| 347 | Make the string in the `version` export match the actual library version. | |
| 348 | ||
| 349 | ## 7.3.0 (2020-06-11) | |
| 350 | ||
| 351 | ### Bug fixes | |
| 352 | ||
| 353 | Fix a bug that caused parsing of object patterns with a property named `set` that had a default value to fail. | |
| 354 | ||
| 355 | ### New features | |
| 356 | ||
| 357 | Add support for optional chaining (`?.`). | |
| 358 | ||
| 359 | ## 7.2.0 (2020-05-09) | |
| 360 | ||
| 361 | ### Bug fixes | |
| 362 | ||
| 363 | Fix precedence issue in parsing of async arrow functions. | |
| 364 | ||
| 365 | ### New features | |
| 366 | ||
| 367 | Add support for nullish coalescing. | |
| 368 | ||
| 369 | Add support for `import.meta`. | |
| 370 | ||
| 371 | Support `export * as ...` syntax. | |
| 372 | ||
| 373 | Upgrade to Unicode 13. | |
| 374 | ||
| 375 | ## 6.4.1 (2020-03-09) | |
| 376 | ||
| 377 | ### Bug fixes | |
| 378 | ||
| 379 | More carefully check for valid UTF16 surrogate pairs in regexp validator. | |
| 380 | ||
| 381 | ## 7.1.1 (2020-03-01) | |
| 382 | ||
| 383 | ### Bug fixes | |
| 384 | ||
| 385 | Treat `\8` and `\9` as invalid escapes in template strings. | |
| 386 | ||
| 387 | Allow unicode escapes in property names that are keywords. | |
| 388 | ||
| 389 | Don't error on an exponential operator expression as argument to `await`. | |
| 390 | ||
| 391 | More carefully check for valid UTF16 surrogate pairs in regexp validator. | |
| 392 | ||
| 393 | ## 7.1.0 (2019-09-24) | |
| 394 | ||
| 395 | ### Bug fixes | |
| 396 | ||
| 397 | Disallow trailing object literal commas when ecmaVersion is less than 5. | |
| 398 | ||
| 399 | ### New features | |
| 400 | ||
| 401 | Add a static `acorn` property to the `Parser` class that contains the entire module interface, to allow plugins to access the instance of the library that they are acting on. | |
| 402 | ||
| 403 | ## 7.0.0 (2019-08-13) | |
| 404 | ||
| 405 | ### Breaking changes | |
| 406 | ||
| 407 | Changes the node format for dynamic imports to use the `ImportExpression` node type, as defined in [ESTree](https://github.com/estree/estree/blob/master/es2020.md#importexpression). | |
| 408 | ||
| 409 | Makes 10 (ES2019) the default value for the `ecmaVersion` option. | |
| 410 | ||
| 411 | ## 6.3.0 (2019-08-12) | |
| 412 | ||
| 413 | ### New features | |
| 414 | ||
| 415 | `sourceType: "module"` can now be used even when `ecmaVersion` is less than 6, to parse module-style code that otherwise conforms to an older standard. | |
| 416 | ||
| 417 | ## 6.2.1 (2019-07-21) | |
| 418 | ||
| 419 | ### Bug fixes | |
| 420 | ||
| 421 | Fix bug causing Acorn to treat some characters as identifier characters that shouldn't be treated as such. | |
| 422 | ||
| 423 | Fix issue where setting the `allowReserved` option to `"never"` allowed reserved words in some circumstances. | |
| 424 | ||
| 425 | ## 6.2.0 (2019-07-04) | |
| 426 | ||
| 427 | ### Bug fixes | |
| 428 | ||
| 429 | Improve valid assignment checking in `for`/`in` and `for`/`of` loops. | |
| 430 | ||
| 431 | Disallow binding `let` in patterns. | |
| 432 | ||
| 433 | ### New features | |
| 434 | ||
| 435 | Support bigint syntax with `ecmaVersion` >= 11. | |
| 436 | ||
| 437 | Support dynamic `import` syntax with `ecmaVersion` >= 11. | |
| 438 | ||
| 439 | Upgrade to Unicode version 12. | |
| 440 | ||
| 441 | ## 6.1.1 (2019-02-27) | |
| 442 | ||
| 443 | ### Bug fixes | |
| 444 | ||
| 445 | Fix bug that caused parsing default exports of with names to fail. | |
| 446 | ||
| 447 | ## 6.1.0 (2019-02-08) | |
| 448 | ||
| 449 | ### Bug fixes | |
| 450 | ||
| 451 | Fix scope checking when redefining a `var` as a lexical binding. | |
| 452 | ||
| 453 | ### New features | |
| 454 | ||
| 455 | Split up `parseSubscripts` to use an internal `parseSubscript` method to make it easier to extend with plugins. | |
| 456 | ||
| 457 | ## 6.0.7 (2019-02-04) | |
| 458 | ||
| 459 | ### Bug fixes | |
| 460 | ||
| 461 | Check that exported bindings are defined. | |
| 462 | ||
| 463 | Don't treat `\u180e` as a whitespace character. | |
| 464 | ||
| 465 | Check for duplicate parameter names in methods. | |
| 466 | ||
| 467 | Don't allow shorthand properties when they are generators or async methods. | |
| 468 | ||
| 469 | Forbid binding `await` in async arrow function's parameter list. | |
| 470 | ||
| 471 | ## 6.0.6 (2019-01-30) | |
| 472 | ||
| 473 | ### Bug fixes | |
| 474 | ||
| 475 | The content of class declarations and expressions is now always parsed in strict mode. | |
| 476 | ||
| 477 | Don't allow `let` or `const` to bind the variable name `let`. | |
| 478 | ||
| 479 | Treat class declarations as lexical. | |
| 480 | ||
| 481 | Don't allow a generator function declaration as the sole body of an `if` or `else`. | |
| 482 | ||
| 483 | Ignore `"use strict"` when after an empty statement. | |
| 484 | ||
| 485 | Allow string line continuations with special line terminator characters. | |
| 486 | ||
| 487 | Treat `for` bodies as part of the `for` scope when checking for conflicting bindings. | |
| 488 | ||
| 489 | Fix bug with parsing `yield` in a `for` loop initializer. | |
| 490 | ||
| 491 | Implement special cases around scope checking for functions. | |
| 492 | ||
| 493 | ## 6.0.5 (2019-01-02) | |
| 494 | ||
| 495 | ### Bug fixes | |
| 496 | ||
| 497 | Fix TypeScript type for `Parser.extend` and add `allowAwaitOutsideFunction` to options type. | |
| 498 | ||
| 499 | Don't treat `let` as a keyword when the next token is `{` on the next line. | |
| 500 | ||
| 501 | Fix bug that broke checking for parentheses around an object pattern in a destructuring assignment when `preserveParens` was on. | |
| 502 | ||
| 503 | ## 6.0.4 (2018-11-05) | |
| 504 | ||
| 505 | ### Bug fixes | |
| 506 | ||
| 507 | Further improvements to tokenizing regular expressions in corner cases. | |
| 508 | ||
| 509 | ## 6.0.3 (2018-11-04) | |
| 510 | ||
| 511 | ### Bug fixes | |
| 512 | ||
| 513 | Fix bug in tokenizing an expression-less return followed by a function followed by a regular expression. | |
| 514 | ||
| 515 | Remove stray symlink in the package tarball. | |
| 516 | ||
| 517 | ## 6.0.2 (2018-09-26) | |
| 518 | ||
| 519 | ### Bug fixes | |
| 520 | ||
| 521 | Fix bug where default expressions could fail to parse inside an object destructuring assignment expression. | |
| 522 | ||
| 523 | ## 6.0.1 (2018-09-14) | |
| 524 | ||
| 525 | ### Bug fixes | |
| 526 | ||
| 527 | Fix wrong value in `version` export. | |
| 528 | ||
| 529 | ## 6.0.0 (2018-09-14) | |
| 530 | ||
| 531 | ### Bug fixes | |
| 532 | ||
| 533 | Better handle variable-redefinition checks for catch bindings and functions directly under if statements. | |
| 534 | ||
| 535 | Forbid `new.target` in top-level arrow functions. | |
| 536 | ||
| 537 | Fix issue with parsing a regexp after `yield` in some contexts. | |
| 538 | ||
| 539 | ### New features | |
| 540 | ||
| 541 | The package now comes with TypeScript definitions. | |
| 542 | ||
| 543 | ### Breaking changes | |
| 544 | ||
| 545 | The default value of the `ecmaVersion` option is now 9 (2018). | |
| 546 | ||
| 547 | Plugins work differently, and will have to be rewritten to work with this version. | |
| 548 | ||
| 549 | The loose parser and walker have been moved into separate packages (`acorn-loose` and `acorn-walk`). | |
| 550 | ||
| 551 | ## 5.7.3 (2018-09-10) | |
| 552 | ||
| 553 | ### Bug fixes | |
| 554 | ||
| 555 | Fix failure to tokenize regexps after expressions like `x.of`. | |
| 556 | ||
| 557 | Better error message for unterminated template literals. | |
| 558 | ||
| 559 | ## 5.7.2 (2018-08-24) | |
| 560 | ||
| 561 | ### Bug fixes | |
| 562 | ||
| 563 | Properly handle `allowAwaitOutsideFunction` in for statements. | |
| 564 | ||
| 565 | Treat function declarations at the top level of modules like let bindings. | |
| 566 | ||
| 567 | Don't allow async function declarations as the only statement under a label. | |
| 568 | ||
| 569 | ## 5.7.0 (2018-06-15) | |
| 570 | ||
| 571 | ### New features | |
| 572 | ||
| 573 | Upgraded to Unicode 11. | |
| 574 | ||
| 575 | ## 5.6.0 (2018-05-31) | |
| 576 | ||
| 577 | ### New features | |
| 578 | ||
| 579 | Allow U+2028 and U+2029 in string when ECMAVersion >= 10. | |
| 580 | ||
| 581 | Allow binding-less catch statements when ECMAVersion >= 10. | |
| 582 | ||
| 583 | Add `allowAwaitOutsideFunction` option for parsing top-level `await`. | |
| 584 | ||
| 585 | ## 5.5.3 (2018-03-08) | |
| 586 | ||
| 587 | ### Bug fixes | |
| 588 | ||
| 589 | A _second_ republish of the code in 5.5.1, this time with yarn, to hopefully get valid timestamps. | |
| 590 | ||
| 591 | ## 5.5.2 (2018-03-08) | |
| 592 | ||
| 593 | ### Bug fixes | |
| 594 | ||
| 595 | A republish of the code in 5.5.1 in an attempt to solve an issue with the file timestamps in the npm package being 0. | |
| 596 | ||
| 597 | ## 5.5.1 (2018-03-06) | |
| 598 | ||
| 599 | ### Bug fixes | |
| 600 | ||
| 601 | Fix misleading error message for octal escapes in template strings. | |
| 602 | ||
| 603 | ## 5.5.0 (2018-02-27) | |
| 604 | ||
| 605 | ### New features | |
| 606 | ||
| 607 | The identifier character categorization is now based on Unicode version 10. | |
| 608 | ||
| 609 | Acorn will now validate the content of regular expressions, including new ES9 features. | |
| 610 | ||
| 611 | ## 5.4.0 (2018-02-01) | |
| 612 | ||
| 613 | ### Bug fixes | |
| 614 | ||
| 615 | Disallow duplicate or escaped flags on regular expressions. | |
| 616 | ||
| 617 | Disallow octal escapes in strings in strict mode. | |
| 618 | ||
| 619 | ### New features | |
| 620 | ||
| 621 | Add support for async iteration. | |
| 622 | ||
| 623 | Add support for object spread and rest. | |
| 624 | ||
| 625 | ## 5.3.0 (2017-12-28) | |
| 626 | ||
| 627 | ### Bug fixes | |
| 628 | ||
| 629 | Fix parsing of floating point literals with leading zeroes in loose mode. | |
| 630 | ||
| 631 | Allow duplicate property names in object patterns. | |
| 632 | ||
| 633 | Don't allow static class methods named `prototype`. | |
| 634 | ||
| 635 | Disallow async functions directly under `if` or `else`. | |
| 636 | ||
| 637 | Parse right-hand-side of `for`/`of` as an assignment expression. | |
| 638 | ||
| 639 | Stricter parsing of `for`/`in`. | |
| 640 | ||
| 641 | Don't allow unicode escapes in contextual keywords. | |
| 642 | ||
| 643 | ### New features | |
| 644 | ||
| 645 | Parsing class members was factored into smaller methods to allow plugins to hook into it. | |
| 646 | ||
| 647 | ## 5.2.1 (2017-10-30) | |
| 648 | ||
| 649 | ### Bug fixes | |
| 650 | ||
| 651 | Fix a token context corruption bug. | |
| 652 | ||
| 653 | ## 5.2.0 (2017-10-30) | |
| 654 | ||
| 655 | ### Bug fixes | |
| 656 | ||
| 657 | Fix token context tracking for `class` and `function` in property-name position. | |
| 658 | ||
| 659 | Make sure `%*` isn't parsed as a valid operator. | |
| 660 | ||
| 661 | Allow shorthand properties `get` and `set` to be followed by default values. | |
| 662 | ||
| 663 | Disallow `super` when not in callee or object position. | |
| 664 | ||
| 665 | ### New features | |
| 666 | ||
| 667 | Support [`directive` property](https://github.com/estree/estree/compare/b3de58c9997504d6fba04b72f76e6dd1619ee4eb...1da8e603237144f44710360f8feb7a9977e905e0) on directive expression statements. | |
| 668 | ||
| 669 | ## 5.1.2 (2017-09-04) | |
| 670 | ||
| 671 | ### Bug fixes | |
| 672 | ||
| 673 | Disable parsing of legacy HTML-style comments in modules. | |
| 674 | ||
| 675 | Fix parsing of async methods whose names are keywords. | |
| 676 | ||
| 677 | ## 5.1.1 (2017-07-06) | |
| 678 | ||
| 679 | ### Bug fixes | |
| 680 | ||
| 681 | Fix problem with disambiguating regexp and division after a class. | |
| 682 | ||
| 683 | ## 5.1.0 (2017-07-05) | |
| 684 | ||
| 685 | ### Bug fixes | |
| 686 | ||
| 687 | Fix tokenizing of regexps in an object-desctructuring `for`/`of` loop and after `yield`. | |
| 688 | ||
| 689 | Parse zero-prefixed numbers with non-octal digits as decimal. | |
| 690 | ||
| 691 | Allow object/array patterns in rest parameters. | |
| 692 | ||
| 693 | Don't error when `yield` is used as a property name. | |
| 694 | ||
| 695 | Allow `async` as a shorthand object property. | |
| 696 | ||
| 697 | ### New features | |
| 698 | ||
| 699 | Implement the [template literal revision proposal](https://github.com/tc39/proposal-template-literal-revision) for ES9. | |
| 700 | ||
| 701 | ## 5.0.3 (2017-04-01) | |
| 702 | ||
| 703 | ### Bug fixes | |
| 704 | ||
| 705 | Fix spurious duplicate variable definition errors for named functions. | |
| 706 | ||
| 707 | ## 5.0.2 (2017-03-30) | |
| 708 | ||
| 709 | ### Bug fixes | |
| 710 | ||
| 711 | A binary operator after a parenthesized arrow expression is no longer incorrectly treated as an error. | |
| 712 | ||
| 713 | ## 5.0.0 (2017-03-28) | |
| 714 | ||
| 715 | ### Bug fixes | |
| 716 | ||
| 717 | Raise an error for duplicated lexical bindings. | |
| 718 | ||
| 719 | Fix spurious error when an assignement expression occurred after a spread expression. | |
| 720 | ||
| 721 | Accept regular expressions after `of` (in `for`/`of`), `yield` (in a generator), and braced arrow functions. | |
| 722 | ||
| 723 | Allow labels in front or `var` declarations, even in strict mode. | |
| 724 | ||
| 725 | ### Breaking changes | |
| 726 | ||
| 727 | Parse declarations following `export default` as declaration nodes, not expressions. This means that class and function declarations nodes can now have `null` as their `id`. | |
| 728 | ||
| 729 | ## 4.0.11 (2017-02-07) | |
| 730 | ||
| 731 | ### Bug fixes | |
| 732 | ||
| 733 | Allow all forms of member expressions to be parenthesized as lvalue. | |
| 734 | ||
| 735 | ## 4.0.10 (2017-02-07) | |
| 736 | ||
| 737 | ### Bug fixes | |
| 738 | ||
| 739 | Don't expect semicolons after default-exported functions or classes, even when they are expressions. | |
| 740 | ||
| 741 | Check for use of `'use strict'` directives in non-simple parameter functions, even when already in strict mode. | |
| 742 | ||
| 743 | ## 4.0.9 (2017-02-06) | |
| 744 | ||
| 745 | ### Bug fixes | |
| 746 | ||
| 747 | Fix incorrect error raised for parenthesized simple assignment targets, so that `(x) = 1` parses again. | |
| 748 | ||
| 749 | ## 4.0.8 (2017-02-03) | |
| 750 | ||
| 751 | ### Bug fixes | |
| 752 | ||
| 753 | Solve spurious parenthesized pattern errors by temporarily erring on the side of accepting programs that our delayed errors don't handle correctly yet. | |
| 754 | ||
| 755 | ## 4.0.7 (2017-02-02) | |
| 756 | ||
| 757 | ### Bug fixes | |
| 758 | ||
| 759 | Accept invalidly rejected code like `(x).y = 2` again. | |
| 760 | ||
| 761 | Don't raise an error when a function _inside_ strict code has a non-simple parameter list. | |
| 762 | ||
| 763 | ## 4.0.6 (2017-02-02) | |
| 764 | ||
| 765 | ### Bug fixes | |
| 766 | ||
| 767 | Fix exponential behavior (manifesting itself as a complete hang for even relatively small source files) introduced by the new 'use strict' check. | |
| 768 | ||
| 769 | ## 4.0.5 (2017-02-02) | |
| 770 | ||
| 771 | ### Bug fixes | |
| 772 | ||
| 773 | Disallow parenthesized pattern expressions. | |
| 774 | ||
| 775 | Allow keywords as export names. | |
| 776 | ||
| 777 | Don't allow the `async` keyword to be parenthesized. | |
| 778 | ||
| 779 | Properly raise an error when a keyword contains a character escape. | |
| 780 | ||
| 781 | Allow `"use strict"` to appear after other string literal expressions. | |
| 782 | ||
| 783 | Disallow labeled declarations. | |
| 784 | ||
| 785 | ## 4.0.4 (2016-12-19) | |
| 786 | ||
| 787 | ### Bug fixes | |
| 788 | ||
| 789 | Fix crash when `export` was followed by a keyword that can't be | |
| 790 | exported. | |
| 791 | ||
| 792 | ## 4.0.3 (2016-08-16) | |
| 793 | ||
| 794 | ### Bug fixes | |
| 795 | ||
| 796 | Allow regular function declarations inside single-statement `if` branches in loose mode. Forbid them entirely in strict mode. | |
| 797 | ||
| 798 | Properly parse properties named `async` in ES2017 mode. | |
| 799 | ||
| 800 | Fix bug where reserved words were broken in ES2017 mode. | |
| 801 | ||
| 802 | ## 4.0.2 (2016-08-11) | |
| 803 | ||
| 804 | ### Bug fixes | |
| 805 | ||
| 806 | Don't ignore period or 'e' characters after octal numbers. | |
| 807 | ||
| 808 | Fix broken parsing for call expressions in default parameter values of arrow functions. | |
| 809 | ||
| 810 | ## 4.0.1 (2016-08-08) | |
| 811 | ||
| 812 | ### Bug fixes | |
| 813 | ||
| 814 | Fix false positives in duplicated export name errors. | |
| 815 | ||
| 816 | ## 4.0.0 (2016-08-07) | |
| 817 | ||
| 818 | ### Breaking changes | |
| 819 | ||
| 820 | The default `ecmaVersion` option value is now 7. | |
| 821 | ||
| 822 | A number of internal method signatures changed, so plugins might need to be updated. | |
| 823 | ||
| 824 | ### Bug fixes | |
| 825 | ||
| 826 | The parser now raises errors on duplicated export names. | |
| 827 | ||
| 828 | `arguments` and `eval` can now be used in shorthand properties. | |
| 829 | ||
| 830 | Duplicate parameter names in non-simple argument lists now always produce an error. | |
| 831 | ||
| 832 | ### New features | |
| 833 | ||
| 834 | The `ecmaVersion` option now also accepts year-style version numbers | |
| 835 | (2015, etc). | |
| 836 | ||
| 837 | Support for `async`/`await` syntax when `ecmaVersion` is >= 8. | |
| 838 | ||
| 839 | Support for trailing commas in call expressions when `ecmaVersion` is >= 8. | |
| 840 | ||
| 841 | ## 3.3.0 (2016-07-25) | |
| 842 | ||
| 843 | ### Bug fixes | |
| 844 | ||
| 845 | Fix bug in tokenizing of regexp operator after a function declaration. | |
| 846 | ||
| 847 | Fix parser crash when parsing an array pattern with a hole. | |
| 848 | ||
| 849 | ### New features | |
| 850 | ||
| 851 | Implement check against complex argument lists in functions that enable strict mode in ES7. | |
| 852 | ||
| 853 | ## 3.2.0 (2016-06-07) | |
| 854 | ||
| 855 | ### Bug fixes | |
| 856 | ||
| 857 | Improve handling of lack of unicode regexp support in host | |
| 858 | environment. | |
| 859 | ||
| 860 | Properly reject shorthand properties whose name is a keyword. | |
| 861 | ||
| 862 | ### New features | |
| 863 | ||
| 864 | Visitors created with `visit.make` now have their base as _prototype_, rather than copying properties into a fresh object. | |
| 865 | ||
| 866 | ## 3.1.0 (2016-04-18) | |
| 867 | ||
| 868 | ### Bug fixes | |
| 869 | ||
| 870 | Properly tokenize the division operator directly after a function expression. | |
| 871 | ||
| 872 | Allow trailing comma in destructuring arrays. | |
| 873 | ||
| 874 | ## 3.0.4 (2016-02-25) | |
| 875 | ||
| 876 | ### Fixes | |
| 877 | ||
| 878 | Allow update expressions as left-hand-side of the ES7 exponential operator. | |
| 879 | ||
| 880 | ## 3.0.2 (2016-02-10) | |
| 881 | ||
| 882 | ### Fixes | |
| 883 | ||
| 884 | Fix bug that accidentally made `undefined` a reserved word when parsing ES7. | |
| 885 | ||
| 886 | ## 3.0.0 (2016-02-10) | |
| 887 | ||
| 888 | ### Breaking changes | |
| 889 | ||
| 890 | The default value of the `ecmaVersion` option is now 6 (used to be 5). | |
| 891 | ||
| 892 | Support for comprehension syntax (which was dropped from the draft spec) has been removed. | |
| 893 | ||
| 894 | ### Fixes | |
| 895 | ||
| 896 | `let` and `yield` are now “contextual keywords”, meaning you can mostly use them as identifiers in ES5 non-strict code. | |
| 897 | ||
| 898 | A parenthesized class or function expression after `export default` is now parsed correctly. | |
| 899 | ||
| 900 | ### New features | |
| 901 | ||
| 902 | When `ecmaVersion` is set to 7, Acorn will parse the exponentiation operator (`**`). | |
| 903 | ||
| 904 | The identifier character ranges are now based on Unicode 8.0.0. | |
| 905 | ||
| 906 | Plugins can now override the `raiseRecoverable` method to override the way non-critical errors are handled. | |
| 907 | ||
| 908 | ## 2.7.0 (2016-01-04) | |
| 909 | ||
| 910 | ### Fixes | |
| 911 | ||
| 912 | Stop allowing rest parameters in setters. | |
| 913 | ||
| 914 | Disallow `y` rexexp flag in ES5. | |
| 915 | ||
| 916 | Disallow `\00` and `\000` escapes in strict mode. | |
| 917 | ||
| 918 | Raise an error when an import name is a reserved word. | |
| 919 | ||
| 920 | ## 2.6.2 (2015-11-10) | |
| 921 | ||
| 922 | ### Fixes | |
| 923 | ||
| 924 | Don't crash when no options object is passed. | |
| 925 | ||
| 926 | ## 2.6.0 (2015-11-09) | |
| 927 | ||
| 928 | ### Fixes | |
| 929 | ||
| 930 | Add `await` as a reserved word in module sources. | |
| 931 | ||
| 932 | Disallow `yield` in a parameter default value for a generator. | |
| 933 | ||
| 934 | Forbid using a comma after a rest pattern in an array destructuring. | |
| 935 | ||
| 936 | ### New features | |
| 937 | ||
| 938 | Support parsing stdin in command-line tool. | |
| 939 | ||
| 940 | ## 2.5.0 (2015-10-27) | |
| 941 | ||
| 942 | ### Fixes | |
| 943 | ||
| 944 | Fix tokenizer support in the command-line tool. | |
| 945 | ||
| 946 | Stop allowing `new.target` outside of functions. | |
| 947 | ||
| 948 | Remove legacy `guard` and `guardedHandler` properties from try nodes. | |
| 949 | ||
| 950 | Stop allowing multiple `__proto__` properties on an object literal in strict mode. | |
| 951 | ||
| 952 | Don't allow rest parameters to be non-identifier patterns. | |
| 953 | ||
| 954 | Check for duplicate paramter names in arrow functions. |
| … | … | @@ -0,0 +1,21 @@ |
| 1 | MIT License | |
| 2 | ||
| 3 | Copyright (C) 2012-2022 by various contributors (see AUTHORS) | |
| 4 | ||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 | of this software and associated documentation files (the "Software"), to deal | |
| 7 | in the Software without restriction, including without limitation the rights | |
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 9 | copies of the Software, and to permit persons to whom the Software is | |
| 10 | furnished to do so, subject to the following conditions: | |
| 11 | ||
| 12 | The above copyright notice and this permission notice shall be included in | |
| 13 | all copies or substantial portions of the Software. | |
| 14 | ||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 21 | THE SOFTWARE. |
| … | … | @@ -0,0 +1,282 @@ |
| 1 | # Acorn | |
| 2 | ||
| 3 | A tiny, fast JavaScript parser written in JavaScript. | |
| 4 | ||
| 5 | ## Community | |
| 6 | ||
| 7 | Acorn is open source software released under an | |
| 8 | [MIT license](https://github.com/acornjs/acorn/blob/master/acorn/LICENSE). | |
| 9 | ||
| 10 | You are welcome to | |
| 11 | [report bugs](https://github.com/acornjs/acorn/issues) or create pull | |
| 12 | requests on [github](https://github.com/acornjs/acorn). | |
| 13 | ||
| 14 | ## Installation | |
| 15 | ||
| 16 | The easiest way to install acorn is from [`npm`](https://www.npmjs.com/): | |
| 17 | ||
| 18 | ```sh | |
| 19 | npm install acorn | |
| 20 | ``` | |
| 21 | ||
| 22 | Alternately, you can download the source and build acorn yourself: | |
| 23 | ||
| 24 | ```sh | |
| 25 | git clone https://github.com/acornjs/acorn.git | |
| 26 | cd acorn | |
| 27 | npm install | |
| 28 | ``` | |
| 29 | ||
| 30 | ## Interface | |
| 31 | ||
| 32 | **parse**`(input, options)` is the main interface to the library. The | |
| 33 | `input` parameter is a string, `options` must be an object setting | |
| 34 | some of the options listed below. The return value will be an abstract | |
| 35 | syntax tree object as specified by the [ESTree | |
| 36 | spec](https://github.com/estree/estree). | |
| 37 | ||
| 38 | ```javascript | |
| 39 | let acorn = require("acorn"); | |
| 40 | console.log(acorn.parse("1 + 1", {ecmaVersion: 2020})); | |
| 41 | ``` | |
| 42 | ||
| 43 | When encountering a syntax error, the parser will raise a | |
| 44 | `SyntaxError` object with a meaningful message. The error object will | |
| 45 | have a `pos` property that indicates the string offset at which the | |
| 46 | error occurred, and a `loc` object that contains a `{line, column}` | |
| 47 | object referring to that same position. | |
| 48 | ||
| 49 | Options are provided by in a second argument, which should be an | |
| 50 | object containing any of these fields (only `ecmaVersion` is | |
| 51 | required): | |
| 52 | ||
| 53 | - **ecmaVersion**: Indicates the ECMAScript version to parse. Can be a | |
| 54 | number, either in year (`2022`) or plain version number (`6`) form, | |
| 55 | or `"latest"` (the latest the library supports). This influences | |
| 56 | support for strict mode, the set of reserved words, and support for | |
| 57 | new syntax features. | |
| 58 | ||
| 59 | **NOTE**: Only 'stage 4' (finalized) ECMAScript features are being | |
| 60 | implemented by Acorn. Other proposed new features must be | |
| 61 | implemented through plugins. | |
| 62 | ||
| 63 | - **sourceType**: Indicate the mode the code should be parsed in. Can be | |
| 64 | either `"script"` or `"module"`. This influences global strict mode | |
| 65 | and parsing of `import` and `export` declarations. | |
| 66 | ||
| 67 | **NOTE**: If set to `"module"`, then static `import` / `export` syntax | |
| 68 | will be valid, even if `ecmaVersion` is less than 6. | |
| 69 | ||
| 70 | - **onInsertedSemicolon**: If given a callback, that callback will be | |
| 71 | called whenever a missing semicolon is inserted by the parser. The | |
| 72 | callback will be given the character offset of the point where the | |
| 73 | semicolon is inserted as argument, and if `locations` is on, also a | |
| 74 | `{line, column}` object representing this position. | |
| 75 | ||
| 76 | - **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing | |
| 77 | commas. | |
| 78 | ||
| 79 | - **allowReserved**: If `false`, using a reserved word will generate | |
| 80 | an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher | |
| 81 | versions. When given the value `"never"`, reserved words and | |
| 82 | keywords can also not be used as property names (as in Internet | |
| 83 | Explorer's old parser). | |
| 84 | ||
| 85 | - **allowReturnOutsideFunction**: By default, a return statement at | |
| 86 | the top level raises an error. Set this to `true` to accept such | |
| 87 | code. | |
| 88 | ||
| 89 | - **allowImportExportEverywhere**: By default, `import` and `export` | |
| 90 | declarations can only appear at a program's top level. Setting this | |
| 91 | option to `true` allows them anywhere where a statement is allowed, | |
| 92 | and also allows `import.meta` expressions to appear in scripts | |
| 93 | (when `sourceType` is not `"module"`). | |
| 94 | ||
| 95 | - **allowAwaitOutsideFunction**: If `false`, `await` expressions can | |
| 96 | only appear inside `async` functions. Defaults to `true` in modules | |
| 97 | for `ecmaVersion` 2022 and later, `false` for lower versions. | |
| 98 | Setting this option to `true` allows to have top-level `await` | |
| 99 | expressions. They are still not allowed in non-`async` functions, | |
| 100 | though. | |
| 101 | ||
| 102 | - **allowSuperOutsideMethod**: By default, `super` outside a method | |
| 103 | raises an error. Set this to `true` to accept such code. | |
| 104 | ||
| 105 | - **allowHashBang**: When this is enabled, if the code starts with the | |
| 106 | characters `#!` (as in a shellscript), the first line will be | |
| 107 | treated as a comment. Defaults to true when `ecmaVersion` >= 2023. | |
| 108 | ||
| 109 | - **checkPrivateFields**: By default, the parser will verify that | |
| 110 | private properties are only used in places where they are valid and | |
| 111 | have been declared. Set this to false to turn such checks off. | |
| 112 | ||
| 113 | - **locations**: When `true`, each node has a `loc` object attached | |
| 114 | with `start` and `end` subobjects, each of which contains the | |
| 115 | one-based line and zero-based column numbers in `{line, column}` | |
| 116 | form. Default is `false`. | |
| 117 | ||
| 118 | - **onToken**: If a function is passed for this option, each found | |
| 119 | token will be passed in same format as tokens returned from | |
| 120 | `tokenizer().getToken()`. | |
| 121 | ||
| 122 | If array is passed, each found token is pushed to it. | |
| 123 | ||
| 124 | Note that you are not allowed to call the parser from the | |
| 125 | callback—that will corrupt its internal state. | |
| 126 | ||
| 127 | - **onComment**: If a function is passed for this option, whenever a | |
| 128 | comment is encountered the function will be called with the | |
| 129 | following parameters: | |
| 130 | ||
| 131 | - `block`: `true` if the comment is a block comment, false if it | |
| 132 | is a line comment. | |
| 133 | - `text`: The content of the comment. | |
| 134 | - `start`: Character offset of the start of the comment. | |
| 135 | - `end`: Character offset of the end of the comment. | |
| 136 | ||
| 137 | When the `locations` options is on, the `{line, column}` locations | |
| 138 | of the comment’s start and end are passed as two additional | |
| 139 | parameters. | |
| 140 | ||
| 141 | If array is passed for this option, each found comment is pushed | |
| 142 | to it as object in Esprima format: | |
| 143 | ||
| 144 | ```javascript | |
| 145 | { | |
| 146 | "type": "Line" | "Block", | |
| 147 | "value": "comment text", | |
| 148 | "start": Number, | |
| 149 | "end": Number, | |
| 150 | // If `locations` option is on: | |
| 151 | "loc": { | |
| 152 | "start": {line: Number, column: Number} | |
| 153 | "end": {line: Number, column: Number} | |
| 154 | }, | |
| 155 | // If `ranges` option is on: | |
| 156 | "range": [Number, Number] | |
| 157 | } | |
| 158 | ``` | |
| 159 | ||
| 160 | Note that you are not allowed to call the parser from the | |
| 161 | callback—that will corrupt its internal state. | |
| 162 | ||
| 163 | - **ranges**: Nodes have their start and end characters offsets | |
| 164 | recorded in `start` and `end` properties (directly on the node, | |
| 165 | rather than the `loc` object, which holds line/column data. To also | |
| 166 | add a | |
| 167 | [semi-standardized](https://bugzilla.mozilla.org/show_bug.cgi?id=745678) | |
| 168 | `range` property holding a `[start, end]` array with the same | |
| 169 | numbers, set the `ranges` option to `true`. | |
| 170 | ||
| 171 | - **program**: It is possible to parse multiple files into a single | |
| 172 | AST by passing the tree produced by parsing the first file as the | |
| 173 | `program` option in subsequent parses. This will add the toplevel | |
| 174 | forms of the parsed file to the "Program" (top) node of an existing | |
| 175 | parse tree. | |
| 176 | ||
| 177 | - **sourceFile**: When the `locations` option is `true`, you can pass | |
| 178 | this option to add a `source` attribute in every node’s `loc` | |
| 179 | object. Note that the contents of this option are not examined or | |
| 180 | processed in any way; you are free to use whatever format you | |
| 181 | choose. | |
| 182 | ||
| 183 | - **directSourceFile**: Like `sourceFile`, but a `sourceFile` property | |
| 184 | will be added (regardless of the `location` option) directly to the | |
| 185 | nodes, rather than the `loc` object. | |
| 186 | ||
| 187 | - **preserveParens**: If this option is `true`, parenthesized expressions | |
| 188 | are represented by (non-standard) `ParenthesizedExpression` nodes | |
| 189 | that have a single `expression` property containing the expression | |
| 190 | inside parentheses. | |
| 191 | ||
| 192 | **parseExpressionAt**`(input, offset, options)` will parse a single | |
| 193 | expression in a string, and return its AST. It will not complain if | |
| 194 | there is more of the string left after the expression. | |
| 195 | ||
| 196 | **tokenizer**`(input, options)` returns an object with a `getToken` | |
| 197 | method that can be called repeatedly to get the next token, a `{start, | |
| 198 | end, type, value}` object (with added `loc` property when the | |
| 199 | `locations` option is enabled and `range` property when the `ranges` | |
| 200 | option is enabled). When the token's type is `tokTypes.eof`, you | |
| 201 | should stop calling the method, since it will keep returning that same | |
| 202 | token forever. | |
| 203 | ||
| 204 | Note that tokenizing JavaScript without parsing it is, in modern | |
| 205 | versions of the language, not really possible due to the way syntax is | |
| 206 | overloaded in ways that can only be disambiguated by the parse | |
| 207 | context. This package applies a bunch of heuristics to try and do a | |
| 208 | reasonable job, but you are advised to use `parse` with the `onToken` | |
| 209 | option instead of this. | |
| 210 | ||
| 211 | In ES6 environment, returned result can be used as any other | |
| 212 | protocol-compliant iterable: | |
| 213 | ||
| 214 | ```javascript | |
| 215 | for (let token of acorn.tokenizer(str)) { | |
| 216 | // iterate over the tokens | |
| 217 | } | |
| 218 | ||
| 219 | // transform code to array of tokens: | |
| 220 | var tokens = [...acorn.tokenizer(str)]; | |
| 221 | ``` | |
| 222 | ||
| 223 | **tokTypes** holds an object mapping names to the token type objects | |
| 224 | that end up in the `type` properties of tokens. | |
| 225 | ||
| 226 | **getLineInfo**`(input, offset)` can be used to get a `{line, | |
| 227 | column}` object for a given program string and offset. | |
| 228 | ||
| 229 | ### The `Parser` class | |
| 230 | ||
| 231 | Instances of the **`Parser`** class contain all the state and logic | |
| 232 | that drives a parse. It has static methods `parse`, | |
| 233 | `parseExpressionAt`, and `tokenizer` that match the top-level | |
| 234 | functions by the same name. | |
| 235 | ||
| 236 | When extending the parser with plugins, you need to call these methods | |
| 237 | on the extended version of the class. To extend a parser with plugins, | |
| 238 | you can use its static `extend` method. | |
| 239 | ||
| 240 | ```javascript | |
| 241 | var acorn = require("acorn"); | |
| 242 | var jsx = require("acorn-jsx"); | |
| 243 | var JSXParser = acorn.Parser.extend(jsx()); | |
| 244 | JSXParser.parse("foo(<bar/>)", {ecmaVersion: 2020}); | |
| 245 | ``` | |
| 246 | ||
| 247 | The `extend` method takes any number of plugin values, and returns a | |
| 248 | new `Parser` class that includes the extra parser logic provided by | |
| 249 | the plugins. | |
| 250 | ||
| 251 | ## Command line interface | |
| 252 | ||
| 253 | The `bin/acorn` utility can be used to parse a file from the command | |
| 254 | line. It accepts as arguments its input file and the following | |
| 255 | options: | |
| 256 | ||
| 257 | - `--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|--ecma10`: Sets the ECMAScript version | |
| 258 | to parse. Default is version 9. | |
| 259 | ||
| 260 | - `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise. | |
| 261 | ||
| 262 | - `--locations`: Attaches a "loc" object to each node with "start" and | |
| 263 | "end" subobjects, each of which contains the one-based line and | |
| 264 | zero-based column numbers in `{line, column}` form. | |
| 265 | ||
| 266 | - `--allow-hash-bang`: If the code starts with the characters #! (as | |
| 267 | in a shellscript), the first line will be treated as a comment. | |
| 268 | ||
| 269 | - `--allow-await-outside-function`: Allows top-level `await` expressions. | |
| 270 | See the `allowAwaitOutsideFunction` option for more information. | |
| 271 | ||
| 272 | - `--compact`: No whitespace is used in the AST output. | |
| 273 | ||
| 274 | - `--silent`: Do not output the AST, just return the exit status. | |
| 275 | ||
| 276 | - `--help`: Print the usage information and quit. | |
| 277 | ||
| 278 | The utility spits out the syntax tree as JSON data. | |
| 279 | ||
| 280 | ## Existing plugins | |
| 281 | ||
| 282 | - [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx) |
| … | … | @@ -0,0 +1,4 @@ |
| 1 | #!/usr/bin/env node | |
| 2 | "use strict" | |
| 3 | ||
| 4 | require("../dist/bin.js") |
| … | … | @@ -0,0 +1,883 @@ |
| 1 | export interface Node { | |
| 2 | start: number | |
| 3 | end: number | |
| 4 | type: string | |
| 5 | range?: [number, number] | |
| 6 | loc?: SourceLocation | null | |
| 7 | } | |
| 8 | ||
| 9 | export interface SourceLocation { | |
| 10 | source?: string | null | |
| 11 | start: Position | |
| 12 | end: Position | |
| 13 | } | |
| 14 | ||
| 15 | export interface Position { | |
| 16 | /** 1-based */ | |
| 17 | line: number | |
| 18 | /** 0-based */ | |
| 19 | column: number | |
| 20 | } | |
| 21 | ||
| 22 | export interface Identifier extends Node { | |
| 23 | type: "Identifier" | |
| 24 | name: string | |
| 25 | } | |
| 26 | ||
| 27 | export interface Literal extends Node { | |
| 28 | type: "Literal" | |
| 29 | value?: string | boolean | null | number | RegExp | bigint | |
| 30 | raw?: string | |
| 31 | regex?: { | |
| 32 | pattern: string | |
| 33 | flags: string | |
| 34 | } | |
| 35 | bigint?: string | |
| 36 | } | |
| 37 | ||
| 38 | export interface Program extends Node { | |
| 39 | type: "Program" | |
| 40 | body: Array<Statement | ModuleDeclaration> | |
| 41 | sourceType: "script" | "module" | |
| 42 | } | |
| 43 | ||
| 44 | export interface Function extends Node { | |
| 45 | id?: Identifier | null | |
| 46 | params: Array<Pattern> | |
| 47 | body: BlockStatement | Expression | |
| 48 | generator: boolean | |
| 49 | expression: boolean | |
| 50 | async: boolean | |
| 51 | } | |
| 52 | ||
| 53 | export interface ExpressionStatement extends Node { | |
| 54 | type: "ExpressionStatement" | |
| 55 | expression: Expression | Literal | |
| 56 | directive?: string | |
| 57 | } | |
| 58 | ||
| 59 | export interface BlockStatement extends Node { | |
| 60 | type: "BlockStatement" | |
| 61 | body: Array<Statement> | |
| 62 | } | |
| 63 | ||
| 64 | export interface EmptyStatement extends Node { | |
| 65 | type: "EmptyStatement" | |
| 66 | } | |
| 67 | ||
| 68 | export interface DebuggerStatement extends Node { | |
| 69 | type: "DebuggerStatement" | |
| 70 | } | |
| 71 | ||
| 72 | export interface WithStatement extends Node { | |
| 73 | type: "WithStatement" | |
| 74 | object: Expression | |
| 75 | body: Statement | |
| 76 | } | |
| 77 | ||
| 78 | export interface ReturnStatement extends Node { | |
| 79 | type: "ReturnStatement" | |
| 80 | argument?: Expression | null | |
| 81 | } | |
| 82 | ||
| 83 | export interface LabeledStatement extends Node { | |
| 84 | type: "LabeledStatement" | |
| 85 | label: Identifier | |
| 86 | body: Statement | |
| 87 | } | |
| 88 | ||
| 89 | export interface BreakStatement extends Node { | |
| 90 | type: "BreakStatement" | |
| 91 | label?: Identifier | null | |
| 92 | } | |
| 93 | ||
| 94 | export interface ContinueStatement extends Node { | |
| 95 | type: "ContinueStatement" | |
| 96 | label?: Identifier | null | |
| 97 | } | |
| 98 | ||
| 99 | export interface IfStatement extends Node { | |
| 100 | type: "IfStatement" | |
| 101 | test: Expression | |
| 102 | consequent: Statement | |
| 103 | alternate?: Statement | null | |
| 104 | } | |
| 105 | ||
| 106 | export interface SwitchStatement extends Node { | |
| 107 | type: "SwitchStatement" | |
| 108 | discriminant: Expression | |
| 109 | cases: Array<SwitchCase> | |
| 110 | } | |
| 111 | ||
| 112 | export interface SwitchCase extends Node { | |
| 113 | type: "SwitchCase" | |
| 114 | test?: Expression | null | |
| 115 | consequent: Array<Statement> | |
| 116 | } | |
| 117 | ||
| 118 | export interface ThrowStatement extends Node { | |
| 119 | type: "ThrowStatement" | |
| 120 | argument: Expression | |
| 121 | } | |
| 122 | ||
| 123 | export interface TryStatement extends Node { | |
| 124 | type: "TryStatement" | |
| 125 | block: BlockStatement | |
| 126 | handler?: CatchClause | null | |
| 127 | finalizer?: BlockStatement | null | |
| 128 | } | |
| 129 | ||
| 130 | export interface CatchClause extends Node { | |
| 131 | type: "CatchClause" | |
| 132 | param?: Pattern | null | |
| 133 | body: BlockStatement | |
| 134 | } | |
| 135 | ||
| 136 | export interface WhileStatement extends Node { | |
| 137 | type: "WhileStatement" | |
| 138 | test: Expression | |
| 139 | body: Statement | |
| 140 | } | |
| 141 | ||
| 142 | export interface DoWhileStatement extends Node { | |
| 143 | type: "DoWhileStatement" | |
| 144 | body: Statement | |
| 145 | test: Expression | |
| 146 | } | |
| 147 | ||
| 148 | export interface ForStatement extends Node { | |
| 149 | type: "ForStatement" | |
| 150 | init?: VariableDeclaration | Expression | null | |
| 151 | test?: Expression | null | |
| 152 | update?: Expression | null | |
| 153 | body: Statement | |
| 154 | } | |
| 155 | ||
| 156 | export interface ForInStatement extends Node { | |
| 157 | type: "ForInStatement" | |
| 158 | left: VariableDeclaration | Pattern | |
| 159 | right: Expression | |
| 160 | body: Statement | |
| 161 | } | |
| 162 | ||
| 163 | export interface FunctionDeclaration extends Function { | |
| 164 | type: "FunctionDeclaration" | |
| 165 | id: Identifier | |
| 166 | body: BlockStatement | |
| 167 | } | |
| 168 | ||
| 169 | export interface VariableDeclaration extends Node { | |
| 170 | type: "VariableDeclaration" | |
| 171 | declarations: Array<VariableDeclarator> | |
| 172 | kind: "var" | "let" | "const" | "using" | "await using" | |
| 173 | } | |
| 174 | ||
| 175 | export interface VariableDeclarator extends Node { | |
| 176 | type: "VariableDeclarator" | |
| 177 | id: Pattern | |
| 178 | init?: Expression | null | |
| 179 | } | |
| 180 | ||
| 181 | export interface ThisExpression extends Node { | |
| 182 | type: "ThisExpression" | |
| 183 | } | |
| 184 | ||
| 185 | export interface ArrayExpression extends Node { | |
| 186 | type: "ArrayExpression" | |
| 187 | elements: Array<Expression | SpreadElement | null> | |
| 188 | } | |
| 189 | ||
| 190 | export interface ObjectExpression extends Node { | |
| 191 | type: "ObjectExpression" | |
| 192 | properties: Array<Property | SpreadElement> | |
| 193 | } | |
| 194 | ||
| 195 | export interface Property extends Node { | |
| 196 | type: "Property" | |
| 197 | key: Expression | |
| 198 | value: Expression | |
| 199 | kind: "init" | "get" | "set" | |
| 200 | method: boolean | |
| 201 | shorthand: boolean | |
| 202 | computed: boolean | |
| 203 | } | |
| 204 | ||
| 205 | export interface FunctionExpression extends Function { | |
| 206 | type: "FunctionExpression" | |
| 207 | body: BlockStatement | |
| 208 | } | |
| 209 | ||
| 210 | export interface UnaryExpression extends Node { | |
| 211 | type: "UnaryExpression" | |
| 212 | operator: UnaryOperator | |
| 213 | prefix: boolean | |
| 214 | argument: Expression | |
| 215 | } | |
| 216 | ||
| 217 | export type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" | |
| 218 | ||
| 219 | export interface UpdateExpression extends Node { | |
| 220 | type: "UpdateExpression" | |
| 221 | operator: UpdateOperator | |
| 222 | argument: Expression | |
| 223 | prefix: boolean | |
| 224 | } | |
| 225 | ||
| 226 | export type UpdateOperator = "++" | "--" | |
| 227 | ||
| 228 | export interface BinaryExpression extends Node { | |
| 229 | type: "BinaryExpression" | |
| 230 | operator: BinaryOperator | |
| 231 | left: Expression | PrivateIdentifier | |
| 232 | right: Expression | |
| 233 | } | |
| 234 | ||
| 235 | export type BinaryOperator = "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in" | "instanceof" | "**" | |
| 236 | ||
| 237 | export interface AssignmentExpression extends Node { | |
| 238 | type: "AssignmentExpression" | |
| 239 | operator: AssignmentOperator | |
| 240 | left: Pattern | |
| 241 | right: Expression | |
| 242 | } | |
| 243 | ||
| 244 | export type AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" | "**=" | "||=" | "&&=" | "??=" | |
| 245 | ||
| 246 | export interface LogicalExpression extends Node { | |
| 247 | type: "LogicalExpression" | |
| 248 | operator: LogicalOperator | |
| 249 | left: Expression | |
| 250 | right: Expression | |
| 251 | } | |
| 252 | ||
| 253 | export type LogicalOperator = "||" | "&&" | "??" | |
| 254 | ||
| 255 | export interface MemberExpression extends Node { | |
| 256 | type: "MemberExpression" | |
| 257 | object: Expression | Super | |
| 258 | property: Expression | PrivateIdentifier | |
| 259 | computed: boolean | |
| 260 | optional: boolean | |
| 261 | } | |
| 262 | ||
| 263 | export interface ConditionalExpression extends Node { | |
| 264 | type: "ConditionalExpression" | |
| 265 | test: Expression | |
| 266 | alternate: Expression | |
| 267 | consequent: Expression | |
| 268 | } | |
| 269 | ||
| 270 | export interface CallExpression extends Node { | |
| 271 | type: "CallExpression" | |
| 272 | callee: Expression | Super | |
| 273 | arguments: Array<Expression | SpreadElement> | |
| 274 | optional: boolean | |
| 275 | } | |
| 276 | ||
| 277 | export interface NewExpression extends Node { | |
| 278 | type: "NewExpression" | |
| 279 | callee: Expression | |
| 280 | arguments: Array<Expression | SpreadElement> | |
| 281 | } | |
| 282 | ||
| 283 | export interface SequenceExpression extends Node { | |
| 284 | type: "SequenceExpression" | |
| 285 | expressions: Array<Expression> | |
| 286 | } | |
| 287 | ||
| 288 | export interface ForOfStatement extends Node { | |
| 289 | type: "ForOfStatement" | |
| 290 | left: VariableDeclaration | Pattern | |
| 291 | right: Expression | |
| 292 | body: Statement | |
| 293 | await: boolean | |
| 294 | } | |
| 295 | ||
| 296 | export interface Super extends Node { | |
| 297 | type: "Super" | |
| 298 | } | |
| 299 | ||
| 300 | export interface SpreadElement extends Node { | |
| 301 | type: "SpreadElement" | |
| 302 | argument: Expression | |
| 303 | } | |
| 304 | ||
| 305 | export interface ArrowFunctionExpression extends Function { | |
| 306 | type: "ArrowFunctionExpression" | |
| 307 | } | |
| 308 | ||
| 309 | export interface YieldExpression extends Node { | |
| 310 | type: "YieldExpression" | |
| 311 | argument?: Expression | null | |
| 312 | delegate: boolean | |
| 313 | } | |
| 314 | ||
| 315 | export interface TemplateLiteral extends Node { | |
| 316 | type: "TemplateLiteral" | |
| 317 | quasis: Array<TemplateElement> | |
| 318 | expressions: Array<Expression> | |
| 319 | } | |
| 320 | ||
| 321 | export interface TaggedTemplateExpression extends Node { | |
| 322 | type: "TaggedTemplateExpression" | |
| 323 | tag: Expression | |
| 324 | quasi: TemplateLiteral | |
| 325 | } | |
| 326 | ||
| 327 | export interface TemplateElement extends Node { | |
| 328 | type: "TemplateElement" | |
| 329 | tail: boolean | |
| 330 | value: { | |
| 331 | cooked?: string | null | |
| 332 | raw: string | |
| 333 | } | |
| 334 | } | |
| 335 | ||
| 336 | export interface AssignmentProperty extends Node { | |
| 337 | type: "Property" | |
| 338 | key: Expression | |
| 339 | value: Pattern | |
| 340 | kind: "init" | |
| 341 | method: false | |
| 342 | shorthand: boolean | |
| 343 | computed: boolean | |
| 344 | } | |
| 345 | ||
| 346 | export interface ObjectPattern extends Node { | |
| 347 | type: "ObjectPattern" | |
| 348 | properties: Array<AssignmentProperty | RestElement> | |
| 349 | } | |
| 350 | ||
| 351 | export interface ArrayPattern extends Node { | |
| 352 | type: "ArrayPattern" | |
| 353 | elements: Array<Pattern | null> | |
| 354 | } | |
| 355 | ||
| 356 | export interface RestElement extends Node { | |
| 357 | type: "RestElement" | |
| 358 | argument: Pattern | |
| 359 | } | |
| 360 | ||
| 361 | export interface AssignmentPattern extends Node { | |
| 362 | type: "AssignmentPattern" | |
| 363 | left: Pattern | |
| 364 | right: Expression | |
| 365 | } | |
| 366 | ||
| 367 | export interface Class extends Node { | |
| 368 | id?: Identifier | null | |
| 369 | superClass?: Expression | null | |
| 370 | body: ClassBody | |
| 371 | } | |
| 372 | ||
| 373 | export interface ClassBody extends Node { | |
| 374 | type: "ClassBody" | |
| 375 | body: Array<MethodDefinition | PropertyDefinition | StaticBlock> | |
| 376 | } | |
| 377 | ||
| 378 | export interface MethodDefinition extends Node { | |
| 379 | type: "MethodDefinition" | |
| 380 | key: Expression | PrivateIdentifier | |
| 381 | value: FunctionExpression | |
| 382 | kind: "constructor" | "method" | "get" | "set" | |
| 383 | computed: boolean | |
| 384 | static: boolean | |
| 385 | } | |
| 386 | ||
| 387 | export interface ClassDeclaration extends Class { | |
| 388 | type: "ClassDeclaration" | |
| 389 | id: Identifier | |
| 390 | } | |
| 391 | ||
| 392 | export interface ClassExpression extends Class { | |
| 393 | type: "ClassExpression" | |
| 394 | } | |
| 395 | ||
| 396 | export interface MetaProperty extends Node { | |
| 397 | type: "MetaProperty" | |
| 398 | meta: Identifier | |
| 399 | property: Identifier | |
| 400 | } | |
| 401 | ||
| 402 | export interface ImportDeclaration extends Node { | |
| 403 | type: "ImportDeclaration" | |
| 404 | specifiers: Array<ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier> | |
| 405 | source: Literal | |
| 406 | attributes: Array<ImportAttribute> | |
| 407 | } | |
| 408 | ||
| 409 | export interface ImportSpecifier extends Node { | |
| 410 | type: "ImportSpecifier" | |
| 411 | imported: Identifier | Literal | |
| 412 | local: Identifier | |
| 413 | } | |
| 414 | ||
| 415 | export interface ImportDefaultSpecifier extends Node { | |
| 416 | type: "ImportDefaultSpecifier" | |
| 417 | local: Identifier | |
| 418 | } | |
| 419 | ||
| 420 | export interface ImportNamespaceSpecifier extends Node { | |
| 421 | type: "ImportNamespaceSpecifier" | |
| 422 | local: Identifier | |
| 423 | } | |
| 424 | ||
| 425 | export interface ImportAttribute extends Node { | |
| 426 | type: "ImportAttribute" | |
| 427 | key: Identifier | Literal | |
| 428 | value: Literal | |
| 429 | } | |
| 430 | ||
| 431 | export interface ExportNamedDeclaration extends Node { | |
| 432 | type: "ExportNamedDeclaration" | |
| 433 | declaration?: Declaration | null | |
| 434 | specifiers: Array<ExportSpecifier> | |
| 435 | source?: Literal | null | |
| 436 | attributes: Array<ImportAttribute> | |
| 437 | } | |
| 438 | ||
| 439 | export interface ExportSpecifier extends Node { | |
| 440 | type: "ExportSpecifier" | |
| 441 | exported: Identifier | Literal | |
| 442 | local: Identifier | Literal | |
| 443 | } | |
| 444 | ||
| 445 | export interface AnonymousFunctionDeclaration extends Function { | |
| 446 | type: "FunctionDeclaration" | |
| 447 | id: null | |
| 448 | body: BlockStatement | |
| 449 | } | |
| 450 | ||
| 451 | export interface AnonymousClassDeclaration extends Class { | |
| 452 | type: "ClassDeclaration" | |
| 453 | id: null | |
| 454 | } | |
| 455 | ||
| 456 | export interface ExportDefaultDeclaration extends Node { | |
| 457 | type: "ExportDefaultDeclaration" | |
| 458 | declaration: AnonymousFunctionDeclaration | FunctionDeclaration | AnonymousClassDeclaration | ClassDeclaration | Expression | |
| 459 | } | |
| 460 | ||
| 461 | export interface ExportAllDeclaration extends Node { | |
| 462 | type: "ExportAllDeclaration" | |
| 463 | source: Literal | |
| 464 | exported?: Identifier | Literal | null | |
| 465 | attributes: Array<ImportAttribute> | |
| 466 | } | |
| 467 | ||
| 468 | export interface AwaitExpression extends Node { | |
| 469 | type: "AwaitExpression" | |
| 470 | argument: Expression | |
| 471 | } | |
| 472 | ||
| 473 | export interface ChainExpression extends Node { | |
| 474 | type: "ChainExpression" | |
| 475 | expression: MemberExpression | CallExpression | |
| 476 | } | |
| 477 | ||
| 478 | export interface ImportExpression extends Node { | |
| 479 | type: "ImportExpression" | |
| 480 | source: Expression | |
| 481 | options: Expression | null | |
| 482 | } | |
| 483 | ||
| 484 | export interface ParenthesizedExpression extends Node { | |
| 485 | type: "ParenthesizedExpression" | |
| 486 | expression: Expression | |
| 487 | } | |
| 488 | ||
| 489 | export interface PropertyDefinition extends Node { | |
| 490 | type: "PropertyDefinition" | |
| 491 | key: Expression | PrivateIdentifier | |
| 492 | value?: Expression | null | |
| 493 | computed: boolean | |
| 494 | static: boolean | |
| 495 | } | |
| 496 | ||
| 497 | export interface PrivateIdentifier extends Node { | |
| 498 | type: "PrivateIdentifier" | |
| 499 | name: string | |
| 500 | } | |
| 501 | ||
| 502 | export interface StaticBlock extends Node { | |
| 503 | type: "StaticBlock" | |
| 504 | body: Array<Statement> | |
| 505 | } | |
| 506 | ||
| 507 | export type Statement = | |
| 508 | | ExpressionStatement | |
| 509 | | BlockStatement | |
| 510 | | EmptyStatement | |
| 511 | | DebuggerStatement | |
| 512 | | WithStatement | |
| 513 | | ReturnStatement | |
| 514 | | LabeledStatement | |
| 515 | | BreakStatement | |
| 516 | | ContinueStatement | |
| 517 | | IfStatement | |
| 518 | | SwitchStatement | |
| 519 | | ThrowStatement | |
| 520 | | TryStatement | |
| 521 | | WhileStatement | |
| 522 | | DoWhileStatement | |
| 523 | | ForStatement | |
| 524 | | ForInStatement | |
| 525 | | ForOfStatement | |
| 526 | | Declaration | |
| 527 | ||
| 528 | export type Declaration = | |
| 529 | | FunctionDeclaration | |
| 530 | | VariableDeclaration | |
| 531 | | ClassDeclaration | |
| 532 | ||
| 533 | export type Expression = | |
| 534 | | Identifier | |
| 535 | | Literal | |
| 536 | | ThisExpression | |
| 537 | | ArrayExpression | |
| 538 | | ObjectExpression | |
| 539 | | FunctionExpression | |
| 540 | | UnaryExpression | |
| 541 | | UpdateExpression | |
| 542 | | BinaryExpression | |
| 543 | | AssignmentExpression | |
| 544 | | LogicalExpression | |
| 545 | | MemberExpression | |
| 546 | | ConditionalExpression | |
| 547 | | CallExpression | |
| 548 | | NewExpression | |
| 549 | | SequenceExpression | |
| 550 | | ArrowFunctionExpression | |
| 551 | | YieldExpression | |
| 552 | | TemplateLiteral | |
| 553 | | TaggedTemplateExpression | |
| 554 | | ClassExpression | |
| 555 | | MetaProperty | |
| 556 | | AwaitExpression | |
| 557 | | ChainExpression | |
| 558 | | ImportExpression | |
| 559 | | ParenthesizedExpression | |
| 560 | ||
| 561 | export type Pattern = | |
| 562 | | Identifier | |
| 563 | | MemberExpression | |
| 564 | | ObjectPattern | |
| 565 | | ArrayPattern | |
| 566 | | RestElement | |
| 567 | | AssignmentPattern | |
| 568 | ||
| 569 | export type ModuleDeclaration = | |
| 570 | | ImportDeclaration | |
| 571 | | ExportNamedDeclaration | |
| 572 | | ExportDefaultDeclaration | |
| 573 | | ExportAllDeclaration | |
| 574 | ||
| 575 | /** | |
| 576 | * This interface is only used for defining {@link AnyNode}. | |
| 577 | * It exists so that it can be extended by plugins: | |
| 578 | * | |
| 579 | * @example | |
| 580 | * ```typescript | |
| 581 | * declare module 'acorn' { | |
| 582 | * interface NodeTypes { | |
| 583 | * pluginName: FirstNode | SecondNode | ThirdNode | ... | LastNode | |
| 584 | * } | |
| 585 | * } | |
| 586 | * ``` | |
| 587 | */ | |
| 588 | interface NodeTypes { | |
| 589 | core: Statement | Expression | Declaration | ModuleDeclaration | Literal | Program | SwitchCase | CatchClause | Property | Super | SpreadElement | TemplateElement | AssignmentProperty | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | ClassBody | MethodDefinition | MetaProperty | ImportAttribute | ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier | AnonymousFunctionDeclaration | AnonymousClassDeclaration | PropertyDefinition | PrivateIdentifier | StaticBlock | VariableDeclarator | |
| 590 | } | |
| 591 | ||
| 592 | export type AnyNode = NodeTypes[keyof NodeTypes] | |
| 593 | ||
| 594 | export function parse(input: string, options: Options): Program | |
| 595 | ||
| 596 | export function parseExpressionAt(input: string, pos: number, options: Options): Expression | |
| 597 | ||
| 598 | export function tokenizer(input: string, options: Options): { | |
| 599 | getToken(): Token | |
| 600 | [Symbol.iterator](): Iterator<Token> | |
| 601 | } | |
| 602 | ||
| 603 | export type ecmaVersion = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | "latest" | |
| 604 | ||
| 605 | export interface Options { | |
| 606 | /** | |
| 607 | * `ecmaVersion` indicates the ECMAScript version to parse. Can be a | |
| 608 | * number, either in year (`2022`) or plain version number (`6`) form, | |
| 609 | * or `"latest"` (the latest the library supports). This influences | |
| 610 | * support for strict mode, the set of reserved words, and support for | |
| 611 | * new syntax features. | |
| 612 | */ | |
| 613 | ecmaVersion: ecmaVersion | |
| 614 | ||
| 615 | /** | |
| 616 | * `sourceType` indicates the mode the code should be parsed in. | |
| 617 | * Can be either `"script"` or `"module"`. This influences global | |
| 618 | * strict mode and parsing of `import` and `export` declarations. | |
| 619 | */ | |
| 620 | sourceType?: "script" | "module" | |
| 621 | ||
| 622 | /** | |
| 623 | * a callback that will be called when a semicolon is automatically inserted. | |
| 624 | * @param lastTokEnd the position of the comma as an offset | |
| 625 | * @param lastTokEndLoc location if {@link locations} is enabled | |
| 626 | */ | |
| 627 | onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void | |
| 628 | ||
| 629 | /** | |
| 630 | * similar to `onInsertedSemicolon`, but for trailing commas | |
| 631 | * @param lastTokEnd the position of the comma as an offset | |
| 632 | * @param lastTokEndLoc location if `locations` is enabled | |
| 633 | */ | |
| 634 | onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void | |
| 635 | ||
| 636 | /** | |
| 637 | * By default, reserved words are only enforced if ecmaVersion >= 5. | |
| 638 | * Set `allowReserved` to a boolean value to explicitly turn this on | |
| 639 | * an off. When this option has the value "never", reserved words | |
| 640 | * and keywords can also not be used as property names. | |
| 641 | */ | |
| 642 | allowReserved?: boolean | "never" | |
| 643 | ||
| 644 | /** | |
| 645 | * When enabled, a return at the top level is not considered an error. | |
| 646 | */ | |
| 647 | allowReturnOutsideFunction?: boolean | |
| 648 | ||
| 649 | /** | |
| 650 | * When enabled, import/export statements are not constrained to | |
| 651 | * appearing at the top of the program, and an import.meta expression | |
| 652 | * in a script isn't considered an error. | |
| 653 | */ | |
| 654 | allowImportExportEverywhere?: boolean | |
| 655 | ||
| 656 | /** | |
| 657 | * By default, `await` identifiers are allowed to appear at the top-level scope only if {@link ecmaVersion} >= 2022. | |
| 658 | * When enabled, await identifiers are allowed to appear at the top-level scope, | |
| 659 | * but they are still not allowed in non-async functions. | |
| 660 | */ | |
| 661 | allowAwaitOutsideFunction?: boolean | |
| 662 | ||
| 663 | /** | |
| 664 | * When enabled, super identifiers are not constrained to | |
| 665 | * appearing in methods and do not raise an error when they appear elsewhere. | |
| 666 | */ | |
| 667 | allowSuperOutsideMethod?: boolean | |
| 668 | ||
| 669 | /** | |
| 670 | * When enabled, hashbang directive in the beginning of file is | |
| 671 | * allowed and treated as a line comment. Enabled by default when | |
| 672 | * {@link ecmaVersion} >= 2023. | |
| 673 | */ | |
| 674 | allowHashBang?: boolean | |
| 675 | ||
| 676 | /** | |
| 677 | * By default, the parser will verify that private properties are | |
| 678 | * only used in places where they are valid and have been declared. | |
| 679 | * Set this to false to turn such checks off. | |
| 680 | */ | |
| 681 | checkPrivateFields?: boolean | |
| 682 | ||
| 683 | /** | |
| 684 | * When `locations` is on, `loc` properties holding objects with | |
| 685 | * `start` and `end` properties as {@link Position} objects will be attached to the | |
| 686 | * nodes. | |
| 687 | */ | |
| 688 | locations?: boolean | |
| 689 | ||
| 690 | /** | |
| 691 | * a callback that will cause Acorn to call that export function with object in the same | |
| 692 | * format as tokens returned from `tokenizer().getToken()`. Note | |
| 693 | * that you are not allowed to call the parser from the | |
| 694 | * callback—that will corrupt its internal state. | |
| 695 | */ | |
| 696 | onToken?: ((token: Token) => void) | Token[] | |
| 697 | ||
| 698 | ||
| 699 | /** | |
| 700 | * This takes a export function or an array. | |
| 701 | * | |
| 702 | * When a export function is passed, Acorn will call that export function with `(block, text, start, | |
| 703 | * end)` parameters whenever a comment is skipped. `block` is a | |
| 704 | * boolean indicating whether this is a block (`/* *\/`) comment, | |
| 705 | * `text` is the content of the comment, and `start` and `end` are | |
| 706 | * character offsets that denote the start and end of the comment. | |
| 707 | * When the {@link locations} option is on, two more parameters are | |
| 708 | * passed, the full locations of {@link Position} export type of the start and | |
| 709 | * end of the comments. | |
| 710 | * | |
| 711 | * When a array is passed, each found comment of {@link Comment} export type is pushed to the array. | |
| 712 | * | |
| 713 | * Note that you are not allowed to call the | |
| 714 | * parser from the callback—that will corrupt its internal state. | |
| 715 | */ | |
| 716 | onComment?: (( | |
| 717 | isBlock: boolean, text: string, start: number, end: number, startLoc?: Position, | |
| 718 | endLoc?: Position | |
| 719 | ) => void) | Comment[] | |
| 720 | ||
| 721 | /** | |
| 722 | * Nodes have their start and end characters offsets recorded in | |
| 723 | * `start` and `end` properties (directly on the node, rather than | |
| 724 | * the `loc` object, which holds line/column data. To also add a | |
| 725 | * [semi-standardized][range] `range` property holding a `[start, | |
| 726 | * end]` array with the same numbers, set the `ranges` option to | |
| 727 | * `true`. | |
| 728 | */ | |
| 729 | ranges?: boolean | |
| 730 | ||
| 731 | /** | |
| 732 | * It is possible to parse multiple files into a single AST by | |
| 733 | * passing the tree produced by parsing the first file as | |
| 734 | * `program` option in subsequent parses. This will add the | |
| 735 | * toplevel forms of the parsed file to the `Program` (top) node | |
| 736 | * of an existing parse tree. | |
| 737 | */ | |
| 738 | program?: Node | |
| 739 | ||
| 740 | /** | |
| 741 | * When {@link locations} is on, you can pass this to record the source | |
| 742 | * file in every node's `loc` object. | |
| 743 | */ | |
| 744 | sourceFile?: string | |
| 745 | ||
| 746 | /** | |
| 747 | * This value, if given, is stored in every node, whether {@link locations} is on or off. | |
| 748 | */ | |
| 749 | directSourceFile?: string | |
| 750 | ||
| 751 | /** | |
| 752 | * When enabled, parenthesized expressions are represented by | |
| 753 | * (non-standard) ParenthesizedExpression nodes | |
| 754 | */ | |
| 755 | preserveParens?: boolean | |
| 756 | } | |
| 757 | ||
| 758 | export class Parser { | |
| 759 | options: Options | |
| 760 | input: string | |
| 761 | ||
| 762 | protected constructor(options: Options, input: string, startPos?: number) | |
| 763 | parse(): Program | |
| 764 | ||
| 765 | static parse(input: string, options: Options): Program | |
| 766 | static parseExpressionAt(input: string, pos: number, options: Options): Expression | |
| 767 | static tokenizer(input: string, options: Options): { | |
| 768 | getToken(): Token | |
| 769 | [Symbol.iterator](): Iterator<Token> | |
| 770 | } | |
| 771 | static extend(...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser | |
| 772 | } | |
| 773 | ||
| 774 | export const defaultOptions: Options | |
| 775 | ||
| 776 | export function getLineInfo(input: string, offset: number): Position | |
| 777 | ||
| 778 | export class TokenType { | |
| 779 | label: string | |
| 780 | keyword: string | undefined | |
| 781 | } | |
| 782 | ||
| 783 | export const tokTypes: { | |
| 784 | num: TokenType | |
| 785 | regexp: TokenType | |
| 786 | string: TokenType | |
| 787 | name: TokenType | |
| 788 | privateId: TokenType | |
| 789 | eof: TokenType | |
| 790 | ||
| 791 | bracketL: TokenType | |
| 792 | bracketR: TokenType | |
| 793 | braceL: TokenType | |
| 794 | braceR: TokenType | |
| 795 | parenL: TokenType | |
| 796 | parenR: TokenType | |
| 797 | comma: TokenType | |
| 798 | semi: TokenType | |
| 799 | colon: TokenType | |
| 800 | dot: TokenType | |
| 801 | question: TokenType | |
| 802 | questionDot: TokenType | |
| 803 | arrow: TokenType | |
| 804 | template: TokenType | |
| 805 | invalidTemplate: TokenType | |
| 806 | ellipsis: TokenType | |
| 807 | backQuote: TokenType | |
| 808 | dollarBraceL: TokenType | |
| 809 | ||
| 810 | eq: TokenType | |
| 811 | assign: TokenType | |
| 812 | incDec: TokenType | |
| 813 | prefix: TokenType | |
| 814 | logicalOR: TokenType | |
| 815 | logicalAND: TokenType | |
| 816 | bitwiseOR: TokenType | |
| 817 | bitwiseXOR: TokenType | |
| 818 | bitwiseAND: TokenType | |
| 819 | equality: TokenType | |
| 820 | relational: TokenType | |
| 821 | bitShift: TokenType | |
| 822 | plusMin: TokenType | |
| 823 | modulo: TokenType | |
| 824 | star: TokenType | |
| 825 | slash: TokenType | |
| 826 | starstar: TokenType | |
| 827 | coalesce: TokenType | |
| 828 | ||
| 829 | _break: TokenType | |
| 830 | _case: TokenType | |
| 831 | _catch: TokenType | |
| 832 | _continue: TokenType | |
| 833 | _debugger: TokenType | |
| 834 | _default: TokenType | |
| 835 | _do: TokenType | |
| 836 | _else: TokenType | |
| 837 | _finally: TokenType | |
| 838 | _for: TokenType | |
| 839 | _function: TokenType | |
| 840 | _if: TokenType | |
| 841 | _return: TokenType | |
| 842 | _switch: TokenType | |
| 843 | _throw: TokenType | |
| 844 | _try: TokenType | |
| 845 | _var: TokenType | |
| 846 | _const: TokenType | |
| 847 | _while: TokenType | |
| 848 | _with: TokenType | |
| 849 | _new: TokenType | |
| 850 | _this: TokenType | |
| 851 | _super: TokenType | |
| 852 | _class: TokenType | |
| 853 | _extends: TokenType | |
| 854 | _export: TokenType | |
| 855 | _import: TokenType | |
| 856 | _null: TokenType | |
| 857 | _true: TokenType | |
| 858 | _false: TokenType | |
| 859 | _in: TokenType | |
| 860 | _instanceof: TokenType | |
| 861 | _typeof: TokenType | |
| 862 | _void: TokenType | |
| 863 | _delete: TokenType | |
| 864 | } | |
| 865 | ||
| 866 | export interface Comment { | |
| 867 | type: "Line" | "Block" | |
| 868 | value: string | |
| 869 | start: number | |
| 870 | end: number | |
| 871 | loc?: SourceLocation | |
| 872 | range?: [number, number] | |
| 873 | } | |
| 874 | ||
| 875 | export class Token { | |
| 876 | type: TokenType | |
| 877 | start: number | |
| 878 | end: number | |
| 879 | loc?: SourceLocation | |
| 880 | range?: [number, number] | |
| 881 | } | |
| 882 | ||
| 883 | export const version: string |
| … | … | @@ -0,0 +1,883 @@ |
| 1 | export interface Node { | |
| 2 | start: number | |
| 3 | end: number | |
| 4 | type: string | |
| 5 | range?: [number, number] | |
| 6 | loc?: SourceLocation | null | |
| 7 | } | |
| 8 | ||
| 9 | export interface SourceLocation { | |
| 10 | source?: string | null | |
| 11 | start: Position | |
| 12 | end: Position | |
| 13 | } | |
| 14 | ||
| 15 | export interface Position { | |
| 16 | /** 1-based */ | |
| 17 | line: number | |
| 18 | /** 0-based */ | |
| 19 | column: number | |
| 20 | } | |
| 21 | ||
| 22 | export interface Identifier extends Node { | |
| 23 | type: "Identifier" | |
| 24 | name: string | |
| 25 | } | |
| 26 | ||
| 27 | export interface Literal extends Node { | |
| 28 | type: "Literal" | |
| 29 | value?: string | boolean | null | number | RegExp | bigint | |
| 30 | raw?: string | |
| 31 | regex?: { | |
| 32 | pattern: string | |
| 33 | flags: string | |
| 34 | } | |
| 35 | bigint?: string | |
| 36 | } | |
| 37 | ||
| 38 | export interface Program extends Node { | |
| 39 | type: "Program" | |
| 40 | body: Array<Statement | ModuleDeclaration> | |
| 41 | sourceType: "script" | "module" | |
| 42 | } | |
| 43 | ||
| 44 | export interface Function extends Node { | |
| 45 | id?: Identifier | null | |
| 46 | params: Array<Pattern> | |
| 47 | body: BlockStatement | Expression | |
| 48 | generator: boolean | |
| 49 | expression: boolean | |
| 50 | async: boolean | |
| 51 | } | |
| 52 | ||
| 53 | export interface ExpressionStatement extends Node { | |
| 54 | type: "ExpressionStatement" | |
| 55 | expression: Expression | Literal | |
| 56 | directive?: string | |
| 57 | } | |
| 58 | ||
| 59 | export interface BlockStatement extends Node { | |
| 60 | type: "BlockStatement" | |
| 61 | body: Array<Statement> | |
| 62 | } | |
| 63 | ||
| 64 | export interface EmptyStatement extends Node { | |
| 65 | type: "EmptyStatement" | |
| 66 | } | |
| 67 | ||
| 68 | export interface DebuggerStatement extends Node { | |
| 69 | type: "DebuggerStatement" | |
| 70 | } | |
| 71 | ||
| 72 | export interface WithStatement extends Node { | |
| 73 | type: "WithStatement" | |
| 74 | object: Expression | |
| 75 | body: Statement | |
| 76 | } | |
| 77 | ||
| 78 | export interface ReturnStatement extends Node { | |
| 79 | type: "ReturnStatement" | |
| 80 | argument?: Expression | null | |
| 81 | } | |
| 82 | ||
| 83 | export interface LabeledStatement extends Node { | |
| 84 | type: "LabeledStatement" | |
| 85 | label: Identifier | |
| 86 | body: Statement | |
| 87 | } | |
| 88 | ||
| 89 | export interface BreakStatement extends Node { | |
| 90 | type: "BreakStatement" | |
| 91 | label?: Identifier | null | |
| 92 | } | |
| 93 | ||
| 94 | export interface ContinueStatement extends Node { | |
| 95 | type: "ContinueStatement" | |
| 96 | label?: Identifier | null | |
| 97 | } | |
| 98 | ||
| 99 | export interface IfStatement extends Node { | |
| 100 | type: "IfStatement" | |
| 101 | test: Expression | |
| 102 | consequent: Statement | |
| 103 | alternate?: Statement | null | |
| 104 | } | |
| 105 | ||
| 106 | export interface SwitchStatement extends Node { | |
| 107 | type: "SwitchStatement" | |
| 108 | discriminant: Expression | |
| 109 | cases: Array<SwitchCase> | |
| 110 | } | |
| 111 | ||
| 112 | export interface SwitchCase extends Node { | |
| 113 | type: "SwitchCase" | |
| 114 | test?: Expression | null | |
| 115 | consequent: Array<Statement> | |
| 116 | } | |
| 117 | ||
| 118 | export interface ThrowStatement extends Node { | |
| 119 | type: "ThrowStatement" | |
| 120 | argument: Expression | |
| 121 | } | |
| 122 | ||
| 123 | export interface TryStatement extends Node { | |
| 124 | type: "TryStatement" | |
| 125 | block: BlockStatement | |
| 126 | handler?: CatchClause | null | |
| 127 | finalizer?: BlockStatement | null | |
| 128 | } | |
| 129 | ||
| 130 | export interface CatchClause extends Node { | |
| 131 | type: "CatchClause" | |
| 132 | param?: Pattern | null | |
| 133 | body: BlockStatement | |
| 134 | } | |
| 135 | ||
| 136 | export interface WhileStatement extends Node { | |
| 137 | type: "WhileStatement" | |
| 138 | test: Expression | |
| 139 | body: Statement | |
| 140 | } | |
| 141 | ||
| 142 | export interface DoWhileStatement extends Node { | |
| 143 | type: "DoWhileStatement" | |
| 144 | body: Statement | |
| 145 | test: Expression | |
| 146 | } | |
| 147 | ||
| 148 | export interface ForStatement extends Node { | |
| 149 | type: "ForStatement" | |
| 150 | init?: VariableDeclaration | Expression | null | |
| 151 | test?: Expression | null | |
| 152 | update?: Expression | null | |
| 153 | body: Statement | |
| 154 | } | |
| 155 | ||
| 156 | export interface ForInStatement extends Node { | |
| 157 | type: "ForInStatement" | |
| 158 | left: VariableDeclaration | Pattern | |
| 159 | right: Expression | |
| 160 | body: Statement | |
| 161 | } | |
| 162 | ||
| 163 | export interface FunctionDeclaration extends Function { | |
| 164 | type: "FunctionDeclaration" | |
| 165 | id: Identifier | |
| 166 | body: BlockStatement | |
| 167 | } | |
| 168 | ||
| 169 | export interface VariableDeclaration extends Node { | |
| 170 | type: "VariableDeclaration" | |
| 171 | declarations: Array<VariableDeclarator> | |
| 172 | kind: "var" | "let" | "const" | "using" | "await using" | |
| 173 | } | |
| 174 | ||
| 175 | export interface VariableDeclarator extends Node { | |
| 176 | type: "VariableDeclarator" | |
| 177 | id: Pattern | |
| 178 | init?: Expression | null | |
| 179 | } | |
| 180 | ||
| 181 | export interface ThisExpression extends Node { | |
| 182 | type: "ThisExpression" | |
| 183 | } | |
| 184 | ||
| 185 | export interface ArrayExpression extends Node { | |
| 186 | type: "ArrayExpression" | |
| 187 | elements: Array<Expression | SpreadElement | null> | |
| 188 | } | |
| 189 | ||
| 190 | export interface ObjectExpression extends Node { | |
| 191 | type: "ObjectExpression" | |
| 192 | properties: Array<Property | SpreadElement> | |
| 193 | } | |
| 194 | ||
| 195 | export interface Property extends Node { | |
| 196 | type: "Property" | |
| 197 | key: Expression | |
| 198 | value: Expression | |
| 199 | kind: "init" | "get" | "set" | |
| 200 | method: boolean | |
| 201 | shorthand: boolean | |
| 202 | computed: boolean | |
| 203 | } | |
| 204 | ||
| 205 | export interface FunctionExpression extends Function { | |
| 206 | type: "FunctionExpression" | |
| 207 | body: BlockStatement | |
| 208 | } | |
| 209 | ||
| 210 | export interface UnaryExpression extends Node { | |
| 211 | type: "UnaryExpression" | |
| 212 | operator: UnaryOperator | |
| 213 | prefix: boolean | |
| 214 | argument: Expression | |
| 215 | } | |
| 216 | ||
| 217 | export type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" | |
| 218 | ||
| 219 | export interface UpdateExpression extends Node { | |
| 220 | type: "UpdateExpression" | |
| 221 | operator: UpdateOperator | |
| 222 | argument: Expression | |
| 223 | prefix: boolean | |
| 224 | } | |
| 225 | ||
| 226 | export type UpdateOperator = "++" | "--" | |
| 227 | ||
| 228 | export interface BinaryExpression extends Node { | |
| 229 | type: "BinaryExpression" | |
| 230 | operator: BinaryOperator | |
| 231 | left: Expression | PrivateIdentifier | |
| 232 | right: Expression | |
| 233 | } | |
| 234 | ||
| 235 | export type BinaryOperator = "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in" | "instanceof" | "**" | |
| 236 | ||
| 237 | export interface AssignmentExpression extends Node { | |
| 238 | type: "AssignmentExpression" | |
| 239 | operator: AssignmentOperator | |
| 240 | left: Pattern | |
| 241 | right: Expression | |
| 242 | } | |
| 243 | ||
| 244 | export type AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" | "**=" | "||=" | "&&=" | "??=" | |
| 245 | ||
| 246 | export interface LogicalExpression extends Node { | |
| 247 | type: "LogicalExpression" | |
| 248 | operator: LogicalOperator | |
| 249 | left: Expression | |
| 250 | right: Expression | |
| 251 | } | |
| 252 | ||
| 253 | export type LogicalOperator = "||" | "&&" | "??" | |
| 254 | ||
| 255 | export interface MemberExpression extends Node { | |
| 256 | type: "MemberExpression" | |
| 257 | object: Expression | Super | |
| 258 | property: Expression | PrivateIdentifier | |
| 259 | computed: boolean | |
| 260 | optional: boolean | |
| 261 | } | |
| 262 | ||
| 263 | export interface ConditionalExpression extends Node { | |
| 264 | type: "ConditionalExpression" | |
| 265 | test: Expression | |
| 266 | alternate: Expression | |
| 267 | consequent: Expression | |
| 268 | } | |
| 269 | ||
| 270 | export interface CallExpression extends Node { | |
| 271 | type: "CallExpression" | |
| 272 | callee: Expression | Super | |
| 273 | arguments: Array<Expression | SpreadElement> | |
| 274 | optional: boolean | |
| 275 | } | |
| 276 | ||
| 277 | export interface NewExpression extends Node { | |
| 278 | type: "NewExpression" | |
| 279 | callee: Expression | |
| 280 | arguments: Array<Expression | SpreadElement> | |
| 281 | } | |
| 282 | ||
| 283 | export interface SequenceExpression extends Node { | |
| 284 | type: "SequenceExpression" | |
| 285 | expressions: Array<Expression> | |
| 286 | } | |
| 287 | ||
| 288 | export interface ForOfStatement extends Node { | |
| 289 | type: "ForOfStatement" | |
| 290 | left: VariableDeclaration | Pattern | |
| 291 | right: Expression | |
| 292 | body: Statement | |
| 293 | await: boolean | |
| 294 | } | |
| 295 | ||
| 296 | export interface Super extends Node { | |
| 297 | type: "Super" | |
| 298 | } | |
| 299 | ||
| 300 | export interface SpreadElement extends Node { | |
| 301 | type: "SpreadElement" | |
| 302 | argument: Expression | |
| 303 | } | |
| 304 | ||
| 305 | export interface ArrowFunctionExpression extends Function { | |
| 306 | type: "ArrowFunctionExpression" | |
| 307 | } | |
| 308 | ||
| 309 | export interface YieldExpression extends Node { | |
| 310 | type: "YieldExpression" | |
| 311 | argument?: Expression | null | |
| 312 | delegate: boolean | |
| 313 | } | |
| 314 | ||
| 315 | export interface TemplateLiteral extends Node { | |
| 316 | type: "TemplateLiteral" | |
| 317 | quasis: Array<TemplateElement> | |
| 318 | expressions: Array<Expression> | |
| 319 | } | |
| 320 | ||
| 321 | export interface TaggedTemplateExpression extends Node { | |
| 322 | type: "TaggedTemplateExpression" | |
| 323 | tag: Expression | |
| 324 | quasi: TemplateLiteral | |
| 325 | } | |
| 326 | ||
| 327 | export interface TemplateElement extends Node { | |
| 328 | type: "TemplateElement" | |
| 329 | tail: boolean | |
| 330 | value: { | |
| 331 | cooked?: string | null | |
| 332 | raw: string | |
| 333 | } | |
| 334 | } | |
| 335 | ||
| 336 | export interface AssignmentProperty extends Node { | |
| 337 | type: "Property" | |
| 338 | key: Expression | |
| 339 | value: Pattern | |
| 340 | kind: "init" | |
| 341 | method: false | |
| 342 | shorthand: boolean | |
| 343 | computed: boolean | |
| 344 | } | |
| 345 | ||
| 346 | export interface ObjectPattern extends Node { | |
| 347 | type: "ObjectPattern" | |
| 348 | properties: Array<AssignmentProperty | RestElement> | |
| 349 | } | |
| 350 | ||
| 351 | export interface ArrayPattern extends Node { | |
| 352 | type: "ArrayPattern" | |
| 353 | elements: Array<Pattern | null> | |
| 354 | } | |
| 355 | ||
| 356 | export interface RestElement extends Node { | |
| 357 | type: "RestElement" | |
| 358 | argument: Pattern | |
| 359 | } | |
| 360 | ||
| 361 | export interface AssignmentPattern extends Node { | |
| 362 | type: "AssignmentPattern" | |
| 363 | left: Pattern | |
| 364 | right: Expression | |
| 365 | } | |
| 366 | ||
| 367 | export interface Class extends Node { | |
| 368 | id?: Identifier | null | |
| 369 | superClass?: Expression | null | |
| 370 | body: ClassBody | |
| 371 | } | |
| 372 | ||
| 373 | export interface ClassBody extends Node { | |
| 374 | type: "ClassBody" | |
| 375 | body: Array<MethodDefinition | PropertyDefinition | StaticBlock> | |
| 376 | } | |
| 377 | ||
| 378 | export interface MethodDefinition extends Node { | |
| 379 | type: "MethodDefinition" | |
| 380 | key: Expression | PrivateIdentifier | |
| 381 | value: FunctionExpression | |
| 382 | kind: "constructor" | "method" | "get" | "set" | |
| 383 | computed: boolean | |
| 384 | static: boolean | |
| 385 | } | |
| 386 | ||
| 387 | export interface ClassDeclaration extends Class { | |
| 388 | type: "ClassDeclaration" | |
| 389 | id: Identifier | |
| 390 | } | |
| 391 | ||
| 392 | export interface ClassExpression extends Class { | |
| 393 | type: "ClassExpression" | |
| 394 | } | |
| 395 | ||
| 396 | export interface MetaProperty extends Node { | |
| 397 | type: "MetaProperty" | |
| 398 | meta: Identifier | |
| 399 | property: Identifier | |
| 400 | } | |
| 401 | ||
| 402 | export interface ImportDeclaration extends Node { | |
| 403 | type: "ImportDeclaration" | |
| 404 | specifiers: Array<ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier> | |
| 405 | source: Literal | |
| 406 | attributes: Array<ImportAttribute> | |
| 407 | } | |
| 408 | ||
| 409 | export interface ImportSpecifier extends Node { | |
| 410 | type: "ImportSpecifier" | |
| 411 | imported: Identifier | Literal | |
| 412 | local: Identifier | |
| 413 | } | |
| 414 | ||
| 415 | export interface ImportDefaultSpecifier extends Node { | |
| 416 | type: "ImportDefaultSpecifier" | |
| 417 | local: Identifier | |
| 418 | } | |
| 419 | ||
| 420 | export interface ImportNamespaceSpecifier extends Node { | |
| 421 | type: "ImportNamespaceSpecifier" | |
| 422 | local: Identifier | |
| 423 | } | |
| 424 | ||
| 425 | export interface ImportAttribute extends Node { | |
| 426 | type: "ImportAttribute" | |
| 427 | key: Identifier | Literal | |
| 428 | value: Literal | |
| 429 | } | |
| 430 | ||
| 431 | export interface ExportNamedDeclaration extends Node { | |
| 432 | type: "ExportNamedDeclaration" | |
| 433 | declaration?: Declaration | null | |
| 434 | specifiers: Array<ExportSpecifier> | |
| 435 | source?: Literal | null | |
| 436 | attributes: Array<ImportAttribute> | |
| 437 | } | |
| 438 | ||
| 439 | export interface ExportSpecifier extends Node { | |
| 440 | type: "ExportSpecifier" | |
| 441 | exported: Identifier | Literal | |
| 442 | local: Identifier | Literal | |
| 443 | } | |
| 444 | ||
| 445 | export interface AnonymousFunctionDeclaration extends Function { | |
| 446 | type: "FunctionDeclaration" | |
| 447 | id: null | |
| 448 | body: BlockStatement | |
| 449 | } | |
| 450 | ||
| 451 | export interface AnonymousClassDeclaration extends Class { | |
| 452 | type: "ClassDeclaration" | |
| 453 | id: null | |
| 454 | } | |
| 455 | ||
| 456 | export interface ExportDefaultDeclaration extends Node { | |
| 457 | type: "ExportDefaultDeclaration" | |
| 458 | declaration: AnonymousFunctionDeclaration | FunctionDeclaration | AnonymousClassDeclaration | ClassDeclaration | Expression | |
| 459 | } | |
| 460 | ||
| 461 | export interface ExportAllDeclaration extends Node { | |
| 462 | type: "ExportAllDeclaration" | |
| 463 | source: Literal | |
| 464 | exported?: Identifier | Literal | null | |
| 465 | attributes: Array<ImportAttribute> | |
| 466 | } | |
| 467 | ||
| 468 | export interface AwaitExpression extends Node { | |
| 469 | type: "AwaitExpression" | |
| 470 | argument: Expression | |
| 471 | } | |
| 472 | ||
| 473 | export interface ChainExpression extends Node { | |
| 474 | type: "ChainExpression" | |
| 475 | expression: MemberExpression | CallExpression | |
| 476 | } | |
| 477 | ||
| 478 | export interface ImportExpression extends Node { | |
| 479 | type: "ImportExpression" | |
| 480 | source: Expression | |
| 481 | options: Expression | null | |
| 482 | } | |
| 483 | ||
| 484 | export interface ParenthesizedExpression extends Node { | |
| 485 | type: "ParenthesizedExpression" | |
| 486 | expression: Expression | |
| 487 | } | |
| 488 | ||
| 489 | export interface PropertyDefinition extends Node { | |
| 490 | type: "PropertyDefinition" | |
| 491 | key: Expression | PrivateIdentifier | |
| 492 | value?: Expression | null | |
| 493 | computed: boolean | |
| 494 | static: boolean | |
| 495 | } | |
| 496 | ||
| 497 | export interface PrivateIdentifier extends Node { | |
| 498 | type: "PrivateIdentifier" | |
| 499 | name: string | |
| 500 | } | |
| 501 | ||
| 502 | export interface StaticBlock extends Node { | |
| 503 | type: "StaticBlock" | |
| 504 | body: Array<Statement> | |
| 505 | } | |
| 506 | ||
| 507 | export type Statement = | |
| 508 | | ExpressionStatement | |
| 509 | | BlockStatement | |
| 510 | | EmptyStatement | |
| 511 | | DebuggerStatement | |
| 512 | | WithStatement | |
| 513 | | ReturnStatement | |
| 514 | | LabeledStatement | |
| 515 | | BreakStatement | |
| 516 | | ContinueStatement | |
| 517 | | IfStatement | |
| 518 | | SwitchStatement | |
| 519 | | ThrowStatement | |
| 520 | | TryStatement | |
| 521 | | WhileStatement | |
| 522 | | DoWhileStatement | |
| 523 | | ForStatement | |
| 524 | | ForInStatement | |
| 525 | | ForOfStatement | |
| 526 | | Declaration | |
| 527 | ||
| 528 | export type Declaration = | |
| 529 | | FunctionDeclaration | |
| 530 | | VariableDeclaration | |
| 531 | | ClassDeclaration | |
| 532 | ||
| 533 | export type Expression = | |
| 534 | | Identifier | |
| 535 | | Literal | |
| 536 | | ThisExpression | |
| 537 | | ArrayExpression | |
| 538 | | ObjectExpression | |
| 539 | | FunctionExpression | |
| 540 | | UnaryExpression | |
| 541 | | UpdateExpression | |
| 542 | | BinaryExpression | |
| 543 | | AssignmentExpression | |
| 544 | | LogicalExpression | |
| 545 | | MemberExpression | |
| 546 | | ConditionalExpression | |
| 547 | | CallExpression | |
| 548 | | NewExpression | |
| 549 | | SequenceExpression | |
| 550 | | ArrowFunctionExpression | |
| 551 | | YieldExpression | |
| 552 | | TemplateLiteral | |
| 553 | | TaggedTemplateExpression | |
| 554 | | ClassExpression | |
| 555 | | MetaProperty | |
| 556 | | AwaitExpression | |
| 557 | | ChainExpression | |
| 558 | | ImportExpression | |
| 559 | | ParenthesizedExpression | |
| 560 | ||
| 561 | export type Pattern = | |
| 562 | | Identifier | |
| 563 | | MemberExpression | |
| 564 | | ObjectPattern | |
| 565 | | ArrayPattern | |
| 566 | | RestElement | |
| 567 | | AssignmentPattern | |
| 568 | ||
| 569 | export type ModuleDeclaration = | |
| 570 | | ImportDeclaration | |
| 571 | | ExportNamedDeclaration | |
| 572 | | ExportDefaultDeclaration | |
| 573 | | ExportAllDeclaration | |
| 574 | ||
| 575 | /** | |
| 576 | * This interface is only used for defining {@link AnyNode}. | |
| 577 | * It exists so that it can be extended by plugins: | |
| 578 | * | |
| 579 | * @example | |
| 580 | * ```typescript | |
| 581 | * declare module 'acorn' { | |
| 582 | * interface NodeTypes { | |
| 583 | * pluginName: FirstNode | SecondNode | ThirdNode | ... | LastNode | |
| 584 | * } | |
| 585 | * } | |
| 586 | * ``` | |
| 587 | */ | |
| 588 | interface NodeTypes { | |
| 589 | core: Statement | Expression | Declaration | ModuleDeclaration | Literal | Program | SwitchCase | CatchClause | Property | Super | SpreadElement | TemplateElement | AssignmentProperty | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | ClassBody | MethodDefinition | MetaProperty | ImportAttribute | ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier | AnonymousFunctionDeclaration | AnonymousClassDeclaration | PropertyDefinition | PrivateIdentifier | StaticBlock | VariableDeclarator | |
| 590 | } | |
| 591 | ||
| 592 | export type AnyNode = NodeTypes[keyof NodeTypes] | |
| 593 | ||
| 594 | export function parse(input: string, options: Options): Program | |
| 595 | ||
| 596 | export function parseExpressionAt(input: string, pos: number, options: Options): Expression | |
| 597 | ||
| 598 | export function tokenizer(input: string, options: Options): { | |
| 599 | getToken(): Token | |
| 600 | [Symbol.iterator](): Iterator<Token> | |
| 601 | } | |
| 602 | ||
| 603 | export type ecmaVersion = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | "latest" | |
| 604 | ||
| 605 | export interface Options { | |
| 606 | /** | |
| 607 | * `ecmaVersion` indicates the ECMAScript version to parse. Can be a | |
| 608 | * number, either in year (`2022`) or plain version number (`6`) form, | |
| 609 | * or `"latest"` (the latest the library supports). This influences | |
| 610 | * support for strict mode, the set of reserved words, and support for | |
| 611 | * new syntax features. | |
| 612 | */ | |
| 613 | ecmaVersion: ecmaVersion | |
| 614 | ||
| 615 | /** | |
| 616 | * `sourceType` indicates the mode the code should be parsed in. | |
| 617 | * Can be either `"script"` or `"module"`. This influences global | |
| 618 | * strict mode and parsing of `import` and `export` declarations. | |
| 619 | */ | |
| 620 | sourceType?: "script" | "module" | |
| 621 | ||
| 622 | /** | |
| 623 | * a callback that will be called when a semicolon is automatically inserted. | |
| 624 | * @param lastTokEnd the position of the comma as an offset | |
| 625 | * @param lastTokEndLoc location if {@link locations} is enabled | |
| 626 | */ | |
| 627 | onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void | |
| 628 | ||
| 629 | /** | |
| 630 | * similar to `onInsertedSemicolon`, but for trailing commas | |
| 631 | * @param lastTokEnd the position of the comma as an offset | |
| 632 | * @param lastTokEndLoc location if `locations` is enabled | |
| 633 | */ | |
| 634 | onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void | |
| 635 | ||
| 636 | /** | |
| 637 | * By default, reserved words are only enforced if ecmaVersion >= 5. | |
| 638 | * Set `allowReserved` to a boolean value to explicitly turn this on | |
| 639 | * an off. When this option has the value "never", reserved words | |
| 640 | * and keywords can also not be used as property names. | |
| 641 | */ | |
| 642 | allowReserved?: boolean | "never" | |
| 643 | ||
| 644 | /** | |
| 645 | * When enabled, a return at the top level is not considered an error. | |
| 646 | */ | |
| 647 | allowReturnOutsideFunction?: boolean | |
| 648 | ||
| 649 | /** | |
| 650 | * When enabled, import/export statements are not constrained to | |
| 651 | * appearing at the top of the program, and an import.meta expression | |
| 652 | * in a script isn't considered an error. | |
| 653 | */ | |
| 654 | allowImportExportEverywhere?: boolean | |
| 655 | ||
| 656 | /** | |
| 657 | * By default, `await` identifiers are allowed to appear at the top-level scope only if {@link ecmaVersion} >= 2022. | |
| 658 | * When enabled, await identifiers are allowed to appear at the top-level scope, | |
| 659 | * but they are still not allowed in non-async functions. | |
| 660 | */ | |
| 661 | allowAwaitOutsideFunction?: boolean | |
| 662 | ||
| 663 | /** | |
| 664 | * When enabled, super identifiers are not constrained to | |
| 665 | * appearing in methods and do not raise an error when they appear elsewhere. | |
| 666 | */ | |
| 667 | allowSuperOutsideMethod?: boolean | |
| 668 | ||
| 669 | /** | |
| 670 | * When enabled, hashbang directive in the beginning of file is | |
| 671 | * allowed and treated as a line comment. Enabled by default when | |
| 672 | * {@link ecmaVersion} >= 2023. | |
| 673 | */ | |
| 674 | allowHashBang?: boolean | |
| 675 | ||
| 676 | /** | |
| 677 | * By default, the parser will verify that private properties are | |
| 678 | * only used in places where they are valid and have been declared. | |
| 679 | * Set this to false to turn such checks off. | |
| 680 | */ | |
| 681 | checkPrivateFields?: boolean | |
| 682 | ||
| 683 | /** | |
| 684 | * When `locations` is on, `loc` properties holding objects with | |
| 685 | * `start` and `end` properties as {@link Position} objects will be attached to the | |
| 686 | * nodes. | |
| 687 | */ | |
| 688 | locations?: boolean | |
| 689 | ||
| 690 | /** | |
| 691 | * a callback that will cause Acorn to call that export function with object in the same | |
| 692 | * format as tokens returned from `tokenizer().getToken()`. Note | |
| 693 | * that you are not allowed to call the parser from the | |
| 694 | * callback—that will corrupt its internal state. | |
| 695 | */ | |
| 696 | onToken?: ((token: Token) => void) | Token[] | |
| 697 | ||
| 698 | ||
| 699 | /** | |
| 700 | * This takes a export function or an array. | |
| 701 | * | |
| 702 | * When a export function is passed, Acorn will call that export function with `(block, text, start, | |
| 703 | * end)` parameters whenever a comment is skipped. `block` is a | |
| 704 | * boolean indicating whether this is a block (`/* *\/`) comment, | |
| 705 | * `text` is the content of the comment, and `start` and `end` are | |
| 706 | * character offsets that denote the start and end of the comment. | |
| 707 | * When the {@link locations} option is on, two more parameters are | |
| 708 | * passed, the full locations of {@link Position} export type of the start and | |
| 709 | * end of the comments. | |
| 710 | * | |
| 711 | * When a array is passed, each found comment of {@link Comment} export type is pushed to the array. | |
| 712 | * | |
| 713 | * Note that you are not allowed to call the | |
| 714 | * parser from the callback—that will corrupt its internal state. | |
| 715 | */ | |
| 716 | onComment?: (( | |
| 717 | isBlock: boolean, text: string, start: number, end: number, startLoc?: Position, | |
| 718 | endLoc?: Position | |
| 719 | ) => void) | Comment[] | |
| 720 | ||
| 721 | /** | |
| 722 | * Nodes have their start and end characters offsets recorded in | |
| 723 | * `start` and `end` properties (directly on the node, rather than | |
| 724 | * the `loc` object, which holds line/column data. To also add a | |
| 725 | * [semi-standardized][range] `range` property holding a `[start, | |
| 726 | * end]` array with the same numbers, set the `ranges` option to | |
| 727 | * `true`. | |
| 728 | */ | |
| 729 | ranges?: boolean | |
| 730 | ||
| 731 | /** | |
| 732 | * It is possible to parse multiple files into a single AST by | |
| 733 | * passing the tree produced by parsing the first file as | |
| 734 | * `program` option in subsequent parses. This will add the | |
| 735 | * toplevel forms of the parsed file to the `Program` (top) node | |
| 736 | * of an existing parse tree. | |
| 737 | */ | |
| 738 | program?: Node | |
| 739 | ||
| 740 | /** | |
| 741 | * When {@link locations} is on, you can pass this to record the source | |
| 742 | * file in every node's `loc` object. | |
| 743 | */ | |
| 744 | sourceFile?: string | |
| 745 | ||
| 746 | /** | |
| 747 | * This value, if given, is stored in every node, whether {@link locations} is on or off. | |
| 748 | */ | |
| 749 | directSourceFile?: string | |
| 750 | ||
| 751 | /** | |
| 752 | * When enabled, parenthesized expressions are represented by | |
| 753 | * (non-standard) ParenthesizedExpression nodes | |
| 754 | */ | |
| 755 | preserveParens?: boolean | |
| 756 | } | |
| 757 | ||
| 758 | export class Parser { | |
| 759 | options: Options | |
| 760 | input: string | |
| 761 | ||
| 762 | protected constructor(options: Options, input: string, startPos?: number) | |
| 763 | parse(): Program | |
| 764 | ||
| 765 | static parse(input: string, options: Options): Program | |
| 766 | static parseExpressionAt(input: string, pos: number, options: Options): Expression | |
| 767 | static tokenizer(input: string, options: Options): { | |
| 768 | getToken(): Token | |
| 769 | [Symbol.iterator](): Iterator<Token> | |
| 770 | } | |
| 771 | static extend(...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser | |
| 772 | } | |
| 773 | ||
| 774 | export const defaultOptions: Options | |
| 775 | ||
| 776 | export function getLineInfo(input: string, offset: number): Position | |
| 777 | ||
| 778 | export class TokenType { | |
| 779 | label: string | |
| 780 | keyword: string | undefined | |
| 781 | } | |
| 782 | ||
| 783 | export const tokTypes: { | |
| 784 | num: TokenType | |
| 785 | regexp: TokenType | |
| 786 | string: TokenType | |
| 787 | name: TokenType | |
| 788 | privateId: TokenType | |
| 789 | eof: TokenType | |
| 790 | ||
| 791 | bracketL: TokenType | |
| 792 | bracketR: TokenType | |
| 793 | braceL: TokenType | |
| 794 | braceR: TokenType | |
| 795 | parenL: TokenType | |
| 796 | parenR: TokenType | |
| 797 | comma: TokenType | |
| 798 | semi: TokenType | |
| 799 | colon: TokenType | |
| 800 | dot: TokenType | |
| 801 | question: TokenType | |
| 802 | questionDot: TokenType | |
| 803 | arrow: TokenType | |
| 804 | template: TokenType | |
| 805 | invalidTemplate: TokenType | |
| 806 | ellipsis: TokenType | |
| 807 | backQuote: TokenType | |
| 808 | dollarBraceL: TokenType | |
| 809 | ||
| 810 | eq: TokenType | |
| 811 | assign: TokenType | |
| 812 | incDec: TokenType | |
| 813 | prefix: TokenType | |
| 814 | logicalOR: TokenType | |
| 815 | logicalAND: TokenType | |
| 816 | bitwiseOR: TokenType | |
| 817 | bitwiseXOR: TokenType | |
| 818 | bitwiseAND: TokenType | |
| 819 | equality: TokenType | |
| 820 | relational: TokenType | |
| 821 | bitShift: TokenType | |
| 822 | plusMin: TokenType | |
| 823 | modulo: TokenType | |
| 824 | star: TokenType | |
| 825 | slash: TokenType | |
| 826 | starstar: TokenType | |
| 827 | coalesce: TokenType | |
| 828 | ||
| 829 | _break: TokenType | |
| 830 | _case: TokenType | |
| 831 | _catch: TokenType | |
| 832 | _continue: TokenType | |
| 833 | _debugger: TokenType | |
| 834 | _default: TokenType | |
| 835 | _do: TokenType | |
| 836 | _else: TokenType | |
| 837 | _finally: TokenType | |
| 838 | _for: TokenType | |
| 839 | _function: TokenType | |
| 840 | _if: TokenType | |
| 841 | _return: TokenType | |
| 842 | _switch: TokenType | |
| 843 | _throw: TokenType | |
| 844 | _try: TokenType | |
| 845 | _var: TokenType | |
| 846 | _const: TokenType | |
| 847 | _while: TokenType | |
| 848 | _with: TokenType | |
| 849 | _new: TokenType | |
| 850 | _this: TokenType | |
| 851 | _super: TokenType | |
| 852 | _class: TokenType | |
| 853 | _extends: TokenType | |
| 854 | _export: TokenType | |
| 855 | _import: TokenType | |
| 856 | _null: TokenType | |
| 857 | _true: TokenType | |
| 858 | _false: TokenType | |
| 859 | _in: TokenType | |
| 860 | _instanceof: TokenType | |
| 861 | _typeof: TokenType | |
| 862 | _void: TokenType | |
| 863 | _delete: TokenType | |
| 864 | } | |
| 865 | ||
| 866 | export interface Comment { | |
| 867 | type: "Line" | "Block" | |
| 868 | value: string | |
| 869 | start: number | |
| 870 | end: number | |
| 871 | loc?: SourceLocation | |
| 872 | range?: [number, number] | |
| 873 | } | |
| 874 | ||
| 875 | export class Token { | |
| 876 | type: TokenType | |
| 877 | start: number | |
| 878 | end: number | |
| 879 | loc?: SourceLocation | |
| 880 | range?: [number, number] | |
| 881 | } | |
| 882 | ||
| 883 | export const version: string |
| … | … | @@ -0,0 +1,6262 @@ |
| 1 | (function (global, factory) { | |
| 2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
| 3 | typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
| 4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.acorn = {})); | |
| 5 | })(this, (function (exports) { 'use strict'; | |
| 6 | ||
| 7 | // This file was generated. Do not modify manually! | |
| 8 | var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 80, 3, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 343, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 726, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; | |
| 9 | ||
| 10 | // This file was generated. Do not modify manually! | |
| 11 | var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 39, 27, 10, 22, 251, 41, 7, 1, 17, 2, 60, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 31, 9, 2, 0, 3, 0, 2, 37, 2, 0, 26, 0, 2, 0, 45, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 200, 32, 32, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 26, 3994, 6, 582, 6842, 29, 1763, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 433, 44, 212, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 42, 9, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 229, 29, 3, 0, 496, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 4191]; | |
| 12 | ||
| 13 | // This file was generated. Do not modify manually! | |
| 14 | var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65"; | |
| 15 | ||
| 16 | // This file was generated. Do not modify manually! | |
| 17 | var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; | |
| 18 | ||
| 19 | // These are a run-length and offset encoded representation of the | |
| 20 | // >0xffff code points that are a valid part of identifiers. The | |
| 21 | // offset starts at 0x10000, and each pair of numbers represents an | |
| 22 | // offset to the next range, and then a size of the range. | |
| 23 | ||
| 24 | // Reserved word lists for various dialects of the language | |
| 25 | ||
| 26 | var reservedWords = { | |
| 27 | 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", | |
| 28 | 5: "class enum extends super const export import", | |
| 29 | 6: "enum", | |
| 30 | strict: "implements interface let package private protected public static yield", | |
| 31 | strictBind: "eval arguments" | |
| 32 | }; | |
| 33 | ||
| 34 | // And the keywords | |
| 35 | ||
| 36 | var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; | |
| 37 | ||
| 38 | var keywords$1 = { | |
| 39 | 5: ecma5AndLessKeywords, | |
| 40 | "5module": ecma5AndLessKeywords + " export import", | |
| 41 | 6: ecma5AndLessKeywords + " const class extends export import super" | |
| 42 | }; | |
| 43 | ||
| 44 | var keywordRelationalOperator = /^in(stanceof)?$/; | |
| 45 | ||
| 46 | // ## Character categories | |
| 47 | ||
| 48 | var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); | |
| 49 | var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); | |
| 50 | ||
| 51 | // This has a complexity linear to the value of the code. The | |
| 52 | // assumption is that looking up astral identifier characters is | |
| 53 | // rare. | |
| 54 | function isInAstralSet(code, set) { | |
| 55 | var pos = 0x10000; | |
| 56 | for (var i = 0; i < set.length; i += 2) { | |
| 57 | pos += set[i]; | |
| 58 | if (pos > code) { return false } | |
| 59 | pos += set[i + 1]; | |
| 60 | if (pos >= code) { return true } | |
| 61 | } | |
| 62 | return false | |
| 63 | } | |
| 64 | ||
| 65 | // Test whether a given character code starts an identifier. | |
| 66 | ||
| 67 | function isIdentifierStart(code, astral) { | |
| 68 | if (code < 65) { return code === 36 } | |
| 69 | if (code < 91) { return true } | |
| 70 | if (code < 97) { return code === 95 } | |
| 71 | if (code < 123) { return true } | |
| 72 | if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } | |
| 73 | if (astral === false) { return false } | |
| 74 | return isInAstralSet(code, astralIdentifierStartCodes) | |
| 75 | } | |
| 76 | ||
| 77 | // Test whether a given character is part of an identifier. | |
| 78 | ||
| 79 | function isIdentifierChar(code, astral) { | |
| 80 | if (code < 48) { return code === 36 } | |
| 81 | if (code < 58) { return true } | |
| 82 | if (code < 65) { return false } | |
| 83 | if (code < 91) { return true } | |
| 84 | if (code < 97) { return code === 95 } | |
| 85 | if (code < 123) { return true } | |
| 86 | if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } | |
| 87 | if (astral === false) { return false } | |
| 88 | return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) | |
| 89 | } | |
| 90 | ||
| 91 | // ## Token types | |
| 92 | ||
| 93 | // The assignment of fine-grained, information-carrying type objects | |
| 94 | // allows the tokenizer to store the information it has about a | |
| 95 | // token in a way that is very cheap for the parser to look up. | |
| 96 | ||
| 97 | // All token type variables start with an underscore, to make them | |
| 98 | // easy to recognize. | |
| 99 | ||
| 100 | // The `beforeExpr` property is used to disambiguate between regular | |
| 101 | // expressions and divisions. It is set on all token types that can | |
| 102 | // be followed by an expression (thus, a slash after them would be a | |
| 103 | // regular expression). | |
| 104 | // | |
| 105 | // The `startsExpr` property is used to check if the token ends a | |
| 106 | // `yield` expression. It is set on all token types that either can | |
| 107 | // directly start an expression (like a quotation mark) or can | |
| 108 | // continue an expression (like the body of a string). | |
| 109 | // | |
| 110 | // `isLoop` marks a keyword as starting a loop, which is important | |
| 111 | // to know when parsing a label, in order to allow or disallow | |
| 112 | // continue jumps to that label. | |
| 113 | ||
| 114 | var TokenType = function TokenType(label, conf) { | |
| 115 | if ( conf === void 0 ) conf = {}; | |
| 116 | ||
| 117 | this.label = label; | |
| 118 | this.keyword = conf.keyword; | |
| 119 | this.beforeExpr = !!conf.beforeExpr; | |
| 120 | this.startsExpr = !!conf.startsExpr; | |
| 121 | this.isLoop = !!conf.isLoop; | |
| 122 | this.isAssign = !!conf.isAssign; | |
| 123 | this.prefix = !!conf.prefix; | |
| 124 | this.postfix = !!conf.postfix; | |
| 125 | this.binop = conf.binop || null; | |
| 126 | this.updateContext = null; | |
| 127 | }; | |
| 128 | ||
| 129 | function binop(name, prec) { | |
| 130 | return new TokenType(name, {beforeExpr: true, binop: prec}) | |
| 131 | } | |
| 132 | var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}; | |
| 133 | ||
| 134 | // Map keyword names to token types. | |
| 135 | ||
| 136 | var keywords = {}; | |
| 137 | ||
| 138 | // Succinct definitions of keyword token types | |
| 139 | function kw(name, options) { | |
| 140 | if ( options === void 0 ) options = {}; | |
| 141 | ||
| 142 | options.keyword = name; | |
| 143 | return keywords[name] = new TokenType(name, options) | |
| 144 | } | |
| 145 | ||
| 146 | var types$1 = { | |
| 147 | num: new TokenType("num", startsExpr), | |
| 148 | regexp: new TokenType("regexp", startsExpr), | |
| 149 | string: new TokenType("string", startsExpr), | |
| 150 | name: new TokenType("name", startsExpr), | |
| 151 | privateId: new TokenType("privateId", startsExpr), | |
| 152 | eof: new TokenType("eof"), | |
| 153 | ||
| 154 | // Punctuation token types. | |
| 155 | bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), | |
| 156 | bracketR: new TokenType("]"), | |
| 157 | braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), | |
| 158 | braceR: new TokenType("}"), | |
| 159 | parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), | |
| 160 | parenR: new TokenType(")"), | |
| 161 | comma: new TokenType(",", beforeExpr), | |
| 162 | semi: new TokenType(";", beforeExpr), | |
| 163 | colon: new TokenType(":", beforeExpr), | |
| 164 | dot: new TokenType("."), | |
| 165 | question: new TokenType("?", beforeExpr), | |
| 166 | questionDot: new TokenType("?."), | |
| 167 | arrow: new TokenType("=>", beforeExpr), | |
| 168 | template: new TokenType("template"), | |
| 169 | invalidTemplate: new TokenType("invalidTemplate"), | |
| 170 | ellipsis: new TokenType("...", beforeExpr), | |
| 171 | backQuote: new TokenType("`", startsExpr), | |
| 172 | dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), | |
| 173 | ||
| 174 | // Operators. These carry several kinds of properties to help the | |
| 175 | // parser use them properly (the presence of these properties is | |
| 176 | // what categorizes them as operators). | |
| 177 | // | |
| 178 | // `binop`, when present, specifies that this operator is a binary | |
| 179 | // operator, and will refer to its precedence. | |
| 180 | // | |
| 181 | // `prefix` and `postfix` mark the operator as a prefix or postfix | |
| 182 | // unary operator. | |
| 183 | // | |
| 184 | // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as | |
| 185 | // binary operators with a very low precedence, that should result | |
| 186 | // in AssignmentExpression nodes. | |
| 187 | ||
| 188 | eq: new TokenType("=", {beforeExpr: true, isAssign: true}), | |
| 189 | assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), | |
| 190 | incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), | |
| 191 | prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), | |
| 192 | logicalOR: binop("||", 1), | |
| 193 | logicalAND: binop("&&", 2), | |
| 194 | bitwiseOR: binop("|", 3), | |
| 195 | bitwiseXOR: binop("^", 4), | |
| 196 | bitwiseAND: binop("&", 5), | |
| 197 | equality: binop("==/!=/===/!==", 6), | |
| 198 | relational: binop("</>/<=/>=", 7), | |
| 199 | bitShift: binop("<</>>/>>>", 8), | |
| 200 | plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), | |
| 201 | modulo: binop("%", 10), | |
| 202 | star: binop("*", 10), | |
| 203 | slash: binop("/", 10), | |
| 204 | starstar: new TokenType("**", {beforeExpr: true}), | |
| 205 | coalesce: binop("??", 1), | |
| 206 | ||
| 207 | // Keyword token types. | |
| 208 | _break: kw("break"), | |
| 209 | _case: kw("case", beforeExpr), | |
| 210 | _catch: kw("catch"), | |
| 211 | _continue: kw("continue"), | |
| 212 | _debugger: kw("debugger"), | |
| 213 | _default: kw("default", beforeExpr), | |
| 214 | _do: kw("do", {isLoop: true, beforeExpr: true}), | |
| 215 | _else: kw("else", beforeExpr), | |
| 216 | _finally: kw("finally"), | |
| 217 | _for: kw("for", {isLoop: true}), | |
| 218 | _function: kw("function", startsExpr), | |
| 219 | _if: kw("if"), | |
| 220 | _return: kw("return", beforeExpr), | |
| 221 | _switch: kw("switch"), | |
| 222 | _throw: kw("throw", beforeExpr), | |
| 223 | _try: kw("try"), | |
| 224 | _var: kw("var"), | |
| 225 | _const: kw("const"), | |
| 226 | _while: kw("while", {isLoop: true}), | |
| 227 | _with: kw("with"), | |
| 228 | _new: kw("new", {beforeExpr: true, startsExpr: true}), | |
| 229 | _this: kw("this", startsExpr), | |
| 230 | _super: kw("super", startsExpr), | |
| 231 | _class: kw("class", startsExpr), | |
| 232 | _extends: kw("extends", beforeExpr), | |
| 233 | _export: kw("export"), | |
| 234 | _import: kw("import", startsExpr), | |
| 235 | _null: kw("null", startsExpr), | |
| 236 | _true: kw("true", startsExpr), | |
| 237 | _false: kw("false", startsExpr), | |
| 238 | _in: kw("in", {beforeExpr: true, binop: 7}), | |
| 239 | _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), | |
| 240 | _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), | |
| 241 | _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), | |
| 242 | _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) | |
| 243 | }; | |
| 244 | ||
| 245 | // Matches a whole line break (where CRLF is considered a single | |
| 246 | // line break). Used to count lines. | |
| 247 | ||
| 248 | var lineBreak = /\r\n?|\n|\u2028|\u2029/; | |
| 249 | var lineBreakG = new RegExp(lineBreak.source, "g"); | |
| 250 | ||
| 251 | function isNewLine(code) { | |
| 252 | return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 | |
| 253 | } | |
| 254 | ||
| 255 | function nextLineBreak(code, from, end) { | |
| 256 | if ( end === void 0 ) end = code.length; | |
| 257 | ||
| 258 | for (var i = from; i < end; i++) { | |
| 259 | var next = code.charCodeAt(i); | |
| 260 | if (isNewLine(next)) | |
| 261 | { return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1 } | |
| 262 | } | |
| 263 | return -1 | |
| 264 | } | |
| 265 | ||
| 266 | var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/; | |
| 267 | ||
| 268 | var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; | |
| 269 | ||
| 270 | var ref = Object.prototype; | |
| 271 | var hasOwnProperty = ref.hasOwnProperty; | |
| 272 | var toString = ref.toString; | |
| 273 | ||
| 274 | var hasOwn = Object.hasOwn || (function (obj, propName) { return ( | |
| 275 | hasOwnProperty.call(obj, propName) | |
| 276 | ); }); | |
| 277 | ||
| 278 | var isArray = Array.isArray || (function (obj) { return ( | |
| 279 | toString.call(obj) === "[object Array]" | |
| 280 | ); }); | |
| 281 | ||
| 282 | var regexpCache = Object.create(null); | |
| 283 | ||
| 284 | function wordsRegexp(words) { | |
| 285 | return regexpCache[words] || (regexpCache[words] = new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")) | |
| 286 | } | |
| 287 | ||
| 288 | function codePointToString(code) { | |
| 289 | // UTF-16 Decoding | |
| 290 | if (code <= 0xFFFF) { return String.fromCharCode(code) } | |
| 291 | code -= 0x10000; | |
| 292 | return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) | |
| 293 | } | |
| 294 | ||
| 295 | var loneSurrogate = /(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/; | |
| 296 | ||
| 297 | // These are used when `options.locations` is on, for the | |
| 298 | // `startLoc` and `endLoc` properties. | |
| 299 | ||
| 300 | var Position = function Position(line, col) { | |
| 301 | this.line = line; | |
| 302 | this.column = col; | |
| 303 | }; | |
| 304 | ||
| 305 | Position.prototype.offset = function offset (n) { | |
| 306 | return new Position(this.line, this.column + n) | |
| 307 | }; | |
| 308 | ||
| 309 | var SourceLocation = function SourceLocation(p, start, end) { | |
| 310 | this.start = start; | |
| 311 | this.end = end; | |
| 312 | if (p.sourceFile !== null) { this.source = p.sourceFile; } | |
| 313 | }; | |
| 314 | ||
| 315 | // The `getLineInfo` function is mostly useful when the | |
| 316 | // `locations` option is off (for performance reasons) and you | |
| 317 | // want to find the line/column position for a given character | |
| 318 | // offset. `input` should be the code string that the offset refers | |
| 319 | // into. | |
| 320 | ||
| 321 | function getLineInfo(input, offset) { | |
| 322 | for (var line = 1, cur = 0;;) { | |
| 323 | var nextBreak = nextLineBreak(input, cur, offset); | |
| 324 | if (nextBreak < 0) { return new Position(line, offset - cur) } | |
| 325 | ++line; | |
| 326 | cur = nextBreak; | |
| 327 | } | |
| 328 | } | |
| 329 | ||
| 330 | // A second argument must be given to configure the parser process. | |
| 331 | // These options are recognized (only `ecmaVersion` is required): | |
| 332 | ||
| 333 | var defaultOptions = { | |
| 334 | // `ecmaVersion` indicates the ECMAScript version to parse. Must be | |
| 335 | // either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 | |
| 336 | // (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"` | |
| 337 | // (the latest version the library supports). This influences | |
| 338 | // support for strict mode, the set of reserved words, and support | |
| 339 | // for new syntax features. | |
| 340 | ecmaVersion: null, | |
| 341 | // `sourceType` indicates the mode the code should be parsed in. | |
| 342 | // Can be either `"script"` or `"module"`. This influences global | |
| 343 | // strict mode and parsing of `import` and `export` declarations. | |
| 344 | sourceType: "script", | |
| 345 | // `onInsertedSemicolon` can be a callback that will be called when | |
| 346 | // a semicolon is automatically inserted. It will be passed the | |
| 347 | // position of the inserted semicolon as an offset, and if | |
| 348 | // `locations` is enabled, it is given the location as a `{line, | |
| 349 | // column}` object as second argument. | |
| 350 | onInsertedSemicolon: null, | |
| 351 | // `onTrailingComma` is similar to `onInsertedSemicolon`, but for | |
| 352 | // trailing commas. | |
| 353 | onTrailingComma: null, | |
| 354 | // By default, reserved words are only enforced if ecmaVersion >= 5. | |
| 355 | // Set `allowReserved` to a boolean value to explicitly turn this on | |
| 356 | // an off. When this option has the value "never", reserved words | |
| 357 | // and keywords can also not be used as property names. | |
| 358 | allowReserved: null, | |
| 359 | // When enabled, a return at the top level is not considered an | |
| 360 | // error. | |
| 361 | allowReturnOutsideFunction: false, | |
| 362 | // When enabled, import/export statements are not constrained to | |
| 363 | // appearing at the top of the program, and an import.meta expression | |
| 364 | // in a script isn't considered an error. | |
| 365 | allowImportExportEverywhere: false, | |
| 366 | // By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022. | |
| 367 | // When enabled, await identifiers are allowed to appear at the top-level scope, | |
| 368 | // but they are still not allowed in non-async functions. | |
| 369 | allowAwaitOutsideFunction: null, | |
| 370 | // When enabled, super identifiers are not constrained to | |
| 371 | // appearing in methods and do not raise an error when they appear elsewhere. | |
| 372 | allowSuperOutsideMethod: null, | |
| 373 | // When enabled, hashbang directive in the beginning of file is | |
| 374 | // allowed and treated as a line comment. Enabled by default when | |
| 375 | // `ecmaVersion` >= 2023. | |
| 376 | allowHashBang: false, | |
| 377 | // By default, the parser will verify that private properties are | |
| 378 | // only used in places where they are valid and have been declared. | |
| 379 | // Set this to false to turn such checks off. | |
| 380 | checkPrivateFields: true, | |
| 381 | // When `locations` is on, `loc` properties holding objects with | |
| 382 | // `start` and `end` properties in `{line, column}` form (with | |
| 383 | // line being 1-based and column 0-based) will be attached to the | |
| 384 | // nodes. | |
| 385 | locations: false, | |
| 386 | // A function can be passed as `onToken` option, which will | |
| 387 | // cause Acorn to call that function with object in the same | |
| 388 | // format as tokens returned from `tokenizer().getToken()`. Note | |
| 389 | // that you are not allowed to call the parser from the | |
| 390 | // callback—that will corrupt its internal state. | |
| 391 | onToken: null, | |
| 392 | // A function can be passed as `onComment` option, which will | |
| 393 | // cause Acorn to call that function with `(block, text, start, | |
| 394 | // end)` parameters whenever a comment is skipped. `block` is a | |
| 395 | // boolean indicating whether this is a block (`/* */`) comment, | |
| 396 | // `text` is the content of the comment, and `start` and `end` are | |
| 397 | // character offsets that denote the start and end of the comment. | |
| 398 | // When the `locations` option is on, two more parameters are | |
| 399 | // passed, the full `{line, column}` locations of the start and | |
| 400 | // end of the comments. Note that you are not allowed to call the | |
| 401 | // parser from the callback—that will corrupt its internal state. | |
| 402 | // When this option has an array as value, objects representing the | |
| 403 | // comments are pushed to it. | |
| 404 | onComment: null, | |
| 405 | // Nodes have their start and end characters offsets recorded in | |
| 406 | // `start` and `end` properties (directly on the node, rather than | |
| 407 | // the `loc` object, which holds line/column data. To also add a | |
| 408 | // [semi-standardized][range] `range` property holding a `[start, | |
| 409 | // end]` array with the same numbers, set the `ranges` option to | |
| 410 | // `true`. | |
| 411 | // | |
| 412 | // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 | |
| 413 | ranges: false, | |
| 414 | // It is possible to parse multiple files into a single AST by | |
| 415 | // passing the tree produced by parsing the first file as | |
| 416 | // `program` option in subsequent parses. This will add the | |
| 417 | // toplevel forms of the parsed file to the `Program` (top) node | |
| 418 | // of an existing parse tree. | |
| 419 | program: null, | |
| 420 | // When `locations` is on, you can pass this to record the source | |
| 421 | // file in every node's `loc` object. | |
| 422 | sourceFile: null, | |
| 423 | // This value, if given, is stored in every node, whether | |
| 424 | // `locations` is on or off. | |
| 425 | directSourceFile: null, | |
| 426 | // When enabled, parenthesized expressions are represented by | |
| 427 | // (non-standard) ParenthesizedExpression nodes | |
| 428 | preserveParens: false | |
| 429 | }; | |
| 430 | ||
| 431 | // Interpret and default an options object | |
| 432 | ||
| 433 | var warnedAboutEcmaVersion = false; | |
| 434 | ||
| 435 | function getOptions(opts) { | |
| 436 | var options = {}; | |
| 437 | ||
| 438 | for (var opt in defaultOptions) | |
| 439 | { options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt]; } | |
| 440 | ||
| 441 | if (options.ecmaVersion === "latest") { | |
| 442 | options.ecmaVersion = 1e8; | |
| 443 | } else if (options.ecmaVersion == null) { | |
| 444 | if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) { | |
| 445 | warnedAboutEcmaVersion = true; | |
| 446 | console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future."); | |
| 447 | } | |
| 448 | options.ecmaVersion = 11; | |
| 449 | } else if (options.ecmaVersion >= 2015) { | |
| 450 | options.ecmaVersion -= 2009; | |
| 451 | } | |
| 452 | ||
| 453 | if (options.allowReserved == null) | |
| 454 | { options.allowReserved = options.ecmaVersion < 5; } | |
| 455 | ||
| 456 | if (!opts || opts.allowHashBang == null) | |
| 457 | { options.allowHashBang = options.ecmaVersion >= 14; } | |
| 458 | ||
| 459 | if (isArray(options.onToken)) { | |
| 460 | var tokens = options.onToken; | |
| 461 | options.onToken = function (token) { return tokens.push(token); }; | |
| 462 | } | |
| 463 | if (isArray(options.onComment)) | |
| 464 | { options.onComment = pushComment(options, options.onComment); } | |
| 465 | ||
| 466 | return options | |
| 467 | } | |
| 468 | ||
| 469 | function pushComment(options, array) { | |
| 470 | return function(block, text, start, end, startLoc, endLoc) { | |
| 471 | var comment = { | |
| 472 | type: block ? "Block" : "Line", | |
| 473 | value: text, | |
| 474 | start: start, | |
| 475 | end: end | |
| 476 | }; | |
| 477 | if (options.locations) | |
| 478 | { comment.loc = new SourceLocation(this, startLoc, endLoc); } | |
| 479 | if (options.ranges) | |
| 480 | { comment.range = [start, end]; } | |
| 481 | array.push(comment); | |
| 482 | } | |
| 483 | } | |
| 484 | ||
| 485 | // Each scope gets a bitset that may contain these flags | |
| 486 | var | |
| 487 | SCOPE_TOP = 1, | |
| 488 | SCOPE_FUNCTION = 2, | |
| 489 | SCOPE_ASYNC = 4, | |
| 490 | SCOPE_GENERATOR = 8, | |
| 491 | SCOPE_ARROW = 16, | |
| 492 | SCOPE_SIMPLE_CATCH = 32, | |
| 493 | SCOPE_SUPER = 64, | |
| 494 | SCOPE_DIRECT_SUPER = 128, | |
| 495 | SCOPE_CLASS_STATIC_BLOCK = 256, | |
| 496 | SCOPE_CLASS_FIELD_INIT = 512, | |
| 497 | SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK; | |
| 498 | ||
| 499 | function functionFlags(async, generator) { | |
| 500 | return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) | |
| 501 | } | |
| 502 | ||
| 503 | // Used in checkLVal* and declareName to determine the type of a binding | |
| 504 | var | |
| 505 | BIND_NONE = 0, // Not a binding | |
| 506 | BIND_VAR = 1, // Var-style binding | |
| 507 | BIND_LEXICAL = 2, // Let- or const-style binding | |
| 508 | BIND_FUNCTION = 3, // Function declaration | |
| 509 | BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding | |
| 510 | BIND_OUTSIDE = 5; // Special case for function names as bound inside the function | |
| 511 | ||
| 512 | var Parser = function Parser(options, input, startPos) { | |
| 513 | this.options = options = getOptions(options); | |
| 514 | this.sourceFile = options.sourceFile; | |
| 515 | this.keywords = wordsRegexp(keywords$1[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]); | |
| 516 | var reserved = ""; | |
| 517 | if (options.allowReserved !== true) { | |
| 518 | reserved = reservedWords[options.ecmaVersion >= 6 ? 6 : options.ecmaVersion === 5 ? 5 : 3]; | |
| 519 | if (options.sourceType === "module") { reserved += " await"; } | |
| 520 | } | |
| 521 | this.reservedWords = wordsRegexp(reserved); | |
| 522 | var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; | |
| 523 | this.reservedWordsStrict = wordsRegexp(reservedStrict); | |
| 524 | this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind); | |
| 525 | this.input = String(input); | |
| 526 | ||
| 527 | // Used to signal to callers of `readWord1` whether the word | |
| 528 | // contained any escape sequences. This is needed because words with | |
| 529 | // escape sequences must not be interpreted as keywords. | |
| 530 | this.containsEsc = false; | |
| 531 | ||
| 532 | // Set up token state | |
| 533 | ||
| 534 | // The current position of the tokenizer in the input. | |
| 535 | if (startPos) { | |
| 536 | this.pos = startPos; | |
| 537 | this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; | |
| 538 | this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; | |
| 539 | } else { | |
| 540 | this.pos = this.lineStart = 0; | |
| 541 | this.curLine = 1; | |
| 542 | } | |
| 543 | ||
| 544 | // Properties of the current token: | |
| 545 | // Its type | |
| 546 | this.type = types$1.eof; | |
| 547 | // For tokens that include more information than their type, the value | |
| 548 | this.value = null; | |
| 549 | // Its start and end offset | |
| 550 | this.start = this.end = this.pos; | |
| 551 | // And, if locations are used, the {line, column} object | |
| 552 | // corresponding to those offsets | |
| 553 | this.startLoc = this.endLoc = this.curPosition(); | |
| 554 | ||
| 555 | // Position information for the previous token | |
| 556 | this.lastTokEndLoc = this.lastTokStartLoc = null; | |
| 557 | this.lastTokStart = this.lastTokEnd = this.pos; | |
| 558 | ||
| 559 | // The context stack is used to superficially track syntactic | |
| 560 | // context to predict whether a regular expression is allowed in a | |
| 561 | // given position. | |
| 562 | this.context = this.initialContext(); | |
| 563 | this.exprAllowed = true; | |
| 564 | ||
| 565 | // Figure out if it's a module code. | |
| 566 | this.inModule = options.sourceType === "module"; | |
| 567 | this.strict = this.inModule || this.strictDirective(this.pos); | |
| 568 | ||
| 569 | // Used to signify the start of a potential arrow function | |
| 570 | this.potentialArrowAt = -1; | |
| 571 | this.potentialArrowInForAwait = false; | |
| 572 | ||
| 573 | // Positions to delayed-check that yield/await does not exist in default parameters. | |
| 574 | this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; | |
| 575 | // Labels in scope. | |
| 576 | this.labels = []; | |
| 577 | // Thus-far undefined exports. | |
| 578 | this.undefinedExports = Object.create(null); | |
| 579 | ||
| 580 | // If enabled, skip leading hashbang line. | |
| 581 | if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") | |
| 582 | { this.skipLineComment(2); } | |
| 583 | ||
| 584 | // Scope tracking for duplicate variable names (see scope.js) | |
| 585 | this.scopeStack = []; | |
| 586 | this.enterScope(SCOPE_TOP); | |
| 587 | ||
| 588 | // For RegExp validation | |
| 589 | this.regexpState = null; | |
| 590 | ||
| 591 | // The stack of private names. | |
| 592 | // Each element has two properties: 'declared' and 'used'. | |
| 593 | // When it exited from the outermost class definition, all used private names must be declared. | |
| 594 | this.privateNameStack = []; | |
| 595 | }; | |
| 596 | ||
| 597 | var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },canAwait: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true },allowNewDotTarget: { configurable: true },inClassStaticBlock: { configurable: true } }; | |
| 598 | ||
| 599 | Parser.prototype.parse = function parse () { | |
| 600 | var node = this.options.program || this.startNode(); | |
| 601 | this.nextToken(); | |
| 602 | return this.parseTopLevel(node) | |
| 603 | }; | |
| 604 | ||
| 605 | prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }; | |
| 606 | ||
| 607 | prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }; | |
| 608 | ||
| 609 | prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }; | |
| 610 | ||
| 611 | prototypeAccessors.canAwait.get = function () { | |
| 612 | for (var i = this.scopeStack.length - 1; i >= 0; i--) { | |
| 613 | var ref = this.scopeStack[i]; | |
| 614 | var flags = ref.flags; | |
| 615 | if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT)) { return false } | |
| 616 | if (flags & SCOPE_FUNCTION) { return (flags & SCOPE_ASYNC) > 0 } | |
| 617 | } | |
| 618 | return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction | |
| 619 | }; | |
| 620 | ||
| 621 | prototypeAccessors.allowSuper.get = function () { | |
| 622 | var ref = this.currentThisScope(); | |
| 623 | var flags = ref.flags; | |
| 624 | return (flags & SCOPE_SUPER) > 0 || this.options.allowSuperOutsideMethod | |
| 625 | }; | |
| 626 | ||
| 627 | prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }; | |
| 628 | ||
| 629 | prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) }; | |
| 630 | ||
| 631 | prototypeAccessors.allowNewDotTarget.get = function () { | |
| 632 | for (var i = this.scopeStack.length - 1; i >= 0; i--) { | |
| 633 | var ref = this.scopeStack[i]; | |
| 634 | var flags = ref.flags; | |
| 635 | if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT) || | |
| 636 | ((flags & SCOPE_FUNCTION) && !(flags & SCOPE_ARROW))) { return true } | |
| 637 | } | |
| 638 | return false | |
| 639 | }; | |
| 640 | ||
| 641 | prototypeAccessors.inClassStaticBlock.get = function () { | |
| 642 | return (this.currentVarScope().flags & SCOPE_CLASS_STATIC_BLOCK) > 0 | |
| 643 | }; | |
| 644 | ||
| 645 | Parser.extend = function extend () { | |
| 646 | var plugins = [], len = arguments.length; | |
| 647 | while ( len-- ) plugins[ len ] = arguments[ len ]; | |
| 648 | ||
| 649 | var cls = this; | |
| 650 | for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } | |
| 651 | return cls | |
| 652 | }; | |
| 653 | ||
| 654 | Parser.parse = function parse (input, options) { | |
| 655 | return new this(options, input).parse() | |
| 656 | }; | |
| 657 | ||
| 658 | Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) { | |
| 659 | var parser = new this(options, input, pos); | |
| 660 | parser.nextToken(); | |
| 661 | return parser.parseExpression() | |
| 662 | }; | |
| 663 | ||
| 664 | Parser.tokenizer = function tokenizer (input, options) { | |
| 665 | return new this(options, input) | |
| 666 | }; | |
| 667 | ||
| 668 | Object.defineProperties( Parser.prototype, prototypeAccessors ); | |
| 669 | ||
| 670 | var pp$9 = Parser.prototype; | |
| 671 | ||
| 672 | // ## Parser utilities | |
| 673 | ||
| 674 | var literal = /^(?:'((?:\\[^]|[^'\\])*?)'|"((?:\\[^]|[^"\\])*?)")/; | |
| 675 | pp$9.strictDirective = function(start) { | |
| 676 | if (this.options.ecmaVersion < 5) { return false } | |
| 677 | for (;;) { | |
| 678 | // Try to find string literal. | |
| 679 | skipWhiteSpace.lastIndex = start; | |
| 680 | start += skipWhiteSpace.exec(this.input)[0].length; | |
| 681 | var match = literal.exec(this.input.slice(start)); | |
| 682 | if (!match) { return false } | |
| 683 | if ((match[1] || match[2]) === "use strict") { | |
| 684 | skipWhiteSpace.lastIndex = start + match[0].length; | |
| 685 | var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length; | |
| 686 | var next = this.input.charAt(end); | |
| 687 | return next === ";" || next === "}" || | |
| 688 | (lineBreak.test(spaceAfter[0]) && | |
| 689 | !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "=")) | |
| 690 | } | |
| 691 | start += match[0].length; | |
| 692 | ||
| 693 | // Skip semicolon, if any. | |
| 694 | skipWhiteSpace.lastIndex = start; | |
| 695 | start += skipWhiteSpace.exec(this.input)[0].length; | |
| 696 | if (this.input[start] === ";") | |
| 697 | { start++; } | |
| 698 | } | |
| 699 | }; | |
| 700 | ||
| 701 | // Predicate that tests whether the next token is of the given | |
| 702 | // type, and if yes, consumes it as a side effect. | |
| 703 | ||
| 704 | pp$9.eat = function(type) { | |
| 705 | if (this.type === type) { | |
| 706 | this.next(); | |
| 707 | return true | |
| 708 | } else { | |
| 709 | return false | |
| 710 | } | |
| 711 | }; | |
| 712 | ||
| 713 | // Tests whether parsed token is a contextual keyword. | |
| 714 | ||
| 715 | pp$9.isContextual = function(name) { | |
| 716 | return this.type === types$1.name && this.value === name && !this.containsEsc | |
| 717 | }; | |
| 718 | ||
| 719 | // Consumes contextual keyword if possible. | |
| 720 | ||
| 721 | pp$9.eatContextual = function(name) { | |
| 722 | if (!this.isContextual(name)) { return false } | |
| 723 | this.next(); | |
| 724 | return true | |
| 725 | }; | |
| 726 | ||
| 727 | // Asserts that following token is given contextual keyword. | |
| 728 | ||
| 729 | pp$9.expectContextual = function(name) { | |
| 730 | if (!this.eatContextual(name)) { this.unexpected(); } | |
| 731 | }; | |
| 732 | ||
| 733 | // Test whether a semicolon can be inserted at the current position. | |
| 734 | ||
| 735 | pp$9.canInsertSemicolon = function() { | |
| 736 | return this.type === types$1.eof || | |
| 737 | this.type === types$1.braceR || | |
| 738 | lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) | |
| 739 | }; | |
| 740 | ||
| 741 | pp$9.insertSemicolon = function() { | |
| 742 | if (this.canInsertSemicolon()) { | |
| 743 | if (this.options.onInsertedSemicolon) | |
| 744 | { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } | |
| 745 | return true | |
| 746 | } | |
| 747 | }; | |
| 748 | ||
| 749 | // Consume a semicolon, or, failing that, see if we are allowed to | |
| 750 | // pretend that there is a semicolon at this position. | |
| 751 | ||
| 752 | pp$9.semicolon = function() { | |
| 753 | if (!this.eat(types$1.semi) && !this.insertSemicolon()) { this.unexpected(); } | |
| 754 | }; | |
| 755 | ||
| 756 | pp$9.afterTrailingComma = function(tokType, notNext) { | |
| 757 | if (this.type === tokType) { | |
| 758 | if (this.options.onTrailingComma) | |
| 759 | { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } | |
| 760 | if (!notNext) | |
| 761 | { this.next(); } | |
| 762 | return true | |
| 763 | } | |
| 764 | }; | |
| 765 | ||
| 766 | // Expect a token of a given type. If found, consume it, otherwise, | |
| 767 | // raise an unexpected token error. | |
| 768 | ||
| 769 | pp$9.expect = function(type) { | |
| 770 | this.eat(type) || this.unexpected(); | |
| 771 | }; | |
| 772 | ||
| 773 | // Raise an unexpected token error. | |
| 774 | ||
| 775 | pp$9.unexpected = function(pos) { | |
| 776 | this.raise(pos != null ? pos : this.start, "Unexpected token"); | |
| 777 | }; | |
| 778 | ||
| 779 | var DestructuringErrors = function DestructuringErrors() { | |
| 780 | this.shorthandAssign = | |
| 781 | this.trailingComma = | |
| 782 | this.parenthesizedAssign = | |
| 783 | this.parenthesizedBind = | |
| 784 | this.doubleProto = | |
| 785 | -1; | |
| 786 | }; | |
| 787 | ||
| 788 | pp$9.checkPatternErrors = function(refDestructuringErrors, isAssign) { | |
| 789 | if (!refDestructuringErrors) { return } | |
| 790 | if (refDestructuringErrors.trailingComma > -1) | |
| 791 | { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } | |
| 792 | var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; | |
| 793 | if (parens > -1) { this.raiseRecoverable(parens, isAssign ? "Assigning to rvalue" : "Parenthesized pattern"); } | |
| 794 | }; | |
| 795 | ||
| 796 | pp$9.checkExpressionErrors = function(refDestructuringErrors, andThrow) { | |
| 797 | if (!refDestructuringErrors) { return false } | |
| 798 | var shorthandAssign = refDestructuringErrors.shorthandAssign; | |
| 799 | var doubleProto = refDestructuringErrors.doubleProto; | |
| 800 | if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } | |
| 801 | if (shorthandAssign >= 0) | |
| 802 | { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } | |
| 803 | if (doubleProto >= 0) | |
| 804 | { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } | |
| 805 | }; | |
| 806 | ||
| 807 | pp$9.checkYieldAwaitInDefaultParams = function() { | |
| 808 | if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) | |
| 809 | { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } | |
| 810 | if (this.awaitPos) | |
| 811 | { this.raise(this.awaitPos, "Await expression cannot be a default value"); } | |
| 812 | }; | |
| 813 | ||
| 814 | pp$9.isSimpleAssignTarget = function(expr) { | |
| 815 | if (expr.type === "ParenthesizedExpression") | |
| 816 | { return this.isSimpleAssignTarget(expr.expression) } | |
| 817 | return expr.type === "Identifier" || expr.type === "MemberExpression" | |
| 818 | }; | |
| 819 | ||
| 820 | var pp$8 = Parser.prototype; | |
| 821 | ||
| 822 | // ### Statement parsing | |
| 823 | ||
| 824 | // Parse a program. Initializes the parser, reads any number of | |
| 825 | // statements, and wraps them in a Program node. Optionally takes a | |
| 826 | // `program` argument. If present, the statements will be appended | |
| 827 | // to its body instead of creating a new node. | |
| 828 | ||
| 829 | pp$8.parseTopLevel = function(node) { | |
| 830 | var exports = Object.create(null); | |
| 831 | if (!node.body) { node.body = []; } | |
| 832 | while (this.type !== types$1.eof) { | |
| 833 | var stmt = this.parseStatement(null, true, exports); | |
| 834 | node.body.push(stmt); | |
| 835 | } | |
| 836 | if (this.inModule) | |
| 837 | { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1) | |
| 838 | { | |
| 839 | var name = list[i]; | |
| 840 | ||
| 841 | this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined")); | |
| 842 | } } | |
| 843 | this.adaptDirectivePrologue(node.body); | |
| 844 | this.next(); | |
| 845 | node.sourceType = this.options.sourceType; | |
| 846 | return this.finishNode(node, "Program") | |
| 847 | }; | |
| 848 | ||
| 849 | var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; | |
| 850 | ||
| 851 | pp$8.isLet = function(context) { | |
| 852 | if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } | |
| 853 | skipWhiteSpace.lastIndex = this.pos; | |
| 854 | var skip = skipWhiteSpace.exec(this.input); | |
| 855 | var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); | |
| 856 | // For ambiguous cases, determine if a LexicalDeclaration (or only a | |
| 857 | // Statement) is allowed here. If context is not empty then only a Statement | |
| 858 | // is allowed. However, `let [` is an explicit negative lookahead for | |
| 859 | // ExpressionStatement, so special-case it first. | |
| 860 | if (nextCh === 91 || nextCh === 92) { return true } // '[', '\' | |
| 861 | if (context) { return false } | |
| 862 | ||
| 863 | if (nextCh === 123 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } // '{', astral | |
| 864 | if (isIdentifierStart(nextCh, true)) { | |
| 865 | var pos = next + 1; | |
| 866 | while (isIdentifierChar(nextCh = this.input.charCodeAt(pos), true)) { ++pos; } | |
| 867 | if (nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } | |
| 868 | var ident = this.input.slice(next, pos); | |
| 869 | if (!keywordRelationalOperator.test(ident)) { return true } | |
| 870 | } | |
| 871 | return false | |
| 872 | }; | |
| 873 | ||
| 874 | // check 'async [no LineTerminator here] function' | |
| 875 | // - 'async /*foo*/ function' is OK. | |
| 876 | // - 'async /*\n*/ function' is invalid. | |
| 877 | pp$8.isAsyncFunction = function() { | |
| 878 | if (this.options.ecmaVersion < 8 || !this.isContextual("async")) | |
| 879 | { return false } | |
| 880 | ||
| 881 | skipWhiteSpace.lastIndex = this.pos; | |
| 882 | var skip = skipWhiteSpace.exec(this.input); | |
| 883 | var next = this.pos + skip[0].length, after; | |
| 884 | return !lineBreak.test(this.input.slice(this.pos, next)) && | |
| 885 | this.input.slice(next, next + 8) === "function" && | |
| 886 | (next + 8 === this.input.length || | |
| 887 | !(isIdentifierChar(after = this.input.charCodeAt(next + 8)) || after > 0xd7ff && after < 0xdc00)) | |
| 888 | }; | |
| 889 | ||
| 890 | pp$8.isUsingKeyword = function(isAwaitUsing, isFor) { | |
| 891 | if (this.options.ecmaVersion < 17 || !this.isContextual(isAwaitUsing ? "await" : "using")) | |
| 892 | { return false } | |
| 893 | ||
| 894 | skipWhiteSpace.lastIndex = this.pos; | |
| 895 | var skip = skipWhiteSpace.exec(this.input); | |
| 896 | var next = this.pos + skip[0].length; | |
| 897 | ||
| 898 | if (lineBreak.test(this.input.slice(this.pos, next))) { return false } | |
| 899 | ||
| 900 | if (isAwaitUsing) { | |
| 901 | var awaitEndPos = next + 5 /* await */, after; | |
| 902 | if (this.input.slice(next, awaitEndPos) !== "using" || | |
| 903 | awaitEndPos === this.input.length || | |
| 904 | isIdentifierChar(after = this.input.charCodeAt(awaitEndPos)) || | |
| 905 | (after > 0xd7ff && after < 0xdc00) | |
| 906 | ) { return false } | |
| 907 | ||
| 908 | skipWhiteSpace.lastIndex = awaitEndPos; | |
| 909 | var skipAfterUsing = skipWhiteSpace.exec(this.input); | |
| 910 | if (skipAfterUsing && lineBreak.test(this.input.slice(awaitEndPos, awaitEndPos + skipAfterUsing[0].length))) { return false } | |
| 911 | } | |
| 912 | ||
| 913 | if (isFor) { | |
| 914 | var ofEndPos = next + 2 /* of */, after$1; | |
| 915 | if (this.input.slice(next, ofEndPos) === "of") { | |
| 916 | if (ofEndPos === this.input.length || | |
| 917 | (!isIdentifierChar(after$1 = this.input.charCodeAt(ofEndPos)) && !(after$1 > 0xd7ff && after$1 < 0xdc00))) { return false } | |
| 918 | } | |
| 919 | } | |
| 920 | ||
| 921 | var ch = this.input.charCodeAt(next); | |
| 922 | return isIdentifierStart(ch, true) || ch === 92 // '\' | |
| 923 | }; | |
| 924 | ||
| 925 | pp$8.isAwaitUsing = function(isFor) { | |
| 926 | return this.isUsingKeyword(true, isFor) | |
| 927 | }; | |
| 928 | ||
| 929 | pp$8.isUsing = function(isFor) { | |
| 930 | return this.isUsingKeyword(false, isFor) | |
| 931 | }; | |
| 932 | ||
| 933 | // Parse a single statement. | |
| 934 | // | |
| 935 | // If expecting a statement and finding a slash operator, parse a | |
| 936 | // regular expression literal. This is to handle cases like | |
| 937 | // `if (foo) /blah/.exec(foo)`, where looking at the previous token | |
| 938 | // does not help. | |
| 939 | ||
| 940 | pp$8.parseStatement = function(context, topLevel, exports) { | |
| 941 | var starttype = this.type, node = this.startNode(), kind; | |
| 942 | ||
| 943 | if (this.isLet(context)) { | |
| 944 | starttype = types$1._var; | |
| 945 | kind = "let"; | |
| 946 | } | |
| 947 | ||
| 948 | // Most types of statements are recognized by the keyword they | |
| 949 | // start with. Many are trivial to parse, some require a bit of | |
| 950 | // complexity. | |
| 951 | ||
| 952 | switch (starttype) { | |
| 953 | case types$1._break: case types$1._continue: return this.parseBreakContinueStatement(node, starttype.keyword) | |
| 954 | case types$1._debugger: return this.parseDebuggerStatement(node) | |
| 955 | case types$1._do: return this.parseDoStatement(node) | |
| 956 | case types$1._for: return this.parseForStatement(node) | |
| 957 | case types$1._function: | |
| 958 | // Function as sole body of either an if statement or a labeled statement | |
| 959 | // works, but not when it is part of a labeled statement that is the sole | |
| 960 | // body of an if statement. | |
| 961 | if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); } | |
| 962 | return this.parseFunctionStatement(node, false, !context) | |
| 963 | case types$1._class: | |
| 964 | if (context) { this.unexpected(); } | |
| 965 | return this.parseClass(node, true) | |
| 966 | case types$1._if: return this.parseIfStatement(node) | |
| 967 | case types$1._return: return this.parseReturnStatement(node) | |
| 968 | case types$1._switch: return this.parseSwitchStatement(node) | |
| 969 | case types$1._throw: return this.parseThrowStatement(node) | |
| 970 | case types$1._try: return this.parseTryStatement(node) | |
| 971 | case types$1._const: case types$1._var: | |
| 972 | kind = kind || this.value; | |
| 973 | if (context && kind !== "var") { this.unexpected(); } | |
| 974 | return this.parseVarStatement(node, kind) | |
| 975 | case types$1._while: return this.parseWhileStatement(node) | |
| 976 | case types$1._with: return this.parseWithStatement(node) | |
| 977 | case types$1.braceL: return this.parseBlock(true, node) | |
| 978 | case types$1.semi: return this.parseEmptyStatement(node) | |
| 979 | case types$1._export: | |
| 980 | case types$1._import: | |
| 981 | if (this.options.ecmaVersion > 10 && starttype === types$1._import) { | |
| 982 | skipWhiteSpace.lastIndex = this.pos; | |
| 983 | var skip = skipWhiteSpace.exec(this.input); | |
| 984 | var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); | |
| 985 | if (nextCh === 40 || nextCh === 46) // '(' or '.' | |
| 986 | { return this.parseExpressionStatement(node, this.parseExpression()) } | |
| 987 | } | |
| 988 | ||
| 989 | if (!this.options.allowImportExportEverywhere) { | |
| 990 | if (!topLevel) | |
| 991 | { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } | |
| 992 | if (!this.inModule) | |
| 993 | { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } | |
| 994 | } | |
| 995 | return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports) | |
| 996 | ||
| 997 | // If the statement does not start with a statement keyword or a | |
| 998 | // brace, it's an ExpressionStatement or LabeledStatement. We | |
| 999 | // simply start parsing an expression, and afterwards, if the | |
| 1000 | // next token is a colon and the expression was a simple | |
| 1001 | // Identifier node, we switch to interpreting it as a label. | |
| 1002 | default: | |
| 1003 | if (this.isAsyncFunction()) { | |
| 1004 | if (context) { this.unexpected(); } | |
| 1005 | this.next(); | |
| 1006 | return this.parseFunctionStatement(node, true, !context) | |
| 1007 | } | |
| 1008 | ||
| 1009 | var usingKind = this.isAwaitUsing(false) ? "await using" : this.isUsing(false) ? "using" : null; | |
| 1010 | if (usingKind) { | |
| 1011 | if (topLevel && this.options.sourceType === "script") { | |
| 1012 | this.raise(this.start, "Using declaration cannot appear in the top level when source type is `script`"); | |
| 1013 | } | |
| 1014 | if (usingKind === "await using") { | |
| 1015 | if (!this.canAwait) { | |
| 1016 | this.raise(this.start, "Await using cannot appear outside of async function"); | |
| 1017 | } | |
| 1018 | this.next(); | |
| 1019 | } | |
| 1020 | this.next(); | |
| 1021 | this.parseVar(node, false, usingKind); | |
| 1022 | this.semicolon(); | |
| 1023 | return this.finishNode(node, "VariableDeclaration") | |
| 1024 | } | |
| 1025 | ||
| 1026 | var maybeName = this.value, expr = this.parseExpression(); | |
| 1027 | if (starttype === types$1.name && expr.type === "Identifier" && this.eat(types$1.colon)) | |
| 1028 | { return this.parseLabeledStatement(node, maybeName, expr, context) } | |
| 1029 | else { return this.parseExpressionStatement(node, expr) } | |
| 1030 | } | |
| 1031 | }; | |
| 1032 | ||
| 1033 | pp$8.parseBreakContinueStatement = function(node, keyword) { | |
| 1034 | var isBreak = keyword === "break"; | |
| 1035 | this.next(); | |
| 1036 | if (this.eat(types$1.semi) || this.insertSemicolon()) { node.label = null; } | |
| 1037 | else if (this.type !== types$1.name) { this.unexpected(); } | |
| 1038 | else { | |
| 1039 | node.label = this.parseIdent(); | |
| 1040 | this.semicolon(); | |
| 1041 | } | |
| 1042 | ||
| 1043 | // Verify that there is an actual destination to break or | |
| 1044 | // continue to. | |
| 1045 | var i = 0; | |
| 1046 | for (; i < this.labels.length; ++i) { | |
| 1047 | var lab = this.labels[i]; | |
| 1048 | if (node.label == null || lab.name === node.label.name) { | |
| 1049 | if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } | |
| 1050 | if (node.label && isBreak) { break } | |
| 1051 | } | |
| 1052 | } | |
| 1053 | if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } | |
| 1054 | return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") | |
| 1055 | }; | |
| 1056 | ||
| 1057 | pp$8.parseDebuggerStatement = function(node) { | |
| 1058 | this.next(); | |
| 1059 | this.semicolon(); | |
| 1060 | return this.finishNode(node, "DebuggerStatement") | |
| 1061 | }; | |
| 1062 | ||
| 1063 | pp$8.parseDoStatement = function(node) { | |
| 1064 | this.next(); | |
| 1065 | this.labels.push(loopLabel); | |
| 1066 | node.body = this.parseStatement("do"); | |
| 1067 | this.labels.pop(); | |
| 1068 | this.expect(types$1._while); | |
| 1069 | node.test = this.parseParenExpression(); | |
| 1070 | if (this.options.ecmaVersion >= 6) | |
| 1071 | { this.eat(types$1.semi); } | |
| 1072 | else | |
| 1073 | { this.semicolon(); } | |
| 1074 | return this.finishNode(node, "DoWhileStatement") | |
| 1075 | }; | |
| 1076 | ||
| 1077 | // Disambiguating between a `for` and a `for`/`in` or `for`/`of` | |
| 1078 | // loop is non-trivial. Basically, we have to parse the init `var` | |
| 1079 | // statement or expression, disallowing the `in` operator (see | |
| 1080 | // the second parameter to `parseExpression`), and then check | |
| 1081 | // whether the next token is `in` or `of`. When there is no init | |
| 1082 | // part (semicolon immediately after the opening parenthesis), it | |
| 1083 | // is a regular `for` loop. | |
| 1084 | ||
| 1085 | pp$8.parseForStatement = function(node) { | |
| 1086 | this.next(); | |
| 1087 | var awaitAt = (this.options.ecmaVersion >= 9 && this.canAwait && this.eatContextual("await")) ? this.lastTokStart : -1; | |
| 1088 | this.labels.push(loopLabel); | |
| 1089 | this.enterScope(0); | |
| 1090 | this.expect(types$1.parenL); | |
| 1091 | if (this.type === types$1.semi) { | |
| 1092 | if (awaitAt > -1) { this.unexpected(awaitAt); } | |
| 1093 | return this.parseFor(node, null) | |
| 1094 | } | |
| 1095 | var isLet = this.isLet(); | |
| 1096 | if (this.type === types$1._var || this.type === types$1._const || isLet) { | |
| 1097 | var init$1 = this.startNode(), kind = isLet ? "let" : this.value; | |
| 1098 | this.next(); | |
| 1099 | this.parseVar(init$1, true, kind); | |
| 1100 | this.finishNode(init$1, "VariableDeclaration"); | |
| 1101 | return this.parseForAfterInit(node, init$1, awaitAt) | |
| 1102 | } | |
| 1103 | var startsWithLet = this.isContextual("let"), isForOf = false; | |
| 1104 | ||
| 1105 | var usingKind = this.isUsing(true) ? "using" : this.isAwaitUsing(true) ? "await using" : null; | |
| 1106 | if (usingKind) { | |
| 1107 | var init$2 = this.startNode(); | |
| 1108 | this.next(); | |
| 1109 | if (usingKind === "await using") { this.next(); } | |
| 1110 | this.parseVar(init$2, true, usingKind); | |
| 1111 | this.finishNode(init$2, "VariableDeclaration"); | |
| 1112 | return this.parseForAfterInit(node, init$2, awaitAt) | |
| 1113 | } | |
| 1114 | var containsEsc = this.containsEsc; | |
| 1115 | var refDestructuringErrors = new DestructuringErrors; | |
| 1116 | var initPos = this.start; | |
| 1117 | var init = awaitAt > -1 | |
| 1118 | ? this.parseExprSubscripts(refDestructuringErrors, "await") | |
| 1119 | : this.parseExpression(true, refDestructuringErrors); | |
| 1120 | if (this.type === types$1._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) { | |
| 1121 | if (awaitAt > -1) { // implies `ecmaVersion >= 9` (see declaration of awaitAt) | |
| 1122 | if (this.type === types$1._in) { this.unexpected(awaitAt); } | |
| 1123 | node.await = true; | |
| 1124 | } else if (isForOf && this.options.ecmaVersion >= 8) { | |
| 1125 | if (init.start === initPos && !containsEsc && init.type === "Identifier" && init.name === "async") { this.unexpected(); } | |
| 1126 | else if (this.options.ecmaVersion >= 9) { node.await = false; } | |
| 1127 | } | |
| 1128 | if (startsWithLet && isForOf) { this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'."); } | |
| 1129 | this.toAssignable(init, false, refDestructuringErrors); | |
| 1130 | this.checkLValPattern(init); | |
| 1131 | return this.parseForIn(node, init) | |
| 1132 | } else { | |
| 1133 | this.checkExpressionErrors(refDestructuringErrors, true); | |
| 1134 | } | |
| 1135 | if (awaitAt > -1) { this.unexpected(awaitAt); } | |
| 1136 | return this.parseFor(node, init) | |
| 1137 | }; | |
| 1138 | ||
| 1139 | // Helper method to parse for loop after variable initialization | |
| 1140 | pp$8.parseForAfterInit = function(node, init, awaitAt) { | |
| 1141 | if ((this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1) { | |
| 1142 | if (this.options.ecmaVersion >= 9) { | |
| 1143 | if (this.type === types$1._in) { | |
| 1144 | if (awaitAt > -1) { this.unexpected(awaitAt); } | |
| 1145 | } else { node.await = awaitAt > -1; } | |
| 1146 | } | |
| 1147 | return this.parseForIn(node, init) | |
| 1148 | } | |
| 1149 | if (awaitAt > -1) { this.unexpected(awaitAt); } | |
| 1150 | return this.parseFor(node, init) | |
| 1151 | }; | |
| 1152 | ||
| 1153 | pp$8.parseFunctionStatement = function(node, isAsync, declarationPosition) { | |
| 1154 | this.next(); | |
| 1155 | return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) | |
| 1156 | }; | |
| 1157 | ||
| 1158 | pp$8.parseIfStatement = function(node) { | |
| 1159 | this.next(); | |
| 1160 | node.test = this.parseParenExpression(); | |
| 1161 | // allow function declarations in branches, but only in non-strict mode | |
| 1162 | node.consequent = this.parseStatement("if"); | |
| 1163 | node.alternate = this.eat(types$1._else) ? this.parseStatement("if") : null; | |
| 1164 | return this.finishNode(node, "IfStatement") | |
| 1165 | }; | |
| 1166 | ||
| 1167 | pp$8.parseReturnStatement = function(node) { | |
| 1168 | if (!this.inFunction && !this.options.allowReturnOutsideFunction) | |
| 1169 | { this.raise(this.start, "'return' outside of function"); } | |
| 1170 | this.next(); | |
| 1171 | ||
| 1172 | // In `return` (and `break`/`continue`), the keywords with | |
| 1173 | // optional arguments, we eagerly look for a semicolon or the | |
| 1174 | // possibility to insert one. | |
| 1175 | ||
| 1176 | if (this.eat(types$1.semi) || this.insertSemicolon()) { node.argument = null; } | |
| 1177 | else { node.argument = this.parseExpression(); this.semicolon(); } | |
| 1178 | return this.finishNode(node, "ReturnStatement") | |
| 1179 | }; | |
| 1180 | ||
| 1181 | pp$8.parseSwitchStatement = function(node) { | |
| 1182 | this.next(); | |
| 1183 | node.discriminant = this.parseParenExpression(); | |
| 1184 | node.cases = []; | |
| 1185 | this.expect(types$1.braceL); | |
| 1186 | this.labels.push(switchLabel); | |
| 1187 | this.enterScope(0); | |
| 1188 | ||
| 1189 | // Statements under must be grouped (by label) in SwitchCase | |
| 1190 | // nodes. `cur` is used to keep the node that we are currently | |
| 1191 | // adding statements to. | |
| 1192 | ||
| 1193 | var cur; | |
| 1194 | for (var sawDefault = false; this.type !== types$1.braceR;) { | |
| 1195 | if (this.type === types$1._case || this.type === types$1._default) { | |
| 1196 | var isCase = this.type === types$1._case; | |
| 1197 | if (cur) { this.finishNode(cur, "SwitchCase"); } | |
| 1198 | node.cases.push(cur = this.startNode()); | |
| 1199 | cur.consequent = []; | |
| 1200 | this.next(); | |
| 1201 | if (isCase) { | |
| 1202 | cur.test = this.parseExpression(); | |
| 1203 | } else { | |
| 1204 | if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); } | |
| 1205 | sawDefault = true; | |
| 1206 | cur.test = null; | |
| 1207 | } | |
| 1208 | this.expect(types$1.colon); | |
| 1209 | } else { | |
| 1210 | if (!cur) { this.unexpected(); } | |
| 1211 | cur.consequent.push(this.parseStatement(null)); | |
| 1212 | } | |
| 1213 | } | |
| 1214 | this.exitScope(); | |
| 1215 | if (cur) { this.finishNode(cur, "SwitchCase"); } | |
| 1216 | this.next(); // Closing brace | |
| 1217 | this.labels.pop(); | |
| 1218 | return this.finishNode(node, "SwitchStatement") | |
| 1219 | }; | |
| 1220 | ||
| 1221 | pp$8.parseThrowStatement = function(node) { | |
| 1222 | this.next(); | |
| 1223 | if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) | |
| 1224 | { this.raise(this.lastTokEnd, "Illegal newline after throw"); } | |
| 1225 | node.argument = this.parseExpression(); | |
| 1226 | this.semicolon(); | |
| 1227 | return this.finishNode(node, "ThrowStatement") | |
| 1228 | }; | |
| 1229 | ||
| 1230 | // Reused empty array added for node fields that are always empty. | |
| 1231 | ||
| 1232 | var empty$1 = []; | |
| 1233 | ||
| 1234 | pp$8.parseCatchClauseParam = function() { | |
| 1235 | var param = this.parseBindingAtom(); | |
| 1236 | var simple = param.type === "Identifier"; | |
| 1237 | this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); | |
| 1238 | this.checkLValPattern(param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); | |
| 1239 | this.expect(types$1.parenR); | |
| 1240 | ||
| 1241 | return param | |
| 1242 | }; | |
| 1243 | ||
| 1244 | pp$8.parseTryStatement = function(node) { | |
| 1245 | this.next(); | |
| 1246 | node.block = this.parseBlock(); | |
| 1247 | node.handler = null; | |
| 1248 | if (this.type === types$1._catch) { | |
| 1249 | var clause = this.startNode(); | |
| 1250 | this.next(); | |
| 1251 | if (this.eat(types$1.parenL)) { | |
| 1252 | clause.param = this.parseCatchClauseParam(); | |
| 1253 | } else { | |
| 1254 | if (this.options.ecmaVersion < 10) { this.unexpected(); } | |
| 1255 | clause.param = null; | |
| 1256 | this.enterScope(0); | |
| 1257 | } | |
| 1258 | clause.body = this.parseBlock(false); | |
| 1259 | this.exitScope(); | |
| 1260 | node.handler = this.finishNode(clause, "CatchClause"); | |
| 1261 | } | |
| 1262 | node.finalizer = this.eat(types$1._finally) ? this.parseBlock() : null; | |
| 1263 | if (!node.handler && !node.finalizer) | |
| 1264 | { this.raise(node.start, "Missing catch or finally clause"); } | |
| 1265 | return this.finishNode(node, "TryStatement") | |
| 1266 | }; | |
| 1267 | ||
| 1268 | pp$8.parseVarStatement = function(node, kind, allowMissingInitializer) { | |
| 1269 | this.next(); | |
| 1270 | this.parseVar(node, false, kind, allowMissingInitializer); | |
| 1271 | this.semicolon(); | |
| 1272 | return this.finishNode(node, "VariableDeclaration") | |
| 1273 | }; | |
| 1274 | ||
| 1275 | pp$8.parseWhileStatement = function(node) { | |
| 1276 | this.next(); | |
| 1277 | node.test = this.parseParenExpression(); | |
| 1278 | this.labels.push(loopLabel); | |
| 1279 | node.body = this.parseStatement("while"); | |
| 1280 | this.labels.pop(); | |
| 1281 | return this.finishNode(node, "WhileStatement") | |
| 1282 | }; | |
| 1283 | ||
| 1284 | pp$8.parseWithStatement = function(node) { | |
| 1285 | if (this.strict) { this.raise(this.start, "'with' in strict mode"); } | |
| 1286 | this.next(); | |
| 1287 | node.object = this.parseParenExpression(); | |
| 1288 | node.body = this.parseStatement("with"); | |
| 1289 | return this.finishNode(node, "WithStatement") | |
| 1290 | }; | |
| 1291 | ||
| 1292 | pp$8.parseEmptyStatement = function(node) { | |
| 1293 | this.next(); | |
| 1294 | return this.finishNode(node, "EmptyStatement") | |
| 1295 | }; | |
| 1296 | ||
| 1297 | pp$8.parseLabeledStatement = function(node, maybeName, expr, context) { | |
| 1298 | for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1) | |
| 1299 | { | |
| 1300 | var label = list[i$1]; | |
| 1301 | ||
| 1302 | if (label.name === maybeName) | |
| 1303 | { this.raise(expr.start, "Label '" + maybeName + "' is already declared"); | |
| 1304 | } } | |
| 1305 | var kind = this.type.isLoop ? "loop" : this.type === types$1._switch ? "switch" : null; | |
| 1306 | for (var i = this.labels.length - 1; i >= 0; i--) { | |
| 1307 | var label$1 = this.labels[i]; | |
| 1308 | if (label$1.statementStart === node.start) { | |
| 1309 | // Update information about previous labels on this node | |
| 1310 | label$1.statementStart = this.start; | |
| 1311 | label$1.kind = kind; | |
| 1312 | } else { break } | |
| 1313 | } | |
| 1314 | this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); | |
| 1315 | node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label"); | |
| 1316 | this.labels.pop(); | |
| 1317 | node.label = expr; | |
| 1318 | return this.finishNode(node, "LabeledStatement") | |
| 1319 | }; | |
| 1320 | ||
| 1321 | pp$8.parseExpressionStatement = function(node, expr) { | |
| 1322 | node.expression = expr; | |
| 1323 | this.semicolon(); | |
| 1324 | return this.finishNode(node, "ExpressionStatement") | |
| 1325 | }; | |
| 1326 | ||
| 1327 | // Parse a semicolon-enclosed block of statements, handling `"use | |
| 1328 | // strict"` declarations when `allowStrict` is true (used for | |
| 1329 | // function bodies). | |
| 1330 | ||
| 1331 | pp$8.parseBlock = function(createNewLexicalScope, node, exitStrict) { | |
| 1332 | if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; | |
| 1333 | if ( node === void 0 ) node = this.startNode(); | |
| 1334 | ||
| 1335 | node.body = []; | |
| 1336 | this.expect(types$1.braceL); | |
| 1337 | if (createNewLexicalScope) { this.enterScope(0); } | |
| 1338 | while (this.type !== types$1.braceR) { | |
| 1339 | var stmt = this.parseStatement(null); | |
| 1340 | node.body.push(stmt); | |
| 1341 | } | |
| 1342 | if (exitStrict) { this.strict = false; } | |
| 1343 | this.next(); | |
| 1344 | if (createNewLexicalScope) { this.exitScope(); } | |
| 1345 | return this.finishNode(node, "BlockStatement") | |
| 1346 | }; | |
| 1347 | ||
| 1348 | // Parse a regular `for` loop. The disambiguation code in | |
| 1349 | // `parseStatement` will already have parsed the init statement or | |
| 1350 | // expression. | |
| 1351 | ||
| 1352 | pp$8.parseFor = function(node, init) { | |
| 1353 | node.init = init; | |
| 1354 | this.expect(types$1.semi); | |
| 1355 | node.test = this.type === types$1.semi ? null : this.parseExpression(); | |
| 1356 | this.expect(types$1.semi); | |
| 1357 | node.update = this.type === types$1.parenR ? null : this.parseExpression(); | |
| 1358 | this.expect(types$1.parenR); | |
| 1359 | node.body = this.parseStatement("for"); | |
| 1360 | this.exitScope(); | |
| 1361 | this.labels.pop(); | |
| 1362 | return this.finishNode(node, "ForStatement") | |
| 1363 | }; | |
| 1364 | ||
| 1365 | // Parse a `for`/`in` and `for`/`of` loop, which are almost | |
| 1366 | // same from parser's perspective. | |
| 1367 | ||
| 1368 | pp$8.parseForIn = function(node, init) { | |
| 1369 | var isForIn = this.type === types$1._in; | |
| 1370 | this.next(); | |
| 1371 | ||
| 1372 | if ( | |
| 1373 | init.type === "VariableDeclaration" && | |
| 1374 | init.declarations[0].init != null && | |
| 1375 | ( | |
| 1376 | !isForIn || | |
| 1377 | this.options.ecmaVersion < 8 || | |
| 1378 | this.strict || | |
| 1379 | init.kind !== "var" || | |
| 1380 | init.declarations[0].id.type !== "Identifier" | |
| 1381 | ) | |
| 1382 | ) { | |
| 1383 | this.raise( | |
| 1384 | init.start, | |
| 1385 | ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer") | |
| 1386 | ); | |
| 1387 | } | |
| 1388 | node.left = init; | |
| 1389 | node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign(); | |
| 1390 | this.expect(types$1.parenR); | |
| 1391 | node.body = this.parseStatement("for"); | |
| 1392 | this.exitScope(); | |
| 1393 | this.labels.pop(); | |
| 1394 | return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement") | |
| 1395 | }; | |
| 1396 | ||
| 1397 | // Parse a list of variable declarations. | |
| 1398 | ||
| 1399 | pp$8.parseVar = function(node, isFor, kind, allowMissingInitializer) { | |
| 1400 | node.declarations = []; | |
| 1401 | node.kind = kind; | |
| 1402 | for (;;) { | |
| 1403 | var decl = this.startNode(); | |
| 1404 | this.parseVarId(decl, kind); | |
| 1405 | if (this.eat(types$1.eq)) { | |
| 1406 | decl.init = this.parseMaybeAssign(isFor); | |
| 1407 | } else if (!allowMissingInitializer && kind === "const" && !(this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { | |
| 1408 | this.unexpected(); | |
| 1409 | } else if (!allowMissingInitializer && (kind === "using" || kind === "await using") && this.options.ecmaVersion >= 17 && this.type !== types$1._in && !this.isContextual("of")) { | |
| 1410 | this.raise(this.lastTokEnd, ("Missing initializer in " + kind + " declaration")); | |
| 1411 | } else if (!allowMissingInitializer && decl.id.type !== "Identifier" && !(isFor && (this.type === types$1._in || this.isContextual("of")))) { | |
| 1412 | this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); | |
| 1413 | } else { | |
| 1414 | decl.init = null; | |
| 1415 | } | |
| 1416 | node.declarations.push(this.finishNode(decl, "VariableDeclarator")); | |
| 1417 | if (!this.eat(types$1.comma)) { break } | |
| 1418 | } | |
| 1419 | return node | |
| 1420 | }; | |
| 1421 | ||
| 1422 | pp$8.parseVarId = function(decl, kind) { | |
| 1423 | decl.id = kind === "using" || kind === "await using" | |
| 1424 | ? this.parseIdent() | |
| 1425 | : this.parseBindingAtom(); | |
| 1426 | ||
| 1427 | this.checkLValPattern(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); | |
| 1428 | }; | |
| 1429 | ||
| 1430 | var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4; | |
| 1431 | ||
| 1432 | // Parse a function declaration or literal (depending on the | |
| 1433 | // `statement & FUNC_STATEMENT`). | |
| 1434 | ||
| 1435 | // Remove `allowExpressionBody` for 7.0.0, as it is only called with false | |
| 1436 | pp$8.parseFunction = function(node, statement, allowExpressionBody, isAsync, forInit) { | |
| 1437 | this.initFunction(node); | |
| 1438 | if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { | |
| 1439 | if (this.type === types$1.star && (statement & FUNC_HANGING_STATEMENT)) | |
| 1440 | { this.unexpected(); } | |
| 1441 | node.generator = this.eat(types$1.star); | |
| 1442 | } | |
| 1443 | if (this.options.ecmaVersion >= 8) | |
| 1444 | { node.async = !!isAsync; } | |
| 1445 | ||
| 1446 | if (statement & FUNC_STATEMENT) { | |
| 1447 | node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types$1.name ? null : this.parseIdent(); | |
| 1448 | if (node.id && !(statement & FUNC_HANGING_STATEMENT)) | |
| 1449 | // If it is a regular function declaration in sloppy mode, then it is | |
| 1450 | // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding | |
| 1451 | // mode depends on properties of the current scope (see | |
| 1452 | // treatFunctionsAsVar). | |
| 1453 | { this.checkLValSimple(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); } | |
| 1454 | } | |
| 1455 | ||
| 1456 | var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
| 1457 | this.yieldPos = 0; | |
| 1458 | this.awaitPos = 0; | |
| 1459 | this.awaitIdentPos = 0; | |
| 1460 | this.enterScope(functionFlags(node.async, node.generator)); | |
| 1461 | ||
| 1462 | if (!(statement & FUNC_STATEMENT)) | |
| 1463 | { node.id = this.type === types$1.name ? this.parseIdent() : null; } | |
| 1464 | ||
| 1465 | this.parseFunctionParams(node); | |
| 1466 | this.parseFunctionBody(node, allowExpressionBody, false, forInit); | |
| 1467 | ||
| 1468 | this.yieldPos = oldYieldPos; | |
| 1469 | this.awaitPos = oldAwaitPos; | |
| 1470 | this.awaitIdentPos = oldAwaitIdentPos; | |
| 1471 | return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") | |
| 1472 | }; | |
| 1473 | ||
| 1474 | pp$8.parseFunctionParams = function(node) { | |
| 1475 | this.expect(types$1.parenL); | |
| 1476 | node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); | |
| 1477 | this.checkYieldAwaitInDefaultParams(); | |
| 1478 | }; | |
| 1479 | ||
| 1480 | // Parse a class declaration or literal (depending on the | |
| 1481 | // `isStatement` parameter). | |
| 1482 | ||
| 1483 | pp$8.parseClass = function(node, isStatement) { | |
| 1484 | this.next(); | |
| 1485 | ||
| 1486 | // ecma-262 14.6 Class Definitions | |
| 1487 | // A class definition is always strict mode code. | |
| 1488 | var oldStrict = this.strict; | |
| 1489 | this.strict = true; | |
| 1490 | ||
| 1491 | this.parseClassId(node, isStatement); | |
| 1492 | this.parseClassSuper(node); | |
| 1493 | var privateNameMap = this.enterClassBody(); | |
| 1494 | var classBody = this.startNode(); | |
| 1495 | var hadConstructor = false; | |
| 1496 | classBody.body = []; | |
| 1497 | this.expect(types$1.braceL); | |
| 1498 | while (this.type !== types$1.braceR) { | |
| 1499 | var element = this.parseClassElement(node.superClass !== null); | |
| 1500 | if (element) { | |
| 1501 | classBody.body.push(element); | |
| 1502 | if (element.type === "MethodDefinition" && element.kind === "constructor") { | |
| 1503 | if (hadConstructor) { this.raiseRecoverable(element.start, "Duplicate constructor in the same class"); } | |
| 1504 | hadConstructor = true; | |
| 1505 | } else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) { | |
| 1506 | this.raiseRecoverable(element.key.start, ("Identifier '#" + (element.key.name) + "' has already been declared")); | |
| 1507 | } | |
| 1508 | } | |
| 1509 | } | |
| 1510 | this.strict = oldStrict; | |
| 1511 | this.next(); | |
| 1512 | node.body = this.finishNode(classBody, "ClassBody"); | |
| 1513 | this.exitClassBody(); | |
| 1514 | return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") | |
| 1515 | }; | |
| 1516 | ||
| 1517 | pp$8.parseClassElement = function(constructorAllowsSuper) { | |
| 1518 | if (this.eat(types$1.semi)) { return null } | |
| 1519 | ||
| 1520 | var ecmaVersion = this.options.ecmaVersion; | |
| 1521 | var node = this.startNode(); | |
| 1522 | var keyName = ""; | |
| 1523 | var isGenerator = false; | |
| 1524 | var isAsync = false; | |
| 1525 | var kind = "method"; | |
| 1526 | var isStatic = false; | |
| 1527 | ||
| 1528 | if (this.eatContextual("static")) { | |
| 1529 | // Parse static init block | |
| 1530 | if (ecmaVersion >= 13 && this.eat(types$1.braceL)) { | |
| 1531 | this.parseClassStaticBlock(node); | |
| 1532 | return node | |
| 1533 | } | |
| 1534 | if (this.isClassElementNameStart() || this.type === types$1.star) { | |
| 1535 | isStatic = true; | |
| 1536 | } else { | |
| 1537 | keyName = "static"; | |
| 1538 | } | |
| 1539 | } | |
| 1540 | node.static = isStatic; | |
| 1541 | if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) { | |
| 1542 | if ((this.isClassElementNameStart() || this.type === types$1.star) && !this.canInsertSemicolon()) { | |
| 1543 | isAsync = true; | |
| 1544 | } else { | |
| 1545 | keyName = "async"; | |
| 1546 | } | |
| 1547 | } | |
| 1548 | if (!keyName && (ecmaVersion >= 9 || !isAsync) && this.eat(types$1.star)) { | |
| 1549 | isGenerator = true; | |
| 1550 | } | |
| 1551 | if (!keyName && !isAsync && !isGenerator) { | |
| 1552 | var lastValue = this.value; | |
| 1553 | if (this.eatContextual("get") || this.eatContextual("set")) { | |
| 1554 | if (this.isClassElementNameStart()) { | |
| 1555 | kind = lastValue; | |
| 1556 | } else { | |
| 1557 | keyName = lastValue; | |
| 1558 | } | |
| 1559 | } | |
| 1560 | } | |
| 1561 | ||
| 1562 | // Parse element name | |
| 1563 | if (keyName) { | |
| 1564 | // 'async', 'get', 'set', or 'static' were not a keyword contextually. | |
| 1565 | // The last token is any of those. Make it the element name. | |
| 1566 | node.computed = false; | |
| 1567 | node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); | |
| 1568 | node.key.name = keyName; | |
| 1569 | this.finishNode(node.key, "Identifier"); | |
| 1570 | } else { | |
| 1571 | this.parseClassElementName(node); | |
| 1572 | } | |
| 1573 | ||
| 1574 | // Parse element value | |
| 1575 | if (ecmaVersion < 13 || this.type === types$1.parenL || kind !== "method" || isGenerator || isAsync) { | |
| 1576 | var isConstructor = !node.static && checkKeyName(node, "constructor"); | |
| 1577 | var allowsDirectSuper = isConstructor && constructorAllowsSuper; | |
| 1578 | // Couldn't move this check into the 'parseClassMethod' method for backward compatibility. | |
| 1579 | if (isConstructor && kind !== "method") { this.raise(node.key.start, "Constructor can't have get/set modifier"); } | |
| 1580 | node.kind = isConstructor ? "constructor" : kind; | |
| 1581 | this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper); | |
| 1582 | } else { | |
| 1583 | this.parseClassField(node); | |
| 1584 | } | |
| 1585 | ||
| 1586 | return node | |
| 1587 | }; | |
| 1588 | ||
| 1589 | pp$8.isClassElementNameStart = function() { | |
| 1590 | return ( | |
| 1591 | this.type === types$1.name || | |
| 1592 | this.type === types$1.privateId || | |
| 1593 | this.type === types$1.num || | |
| 1594 | this.type === types$1.string || | |
| 1595 | this.type === types$1.bracketL || | |
| 1596 | this.type.keyword | |
| 1597 | ) | |
| 1598 | }; | |
| 1599 | ||
| 1600 | pp$8.parseClassElementName = function(element) { | |
| 1601 | if (this.type === types$1.privateId) { | |
| 1602 | if (this.value === "constructor") { | |
| 1603 | this.raise(this.start, "Classes can't have an element named '#constructor'"); | |
| 1604 | } | |
| 1605 | element.computed = false; | |
| 1606 | element.key = this.parsePrivateIdent(); | |
| 1607 | } else { | |
| 1608 | this.parsePropertyName(element); | |
| 1609 | } | |
| 1610 | }; | |
| 1611 | ||
| 1612 | pp$8.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) { | |
| 1613 | // Check key and flags | |
| 1614 | var key = method.key; | |
| 1615 | if (method.kind === "constructor") { | |
| 1616 | if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } | |
| 1617 | if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } | |
| 1618 | } else if (method.static && checkKeyName(method, "prototype")) { | |
| 1619 | this.raise(key.start, "Classes may not have a static property named prototype"); | |
| 1620 | } | |
| 1621 | ||
| 1622 | // Parse value | |
| 1623 | var value = method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); | |
| 1624 | ||
| 1625 | // Check value | |
| 1626 | if (method.kind === "get" && value.params.length !== 0) | |
| 1627 | { this.raiseRecoverable(value.start, "getter should have no params"); } | |
| 1628 | if (method.kind === "set" && value.params.length !== 1) | |
| 1629 | { this.raiseRecoverable(value.start, "setter should have exactly one param"); } | |
| 1630 | if (method.kind === "set" && value.params[0].type === "RestElement") | |
| 1631 | { this.raiseRecoverable(value.params[0].start, "Setter cannot use rest params"); } | |
| 1632 | ||
| 1633 | return this.finishNode(method, "MethodDefinition") | |
| 1634 | }; | |
| 1635 | ||
| 1636 | pp$8.parseClassField = function(field) { | |
| 1637 | if (checkKeyName(field, "constructor")) { | |
| 1638 | this.raise(field.key.start, "Classes can't have a field named 'constructor'"); | |
| 1639 | } else if (field.static && checkKeyName(field, "prototype")) { | |
| 1640 | this.raise(field.key.start, "Classes can't have a static field named 'prototype'"); | |
| 1641 | } | |
| 1642 | ||
| 1643 | if (this.eat(types$1.eq)) { | |
| 1644 | // To raise SyntaxError if 'arguments' exists in the initializer. | |
| 1645 | this.enterScope(SCOPE_CLASS_FIELD_INIT | SCOPE_SUPER); | |
| 1646 | field.value = this.parseMaybeAssign(); | |
| 1647 | this.exitScope(); | |
| 1648 | } else { | |
| 1649 | field.value = null; | |
| 1650 | } | |
| 1651 | this.semicolon(); | |
| 1652 | ||
| 1653 | return this.finishNode(field, "PropertyDefinition") | |
| 1654 | }; | |
| 1655 | ||
| 1656 | pp$8.parseClassStaticBlock = function(node) { | |
| 1657 | node.body = []; | |
| 1658 | ||
| 1659 | var oldLabels = this.labels; | |
| 1660 | this.labels = []; | |
| 1661 | this.enterScope(SCOPE_CLASS_STATIC_BLOCK | SCOPE_SUPER); | |
| 1662 | while (this.type !== types$1.braceR) { | |
| 1663 | var stmt = this.parseStatement(null); | |
| 1664 | node.body.push(stmt); | |
| 1665 | } | |
| 1666 | this.next(); | |
| 1667 | this.exitScope(); | |
| 1668 | this.labels = oldLabels; | |
| 1669 | ||
| 1670 | return this.finishNode(node, "StaticBlock") | |
| 1671 | }; | |
| 1672 | ||
| 1673 | pp$8.parseClassId = function(node, isStatement) { | |
| 1674 | if (this.type === types$1.name) { | |
| 1675 | node.id = this.parseIdent(); | |
| 1676 | if (isStatement) | |
| 1677 | { this.checkLValSimple(node.id, BIND_LEXICAL, false); } | |
| 1678 | } else { | |
| 1679 | if (isStatement === true) | |
| 1680 | { this.unexpected(); } | |
| 1681 | node.id = null; | |
| 1682 | } | |
| 1683 | }; | |
| 1684 | ||
| 1685 | pp$8.parseClassSuper = function(node) { | |
| 1686 | node.superClass = this.eat(types$1._extends) ? this.parseExprSubscripts(null, false) : null; | |
| 1687 | }; | |
| 1688 | ||
| 1689 | pp$8.enterClassBody = function() { | |
| 1690 | var element = {declared: Object.create(null), used: []}; | |
| 1691 | this.privateNameStack.push(element); | |
| 1692 | return element.declared | |
| 1693 | }; | |
| 1694 | ||
| 1695 | pp$8.exitClassBody = function() { | |
| 1696 | var ref = this.privateNameStack.pop(); | |
| 1697 | var declared = ref.declared; | |
| 1698 | var used = ref.used; | |
| 1699 | if (!this.options.checkPrivateFields) { return } | |
| 1700 | var len = this.privateNameStack.length; | |
| 1701 | var parent = len === 0 ? null : this.privateNameStack[len - 1]; | |
| 1702 | for (var i = 0; i < used.length; ++i) { | |
| 1703 | var id = used[i]; | |
| 1704 | if (!hasOwn(declared, id.name)) { | |
| 1705 | if (parent) { | |
| 1706 | parent.used.push(id); | |
| 1707 | } else { | |
| 1708 | this.raiseRecoverable(id.start, ("Private field '#" + (id.name) + "' must be declared in an enclosing class")); | |
| 1709 | } | |
| 1710 | } | |
| 1711 | } | |
| 1712 | }; | |
| 1713 | ||
| 1714 | function isPrivateNameConflicted(privateNameMap, element) { | |
| 1715 | var name = element.key.name; | |
| 1716 | var curr = privateNameMap[name]; | |
| 1717 | ||
| 1718 | var next = "true"; | |
| 1719 | if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) { | |
| 1720 | next = (element.static ? "s" : "i") + element.kind; | |
| 1721 | } | |
| 1722 | ||
| 1723 | // `class { get #a(){}; static set #a(_){} }` is also conflict. | |
| 1724 | if ( | |
| 1725 | curr === "iget" && next === "iset" || | |
| 1726 | curr === "iset" && next === "iget" || | |
| 1727 | curr === "sget" && next === "sset" || | |
| 1728 | curr === "sset" && next === "sget" | |
| 1729 | ) { | |
| 1730 | privateNameMap[name] = "true"; | |
| 1731 | return false | |
| 1732 | } else if (!curr) { | |
| 1733 | privateNameMap[name] = next; | |
| 1734 | return false | |
| 1735 | } else { | |
| 1736 | return true | |
| 1737 | } | |
| 1738 | } | |
| 1739 | ||
| 1740 | function checkKeyName(node, name) { | |
| 1741 | var computed = node.computed; | |
| 1742 | var key = node.key; | |
| 1743 | return !computed && ( | |
| 1744 | key.type === "Identifier" && key.name === name || | |
| 1745 | key.type === "Literal" && key.value === name | |
| 1746 | ) | |
| 1747 | } | |
| 1748 | ||
| 1749 | // Parses module export declaration. | |
| 1750 | ||
| 1751 | pp$8.parseExportAllDeclaration = function(node, exports) { | |
| 1752 | if (this.options.ecmaVersion >= 11) { | |
| 1753 | if (this.eatContextual("as")) { | |
| 1754 | node.exported = this.parseModuleExportName(); | |
| 1755 | this.checkExport(exports, node.exported, this.lastTokStart); | |
| 1756 | } else { | |
| 1757 | node.exported = null; | |
| 1758 | } | |
| 1759 | } | |
| 1760 | this.expectContextual("from"); | |
| 1761 | if (this.type !== types$1.string) { this.unexpected(); } | |
| 1762 | node.source = this.parseExprAtom(); | |
| 1763 | if (this.options.ecmaVersion >= 16) | |
| 1764 | { node.attributes = this.parseWithClause(); } | |
| 1765 | this.semicolon(); | |
| 1766 | return this.finishNode(node, "ExportAllDeclaration") | |
| 1767 | }; | |
| 1768 | ||
| 1769 | pp$8.parseExport = function(node, exports) { | |
| 1770 | this.next(); | |
| 1771 | // export * from '...' | |
| 1772 | if (this.eat(types$1.star)) { | |
| 1773 | return this.parseExportAllDeclaration(node, exports) | |
| 1774 | } | |
| 1775 | if (this.eat(types$1._default)) { // export default ... | |
| 1776 | this.checkExport(exports, "default", this.lastTokStart); | |
| 1777 | node.declaration = this.parseExportDefaultDeclaration(); | |
| 1778 | return this.finishNode(node, "ExportDefaultDeclaration") | |
| 1779 | } | |
| 1780 | // export var|const|let|function|class ... | |
| 1781 | if (this.shouldParseExportStatement()) { | |
| 1782 | node.declaration = this.parseExportDeclaration(node); | |
| 1783 | if (node.declaration.type === "VariableDeclaration") | |
| 1784 | { this.checkVariableExport(exports, node.declaration.declarations); } | |
| 1785 | else | |
| 1786 | { this.checkExport(exports, node.declaration.id, node.declaration.id.start); } | |
| 1787 | node.specifiers = []; | |
| 1788 | node.source = null; | |
| 1789 | if (this.options.ecmaVersion >= 16) | |
| 1790 | { node.attributes = []; } | |
| 1791 | } else { // export { x, y as z } [from '...'] | |
| 1792 | node.declaration = null; | |
| 1793 | node.specifiers = this.parseExportSpecifiers(exports); | |
| 1794 | if (this.eatContextual("from")) { | |
| 1795 | if (this.type !== types$1.string) { this.unexpected(); } | |
| 1796 | node.source = this.parseExprAtom(); | |
| 1797 | if (this.options.ecmaVersion >= 16) | |
| 1798 | { node.attributes = this.parseWithClause(); } | |
| 1799 | } else { | |
| 1800 | for (var i = 0, list = node.specifiers; i < list.length; i += 1) { | |
| 1801 | // check for keywords used as local names | |
| 1802 | var spec = list[i]; | |
| 1803 | ||
| 1804 | this.checkUnreserved(spec.local); | |
| 1805 | // check if export is defined | |
| 1806 | this.checkLocalExport(spec.local); | |
| 1807 | ||
| 1808 | if (spec.local.type === "Literal") { | |
| 1809 | this.raise(spec.local.start, "A string literal cannot be used as an exported binding without `from`."); | |
| 1810 | } | |
| 1811 | } | |
| 1812 | ||
| 1813 | node.source = null; | |
| 1814 | if (this.options.ecmaVersion >= 16) | |
| 1815 | { node.attributes = []; } | |
| 1816 | } | |
| 1817 | this.semicolon(); | |
| 1818 | } | |
| 1819 | return this.finishNode(node, "ExportNamedDeclaration") | |
| 1820 | }; | |
| 1821 | ||
| 1822 | pp$8.parseExportDeclaration = function(node) { | |
| 1823 | return this.parseStatement(null) | |
| 1824 | }; | |
| 1825 | ||
| 1826 | pp$8.parseExportDefaultDeclaration = function() { | |
| 1827 | var isAsync; | |
| 1828 | if (this.type === types$1._function || (isAsync = this.isAsyncFunction())) { | |
| 1829 | var fNode = this.startNode(); | |
| 1830 | this.next(); | |
| 1831 | if (isAsync) { this.next(); } | |
| 1832 | return this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync) | |
| 1833 | } else if (this.type === types$1._class) { | |
| 1834 | var cNode = this.startNode(); | |
| 1835 | return this.parseClass(cNode, "nullableID") | |
| 1836 | } else { | |
| 1837 | var declaration = this.parseMaybeAssign(); | |
| 1838 | this.semicolon(); | |
| 1839 | return declaration | |
| 1840 | } | |
| 1841 | }; | |
| 1842 | ||
| 1843 | pp$8.checkExport = function(exports, name, pos) { | |
| 1844 | if (!exports) { return } | |
| 1845 | if (typeof name !== "string") | |
| 1846 | { name = name.type === "Identifier" ? name.name : name.value; } | |
| 1847 | if (hasOwn(exports, name)) | |
| 1848 | { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } | |
| 1849 | exports[name] = true; | |
| 1850 | }; | |
| 1851 | ||
| 1852 | pp$8.checkPatternExport = function(exports, pat) { | |
| 1853 | var type = pat.type; | |
| 1854 | if (type === "Identifier") | |
| 1855 | { this.checkExport(exports, pat, pat.start); } | |
| 1856 | else if (type === "ObjectPattern") | |
| 1857 | { for (var i = 0, list = pat.properties; i < list.length; i += 1) | |
| 1858 | { | |
| 1859 | var prop = list[i]; | |
| 1860 | ||
| 1861 | this.checkPatternExport(exports, prop); | |
| 1862 | } } | |
| 1863 | else if (type === "ArrayPattern") | |
| 1864 | { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { | |
| 1865 | var elt = list$1[i$1]; | |
| 1866 | ||
| 1867 | if (elt) { this.checkPatternExport(exports, elt); } | |
| 1868 | } } | |
| 1869 | else if (type === "Property") | |
| 1870 | { this.checkPatternExport(exports, pat.value); } | |
| 1871 | else if (type === "AssignmentPattern") | |
| 1872 | { this.checkPatternExport(exports, pat.left); } | |
| 1873 | else if (type === "RestElement") | |
| 1874 | { this.checkPatternExport(exports, pat.argument); } | |
| 1875 | }; | |
| 1876 | ||
| 1877 | pp$8.checkVariableExport = function(exports, decls) { | |
| 1878 | if (!exports) { return } | |
| 1879 | for (var i = 0, list = decls; i < list.length; i += 1) | |
| 1880 | { | |
| 1881 | var decl = list[i]; | |
| 1882 | ||
| 1883 | this.checkPatternExport(exports, decl.id); | |
| 1884 | } | |
| 1885 | }; | |
| 1886 | ||
| 1887 | pp$8.shouldParseExportStatement = function() { | |
| 1888 | return this.type.keyword === "var" || | |
| 1889 | this.type.keyword === "const" || | |
| 1890 | this.type.keyword === "class" || | |
| 1891 | this.type.keyword === "function" || | |
| 1892 | this.isLet() || | |
| 1893 | this.isAsyncFunction() | |
| 1894 | }; | |
| 1895 | ||
| 1896 | // Parses a comma-separated list of module exports. | |
| 1897 | ||
| 1898 | pp$8.parseExportSpecifier = function(exports) { | |
| 1899 | var node = this.startNode(); | |
| 1900 | node.local = this.parseModuleExportName(); | |
| 1901 | ||
| 1902 | node.exported = this.eatContextual("as") ? this.parseModuleExportName() : node.local; | |
| 1903 | this.checkExport( | |
| 1904 | exports, | |
| 1905 | node.exported, | |
| 1906 | node.exported.start | |
| 1907 | ); | |
| 1908 | ||
| 1909 | return this.finishNode(node, "ExportSpecifier") | |
| 1910 | }; | |
| 1911 | ||
| 1912 | pp$8.parseExportSpecifiers = function(exports) { | |
| 1913 | var nodes = [], first = true; | |
| 1914 | // export { x, y as z } [from '...'] | |
| 1915 | this.expect(types$1.braceL); | |
| 1916 | while (!this.eat(types$1.braceR)) { | |
| 1917 | if (!first) { | |
| 1918 | this.expect(types$1.comma); | |
| 1919 | if (this.afterTrailingComma(types$1.braceR)) { break } | |
| 1920 | } else { first = false; } | |
| 1921 | ||
| 1922 | nodes.push(this.parseExportSpecifier(exports)); | |
| 1923 | } | |
| 1924 | return nodes | |
| 1925 | }; | |
| 1926 | ||
| 1927 | // Parses import declaration. | |
| 1928 | ||
| 1929 | pp$8.parseImport = function(node) { | |
| 1930 | this.next(); | |
| 1931 | ||
| 1932 | // import '...' | |
| 1933 | if (this.type === types$1.string) { | |
| 1934 | node.specifiers = empty$1; | |
| 1935 | node.source = this.parseExprAtom(); | |
| 1936 | } else { | |
| 1937 | node.specifiers = this.parseImportSpecifiers(); | |
| 1938 | this.expectContextual("from"); | |
| 1939 | node.source = this.type === types$1.string ? this.parseExprAtom() : this.unexpected(); | |
| 1940 | } | |
| 1941 | if (this.options.ecmaVersion >= 16) | |
| 1942 | { node.attributes = this.parseWithClause(); } | |
| 1943 | this.semicolon(); | |
| 1944 | return this.finishNode(node, "ImportDeclaration") | |
| 1945 | }; | |
| 1946 | ||
| 1947 | // Parses a comma-separated list of module imports. | |
| 1948 | ||
| 1949 | pp$8.parseImportSpecifier = function() { | |
| 1950 | var node = this.startNode(); | |
| 1951 | node.imported = this.parseModuleExportName(); | |
| 1952 | ||
| 1953 | if (this.eatContextual("as")) { | |
| 1954 | node.local = this.parseIdent(); | |
| 1955 | } else { | |
| 1956 | this.checkUnreserved(node.imported); | |
| 1957 | node.local = node.imported; | |
| 1958 | } | |
| 1959 | this.checkLValSimple(node.local, BIND_LEXICAL); | |
| 1960 | ||
| 1961 | return this.finishNode(node, "ImportSpecifier") | |
| 1962 | }; | |
| 1963 | ||
| 1964 | pp$8.parseImportDefaultSpecifier = function() { | |
| 1965 | // import defaultObj, { x, y as z } from '...' | |
| 1966 | var node = this.startNode(); | |
| 1967 | node.local = this.parseIdent(); | |
| 1968 | this.checkLValSimple(node.local, BIND_LEXICAL); | |
| 1969 | return this.finishNode(node, "ImportDefaultSpecifier") | |
| 1970 | }; | |
| 1971 | ||
| 1972 | pp$8.parseImportNamespaceSpecifier = function() { | |
| 1973 | var node = this.startNode(); | |
| 1974 | this.next(); | |
| 1975 | this.expectContextual("as"); | |
| 1976 | node.local = this.parseIdent(); | |
| 1977 | this.checkLValSimple(node.local, BIND_LEXICAL); | |
| 1978 | return this.finishNode(node, "ImportNamespaceSpecifier") | |
| 1979 | }; | |
| 1980 | ||
| 1981 | pp$8.parseImportSpecifiers = function() { | |
| 1982 | var nodes = [], first = true; | |
| 1983 | if (this.type === types$1.name) { | |
| 1984 | nodes.push(this.parseImportDefaultSpecifier()); | |
| 1985 | if (!this.eat(types$1.comma)) { return nodes } | |
| 1986 | } | |
| 1987 | if (this.type === types$1.star) { | |
| 1988 | nodes.push(this.parseImportNamespaceSpecifier()); | |
| 1989 | return nodes | |
| 1990 | } | |
| 1991 | this.expect(types$1.braceL); | |
| 1992 | while (!this.eat(types$1.braceR)) { | |
| 1993 | if (!first) { | |
| 1994 | this.expect(types$1.comma); | |
| 1995 | if (this.afterTrailingComma(types$1.braceR)) { break } | |
| 1996 | } else { first = false; } | |
| 1997 | ||
| 1998 | nodes.push(this.parseImportSpecifier()); | |
| 1999 | } | |
| 2000 | return nodes | |
| 2001 | }; | |
| 2002 | ||
| 2003 | pp$8.parseWithClause = function() { | |
| 2004 | var nodes = []; | |
| 2005 | if (!this.eat(types$1._with)) { | |
| 2006 | return nodes | |
| 2007 | } | |
| 2008 | this.expect(types$1.braceL); | |
| 2009 | var attributeKeys = {}; | |
| 2010 | var first = true; | |
| 2011 | while (!this.eat(types$1.braceR)) { | |
| 2012 | if (!first) { | |
| 2013 | this.expect(types$1.comma); | |
| 2014 | if (this.afterTrailingComma(types$1.braceR)) { break } | |
| 2015 | } else { first = false; } | |
| 2016 | ||
| 2017 | var attr = this.parseImportAttribute(); | |
| 2018 | var keyName = attr.key.type === "Identifier" ? attr.key.name : attr.key.value; | |
| 2019 | if (hasOwn(attributeKeys, keyName)) | |
| 2020 | { this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" + keyName + "'"); } | |
| 2021 | attributeKeys[keyName] = true; | |
| 2022 | nodes.push(attr); | |
| 2023 | } | |
| 2024 | return nodes | |
| 2025 | }; | |
| 2026 | ||
| 2027 | pp$8.parseImportAttribute = function() { | |
| 2028 | var node = this.startNode(); | |
| 2029 | node.key = this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never"); | |
| 2030 | this.expect(types$1.colon); | |
| 2031 | if (this.type !== types$1.string) { | |
| 2032 | this.unexpected(); | |
| 2033 | } | |
| 2034 | node.value = this.parseExprAtom(); | |
| 2035 | return this.finishNode(node, "ImportAttribute") | |
| 2036 | }; | |
| 2037 | ||
| 2038 | pp$8.parseModuleExportName = function() { | |
| 2039 | if (this.options.ecmaVersion >= 13 && this.type === types$1.string) { | |
| 2040 | var stringLiteral = this.parseLiteral(this.value); | |
| 2041 | if (loneSurrogate.test(stringLiteral.value)) { | |
| 2042 | this.raise(stringLiteral.start, "An export name cannot include a lone surrogate."); | |
| 2043 | } | |
| 2044 | return stringLiteral | |
| 2045 | } | |
| 2046 | return this.parseIdent(true) | |
| 2047 | }; | |
| 2048 | ||
| 2049 | // Set `ExpressionStatement#directive` property for directive prologues. | |
| 2050 | pp$8.adaptDirectivePrologue = function(statements) { | |
| 2051 | for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { | |
| 2052 | statements[i].directive = statements[i].expression.raw.slice(1, -1); | |
| 2053 | } | |
| 2054 | }; | |
| 2055 | pp$8.isDirectiveCandidate = function(statement) { | |
| 2056 | return ( | |
| 2057 | this.options.ecmaVersion >= 5 && | |
| 2058 | statement.type === "ExpressionStatement" && | |
| 2059 | statement.expression.type === "Literal" && | |
| 2060 | typeof statement.expression.value === "string" && | |
| 2061 | // Reject parenthesized strings. | |
| 2062 | (this.input[statement.start] === "\"" || this.input[statement.start] === "'") | |
| 2063 | ) | |
| 2064 | }; | |
| 2065 | ||
| 2066 | var pp$7 = Parser.prototype; | |
| 2067 | ||
| 2068 | // Convert existing expression atom to assignable pattern | |
| 2069 | // if possible. | |
| 2070 | ||
| 2071 | pp$7.toAssignable = function(node, isBinding, refDestructuringErrors) { | |
| 2072 | if (this.options.ecmaVersion >= 6 && node) { | |
| 2073 | switch (node.type) { | |
| 2074 | case "Identifier": | |
| 2075 | if (this.inAsync && node.name === "await") | |
| 2076 | { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); } | |
| 2077 | break | |
| 2078 | ||
| 2079 | case "ObjectPattern": | |
| 2080 | case "ArrayPattern": | |
| 2081 | case "AssignmentPattern": | |
| 2082 | case "RestElement": | |
| 2083 | break | |
| 2084 | ||
| 2085 | case "ObjectExpression": | |
| 2086 | node.type = "ObjectPattern"; | |
| 2087 | if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
| 2088 | for (var i = 0, list = node.properties; i < list.length; i += 1) { | |
| 2089 | var prop = list[i]; | |
| 2090 | ||
| 2091 | this.toAssignable(prop, isBinding); | |
| 2092 | // Early error: | |
| 2093 | // AssignmentRestProperty[Yield, Await] : | |
| 2094 | // `...` DestructuringAssignmentTarget[Yield, Await] | |
| 2095 | // | |
| 2096 | // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. | |
| 2097 | if ( | |
| 2098 | prop.type === "RestElement" && | |
| 2099 | (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") | |
| 2100 | ) { | |
| 2101 | this.raise(prop.argument.start, "Unexpected token"); | |
| 2102 | } | |
| 2103 | } | |
| 2104 | break | |
| 2105 | ||
| 2106 | case "Property": | |
| 2107 | // AssignmentProperty has type === "Property" | |
| 2108 | if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } | |
| 2109 | this.toAssignable(node.value, isBinding); | |
| 2110 | break | |
| 2111 | ||
| 2112 | case "ArrayExpression": | |
| 2113 | node.type = "ArrayPattern"; | |
| 2114 | if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
| 2115 | this.toAssignableList(node.elements, isBinding); | |
| 2116 | break | |
| 2117 | ||
| 2118 | case "SpreadElement": | |
| 2119 | node.type = "RestElement"; | |
| 2120 | this.toAssignable(node.argument, isBinding); | |
| 2121 | if (node.argument.type === "AssignmentPattern") | |
| 2122 | { this.raise(node.argument.start, "Rest elements cannot have a default value"); } | |
| 2123 | break | |
| 2124 | ||
| 2125 | case "AssignmentExpression": | |
| 2126 | if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } | |
| 2127 | node.type = "AssignmentPattern"; | |
| 2128 | delete node.operator; | |
| 2129 | this.toAssignable(node.left, isBinding); | |
| 2130 | break | |
| 2131 | ||
| 2132 | case "ParenthesizedExpression": | |
| 2133 | this.toAssignable(node.expression, isBinding, refDestructuringErrors); | |
| 2134 | break | |
| 2135 | ||
| 2136 | case "ChainExpression": | |
| 2137 | this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side"); | |
| 2138 | break | |
| 2139 | ||
| 2140 | case "MemberExpression": | |
| 2141 | if (!isBinding) { break } | |
| 2142 | ||
| 2143 | default: | |
| 2144 | this.raise(node.start, "Assigning to rvalue"); | |
| 2145 | } | |
| 2146 | } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
| 2147 | return node | |
| 2148 | }; | |
| 2149 | ||
| 2150 | // Convert list of expression atoms to binding list. | |
| 2151 | ||
| 2152 | pp$7.toAssignableList = function(exprList, isBinding) { | |
| 2153 | var end = exprList.length; | |
| 2154 | for (var i = 0; i < end; i++) { | |
| 2155 | var elt = exprList[i]; | |
| 2156 | if (elt) { this.toAssignable(elt, isBinding); } | |
| 2157 | } | |
| 2158 | if (end) { | |
| 2159 | var last = exprList[end - 1]; | |
| 2160 | if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") | |
| 2161 | { this.unexpected(last.argument.start); } | |
| 2162 | } | |
| 2163 | return exprList | |
| 2164 | }; | |
| 2165 | ||
| 2166 | // Parses spread element. | |
| 2167 | ||
| 2168 | pp$7.parseSpread = function(refDestructuringErrors) { | |
| 2169 | var node = this.startNode(); | |
| 2170 | this.next(); | |
| 2171 | node.argument = this.parseMaybeAssign(false, refDestructuringErrors); | |
| 2172 | return this.finishNode(node, "SpreadElement") | |
| 2173 | }; | |
| 2174 | ||
| 2175 | pp$7.parseRestBinding = function() { | |
| 2176 | var node = this.startNode(); | |
| 2177 | this.next(); | |
| 2178 | ||
| 2179 | // RestElement inside of a function parameter must be an identifier | |
| 2180 | if (this.options.ecmaVersion === 6 && this.type !== types$1.name) | |
| 2181 | { this.unexpected(); } | |
| 2182 | ||
| 2183 | node.argument = this.parseBindingAtom(); | |
| 2184 | ||
| 2185 | return this.finishNode(node, "RestElement") | |
| 2186 | }; | |
| 2187 | ||
| 2188 | // Parses lvalue (assignable) atom. | |
| 2189 | ||
| 2190 | pp$7.parseBindingAtom = function() { | |
| 2191 | if (this.options.ecmaVersion >= 6) { | |
| 2192 | switch (this.type) { | |
| 2193 | case types$1.bracketL: | |
| 2194 | var node = this.startNode(); | |
| 2195 | this.next(); | |
| 2196 | node.elements = this.parseBindingList(types$1.bracketR, true, true); | |
| 2197 | return this.finishNode(node, "ArrayPattern") | |
| 2198 | ||
| 2199 | case types$1.braceL: | |
| 2200 | return this.parseObj(true) | |
| 2201 | } | |
| 2202 | } | |
| 2203 | return this.parseIdent() | |
| 2204 | }; | |
| 2205 | ||
| 2206 | pp$7.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowModifiers) { | |
| 2207 | var elts = [], first = true; | |
| 2208 | while (!this.eat(close)) { | |
| 2209 | if (first) { first = false; } | |
| 2210 | else { this.expect(types$1.comma); } | |
| 2211 | if (allowEmpty && this.type === types$1.comma) { | |
| 2212 | elts.push(null); | |
| 2213 | } else if (allowTrailingComma && this.afterTrailingComma(close)) { | |
| 2214 | break | |
| 2215 | } else if (this.type === types$1.ellipsis) { | |
| 2216 | var rest = this.parseRestBinding(); | |
| 2217 | this.parseBindingListItem(rest); | |
| 2218 | elts.push(rest); | |
| 2219 | if (this.type === types$1.comma) { this.raiseRecoverable(this.start, "Comma is not permitted after the rest element"); } | |
| 2220 | this.expect(close); | |
| 2221 | break | |
| 2222 | } else { | |
| 2223 | elts.push(this.parseAssignableListItem(allowModifiers)); | |
| 2224 | } | |
| 2225 | } | |
| 2226 | return elts | |
| 2227 | }; | |
| 2228 | ||
| 2229 | pp$7.parseAssignableListItem = function(allowModifiers) { | |
| 2230 | var elem = this.parseMaybeDefault(this.start, this.startLoc); | |
| 2231 | this.parseBindingListItem(elem); | |
| 2232 | return elem | |
| 2233 | }; | |
| 2234 | ||
| 2235 | pp$7.parseBindingListItem = function(param) { | |
| 2236 | return param | |
| 2237 | }; | |
| 2238 | ||
| 2239 | // Parses assignment pattern around given atom if possible. | |
| 2240 | ||
| 2241 | pp$7.parseMaybeDefault = function(startPos, startLoc, left) { | |
| 2242 | left = left || this.parseBindingAtom(); | |
| 2243 | if (this.options.ecmaVersion < 6 || !this.eat(types$1.eq)) { return left } | |
| 2244 | var node = this.startNodeAt(startPos, startLoc); | |
| 2245 | node.left = left; | |
| 2246 | node.right = this.parseMaybeAssign(); | |
| 2247 | return this.finishNode(node, "AssignmentPattern") | |
| 2248 | }; | |
| 2249 | ||
| 2250 | // The following three functions all verify that a node is an lvalue — | |
| 2251 | // something that can be bound, or assigned to. In order to do so, they perform | |
| 2252 | // a variety of checks: | |
| 2253 | // | |
| 2254 | // - Check that none of the bound/assigned-to identifiers are reserved words. | |
| 2255 | // - Record name declarations for bindings in the appropriate scope. | |
| 2256 | // - Check duplicate argument names, if checkClashes is set. | |
| 2257 | // | |
| 2258 | // If a complex binding pattern is encountered (e.g., object and array | |
| 2259 | // destructuring), the entire pattern is recursively checked. | |
| 2260 | // | |
| 2261 | // There are three versions of checkLVal*() appropriate for different | |
| 2262 | // circumstances: | |
| 2263 | // | |
| 2264 | // - checkLValSimple() shall be used if the syntactic construct supports | |
| 2265 | // nothing other than identifiers and member expressions. Parenthesized | |
| 2266 | // expressions are also correctly handled. This is generally appropriate for | |
| 2267 | // constructs for which the spec says | |
| 2268 | // | |
| 2269 | // > It is a Syntax Error if AssignmentTargetType of [the production] is not | |
| 2270 | // > simple. | |
| 2271 | // | |
| 2272 | // It is also appropriate for checking if an identifier is valid and not | |
| 2273 | // defined elsewhere, like import declarations or function/class identifiers. | |
| 2274 | // | |
| 2275 | // Examples where this is used include: | |
| 2276 | // a += …; | |
| 2277 | // import a from '…'; | |
| 2278 | // where a is the node to be checked. | |
| 2279 | // | |
| 2280 | // - checkLValPattern() shall be used if the syntactic construct supports | |
| 2281 | // anything checkLValSimple() supports, as well as object and array | |
| 2282 | // destructuring patterns. This is generally appropriate for constructs for | |
| 2283 | // which the spec says | |
| 2284 | // | |
| 2285 | // > It is a Syntax Error if [the production] is neither an ObjectLiteral nor | |
| 2286 | // > an ArrayLiteral and AssignmentTargetType of [the production] is not | |
| 2287 | // > simple. | |
| 2288 | // | |
| 2289 | // Examples where this is used include: | |
| 2290 | // (a = …); | |
| 2291 | // const a = …; | |
| 2292 | // try { … } catch (a) { … } | |
| 2293 | // where a is the node to be checked. | |
| 2294 | // | |
| 2295 | // - checkLValInnerPattern() shall be used if the syntactic construct supports | |
| 2296 | // anything checkLValPattern() supports, as well as default assignment | |
| 2297 | // patterns, rest elements, and other constructs that may appear within an | |
| 2298 | // object or array destructuring pattern. | |
| 2299 | // | |
| 2300 | // As a special case, function parameters also use checkLValInnerPattern(), | |
| 2301 | // as they also support defaults and rest constructs. | |
| 2302 | // | |
| 2303 | // These functions deliberately support both assignment and binding constructs, | |
| 2304 | // as the logic for both is exceedingly similar. If the node is the target of | |
| 2305 | // an assignment, then bindingType should be set to BIND_NONE. Otherwise, it | |
| 2306 | // should be set to the appropriate BIND_* constant, like BIND_VAR or | |
| 2307 | // BIND_LEXICAL. | |
| 2308 | // | |
| 2309 | // If the function is called with a non-BIND_NONE bindingType, then | |
| 2310 | // additionally a checkClashes object may be specified to allow checking for | |
| 2311 | // duplicate argument names. checkClashes is ignored if the provided construct | |
| 2312 | // is an assignment (i.e., bindingType is BIND_NONE). | |
| 2313 | ||
| 2314 | pp$7.checkLValSimple = function(expr, bindingType, checkClashes) { | |
| 2315 | if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
| 2316 | ||
| 2317 | var isBind = bindingType !== BIND_NONE; | |
| 2318 | ||
| 2319 | switch (expr.type) { | |
| 2320 | case "Identifier": | |
| 2321 | if (this.strict && this.reservedWordsStrictBind.test(expr.name)) | |
| 2322 | { this.raiseRecoverable(expr.start, (isBind ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } | |
| 2323 | if (isBind) { | |
| 2324 | if (bindingType === BIND_LEXICAL && expr.name === "let") | |
| 2325 | { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); } | |
| 2326 | if (checkClashes) { | |
| 2327 | if (hasOwn(checkClashes, expr.name)) | |
| 2328 | { this.raiseRecoverable(expr.start, "Argument name clash"); } | |
| 2329 | checkClashes[expr.name] = true; | |
| 2330 | } | |
| 2331 | if (bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); } | |
| 2332 | } | |
| 2333 | break | |
| 2334 | ||
| 2335 | case "ChainExpression": | |
| 2336 | this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side"); | |
| 2337 | break | |
| 2338 | ||
| 2339 | case "MemberExpression": | |
| 2340 | if (isBind) { this.raiseRecoverable(expr.start, "Binding member expression"); } | |
| 2341 | break | |
| 2342 | ||
| 2343 | case "ParenthesizedExpression": | |
| 2344 | if (isBind) { this.raiseRecoverable(expr.start, "Binding parenthesized expression"); } | |
| 2345 | return this.checkLValSimple(expr.expression, bindingType, checkClashes) | |
| 2346 | ||
| 2347 | default: | |
| 2348 | this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue"); | |
| 2349 | } | |
| 2350 | }; | |
| 2351 | ||
| 2352 | pp$7.checkLValPattern = function(expr, bindingType, checkClashes) { | |
| 2353 | if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
| 2354 | ||
| 2355 | switch (expr.type) { | |
| 2356 | case "ObjectPattern": | |
| 2357 | for (var i = 0, list = expr.properties; i < list.length; i += 1) { | |
| 2358 | var prop = list[i]; | |
| 2359 | ||
| 2360 | this.checkLValInnerPattern(prop, bindingType, checkClashes); | |
| 2361 | } | |
| 2362 | break | |
| 2363 | ||
| 2364 | case "ArrayPattern": | |
| 2365 | for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { | |
| 2366 | var elem = list$1[i$1]; | |
| 2367 | ||
| 2368 | if (elem) { this.checkLValInnerPattern(elem, bindingType, checkClashes); } | |
| 2369 | } | |
| 2370 | break | |
| 2371 | ||
| 2372 | default: | |
| 2373 | this.checkLValSimple(expr, bindingType, checkClashes); | |
| 2374 | } | |
| 2375 | }; | |
| 2376 | ||
| 2377 | pp$7.checkLValInnerPattern = function(expr, bindingType, checkClashes) { | |
| 2378 | if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
| 2379 | ||
| 2380 | switch (expr.type) { | |
| 2381 | case "Property": | |
| 2382 | // AssignmentProperty has type === "Property" | |
| 2383 | this.checkLValInnerPattern(expr.value, bindingType, checkClashes); | |
| 2384 | break | |
| 2385 | ||
| 2386 | case "AssignmentPattern": | |
| 2387 | this.checkLValPattern(expr.left, bindingType, checkClashes); | |
| 2388 | break | |
| 2389 | ||
| 2390 | case "RestElement": | |
| 2391 | this.checkLValPattern(expr.argument, bindingType, checkClashes); | |
| 2392 | break | |
| 2393 | ||
| 2394 | default: | |
| 2395 | this.checkLValPattern(expr, bindingType, checkClashes); | |
| 2396 | } | |
| 2397 | }; | |
| 2398 | ||
| 2399 | // The algorithm used to determine whether a regexp can appear at a | |
| 2400 | // given point in the program is loosely based on sweet.js' approach. | |
| 2401 | // See https://github.com/mozilla/sweet.js/wiki/design | |
| 2402 | ||
| 2403 | ||
| 2404 | var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { | |
| 2405 | this.token = token; | |
| 2406 | this.isExpr = !!isExpr; | |
| 2407 | this.preserveSpace = !!preserveSpace; | |
| 2408 | this.override = override; | |
| 2409 | this.generator = !!generator; | |
| 2410 | }; | |
| 2411 | ||
| 2412 | var types = { | |
| 2413 | b_stat: new TokContext("{", false), | |
| 2414 | b_expr: new TokContext("{", true), | |
| 2415 | b_tmpl: new TokContext("${", false), | |
| 2416 | p_stat: new TokContext("(", false), | |
| 2417 | p_expr: new TokContext("(", true), | |
| 2418 | q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), | |
| 2419 | f_stat: new TokContext("function", false), | |
| 2420 | f_expr: new TokContext("function", true), | |
| 2421 | f_expr_gen: new TokContext("function", true, false, null, true), | |
| 2422 | f_gen: new TokContext("function", false, false, null, true) | |
| 2423 | }; | |
| 2424 | ||
| 2425 | var pp$6 = Parser.prototype; | |
| 2426 | ||
| 2427 | pp$6.initialContext = function() { | |
| 2428 | return [types.b_stat] | |
| 2429 | }; | |
| 2430 | ||
| 2431 | pp$6.curContext = function() { | |
| 2432 | return this.context[this.context.length - 1] | |
| 2433 | }; | |
| 2434 | ||
| 2435 | pp$6.braceIsBlock = function(prevType) { | |
| 2436 | var parent = this.curContext(); | |
| 2437 | if (parent === types.f_expr || parent === types.f_stat) | |
| 2438 | { return true } | |
| 2439 | if (prevType === types$1.colon && (parent === types.b_stat || parent === types.b_expr)) | |
| 2440 | { return !parent.isExpr } | |
| 2441 | ||
| 2442 | // The check for `tt.name && exprAllowed` detects whether we are | |
| 2443 | // after a `yield` or `of` construct. See the `updateContext` for | |
| 2444 | // `tt.name`. | |
| 2445 | if (prevType === types$1._return || prevType === types$1.name && this.exprAllowed) | |
| 2446 | { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } | |
| 2447 | if (prevType === types$1._else || prevType === types$1.semi || prevType === types$1.eof || prevType === types$1.parenR || prevType === types$1.arrow) | |
| 2448 | { return true } | |
| 2449 | if (prevType === types$1.braceL) | |
| 2450 | { return parent === types.b_stat } | |
| 2451 | if (prevType === types$1._var || prevType === types$1._const || prevType === types$1.name) | |
| 2452 | { return false } | |
| 2453 | return !this.exprAllowed | |
| 2454 | }; | |
| 2455 | ||
| 2456 | pp$6.inGeneratorContext = function() { | |
| 2457 | for (var i = this.context.length - 1; i >= 1; i--) { | |
| 2458 | var context = this.context[i]; | |
| 2459 | if (context.token === "function") | |
| 2460 | { return context.generator } | |
| 2461 | } | |
| 2462 | return false | |
| 2463 | }; | |
| 2464 | ||
| 2465 | pp$6.updateContext = function(prevType) { | |
| 2466 | var update, type = this.type; | |
| 2467 | if (type.keyword && prevType === types$1.dot) | |
| 2468 | { this.exprAllowed = false; } | |
| 2469 | else if (update = type.updateContext) | |
| 2470 | { update.call(this, prevType); } | |
| 2471 | else | |
| 2472 | { this.exprAllowed = type.beforeExpr; } | |
| 2473 | }; | |
| 2474 | ||
| 2475 | // Used to handle edge cases when token context could not be inferred correctly during tokenization phase | |
| 2476 | ||
| 2477 | pp$6.overrideContext = function(tokenCtx) { | |
| 2478 | if (this.curContext() !== tokenCtx) { | |
| 2479 | this.context[this.context.length - 1] = tokenCtx; | |
| 2480 | } | |
| 2481 | }; | |
| 2482 | ||
| 2483 | // Token-specific context update code | |
| 2484 | ||
| 2485 | types$1.parenR.updateContext = types$1.braceR.updateContext = function() { | |
| 2486 | if (this.context.length === 1) { | |
| 2487 | this.exprAllowed = true; | |
| 2488 | return | |
| 2489 | } | |
| 2490 | var out = this.context.pop(); | |
| 2491 | if (out === types.b_stat && this.curContext().token === "function") { | |
| 2492 | out = this.context.pop(); | |
| 2493 | } | |
| 2494 | this.exprAllowed = !out.isExpr; | |
| 2495 | }; | |
| 2496 | ||
| 2497 | types$1.braceL.updateContext = function(prevType) { | |
| 2498 | this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); | |
| 2499 | this.exprAllowed = true; | |
| 2500 | }; | |
| 2501 | ||
| 2502 | types$1.dollarBraceL.updateContext = function() { | |
| 2503 | this.context.push(types.b_tmpl); | |
| 2504 | this.exprAllowed = true; | |
| 2505 | }; | |
| 2506 | ||
| 2507 | types$1.parenL.updateContext = function(prevType) { | |
| 2508 | var statementParens = prevType === types$1._if || prevType === types$1._for || prevType === types$1._with || prevType === types$1._while; | |
| 2509 | this.context.push(statementParens ? types.p_stat : types.p_expr); | |
| 2510 | this.exprAllowed = true; | |
| 2511 | }; | |
| 2512 | ||
| 2513 | types$1.incDec.updateContext = function() { | |
| 2514 | // tokExprAllowed stays unchanged | |
| 2515 | }; | |
| 2516 | ||
| 2517 | types$1._function.updateContext = types$1._class.updateContext = function(prevType) { | |
| 2518 | if (prevType.beforeExpr && prevType !== types$1._else && | |
| 2519 | !(prevType === types$1.semi && this.curContext() !== types.p_stat) && | |
| 2520 | !(prevType === types$1._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && | |
| 2521 | !((prevType === types$1.colon || prevType === types$1.braceL) && this.curContext() === types.b_stat)) | |
| 2522 | { this.context.push(types.f_expr); } | |
| 2523 | else | |
| 2524 | { this.context.push(types.f_stat); } | |
| 2525 | this.exprAllowed = false; | |
| 2526 | }; | |
| 2527 | ||
| 2528 | types$1.colon.updateContext = function() { | |
| 2529 | if (this.curContext().token === "function") { this.context.pop(); } | |
| 2530 | this.exprAllowed = true; | |
| 2531 | }; | |
| 2532 | ||
| 2533 | types$1.backQuote.updateContext = function() { | |
| 2534 | if (this.curContext() === types.q_tmpl) | |
| 2535 | { this.context.pop(); } | |
| 2536 | else | |
| 2537 | { this.context.push(types.q_tmpl); } | |
| 2538 | this.exprAllowed = false; | |
| 2539 | }; | |
| 2540 | ||
| 2541 | types$1.star.updateContext = function(prevType) { | |
| 2542 | if (prevType === types$1._function) { | |
| 2543 | var index = this.context.length - 1; | |
| 2544 | if (this.context[index] === types.f_expr) | |
| 2545 | { this.context[index] = types.f_expr_gen; } | |
| 2546 | else | |
| 2547 | { this.context[index] = types.f_gen; } | |
| 2548 | } | |
| 2549 | this.exprAllowed = true; | |
| 2550 | }; | |
| 2551 | ||
| 2552 | types$1.name.updateContext = function(prevType) { | |
| 2553 | var allowed = false; | |
| 2554 | if (this.options.ecmaVersion >= 6 && prevType !== types$1.dot) { | |
| 2555 | if (this.value === "of" && !this.exprAllowed || | |
| 2556 | this.value === "yield" && this.inGeneratorContext()) | |
| 2557 | { allowed = true; } | |
| 2558 | } | |
| 2559 | this.exprAllowed = allowed; | |
| 2560 | }; | |
| 2561 | ||
| 2562 | // A recursive descent parser operates by defining functions for all | |
| 2563 | // syntactic elements, and recursively calling those, each function | |
| 2564 | // advancing the input stream and returning an AST node. Precedence | |
| 2565 | // of constructs (for example, the fact that `!x[1]` means `!(x[1])` | |
| 2566 | // instead of `(!x)[1]` is handled by the fact that the parser | |
| 2567 | // function that parses unary prefix operators is called first, and | |
| 2568 | // in turn calls the function that parses `[]` subscripts — that | |
| 2569 | // way, it'll receive the node for `x[1]` already parsed, and wraps | |
| 2570 | // *that* in the unary operator node. | |
| 2571 | // | |
| 2572 | // Acorn uses an [operator precedence parser][opp] to handle binary | |
| 2573 | // operator precedence, because it is much more compact than using | |
| 2574 | // the technique outlined above, which uses different, nesting | |
| 2575 | // functions to specify precedence, for all of the ten binary | |
| 2576 | // precedence levels that JavaScript defines. | |
| 2577 | // | |
| 2578 | // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser | |
| 2579 | ||
| 2580 | ||
| 2581 | var pp$5 = Parser.prototype; | |
| 2582 | ||
| 2583 | // Check if property name clashes with already added. | |
| 2584 | // Object/class getters and setters are not allowed to clash — | |
| 2585 | // either with each other or with an init property — and in | |
| 2586 | // strict mode, init properties are also not allowed to be repeated. | |
| 2587 | ||
| 2588 | pp$5.checkPropClash = function(prop, propHash, refDestructuringErrors) { | |
| 2589 | if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") | |
| 2590 | { return } | |
| 2591 | if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) | |
| 2592 | { return } | |
| 2593 | var key = prop.key; | |
| 2594 | var name; | |
| 2595 | switch (key.type) { | |
| 2596 | case "Identifier": name = key.name; break | |
| 2597 | case "Literal": name = String(key.value); break | |
| 2598 | default: return | |
| 2599 | } | |
| 2600 | var kind = prop.kind; | |
| 2601 | if (this.options.ecmaVersion >= 6) { | |
| 2602 | if (name === "__proto__" && kind === "init") { | |
| 2603 | if (propHash.proto) { | |
| 2604 | if (refDestructuringErrors) { | |
| 2605 | if (refDestructuringErrors.doubleProto < 0) { | |
| 2606 | refDestructuringErrors.doubleProto = key.start; | |
| 2607 | } | |
| 2608 | } else { | |
| 2609 | this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); | |
| 2610 | } | |
| 2611 | } | |
| 2612 | propHash.proto = true; | |
| 2613 | } | |
| 2614 | return | |
| 2615 | } | |
| 2616 | name = "$" + name; | |
| 2617 | var other = propHash[name]; | |
| 2618 | if (other) { | |
| 2619 | var redefinition; | |
| 2620 | if (kind === "init") { | |
| 2621 | redefinition = this.strict && other.init || other.get || other.set; | |
| 2622 | } else { | |
| 2623 | redefinition = other.init || other[kind]; | |
| 2624 | } | |
| 2625 | if (redefinition) | |
| 2626 | { this.raiseRecoverable(key.start, "Redefinition of property"); } | |
| 2627 | } else { | |
| 2628 | other = propHash[name] = { | |
| 2629 | init: false, | |
| 2630 | get: false, | |
| 2631 | set: false | |
| 2632 | }; | |
| 2633 | } | |
| 2634 | other[kind] = true; | |
| 2635 | }; | |
| 2636 | ||
| 2637 | // ### Expression parsing | |
| 2638 | ||
| 2639 | // These nest, from the most general expression type at the top to | |
| 2640 | // 'atomic', nondivisible expression types at the bottom. Most of | |
| 2641 | // the functions will simply let the function(s) below them parse, | |
| 2642 | // and, *if* the syntactic construct they handle is present, wrap | |
| 2643 | // the AST node that the inner parser gave them in another node. | |
| 2644 | ||
| 2645 | // Parse a full expression. The optional arguments are used to | |
| 2646 | // forbid the `in` operator (in for loops initalization expressions) | |
| 2647 | // and provide reference for storing '=' operator inside shorthand | |
| 2648 | // property assignment in contexts where both object expression | |
| 2649 | // and object pattern might appear (so it's possible to raise | |
| 2650 | // delayed syntax error at correct position). | |
| 2651 | ||
| 2652 | pp$5.parseExpression = function(forInit, refDestructuringErrors) { | |
| 2653 | var startPos = this.start, startLoc = this.startLoc; | |
| 2654 | var expr = this.parseMaybeAssign(forInit, refDestructuringErrors); | |
| 2655 | if (this.type === types$1.comma) { | |
| 2656 | var node = this.startNodeAt(startPos, startLoc); | |
| 2657 | node.expressions = [expr]; | |
| 2658 | while (this.eat(types$1.comma)) { node.expressions.push(this.parseMaybeAssign(forInit, refDestructuringErrors)); } | |
| 2659 | return this.finishNode(node, "SequenceExpression") | |
| 2660 | } | |
| 2661 | return expr | |
| 2662 | }; | |
| 2663 | ||
| 2664 | // Parse an assignment expression. This includes applications of | |
| 2665 | // operators like `+=`. | |
| 2666 | ||
| 2667 | pp$5.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse) { | |
| 2668 | if (this.isContextual("yield")) { | |
| 2669 | if (this.inGenerator) { return this.parseYield(forInit) } | |
| 2670 | // The tokenizer will assume an expression is allowed after | |
| 2671 | // `yield`, but this isn't that kind of yield | |
| 2672 | else { this.exprAllowed = false; } | |
| 2673 | } | |
| 2674 | ||
| 2675 | var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1; | |
| 2676 | if (refDestructuringErrors) { | |
| 2677 | oldParenAssign = refDestructuringErrors.parenthesizedAssign; | |
| 2678 | oldTrailingComma = refDestructuringErrors.trailingComma; | |
| 2679 | oldDoubleProto = refDestructuringErrors.doubleProto; | |
| 2680 | refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; | |
| 2681 | } else { | |
| 2682 | refDestructuringErrors = new DestructuringErrors; | |
| 2683 | ownDestructuringErrors = true; | |
| 2684 | } | |
| 2685 | ||
| 2686 | var startPos = this.start, startLoc = this.startLoc; | |
| 2687 | if (this.type === types$1.parenL || this.type === types$1.name) { | |
| 2688 | this.potentialArrowAt = this.start; | |
| 2689 | this.potentialArrowInForAwait = forInit === "await"; | |
| 2690 | } | |
| 2691 | var left = this.parseMaybeConditional(forInit, refDestructuringErrors); | |
| 2692 | if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } | |
| 2693 | if (this.type.isAssign) { | |
| 2694 | var node = this.startNodeAt(startPos, startLoc); | |
| 2695 | node.operator = this.value; | |
| 2696 | if (this.type === types$1.eq) | |
| 2697 | { left = this.toAssignable(left, false, refDestructuringErrors); } | |
| 2698 | if (!ownDestructuringErrors) { | |
| 2699 | refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1; | |
| 2700 | } | |
| 2701 | if (refDestructuringErrors.shorthandAssign >= left.start) | |
| 2702 | { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly | |
| 2703 | if (this.type === types$1.eq) | |
| 2704 | { this.checkLValPattern(left); } | |
| 2705 | else | |
| 2706 | { this.checkLValSimple(left); } | |
| 2707 | node.left = left; | |
| 2708 | this.next(); | |
| 2709 | node.right = this.parseMaybeAssign(forInit); | |
| 2710 | if (oldDoubleProto > -1) { refDestructuringErrors.doubleProto = oldDoubleProto; } | |
| 2711 | return this.finishNode(node, "AssignmentExpression") | |
| 2712 | } else { | |
| 2713 | if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } | |
| 2714 | } | |
| 2715 | if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } | |
| 2716 | if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } | |
| 2717 | return left | |
| 2718 | }; | |
| 2719 | ||
| 2720 | // Parse a ternary conditional (`?:`) operator. | |
| 2721 | ||
| 2722 | pp$5.parseMaybeConditional = function(forInit, refDestructuringErrors) { | |
| 2723 | var startPos = this.start, startLoc = this.startLoc; | |
| 2724 | var expr = this.parseExprOps(forInit, refDestructuringErrors); | |
| 2725 | if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
| 2726 | if (this.eat(types$1.question)) { | |
| 2727 | var node = this.startNodeAt(startPos, startLoc); | |
| 2728 | node.test = expr; | |
| 2729 | node.consequent = this.parseMaybeAssign(); | |
| 2730 | this.expect(types$1.colon); | |
| 2731 | node.alternate = this.parseMaybeAssign(forInit); | |
| 2732 | return this.finishNode(node, "ConditionalExpression") | |
| 2733 | } | |
| 2734 | return expr | |
| 2735 | }; | |
| 2736 | ||
| 2737 | // Start the precedence parser. | |
| 2738 | ||
| 2739 | pp$5.parseExprOps = function(forInit, refDestructuringErrors) { | |
| 2740 | var startPos = this.start, startLoc = this.startLoc; | |
| 2741 | var expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit); | |
| 2742 | if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
| 2743 | return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit) | |
| 2744 | }; | |
| 2745 | ||
| 2746 | // Parse binary operators with the operator precedence parsing | |
| 2747 | // algorithm. `left` is the left-hand side of the operator. | |
| 2748 | // `minPrec` provides context that allows the function to stop and | |
| 2749 | // defer further parser to one of its callers when it encounters an | |
| 2750 | // operator that has a lower precedence than the set it is parsing. | |
| 2751 | ||
| 2752 | pp$5.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, forInit) { | |
| 2753 | var prec = this.type.binop; | |
| 2754 | if (prec != null && (!forInit || this.type !== types$1._in)) { | |
| 2755 | if (prec > minPrec) { | |
| 2756 | var logical = this.type === types$1.logicalOR || this.type === types$1.logicalAND; | |
| 2757 | var coalesce = this.type === types$1.coalesce; | |
| 2758 | if (coalesce) { | |
| 2759 | // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions. | |
| 2760 | // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error. | |
| 2761 | prec = types$1.logicalAND.binop; | |
| 2762 | } | |
| 2763 | var op = this.value; | |
| 2764 | this.next(); | |
| 2765 | var startPos = this.start, startLoc = this.startLoc; | |
| 2766 | var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit); | |
| 2767 | var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce); | |
| 2768 | if ((logical && this.type === types$1.coalesce) || (coalesce && (this.type === types$1.logicalOR || this.type === types$1.logicalAND))) { | |
| 2769 | this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses"); | |
| 2770 | } | |
| 2771 | return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit) | |
| 2772 | } | |
| 2773 | } | |
| 2774 | return left | |
| 2775 | }; | |
| 2776 | ||
| 2777 | pp$5.buildBinary = function(startPos, startLoc, left, right, op, logical) { | |
| 2778 | if (right.type === "PrivateIdentifier") { this.raise(right.start, "Private identifier can only be left side of binary expression"); } | |
| 2779 | var node = this.startNodeAt(startPos, startLoc); | |
| 2780 | node.left = left; | |
| 2781 | node.operator = op; | |
| 2782 | node.right = right; | |
| 2783 | return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") | |
| 2784 | }; | |
| 2785 | ||
| 2786 | // Parse unary operators, both prefix and postfix. | |
| 2787 | ||
| 2788 | pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forInit) { | |
| 2789 | var startPos = this.start, startLoc = this.startLoc, expr; | |
| 2790 | if (this.isContextual("await") && this.canAwait) { | |
| 2791 | expr = this.parseAwait(forInit); | |
| 2792 | sawUnary = true; | |
| 2793 | } else if (this.type.prefix) { | |
| 2794 | var node = this.startNode(), update = this.type === types$1.incDec; | |
| 2795 | node.operator = this.value; | |
| 2796 | node.prefix = true; | |
| 2797 | this.next(); | |
| 2798 | node.argument = this.parseMaybeUnary(null, true, update, forInit); | |
| 2799 | this.checkExpressionErrors(refDestructuringErrors, true); | |
| 2800 | if (update) { this.checkLValSimple(node.argument); } | |
| 2801 | else if (this.strict && node.operator === "delete" && isLocalVariableAccess(node.argument)) | |
| 2802 | { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } | |
| 2803 | else if (node.operator === "delete" && isPrivateFieldAccess(node.argument)) | |
| 2804 | { this.raiseRecoverable(node.start, "Private fields can not be deleted"); } | |
| 2805 | else { sawUnary = true; } | |
| 2806 | expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); | |
| 2807 | } else if (!sawUnary && this.type === types$1.privateId) { | |
| 2808 | if ((forInit || this.privateNameStack.length === 0) && this.options.checkPrivateFields) { this.unexpected(); } | |
| 2809 | expr = this.parsePrivateIdent(); | |
| 2810 | // only could be private fields in 'in', such as #x in obj | |
| 2811 | if (this.type !== types$1._in) { this.unexpected(); } | |
| 2812 | } else { | |
| 2813 | expr = this.parseExprSubscripts(refDestructuringErrors, forInit); | |
| 2814 | if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
| 2815 | while (this.type.postfix && !this.canInsertSemicolon()) { | |
| 2816 | var node$1 = this.startNodeAt(startPos, startLoc); | |
| 2817 | node$1.operator = this.value; | |
| 2818 | node$1.prefix = false; | |
| 2819 | node$1.argument = expr; | |
| 2820 | this.checkLValSimple(expr); | |
| 2821 | this.next(); | |
| 2822 | expr = this.finishNode(node$1, "UpdateExpression"); | |
| 2823 | } | |
| 2824 | } | |
| 2825 | ||
| 2826 | if (!incDec && this.eat(types$1.starstar)) { | |
| 2827 | if (sawUnary) | |
| 2828 | { this.unexpected(this.lastTokStart); } | |
| 2829 | else | |
| 2830 | { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false) } | |
| 2831 | } else { | |
| 2832 | return expr | |
| 2833 | } | |
| 2834 | }; | |
| 2835 | ||
| 2836 | function isLocalVariableAccess(node) { | |
| 2837 | return ( | |
| 2838 | node.type === "Identifier" || | |
| 2839 | node.type === "ParenthesizedExpression" && isLocalVariableAccess(node.expression) | |
| 2840 | ) | |
| 2841 | } | |
| 2842 | ||
| 2843 | function isPrivateFieldAccess(node) { | |
| 2844 | return ( | |
| 2845 | node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" || | |
| 2846 | node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) || | |
| 2847 | node.type === "ParenthesizedExpression" && isPrivateFieldAccess(node.expression) | |
| 2848 | ) | |
| 2849 | } | |
| 2850 | ||
| 2851 | // Parse call, dot, and `[]`-subscript expressions. | |
| 2852 | ||
| 2853 | pp$5.parseExprSubscripts = function(refDestructuringErrors, forInit) { | |
| 2854 | var startPos = this.start, startLoc = this.startLoc; | |
| 2855 | var expr = this.parseExprAtom(refDestructuringErrors, forInit); | |
| 2856 | if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")") | |
| 2857 | { return expr } | |
| 2858 | var result = this.parseSubscripts(expr, startPos, startLoc, false, forInit); | |
| 2859 | if (refDestructuringErrors && result.type === "MemberExpression") { | |
| 2860 | if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } | |
| 2861 | if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } | |
| 2862 | if (refDestructuringErrors.trailingComma >= result.start) { refDestructuringErrors.trailingComma = -1; } | |
| 2863 | } | |
| 2864 | return result | |
| 2865 | }; | |
| 2866 | ||
| 2867 | pp$5.parseSubscripts = function(base, startPos, startLoc, noCalls, forInit) { | |
| 2868 | var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && | |
| 2869 | this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && | |
| 2870 | this.potentialArrowAt === base.start; | |
| 2871 | var optionalChained = false; | |
| 2872 | ||
| 2873 | while (true) { | |
| 2874 | var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit); | |
| 2875 | ||
| 2876 | if (element.optional) { optionalChained = true; } | |
| 2877 | if (element === base || element.type === "ArrowFunctionExpression") { | |
| 2878 | if (optionalChained) { | |
| 2879 | var chainNode = this.startNodeAt(startPos, startLoc); | |
| 2880 | chainNode.expression = element; | |
| 2881 | element = this.finishNode(chainNode, "ChainExpression"); | |
| 2882 | } | |
| 2883 | return element | |
| 2884 | } | |
| 2885 | ||
| 2886 | base = element; | |
| 2887 | } | |
| 2888 | }; | |
| 2889 | ||
| 2890 | pp$5.shouldParseAsyncArrow = function() { | |
| 2891 | return !this.canInsertSemicolon() && this.eat(types$1.arrow) | |
| 2892 | }; | |
| 2893 | ||
| 2894 | pp$5.parseSubscriptAsyncArrow = function(startPos, startLoc, exprList, forInit) { | |
| 2895 | return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true, forInit) | |
| 2896 | }; | |
| 2897 | ||
| 2898 | pp$5.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) { | |
| 2899 | var optionalSupported = this.options.ecmaVersion >= 11; | |
| 2900 | var optional = optionalSupported && this.eat(types$1.questionDot); | |
| 2901 | if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); } | |
| 2902 | ||
| 2903 | var computed = this.eat(types$1.bracketL); | |
| 2904 | if (computed || (optional && this.type !== types$1.parenL && this.type !== types$1.backQuote) || this.eat(types$1.dot)) { | |
| 2905 | var node = this.startNodeAt(startPos, startLoc); | |
| 2906 | node.object = base; | |
| 2907 | if (computed) { | |
| 2908 | node.property = this.parseExpression(); | |
| 2909 | this.expect(types$1.bracketR); | |
| 2910 | } else if (this.type === types$1.privateId && base.type !== "Super") { | |
| 2911 | node.property = this.parsePrivateIdent(); | |
| 2912 | } else { | |
| 2913 | node.property = this.parseIdent(this.options.allowReserved !== "never"); | |
| 2914 | } | |
| 2915 | node.computed = !!computed; | |
| 2916 | if (optionalSupported) { | |
| 2917 | node.optional = optional; | |
| 2918 | } | |
| 2919 | base = this.finishNode(node, "MemberExpression"); | |
| 2920 | } else if (!noCalls && this.eat(types$1.parenL)) { | |
| 2921 | var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
| 2922 | this.yieldPos = 0; | |
| 2923 | this.awaitPos = 0; | |
| 2924 | this.awaitIdentPos = 0; | |
| 2925 | var exprList = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors); | |
| 2926 | if (maybeAsyncArrow && !optional && this.shouldParseAsyncArrow()) { | |
| 2927 | this.checkPatternErrors(refDestructuringErrors, false); | |
| 2928 | this.checkYieldAwaitInDefaultParams(); | |
| 2929 | if (this.awaitIdentPos > 0) | |
| 2930 | { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); } | |
| 2931 | this.yieldPos = oldYieldPos; | |
| 2932 | this.awaitPos = oldAwaitPos; | |
| 2933 | this.awaitIdentPos = oldAwaitIdentPos; | |
| 2934 | return this.parseSubscriptAsyncArrow(startPos, startLoc, exprList, forInit) | |
| 2935 | } | |
| 2936 | this.checkExpressionErrors(refDestructuringErrors, true); | |
| 2937 | this.yieldPos = oldYieldPos || this.yieldPos; | |
| 2938 | this.awaitPos = oldAwaitPos || this.awaitPos; | |
| 2939 | this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos; | |
| 2940 | var node$1 = this.startNodeAt(startPos, startLoc); | |
| 2941 | node$1.callee = base; | |
| 2942 | node$1.arguments = exprList; | |
| 2943 | if (optionalSupported) { | |
| 2944 | node$1.optional = optional; | |
| 2945 | } | |
| 2946 | base = this.finishNode(node$1, "CallExpression"); | |
| 2947 | } else if (this.type === types$1.backQuote) { | |
| 2948 | if (optional || optionalChained) { | |
| 2949 | this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions"); | |
| 2950 | } | |
| 2951 | var node$2 = this.startNodeAt(startPos, startLoc); | |
| 2952 | node$2.tag = base; | |
| 2953 | node$2.quasi = this.parseTemplate({isTagged: true}); | |
| 2954 | base = this.finishNode(node$2, "TaggedTemplateExpression"); | |
| 2955 | } | |
| 2956 | return base | |
| 2957 | }; | |
| 2958 | ||
| 2959 | // Parse an atomic expression — either a single token that is an | |
| 2960 | // expression, an expression started by a keyword like `function` or | |
| 2961 | // `new`, or an expression wrapped in punctuation like `()`, `[]`, | |
| 2962 | // or `{}`. | |
| 2963 | ||
| 2964 | pp$5.parseExprAtom = function(refDestructuringErrors, forInit, forNew) { | |
| 2965 | // If a division operator appears in an expression position, the | |
| 2966 | // tokenizer got confused, and we force it to read a regexp instead. | |
| 2967 | if (this.type === types$1.slash) { this.readRegexp(); } | |
| 2968 | ||
| 2969 | var node, canBeArrow = this.potentialArrowAt === this.start; | |
| 2970 | switch (this.type) { | |
| 2971 | case types$1._super: | |
| 2972 | if (!this.allowSuper) | |
| 2973 | { this.raise(this.start, "'super' keyword outside a method"); } | |
| 2974 | node = this.startNode(); | |
| 2975 | this.next(); | |
| 2976 | if (this.type === types$1.parenL && !this.allowDirectSuper) | |
| 2977 | { this.raise(node.start, "super() call outside constructor of a subclass"); } | |
| 2978 | // The `super` keyword can appear at below: | |
| 2979 | // SuperProperty: | |
| 2980 | // super [ Expression ] | |
| 2981 | // super . IdentifierName | |
| 2982 | // SuperCall: | |
| 2983 | // super ( Arguments ) | |
| 2984 | if (this.type !== types$1.dot && this.type !== types$1.bracketL && this.type !== types$1.parenL) | |
| 2985 | { this.unexpected(); } | |
| 2986 | return this.finishNode(node, "Super") | |
| 2987 | ||
| 2988 | case types$1._this: | |
| 2989 | node = this.startNode(); | |
| 2990 | this.next(); | |
| 2991 | return this.finishNode(node, "ThisExpression") | |
| 2992 | ||
| 2993 | case types$1.name: | |
| 2994 | var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; | |
| 2995 | var id = this.parseIdent(false); | |
| 2996 | if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types$1._function)) { | |
| 2997 | this.overrideContext(types.f_expr); | |
| 2998 | return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true, forInit) | |
| 2999 | } | |
| 3000 | if (canBeArrow && !this.canInsertSemicolon()) { | |
| 3001 | if (this.eat(types$1.arrow)) | |
| 3002 | { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false, forInit) } | |
| 3003 | if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types$1.name && !containsEsc && | |
| 3004 | (!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) { | |
| 3005 | id = this.parseIdent(false); | |
| 3006 | if (this.canInsertSemicolon() || !this.eat(types$1.arrow)) | |
| 3007 | { this.unexpected(); } | |
| 3008 | return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true, forInit) | |
| 3009 | } | |
| 3010 | } | |
| 3011 | return id | |
| 3012 | ||
| 3013 | case types$1.regexp: | |
| 3014 | var value = this.value; | |
| 3015 | node = this.parseLiteral(value.value); | |
| 3016 | node.regex = {pattern: value.pattern, flags: value.flags}; | |
| 3017 | return node | |
| 3018 | ||
| 3019 | case types$1.num: case types$1.string: | |
| 3020 | return this.parseLiteral(this.value) | |
| 3021 | ||
| 3022 | case types$1._null: case types$1._true: case types$1._false: | |
| 3023 | node = this.startNode(); | |
| 3024 | node.value = this.type === types$1._null ? null : this.type === types$1._true; | |
| 3025 | node.raw = this.type.keyword; | |
| 3026 | this.next(); | |
| 3027 | return this.finishNode(node, "Literal") | |
| 3028 | ||
| 3029 | case types$1.parenL: | |
| 3030 | var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow, forInit); | |
| 3031 | if (refDestructuringErrors) { | |
| 3032 | if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) | |
| 3033 | { refDestructuringErrors.parenthesizedAssign = start; } | |
| 3034 | if (refDestructuringErrors.parenthesizedBind < 0) | |
| 3035 | { refDestructuringErrors.parenthesizedBind = start; } | |
| 3036 | } | |
| 3037 | return expr | |
| 3038 | ||
| 3039 | case types$1.bracketL: | |
| 3040 | node = this.startNode(); | |
| 3041 | this.next(); | |
| 3042 | node.elements = this.parseExprList(types$1.bracketR, true, true, refDestructuringErrors); | |
| 3043 | return this.finishNode(node, "ArrayExpression") | |
| 3044 | ||
| 3045 | case types$1.braceL: | |
| 3046 | this.overrideContext(types.b_expr); | |
| 3047 | return this.parseObj(false, refDestructuringErrors) | |
| 3048 | ||
| 3049 | case types$1._function: | |
| 3050 | node = this.startNode(); | |
| 3051 | this.next(); | |
| 3052 | return this.parseFunction(node, 0) | |
| 3053 | ||
| 3054 | case types$1._class: | |
| 3055 | return this.parseClass(this.startNode(), false) | |
| 3056 | ||
| 3057 | case types$1._new: | |
| 3058 | return this.parseNew() | |
| 3059 | ||
| 3060 | case types$1.backQuote: | |
| 3061 | return this.parseTemplate() | |
| 3062 | ||
| 3063 | case types$1._import: | |
| 3064 | if (this.options.ecmaVersion >= 11) { | |
| 3065 | return this.parseExprImport(forNew) | |
| 3066 | } else { | |
| 3067 | return this.unexpected() | |
| 3068 | } | |
| 3069 | ||
| 3070 | default: | |
| 3071 | return this.parseExprAtomDefault() | |
| 3072 | } | |
| 3073 | }; | |
| 3074 | ||
| 3075 | pp$5.parseExprAtomDefault = function() { | |
| 3076 | this.unexpected(); | |
| 3077 | }; | |
| 3078 | ||
| 3079 | pp$5.parseExprImport = function(forNew) { | |
| 3080 | var node = this.startNode(); | |
| 3081 | ||
| 3082 | // Consume `import` as an identifier for `import.meta`. | |
| 3083 | // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`. | |
| 3084 | if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); } | |
| 3085 | this.next(); | |
| 3086 | ||
| 3087 | if (this.type === types$1.parenL && !forNew) { | |
| 3088 | return this.parseDynamicImport(node) | |
| 3089 | } else if (this.type === types$1.dot) { | |
| 3090 | var meta = this.startNodeAt(node.start, node.loc && node.loc.start); | |
| 3091 | meta.name = "import"; | |
| 3092 | node.meta = this.finishNode(meta, "Identifier"); | |
| 3093 | return this.parseImportMeta(node) | |
| 3094 | } else { | |
| 3095 | this.unexpected(); | |
| 3096 | } | |
| 3097 | }; | |
| 3098 | ||
| 3099 | pp$5.parseDynamicImport = function(node) { | |
| 3100 | this.next(); // skip `(` | |
| 3101 | ||
| 3102 | // Parse node.source. | |
| 3103 | node.source = this.parseMaybeAssign(); | |
| 3104 | ||
| 3105 | if (this.options.ecmaVersion >= 16) { | |
| 3106 | if (!this.eat(types$1.parenR)) { | |
| 3107 | this.expect(types$1.comma); | |
| 3108 | if (!this.afterTrailingComma(types$1.parenR)) { | |
| 3109 | node.options = this.parseMaybeAssign(); | |
| 3110 | if (!this.eat(types$1.parenR)) { | |
| 3111 | this.expect(types$1.comma); | |
| 3112 | if (!this.afterTrailingComma(types$1.parenR)) { | |
| 3113 | this.unexpected(); | |
| 3114 | } | |
| 3115 | } | |
| 3116 | } else { | |
| 3117 | node.options = null; | |
| 3118 | } | |
| 3119 | } else { | |
| 3120 | node.options = null; | |
| 3121 | } | |
| 3122 | } else { | |
| 3123 | // Verify ending. | |
| 3124 | if (!this.eat(types$1.parenR)) { | |
| 3125 | var errorPos = this.start; | |
| 3126 | if (this.eat(types$1.comma) && this.eat(types$1.parenR)) { | |
| 3127 | this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()"); | |
| 3128 | } else { | |
| 3129 | this.unexpected(errorPos); | |
| 3130 | } | |
| 3131 | } | |
| 3132 | } | |
| 3133 | ||
| 3134 | return this.finishNode(node, "ImportExpression") | |
| 3135 | }; | |
| 3136 | ||
| 3137 | pp$5.parseImportMeta = function(node) { | |
| 3138 | this.next(); // skip `.` | |
| 3139 | ||
| 3140 | var containsEsc = this.containsEsc; | |
| 3141 | node.property = this.parseIdent(true); | |
| 3142 | ||
| 3143 | if (node.property.name !== "meta") | |
| 3144 | { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); } | |
| 3145 | if (containsEsc) | |
| 3146 | { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); } | |
| 3147 | if (this.options.sourceType !== "module" && !this.options.allowImportExportEverywhere) | |
| 3148 | { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); } | |
| 3149 | ||
| 3150 | return this.finishNode(node, "MetaProperty") | |
| 3151 | }; | |
| 3152 | ||
| 3153 | pp$5.parseLiteral = function(value) { | |
| 3154 | var node = this.startNode(); | |
| 3155 | node.value = value; | |
| 3156 | node.raw = this.input.slice(this.start, this.end); | |
| 3157 | if (node.raw.charCodeAt(node.raw.length - 1) === 110) | |
| 3158 | { node.bigint = node.value != null ? node.value.toString() : node.raw.slice(0, -1).replace(/_/g, ""); } | |
| 3159 | this.next(); | |
| 3160 | return this.finishNode(node, "Literal") | |
| 3161 | }; | |
| 3162 | ||
| 3163 | pp$5.parseParenExpression = function() { | |
| 3164 | this.expect(types$1.parenL); | |
| 3165 | var val = this.parseExpression(); | |
| 3166 | this.expect(types$1.parenR); | |
| 3167 | return val | |
| 3168 | }; | |
| 3169 | ||
| 3170 | pp$5.shouldParseArrow = function(exprList) { | |
| 3171 | return !this.canInsertSemicolon() | |
| 3172 | }; | |
| 3173 | ||
| 3174 | pp$5.parseParenAndDistinguishExpression = function(canBeArrow, forInit) { | |
| 3175 | var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; | |
| 3176 | if (this.options.ecmaVersion >= 6) { | |
| 3177 | this.next(); | |
| 3178 | ||
| 3179 | var innerStartPos = this.start, innerStartLoc = this.startLoc; | |
| 3180 | var exprList = [], first = true, lastIsComma = false; | |
| 3181 | var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; | |
| 3182 | this.yieldPos = 0; | |
| 3183 | this.awaitPos = 0; | |
| 3184 | // Do not save awaitIdentPos to allow checking awaits nested in parameters | |
| 3185 | while (this.type !== types$1.parenR) { | |
| 3186 | first ? first = false : this.expect(types$1.comma); | |
| 3187 | if (allowTrailingComma && this.afterTrailingComma(types$1.parenR, true)) { | |
| 3188 | lastIsComma = true; | |
| 3189 | break | |
| 3190 | } else if (this.type === types$1.ellipsis) { | |
| 3191 | spreadStart = this.start; | |
| 3192 | exprList.push(this.parseParenItem(this.parseRestBinding())); | |
| 3193 | if (this.type === types$1.comma) { | |
| 3194 | this.raiseRecoverable( | |
| 3195 | this.start, | |
| 3196 | "Comma is not permitted after the rest element" | |
| 3197 | ); | |
| 3198 | } | |
| 3199 | break | |
| 3200 | } else { | |
| 3201 | exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); | |
| 3202 | } | |
| 3203 | } | |
| 3204 | var innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc; | |
| 3205 | this.expect(types$1.parenR); | |
| 3206 | ||
| 3207 | if (canBeArrow && this.shouldParseArrow(exprList) && this.eat(types$1.arrow)) { | |
| 3208 | this.checkPatternErrors(refDestructuringErrors, false); | |
| 3209 | this.checkYieldAwaitInDefaultParams(); | |
| 3210 | this.yieldPos = oldYieldPos; | |
| 3211 | this.awaitPos = oldAwaitPos; | |
| 3212 | return this.parseParenArrowList(startPos, startLoc, exprList, forInit) | |
| 3213 | } | |
| 3214 | ||
| 3215 | if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } | |
| 3216 | if (spreadStart) { this.unexpected(spreadStart); } | |
| 3217 | this.checkExpressionErrors(refDestructuringErrors, true); | |
| 3218 | this.yieldPos = oldYieldPos || this.yieldPos; | |
| 3219 | this.awaitPos = oldAwaitPos || this.awaitPos; | |
| 3220 | ||
| 3221 | if (exprList.length > 1) { | |
| 3222 | val = this.startNodeAt(innerStartPos, innerStartLoc); | |
| 3223 | val.expressions = exprList; | |
| 3224 | this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); | |
| 3225 | } else { | |
| 3226 | val = exprList[0]; | |
| 3227 | } | |
| 3228 | } else { | |
| 3229 | val = this.parseParenExpression(); | |
| 3230 | } | |
| 3231 | ||
| 3232 | if (this.options.preserveParens) { | |
| 3233 | var par = this.startNodeAt(startPos, startLoc); | |
| 3234 | par.expression = val; | |
| 3235 | return this.finishNode(par, "ParenthesizedExpression") | |
| 3236 | } else { | |
| 3237 | return val | |
| 3238 | } | |
| 3239 | }; | |
| 3240 | ||
| 3241 | pp$5.parseParenItem = function(item) { | |
| 3242 | return item | |
| 3243 | }; | |
| 3244 | ||
| 3245 | pp$5.parseParenArrowList = function(startPos, startLoc, exprList, forInit) { | |
| 3246 | return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit) | |
| 3247 | }; | |
| 3248 | ||
| 3249 | // New's precedence is slightly tricky. It must allow its argument to | |
| 3250 | // be a `[]` or dot subscript expression, but not a call — at least, | |
| 3251 | // not without wrapping it in parentheses. Thus, it uses the noCalls | |
| 3252 | // argument to parseSubscripts to prevent it from consuming the | |
| 3253 | // argument list. | |
| 3254 | ||
| 3255 | var empty = []; | |
| 3256 | ||
| 3257 | pp$5.parseNew = function() { | |
| 3258 | if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); } | |
| 3259 | var node = this.startNode(); | |
| 3260 | this.next(); | |
| 3261 | if (this.options.ecmaVersion >= 6 && this.type === types$1.dot) { | |
| 3262 | var meta = this.startNodeAt(node.start, node.loc && node.loc.start); | |
| 3263 | meta.name = "new"; | |
| 3264 | node.meta = this.finishNode(meta, "Identifier"); | |
| 3265 | this.next(); | |
| 3266 | var containsEsc = this.containsEsc; | |
| 3267 | node.property = this.parseIdent(true); | |
| 3268 | if (node.property.name !== "target") | |
| 3269 | { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); } | |
| 3270 | if (containsEsc) | |
| 3271 | { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); } | |
| 3272 | if (!this.allowNewDotTarget) | |
| 3273 | { this.raiseRecoverable(node.start, "'new.target' can only be used in functions and class static block"); } | |
| 3274 | return this.finishNode(node, "MetaProperty") | |
| 3275 | } | |
| 3276 | var startPos = this.start, startLoc = this.startLoc; | |
| 3277 | node.callee = this.parseSubscripts(this.parseExprAtom(null, false, true), startPos, startLoc, true, false); | |
| 3278 | if (this.eat(types$1.parenL)) { node.arguments = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false); } | |
| 3279 | else { node.arguments = empty; } | |
| 3280 | return this.finishNode(node, "NewExpression") | |
| 3281 | }; | |
| 3282 | ||
| 3283 | // Parse template expression. | |
| 3284 | ||
| 3285 | pp$5.parseTemplateElement = function(ref) { | |
| 3286 | var isTagged = ref.isTagged; | |
| 3287 | ||
| 3288 | var elem = this.startNode(); | |
| 3289 | if (this.type === types$1.invalidTemplate) { | |
| 3290 | if (!isTagged) { | |
| 3291 | this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); | |
| 3292 | } | |
| 3293 | elem.value = { | |
| 3294 | raw: this.value.replace(/\r\n?/g, "\n"), | |
| 3295 | cooked: null | |
| 3296 | }; | |
| 3297 | } else { | |
| 3298 | elem.value = { | |
| 3299 | raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), | |
| 3300 | cooked: this.value | |
| 3301 | }; | |
| 3302 | } | |
| 3303 | this.next(); | |
| 3304 | elem.tail = this.type === types$1.backQuote; | |
| 3305 | return this.finishNode(elem, "TemplateElement") | |
| 3306 | }; | |
| 3307 | ||
| 3308 | pp$5.parseTemplate = function(ref) { | |
| 3309 | if ( ref === void 0 ) ref = {}; | |
| 3310 | var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; | |
| 3311 | ||
| 3312 | var node = this.startNode(); | |
| 3313 | this.next(); | |
| 3314 | node.expressions = []; | |
| 3315 | var curElt = this.parseTemplateElement({isTagged: isTagged}); | |
| 3316 | node.quasis = [curElt]; | |
| 3317 | while (!curElt.tail) { | |
| 3318 | if (this.type === types$1.eof) { this.raise(this.pos, "Unterminated template literal"); } | |
| 3319 | this.expect(types$1.dollarBraceL); | |
| 3320 | node.expressions.push(this.parseExpression()); | |
| 3321 | this.expect(types$1.braceR); | |
| 3322 | node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged})); | |
| 3323 | } | |
| 3324 | this.next(); | |
| 3325 | return this.finishNode(node, "TemplateLiteral") | |
| 3326 | }; | |
| 3327 | ||
| 3328 | pp$5.isAsyncProp = function(prop) { | |
| 3329 | return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && | |
| 3330 | (this.type === types$1.name || this.type === types$1.num || this.type === types$1.string || this.type === types$1.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types$1.star)) && | |
| 3331 | !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) | |
| 3332 | }; | |
| 3333 | ||
| 3334 | // Parse an object literal or binding pattern. | |
| 3335 | ||
| 3336 | pp$5.parseObj = function(isPattern, refDestructuringErrors) { | |
| 3337 | var node = this.startNode(), first = true, propHash = {}; | |
| 3338 | node.properties = []; | |
| 3339 | this.next(); | |
| 3340 | while (!this.eat(types$1.braceR)) { | |
| 3341 | if (!first) { | |
| 3342 | this.expect(types$1.comma); | |
| 3343 | if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types$1.braceR)) { break } | |
| 3344 | } else { first = false; } | |
| 3345 | ||
| 3346 | var prop = this.parseProperty(isPattern, refDestructuringErrors); | |
| 3347 | if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); } | |
| 3348 | node.properties.push(prop); | |
| 3349 | } | |
| 3350 | return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") | |
| 3351 | }; | |
| 3352 | ||
| 3353 | pp$5.parseProperty = function(isPattern, refDestructuringErrors) { | |
| 3354 | var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; | |
| 3355 | if (this.options.ecmaVersion >= 9 && this.eat(types$1.ellipsis)) { | |
| 3356 | if (isPattern) { | |
| 3357 | prop.argument = this.parseIdent(false); | |
| 3358 | if (this.type === types$1.comma) { | |
| 3359 | this.raiseRecoverable(this.start, "Comma is not permitted after the rest element"); | |
| 3360 | } | |
| 3361 | return this.finishNode(prop, "RestElement") | |
| 3362 | } | |
| 3363 | // Parse argument. | |
| 3364 | prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); | |
| 3365 | // To disallow trailing comma via `this.toAssignable()`. | |
| 3366 | if (this.type === types$1.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { | |
| 3367 | refDestructuringErrors.trailingComma = this.start; | |
| 3368 | } | |
| 3369 | // Finish | |
| 3370 | return this.finishNode(prop, "SpreadElement") | |
| 3371 | } | |
| 3372 | if (this.options.ecmaVersion >= 6) { | |
| 3373 | prop.method = false; | |
| 3374 | prop.shorthand = false; | |
| 3375 | if (isPattern || refDestructuringErrors) { | |
| 3376 | startPos = this.start; | |
| 3377 | startLoc = this.startLoc; | |
| 3378 | } | |
| 3379 | if (!isPattern) | |
| 3380 | { isGenerator = this.eat(types$1.star); } | |
| 3381 | } | |
| 3382 | var containsEsc = this.containsEsc; | |
| 3383 | this.parsePropertyName(prop); | |
| 3384 | if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { | |
| 3385 | isAsync = true; | |
| 3386 | isGenerator = this.options.ecmaVersion >= 9 && this.eat(types$1.star); | |
| 3387 | this.parsePropertyName(prop); | |
| 3388 | } else { | |
| 3389 | isAsync = false; | |
| 3390 | } | |
| 3391 | this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); | |
| 3392 | return this.finishNode(prop, "Property") | |
| 3393 | }; | |
| 3394 | ||
| 3395 | pp$5.parseGetterSetter = function(prop) { | |
| 3396 | var kind = prop.key.name; | |
| 3397 | this.parsePropertyName(prop); | |
| 3398 | prop.value = this.parseMethod(false); | |
| 3399 | prop.kind = kind; | |
| 3400 | var paramCount = prop.kind === "get" ? 0 : 1; | |
| 3401 | if (prop.value.params.length !== paramCount) { | |
| 3402 | var start = prop.value.start; | |
| 3403 | if (prop.kind === "get") | |
| 3404 | { this.raiseRecoverable(start, "getter should have no params"); } | |
| 3405 | else | |
| 3406 | { this.raiseRecoverable(start, "setter should have exactly one param"); } | |
| 3407 | } else { | |
| 3408 | if (prop.kind === "set" && prop.value.params[0].type === "RestElement") | |
| 3409 | { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } | |
| 3410 | } | |
| 3411 | }; | |
| 3412 | ||
| 3413 | pp$5.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { | |
| 3414 | if ((isGenerator || isAsync) && this.type === types$1.colon) | |
| 3415 | { this.unexpected(); } | |
| 3416 | ||
| 3417 | if (this.eat(types$1.colon)) { | |
| 3418 | prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); | |
| 3419 | prop.kind = "init"; | |
| 3420 | } else if (this.options.ecmaVersion >= 6 && this.type === types$1.parenL) { | |
| 3421 | if (isPattern) { this.unexpected(); } | |
| 3422 | prop.method = true; | |
| 3423 | prop.value = this.parseMethod(isGenerator, isAsync); | |
| 3424 | prop.kind = "init"; | |
| 3425 | } else if (!isPattern && !containsEsc && | |
| 3426 | this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && | |
| 3427 | (prop.key.name === "get" || prop.key.name === "set") && | |
| 3428 | (this.type !== types$1.comma && this.type !== types$1.braceR && this.type !== types$1.eq)) { | |
| 3429 | if (isGenerator || isAsync) { this.unexpected(); } | |
| 3430 | this.parseGetterSetter(prop); | |
| 3431 | } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { | |
| 3432 | if (isGenerator || isAsync) { this.unexpected(); } | |
| 3433 | this.checkUnreserved(prop.key); | |
| 3434 | if (prop.key.name === "await" && !this.awaitIdentPos) | |
| 3435 | { this.awaitIdentPos = startPos; } | |
| 3436 | if (isPattern) { | |
| 3437 | prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); | |
| 3438 | } else if (this.type === types$1.eq && refDestructuringErrors) { | |
| 3439 | if (refDestructuringErrors.shorthandAssign < 0) | |
| 3440 | { refDestructuringErrors.shorthandAssign = this.start; } | |
| 3441 | prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); | |
| 3442 | } else { | |
| 3443 | prop.value = this.copyNode(prop.key); | |
| 3444 | } | |
| 3445 | prop.kind = "init"; | |
| 3446 | prop.shorthand = true; | |
| 3447 | } else { this.unexpected(); } | |
| 3448 | }; | |
| 3449 | ||
| 3450 | pp$5.parsePropertyName = function(prop) { | |
| 3451 | if (this.options.ecmaVersion >= 6) { | |
| 3452 | if (this.eat(types$1.bracketL)) { | |
| 3453 | prop.computed = true; | |
| 3454 | prop.key = this.parseMaybeAssign(); | |
| 3455 | this.expect(types$1.bracketR); | |
| 3456 | return prop.key | |
| 3457 | } else { | |
| 3458 | prop.computed = false; | |
| 3459 | } | |
| 3460 | } | |
| 3461 | return prop.key = this.type === types$1.num || this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never") | |
| 3462 | }; | |
| 3463 | ||
| 3464 | // Initialize empty function node. | |
| 3465 | ||
| 3466 | pp$5.initFunction = function(node) { | |
| 3467 | node.id = null; | |
| 3468 | if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; } | |
| 3469 | if (this.options.ecmaVersion >= 8) { node.async = false; } | |
| 3470 | }; | |
| 3471 | ||
| 3472 | // Parse object or class method. | |
| 3473 | ||
| 3474 | pp$5.parseMethod = function(isGenerator, isAsync, allowDirectSuper) { | |
| 3475 | var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
| 3476 | ||
| 3477 | this.initFunction(node); | |
| 3478 | if (this.options.ecmaVersion >= 6) | |
| 3479 | { node.generator = isGenerator; } | |
| 3480 | if (this.options.ecmaVersion >= 8) | |
| 3481 | { node.async = !!isAsync; } | |
| 3482 | ||
| 3483 | this.yieldPos = 0; | |
| 3484 | this.awaitPos = 0; | |
| 3485 | this.awaitIdentPos = 0; | |
| 3486 | this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0)); | |
| 3487 | ||
| 3488 | this.expect(types$1.parenL); | |
| 3489 | node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); | |
| 3490 | this.checkYieldAwaitInDefaultParams(); | |
| 3491 | this.parseFunctionBody(node, false, true, false); | |
| 3492 | ||
| 3493 | this.yieldPos = oldYieldPos; | |
| 3494 | this.awaitPos = oldAwaitPos; | |
| 3495 | this.awaitIdentPos = oldAwaitIdentPos; | |
| 3496 | return this.finishNode(node, "FunctionExpression") | |
| 3497 | }; | |
| 3498 | ||
| 3499 | // Parse arrow function expression with given parameters. | |
| 3500 | ||
| 3501 | pp$5.parseArrowExpression = function(node, params, isAsync, forInit) { | |
| 3502 | var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
| 3503 | ||
| 3504 | this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW); | |
| 3505 | this.initFunction(node); | |
| 3506 | if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } | |
| 3507 | ||
| 3508 | this.yieldPos = 0; | |
| 3509 | this.awaitPos = 0; | |
| 3510 | this.awaitIdentPos = 0; | |
| 3511 | ||
| 3512 | node.params = this.toAssignableList(params, true); | |
| 3513 | this.parseFunctionBody(node, true, false, forInit); | |
| 3514 | ||
| 3515 | this.yieldPos = oldYieldPos; | |
| 3516 | this.awaitPos = oldAwaitPos; | |
| 3517 | this.awaitIdentPos = oldAwaitIdentPos; | |
| 3518 | return this.finishNode(node, "ArrowFunctionExpression") | |
| 3519 | }; | |
| 3520 | ||
| 3521 | // Parse function body and check parameters. | |
| 3522 | ||
| 3523 | pp$5.parseFunctionBody = function(node, isArrowFunction, isMethod, forInit) { | |
| 3524 | var isExpression = isArrowFunction && this.type !== types$1.braceL; | |
| 3525 | var oldStrict = this.strict, useStrict = false; | |
| 3526 | ||
| 3527 | if (isExpression) { | |
| 3528 | node.body = this.parseMaybeAssign(forInit); | |
| 3529 | node.expression = true; | |
| 3530 | this.checkParams(node, false); | |
| 3531 | } else { | |
| 3532 | var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); | |
| 3533 | if (!oldStrict || nonSimple) { | |
| 3534 | useStrict = this.strictDirective(this.end); | |
| 3535 | // If this is a strict mode function, verify that argument names | |
| 3536 | // are not repeated, and it does not try to bind the words `eval` | |
| 3537 | // or `arguments`. | |
| 3538 | if (useStrict && nonSimple) | |
| 3539 | { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } | |
| 3540 | } | |
| 3541 | // Start a new scope with regard to labels and the `inFunction` | |
| 3542 | // flag (restore them to their old value afterwards). | |
| 3543 | var oldLabels = this.labels; | |
| 3544 | this.labels = []; | |
| 3545 | if (useStrict) { this.strict = true; } | |
| 3546 | ||
| 3547 | // Add the params to varDeclaredNames to ensure that an error is thrown | |
| 3548 | // if a let/const declaration in the function clashes with one of the params. | |
| 3549 | this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); | |
| 3550 | // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' | |
| 3551 | if (this.strict && node.id) { this.checkLValSimple(node.id, BIND_OUTSIDE); } | |
| 3552 | node.body = this.parseBlock(false, undefined, useStrict && !oldStrict); | |
| 3553 | node.expression = false; | |
| 3554 | this.adaptDirectivePrologue(node.body.body); | |
| 3555 | this.labels = oldLabels; | |
| 3556 | } | |
| 3557 | this.exitScope(); | |
| 3558 | }; | |
| 3559 | ||
| 3560 | pp$5.isSimpleParamList = function(params) { | |
| 3561 | for (var i = 0, list = params; i < list.length; i += 1) | |
| 3562 | { | |
| 3563 | var param = list[i]; | |
| 3564 | ||
| 3565 | if (param.type !== "Identifier") { return false | |
| 3566 | } } | |
| 3567 | return true | |
| 3568 | }; | |
| 3569 | ||
| 3570 | // Checks function params for various disallowed patterns such as using "eval" | |
| 3571 | // or "arguments" and duplicate parameters. | |
| 3572 | ||
| 3573 | pp$5.checkParams = function(node, allowDuplicates) { | |
| 3574 | var nameHash = Object.create(null); | |
| 3575 | for (var i = 0, list = node.params; i < list.length; i += 1) | |
| 3576 | { | |
| 3577 | var param = list[i]; | |
| 3578 | ||
| 3579 | this.checkLValInnerPattern(param, BIND_VAR, allowDuplicates ? null : nameHash); | |
| 3580 | } | |
| 3581 | }; | |
| 3582 | ||
| 3583 | // Parses a comma-separated list of expressions, and returns them as | |
| 3584 | // an array. `close` is the token type that ends the list, and | |
| 3585 | // `allowEmpty` can be turned on to allow subsequent commas with | |
| 3586 | // nothing in between them to be parsed as `null` (which is needed | |
| 3587 | // for array literals). | |
| 3588 | ||
| 3589 | pp$5.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { | |
| 3590 | var elts = [], first = true; | |
| 3591 | while (!this.eat(close)) { | |
| 3592 | if (!first) { | |
| 3593 | this.expect(types$1.comma); | |
| 3594 | if (allowTrailingComma && this.afterTrailingComma(close)) { break } | |
| 3595 | } else { first = false; } | |
| 3596 | ||
| 3597 | var elt = (void 0); | |
| 3598 | if (allowEmpty && this.type === types$1.comma) | |
| 3599 | { elt = null; } | |
| 3600 | else if (this.type === types$1.ellipsis) { | |
| 3601 | elt = this.parseSpread(refDestructuringErrors); | |
| 3602 | if (refDestructuringErrors && this.type === types$1.comma && refDestructuringErrors.trailingComma < 0) | |
| 3603 | { refDestructuringErrors.trailingComma = this.start; } | |
| 3604 | } else { | |
| 3605 | elt = this.parseMaybeAssign(false, refDestructuringErrors); | |
| 3606 | } | |
| 3607 | elts.push(elt); | |
| 3608 | } | |
| 3609 | return elts | |
| 3610 | }; | |
| 3611 | ||
| 3612 | pp$5.checkUnreserved = function(ref) { | |
| 3613 | var start = ref.start; | |
| 3614 | var end = ref.end; | |
| 3615 | var name = ref.name; | |
| 3616 | ||
| 3617 | if (this.inGenerator && name === "yield") | |
| 3618 | { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); } | |
| 3619 | if (this.inAsync && name === "await") | |
| 3620 | { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); } | |
| 3621 | if (!(this.currentThisScope().flags & SCOPE_VAR) && name === "arguments") | |
| 3622 | { this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer"); } | |
| 3623 | if (this.inClassStaticBlock && (name === "arguments" || name === "await")) | |
| 3624 | { this.raise(start, ("Cannot use " + name + " in class static initialization block")); } | |
| 3625 | if (this.keywords.test(name)) | |
| 3626 | { this.raise(start, ("Unexpected keyword '" + name + "'")); } | |
| 3627 | if (this.options.ecmaVersion < 6 && | |
| 3628 | this.input.slice(start, end).indexOf("\\") !== -1) { return } | |
| 3629 | var re = this.strict ? this.reservedWordsStrict : this.reservedWords; | |
| 3630 | if (re.test(name)) { | |
| 3631 | if (!this.inAsync && name === "await") | |
| 3632 | { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); } | |
| 3633 | this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); | |
| 3634 | } | |
| 3635 | }; | |
| 3636 | ||
| 3637 | // Parse the next token as an identifier. If `liberal` is true (used | |
| 3638 | // when parsing properties), it will also convert keywords into | |
| 3639 | // identifiers. | |
| 3640 | ||
| 3641 | pp$5.parseIdent = function(liberal) { | |
| 3642 | var node = this.parseIdentNode(); | |
| 3643 | this.next(!!liberal); | |
| 3644 | this.finishNode(node, "Identifier"); | |
| 3645 | if (!liberal) { | |
| 3646 | this.checkUnreserved(node); | |
| 3647 | if (node.name === "await" && !this.awaitIdentPos) | |
| 3648 | { this.awaitIdentPos = node.start; } | |
| 3649 | } | |
| 3650 | return node | |
| 3651 | }; | |
| 3652 | ||
| 3653 | pp$5.parseIdentNode = function() { | |
| 3654 | var node = this.startNode(); | |
| 3655 | if (this.type === types$1.name) { | |
| 3656 | node.name = this.value; | |
| 3657 | } else if (this.type.keyword) { | |
| 3658 | node.name = this.type.keyword; | |
| 3659 | ||
| 3660 | // To fix https://github.com/acornjs/acorn/issues/575 | |
| 3661 | // `class` and `function` keywords push new context into this.context. | |
| 3662 | // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. | |
| 3663 | // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword | |
| 3664 | if ((node.name === "class" || node.name === "function") && | |
| 3665 | (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { | |
| 3666 | this.context.pop(); | |
| 3667 | } | |
| 3668 | this.type = types$1.name; | |
| 3669 | } else { | |
| 3670 | this.unexpected(); | |
| 3671 | } | |
| 3672 | return node | |
| 3673 | }; | |
| 3674 | ||
| 3675 | pp$5.parsePrivateIdent = function() { | |
| 3676 | var node = this.startNode(); | |
| 3677 | if (this.type === types$1.privateId) { | |
| 3678 | node.name = this.value; | |
| 3679 | } else { | |
| 3680 | this.unexpected(); | |
| 3681 | } | |
| 3682 | this.next(); | |
| 3683 | this.finishNode(node, "PrivateIdentifier"); | |
| 3684 | ||
| 3685 | // For validating existence | |
| 3686 | if (this.options.checkPrivateFields) { | |
| 3687 | if (this.privateNameStack.length === 0) { | |
| 3688 | this.raise(node.start, ("Private field '#" + (node.name) + "' must be declared in an enclosing class")); | |
| 3689 | } else { | |
| 3690 | this.privateNameStack[this.privateNameStack.length - 1].used.push(node); | |
| 3691 | } | |
| 3692 | } | |
| 3693 | ||
| 3694 | return node | |
| 3695 | }; | |
| 3696 | ||
| 3697 | // Parses yield expression inside generator. | |
| 3698 | ||
| 3699 | pp$5.parseYield = function(forInit) { | |
| 3700 | if (!this.yieldPos) { this.yieldPos = this.start; } | |
| 3701 | ||
| 3702 | var node = this.startNode(); | |
| 3703 | this.next(); | |
| 3704 | if (this.type === types$1.semi || this.canInsertSemicolon() || (this.type !== types$1.star && !this.type.startsExpr)) { | |
| 3705 | node.delegate = false; | |
| 3706 | node.argument = null; | |
| 3707 | } else { | |
| 3708 | node.delegate = this.eat(types$1.star); | |
| 3709 | node.argument = this.parseMaybeAssign(forInit); | |
| 3710 | } | |
| 3711 | return this.finishNode(node, "YieldExpression") | |
| 3712 | }; | |
| 3713 | ||
| 3714 | pp$5.parseAwait = function(forInit) { | |
| 3715 | if (!this.awaitPos) { this.awaitPos = this.start; } | |
| 3716 | ||
| 3717 | var node = this.startNode(); | |
| 3718 | this.next(); | |
| 3719 | node.argument = this.parseMaybeUnary(null, true, false, forInit); | |
| 3720 | return this.finishNode(node, "AwaitExpression") | |
| 3721 | }; | |
| 3722 | ||
| 3723 | var pp$4 = Parser.prototype; | |
| 3724 | ||
| 3725 | // This function is used to raise exceptions on parse errors. It | |
| 3726 | // takes an offset integer (into the current `input`) to indicate | |
| 3727 | // the location of the error, attaches the position to the end | |
| 3728 | // of the error message, and then raises a `SyntaxError` with that | |
| 3729 | // message. | |
| 3730 | ||
| 3731 | pp$4.raise = function(pos, message) { | |
| 3732 | var loc = getLineInfo(this.input, pos); | |
| 3733 | message += " (" + loc.line + ":" + loc.column + ")"; | |
| 3734 | if (this.sourceFile) { | |
| 3735 | message += " in " + this.sourceFile; | |
| 3736 | } | |
| 3737 | var err = new SyntaxError(message); | |
| 3738 | err.pos = pos; err.loc = loc; err.raisedAt = this.pos; | |
| 3739 | throw err | |
| 3740 | }; | |
| 3741 | ||
| 3742 | pp$4.raiseRecoverable = pp$4.raise; | |
| 3743 | ||
| 3744 | pp$4.curPosition = function() { | |
| 3745 | if (this.options.locations) { | |
| 3746 | return new Position(this.curLine, this.pos - this.lineStart) | |
| 3747 | } | |
| 3748 | }; | |
| 3749 | ||
| 3750 | var pp$3 = Parser.prototype; | |
| 3751 | ||
| 3752 | var Scope = function Scope(flags) { | |
| 3753 | this.flags = flags; | |
| 3754 | // A list of var-declared names in the current lexical scope | |
| 3755 | this.var = []; | |
| 3756 | // A list of lexically-declared names in the current lexical scope | |
| 3757 | this.lexical = []; | |
| 3758 | // A list of lexically-declared FunctionDeclaration names in the current lexical scope | |
| 3759 | this.functions = []; | |
| 3760 | }; | |
| 3761 | ||
| 3762 | // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. | |
| 3763 | ||
| 3764 | pp$3.enterScope = function(flags) { | |
| 3765 | this.scopeStack.push(new Scope(flags)); | |
| 3766 | }; | |
| 3767 | ||
| 3768 | pp$3.exitScope = function() { | |
| 3769 | this.scopeStack.pop(); | |
| 3770 | }; | |
| 3771 | ||
| 3772 | // The spec says: | |
| 3773 | // > At the top level of a function, or script, function declarations are | |
| 3774 | // > treated like var declarations rather than like lexical declarations. | |
| 3775 | pp$3.treatFunctionsAsVarInScope = function(scope) { | |
| 3776 | return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP) | |
| 3777 | }; | |
| 3778 | ||
| 3779 | pp$3.declareName = function(name, bindingType, pos) { | |
| 3780 | var redeclared = false; | |
| 3781 | if (bindingType === BIND_LEXICAL) { | |
| 3782 | var scope = this.currentScope(); | |
| 3783 | redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1; | |
| 3784 | scope.lexical.push(name); | |
| 3785 | if (this.inModule && (scope.flags & SCOPE_TOP)) | |
| 3786 | { delete this.undefinedExports[name]; } | |
| 3787 | } else if (bindingType === BIND_SIMPLE_CATCH) { | |
| 3788 | var scope$1 = this.currentScope(); | |
| 3789 | scope$1.lexical.push(name); | |
| 3790 | } else if (bindingType === BIND_FUNCTION) { | |
| 3791 | var scope$2 = this.currentScope(); | |
| 3792 | if (this.treatFunctionsAsVar) | |
| 3793 | { redeclared = scope$2.lexical.indexOf(name) > -1; } | |
| 3794 | else | |
| 3795 | { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; } | |
| 3796 | scope$2.functions.push(name); | |
| 3797 | } else { | |
| 3798 | for (var i = this.scopeStack.length - 1; i >= 0; --i) { | |
| 3799 | var scope$3 = this.scopeStack[i]; | |
| 3800 | if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) || | |
| 3801 | !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) { | |
| 3802 | redeclared = true; | |
| 3803 | break | |
| 3804 | } | |
| 3805 | scope$3.var.push(name); | |
| 3806 | if (this.inModule && (scope$3.flags & SCOPE_TOP)) | |
| 3807 | { delete this.undefinedExports[name]; } | |
| 3808 | if (scope$3.flags & SCOPE_VAR) { break } | |
| 3809 | } | |
| 3810 | } | |
| 3811 | if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); } | |
| 3812 | }; | |
| 3813 | ||
| 3814 | pp$3.checkLocalExport = function(id) { | |
| 3815 | // scope.functions must be empty as Module code is always strict. | |
| 3816 | if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && | |
| 3817 | this.scopeStack[0].var.indexOf(id.name) === -1) { | |
| 3818 | this.undefinedExports[id.name] = id; | |
| 3819 | } | |
| 3820 | }; | |
| 3821 | ||
| 3822 | pp$3.currentScope = function() { | |
| 3823 | return this.scopeStack[this.scopeStack.length - 1] | |
| 3824 | }; | |
| 3825 | ||
| 3826 | pp$3.currentVarScope = function() { | |
| 3827 | for (var i = this.scopeStack.length - 1;; i--) { | |
| 3828 | var scope = this.scopeStack[i]; | |
| 3829 | if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK)) { return scope } | |
| 3830 | } | |
| 3831 | }; | |
| 3832 | ||
| 3833 | // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. | |
| 3834 | pp$3.currentThisScope = function() { | |
| 3835 | for (var i = this.scopeStack.length - 1;; i--) { | |
| 3836 | var scope = this.scopeStack[i]; | |
| 3837 | if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK) && | |
| 3838 | !(scope.flags & SCOPE_ARROW)) { return scope } | |
| 3839 | } | |
| 3840 | }; | |
| 3841 | ||
| 3842 | var Node = function Node(parser, pos, loc) { | |
| 3843 | this.type = ""; | |
| 3844 | this.start = pos; | |
| 3845 | this.end = 0; | |
| 3846 | if (parser.options.locations) | |
| 3847 | { this.loc = new SourceLocation(parser, loc); } | |
| 3848 | if (parser.options.directSourceFile) | |
| 3849 | { this.sourceFile = parser.options.directSourceFile; } | |
| 3850 | if (parser.options.ranges) | |
| 3851 | { this.range = [pos, 0]; } | |
| 3852 | }; | |
| 3853 | ||
| 3854 | // Start an AST node, attaching a start offset. | |
| 3855 | ||
| 3856 | var pp$2 = Parser.prototype; | |
| 3857 | ||
| 3858 | pp$2.startNode = function() { | |
| 3859 | return new Node(this, this.start, this.startLoc) | |
| 3860 | }; | |
| 3861 | ||
| 3862 | pp$2.startNodeAt = function(pos, loc) { | |
| 3863 | return new Node(this, pos, loc) | |
| 3864 | }; | |
| 3865 | ||
| 3866 | // Finish an AST node, adding `type` and `end` properties. | |
| 3867 | ||
| 3868 | function finishNodeAt(node, type, pos, loc) { | |
| 3869 | node.type = type; | |
| 3870 | node.end = pos; | |
| 3871 | if (this.options.locations) | |
| 3872 | { node.loc.end = loc; } | |
| 3873 | if (this.options.ranges) | |
| 3874 | { node.range[1] = pos; } | |
| 3875 | return node | |
| 3876 | } | |
| 3877 | ||
| 3878 | pp$2.finishNode = function(node, type) { | |
| 3879 | return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) | |
| 3880 | }; | |
| 3881 | ||
| 3882 | // Finish node at given position | |
| 3883 | ||
| 3884 | pp$2.finishNodeAt = function(node, type, pos, loc) { | |
| 3885 | return finishNodeAt.call(this, node, type, pos, loc) | |
| 3886 | }; | |
| 3887 | ||
| 3888 | pp$2.copyNode = function(node) { | |
| 3889 | var newNode = new Node(this, node.start, this.startLoc); | |
| 3890 | for (var prop in node) { newNode[prop] = node[prop]; } | |
| 3891 | return newNode | |
| 3892 | }; | |
| 3893 | ||
| 3894 | // This file was generated by "bin/generate-unicode-script-values.js". Do not modify manually! | |
| 3895 | var scriptValuesAddedInUnicode = "Gara Garay Gukh Gurung_Khema Hrkt Katakana_Or_Hiragana Kawi Kirat_Rai Krai Nag_Mundari Nagm Ol_Onal Onao Sunu Sunuwar Todhri Todr Tulu_Tigalari Tutg Unknown Zzzz"; | |
| 3896 | ||
| 3897 | // This file contains Unicode properties extracted from the ECMAScript specification. | |
| 3898 | // The lists are extracted like so: | |
| 3899 | // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText) | |
| 3900 | ||
| 3901 | // #table-binary-unicode-properties | |
| 3902 | var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"; | |
| 3903 | var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"; | |
| 3904 | var ecma11BinaryProperties = ecma10BinaryProperties; | |
| 3905 | var ecma12BinaryProperties = ecma11BinaryProperties + " EBase EComp EMod EPres ExtPict"; | |
| 3906 | var ecma13BinaryProperties = ecma12BinaryProperties; | |
| 3907 | var ecma14BinaryProperties = ecma13BinaryProperties; | |
| 3908 | ||
| 3909 | var unicodeBinaryProperties = { | |
| 3910 | 9: ecma9BinaryProperties, | |
| 3911 | 10: ecma10BinaryProperties, | |
| 3912 | 11: ecma11BinaryProperties, | |
| 3913 | 12: ecma12BinaryProperties, | |
| 3914 | 13: ecma13BinaryProperties, | |
| 3915 | 14: ecma14BinaryProperties | |
| 3916 | }; | |
| 3917 | ||
| 3918 | // #table-binary-unicode-properties-of-strings | |
| 3919 | var ecma14BinaryPropertiesOfStrings = "Basic_Emoji Emoji_Keycap_Sequence RGI_Emoji_Modifier_Sequence RGI_Emoji_Flag_Sequence RGI_Emoji_Tag_Sequence RGI_Emoji_ZWJ_Sequence RGI_Emoji"; | |
| 3920 | ||
| 3921 | var unicodeBinaryPropertiesOfStrings = { | |
| 3922 | 9: "", | |
| 3923 | 10: "", | |
| 3924 | 11: "", | |
| 3925 | 12: "", | |
| 3926 | 13: "", | |
| 3927 | 14: ecma14BinaryPropertiesOfStrings | |
| 3928 | }; | |
| 3929 | ||
| 3930 | // #table-unicode-general-category-values | |
| 3931 | var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; | |
| 3932 | ||
| 3933 | // #table-unicode-script-values | |
| 3934 | var ecma9ScriptValues = "Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"; | |
| 3935 | var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"; | |
| 3936 | var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"; | |
| 3937 | var ecma12ScriptValues = ecma11ScriptValues + " Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi"; | |
| 3938 | var ecma13ScriptValues = ecma12ScriptValues + " Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith"; | |
| 3939 | var ecma14ScriptValues = ecma13ScriptValues + " " + scriptValuesAddedInUnicode; | |
| 3940 | ||
| 3941 | var unicodeScriptValues = { | |
| 3942 | 9: ecma9ScriptValues, | |
| 3943 | 10: ecma10ScriptValues, | |
| 3944 | 11: ecma11ScriptValues, | |
| 3945 | 12: ecma12ScriptValues, | |
| 3946 | 13: ecma13ScriptValues, | |
| 3947 | 14: ecma14ScriptValues | |
| 3948 | }; | |
| 3949 | ||
| 3950 | var data = {}; | |
| 3951 | function buildUnicodeData(ecmaVersion) { | |
| 3952 | var d = data[ecmaVersion] = { | |
| 3953 | binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues), | |
| 3954 | binaryOfStrings: wordsRegexp(unicodeBinaryPropertiesOfStrings[ecmaVersion]), | |
| 3955 | nonBinary: { | |
| 3956 | General_Category: wordsRegexp(unicodeGeneralCategoryValues), | |
| 3957 | Script: wordsRegexp(unicodeScriptValues[ecmaVersion]) | |
| 3958 | } | |
| 3959 | }; | |
| 3960 | d.nonBinary.Script_Extensions = d.nonBinary.Script; | |
| 3961 | ||
| 3962 | d.nonBinary.gc = d.nonBinary.General_Category; | |
| 3963 | d.nonBinary.sc = d.nonBinary.Script; | |
| 3964 | d.nonBinary.scx = d.nonBinary.Script_Extensions; | |
| 3965 | } | |
| 3966 | ||
| 3967 | for (var i = 0, list = [9, 10, 11, 12, 13, 14]; i < list.length; i += 1) { | |
| 3968 | var ecmaVersion = list[i]; | |
| 3969 | ||
| 3970 | buildUnicodeData(ecmaVersion); | |
| 3971 | } | |
| 3972 | ||
| 3973 | var pp$1 = Parser.prototype; | |
| 3974 | ||
| 3975 | // Track disjunction structure to determine whether a duplicate | |
| 3976 | // capture group name is allowed because it is in a separate branch. | |
| 3977 | var BranchID = function BranchID(parent, base) { | |
| 3978 | // Parent disjunction branch | |
| 3979 | this.parent = parent; | |
| 3980 | // Identifies this set of sibling branches | |
| 3981 | this.base = base || this; | |
| 3982 | }; | |
| 3983 | ||
| 3984 | BranchID.prototype.separatedFrom = function separatedFrom (alt) { | |
| 3985 | // A branch is separate from another branch if they or any of | |
| 3986 | // their parents are siblings in a given disjunction | |
| 3987 | for (var self = this; self; self = self.parent) { | |
| 3988 | for (var other = alt; other; other = other.parent) { | |
| 3989 | if (self.base === other.base && self !== other) { return true } | |
| 3990 | } | |
| 3991 | } | |
| 3992 | return false | |
| 3993 | }; | |
| 3994 | ||
| 3995 | BranchID.prototype.sibling = function sibling () { | |
| 3996 | return new BranchID(this.parent, this.base) | |
| 3997 | }; | |
| 3998 | ||
| 3999 | var RegExpValidationState = function RegExpValidationState(parser) { | |
| 4000 | this.parser = parser; | |
| 4001 | this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "") + (parser.options.ecmaVersion >= 13 ? "d" : "") + (parser.options.ecmaVersion >= 15 ? "v" : ""); | |
| 4002 | this.unicodeProperties = data[parser.options.ecmaVersion >= 14 ? 14 : parser.options.ecmaVersion]; | |
| 4003 | this.source = ""; | |
| 4004 | this.flags = ""; | |
| 4005 | this.start = 0; | |
| 4006 | this.switchU = false; | |
| 4007 | this.switchV = false; | |
| 4008 | this.switchN = false; | |
| 4009 | this.pos = 0; | |
| 4010 | this.lastIntValue = 0; | |
| 4011 | this.lastStringValue = ""; | |
| 4012 | this.lastAssertionIsQuantifiable = false; | |
| 4013 | this.numCapturingParens = 0; | |
| 4014 | this.maxBackReference = 0; | |
| 4015 | this.groupNames = Object.create(null); | |
| 4016 | this.backReferenceNames = []; | |
| 4017 | this.branchID = null; | |
| 4018 | }; | |
| 4019 | ||
| 4020 | RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { | |
| 4021 | var unicodeSets = flags.indexOf("v") !== -1; | |
| 4022 | var unicode = flags.indexOf("u") !== -1; | |
| 4023 | this.start = start | 0; | |
| 4024 | this.source = pattern + ""; | |
| 4025 | this.flags = flags; | |
| 4026 | if (unicodeSets && this.parser.options.ecmaVersion >= 15) { | |
| 4027 | this.switchU = true; | |
| 4028 | this.switchV = true; | |
| 4029 | this.switchN = true; | |
| 4030 | } else { | |
| 4031 | this.switchU = unicode && this.parser.options.ecmaVersion >= 6; | |
| 4032 | this.switchV = false; | |
| 4033 | this.switchN = unicode && this.parser.options.ecmaVersion >= 9; | |
| 4034 | } | |
| 4035 | }; | |
| 4036 | ||
| 4037 | RegExpValidationState.prototype.raise = function raise (message) { | |
| 4038 | this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); | |
| 4039 | }; | |
| 4040 | ||
| 4041 | // If u flag is given, this returns the code point at the index (it combines a surrogate pair). | |
| 4042 | // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). | |
| 4043 | RegExpValidationState.prototype.at = function at (i, forceU) { | |
| 4044 | if ( forceU === void 0 ) forceU = false; | |
| 4045 | ||
| 4046 | var s = this.source; | |
| 4047 | var l = s.length; | |
| 4048 | if (i >= l) { | |
| 4049 | return -1 | |
| 4050 | } | |
| 4051 | var c = s.charCodeAt(i); | |
| 4052 | if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { | |
| 4053 | return c | |
| 4054 | } | |
| 4055 | var next = s.charCodeAt(i + 1); | |
| 4056 | return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c | |
| 4057 | }; | |
| 4058 | ||
| 4059 | RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) { | |
| 4060 | if ( forceU === void 0 ) forceU = false; | |
| 4061 | ||
| 4062 | var s = this.source; | |
| 4063 | var l = s.length; | |
| 4064 | if (i >= l) { | |
| 4065 | return l | |
| 4066 | } | |
| 4067 | var c = s.charCodeAt(i), next; | |
| 4068 | if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || | |
| 4069 | (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) { | |
| 4070 | return i + 1 | |
| 4071 | } | |
| 4072 | return i + 2 | |
| 4073 | }; | |
| 4074 | ||
| 4075 | RegExpValidationState.prototype.current = function current (forceU) { | |
| 4076 | if ( forceU === void 0 ) forceU = false; | |
| 4077 | ||
| 4078 | return this.at(this.pos, forceU) | |
| 4079 | }; | |
| 4080 | ||
| 4081 | RegExpValidationState.prototype.lookahead = function lookahead (forceU) { | |
| 4082 | if ( forceU === void 0 ) forceU = false; | |
| 4083 | ||
| 4084 | return this.at(this.nextIndex(this.pos, forceU), forceU) | |
| 4085 | }; | |
| 4086 | ||
| 4087 | RegExpValidationState.prototype.advance = function advance (forceU) { | |
| 4088 | if ( forceU === void 0 ) forceU = false; | |
| 4089 | ||
| 4090 | this.pos = this.nextIndex(this.pos, forceU); | |
| 4091 | }; | |
| 4092 | ||
| 4093 | RegExpValidationState.prototype.eat = function eat (ch, forceU) { | |
| 4094 | if ( forceU === void 0 ) forceU = false; | |
| 4095 | ||
| 4096 | if (this.current(forceU) === ch) { | |
| 4097 | this.advance(forceU); | |
| 4098 | return true | |
| 4099 | } | |
| 4100 | return false | |
| 4101 | }; | |
| 4102 | ||
| 4103 | RegExpValidationState.prototype.eatChars = function eatChars (chs, forceU) { | |
| 4104 | if ( forceU === void 0 ) forceU = false; | |
| 4105 | ||
| 4106 | var pos = this.pos; | |
| 4107 | for (var i = 0, list = chs; i < list.length; i += 1) { | |
| 4108 | var ch = list[i]; | |
| 4109 | ||
| 4110 | var current = this.at(pos, forceU); | |
| 4111 | if (current === -1 || current !== ch) { | |
| 4112 | return false | |
| 4113 | } | |
| 4114 | pos = this.nextIndex(pos, forceU); | |
| 4115 | } | |
| 4116 | this.pos = pos; | |
| 4117 | return true | |
| 4118 | }; | |
| 4119 | ||
| 4120 | /** | |
| 4121 | * Validate the flags part of a given RegExpLiteral. | |
| 4122 | * | |
| 4123 | * @param {RegExpValidationState} state The state to validate RegExp. | |
| 4124 | * @returns {void} | |
| 4125 | */ | |
| 4126 | pp$1.validateRegExpFlags = function(state) { | |
| 4127 | var validFlags = state.validFlags; | |
| 4128 | var flags = state.flags; | |
| 4129 | ||
| 4130 | var u = false; | |
| 4131 | var v = false; | |
| 4132 | ||
| 4133 | for (var i = 0; i < flags.length; i++) { | |
| 4134 | var flag = flags.charAt(i); | |
| 4135 | if (validFlags.indexOf(flag) === -1) { | |
| 4136 | this.raise(state.start, "Invalid regular expression flag"); | |
| 4137 | } | |
| 4138 | if (flags.indexOf(flag, i + 1) > -1) { | |
| 4139 | this.raise(state.start, "Duplicate regular expression flag"); | |
| 4140 | } | |
| 4141 | if (flag === "u") { u = true; } | |
| 4142 | if (flag === "v") { v = true; } | |
| 4143 | } | |
| 4144 | if (this.options.ecmaVersion >= 15 && u && v) { | |
| 4145 | this.raise(state.start, "Invalid regular expression flag"); | |
| 4146 | } | |
| 4147 | }; | |
| 4148 | ||
| 4149 | function hasProp(obj) { | |
| 4150 | for (var _ in obj) { return true } | |
| 4151 | return false | |
| 4152 | } | |
| 4153 | ||
| 4154 | /** | |
| 4155 | * Validate the pattern part of a given RegExpLiteral. | |
| 4156 | * | |
| 4157 | * @param {RegExpValidationState} state The state to validate RegExp. | |
| 4158 | * @returns {void} | |
| 4159 | */ | |
| 4160 | pp$1.validateRegExpPattern = function(state) { | |
| 4161 | this.regexp_pattern(state); | |
| 4162 | ||
| 4163 | // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of | |
| 4164 | // parsing contains a |GroupName|, reparse with the goal symbol | |
| 4165 | // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* | |
| 4166 | // exception if _P_ did not conform to the grammar, if any elements of _P_ | |
| 4167 | // were not matched by the parse, or if any Early Error conditions exist. | |
| 4168 | if (!state.switchN && this.options.ecmaVersion >= 9 && hasProp(state.groupNames)) { | |
| 4169 | state.switchN = true; | |
| 4170 | this.regexp_pattern(state); | |
| 4171 | } | |
| 4172 | }; | |
| 4173 | ||
| 4174 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern | |
| 4175 | pp$1.regexp_pattern = function(state) { | |
| 4176 | state.pos = 0; | |
| 4177 | state.lastIntValue = 0; | |
| 4178 | state.lastStringValue = ""; | |
| 4179 | state.lastAssertionIsQuantifiable = false; | |
| 4180 | state.numCapturingParens = 0; | |
| 4181 | state.maxBackReference = 0; | |
| 4182 | state.groupNames = Object.create(null); | |
| 4183 | state.backReferenceNames.length = 0; | |
| 4184 | state.branchID = null; | |
| 4185 | ||
| 4186 | this.regexp_disjunction(state); | |
| 4187 | ||
| 4188 | if (state.pos !== state.source.length) { | |
| 4189 | // Make the same messages as V8. | |
| 4190 | if (state.eat(0x29 /* ) */)) { | |
| 4191 | state.raise("Unmatched ')'"); | |
| 4192 | } | |
| 4193 | if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) { | |
| 4194 | state.raise("Lone quantifier brackets"); | |
| 4195 | } | |
| 4196 | } | |
| 4197 | if (state.maxBackReference > state.numCapturingParens) { | |
| 4198 | state.raise("Invalid escape"); | |
| 4199 | } | |
| 4200 | for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { | |
| 4201 | var name = list[i]; | |
| 4202 | ||
| 4203 | if (!state.groupNames[name]) { | |
| 4204 | state.raise("Invalid named capture referenced"); | |
| 4205 | } | |
| 4206 | } | |
| 4207 | }; | |
| 4208 | ||
| 4209 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction | |
| 4210 | pp$1.regexp_disjunction = function(state) { | |
| 4211 | var trackDisjunction = this.options.ecmaVersion >= 16; | |
| 4212 | if (trackDisjunction) { state.branchID = new BranchID(state.branchID, null); } | |
| 4213 | this.regexp_alternative(state); | |
| 4214 | while (state.eat(0x7C /* | */)) { | |
| 4215 | if (trackDisjunction) { state.branchID = state.branchID.sibling(); } | |
| 4216 | this.regexp_alternative(state); | |
| 4217 | } | |
| 4218 | if (trackDisjunction) { state.branchID = state.branchID.parent; } | |
| 4219 | ||
| 4220 | // Make the same message as V8. | |
| 4221 | if (this.regexp_eatQuantifier(state, true)) { | |
| 4222 | state.raise("Nothing to repeat"); | |
| 4223 | } | |
| 4224 | if (state.eat(0x7B /* { */)) { | |
| 4225 | state.raise("Lone quantifier brackets"); | |
| 4226 | } | |
| 4227 | }; | |
| 4228 | ||
| 4229 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative | |
| 4230 | pp$1.regexp_alternative = function(state) { | |
| 4231 | while (state.pos < state.source.length && this.regexp_eatTerm(state)) {} | |
| 4232 | }; | |
| 4233 | ||
| 4234 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term | |
| 4235 | pp$1.regexp_eatTerm = function(state) { | |
| 4236 | if (this.regexp_eatAssertion(state)) { | |
| 4237 | // Handle `QuantifiableAssertion Quantifier` alternative. | |
| 4238 | // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion | |
| 4239 | // is a QuantifiableAssertion. | |
| 4240 | if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { | |
| 4241 | // Make the same message as V8. | |
| 4242 | if (state.switchU) { | |
| 4243 | state.raise("Invalid quantifier"); | |
| 4244 | } | |
| 4245 | } | |
| 4246 | return true | |
| 4247 | } | |
| 4248 | ||
| 4249 | if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { | |
| 4250 | this.regexp_eatQuantifier(state); | |
| 4251 | return true | |
| 4252 | } | |
| 4253 | ||
| 4254 | return false | |
| 4255 | }; | |
| 4256 | ||
| 4257 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion | |
| 4258 | pp$1.regexp_eatAssertion = function(state) { | |
| 4259 | var start = state.pos; | |
| 4260 | state.lastAssertionIsQuantifiable = false; | |
| 4261 | ||
| 4262 | // ^, $ | |
| 4263 | if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { | |
| 4264 | return true | |
| 4265 | } | |
| 4266 | ||
| 4267 | // \b \B | |
| 4268 | if (state.eat(0x5C /* \ */)) { | |
| 4269 | if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { | |
| 4270 | return true | |
| 4271 | } | |
| 4272 | state.pos = start; | |
| 4273 | } | |
| 4274 | ||
| 4275 | // Lookahead / Lookbehind | |
| 4276 | if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { | |
| 4277 | var lookbehind = false; | |
| 4278 | if (this.options.ecmaVersion >= 9) { | |
| 4279 | lookbehind = state.eat(0x3C /* < */); | |
| 4280 | } | |
| 4281 | if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { | |
| 4282 | this.regexp_disjunction(state); | |
| 4283 | if (!state.eat(0x29 /* ) */)) { | |
| 4284 | state.raise("Unterminated group"); | |
| 4285 | } | |
| 4286 | state.lastAssertionIsQuantifiable = !lookbehind; | |
| 4287 | return true | |
| 4288 | } | |
| 4289 | } | |
| 4290 | ||
| 4291 | state.pos = start; | |
| 4292 | return false | |
| 4293 | }; | |
| 4294 | ||
| 4295 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier | |
| 4296 | pp$1.regexp_eatQuantifier = function(state, noError) { | |
| 4297 | if ( noError === void 0 ) noError = false; | |
| 4298 | ||
| 4299 | if (this.regexp_eatQuantifierPrefix(state, noError)) { | |
| 4300 | state.eat(0x3F /* ? */); | |
| 4301 | return true | |
| 4302 | } | |
| 4303 | return false | |
| 4304 | }; | |
| 4305 | ||
| 4306 | // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix | |
| 4307 | pp$1.regexp_eatQuantifierPrefix = function(state, noError) { | |
| 4308 | return ( | |
| 4309 | state.eat(0x2A /* * */) || | |
| 4310 | state.eat(0x2B /* + */) || | |
| 4311 | state.eat(0x3F /* ? */) || | |
| 4312 | this.regexp_eatBracedQuantifier(state, noError) | |
| 4313 | ) | |
| 4314 | }; | |
| 4315 | pp$1.regexp_eatBracedQuantifier = function(state, noError) { | |
| 4316 | var start = state.pos; | |
| 4317 | if (state.eat(0x7B /* { */)) { | |
| 4318 | var min = 0, max = -1; | |
| 4319 | if (this.regexp_eatDecimalDigits(state)) { | |
| 4320 | min = state.lastIntValue; | |
| 4321 | if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { | |
| 4322 | max = state.lastIntValue; | |
| 4323 | } | |
| 4324 | if (state.eat(0x7D /* } */)) { | |
| 4325 | // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term | |
| 4326 | if (max !== -1 && max < min && !noError) { | |
| 4327 | state.raise("numbers out of order in {} quantifier"); | |
| 4328 | } | |
| 4329 | return true | |
| 4330 | } | |
| 4331 | } | |
| 4332 | if (state.switchU && !noError) { | |
| 4333 | state.raise("Incomplete quantifier"); | |
| 4334 | } | |
| 4335 | state.pos = start; | |
| 4336 | } | |
| 4337 | return false | |
| 4338 | }; | |
| 4339 | ||
| 4340 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom | |
| 4341 | pp$1.regexp_eatAtom = function(state) { | |
| 4342 | return ( | |
| 4343 | this.regexp_eatPatternCharacters(state) || | |
| 4344 | state.eat(0x2E /* . */) || | |
| 4345 | this.regexp_eatReverseSolidusAtomEscape(state) || | |
| 4346 | this.regexp_eatCharacterClass(state) || | |
| 4347 | this.regexp_eatUncapturingGroup(state) || | |
| 4348 | this.regexp_eatCapturingGroup(state) | |
| 4349 | ) | |
| 4350 | }; | |
| 4351 | pp$1.regexp_eatReverseSolidusAtomEscape = function(state) { | |
| 4352 | var start = state.pos; | |
| 4353 | if (state.eat(0x5C /* \ */)) { | |
| 4354 | if (this.regexp_eatAtomEscape(state)) { | |
| 4355 | return true | |
| 4356 | } | |
| 4357 | state.pos = start; | |
| 4358 | } | |
| 4359 | return false | |
| 4360 | }; | |
| 4361 | pp$1.regexp_eatUncapturingGroup = function(state) { | |
| 4362 | var start = state.pos; | |
| 4363 | if (state.eat(0x28 /* ( */)) { | |
| 4364 | if (state.eat(0x3F /* ? */)) { | |
| 4365 | if (this.options.ecmaVersion >= 16) { | |
| 4366 | var addModifiers = this.regexp_eatModifiers(state); | |
| 4367 | var hasHyphen = state.eat(0x2D /* - */); | |
| 4368 | if (addModifiers || hasHyphen) { | |
| 4369 | for (var i = 0; i < addModifiers.length; i++) { | |
| 4370 | var modifier = addModifiers.charAt(i); | |
| 4371 | if (addModifiers.indexOf(modifier, i + 1) > -1) { | |
| 4372 | state.raise("Duplicate regular expression modifiers"); | |
| 4373 | } | |
| 4374 | } | |
| 4375 | if (hasHyphen) { | |
| 4376 | var removeModifiers = this.regexp_eatModifiers(state); | |
| 4377 | if (!addModifiers && !removeModifiers && state.current() === 0x3A /* : */) { | |
| 4378 | state.raise("Invalid regular expression modifiers"); | |
| 4379 | } | |
| 4380 | for (var i$1 = 0; i$1 < removeModifiers.length; i$1++) { | |
| 4381 | var modifier$1 = removeModifiers.charAt(i$1); | |
| 4382 | if ( | |
| 4383 | removeModifiers.indexOf(modifier$1, i$1 + 1) > -1 || | |
| 4384 | addModifiers.indexOf(modifier$1) > -1 | |
| 4385 | ) { | |
| 4386 | state.raise("Duplicate regular expression modifiers"); | |
| 4387 | } | |
| 4388 | } | |
| 4389 | } | |
| 4390 | } | |
| 4391 | } | |
| 4392 | if (state.eat(0x3A /* : */)) { | |
| 4393 | this.regexp_disjunction(state); | |
| 4394 | if (state.eat(0x29 /* ) */)) { | |
| 4395 | return true | |
| 4396 | } | |
| 4397 | state.raise("Unterminated group"); | |
| 4398 | } | |
| 4399 | } | |
| 4400 | state.pos = start; | |
| 4401 | } | |
| 4402 | return false | |
| 4403 | }; | |
| 4404 | pp$1.regexp_eatCapturingGroup = function(state) { | |
| 4405 | if (state.eat(0x28 /* ( */)) { | |
| 4406 | if (this.options.ecmaVersion >= 9) { | |
| 4407 | this.regexp_groupSpecifier(state); | |
| 4408 | } else if (state.current() === 0x3F /* ? */) { | |
| 4409 | state.raise("Invalid group"); | |
| 4410 | } | |
| 4411 | this.regexp_disjunction(state); | |
| 4412 | if (state.eat(0x29 /* ) */)) { | |
| 4413 | state.numCapturingParens += 1; | |
| 4414 | return true | |
| 4415 | } | |
| 4416 | state.raise("Unterminated group"); | |
| 4417 | } | |
| 4418 | return false | |
| 4419 | }; | |
| 4420 | // RegularExpressionModifiers :: | |
| 4421 | // [empty] | |
| 4422 | // RegularExpressionModifiers RegularExpressionModifier | |
| 4423 | pp$1.regexp_eatModifiers = function(state) { | |
| 4424 | var modifiers = ""; | |
| 4425 | var ch = 0; | |
| 4426 | while ((ch = state.current()) !== -1 && isRegularExpressionModifier(ch)) { | |
| 4427 | modifiers += codePointToString(ch); | |
| 4428 | state.advance(); | |
| 4429 | } | |
| 4430 | return modifiers | |
| 4431 | }; | |
| 4432 | // RegularExpressionModifier :: one of | |
| 4433 | // `i` `m` `s` | |
| 4434 | function isRegularExpressionModifier(ch) { | |
| 4435 | return ch === 0x69 /* i */ || ch === 0x6d /* m */ || ch === 0x73 /* s */ | |
| 4436 | } | |
| 4437 | ||
| 4438 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom | |
| 4439 | pp$1.regexp_eatExtendedAtom = function(state) { | |
| 4440 | return ( | |
| 4441 | state.eat(0x2E /* . */) || | |
| 4442 | this.regexp_eatReverseSolidusAtomEscape(state) || | |
| 4443 | this.regexp_eatCharacterClass(state) || | |
| 4444 | this.regexp_eatUncapturingGroup(state) || | |
| 4445 | this.regexp_eatCapturingGroup(state) || | |
| 4446 | this.regexp_eatInvalidBracedQuantifier(state) || | |
| 4447 | this.regexp_eatExtendedPatternCharacter(state) | |
| 4448 | ) | |
| 4449 | }; | |
| 4450 | ||
| 4451 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier | |
| 4452 | pp$1.regexp_eatInvalidBracedQuantifier = function(state) { | |
| 4453 | if (this.regexp_eatBracedQuantifier(state, true)) { | |
| 4454 | state.raise("Nothing to repeat"); | |
| 4455 | } | |
| 4456 | return false | |
| 4457 | }; | |
| 4458 | ||
| 4459 | // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter | |
| 4460 | pp$1.regexp_eatSyntaxCharacter = function(state) { | |
| 4461 | var ch = state.current(); | |
| 4462 | if (isSyntaxCharacter(ch)) { | |
| 4463 | state.lastIntValue = ch; | |
| 4464 | state.advance(); | |
| 4465 | return true | |
| 4466 | } | |
| 4467 | return false | |
| 4468 | }; | |
| 4469 | function isSyntaxCharacter(ch) { | |
| 4470 | return ( | |
| 4471 | ch === 0x24 /* $ */ || | |
| 4472 | ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || | |
| 4473 | ch === 0x2E /* . */ || | |
| 4474 | ch === 0x3F /* ? */ || | |
| 4475 | ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || | |
| 4476 | ch >= 0x7B /* { */ && ch <= 0x7D /* } */ | |
| 4477 | ) | |
| 4478 | } | |
| 4479 | ||
| 4480 | // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter | |
| 4481 | // But eat eager. | |
| 4482 | pp$1.regexp_eatPatternCharacters = function(state) { | |
| 4483 | var start = state.pos; | |
| 4484 | var ch = 0; | |
| 4485 | while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { | |
| 4486 | state.advance(); | |
| 4487 | } | |
| 4488 | return state.pos !== start | |
| 4489 | }; | |
| 4490 | ||
| 4491 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter | |
| 4492 | pp$1.regexp_eatExtendedPatternCharacter = function(state) { | |
| 4493 | var ch = state.current(); | |
| 4494 | if ( | |
| 4495 | ch !== -1 && | |
| 4496 | ch !== 0x24 /* $ */ && | |
| 4497 | !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && | |
| 4498 | ch !== 0x2E /* . */ && | |
| 4499 | ch !== 0x3F /* ? */ && | |
| 4500 | ch !== 0x5B /* [ */ && | |
| 4501 | ch !== 0x5E /* ^ */ && | |
| 4502 | ch !== 0x7C /* | */ | |
| 4503 | ) { | |
| 4504 | state.advance(); | |
| 4505 | return true | |
| 4506 | } | |
| 4507 | return false | |
| 4508 | }; | |
| 4509 | ||
| 4510 | // GroupSpecifier :: | |
| 4511 | // [empty] | |
| 4512 | // `?` GroupName | |
| 4513 | pp$1.regexp_groupSpecifier = function(state) { | |
| 4514 | if (state.eat(0x3F /* ? */)) { | |
| 4515 | if (!this.regexp_eatGroupName(state)) { state.raise("Invalid group"); } | |
| 4516 | var trackDisjunction = this.options.ecmaVersion >= 16; | |
| 4517 | var known = state.groupNames[state.lastStringValue]; | |
| 4518 | if (known) { | |
| 4519 | if (trackDisjunction) { | |
| 4520 | for (var i = 0, list = known; i < list.length; i += 1) { | |
| 4521 | var altID = list[i]; | |
| 4522 | ||
| 4523 | if (!altID.separatedFrom(state.branchID)) | |
| 4524 | { state.raise("Duplicate capture group name"); } | |
| 4525 | } | |
| 4526 | } else { | |
| 4527 | state.raise("Duplicate capture group name"); | |
| 4528 | } | |
| 4529 | } | |
| 4530 | if (trackDisjunction) { | |
| 4531 | (known || (state.groupNames[state.lastStringValue] = [])).push(state.branchID); | |
| 4532 | } else { | |
| 4533 | state.groupNames[state.lastStringValue] = true; | |
| 4534 | } | |
| 4535 | } | |
| 4536 | }; | |
| 4537 | ||
| 4538 | // GroupName :: | |
| 4539 | // `<` RegExpIdentifierName `>` | |
| 4540 | // Note: this updates `state.lastStringValue` property with the eaten name. | |
| 4541 | pp$1.regexp_eatGroupName = function(state) { | |
| 4542 | state.lastStringValue = ""; | |
| 4543 | if (state.eat(0x3C /* < */)) { | |
| 4544 | if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { | |
| 4545 | return true | |
| 4546 | } | |
| 4547 | state.raise("Invalid capture group name"); | |
| 4548 | } | |
| 4549 | return false | |
| 4550 | }; | |
| 4551 | ||
| 4552 | // RegExpIdentifierName :: | |
| 4553 | // RegExpIdentifierStart | |
| 4554 | // RegExpIdentifierName RegExpIdentifierPart | |
| 4555 | // Note: this updates `state.lastStringValue` property with the eaten name. | |
| 4556 | pp$1.regexp_eatRegExpIdentifierName = function(state) { | |
| 4557 | state.lastStringValue = ""; | |
| 4558 | if (this.regexp_eatRegExpIdentifierStart(state)) { | |
| 4559 | state.lastStringValue += codePointToString(state.lastIntValue); | |
| 4560 | while (this.regexp_eatRegExpIdentifierPart(state)) { | |
| 4561 | state.lastStringValue += codePointToString(state.lastIntValue); | |
| 4562 | } | |
| 4563 | return true | |
| 4564 | } | |
| 4565 | return false | |
| 4566 | }; | |
| 4567 | ||
| 4568 | // RegExpIdentifierStart :: | |
| 4569 | // UnicodeIDStart | |
| 4570 | // `$` | |
| 4571 | // `_` | |
| 4572 | // `\` RegExpUnicodeEscapeSequence[+U] | |
| 4573 | pp$1.regexp_eatRegExpIdentifierStart = function(state) { | |
| 4574 | var start = state.pos; | |
| 4575 | var forceU = this.options.ecmaVersion >= 11; | |
| 4576 | var ch = state.current(forceU); | |
| 4577 | state.advance(forceU); | |
| 4578 | ||
| 4579 | if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { | |
| 4580 | ch = state.lastIntValue; | |
| 4581 | } | |
| 4582 | if (isRegExpIdentifierStart(ch)) { | |
| 4583 | state.lastIntValue = ch; | |
| 4584 | return true | |
| 4585 | } | |
| 4586 | ||
| 4587 | state.pos = start; | |
| 4588 | return false | |
| 4589 | }; | |
| 4590 | function isRegExpIdentifierStart(ch) { | |
| 4591 | return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ | |
| 4592 | } | |
| 4593 | ||
| 4594 | // RegExpIdentifierPart :: | |
| 4595 | // UnicodeIDContinue | |
| 4596 | // `$` | |
| 4597 | // `_` | |
| 4598 | // `\` RegExpUnicodeEscapeSequence[+U] | |
| 4599 | // <ZWNJ> | |
| 4600 | // <ZWJ> | |
| 4601 | pp$1.regexp_eatRegExpIdentifierPart = function(state) { | |
| 4602 | var start = state.pos; | |
| 4603 | var forceU = this.options.ecmaVersion >= 11; | |
| 4604 | var ch = state.current(forceU); | |
| 4605 | state.advance(forceU); | |
| 4606 | ||
| 4607 | if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { | |
| 4608 | ch = state.lastIntValue; | |
| 4609 | } | |
| 4610 | if (isRegExpIdentifierPart(ch)) { | |
| 4611 | state.lastIntValue = ch; | |
| 4612 | return true | |
| 4613 | } | |
| 4614 | ||
| 4615 | state.pos = start; | |
| 4616 | return false | |
| 4617 | }; | |
| 4618 | function isRegExpIdentifierPart(ch) { | |
| 4619 | return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */ | |
| 4620 | } | |
| 4621 | ||
| 4622 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape | |
| 4623 | pp$1.regexp_eatAtomEscape = function(state) { | |
| 4624 | if ( | |
| 4625 | this.regexp_eatBackReference(state) || | |
| 4626 | this.regexp_eatCharacterClassEscape(state) || | |
| 4627 | this.regexp_eatCharacterEscape(state) || | |
| 4628 | (state.switchN && this.regexp_eatKGroupName(state)) | |
| 4629 | ) { | |
| 4630 | return true | |
| 4631 | } | |
| 4632 | if (state.switchU) { | |
| 4633 | // Make the same message as V8. | |
| 4634 | if (state.current() === 0x63 /* c */) { | |
| 4635 | state.raise("Invalid unicode escape"); | |
| 4636 | } | |
| 4637 | state.raise("Invalid escape"); | |
| 4638 | } | |
| 4639 | return false | |
| 4640 | }; | |
| 4641 | pp$1.regexp_eatBackReference = function(state) { | |
| 4642 | var start = state.pos; | |
| 4643 | if (this.regexp_eatDecimalEscape(state)) { | |
| 4644 | var n = state.lastIntValue; | |
| 4645 | if (state.switchU) { | |
| 4646 | // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape | |
| 4647 | if (n > state.maxBackReference) { | |
| 4648 | state.maxBackReference = n; | |
| 4649 | } | |
| 4650 | return true | |
| 4651 | } | |
| 4652 | if (n <= state.numCapturingParens) { | |
| 4653 | return true | |
| 4654 | } | |
| 4655 | state.pos = start; | |
| 4656 | } | |
| 4657 | return false | |
| 4658 | }; | |
| 4659 | pp$1.regexp_eatKGroupName = function(state) { | |
| 4660 | if (state.eat(0x6B /* k */)) { | |
| 4661 | if (this.regexp_eatGroupName(state)) { | |
| 4662 | state.backReferenceNames.push(state.lastStringValue); | |
| 4663 | return true | |
| 4664 | } | |
| 4665 | state.raise("Invalid named reference"); | |
| 4666 | } | |
| 4667 | return false | |
| 4668 | }; | |
| 4669 | ||
| 4670 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape | |
| 4671 | pp$1.regexp_eatCharacterEscape = function(state) { | |
| 4672 | return ( | |
| 4673 | this.regexp_eatControlEscape(state) || | |
| 4674 | this.regexp_eatCControlLetter(state) || | |
| 4675 | this.regexp_eatZero(state) || | |
| 4676 | this.regexp_eatHexEscapeSequence(state) || | |
| 4677 | this.regexp_eatRegExpUnicodeEscapeSequence(state, false) || | |
| 4678 | (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || | |
| 4679 | this.regexp_eatIdentityEscape(state) | |
| 4680 | ) | |
| 4681 | }; | |
| 4682 | pp$1.regexp_eatCControlLetter = function(state) { | |
| 4683 | var start = state.pos; | |
| 4684 | if (state.eat(0x63 /* c */)) { | |
| 4685 | if (this.regexp_eatControlLetter(state)) { | |
| 4686 | return true | |
| 4687 | } | |
| 4688 | state.pos = start; | |
| 4689 | } | |
| 4690 | return false | |
| 4691 | }; | |
| 4692 | pp$1.regexp_eatZero = function(state) { | |
| 4693 | if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { | |
| 4694 | state.lastIntValue = 0; | |
| 4695 | state.advance(); | |
| 4696 | return true | |
| 4697 | } | |
| 4698 | return false | |
| 4699 | }; | |
| 4700 | ||
| 4701 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape | |
| 4702 | pp$1.regexp_eatControlEscape = function(state) { | |
| 4703 | var ch = state.current(); | |
| 4704 | if (ch === 0x74 /* t */) { | |
| 4705 | state.lastIntValue = 0x09; /* \t */ | |
| 4706 | state.advance(); | |
| 4707 | return true | |
| 4708 | } | |
| 4709 | if (ch === 0x6E /* n */) { | |
| 4710 | state.lastIntValue = 0x0A; /* \n */ | |
| 4711 | state.advance(); | |
| 4712 | return true | |
| 4713 | } | |
| 4714 | if (ch === 0x76 /* v */) { | |
| 4715 | state.lastIntValue = 0x0B; /* \v */ | |
| 4716 | state.advance(); | |
| 4717 | return true | |
| 4718 | } | |
| 4719 | if (ch === 0x66 /* f */) { | |
| 4720 | state.lastIntValue = 0x0C; /* \f */ | |
| 4721 | state.advance(); | |
| 4722 | return true | |
| 4723 | } | |
| 4724 | if (ch === 0x72 /* r */) { | |
| 4725 | state.lastIntValue = 0x0D; /* \r */ | |
| 4726 | state.advance(); | |
| 4727 | return true | |
| 4728 | } | |
| 4729 | return false | |
| 4730 | }; | |
| 4731 | ||
| 4732 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter | |
| 4733 | pp$1.regexp_eatControlLetter = function(state) { | |
| 4734 | var ch = state.current(); | |
| 4735 | if (isControlLetter(ch)) { | |
| 4736 | state.lastIntValue = ch % 0x20; | |
| 4737 | state.advance(); | |
| 4738 | return true | |
| 4739 | } | |
| 4740 | return false | |
| 4741 | }; | |
| 4742 | function isControlLetter(ch) { | |
| 4743 | return ( | |
| 4744 | (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || | |
| 4745 | (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) | |
| 4746 | ) | |
| 4747 | } | |
| 4748 | ||
| 4749 | // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence | |
| 4750 | pp$1.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) { | |
| 4751 | if ( forceU === void 0 ) forceU = false; | |
| 4752 | ||
| 4753 | var start = state.pos; | |
| 4754 | var switchU = forceU || state.switchU; | |
| 4755 | ||
| 4756 | if (state.eat(0x75 /* u */)) { | |
| 4757 | if (this.regexp_eatFixedHexDigits(state, 4)) { | |
| 4758 | var lead = state.lastIntValue; | |
| 4759 | if (switchU && lead >= 0xD800 && lead <= 0xDBFF) { | |
| 4760 | var leadSurrogateEnd = state.pos; | |
| 4761 | if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { | |
| 4762 | var trail = state.lastIntValue; | |
| 4763 | if (trail >= 0xDC00 && trail <= 0xDFFF) { | |
| 4764 | state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; | |
| 4765 | return true | |
| 4766 | } | |
| 4767 | } | |
| 4768 | state.pos = leadSurrogateEnd; | |
| 4769 | state.lastIntValue = lead; | |
| 4770 | } | |
| 4771 | return true | |
| 4772 | } | |
| 4773 | if ( | |
| 4774 | switchU && | |
| 4775 | state.eat(0x7B /* { */) && | |
| 4776 | this.regexp_eatHexDigits(state) && | |
| 4777 | state.eat(0x7D /* } */) && | |
| 4778 | isValidUnicode(state.lastIntValue) | |
| 4779 | ) { | |
| 4780 | return true | |
| 4781 | } | |
| 4782 | if (switchU) { | |
| 4783 | state.raise("Invalid unicode escape"); | |
| 4784 | } | |
| 4785 | state.pos = start; | |
| 4786 | } | |
| 4787 | ||
| 4788 | return false | |
| 4789 | }; | |
| 4790 | function isValidUnicode(ch) { | |
| 4791 | return ch >= 0 && ch <= 0x10FFFF | |
| 4792 | } | |
| 4793 | ||
| 4794 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape | |
| 4795 | pp$1.regexp_eatIdentityEscape = function(state) { | |
| 4796 | if (state.switchU) { | |
| 4797 | if (this.regexp_eatSyntaxCharacter(state)) { | |
| 4798 | return true | |
| 4799 | } | |
| 4800 | if (state.eat(0x2F /* / */)) { | |
| 4801 | state.lastIntValue = 0x2F; /* / */ | |
| 4802 | return true | |
| 4803 | } | |
| 4804 | return false | |
| 4805 | } | |
| 4806 | ||
| 4807 | var ch = state.current(); | |
| 4808 | if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { | |
| 4809 | state.lastIntValue = ch; | |
| 4810 | state.advance(); | |
| 4811 | return true | |
| 4812 | } | |
| 4813 | ||
| 4814 | return false | |
| 4815 | }; | |
| 4816 | ||
| 4817 | // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape | |
| 4818 | pp$1.regexp_eatDecimalEscape = function(state) { | |
| 4819 | state.lastIntValue = 0; | |
| 4820 | var ch = state.current(); | |
| 4821 | if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { | |
| 4822 | do { | |
| 4823 | state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); | |
| 4824 | state.advance(); | |
| 4825 | } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) | |
| 4826 | return true | |
| 4827 | } | |
| 4828 | return false | |
| 4829 | }; | |
| 4830 | ||
| 4831 | // Return values used by character set parsing methods, needed to | |
| 4832 | // forbid negation of sets that can match strings. | |
| 4833 | var CharSetNone = 0; // Nothing parsed | |
| 4834 | var CharSetOk = 1; // Construct parsed, cannot contain strings | |
| 4835 | var CharSetString = 2; // Construct parsed, can contain strings | |
| 4836 | ||
| 4837 | // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape | |
| 4838 | pp$1.regexp_eatCharacterClassEscape = function(state) { | |
| 4839 | var ch = state.current(); | |
| 4840 | ||
| 4841 | if (isCharacterClassEscape(ch)) { | |
| 4842 | state.lastIntValue = -1; | |
| 4843 | state.advance(); | |
| 4844 | return CharSetOk | |
| 4845 | } | |
| 4846 | ||
| 4847 | var negate = false; | |
| 4848 | if ( | |
| 4849 | state.switchU && | |
| 4850 | this.options.ecmaVersion >= 9 && | |
| 4851 | ((negate = ch === 0x50 /* P */) || ch === 0x70 /* p */) | |
| 4852 | ) { | |
| 4853 | state.lastIntValue = -1; | |
| 4854 | state.advance(); | |
| 4855 | var result; | |
| 4856 | if ( | |
| 4857 | state.eat(0x7B /* { */) && | |
| 4858 | (result = this.regexp_eatUnicodePropertyValueExpression(state)) && | |
| 4859 | state.eat(0x7D /* } */) | |
| 4860 | ) { | |
| 4861 | if (negate && result === CharSetString) { state.raise("Invalid property name"); } | |
| 4862 | return result | |
| 4863 | } | |
| 4864 | state.raise("Invalid property name"); | |
| 4865 | } | |
| 4866 | ||
| 4867 | return CharSetNone | |
| 4868 | }; | |
| 4869 | ||
| 4870 | function isCharacterClassEscape(ch) { | |
| 4871 | return ( | |
| 4872 | ch === 0x64 /* d */ || | |
| 4873 | ch === 0x44 /* D */ || | |
| 4874 | ch === 0x73 /* s */ || | |
| 4875 | ch === 0x53 /* S */ || | |
| 4876 | ch === 0x77 /* w */ || | |
| 4877 | ch === 0x57 /* W */ | |
| 4878 | ) | |
| 4879 | } | |
| 4880 | ||
| 4881 | // UnicodePropertyValueExpression :: | |
| 4882 | // UnicodePropertyName `=` UnicodePropertyValue | |
| 4883 | // LoneUnicodePropertyNameOrValue | |
| 4884 | pp$1.regexp_eatUnicodePropertyValueExpression = function(state) { | |
| 4885 | var start = state.pos; | |
| 4886 | ||
| 4887 | // UnicodePropertyName `=` UnicodePropertyValue | |
| 4888 | if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { | |
| 4889 | var name = state.lastStringValue; | |
| 4890 | if (this.regexp_eatUnicodePropertyValue(state)) { | |
| 4891 | var value = state.lastStringValue; | |
| 4892 | this.regexp_validateUnicodePropertyNameAndValue(state, name, value); | |
| 4893 | return CharSetOk | |
| 4894 | } | |
| 4895 | } | |
| 4896 | state.pos = start; | |
| 4897 | ||
| 4898 | // LoneUnicodePropertyNameOrValue | |
| 4899 | if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { | |
| 4900 | var nameOrValue = state.lastStringValue; | |
| 4901 | return this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue) | |
| 4902 | } | |
| 4903 | return CharSetNone | |
| 4904 | }; | |
| 4905 | ||
| 4906 | pp$1.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { | |
| 4907 | if (!hasOwn(state.unicodeProperties.nonBinary, name)) | |
| 4908 | { state.raise("Invalid property name"); } | |
| 4909 | if (!state.unicodeProperties.nonBinary[name].test(value)) | |
| 4910 | { state.raise("Invalid property value"); } | |
| 4911 | }; | |
| 4912 | ||
| 4913 | pp$1.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { | |
| 4914 | if (state.unicodeProperties.binary.test(nameOrValue)) { return CharSetOk } | |
| 4915 | if (state.switchV && state.unicodeProperties.binaryOfStrings.test(nameOrValue)) { return CharSetString } | |
| 4916 | state.raise("Invalid property name"); | |
| 4917 | }; | |
| 4918 | ||
| 4919 | // UnicodePropertyName :: | |
| 4920 | // UnicodePropertyNameCharacters | |
| 4921 | pp$1.regexp_eatUnicodePropertyName = function(state) { | |
| 4922 | var ch = 0; | |
| 4923 | state.lastStringValue = ""; | |
| 4924 | while (isUnicodePropertyNameCharacter(ch = state.current())) { | |
| 4925 | state.lastStringValue += codePointToString(ch); | |
| 4926 | state.advance(); | |
| 4927 | } | |
| 4928 | return state.lastStringValue !== "" | |
| 4929 | }; | |
| 4930 | ||
| 4931 | function isUnicodePropertyNameCharacter(ch) { | |
| 4932 | return isControlLetter(ch) || ch === 0x5F /* _ */ | |
| 4933 | } | |
| 4934 | ||
| 4935 | // UnicodePropertyValue :: | |
| 4936 | // UnicodePropertyValueCharacters | |
| 4937 | pp$1.regexp_eatUnicodePropertyValue = function(state) { | |
| 4938 | var ch = 0; | |
| 4939 | state.lastStringValue = ""; | |
| 4940 | while (isUnicodePropertyValueCharacter(ch = state.current())) { | |
| 4941 | state.lastStringValue += codePointToString(ch); | |
| 4942 | state.advance(); | |
| 4943 | } | |
| 4944 | return state.lastStringValue !== "" | |
| 4945 | }; | |
| 4946 | function isUnicodePropertyValueCharacter(ch) { | |
| 4947 | return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) | |
| 4948 | } | |
| 4949 | ||
| 4950 | // LoneUnicodePropertyNameOrValue :: | |
| 4951 | // UnicodePropertyValueCharacters | |
| 4952 | pp$1.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { | |
| 4953 | return this.regexp_eatUnicodePropertyValue(state) | |
| 4954 | }; | |
| 4955 | ||
| 4956 | // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass | |
| 4957 | pp$1.regexp_eatCharacterClass = function(state) { | |
| 4958 | if (state.eat(0x5B /* [ */)) { | |
| 4959 | var negate = state.eat(0x5E /* ^ */); | |
| 4960 | var result = this.regexp_classContents(state); | |
| 4961 | if (!state.eat(0x5D /* ] */)) | |
| 4962 | { state.raise("Unterminated character class"); } | |
| 4963 | if (negate && result === CharSetString) | |
| 4964 | { state.raise("Negated character class may contain strings"); } | |
| 4965 | return true | |
| 4966 | } | |
| 4967 | return false | |
| 4968 | }; | |
| 4969 | ||
| 4970 | // https://tc39.es/ecma262/#prod-ClassContents | |
| 4971 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges | |
| 4972 | pp$1.regexp_classContents = function(state) { | |
| 4973 | if (state.current() === 0x5D /* ] */) { return CharSetOk } | |
| 4974 | if (state.switchV) { return this.regexp_classSetExpression(state) } | |
| 4975 | this.regexp_nonEmptyClassRanges(state); | |
| 4976 | return CharSetOk | |
| 4977 | }; | |
| 4978 | ||
| 4979 | // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges | |
| 4980 | // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash | |
| 4981 | pp$1.regexp_nonEmptyClassRanges = function(state) { | |
| 4982 | while (this.regexp_eatClassAtom(state)) { | |
| 4983 | var left = state.lastIntValue; | |
| 4984 | if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { | |
| 4985 | var right = state.lastIntValue; | |
| 4986 | if (state.switchU && (left === -1 || right === -1)) { | |
| 4987 | state.raise("Invalid character class"); | |
| 4988 | } | |
| 4989 | if (left !== -1 && right !== -1 && left > right) { | |
| 4990 | state.raise("Range out of order in character class"); | |
| 4991 | } | |
| 4992 | } | |
| 4993 | } | |
| 4994 | }; | |
| 4995 | ||
| 4996 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom | |
| 4997 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash | |
| 4998 | pp$1.regexp_eatClassAtom = function(state) { | |
| 4999 | var start = state.pos; | |
| 5000 | ||
| 5001 | if (state.eat(0x5C /* \ */)) { | |
| 5002 | if (this.regexp_eatClassEscape(state)) { | |
| 5003 | return true | |
| 5004 | } | |
| 5005 | if (state.switchU) { | |
| 5006 | // Make the same message as V8. | |
| 5007 | var ch$1 = state.current(); | |
| 5008 | if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) { | |
| 5009 | state.raise("Invalid class escape"); | |
| 5010 | } | |
| 5011 | state.raise("Invalid escape"); | |
| 5012 | } | |
| 5013 | state.pos = start; | |
| 5014 | } | |
| 5015 | ||
| 5016 | var ch = state.current(); | |
| 5017 | if (ch !== 0x5D /* ] */) { | |
| 5018 | state.lastIntValue = ch; | |
| 5019 | state.advance(); | |
| 5020 | return true | |
| 5021 | } | |
| 5022 | ||
| 5023 | return false | |
| 5024 | }; | |
| 5025 | ||
| 5026 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape | |
| 5027 | pp$1.regexp_eatClassEscape = function(state) { | |
| 5028 | var start = state.pos; | |
| 5029 | ||
| 5030 | if (state.eat(0x62 /* b */)) { | |
| 5031 | state.lastIntValue = 0x08; /* <BS> */ | |
| 5032 | return true | |
| 5033 | } | |
| 5034 | ||
| 5035 | if (state.switchU && state.eat(0x2D /* - */)) { | |
| 5036 | state.lastIntValue = 0x2D; /* - */ | |
| 5037 | return true | |
| 5038 | } | |
| 5039 | ||
| 5040 | if (!state.switchU && state.eat(0x63 /* c */)) { | |
| 5041 | if (this.regexp_eatClassControlLetter(state)) { | |
| 5042 | return true | |
| 5043 | } | |
| 5044 | state.pos = start; | |
| 5045 | } | |
| 5046 | ||
| 5047 | return ( | |
| 5048 | this.regexp_eatCharacterClassEscape(state) || | |
| 5049 | this.regexp_eatCharacterEscape(state) | |
| 5050 | ) | |
| 5051 | }; | |
| 5052 | ||
| 5053 | // https://tc39.es/ecma262/#prod-ClassSetExpression | |
| 5054 | // https://tc39.es/ecma262/#prod-ClassUnion | |
| 5055 | // https://tc39.es/ecma262/#prod-ClassIntersection | |
| 5056 | // https://tc39.es/ecma262/#prod-ClassSubtraction | |
| 5057 | pp$1.regexp_classSetExpression = function(state) { | |
| 5058 | var result = CharSetOk, subResult; | |
| 5059 | if (this.regexp_eatClassSetRange(state)) ; else if (subResult = this.regexp_eatClassSetOperand(state)) { | |
| 5060 | if (subResult === CharSetString) { result = CharSetString; } | |
| 5061 | // https://tc39.es/ecma262/#prod-ClassIntersection | |
| 5062 | var start = state.pos; | |
| 5063 | while (state.eatChars([0x26, 0x26] /* && */)) { | |
| 5064 | if ( | |
| 5065 | state.current() !== 0x26 /* & */ && | |
| 5066 | (subResult = this.regexp_eatClassSetOperand(state)) | |
| 5067 | ) { | |
| 5068 | if (subResult !== CharSetString) { result = CharSetOk; } | |
| 5069 | continue | |
| 5070 | } | |
| 5071 | state.raise("Invalid character in character class"); | |
| 5072 | } | |
| 5073 | if (start !== state.pos) { return result } | |
| 5074 | // https://tc39.es/ecma262/#prod-ClassSubtraction | |
| 5075 | while (state.eatChars([0x2D, 0x2D] /* -- */)) { | |
| 5076 | if (this.regexp_eatClassSetOperand(state)) { continue } | |
| 5077 | state.raise("Invalid character in character class"); | |
| 5078 | } | |
| 5079 | if (start !== state.pos) { return result } | |
| 5080 | } else { | |
| 5081 | state.raise("Invalid character in character class"); | |
| 5082 | } | |
| 5083 | // https://tc39.es/ecma262/#prod-ClassUnion | |
| 5084 | for (;;) { | |
| 5085 | if (this.regexp_eatClassSetRange(state)) { continue } | |
| 5086 | subResult = this.regexp_eatClassSetOperand(state); | |
| 5087 | if (!subResult) { return result } | |
| 5088 | if (subResult === CharSetString) { result = CharSetString; } | |
| 5089 | } | |
| 5090 | }; | |
| 5091 | ||
| 5092 | // https://tc39.es/ecma262/#prod-ClassSetRange | |
| 5093 | pp$1.regexp_eatClassSetRange = function(state) { | |
| 5094 | var start = state.pos; | |
| 5095 | if (this.regexp_eatClassSetCharacter(state)) { | |
| 5096 | var left = state.lastIntValue; | |
| 5097 | if (state.eat(0x2D /* - */) && this.regexp_eatClassSetCharacter(state)) { | |
| 5098 | var right = state.lastIntValue; | |
| 5099 | if (left !== -1 && right !== -1 && left > right) { | |
| 5100 | state.raise("Range out of order in character class"); | |
| 5101 | } | |
| 5102 | return true | |
| 5103 | } | |
| 5104 | state.pos = start; | |
| 5105 | } | |
| 5106 | return false | |
| 5107 | }; | |
| 5108 | ||
| 5109 | // https://tc39.es/ecma262/#prod-ClassSetOperand | |
| 5110 | pp$1.regexp_eatClassSetOperand = function(state) { | |
| 5111 | if (this.regexp_eatClassSetCharacter(state)) { return CharSetOk } | |
| 5112 | return this.regexp_eatClassStringDisjunction(state) || this.regexp_eatNestedClass(state) | |
| 5113 | }; | |
| 5114 | ||
| 5115 | // https://tc39.es/ecma262/#prod-NestedClass | |
| 5116 | pp$1.regexp_eatNestedClass = function(state) { | |
| 5117 | var start = state.pos; | |
| 5118 | if (state.eat(0x5B /* [ */)) { | |
| 5119 | var negate = state.eat(0x5E /* ^ */); | |
| 5120 | var result = this.regexp_classContents(state); | |
| 5121 | if (state.eat(0x5D /* ] */)) { | |
| 5122 | if (negate && result === CharSetString) { | |
| 5123 | state.raise("Negated character class may contain strings"); | |
| 5124 | } | |
| 5125 | return result | |
| 5126 | } | |
| 5127 | state.pos = start; | |
| 5128 | } | |
| 5129 | if (state.eat(0x5C /* \ */)) { | |
| 5130 | var result$1 = this.regexp_eatCharacterClassEscape(state); | |
| 5131 | if (result$1) { | |
| 5132 | return result$1 | |
| 5133 | } | |
| 5134 | state.pos = start; | |
| 5135 | } | |
| 5136 | return null | |
| 5137 | }; | |
| 5138 | ||
| 5139 | // https://tc39.es/ecma262/#prod-ClassStringDisjunction | |
| 5140 | pp$1.regexp_eatClassStringDisjunction = function(state) { | |
| 5141 | var start = state.pos; | |
| 5142 | if (state.eatChars([0x5C, 0x71] /* \q */)) { | |
| 5143 | if (state.eat(0x7B /* { */)) { | |
| 5144 | var result = this.regexp_classStringDisjunctionContents(state); | |
| 5145 | if (state.eat(0x7D /* } */)) { | |
| 5146 | return result | |
| 5147 | } | |
| 5148 | } else { | |
| 5149 | // Make the same message as V8. | |
| 5150 | state.raise("Invalid escape"); | |
| 5151 | } | |
| 5152 | state.pos = start; | |
| 5153 | } | |
| 5154 | return null | |
| 5155 | }; | |
| 5156 | ||
| 5157 | // https://tc39.es/ecma262/#prod-ClassStringDisjunctionContents | |
| 5158 | pp$1.regexp_classStringDisjunctionContents = function(state) { | |
| 5159 | var result = this.regexp_classString(state); | |
| 5160 | while (state.eat(0x7C /* | */)) { | |
| 5161 | if (this.regexp_classString(state) === CharSetString) { result = CharSetString; } | |
| 5162 | } | |
| 5163 | return result | |
| 5164 | }; | |
| 5165 | ||
| 5166 | // https://tc39.es/ecma262/#prod-ClassString | |
| 5167 | // https://tc39.es/ecma262/#prod-NonEmptyClassString | |
| 5168 | pp$1.regexp_classString = function(state) { | |
| 5169 | var count = 0; | |
| 5170 | while (this.regexp_eatClassSetCharacter(state)) { count++; } | |
| 5171 | return count === 1 ? CharSetOk : CharSetString | |
| 5172 | }; | |
| 5173 | ||
| 5174 | // https://tc39.es/ecma262/#prod-ClassSetCharacter | |
| 5175 | pp$1.regexp_eatClassSetCharacter = function(state) { | |
| 5176 | var start = state.pos; | |
| 5177 | if (state.eat(0x5C /* \ */)) { | |
| 5178 | if ( | |
| 5179 | this.regexp_eatCharacterEscape(state) || | |
| 5180 | this.regexp_eatClassSetReservedPunctuator(state) | |
| 5181 | ) { | |
| 5182 | return true | |
| 5183 | } | |
| 5184 | if (state.eat(0x62 /* b */)) { | |
| 5185 | state.lastIntValue = 0x08; /* <BS> */ | |
| 5186 | return true | |
| 5187 | } | |
| 5188 | state.pos = start; | |
| 5189 | return false | |
| 5190 | } | |
| 5191 | var ch = state.current(); | |
| 5192 | if (ch < 0 || ch === state.lookahead() && isClassSetReservedDoublePunctuatorCharacter(ch)) { return false } | |
| 5193 | if (isClassSetSyntaxCharacter(ch)) { return false } | |
| 5194 | state.advance(); | |
| 5195 | state.lastIntValue = ch; | |
| 5196 | return true | |
| 5197 | }; | |
| 5198 | ||
| 5199 | // https://tc39.es/ecma262/#prod-ClassSetReservedDoublePunctuator | |
| 5200 | function isClassSetReservedDoublePunctuatorCharacter(ch) { | |
| 5201 | return ( | |
| 5202 | ch === 0x21 /* ! */ || | |
| 5203 | ch >= 0x23 /* # */ && ch <= 0x26 /* & */ || | |
| 5204 | ch >= 0x2A /* * */ && ch <= 0x2C /* , */ || | |
| 5205 | ch === 0x2E /* . */ || | |
| 5206 | ch >= 0x3A /* : */ && ch <= 0x40 /* @ */ || | |
| 5207 | ch === 0x5E /* ^ */ || | |
| 5208 | ch === 0x60 /* ` */ || | |
| 5209 | ch === 0x7E /* ~ */ | |
| 5210 | ) | |
| 5211 | } | |
| 5212 | ||
| 5213 | // https://tc39.es/ecma262/#prod-ClassSetSyntaxCharacter | |
| 5214 | function isClassSetSyntaxCharacter(ch) { | |
| 5215 | return ( | |
| 5216 | ch === 0x28 /* ( */ || | |
| 5217 | ch === 0x29 /* ) */ || | |
| 5218 | ch === 0x2D /* - */ || | |
| 5219 | ch === 0x2F /* / */ || | |
| 5220 | ch >= 0x5B /* [ */ && ch <= 0x5D /* ] */ || | |
| 5221 | ch >= 0x7B /* { */ && ch <= 0x7D /* } */ | |
| 5222 | ) | |
| 5223 | } | |
| 5224 | ||
| 5225 | // https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator | |
| 5226 | pp$1.regexp_eatClassSetReservedPunctuator = function(state) { | |
| 5227 | var ch = state.current(); | |
| 5228 | if (isClassSetReservedPunctuator(ch)) { | |
| 5229 | state.lastIntValue = ch; | |
| 5230 | state.advance(); | |
| 5231 | return true | |
| 5232 | } | |
| 5233 | return false | |
| 5234 | }; | |
| 5235 | ||
| 5236 | // https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator | |
| 5237 | function isClassSetReservedPunctuator(ch) { | |
| 5238 | return ( | |
| 5239 | ch === 0x21 /* ! */ || | |
| 5240 | ch === 0x23 /* # */ || | |
| 5241 | ch === 0x25 /* % */ || | |
| 5242 | ch === 0x26 /* & */ || | |
| 5243 | ch === 0x2C /* , */ || | |
| 5244 | ch === 0x2D /* - */ || | |
| 5245 | ch >= 0x3A /* : */ && ch <= 0x3E /* > */ || | |
| 5246 | ch === 0x40 /* @ */ || | |
| 5247 | ch === 0x60 /* ` */ || | |
| 5248 | ch === 0x7E /* ~ */ | |
| 5249 | ) | |
| 5250 | } | |
| 5251 | ||
| 5252 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter | |
| 5253 | pp$1.regexp_eatClassControlLetter = function(state) { | |
| 5254 | var ch = state.current(); | |
| 5255 | if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { | |
| 5256 | state.lastIntValue = ch % 0x20; | |
| 5257 | state.advance(); | |
| 5258 | return true | |
| 5259 | } | |
| 5260 | return false | |
| 5261 | }; | |
| 5262 | ||
| 5263 | // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence | |
| 5264 | pp$1.regexp_eatHexEscapeSequence = function(state) { | |
| 5265 | var start = state.pos; | |
| 5266 | if (state.eat(0x78 /* x */)) { | |
| 5267 | if (this.regexp_eatFixedHexDigits(state, 2)) { | |
| 5268 | return true | |
| 5269 | } | |
| 5270 | if (state.switchU) { | |
| 5271 | state.raise("Invalid escape"); | |
| 5272 | } | |
| 5273 | state.pos = start; | |
| 5274 | } | |
| 5275 | return false | |
| 5276 | }; | |
| 5277 | ||
| 5278 | // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits | |
| 5279 | pp$1.regexp_eatDecimalDigits = function(state) { | |
| 5280 | var start = state.pos; | |
| 5281 | var ch = 0; | |
| 5282 | state.lastIntValue = 0; | |
| 5283 | while (isDecimalDigit(ch = state.current())) { | |
| 5284 | state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); | |
| 5285 | state.advance(); | |
| 5286 | } | |
| 5287 | return state.pos !== start | |
| 5288 | }; | |
| 5289 | function isDecimalDigit(ch) { | |
| 5290 | return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ | |
| 5291 | } | |
| 5292 | ||
| 5293 | // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits | |
| 5294 | pp$1.regexp_eatHexDigits = function(state) { | |
| 5295 | var start = state.pos; | |
| 5296 | var ch = 0; | |
| 5297 | state.lastIntValue = 0; | |
| 5298 | while (isHexDigit(ch = state.current())) { | |
| 5299 | state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); | |
| 5300 | state.advance(); | |
| 5301 | } | |
| 5302 | return state.pos !== start | |
| 5303 | }; | |
| 5304 | function isHexDigit(ch) { | |
| 5305 | return ( | |
| 5306 | (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || | |
| 5307 | (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || | |
| 5308 | (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) | |
| 5309 | ) | |
| 5310 | } | |
| 5311 | function hexToInt(ch) { | |
| 5312 | if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { | |
| 5313 | return 10 + (ch - 0x41 /* A */) | |
| 5314 | } | |
| 5315 | if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { | |
| 5316 | return 10 + (ch - 0x61 /* a */) | |
| 5317 | } | |
| 5318 | return ch - 0x30 /* 0 */ | |
| 5319 | } | |
| 5320 | ||
| 5321 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence | |
| 5322 | // Allows only 0-377(octal) i.e. 0-255(decimal). | |
| 5323 | pp$1.regexp_eatLegacyOctalEscapeSequence = function(state) { | |
| 5324 | if (this.regexp_eatOctalDigit(state)) { | |
| 5325 | var n1 = state.lastIntValue; | |
| 5326 | if (this.regexp_eatOctalDigit(state)) { | |
| 5327 | var n2 = state.lastIntValue; | |
| 5328 | if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { | |
| 5329 | state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; | |
| 5330 | } else { | |
| 5331 | state.lastIntValue = n1 * 8 + n2; | |
| 5332 | } | |
| 5333 | } else { | |
| 5334 | state.lastIntValue = n1; | |
| 5335 | } | |
| 5336 | return true | |
| 5337 | } | |
| 5338 | return false | |
| 5339 | }; | |
| 5340 | ||
| 5341 | // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit | |
| 5342 | pp$1.regexp_eatOctalDigit = function(state) { | |
| 5343 | var ch = state.current(); | |
| 5344 | if (isOctalDigit(ch)) { | |
| 5345 | state.lastIntValue = ch - 0x30; /* 0 */ | |
| 5346 | state.advance(); | |
| 5347 | return true | |
| 5348 | } | |
| 5349 | state.lastIntValue = 0; | |
| 5350 | return false | |
| 5351 | }; | |
| 5352 | function isOctalDigit(ch) { | |
| 5353 | return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ | |
| 5354 | } | |
| 5355 | ||
| 5356 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits | |
| 5357 | // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit | |
| 5358 | // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence | |
| 5359 | pp$1.regexp_eatFixedHexDigits = function(state, length) { | |
| 5360 | var start = state.pos; | |
| 5361 | state.lastIntValue = 0; | |
| 5362 | for (var i = 0; i < length; ++i) { | |
| 5363 | var ch = state.current(); | |
| 5364 | if (!isHexDigit(ch)) { | |
| 5365 | state.pos = start; | |
| 5366 | return false | |
| 5367 | } | |
| 5368 | state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); | |
| 5369 | state.advance(); | |
| 5370 | } | |
| 5371 | return true | |
| 5372 | }; | |
| 5373 | ||
| 5374 | // Object type used to represent tokens. Note that normally, tokens | |
| 5375 | // simply exist as properties on the parser object. This is only | |
| 5376 | // used for the onToken callback and the external tokenizer. | |
| 5377 | ||
| 5378 | var Token = function Token(p) { | |
| 5379 | this.type = p.type; | |
| 5380 | this.value = p.value; | |
| 5381 | this.start = p.start; | |
| 5382 | this.end = p.end; | |
| 5383 | if (p.options.locations) | |
| 5384 | { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } | |
| 5385 | if (p.options.ranges) | |
| 5386 | { this.range = [p.start, p.end]; } | |
| 5387 | }; | |
| 5388 | ||
| 5389 | // ## Tokenizer | |
| 5390 | ||
| 5391 | var pp = Parser.prototype; | |
| 5392 | ||
| 5393 | // Move to the next token | |
| 5394 | ||
| 5395 | pp.next = function(ignoreEscapeSequenceInKeyword) { | |
| 5396 | if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc) | |
| 5397 | { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); } | |
| 5398 | if (this.options.onToken) | |
| 5399 | { this.options.onToken(new Token(this)); } | |
| 5400 | ||
| 5401 | this.lastTokEnd = this.end; | |
| 5402 | this.lastTokStart = this.start; | |
| 5403 | this.lastTokEndLoc = this.endLoc; | |
| 5404 | this.lastTokStartLoc = this.startLoc; | |
| 5405 | this.nextToken(); | |
| 5406 | }; | |
| 5407 | ||
| 5408 | pp.getToken = function() { | |
| 5409 | this.next(); | |
| 5410 | return new Token(this) | |
| 5411 | }; | |
| 5412 | ||
| 5413 | // If we're in an ES6 environment, make parsers iterable | |
| 5414 | if (typeof Symbol !== "undefined") | |
| 5415 | { pp[Symbol.iterator] = function() { | |
| 5416 | var this$1$1 = this; | |
| 5417 | ||
| 5418 | return { | |
| 5419 | next: function () { | |
| 5420 | var token = this$1$1.getToken(); | |
| 5421 | return { | |
| 5422 | done: token.type === types$1.eof, | |
| 5423 | value: token | |
| 5424 | } | |
| 5425 | } | |
| 5426 | } | |
| 5427 | }; } | |
| 5428 | ||
| 5429 | // Toggle strict mode. Re-reads the next number or string to please | |
| 5430 | // pedantic tests (`"use strict"; 010;` should fail). | |
| 5431 | ||
| 5432 | // Read a single token, updating the parser object's token-related | |
| 5433 | // properties. | |
| 5434 | ||
| 5435 | pp.nextToken = function() { | |
| 5436 | var curContext = this.curContext(); | |
| 5437 | if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } | |
| 5438 | ||
| 5439 | this.start = this.pos; | |
| 5440 | if (this.options.locations) { this.startLoc = this.curPosition(); } | |
| 5441 | if (this.pos >= this.input.length) { return this.finishToken(types$1.eof) } | |
| 5442 | ||
| 5443 | if (curContext.override) { return curContext.override(this) } | |
| 5444 | else { this.readToken(this.fullCharCodeAtPos()); } | |
| 5445 | }; | |
| 5446 | ||
| 5447 | pp.readToken = function(code) { | |
| 5448 | // Identifier or keyword. '\uXXXX' sequences are allowed in | |
| 5449 | // identifiers, so '\' also dispatches to that. | |
| 5450 | if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) | |
| 5451 | { return this.readWord() } | |
| 5452 | ||
| 5453 | return this.getTokenFromCode(code) | |
| 5454 | }; | |
| 5455 | ||
| 5456 | pp.fullCharCodeAtPos = function() { | |
| 5457 | var code = this.input.charCodeAt(this.pos); | |
| 5458 | if (code <= 0xd7ff || code >= 0xdc00) { return code } | |
| 5459 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5460 | return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00 | |
| 5461 | }; | |
| 5462 | ||
| 5463 | pp.skipBlockComment = function() { | |
| 5464 | var startLoc = this.options.onComment && this.curPosition(); | |
| 5465 | var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); | |
| 5466 | if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } | |
| 5467 | this.pos = end + 2; | |
| 5468 | if (this.options.locations) { | |
| 5469 | for (var nextBreak = (void 0), pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1;) { | |
| 5470 | ++this.curLine; | |
| 5471 | pos = this.lineStart = nextBreak; | |
| 5472 | } | |
| 5473 | } | |
| 5474 | if (this.options.onComment) | |
| 5475 | { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, | |
| 5476 | startLoc, this.curPosition()); } | |
| 5477 | }; | |
| 5478 | ||
| 5479 | pp.skipLineComment = function(startSkip) { | |
| 5480 | var start = this.pos; | |
| 5481 | var startLoc = this.options.onComment && this.curPosition(); | |
| 5482 | var ch = this.input.charCodeAt(this.pos += startSkip); | |
| 5483 | while (this.pos < this.input.length && !isNewLine(ch)) { | |
| 5484 | ch = this.input.charCodeAt(++this.pos); | |
| 5485 | } | |
| 5486 | if (this.options.onComment) | |
| 5487 | { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, | |
| 5488 | startLoc, this.curPosition()); } | |
| 5489 | }; | |
| 5490 | ||
| 5491 | // Called at the start of the parse and after every token. Skips | |
| 5492 | // whitespace and comments, and. | |
| 5493 | ||
| 5494 | pp.skipSpace = function() { | |
| 5495 | loop: while (this.pos < this.input.length) { | |
| 5496 | var ch = this.input.charCodeAt(this.pos); | |
| 5497 | switch (ch) { | |
| 5498 | case 32: case 160: // ' ' | |
| 5499 | ++this.pos; | |
| 5500 | break | |
| 5501 | case 13: | |
| 5502 | if (this.input.charCodeAt(this.pos + 1) === 10) { | |
| 5503 | ++this.pos; | |
| 5504 | } | |
| 5505 | case 10: case 8232: case 8233: | |
| 5506 | ++this.pos; | |
| 5507 | if (this.options.locations) { | |
| 5508 | ++this.curLine; | |
| 5509 | this.lineStart = this.pos; | |
| 5510 | } | |
| 5511 | break | |
| 5512 | case 47: // '/' | |
| 5513 | switch (this.input.charCodeAt(this.pos + 1)) { | |
| 5514 | case 42: // '*' | |
| 5515 | this.skipBlockComment(); | |
| 5516 | break | |
| 5517 | case 47: | |
| 5518 | this.skipLineComment(2); | |
| 5519 | break | |
| 5520 | default: | |
| 5521 | break loop | |
| 5522 | } | |
| 5523 | break | |
| 5524 | default: | |
| 5525 | if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { | |
| 5526 | ++this.pos; | |
| 5527 | } else { | |
| 5528 | break loop | |
| 5529 | } | |
| 5530 | } | |
| 5531 | } | |
| 5532 | }; | |
| 5533 | ||
| 5534 | // Called at the end of every token. Sets `end`, `val`, and | |
| 5535 | // maintains `context` and `exprAllowed`, and skips the space after | |
| 5536 | // the token, so that the next one's `start` will point at the | |
| 5537 | // right position. | |
| 5538 | ||
| 5539 | pp.finishToken = function(type, val) { | |
| 5540 | this.end = this.pos; | |
| 5541 | if (this.options.locations) { this.endLoc = this.curPosition(); } | |
| 5542 | var prevType = this.type; | |
| 5543 | this.type = type; | |
| 5544 | this.value = val; | |
| 5545 | ||
| 5546 | this.updateContext(prevType); | |
| 5547 | }; | |
| 5548 | ||
| 5549 | // ### Token reading | |
| 5550 | ||
| 5551 | // This is the function that is called to fetch the next token. It | |
| 5552 | // is somewhat obscure, because it works in character codes rather | |
| 5553 | // than characters, and because operator parsing has been inlined | |
| 5554 | // into it. | |
| 5555 | // | |
| 5556 | // All in the name of speed. | |
| 5557 | // | |
| 5558 | pp.readToken_dot = function() { | |
| 5559 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5560 | if (next >= 48 && next <= 57) { return this.readNumber(true) } | |
| 5561 | var next2 = this.input.charCodeAt(this.pos + 2); | |
| 5562 | if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' | |
| 5563 | this.pos += 3; | |
| 5564 | return this.finishToken(types$1.ellipsis) | |
| 5565 | } else { | |
| 5566 | ++this.pos; | |
| 5567 | return this.finishToken(types$1.dot) | |
| 5568 | } | |
| 5569 | }; | |
| 5570 | ||
| 5571 | pp.readToken_slash = function() { // '/' | |
| 5572 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5573 | if (this.exprAllowed) { ++this.pos; return this.readRegexp() } | |
| 5574 | if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
| 5575 | return this.finishOp(types$1.slash, 1) | |
| 5576 | }; | |
| 5577 | ||
| 5578 | pp.readToken_mult_modulo_exp = function(code) { // '%*' | |
| 5579 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5580 | var size = 1; | |
| 5581 | var tokentype = code === 42 ? types$1.star : types$1.modulo; | |
| 5582 | ||
| 5583 | // exponentiation operator ** and **= | |
| 5584 | if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { | |
| 5585 | ++size; | |
| 5586 | tokentype = types$1.starstar; | |
| 5587 | next = this.input.charCodeAt(this.pos + 2); | |
| 5588 | } | |
| 5589 | ||
| 5590 | if (next === 61) { return this.finishOp(types$1.assign, size + 1) } | |
| 5591 | return this.finishOp(tokentype, size) | |
| 5592 | }; | |
| 5593 | ||
| 5594 | pp.readToken_pipe_amp = function(code) { // '|&' | |
| 5595 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5596 | if (next === code) { | |
| 5597 | if (this.options.ecmaVersion >= 12) { | |
| 5598 | var next2 = this.input.charCodeAt(this.pos + 2); | |
| 5599 | if (next2 === 61) { return this.finishOp(types$1.assign, 3) } | |
| 5600 | } | |
| 5601 | return this.finishOp(code === 124 ? types$1.logicalOR : types$1.logicalAND, 2) | |
| 5602 | } | |
| 5603 | if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
| 5604 | return this.finishOp(code === 124 ? types$1.bitwiseOR : types$1.bitwiseAND, 1) | |
| 5605 | }; | |
| 5606 | ||
| 5607 | pp.readToken_caret = function() { // '^' | |
| 5608 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5609 | if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
| 5610 | return this.finishOp(types$1.bitwiseXOR, 1) | |
| 5611 | }; | |
| 5612 | ||
| 5613 | pp.readToken_plus_min = function(code) { // '+-' | |
| 5614 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5615 | if (next === code) { | |
| 5616 | if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && | |
| 5617 | (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { | |
| 5618 | // A `-->` line comment | |
| 5619 | this.skipLineComment(3); | |
| 5620 | this.skipSpace(); | |
| 5621 | return this.nextToken() | |
| 5622 | } | |
| 5623 | return this.finishOp(types$1.incDec, 2) | |
| 5624 | } | |
| 5625 | if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
| 5626 | return this.finishOp(types$1.plusMin, 1) | |
| 5627 | }; | |
| 5628 | ||
| 5629 | pp.readToken_lt_gt = function(code) { // '<>' | |
| 5630 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5631 | var size = 1; | |
| 5632 | if (next === code) { | |
| 5633 | size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; | |
| 5634 | if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types$1.assign, size + 1) } | |
| 5635 | return this.finishOp(types$1.bitShift, size) | |
| 5636 | } | |
| 5637 | if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && | |
| 5638 | this.input.charCodeAt(this.pos + 3) === 45) { | |
| 5639 | // `<!--`, an XML-style comment that should be interpreted as a line comment | |
| 5640 | this.skipLineComment(4); | |
| 5641 | this.skipSpace(); | |
| 5642 | return this.nextToken() | |
| 5643 | } | |
| 5644 | if (next === 61) { size = 2; } | |
| 5645 | return this.finishOp(types$1.relational, size) | |
| 5646 | }; | |
| 5647 | ||
| 5648 | pp.readToken_eq_excl = function(code) { // '=!' | |
| 5649 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5650 | if (next === 61) { return this.finishOp(types$1.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) } | |
| 5651 | if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>' | |
| 5652 | this.pos += 2; | |
| 5653 | return this.finishToken(types$1.arrow) | |
| 5654 | } | |
| 5655 | return this.finishOp(code === 61 ? types$1.eq : types$1.prefix, 1) | |
| 5656 | }; | |
| 5657 | ||
| 5658 | pp.readToken_question = function() { // '?' | |
| 5659 | var ecmaVersion = this.options.ecmaVersion; | |
| 5660 | if (ecmaVersion >= 11) { | |
| 5661 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5662 | if (next === 46) { | |
| 5663 | var next2 = this.input.charCodeAt(this.pos + 2); | |
| 5664 | if (next2 < 48 || next2 > 57) { return this.finishOp(types$1.questionDot, 2) } | |
| 5665 | } | |
| 5666 | if (next === 63) { | |
| 5667 | if (ecmaVersion >= 12) { | |
| 5668 | var next2$1 = this.input.charCodeAt(this.pos + 2); | |
| 5669 | if (next2$1 === 61) { return this.finishOp(types$1.assign, 3) } | |
| 5670 | } | |
| 5671 | return this.finishOp(types$1.coalesce, 2) | |
| 5672 | } | |
| 5673 | } | |
| 5674 | return this.finishOp(types$1.question, 1) | |
| 5675 | }; | |
| 5676 | ||
| 5677 | pp.readToken_numberSign = function() { // '#' | |
| 5678 | var ecmaVersion = this.options.ecmaVersion; | |
| 5679 | var code = 35; // '#' | |
| 5680 | if (ecmaVersion >= 13) { | |
| 5681 | ++this.pos; | |
| 5682 | code = this.fullCharCodeAtPos(); | |
| 5683 | if (isIdentifierStart(code, true) || code === 92 /* '\' */) { | |
| 5684 | return this.finishToken(types$1.privateId, this.readWord1()) | |
| 5685 | } | |
| 5686 | } | |
| 5687 | ||
| 5688 | this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); | |
| 5689 | }; | |
| 5690 | ||
| 5691 | pp.getTokenFromCode = function(code) { | |
| 5692 | switch (code) { | |
| 5693 | // The interpretation of a dot depends on whether it is followed | |
| 5694 | // by a digit or another two dots. | |
| 5695 | case 46: // '.' | |
| 5696 | return this.readToken_dot() | |
| 5697 | ||
| 5698 | // Punctuation tokens. | |
| 5699 | case 40: ++this.pos; return this.finishToken(types$1.parenL) | |
| 5700 | case 41: ++this.pos; return this.finishToken(types$1.parenR) | |
| 5701 | case 59: ++this.pos; return this.finishToken(types$1.semi) | |
| 5702 | case 44: ++this.pos; return this.finishToken(types$1.comma) | |
| 5703 | case 91: ++this.pos; return this.finishToken(types$1.bracketL) | |
| 5704 | case 93: ++this.pos; return this.finishToken(types$1.bracketR) | |
| 5705 | case 123: ++this.pos; return this.finishToken(types$1.braceL) | |
| 5706 | case 125: ++this.pos; return this.finishToken(types$1.braceR) | |
| 5707 | case 58: ++this.pos; return this.finishToken(types$1.colon) | |
| 5708 | ||
| 5709 | case 96: // '`' | |
| 5710 | if (this.options.ecmaVersion < 6) { break } | |
| 5711 | ++this.pos; | |
| 5712 | return this.finishToken(types$1.backQuote) | |
| 5713 | ||
| 5714 | case 48: // '0' | |
| 5715 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5716 | if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number | |
| 5717 | if (this.options.ecmaVersion >= 6) { | |
| 5718 | if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number | |
| 5719 | if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number | |
| 5720 | } | |
| 5721 | ||
| 5722 | // Anything else beginning with a digit is an integer, octal | |
| 5723 | // number, or float. | |
| 5724 | case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 | |
| 5725 | return this.readNumber(false) | |
| 5726 | ||
| 5727 | // Quotes produce strings. | |
| 5728 | case 34: case 39: // '"', "'" | |
| 5729 | return this.readString(code) | |
| 5730 | ||
| 5731 | // Operators are parsed inline in tiny state machines. '=' (61) is | |
| 5732 | // often referred to. `finishOp` simply skips the amount of | |
| 5733 | // characters it is given as second argument, and returns a token | |
| 5734 | // of the type given by its first argument. | |
| 5735 | case 47: // '/' | |
| 5736 | return this.readToken_slash() | |
| 5737 | ||
| 5738 | case 37: case 42: // '%*' | |
| 5739 | return this.readToken_mult_modulo_exp(code) | |
| 5740 | ||
| 5741 | case 124: case 38: // '|&' | |
| 5742 | return this.readToken_pipe_amp(code) | |
| 5743 | ||
| 5744 | case 94: // '^' | |
| 5745 | return this.readToken_caret() | |
| 5746 | ||
| 5747 | case 43: case 45: // '+-' | |
| 5748 | return this.readToken_plus_min(code) | |
| 5749 | ||
| 5750 | case 60: case 62: // '<>' | |
| 5751 | return this.readToken_lt_gt(code) | |
| 5752 | ||
| 5753 | case 61: case 33: // '=!' | |
| 5754 | return this.readToken_eq_excl(code) | |
| 5755 | ||
| 5756 | case 63: // '?' | |
| 5757 | return this.readToken_question() | |
| 5758 | ||
| 5759 | case 126: // '~' | |
| 5760 | return this.finishOp(types$1.prefix, 1) | |
| 5761 | ||
| 5762 | case 35: // '#' | |
| 5763 | return this.readToken_numberSign() | |
| 5764 | } | |
| 5765 | ||
| 5766 | this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); | |
| 5767 | }; | |
| 5768 | ||
| 5769 | pp.finishOp = function(type, size) { | |
| 5770 | var str = this.input.slice(this.pos, this.pos + size); | |
| 5771 | this.pos += size; | |
| 5772 | return this.finishToken(type, str) | |
| 5773 | }; | |
| 5774 | ||
| 5775 | pp.readRegexp = function() { | |
| 5776 | var escaped, inClass, start = this.pos; | |
| 5777 | for (;;) { | |
| 5778 | if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); } | |
| 5779 | var ch = this.input.charAt(this.pos); | |
| 5780 | if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); } | |
| 5781 | if (!escaped) { | |
| 5782 | if (ch === "[") { inClass = true; } | |
| 5783 | else if (ch === "]" && inClass) { inClass = false; } | |
| 5784 | else if (ch === "/" && !inClass) { break } | |
| 5785 | escaped = ch === "\\"; | |
| 5786 | } else { escaped = false; } | |
| 5787 | ++this.pos; | |
| 5788 | } | |
| 5789 | var pattern = this.input.slice(start, this.pos); | |
| 5790 | ++this.pos; | |
| 5791 | var flagsStart = this.pos; | |
| 5792 | var flags = this.readWord1(); | |
| 5793 | if (this.containsEsc) { this.unexpected(flagsStart); } | |
| 5794 | ||
| 5795 | // Validate pattern | |
| 5796 | var state = this.regexpState || (this.regexpState = new RegExpValidationState(this)); | |
| 5797 | state.reset(start, pattern, flags); | |
| 5798 | this.validateRegExpFlags(state); | |
| 5799 | this.validateRegExpPattern(state); | |
| 5800 | ||
| 5801 | // Create Literal#value property value. | |
| 5802 | var value = null; | |
| 5803 | try { | |
| 5804 | value = new RegExp(pattern, flags); | |
| 5805 | } catch (e) { | |
| 5806 | // ESTree requires null if it failed to instantiate RegExp object. | |
| 5807 | // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral | |
| 5808 | } | |
| 5809 | ||
| 5810 | return this.finishToken(types$1.regexp, {pattern: pattern, flags: flags, value: value}) | |
| 5811 | }; | |
| 5812 | ||
| 5813 | // Read an integer in the given radix. Return null if zero digits | |
| 5814 | // were read, the integer value otherwise. When `len` is given, this | |
| 5815 | // will return `null` unless the integer has exactly `len` digits. | |
| 5816 | ||
| 5817 | pp.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) { | |
| 5818 | // `len` is used for character escape sequences. In that case, disallow separators. | |
| 5819 | var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined; | |
| 5820 | ||
| 5821 | // `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b) | |
| 5822 | // and isn't fraction part nor exponent part. In that case, if the first digit | |
| 5823 | // is zero then disallow separators. | |
| 5824 | var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48; | |
| 5825 | ||
| 5826 | var start = this.pos, total = 0, lastCode = 0; | |
| 5827 | for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) { | |
| 5828 | var code = this.input.charCodeAt(this.pos), val = (void 0); | |
| 5829 | ||
| 5830 | if (allowSeparators && code === 95) { | |
| 5831 | if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); } | |
| 5832 | if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); } | |
| 5833 | if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); } | |
| 5834 | lastCode = code; | |
| 5835 | continue | |
| 5836 | } | |
| 5837 | ||
| 5838 | if (code >= 97) { val = code - 97 + 10; } // a | |
| 5839 | else if (code >= 65) { val = code - 65 + 10; } // A | |
| 5840 | else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9 | |
| 5841 | else { val = Infinity; } | |
| 5842 | if (val >= radix) { break } | |
| 5843 | lastCode = code; | |
| 5844 | total = total * radix + val; | |
| 5845 | } | |
| 5846 | ||
| 5847 | if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); } | |
| 5848 | if (this.pos === start || len != null && this.pos - start !== len) { return null } | |
| 5849 | ||
| 5850 | return total | |
| 5851 | }; | |
| 5852 | ||
| 5853 | function stringToNumber(str, isLegacyOctalNumericLiteral) { | |
| 5854 | if (isLegacyOctalNumericLiteral) { | |
| 5855 | return parseInt(str, 8) | |
| 5856 | } | |
| 5857 | ||
| 5858 | // `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value. | |
| 5859 | return parseFloat(str.replace(/_/g, "")) | |
| 5860 | } | |
| 5861 | ||
| 5862 | function stringToBigInt(str) { | |
| 5863 | if (typeof BigInt !== "function") { | |
| 5864 | return null | |
| 5865 | } | |
| 5866 | ||
| 5867 | // `BigInt(value)` throws syntax error if the string contains numeric separators. | |
| 5868 | return BigInt(str.replace(/_/g, "")) | |
| 5869 | } | |
| 5870 | ||
| 5871 | pp.readRadixNumber = function(radix) { | |
| 5872 | var start = this.pos; | |
| 5873 | this.pos += 2; // 0x | |
| 5874 | var val = this.readInt(radix); | |
| 5875 | if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); } | |
| 5876 | if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) { | |
| 5877 | val = stringToBigInt(this.input.slice(start, this.pos)); | |
| 5878 | ++this.pos; | |
| 5879 | } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
| 5880 | return this.finishToken(types$1.num, val) | |
| 5881 | }; | |
| 5882 | ||
| 5883 | // Read an integer, octal integer, or floating-point number. | |
| 5884 | ||
| 5885 | pp.readNumber = function(startsWithDot) { | |
| 5886 | var start = this.pos; | |
| 5887 | if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); } | |
| 5888 | var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48; | |
| 5889 | if (octal && this.strict) { this.raise(start, "Invalid number"); } | |
| 5890 | var next = this.input.charCodeAt(this.pos); | |
| 5891 | if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) { | |
| 5892 | var val$1 = stringToBigInt(this.input.slice(start, this.pos)); | |
| 5893 | ++this.pos; | |
| 5894 | if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
| 5895 | return this.finishToken(types$1.num, val$1) | |
| 5896 | } | |
| 5897 | if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; } | |
| 5898 | if (next === 46 && !octal) { // '.' | |
| 5899 | ++this.pos; | |
| 5900 | this.readInt(10); | |
| 5901 | next = this.input.charCodeAt(this.pos); | |
| 5902 | } | |
| 5903 | if ((next === 69 || next === 101) && !octal) { // 'eE' | |
| 5904 | next = this.input.charCodeAt(++this.pos); | |
| 5905 | if (next === 43 || next === 45) { ++this.pos; } // '+-' | |
| 5906 | if (this.readInt(10) === null) { this.raise(start, "Invalid number"); } | |
| 5907 | } | |
| 5908 | if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
| 5909 | ||
| 5910 | var val = stringToNumber(this.input.slice(start, this.pos), octal); | |
| 5911 | return this.finishToken(types$1.num, val) | |
| 5912 | }; | |
| 5913 | ||
| 5914 | // Read a string value, interpreting backslash-escapes. | |
| 5915 | ||
| 5916 | pp.readCodePoint = function() { | |
| 5917 | var ch = this.input.charCodeAt(this.pos), code; | |
| 5918 | ||
| 5919 | if (ch === 123) { // '{' | |
| 5920 | if (this.options.ecmaVersion < 6) { this.unexpected(); } | |
| 5921 | var codePos = ++this.pos; | |
| 5922 | code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos); | |
| 5923 | ++this.pos; | |
| 5924 | if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); } | |
| 5925 | } else { | |
| 5926 | code = this.readHexChar(4); | |
| 5927 | } | |
| 5928 | return code | |
| 5929 | }; | |
| 5930 | ||
| 5931 | pp.readString = function(quote) { | |
| 5932 | var out = "", chunkStart = ++this.pos; | |
| 5933 | for (;;) { | |
| 5934 | if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); } | |
| 5935 | var ch = this.input.charCodeAt(this.pos); | |
| 5936 | if (ch === quote) { break } | |
| 5937 | if (ch === 92) { // '\' | |
| 5938 | out += this.input.slice(chunkStart, this.pos); | |
| 5939 | out += this.readEscapedChar(false); | |
| 5940 | chunkStart = this.pos; | |
| 5941 | } else if (ch === 0x2028 || ch === 0x2029) { | |
| 5942 | if (this.options.ecmaVersion < 10) { this.raise(this.start, "Unterminated string constant"); } | |
| 5943 | ++this.pos; | |
| 5944 | if (this.options.locations) { | |
| 5945 | this.curLine++; | |
| 5946 | this.lineStart = this.pos; | |
| 5947 | } | |
| 5948 | } else { | |
| 5949 | if (isNewLine(ch)) { this.raise(this.start, "Unterminated string constant"); } | |
| 5950 | ++this.pos; | |
| 5951 | } | |
| 5952 | } | |
| 5953 | out += this.input.slice(chunkStart, this.pos++); | |
| 5954 | return this.finishToken(types$1.string, out) | |
| 5955 | }; | |
| 5956 | ||
| 5957 | // Reads template string tokens. | |
| 5958 | ||
| 5959 | var INVALID_TEMPLATE_ESCAPE_ERROR = {}; | |
| 5960 | ||
| 5961 | pp.tryReadTemplateToken = function() { | |
| 5962 | this.inTemplateElement = true; | |
| 5963 | try { | |
| 5964 | this.readTmplToken(); | |
| 5965 | } catch (err) { | |
| 5966 | if (err === INVALID_TEMPLATE_ESCAPE_ERROR) { | |
| 5967 | this.readInvalidTemplateToken(); | |
| 5968 | } else { | |
| 5969 | throw err | |
| 5970 | } | |
| 5971 | } | |
| 5972 | ||
| 5973 | this.inTemplateElement = false; | |
| 5974 | }; | |
| 5975 | ||
| 5976 | pp.invalidStringToken = function(position, message) { | |
| 5977 | if (this.inTemplateElement && this.options.ecmaVersion >= 9) { | |
| 5978 | throw INVALID_TEMPLATE_ESCAPE_ERROR | |
| 5979 | } else { | |
| 5980 | this.raise(position, message); | |
| 5981 | } | |
| 5982 | }; | |
| 5983 | ||
| 5984 | pp.readTmplToken = function() { | |
| 5985 | var out = "", chunkStart = this.pos; | |
| 5986 | for (;;) { | |
| 5987 | if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); } | |
| 5988 | var ch = this.input.charCodeAt(this.pos); | |
| 5989 | if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${' | |
| 5990 | if (this.pos === this.start && (this.type === types$1.template || this.type === types$1.invalidTemplate)) { | |
| 5991 | if (ch === 36) { | |
| 5992 | this.pos += 2; | |
| 5993 | return this.finishToken(types$1.dollarBraceL) | |
| 5994 | } else { | |
| 5995 | ++this.pos; | |
| 5996 | return this.finishToken(types$1.backQuote) | |
| 5997 | } | |
| 5998 | } | |
| 5999 | out += this.input.slice(chunkStart, this.pos); | |
| 6000 | return this.finishToken(types$1.template, out) | |
| 6001 | } | |
| 6002 | if (ch === 92) { // '\' | |
| 6003 | out += this.input.slice(chunkStart, this.pos); | |
| 6004 | out += this.readEscapedChar(true); | |
| 6005 | chunkStart = this.pos; | |
| 6006 | } else if (isNewLine(ch)) { | |
| 6007 | out += this.input.slice(chunkStart, this.pos); | |
| 6008 | ++this.pos; | |
| 6009 | switch (ch) { | |
| 6010 | case 13: | |
| 6011 | if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } | |
| 6012 | case 10: | |
| 6013 | out += "\n"; | |
| 6014 | break | |
| 6015 | default: | |
| 6016 | out += String.fromCharCode(ch); | |
| 6017 | break | |
| 6018 | } | |
| 6019 | if (this.options.locations) { | |
| 6020 | ++this.curLine; | |
| 6021 | this.lineStart = this.pos; | |
| 6022 | } | |
| 6023 | chunkStart = this.pos; | |
| 6024 | } else { | |
| 6025 | ++this.pos; | |
| 6026 | } | |
| 6027 | } | |
| 6028 | }; | |
| 6029 | ||
| 6030 | // Reads a template token to search for the end, without validating any escape sequences | |
| 6031 | pp.readInvalidTemplateToken = function() { | |
| 6032 | for (; this.pos < this.input.length; this.pos++) { | |
| 6033 | switch (this.input[this.pos]) { | |
| 6034 | case "\\": | |
| 6035 | ++this.pos; | |
| 6036 | break | |
| 6037 | ||
| 6038 | case "$": | |
| 6039 | if (this.input[this.pos + 1] !== "{") { break } | |
| 6040 | // fall through | |
| 6041 | case "`": | |
| 6042 | return this.finishToken(types$1.invalidTemplate, this.input.slice(this.start, this.pos)) | |
| 6043 | ||
| 6044 | case "\r": | |
| 6045 | if (this.input[this.pos + 1] === "\n") { ++this.pos; } | |
| 6046 | // fall through | |
| 6047 | case "\n": case "\u2028": case "\u2029": | |
| 6048 | ++this.curLine; | |
| 6049 | this.lineStart = this.pos + 1; | |
| 6050 | break | |
| 6051 | } | |
| 6052 | } | |
| 6053 | this.raise(this.start, "Unterminated template"); | |
| 6054 | }; | |
| 6055 | ||
| 6056 | // Used to read escaped characters | |
| 6057 | ||
| 6058 | pp.readEscapedChar = function(inTemplate) { | |
| 6059 | var ch = this.input.charCodeAt(++this.pos); | |
| 6060 | ++this.pos; | |
| 6061 | switch (ch) { | |
| 6062 | case 110: return "\n" // 'n' -> '\n' | |
| 6063 | case 114: return "\r" // 'r' -> '\r' | |
| 6064 | case 120: return String.fromCharCode(this.readHexChar(2)) // 'x' | |
| 6065 | case 117: return codePointToString(this.readCodePoint()) // 'u' | |
| 6066 | case 116: return "\t" // 't' -> '\t' | |
| 6067 | case 98: return "\b" // 'b' -> '\b' | |
| 6068 | case 118: return "\u000b" // 'v' -> '\u000b' | |
| 6069 | case 102: return "\f" // 'f' -> '\f' | |
| 6070 | case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n' | |
| 6071 | case 10: // ' \n' | |
| 6072 | if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } | |
| 6073 | return "" | |
| 6074 | case 56: | |
| 6075 | case 57: | |
| 6076 | if (this.strict) { | |
| 6077 | this.invalidStringToken( | |
| 6078 | this.pos - 1, | |
| 6079 | "Invalid escape sequence" | |
| 6080 | ); | |
| 6081 | } | |
| 6082 | if (inTemplate) { | |
| 6083 | var codePos = this.pos - 1; | |
| 6084 | ||
| 6085 | this.invalidStringToken( | |
| 6086 | codePos, | |
| 6087 | "Invalid escape sequence in template string" | |
| 6088 | ); | |
| 6089 | } | |
| 6090 | default: | |
| 6091 | if (ch >= 48 && ch <= 55) { | |
| 6092 | var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]; | |
| 6093 | var octal = parseInt(octalStr, 8); | |
| 6094 | if (octal > 255) { | |
| 6095 | octalStr = octalStr.slice(0, -1); | |
| 6096 | octal = parseInt(octalStr, 8); | |
| 6097 | } | |
| 6098 | this.pos += octalStr.length - 1; | |
| 6099 | ch = this.input.charCodeAt(this.pos); | |
| 6100 | if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) { | |
| 6101 | this.invalidStringToken( | |
| 6102 | this.pos - 1 - octalStr.length, | |
| 6103 | inTemplate | |
| 6104 | ? "Octal literal in template string" | |
| 6105 | : "Octal literal in strict mode" | |
| 6106 | ); | |
| 6107 | } | |
| 6108 | return String.fromCharCode(octal) | |
| 6109 | } | |
| 6110 | if (isNewLine(ch)) { | |
| 6111 | // Unicode new line characters after \ get removed from output in both | |
| 6112 | // template literals and strings | |
| 6113 | if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } | |
| 6114 | return "" | |
| 6115 | } | |
| 6116 | return String.fromCharCode(ch) | |
| 6117 | } | |
| 6118 | }; | |
| 6119 | ||
| 6120 | // Used to read character escape sequences ('\x', '\u', '\U'). | |
| 6121 | ||
| 6122 | pp.readHexChar = function(len) { | |
| 6123 | var codePos = this.pos; | |
| 6124 | var n = this.readInt(16, len); | |
| 6125 | if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); } | |
| 6126 | return n | |
| 6127 | }; | |
| 6128 | ||
| 6129 | // Read an identifier, and return it as a string. Sets `this.containsEsc` | |
| 6130 | // to whether the word contained a '\u' escape. | |
| 6131 | // | |
| 6132 | // Incrementally adds only escaped chars, adding other chunks as-is | |
| 6133 | // as a micro-optimization. | |
| 6134 | ||
| 6135 | pp.readWord1 = function() { | |
| 6136 | this.containsEsc = false; | |
| 6137 | var word = "", first = true, chunkStart = this.pos; | |
| 6138 | var astral = this.options.ecmaVersion >= 6; | |
| 6139 | while (this.pos < this.input.length) { | |
| 6140 | var ch = this.fullCharCodeAtPos(); | |
| 6141 | if (isIdentifierChar(ch, astral)) { | |
| 6142 | this.pos += ch <= 0xffff ? 1 : 2; | |
| 6143 | } else if (ch === 92) { // "\" | |
| 6144 | this.containsEsc = true; | |
| 6145 | word += this.input.slice(chunkStart, this.pos); | |
| 6146 | var escStart = this.pos; | |
| 6147 | if (this.input.charCodeAt(++this.pos) !== 117) // "u" | |
| 6148 | { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); } | |
| 6149 | ++this.pos; | |
| 6150 | var esc = this.readCodePoint(); | |
| 6151 | if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral)) | |
| 6152 | { this.invalidStringToken(escStart, "Invalid Unicode escape"); } | |
| 6153 | word += codePointToString(esc); | |
| 6154 | chunkStart = this.pos; | |
| 6155 | } else { | |
| 6156 | break | |
| 6157 | } | |
| 6158 | first = false; | |
| 6159 | } | |
| 6160 | return word + this.input.slice(chunkStart, this.pos) | |
| 6161 | }; | |
| 6162 | ||
| 6163 | // Read an identifier or keyword token. Will check for reserved | |
| 6164 | // words when necessary. | |
| 6165 | ||
| 6166 | pp.readWord = function() { | |
| 6167 | var word = this.readWord1(); | |
| 6168 | var type = types$1.name; | |
| 6169 | if (this.keywords.test(word)) { | |
| 6170 | type = keywords[word]; | |
| 6171 | } | |
| 6172 | return this.finishToken(type, word) | |
| 6173 | }; | |
| 6174 | ||
| 6175 | // Acorn is a tiny, fast JavaScript parser written in JavaScript. | |
| 6176 | // | |
| 6177 | // Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and | |
| 6178 | // various contributors and released under an MIT license. | |
| 6179 | // | |
| 6180 | // Git repositories for Acorn are available at | |
| 6181 | // | |
| 6182 | // http://marijnhaverbeke.nl/git/acorn | |
| 6183 | // https://github.com/acornjs/acorn.git | |
| 6184 | // | |
| 6185 | // Please use the [github bug tracker][ghbt] to report issues. | |
| 6186 | // | |
| 6187 | // [ghbt]: https://github.com/acornjs/acorn/issues | |
| 6188 | ||
| 6189 | ||
| 6190 | var version = "8.15.0"; | |
| 6191 | ||
| 6192 | Parser.acorn = { | |
| 6193 | Parser: Parser, | |
| 6194 | version: version, | |
| 6195 | defaultOptions: defaultOptions, | |
| 6196 | Position: Position, | |
| 6197 | SourceLocation: SourceLocation, | |
| 6198 | getLineInfo: getLineInfo, | |
| 6199 | Node: Node, | |
| 6200 | TokenType: TokenType, | |
| 6201 | tokTypes: types$1, | |
| 6202 | keywordTypes: keywords, | |
| 6203 | TokContext: TokContext, | |
| 6204 | tokContexts: types, | |
| 6205 | isIdentifierChar: isIdentifierChar, | |
| 6206 | isIdentifierStart: isIdentifierStart, | |
| 6207 | Token: Token, | |
| 6208 | isNewLine: isNewLine, | |
| 6209 | lineBreak: lineBreak, | |
| 6210 | lineBreakG: lineBreakG, | |
| 6211 | nonASCIIwhitespace: nonASCIIwhitespace | |
| 6212 | }; | |
| 6213 | ||
| 6214 | // The main exported interface (under `self.acorn` when in the | |
| 6215 | // browser) is a `parse` function that takes a code string and returns | |
| 6216 | // an abstract syntax tree as specified by the [ESTree spec][estree]. | |
| 6217 | // | |
| 6218 | // [estree]: https://github.com/estree/estree | |
| 6219 | ||
| 6220 | function parse(input, options) { | |
| 6221 | return Parser.parse(input, options) | |
| 6222 | } | |
| 6223 | ||
| 6224 | // This function tries to parse a single expression at a given | |
| 6225 | // offset in a string. Useful for parsing mixed-language formats | |
| 6226 | // that embed JavaScript expressions. | |
| 6227 | ||
| 6228 | function parseExpressionAt(input, pos, options) { | |
| 6229 | return Parser.parseExpressionAt(input, pos, options) | |
| 6230 | } | |
| 6231 | ||
| 6232 | // Acorn is organized as a tokenizer and a recursive-descent parser. | |
| 6233 | // The `tokenizer` export provides an interface to the tokenizer. | |
| 6234 | ||
| 6235 | function tokenizer(input, options) { | |
| 6236 | return Parser.tokenizer(input, options) | |
| 6237 | } | |
| 6238 | ||
| 6239 | exports.Node = Node; | |
| 6240 | exports.Parser = Parser; | |
| 6241 | exports.Position = Position; | |
| 6242 | exports.SourceLocation = SourceLocation; | |
| 6243 | exports.TokContext = TokContext; | |
| 6244 | exports.Token = Token; | |
| 6245 | exports.TokenType = TokenType; | |
| 6246 | exports.defaultOptions = defaultOptions; | |
| 6247 | exports.getLineInfo = getLineInfo; | |
| 6248 | exports.isIdentifierChar = isIdentifierChar; | |
| 6249 | exports.isIdentifierStart = isIdentifierStart; | |
| 6250 | exports.isNewLine = isNewLine; | |
| 6251 | exports.keywordTypes = keywords; | |
| 6252 | exports.lineBreak = lineBreak; | |
| 6253 | exports.lineBreakG = lineBreakG; | |
| 6254 | exports.nonASCIIwhitespace = nonASCIIwhitespace; | |
| 6255 | exports.parse = parse; | |
| 6256 | exports.parseExpressionAt = parseExpressionAt; | |
| 6257 | exports.tokContexts = types; | |
| 6258 | exports.tokTypes = types$1; | |
| 6259 | exports.tokenizer = tokenizer; | |
| 6260 | exports.version = version; | |
| 6261 | ||
| 6262 | })); |
| … | … | @@ -0,0 +1,6233 @@ |
| 1 | // This file was generated. Do not modify manually! | |
| 2 | var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 80, 3, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 343, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 726, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; | |
| 3 | ||
| 4 | // This file was generated. Do not modify manually! | |
| 5 | var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 39, 27, 10, 22, 251, 41, 7, 1, 17, 2, 60, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 31, 9, 2, 0, 3, 0, 2, 37, 2, 0, 26, 0, 2, 0, 45, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 200, 32, 32, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 26, 3994, 6, 582, 6842, 29, 1763, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 433, 44, 212, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 42, 9, 8936, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 229, 29, 3, 0, 496, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4153, 7, 221, 3, 5761, 15, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 4191]; | |
| 6 | ||
| 7 | // This file was generated. Do not modify manually! | |
| 8 | var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65"; | |
| 9 | ||
| 10 | // This file was generated. Do not modify manually! | |
| 11 | var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; | |
| 12 | ||
| 13 | // These are a run-length and offset encoded representation of the | |
| 14 | // >0xffff code points that are a valid part of identifiers. The | |
| 15 | // offset starts at 0x10000, and each pair of numbers represents an | |
| 16 | // offset to the next range, and then a size of the range. | |
| 17 | ||
| 18 | // Reserved word lists for various dialects of the language | |
| 19 | ||
| 20 | var reservedWords = { | |
| 21 | 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", | |
| 22 | 5: "class enum extends super const export import", | |
| 23 | 6: "enum", | |
| 24 | strict: "implements interface let package private protected public static yield", | |
| 25 | strictBind: "eval arguments" | |
| 26 | }; | |
| 27 | ||
| 28 | // And the keywords | |
| 29 | ||
| 30 | var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; | |
| 31 | ||
| 32 | var keywords$1 = { | |
| 33 | 5: ecma5AndLessKeywords, | |
| 34 | "5module": ecma5AndLessKeywords + " export import", | |
| 35 | 6: ecma5AndLessKeywords + " const class extends export import super" | |
| 36 | }; | |
| 37 | ||
| 38 | var keywordRelationalOperator = /^in(stanceof)?$/; | |
| 39 | ||
| 40 | // ## Character categories | |
| 41 | ||
| 42 | var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); | |
| 43 | var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); | |
| 44 | ||
| 45 | // This has a complexity linear to the value of the code. The | |
| 46 | // assumption is that looking up astral identifier characters is | |
| 47 | // rare. | |
| 48 | function isInAstralSet(code, set) { | |
| 49 | var pos = 0x10000; | |
| 50 | for (var i = 0; i < set.length; i += 2) { | |
| 51 | pos += set[i]; | |
| 52 | if (pos > code) { return false } | |
| 53 | pos += set[i + 1]; | |
| 54 | if (pos >= code) { return true } | |
| 55 | } | |
| 56 | return false | |
| 57 | } | |
| 58 | ||
| 59 | // Test whether a given character code starts an identifier. | |
| 60 | ||
| 61 | function isIdentifierStart(code, astral) { | |
| 62 | if (code < 65) { return code === 36 } | |
| 63 | if (code < 91) { return true } | |
| 64 | if (code < 97) { return code === 95 } | |
| 65 | if (code < 123) { return true } | |
| 66 | if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } | |
| 67 | if (astral === false) { return false } | |
| 68 | return isInAstralSet(code, astralIdentifierStartCodes) | |
| 69 | } | |
| 70 | ||
| 71 | // Test whether a given character is part of an identifier. | |
| 72 | ||
| 73 | function isIdentifierChar(code, astral) { | |
| 74 | if (code < 48) { return code === 36 } | |
| 75 | if (code < 58) { return true } | |
| 76 | if (code < 65) { return false } | |
| 77 | if (code < 91) { return true } | |
| 78 | if (code < 97) { return code === 95 } | |
| 79 | if (code < 123) { return true } | |
| 80 | if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } | |
| 81 | if (astral === false) { return false } | |
| 82 | return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) | |
| 83 | } | |
| 84 | ||
| 85 | // ## Token types | |
| 86 | ||
| 87 | // The assignment of fine-grained, information-carrying type objects | |
| 88 | // allows the tokenizer to store the information it has about a | |
| 89 | // token in a way that is very cheap for the parser to look up. | |
| 90 | ||
| 91 | // All token type variables start with an underscore, to make them | |
| 92 | // easy to recognize. | |
| 93 | ||
| 94 | // The `beforeExpr` property is used to disambiguate between regular | |
| 95 | // expressions and divisions. It is set on all token types that can | |
| 96 | // be followed by an expression (thus, a slash after them would be a | |
| 97 | // regular expression). | |
| 98 | // | |
| 99 | // The `startsExpr` property is used to check if the token ends a | |
| 100 | // `yield` expression. It is set on all token types that either can | |
| 101 | // directly start an expression (like a quotation mark) or can | |
| 102 | // continue an expression (like the body of a string). | |
| 103 | // | |
| 104 | // `isLoop` marks a keyword as starting a loop, which is important | |
| 105 | // to know when parsing a label, in order to allow or disallow | |
| 106 | // continue jumps to that label. | |
| 107 | ||
| 108 | var TokenType = function TokenType(label, conf) { | |
| 109 | if ( conf === void 0 ) conf = {}; | |
| 110 | ||
| 111 | this.label = label; | |
| 112 | this.keyword = conf.keyword; | |
| 113 | this.beforeExpr = !!conf.beforeExpr; | |
| 114 | this.startsExpr = !!conf.startsExpr; | |
| 115 | this.isLoop = !!conf.isLoop; | |
| 116 | this.isAssign = !!conf.isAssign; | |
| 117 | this.prefix = !!conf.prefix; | |
| 118 | this.postfix = !!conf.postfix; | |
| 119 | this.binop = conf.binop || null; | |
| 120 | this.updateContext = null; | |
| 121 | }; | |
| 122 | ||
| 123 | function binop(name, prec) { | |
| 124 | return new TokenType(name, {beforeExpr: true, binop: prec}) | |
| 125 | } | |
| 126 | var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}; | |
| 127 | ||
| 128 | // Map keyword names to token types. | |
| 129 | ||
| 130 | var keywords = {}; | |
| 131 | ||
| 132 | // Succinct definitions of keyword token types | |
| 133 | function kw(name, options) { | |
| 134 | if ( options === void 0 ) options = {}; | |
| 135 | ||
| 136 | options.keyword = name; | |
| 137 | return keywords[name] = new TokenType(name, options) | |
| 138 | } | |
| 139 | ||
| 140 | var types$1 = { | |
| 141 | num: new TokenType("num", startsExpr), | |
| 142 | regexp: new TokenType("regexp", startsExpr), | |
| 143 | string: new TokenType("string", startsExpr), | |
| 144 | name: new TokenType("name", startsExpr), | |
| 145 | privateId: new TokenType("privateId", startsExpr), | |
| 146 | eof: new TokenType("eof"), | |
| 147 | ||
| 148 | // Punctuation token types. | |
| 149 | bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), | |
| 150 | bracketR: new TokenType("]"), | |
| 151 | braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), | |
| 152 | braceR: new TokenType("}"), | |
| 153 | parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), | |
| 154 | parenR: new TokenType(")"), | |
| 155 | comma: new TokenType(",", beforeExpr), | |
| 156 | semi: new TokenType(";", beforeExpr), | |
| 157 | colon: new TokenType(":", beforeExpr), | |
| 158 | dot: new TokenType("."), | |
| 159 | question: new TokenType("?", beforeExpr), | |
| 160 | questionDot: new TokenType("?."), | |
| 161 | arrow: new TokenType("=>", beforeExpr), | |
| 162 | template: new TokenType("template"), | |
| 163 | invalidTemplate: new TokenType("invalidTemplate"), | |
| 164 | ellipsis: new TokenType("...", beforeExpr), | |
| 165 | backQuote: new TokenType("`", startsExpr), | |
| 166 | dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), | |
| 167 | ||
| 168 | // Operators. These carry several kinds of properties to help the | |
| 169 | // parser use them properly (the presence of these properties is | |
| 170 | // what categorizes them as operators). | |
| 171 | // | |
| 172 | // `binop`, when present, specifies that this operator is a binary | |
| 173 | // operator, and will refer to its precedence. | |
| 174 | // | |
| 175 | // `prefix` and `postfix` mark the operator as a prefix or postfix | |
| 176 | // unary operator. | |
| 177 | // | |
| 178 | // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as | |
| 179 | // binary operators with a very low precedence, that should result | |
| 180 | // in AssignmentExpression nodes. | |
| 181 | ||
| 182 | eq: new TokenType("=", {beforeExpr: true, isAssign: true}), | |
| 183 | assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), | |
| 184 | incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), | |
| 185 | prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), | |
| 186 | logicalOR: binop("||", 1), | |
| 187 | logicalAND: binop("&&", 2), | |
| 188 | bitwiseOR: binop("|", 3), | |
| 189 | bitwiseXOR: binop("^", 4), | |
| 190 | bitwiseAND: binop("&", 5), | |
| 191 | equality: binop("==/!=/===/!==", 6), | |
| 192 | relational: binop("</>/<=/>=", 7), | |
| 193 | bitShift: binop("<</>>/>>>", 8), | |
| 194 | plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), | |
| 195 | modulo: binop("%", 10), | |
| 196 | star: binop("*", 10), | |
| 197 | slash: binop("/", 10), | |
| 198 | starstar: new TokenType("**", {beforeExpr: true}), | |
| 199 | coalesce: binop("??", 1), | |
| 200 | ||
| 201 | // Keyword token types. | |
| 202 | _break: kw("break"), | |
| 203 | _case: kw("case", beforeExpr), | |
| 204 | _catch: kw("catch"), | |
| 205 | _continue: kw("continue"), | |
| 206 | _debugger: kw("debugger"), | |
| 207 | _default: kw("default", beforeExpr), | |
| 208 | _do: kw("do", {isLoop: true, beforeExpr: true}), | |
| 209 | _else: kw("else", beforeExpr), | |
| 210 | _finally: kw("finally"), | |
| 211 | _for: kw("for", {isLoop: true}), | |
| 212 | _function: kw("function", startsExpr), | |
| 213 | _if: kw("if"), | |
| 214 | _return: kw("return", beforeExpr), | |
| 215 | _switch: kw("switch"), | |
| 216 | _throw: kw("throw", beforeExpr), | |
| 217 | _try: kw("try"), | |
| 218 | _var: kw("var"), | |
| 219 | _const: kw("const"), | |
| 220 | _while: kw("while", {isLoop: true}), | |
| 221 | _with: kw("with"), | |
| 222 | _new: kw("new", {beforeExpr: true, startsExpr: true}), | |
| 223 | _this: kw("this", startsExpr), | |
| 224 | _super: kw("super", startsExpr), | |
| 225 | _class: kw("class", startsExpr), | |
| 226 | _extends: kw("extends", beforeExpr), | |
| 227 | _export: kw("export"), | |
| 228 | _import: kw("import", startsExpr), | |
| 229 | _null: kw("null", startsExpr), | |
| 230 | _true: kw("true", startsExpr), | |
| 231 | _false: kw("false", startsExpr), | |
| 232 | _in: kw("in", {beforeExpr: true, binop: 7}), | |
| 233 | _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), | |
| 234 | _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), | |
| 235 | _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), | |
| 236 | _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) | |
| 237 | }; | |
| 238 | ||
| 239 | // Matches a whole line break (where CRLF is considered a single | |
| 240 | // line break). Used to count lines. | |
| 241 | ||
| 242 | var lineBreak = /\r\n?|\n|\u2028|\u2029/; | |
| 243 | var lineBreakG = new RegExp(lineBreak.source, "g"); | |
| 244 | ||
| 245 | function isNewLine(code) { | |
| 246 | return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 | |
| 247 | } | |
| 248 | ||
| 249 | function nextLineBreak(code, from, end) { | |
| 250 | if ( end === void 0 ) end = code.length; | |
| 251 | ||
| 252 | for (var i = from; i < end; i++) { | |
| 253 | var next = code.charCodeAt(i); | |
| 254 | if (isNewLine(next)) | |
| 255 | { return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1 } | |
| 256 | } | |
| 257 | return -1 | |
| 258 | } | |
| 259 | ||
| 260 | var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/; | |
| 261 | ||
| 262 | var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; | |
| 263 | ||
| 264 | var ref = Object.prototype; | |
| 265 | var hasOwnProperty = ref.hasOwnProperty; | |
| 266 | var toString = ref.toString; | |
| 267 | ||
| 268 | var hasOwn = Object.hasOwn || (function (obj, propName) { return ( | |
| 269 | hasOwnProperty.call(obj, propName) | |
| 270 | ); }); | |
| 271 | ||
| 272 | var isArray = Array.isArray || (function (obj) { return ( | |
| 273 | toString.call(obj) === "[object Array]" | |
| 274 | ); }); | |
| 275 | ||
| 276 | var regexpCache = Object.create(null); | |
| 277 | ||
| 278 | function wordsRegexp(words) { | |
| 279 | return regexpCache[words] || (regexpCache[words] = new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")) | |
| 280 | } | |
| 281 | ||
| 282 | function codePointToString(code) { | |
| 283 | // UTF-16 Decoding | |
| 284 | if (code <= 0xFFFF) { return String.fromCharCode(code) } | |
| 285 | code -= 0x10000; | |
| 286 | return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) | |
| 287 | } | |
| 288 | ||
| 289 | var loneSurrogate = /(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/; | |
| 290 | ||
| 291 | // These are used when `options.locations` is on, for the | |
| 292 | // `startLoc` and `endLoc` properties. | |
| 293 | ||
| 294 | var Position = function Position(line, col) { | |
| 295 | this.line = line; | |
| 296 | this.column = col; | |
| 297 | }; | |
| 298 | ||
| 299 | Position.prototype.offset = function offset (n) { | |
| 300 | return new Position(this.line, this.column + n) | |
| 301 | }; | |
| 302 | ||
| 303 | var SourceLocation = function SourceLocation(p, start, end) { | |
| 304 | this.start = start; | |
| 305 | this.end = end; | |
| 306 | if (p.sourceFile !== null) { this.source = p.sourceFile; } | |
| 307 | }; | |
| 308 | ||
| 309 | // The `getLineInfo` function is mostly useful when the | |
| 310 | // `locations` option is off (for performance reasons) and you | |
| 311 | // want to find the line/column position for a given character | |
| 312 | // offset. `input` should be the code string that the offset refers | |
| 313 | // into. | |
| 314 | ||
| 315 | function getLineInfo(input, offset) { | |
| 316 | for (var line = 1, cur = 0;;) { | |
| 317 | var nextBreak = nextLineBreak(input, cur, offset); | |
| 318 | if (nextBreak < 0) { return new Position(line, offset - cur) } | |
| 319 | ++line; | |
| 320 | cur = nextBreak; | |
| 321 | } | |
| 322 | } | |
| 323 | ||
| 324 | // A second argument must be given to configure the parser process. | |
| 325 | // These options are recognized (only `ecmaVersion` is required): | |
| 326 | ||
| 327 | var defaultOptions = { | |
| 328 | // `ecmaVersion` indicates the ECMAScript version to parse. Must be | |
| 329 | // either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 | |
| 330 | // (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"` | |
| 331 | // (the latest version the library supports). This influences | |
| 332 | // support for strict mode, the set of reserved words, and support | |
| 333 | // for new syntax features. | |
| 334 | ecmaVersion: null, | |
| 335 | // `sourceType` indicates the mode the code should be parsed in. | |
| 336 | // Can be either `"script"` or `"module"`. This influences global | |
| 337 | // strict mode and parsing of `import` and `export` declarations. | |
| 338 | sourceType: "script", | |
| 339 | // `onInsertedSemicolon` can be a callback that will be called when | |
| 340 | // a semicolon is automatically inserted. It will be passed the | |
| 341 | // position of the inserted semicolon as an offset, and if | |
| 342 | // `locations` is enabled, it is given the location as a `{line, | |
| 343 | // column}` object as second argument. | |
| 344 | onInsertedSemicolon: null, | |
| 345 | // `onTrailingComma` is similar to `onInsertedSemicolon`, but for | |
| 346 | // trailing commas. | |
| 347 | onTrailingComma: null, | |
| 348 | // By default, reserved words are only enforced if ecmaVersion >= 5. | |
| 349 | // Set `allowReserved` to a boolean value to explicitly turn this on | |
| 350 | // an off. When this option has the value "never", reserved words | |
| 351 | // and keywords can also not be used as property names. | |
| 352 | allowReserved: null, | |
| 353 | // When enabled, a return at the top level is not considered an | |
| 354 | // error. | |
| 355 | allowReturnOutsideFunction: false, | |
| 356 | // When enabled, import/export statements are not constrained to | |
| 357 | // appearing at the top of the program, and an import.meta expression | |
| 358 | // in a script isn't considered an error. | |
| 359 | allowImportExportEverywhere: false, | |
| 360 | // By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022. | |
| 361 | // When enabled, await identifiers are allowed to appear at the top-level scope, | |
| 362 | // but they are still not allowed in non-async functions. | |
| 363 | allowAwaitOutsideFunction: null, | |
| 364 | // When enabled, super identifiers are not constrained to | |
| 365 | // appearing in methods and do not raise an error when they appear elsewhere. | |
| 366 | allowSuperOutsideMethod: null, | |
| 367 | // When enabled, hashbang directive in the beginning of file is | |
| 368 | // allowed and treated as a line comment. Enabled by default when | |
| 369 | // `ecmaVersion` >= 2023. | |
| 370 | allowHashBang: false, | |
| 371 | // By default, the parser will verify that private properties are | |
| 372 | // only used in places where they are valid and have been declared. | |
| 373 | // Set this to false to turn such checks off. | |
| 374 | checkPrivateFields: true, | |
| 375 | // When `locations` is on, `loc` properties holding objects with | |
| 376 | // `start` and `end` properties in `{line, column}` form (with | |
| 377 | // line being 1-based and column 0-based) will be attached to the | |
| 378 | // nodes. | |
| 379 | locations: false, | |
| 380 | // A function can be passed as `onToken` option, which will | |
| 381 | // cause Acorn to call that function with object in the same | |
| 382 | // format as tokens returned from `tokenizer().getToken()`. Note | |
| 383 | // that you are not allowed to call the parser from the | |
| 384 | // callback—that will corrupt its internal state. | |
| 385 | onToken: null, | |
| 386 | // A function can be passed as `onComment` option, which will | |
| 387 | // cause Acorn to call that function with `(block, text, start, | |
| 388 | // end)` parameters whenever a comment is skipped. `block` is a | |
| 389 | // boolean indicating whether this is a block (`/* */`) comment, | |
| 390 | // `text` is the content of the comment, and `start` and `end` are | |
| 391 | // character offsets that denote the start and end of the comment. | |
| 392 | // When the `locations` option is on, two more parameters are | |
| 393 | // passed, the full `{line, column}` locations of the start and | |
| 394 | // end of the comments. Note that you are not allowed to call the | |
| 395 | // parser from the callback—that will corrupt its internal state. | |
| 396 | // When this option has an array as value, objects representing the | |
| 397 | // comments are pushed to it. | |
| 398 | onComment: null, | |
| 399 | // Nodes have their start and end characters offsets recorded in | |
| 400 | // `start` and `end` properties (directly on the node, rather than | |
| 401 | // the `loc` object, which holds line/column data. To also add a | |
| 402 | // [semi-standardized][range] `range` property holding a `[start, | |
| 403 | // end]` array with the same numbers, set the `ranges` option to | |
| 404 | // `true`. | |
| 405 | // | |
| 406 | // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 | |
| 407 | ranges: false, | |
| 408 | // It is possible to parse multiple files into a single AST by | |
| 409 | // passing the tree produced by parsing the first file as | |
| 410 | // `program` option in subsequent parses. This will add the | |
| 411 | // toplevel forms of the parsed file to the `Program` (top) node | |
| 412 | // of an existing parse tree. | |
| 413 | program: null, | |
| 414 | // When `locations` is on, you can pass this to record the source | |
| 415 | // file in every node's `loc` object. | |
| 416 | sourceFile: null, | |
| 417 | // This value, if given, is stored in every node, whether | |
| 418 | // `locations` is on or off. | |
| 419 | directSourceFile: null, | |
| 420 | // When enabled, parenthesized expressions are represented by | |
| 421 | // (non-standard) ParenthesizedExpression nodes | |
| 422 | preserveParens: false | |
| 423 | }; | |
| 424 | ||
| 425 | // Interpret and default an options object | |
| 426 | ||
| 427 | var warnedAboutEcmaVersion = false; | |
| 428 | ||
| 429 | function getOptions(opts) { | |
| 430 | var options = {}; | |
| 431 | ||
| 432 | for (var opt in defaultOptions) | |
| 433 | { options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt]; } | |
| 434 | ||
| 435 | if (options.ecmaVersion === "latest") { | |
| 436 | options.ecmaVersion = 1e8; | |
| 437 | } else if (options.ecmaVersion == null) { | |
| 438 | if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) { | |
| 439 | warnedAboutEcmaVersion = true; | |
| 440 | console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future."); | |
| 441 | } | |
| 442 | options.ecmaVersion = 11; | |
| 443 | } else if (options.ecmaVersion >= 2015) { | |
| 444 | options.ecmaVersion -= 2009; | |
| 445 | } | |
| 446 | ||
| 447 | if (options.allowReserved == null) | |
| 448 | { options.allowReserved = options.ecmaVersion < 5; } | |
| 449 | ||
| 450 | if (!opts || opts.allowHashBang == null) | |
| 451 | { options.allowHashBang = options.ecmaVersion >= 14; } | |
| 452 | ||
| 453 | if (isArray(options.onToken)) { | |
| 454 | var tokens = options.onToken; | |
| 455 | options.onToken = function (token) { return tokens.push(token); }; | |
| 456 | } | |
| 457 | if (isArray(options.onComment)) | |
| 458 | { options.onComment = pushComment(options, options.onComment); } | |
| 459 | ||
| 460 | return options | |
| 461 | } | |
| 462 | ||
| 463 | function pushComment(options, array) { | |
| 464 | return function(block, text, start, end, startLoc, endLoc) { | |
| 465 | var comment = { | |
| 466 | type: block ? "Block" : "Line", | |
| 467 | value: text, | |
| 468 | start: start, | |
| 469 | end: end | |
| 470 | }; | |
| 471 | if (options.locations) | |
| 472 | { comment.loc = new SourceLocation(this, startLoc, endLoc); } | |
| 473 | if (options.ranges) | |
| 474 | { comment.range = [start, end]; } | |
| 475 | array.push(comment); | |
| 476 | } | |
| 477 | } | |
| 478 | ||
| 479 | // Each scope gets a bitset that may contain these flags | |
| 480 | var | |
| 481 | SCOPE_TOP = 1, | |
| 482 | SCOPE_FUNCTION = 2, | |
| 483 | SCOPE_ASYNC = 4, | |
| 484 | SCOPE_GENERATOR = 8, | |
| 485 | SCOPE_ARROW = 16, | |
| 486 | SCOPE_SIMPLE_CATCH = 32, | |
| 487 | SCOPE_SUPER = 64, | |
| 488 | SCOPE_DIRECT_SUPER = 128, | |
| 489 | SCOPE_CLASS_STATIC_BLOCK = 256, | |
| 490 | SCOPE_CLASS_FIELD_INIT = 512, | |
| 491 | SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK; | |
| 492 | ||
| 493 | function functionFlags(async, generator) { | |
| 494 | return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) | |
| 495 | } | |
| 496 | ||
| 497 | // Used in checkLVal* and declareName to determine the type of a binding | |
| 498 | var | |
| 499 | BIND_NONE = 0, // Not a binding | |
| 500 | BIND_VAR = 1, // Var-style binding | |
| 501 | BIND_LEXICAL = 2, // Let- or const-style binding | |
| 502 | BIND_FUNCTION = 3, // Function declaration | |
| 503 | BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding | |
| 504 | BIND_OUTSIDE = 5; // Special case for function names as bound inside the function | |
| 505 | ||
| 506 | var Parser = function Parser(options, input, startPos) { | |
| 507 | this.options = options = getOptions(options); | |
| 508 | this.sourceFile = options.sourceFile; | |
| 509 | this.keywords = wordsRegexp(keywords$1[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]); | |
| 510 | var reserved = ""; | |
| 511 | if (options.allowReserved !== true) { | |
| 512 | reserved = reservedWords[options.ecmaVersion >= 6 ? 6 : options.ecmaVersion === 5 ? 5 : 3]; | |
| 513 | if (options.sourceType === "module") { reserved += " await"; } | |
| 514 | } | |
| 515 | this.reservedWords = wordsRegexp(reserved); | |
| 516 | var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; | |
| 517 | this.reservedWordsStrict = wordsRegexp(reservedStrict); | |
| 518 | this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind); | |
| 519 | this.input = String(input); | |
| 520 | ||
| 521 | // Used to signal to callers of `readWord1` whether the word | |
| 522 | // contained any escape sequences. This is needed because words with | |
| 523 | // escape sequences must not be interpreted as keywords. | |
| 524 | this.containsEsc = false; | |
| 525 | ||
| 526 | // Set up token state | |
| 527 | ||
| 528 | // The current position of the tokenizer in the input. | |
| 529 | if (startPos) { | |
| 530 | this.pos = startPos; | |
| 531 | this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; | |
| 532 | this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; | |
| 533 | } else { | |
| 534 | this.pos = this.lineStart = 0; | |
| 535 | this.curLine = 1; | |
| 536 | } | |
| 537 | ||
| 538 | // Properties of the current token: | |
| 539 | // Its type | |
| 540 | this.type = types$1.eof; | |
| 541 | // For tokens that include more information than their type, the value | |
| 542 | this.value = null; | |
| 543 | // Its start and end offset | |
| 544 | this.start = this.end = this.pos; | |
| 545 | // And, if locations are used, the {line, column} object | |
| 546 | // corresponding to those offsets | |
| 547 | this.startLoc = this.endLoc = this.curPosition(); | |
| 548 | ||
| 549 | // Position information for the previous token | |
| 550 | this.lastTokEndLoc = this.lastTokStartLoc = null; | |
| 551 | this.lastTokStart = this.lastTokEnd = this.pos; | |
| 552 | ||
| 553 | // The context stack is used to superficially track syntactic | |
| 554 | // context to predict whether a regular expression is allowed in a | |
| 555 | // given position. | |
| 556 | this.context = this.initialContext(); | |
| 557 | this.exprAllowed = true; | |
| 558 | ||
| 559 | // Figure out if it's a module code. | |
| 560 | this.inModule = options.sourceType === "module"; | |
| 561 | this.strict = this.inModule || this.strictDirective(this.pos); | |
| 562 | ||
| 563 | // Used to signify the start of a potential arrow function | |
| 564 | this.potentialArrowAt = -1; | |
| 565 | this.potentialArrowInForAwait = false; | |
| 566 | ||
| 567 | // Positions to delayed-check that yield/await does not exist in default parameters. | |
| 568 | this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; | |
| 569 | // Labels in scope. | |
| 570 | this.labels = []; | |
| 571 | // Thus-far undefined exports. | |
| 572 | this.undefinedExports = Object.create(null); | |
| 573 | ||
| 574 | // If enabled, skip leading hashbang line. | |
| 575 | if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") | |
| 576 | { this.skipLineComment(2); } | |
| 577 | ||
| 578 | // Scope tracking for duplicate variable names (see scope.js) | |
| 579 | this.scopeStack = []; | |
| 580 | this.enterScope(SCOPE_TOP); | |
| 581 | ||
| 582 | // For RegExp validation | |
| 583 | this.regexpState = null; | |
| 584 | ||
| 585 | // The stack of private names. | |
| 586 | // Each element has two properties: 'declared' and 'used'. | |
| 587 | // When it exited from the outermost class definition, all used private names must be declared. | |
| 588 | this.privateNameStack = []; | |
| 589 | }; | |
| 590 | ||
| 591 | var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },canAwait: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true },allowNewDotTarget: { configurable: true },inClassStaticBlock: { configurable: true } }; | |
| 592 | ||
| 593 | Parser.prototype.parse = function parse () { | |
| 594 | var node = this.options.program || this.startNode(); | |
| 595 | this.nextToken(); | |
| 596 | return this.parseTopLevel(node) | |
| 597 | }; | |
| 598 | ||
| 599 | prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }; | |
| 600 | ||
| 601 | prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }; | |
| 602 | ||
| 603 | prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }; | |
| 604 | ||
| 605 | prototypeAccessors.canAwait.get = function () { | |
| 606 | for (var i = this.scopeStack.length - 1; i >= 0; i--) { | |
| 607 | var ref = this.scopeStack[i]; | |
| 608 | var flags = ref.flags; | |
| 609 | if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT)) { return false } | |
| 610 | if (flags & SCOPE_FUNCTION) { return (flags & SCOPE_ASYNC) > 0 } | |
| 611 | } | |
| 612 | return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction | |
| 613 | }; | |
| 614 | ||
| 615 | prototypeAccessors.allowSuper.get = function () { | |
| 616 | var ref = this.currentThisScope(); | |
| 617 | var flags = ref.flags; | |
| 618 | return (flags & SCOPE_SUPER) > 0 || this.options.allowSuperOutsideMethod | |
| 619 | }; | |
| 620 | ||
| 621 | prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }; | |
| 622 | ||
| 623 | prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) }; | |
| 624 | ||
| 625 | prototypeAccessors.allowNewDotTarget.get = function () { | |
| 626 | for (var i = this.scopeStack.length - 1; i >= 0; i--) { | |
| 627 | var ref = this.scopeStack[i]; | |
| 628 | var flags = ref.flags; | |
| 629 | if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT) || | |
| 630 | ((flags & SCOPE_FUNCTION) && !(flags & SCOPE_ARROW))) { return true } | |
| 631 | } | |
| 632 | return false | |
| 633 | }; | |
| 634 | ||
| 635 | prototypeAccessors.inClassStaticBlock.get = function () { | |
| 636 | return (this.currentVarScope().flags & SCOPE_CLASS_STATIC_BLOCK) > 0 | |
| 637 | }; | |
| 638 | ||
| 639 | Parser.extend = function extend () { | |
| 640 | var plugins = [], len = arguments.length; | |
| 641 | while ( len-- ) plugins[ len ] = arguments[ len ]; | |
| 642 | ||
| 643 | var cls = this; | |
| 644 | for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } | |
| 645 | return cls | |
| 646 | }; | |
| 647 | ||
| 648 | Parser.parse = function parse (input, options) { | |
| 649 | return new this(options, input).parse() | |
| 650 | }; | |
| 651 | ||
| 652 | Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) { | |
| 653 | var parser = new this(options, input, pos); | |
| 654 | parser.nextToken(); | |
| 655 | return parser.parseExpression() | |
| 656 | }; | |
| 657 | ||
| 658 | Parser.tokenizer = function tokenizer (input, options) { | |
| 659 | return new this(options, input) | |
| 660 | }; | |
| 661 | ||
| 662 | Object.defineProperties( Parser.prototype, prototypeAccessors ); | |
| 663 | ||
| 664 | var pp$9 = Parser.prototype; | |
| 665 | ||
| 666 | // ## Parser utilities | |
| 667 | ||
| 668 | var literal = /^(?:'((?:\\[^]|[^'\\])*?)'|"((?:\\[^]|[^"\\])*?)")/; | |
| 669 | pp$9.strictDirective = function(start) { | |
| 670 | if (this.options.ecmaVersion < 5) { return false } | |
| 671 | for (;;) { | |
| 672 | // Try to find string literal. | |
| 673 | skipWhiteSpace.lastIndex = start; | |
| 674 | start += skipWhiteSpace.exec(this.input)[0].length; | |
| 675 | var match = literal.exec(this.input.slice(start)); | |
| 676 | if (!match) { return false } | |
| 677 | if ((match[1] || match[2]) === "use strict") { | |
| 678 | skipWhiteSpace.lastIndex = start + match[0].length; | |
| 679 | var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length; | |
| 680 | var next = this.input.charAt(end); | |
| 681 | return next === ";" || next === "}" || | |
| 682 | (lineBreak.test(spaceAfter[0]) && | |
| 683 | !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "=")) | |
| 684 | } | |
| 685 | start += match[0].length; | |
| 686 | ||
| 687 | // Skip semicolon, if any. | |
| 688 | skipWhiteSpace.lastIndex = start; | |
| 689 | start += skipWhiteSpace.exec(this.input)[0].length; | |
| 690 | if (this.input[start] === ";") | |
| 691 | { start++; } | |
| 692 | } | |
| 693 | }; | |
| 694 | ||
| 695 | // Predicate that tests whether the next token is of the given | |
| 696 | // type, and if yes, consumes it as a side effect. | |
| 697 | ||
| 698 | pp$9.eat = function(type) { | |
| 699 | if (this.type === type) { | |
| 700 | this.next(); | |
| 701 | return true | |
| 702 | } else { | |
| 703 | return false | |
| 704 | } | |
| 705 | }; | |
| 706 | ||
| 707 | // Tests whether parsed token is a contextual keyword. | |
| 708 | ||
| 709 | pp$9.isContextual = function(name) { | |
| 710 | return this.type === types$1.name && this.value === name && !this.containsEsc | |
| 711 | }; | |
| 712 | ||
| 713 | // Consumes contextual keyword if possible. | |
| 714 | ||
| 715 | pp$9.eatContextual = function(name) { | |
| 716 | if (!this.isContextual(name)) { return false } | |
| 717 | this.next(); | |
| 718 | return true | |
| 719 | }; | |
| 720 | ||
| 721 | // Asserts that following token is given contextual keyword. | |
| 722 | ||
| 723 | pp$9.expectContextual = function(name) { | |
| 724 | if (!this.eatContextual(name)) { this.unexpected(); } | |
| 725 | }; | |
| 726 | ||
| 727 | // Test whether a semicolon can be inserted at the current position. | |
| 728 | ||
| 729 | pp$9.canInsertSemicolon = function() { | |
| 730 | return this.type === types$1.eof || | |
| 731 | this.type === types$1.braceR || | |
| 732 | lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) | |
| 733 | }; | |
| 734 | ||
| 735 | pp$9.insertSemicolon = function() { | |
| 736 | if (this.canInsertSemicolon()) { | |
| 737 | if (this.options.onInsertedSemicolon) | |
| 738 | { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } | |
| 739 | return true | |
| 740 | } | |
| 741 | }; | |
| 742 | ||
| 743 | // Consume a semicolon, or, failing that, see if we are allowed to | |
| 744 | // pretend that there is a semicolon at this position. | |
| 745 | ||
| 746 | pp$9.semicolon = function() { | |
| 747 | if (!this.eat(types$1.semi) && !this.insertSemicolon()) { this.unexpected(); } | |
| 748 | }; | |
| 749 | ||
| 750 | pp$9.afterTrailingComma = function(tokType, notNext) { | |
| 751 | if (this.type === tokType) { | |
| 752 | if (this.options.onTrailingComma) | |
| 753 | { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } | |
| 754 | if (!notNext) | |
| 755 | { this.next(); } | |
| 756 | return true | |
| 757 | } | |
| 758 | }; | |
| 759 | ||
| 760 | // Expect a token of a given type. If found, consume it, otherwise, | |
| 761 | // raise an unexpected token error. | |
| 762 | ||
| 763 | pp$9.expect = function(type) { | |
| 764 | this.eat(type) || this.unexpected(); | |
| 765 | }; | |
| 766 | ||
| 767 | // Raise an unexpected token error. | |
| 768 | ||
| 769 | pp$9.unexpected = function(pos) { | |
| 770 | this.raise(pos != null ? pos : this.start, "Unexpected token"); | |
| 771 | }; | |
| 772 | ||
| 773 | var DestructuringErrors = function DestructuringErrors() { | |
| 774 | this.shorthandAssign = | |
| 775 | this.trailingComma = | |
| 776 | this.parenthesizedAssign = | |
| 777 | this.parenthesizedBind = | |
| 778 | this.doubleProto = | |
| 779 | -1; | |
| 780 | }; | |
| 781 | ||
| 782 | pp$9.checkPatternErrors = function(refDestructuringErrors, isAssign) { | |
| 783 | if (!refDestructuringErrors) { return } | |
| 784 | if (refDestructuringErrors.trailingComma > -1) | |
| 785 | { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } | |
| 786 | var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; | |
| 787 | if (parens > -1) { this.raiseRecoverable(parens, isAssign ? "Assigning to rvalue" : "Parenthesized pattern"); } | |
| 788 | }; | |
| 789 | ||
| 790 | pp$9.checkExpressionErrors = function(refDestructuringErrors, andThrow) { | |
| 791 | if (!refDestructuringErrors) { return false } | |
| 792 | var shorthandAssign = refDestructuringErrors.shorthandAssign; | |
| 793 | var doubleProto = refDestructuringErrors.doubleProto; | |
| 794 | if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } | |
| 795 | if (shorthandAssign >= 0) | |
| 796 | { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } | |
| 797 | if (doubleProto >= 0) | |
| 798 | { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } | |
| 799 | }; | |
| 800 | ||
| 801 | pp$9.checkYieldAwaitInDefaultParams = function() { | |
| 802 | if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) | |
| 803 | { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } | |
| 804 | if (this.awaitPos) | |
| 805 | { this.raise(this.awaitPos, "Await expression cannot be a default value"); } | |
| 806 | }; | |
| 807 | ||
| 808 | pp$9.isSimpleAssignTarget = function(expr) { | |
| 809 | if (expr.type === "ParenthesizedExpression") | |
| 810 | { return this.isSimpleAssignTarget(expr.expression) } | |
| 811 | return expr.type === "Identifier" || expr.type === "MemberExpression" | |
| 812 | }; | |
| 813 | ||
| 814 | var pp$8 = Parser.prototype; | |
| 815 | ||
| 816 | // ### Statement parsing | |
| 817 | ||
| 818 | // Parse a program. Initializes the parser, reads any number of | |
| 819 | // statements, and wraps them in a Program node. Optionally takes a | |
| 820 | // `program` argument. If present, the statements will be appended | |
| 821 | // to its body instead of creating a new node. | |
| 822 | ||
| 823 | pp$8.parseTopLevel = function(node) { | |
| 824 | var exports = Object.create(null); | |
| 825 | if (!node.body) { node.body = []; } | |
| 826 | while (this.type !== types$1.eof) { | |
| 827 | var stmt = this.parseStatement(null, true, exports); | |
| 828 | node.body.push(stmt); | |
| 829 | } | |
| 830 | if (this.inModule) | |
| 831 | { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1) | |
| 832 | { | |
| 833 | var name = list[i]; | |
| 834 | ||
| 835 | this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined")); | |
| 836 | } } | |
| 837 | this.adaptDirectivePrologue(node.body); | |
| 838 | this.next(); | |
| 839 | node.sourceType = this.options.sourceType; | |
| 840 | return this.finishNode(node, "Program") | |
| 841 | }; | |
| 842 | ||
| 843 | var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; | |
| 844 | ||
| 845 | pp$8.isLet = function(context) { | |
| 846 | if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } | |
| 847 | skipWhiteSpace.lastIndex = this.pos; | |
| 848 | var skip = skipWhiteSpace.exec(this.input); | |
| 849 | var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); | |
| 850 | // For ambiguous cases, determine if a LexicalDeclaration (or only a | |
| 851 | // Statement) is allowed here. If context is not empty then only a Statement | |
| 852 | // is allowed. However, `let [` is an explicit negative lookahead for | |
| 853 | // ExpressionStatement, so special-case it first. | |
| 854 | if (nextCh === 91 || nextCh === 92) { return true } // '[', '\' | |
| 855 | if (context) { return false } | |
| 856 | ||
| 857 | if (nextCh === 123 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } // '{', astral | |
| 858 | if (isIdentifierStart(nextCh, true)) { | |
| 859 | var pos = next + 1; | |
| 860 | while (isIdentifierChar(nextCh = this.input.charCodeAt(pos), true)) { ++pos; } | |
| 861 | if (nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00) { return true } | |
| 862 | var ident = this.input.slice(next, pos); | |
| 863 | if (!keywordRelationalOperator.test(ident)) { return true } | |
| 864 | } | |
| 865 | return false | |
| 866 | }; | |
| 867 | ||
| 868 | // check 'async [no LineTerminator here] function' | |
| 869 | // - 'async /*foo*/ function' is OK. | |
| 870 | // - 'async /*\n*/ function' is invalid. | |
| 871 | pp$8.isAsyncFunction = function() { | |
| 872 | if (this.options.ecmaVersion < 8 || !this.isContextual("async")) | |
| 873 | { return false } | |
| 874 | ||
| 875 | skipWhiteSpace.lastIndex = this.pos; | |
| 876 | var skip = skipWhiteSpace.exec(this.input); | |
| 877 | var next = this.pos + skip[0].length, after; | |
| 878 | return !lineBreak.test(this.input.slice(this.pos, next)) && | |
| 879 | this.input.slice(next, next + 8) === "function" && | |
| 880 | (next + 8 === this.input.length || | |
| 881 | !(isIdentifierChar(after = this.input.charCodeAt(next + 8)) || after > 0xd7ff && after < 0xdc00)) | |
| 882 | }; | |
| 883 | ||
| 884 | pp$8.isUsingKeyword = function(isAwaitUsing, isFor) { | |
| 885 | if (this.options.ecmaVersion < 17 || !this.isContextual(isAwaitUsing ? "await" : "using")) | |
| 886 | { return false } | |
| 887 | ||
| 888 | skipWhiteSpace.lastIndex = this.pos; | |
| 889 | var skip = skipWhiteSpace.exec(this.input); | |
| 890 | var next = this.pos + skip[0].length; | |
| 891 | ||
| 892 | if (lineBreak.test(this.input.slice(this.pos, next))) { return false } | |
| 893 | ||
| 894 | if (isAwaitUsing) { | |
| 895 | var awaitEndPos = next + 5 /* await */, after; | |
| 896 | if (this.input.slice(next, awaitEndPos) !== "using" || | |
| 897 | awaitEndPos === this.input.length || | |
| 898 | isIdentifierChar(after = this.input.charCodeAt(awaitEndPos)) || | |
| 899 | (after > 0xd7ff && after < 0xdc00) | |
| 900 | ) { return false } | |
| 901 | ||
| 902 | skipWhiteSpace.lastIndex = awaitEndPos; | |
| 903 | var skipAfterUsing = skipWhiteSpace.exec(this.input); | |
| 904 | if (skipAfterUsing && lineBreak.test(this.input.slice(awaitEndPos, awaitEndPos + skipAfterUsing[0].length))) { return false } | |
| 905 | } | |
| 906 | ||
| 907 | if (isFor) { | |
| 908 | var ofEndPos = next + 2 /* of */, after$1; | |
| 909 | if (this.input.slice(next, ofEndPos) === "of") { | |
| 910 | if (ofEndPos === this.input.length || | |
| 911 | (!isIdentifierChar(after$1 = this.input.charCodeAt(ofEndPos)) && !(after$1 > 0xd7ff && after$1 < 0xdc00))) { return false } | |
| 912 | } | |
| 913 | } | |
| 914 | ||
| 915 | var ch = this.input.charCodeAt(next); | |
| 916 | return isIdentifierStart(ch, true) || ch === 92 // '\' | |
| 917 | }; | |
| 918 | ||
| 919 | pp$8.isAwaitUsing = function(isFor) { | |
| 920 | return this.isUsingKeyword(true, isFor) | |
| 921 | }; | |
| 922 | ||
| 923 | pp$8.isUsing = function(isFor) { | |
| 924 | return this.isUsingKeyword(false, isFor) | |
| 925 | }; | |
| 926 | ||
| 927 | // Parse a single statement. | |
| 928 | // | |
| 929 | // If expecting a statement and finding a slash operator, parse a | |
| 930 | // regular expression literal. This is to handle cases like | |
| 931 | // `if (foo) /blah/.exec(foo)`, where looking at the previous token | |
| 932 | // does not help. | |
| 933 | ||
| 934 | pp$8.parseStatement = function(context, topLevel, exports) { | |
| 935 | var starttype = this.type, node = this.startNode(), kind; | |
| 936 | ||
| 937 | if (this.isLet(context)) { | |
| 938 | starttype = types$1._var; | |
| 939 | kind = "let"; | |
| 940 | } | |
| 941 | ||
| 942 | // Most types of statements are recognized by the keyword they | |
| 943 | // start with. Many are trivial to parse, some require a bit of | |
| 944 | // complexity. | |
| 945 | ||
| 946 | switch (starttype) { | |
| 947 | case types$1._break: case types$1._continue: return this.parseBreakContinueStatement(node, starttype.keyword) | |
| 948 | case types$1._debugger: return this.parseDebuggerStatement(node) | |
| 949 | case types$1._do: return this.parseDoStatement(node) | |
| 950 | case types$1._for: return this.parseForStatement(node) | |
| 951 | case types$1._function: | |
| 952 | // Function as sole body of either an if statement or a labeled statement | |
| 953 | // works, but not when it is part of a labeled statement that is the sole | |
| 954 | // body of an if statement. | |
| 955 | if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); } | |
| 956 | return this.parseFunctionStatement(node, false, !context) | |
| 957 | case types$1._class: | |
| 958 | if (context) { this.unexpected(); } | |
| 959 | return this.parseClass(node, true) | |
| 960 | case types$1._if: return this.parseIfStatement(node) | |
| 961 | case types$1._return: return this.parseReturnStatement(node) | |
| 962 | case types$1._switch: return this.parseSwitchStatement(node) | |
| 963 | case types$1._throw: return this.parseThrowStatement(node) | |
| 964 | case types$1._try: return this.parseTryStatement(node) | |
| 965 | case types$1._const: case types$1._var: | |
| 966 | kind = kind || this.value; | |
| 967 | if (context && kind !== "var") { this.unexpected(); } | |
| 968 | return this.parseVarStatement(node, kind) | |
| 969 | case types$1._while: return this.parseWhileStatement(node) | |
| 970 | case types$1._with: return this.parseWithStatement(node) | |
| 971 | case types$1.braceL: return this.parseBlock(true, node) | |
| 972 | case types$1.semi: return this.parseEmptyStatement(node) | |
| 973 | case types$1._export: | |
| 974 | case types$1._import: | |
| 975 | if (this.options.ecmaVersion > 10 && starttype === types$1._import) { | |
| 976 | skipWhiteSpace.lastIndex = this.pos; | |
| 977 | var skip = skipWhiteSpace.exec(this.input); | |
| 978 | var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); | |
| 979 | if (nextCh === 40 || nextCh === 46) // '(' or '.' | |
| 980 | { return this.parseExpressionStatement(node, this.parseExpression()) } | |
| 981 | } | |
| 982 | ||
| 983 | if (!this.options.allowImportExportEverywhere) { | |
| 984 | if (!topLevel) | |
| 985 | { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } | |
| 986 | if (!this.inModule) | |
| 987 | { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } | |
| 988 | } | |
| 989 | return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports) | |
| 990 | ||
| 991 | // If the statement does not start with a statement keyword or a | |
| 992 | // brace, it's an ExpressionStatement or LabeledStatement. We | |
| 993 | // simply start parsing an expression, and afterwards, if the | |
| 994 | // next token is a colon and the expression was a simple | |
| 995 | // Identifier node, we switch to interpreting it as a label. | |
| 996 | default: | |
| 997 | if (this.isAsyncFunction()) { | |
| 998 | if (context) { this.unexpected(); } | |
| 999 | this.next(); | |
| 1000 | return this.parseFunctionStatement(node, true, !context) | |
| 1001 | } | |
| 1002 | ||
| 1003 | var usingKind = this.isAwaitUsing(false) ? "await using" : this.isUsing(false) ? "using" : null; | |
| 1004 | if (usingKind) { | |
| 1005 | if (topLevel && this.options.sourceType === "script") { | |
| 1006 | this.raise(this.start, "Using declaration cannot appear in the top level when source type is `script`"); | |
| 1007 | } | |
| 1008 | if (usingKind === "await using") { | |
| 1009 | if (!this.canAwait) { | |
| 1010 | this.raise(this.start, "Await using cannot appear outside of async function"); | |
| 1011 | } | |
| 1012 | this.next(); | |
| 1013 | } | |
| 1014 | this.next(); | |
| 1015 | this.parseVar(node, false, usingKind); | |
| 1016 | this.semicolon(); | |
| 1017 | return this.finishNode(node, "VariableDeclaration") | |
| 1018 | } | |
| 1019 | ||
| 1020 | var maybeName = this.value, expr = this.parseExpression(); | |
| 1021 | if (starttype === types$1.name && expr.type === "Identifier" && this.eat(types$1.colon)) | |
| 1022 | { return this.parseLabeledStatement(node, maybeName, expr, context) } | |
| 1023 | else { return this.parseExpressionStatement(node, expr) } | |
| 1024 | } | |
| 1025 | }; | |
| 1026 | ||
| 1027 | pp$8.parseBreakContinueStatement = function(node, keyword) { | |
| 1028 | var isBreak = keyword === "break"; | |
| 1029 | this.next(); | |
| 1030 | if (this.eat(types$1.semi) || this.insertSemicolon()) { node.label = null; } | |
| 1031 | else if (this.type !== types$1.name) { this.unexpected(); } | |
| 1032 | else { | |
| 1033 | node.label = this.parseIdent(); | |
| 1034 | this.semicolon(); | |
| 1035 | } | |
| 1036 | ||
| 1037 | // Verify that there is an actual destination to break or | |
| 1038 | // continue to. | |
| 1039 | var i = 0; | |
| 1040 | for (; i < this.labels.length; ++i) { | |
| 1041 | var lab = this.labels[i]; | |
| 1042 | if (node.label == null || lab.name === node.label.name) { | |
| 1043 | if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } | |
| 1044 | if (node.label && isBreak) { break } | |
| 1045 | } | |
| 1046 | } | |
| 1047 | if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } | |
| 1048 | return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") | |
| 1049 | }; | |
| 1050 | ||
| 1051 | pp$8.parseDebuggerStatement = function(node) { | |
| 1052 | this.next(); | |
| 1053 | this.semicolon(); | |
| 1054 | return this.finishNode(node, "DebuggerStatement") | |
| 1055 | }; | |
| 1056 | ||
| 1057 | pp$8.parseDoStatement = function(node) { | |
| 1058 | this.next(); | |
| 1059 | this.labels.push(loopLabel); | |
| 1060 | node.body = this.parseStatement("do"); | |
| 1061 | this.labels.pop(); | |
| 1062 | this.expect(types$1._while); | |
| 1063 | node.test = this.parseParenExpression(); | |
| 1064 | if (this.options.ecmaVersion >= 6) | |
| 1065 | { this.eat(types$1.semi); } | |
| 1066 | else | |
| 1067 | { this.semicolon(); } | |
| 1068 | return this.finishNode(node, "DoWhileStatement") | |
| 1069 | }; | |
| 1070 | ||
| 1071 | // Disambiguating between a `for` and a `for`/`in` or `for`/`of` | |
| 1072 | // loop is non-trivial. Basically, we have to parse the init `var` | |
| 1073 | // statement or expression, disallowing the `in` operator (see | |
| 1074 | // the second parameter to `parseExpression`), and then check | |
| 1075 | // whether the next token is `in` or `of`. When there is no init | |
| 1076 | // part (semicolon immediately after the opening parenthesis), it | |
| 1077 | // is a regular `for` loop. | |
| 1078 | ||
| 1079 | pp$8.parseForStatement = function(node) { | |
| 1080 | this.next(); | |
| 1081 | var awaitAt = (this.options.ecmaVersion >= 9 && this.canAwait && this.eatContextual("await")) ? this.lastTokStart : -1; | |
| 1082 | this.labels.push(loopLabel); | |
| 1083 | this.enterScope(0); | |
| 1084 | this.expect(types$1.parenL); | |
| 1085 | if (this.type === types$1.semi) { | |
| 1086 | if (awaitAt > -1) { this.unexpected(awaitAt); } | |
| 1087 | return this.parseFor(node, null) | |
| 1088 | } | |
| 1089 | var isLet = this.isLet(); | |
| 1090 | if (this.type === types$1._var || this.type === types$1._const || isLet) { | |
| 1091 | var init$1 = this.startNode(), kind = isLet ? "let" : this.value; | |
| 1092 | this.next(); | |
| 1093 | this.parseVar(init$1, true, kind); | |
| 1094 | this.finishNode(init$1, "VariableDeclaration"); | |
| 1095 | return this.parseForAfterInit(node, init$1, awaitAt) | |
| 1096 | } | |
| 1097 | var startsWithLet = this.isContextual("let"), isForOf = false; | |
| 1098 | ||
| 1099 | var usingKind = this.isUsing(true) ? "using" : this.isAwaitUsing(true) ? "await using" : null; | |
| 1100 | if (usingKind) { | |
| 1101 | var init$2 = this.startNode(); | |
| 1102 | this.next(); | |
| 1103 | if (usingKind === "await using") { this.next(); } | |
| 1104 | this.parseVar(init$2, true, usingKind); | |
| 1105 | this.finishNode(init$2, "VariableDeclaration"); | |
| 1106 | return this.parseForAfterInit(node, init$2, awaitAt) | |
| 1107 | } | |
| 1108 | var containsEsc = this.containsEsc; | |
| 1109 | var refDestructuringErrors = new DestructuringErrors; | |
| 1110 | var initPos = this.start; | |
| 1111 | var init = awaitAt > -1 | |
| 1112 | ? this.parseExprSubscripts(refDestructuringErrors, "await") | |
| 1113 | : this.parseExpression(true, refDestructuringErrors); | |
| 1114 | if (this.type === types$1._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) { | |
| 1115 | if (awaitAt > -1) { // implies `ecmaVersion >= 9` (see declaration of awaitAt) | |
| 1116 | if (this.type === types$1._in) { this.unexpected(awaitAt); } | |
| 1117 | node.await = true; | |
| 1118 | } else if (isForOf && this.options.ecmaVersion >= 8) { | |
| 1119 | if (init.start === initPos && !containsEsc && init.type === "Identifier" && init.name === "async") { this.unexpected(); } | |
| 1120 | else if (this.options.ecmaVersion >= 9) { node.await = false; } | |
| 1121 | } | |
| 1122 | if (startsWithLet && isForOf) { this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'."); } | |
| 1123 | this.toAssignable(init, false, refDestructuringErrors); | |
| 1124 | this.checkLValPattern(init); | |
| 1125 | return this.parseForIn(node, init) | |
| 1126 | } else { | |
| 1127 | this.checkExpressionErrors(refDestructuringErrors, true); | |
| 1128 | } | |
| 1129 | if (awaitAt > -1) { this.unexpected(awaitAt); } | |
| 1130 | return this.parseFor(node, init) | |
| 1131 | }; | |
| 1132 | ||
| 1133 | // Helper method to parse for loop after variable initialization | |
| 1134 | pp$8.parseForAfterInit = function(node, init, awaitAt) { | |
| 1135 | if ((this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1) { | |
| 1136 | if (this.options.ecmaVersion >= 9) { | |
| 1137 | if (this.type === types$1._in) { | |
| 1138 | if (awaitAt > -1) { this.unexpected(awaitAt); } | |
| 1139 | } else { node.await = awaitAt > -1; } | |
| 1140 | } | |
| 1141 | return this.parseForIn(node, init) | |
| 1142 | } | |
| 1143 | if (awaitAt > -1) { this.unexpected(awaitAt); } | |
| 1144 | return this.parseFor(node, init) | |
| 1145 | }; | |
| 1146 | ||
| 1147 | pp$8.parseFunctionStatement = function(node, isAsync, declarationPosition) { | |
| 1148 | this.next(); | |
| 1149 | return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) | |
| 1150 | }; | |
| 1151 | ||
| 1152 | pp$8.parseIfStatement = function(node) { | |
| 1153 | this.next(); | |
| 1154 | node.test = this.parseParenExpression(); | |
| 1155 | // allow function declarations in branches, but only in non-strict mode | |
| 1156 | node.consequent = this.parseStatement("if"); | |
| 1157 | node.alternate = this.eat(types$1._else) ? this.parseStatement("if") : null; | |
| 1158 | return this.finishNode(node, "IfStatement") | |
| 1159 | }; | |
| 1160 | ||
| 1161 | pp$8.parseReturnStatement = function(node) { | |
| 1162 | if (!this.inFunction && !this.options.allowReturnOutsideFunction) | |
| 1163 | { this.raise(this.start, "'return' outside of function"); } | |
| 1164 | this.next(); | |
| 1165 | ||
| 1166 | // In `return` (and `break`/`continue`), the keywords with | |
| 1167 | // optional arguments, we eagerly look for a semicolon or the | |
| 1168 | // possibility to insert one. | |
| 1169 | ||
| 1170 | if (this.eat(types$1.semi) || this.insertSemicolon()) { node.argument = null; } | |
| 1171 | else { node.argument = this.parseExpression(); this.semicolon(); } | |
| 1172 | return this.finishNode(node, "ReturnStatement") | |
| 1173 | }; | |
| 1174 | ||
| 1175 | pp$8.parseSwitchStatement = function(node) { | |
| 1176 | this.next(); | |
| 1177 | node.discriminant = this.parseParenExpression(); | |
| 1178 | node.cases = []; | |
| 1179 | this.expect(types$1.braceL); | |
| 1180 | this.labels.push(switchLabel); | |
| 1181 | this.enterScope(0); | |
| 1182 | ||
| 1183 | // Statements under must be grouped (by label) in SwitchCase | |
| 1184 | // nodes. `cur` is used to keep the node that we are currently | |
| 1185 | // adding statements to. | |
| 1186 | ||
| 1187 | var cur; | |
| 1188 | for (var sawDefault = false; this.type !== types$1.braceR;) { | |
| 1189 | if (this.type === types$1._case || this.type === types$1._default) { | |
| 1190 | var isCase = this.type === types$1._case; | |
| 1191 | if (cur) { this.finishNode(cur, "SwitchCase"); } | |
| 1192 | node.cases.push(cur = this.startNode()); | |
| 1193 | cur.consequent = []; | |
| 1194 | this.next(); | |
| 1195 | if (isCase) { | |
| 1196 | cur.test = this.parseExpression(); | |
| 1197 | } else { | |
| 1198 | if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); } | |
| 1199 | sawDefault = true; | |
| 1200 | cur.test = null; | |
| 1201 | } | |
| 1202 | this.expect(types$1.colon); | |
| 1203 | } else { | |
| 1204 | if (!cur) { this.unexpected(); } | |
| 1205 | cur.consequent.push(this.parseStatement(null)); | |
| 1206 | } | |
| 1207 | } | |
| 1208 | this.exitScope(); | |
| 1209 | if (cur) { this.finishNode(cur, "SwitchCase"); } | |
| 1210 | this.next(); // Closing brace | |
| 1211 | this.labels.pop(); | |
| 1212 | return this.finishNode(node, "SwitchStatement") | |
| 1213 | }; | |
| 1214 | ||
| 1215 | pp$8.parseThrowStatement = function(node) { | |
| 1216 | this.next(); | |
| 1217 | if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) | |
| 1218 | { this.raise(this.lastTokEnd, "Illegal newline after throw"); } | |
| 1219 | node.argument = this.parseExpression(); | |
| 1220 | this.semicolon(); | |
| 1221 | return this.finishNode(node, "ThrowStatement") | |
| 1222 | }; | |
| 1223 | ||
| 1224 | // Reused empty array added for node fields that are always empty. | |
| 1225 | ||
| 1226 | var empty$1 = []; | |
| 1227 | ||
| 1228 | pp$8.parseCatchClauseParam = function() { | |
| 1229 | var param = this.parseBindingAtom(); | |
| 1230 | var simple = param.type === "Identifier"; | |
| 1231 | this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); | |
| 1232 | this.checkLValPattern(param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); | |
| 1233 | this.expect(types$1.parenR); | |
| 1234 | ||
| 1235 | return param | |
| 1236 | }; | |
| 1237 | ||
| 1238 | pp$8.parseTryStatement = function(node) { | |
| 1239 | this.next(); | |
| 1240 | node.block = this.parseBlock(); | |
| 1241 | node.handler = null; | |
| 1242 | if (this.type === types$1._catch) { | |
| 1243 | var clause = this.startNode(); | |
| 1244 | this.next(); | |
| 1245 | if (this.eat(types$1.parenL)) { | |
| 1246 | clause.param = this.parseCatchClauseParam(); | |
| 1247 | } else { | |
| 1248 | if (this.options.ecmaVersion < 10) { this.unexpected(); } | |
| 1249 | clause.param = null; | |
| 1250 | this.enterScope(0); | |
| 1251 | } | |
| 1252 | clause.body = this.parseBlock(false); | |
| 1253 | this.exitScope(); | |
| 1254 | node.handler = this.finishNode(clause, "CatchClause"); | |
| 1255 | } | |
| 1256 | node.finalizer = this.eat(types$1._finally) ? this.parseBlock() : null; | |
| 1257 | if (!node.handler && !node.finalizer) | |
| 1258 | { this.raise(node.start, "Missing catch or finally clause"); } | |
| 1259 | return this.finishNode(node, "TryStatement") | |
| 1260 | }; | |
| 1261 | ||
| 1262 | pp$8.parseVarStatement = function(node, kind, allowMissingInitializer) { | |
| 1263 | this.next(); | |
| 1264 | this.parseVar(node, false, kind, allowMissingInitializer); | |
| 1265 | this.semicolon(); | |
| 1266 | return this.finishNode(node, "VariableDeclaration") | |
| 1267 | }; | |
| 1268 | ||
| 1269 | pp$8.parseWhileStatement = function(node) { | |
| 1270 | this.next(); | |
| 1271 | node.test = this.parseParenExpression(); | |
| 1272 | this.labels.push(loopLabel); | |
| 1273 | node.body = this.parseStatement("while"); | |
| 1274 | this.labels.pop(); | |
| 1275 | return this.finishNode(node, "WhileStatement") | |
| 1276 | }; | |
| 1277 | ||
| 1278 | pp$8.parseWithStatement = function(node) { | |
| 1279 | if (this.strict) { this.raise(this.start, "'with' in strict mode"); } | |
| 1280 | this.next(); | |
| 1281 | node.object = this.parseParenExpression(); | |
| 1282 | node.body = this.parseStatement("with"); | |
| 1283 | return this.finishNode(node, "WithStatement") | |
| 1284 | }; | |
| 1285 | ||
| 1286 | pp$8.parseEmptyStatement = function(node) { | |
| 1287 | this.next(); | |
| 1288 | return this.finishNode(node, "EmptyStatement") | |
| 1289 | }; | |
| 1290 | ||
| 1291 | pp$8.parseLabeledStatement = function(node, maybeName, expr, context) { | |
| 1292 | for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1) | |
| 1293 | { | |
| 1294 | var label = list[i$1]; | |
| 1295 | ||
| 1296 | if (label.name === maybeName) | |
| 1297 | { this.raise(expr.start, "Label '" + maybeName + "' is already declared"); | |
| 1298 | } } | |
| 1299 | var kind = this.type.isLoop ? "loop" : this.type === types$1._switch ? "switch" : null; | |
| 1300 | for (var i = this.labels.length - 1; i >= 0; i--) { | |
| 1301 | var label$1 = this.labels[i]; | |
| 1302 | if (label$1.statementStart === node.start) { | |
| 1303 | // Update information about previous labels on this node | |
| 1304 | label$1.statementStart = this.start; | |
| 1305 | label$1.kind = kind; | |
| 1306 | } else { break } | |
| 1307 | } | |
| 1308 | this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); | |
| 1309 | node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label"); | |
| 1310 | this.labels.pop(); | |
| 1311 | node.label = expr; | |
| 1312 | return this.finishNode(node, "LabeledStatement") | |
| 1313 | }; | |
| 1314 | ||
| 1315 | pp$8.parseExpressionStatement = function(node, expr) { | |
| 1316 | node.expression = expr; | |
| 1317 | this.semicolon(); | |
| 1318 | return this.finishNode(node, "ExpressionStatement") | |
| 1319 | }; | |
| 1320 | ||
| 1321 | // Parse a semicolon-enclosed block of statements, handling `"use | |
| 1322 | // strict"` declarations when `allowStrict` is true (used for | |
| 1323 | // function bodies). | |
| 1324 | ||
| 1325 | pp$8.parseBlock = function(createNewLexicalScope, node, exitStrict) { | |
| 1326 | if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; | |
| 1327 | if ( node === void 0 ) node = this.startNode(); | |
| 1328 | ||
| 1329 | node.body = []; | |
| 1330 | this.expect(types$1.braceL); | |
| 1331 | if (createNewLexicalScope) { this.enterScope(0); } | |
| 1332 | while (this.type !== types$1.braceR) { | |
| 1333 | var stmt = this.parseStatement(null); | |
| 1334 | node.body.push(stmt); | |
| 1335 | } | |
| 1336 | if (exitStrict) { this.strict = false; } | |
| 1337 | this.next(); | |
| 1338 | if (createNewLexicalScope) { this.exitScope(); } | |
| 1339 | return this.finishNode(node, "BlockStatement") | |
| 1340 | }; | |
| 1341 | ||
| 1342 | // Parse a regular `for` loop. The disambiguation code in | |
| 1343 | // `parseStatement` will already have parsed the init statement or | |
| 1344 | // expression. | |
| 1345 | ||
| 1346 | pp$8.parseFor = function(node, init) { | |
| 1347 | node.init = init; | |
| 1348 | this.expect(types$1.semi); | |
| 1349 | node.test = this.type === types$1.semi ? null : this.parseExpression(); | |
| 1350 | this.expect(types$1.semi); | |
| 1351 | node.update = this.type === types$1.parenR ? null : this.parseExpression(); | |
| 1352 | this.expect(types$1.parenR); | |
| 1353 | node.body = this.parseStatement("for"); | |
| 1354 | this.exitScope(); | |
| 1355 | this.labels.pop(); | |
| 1356 | return this.finishNode(node, "ForStatement") | |
| 1357 | }; | |
| 1358 | ||
| 1359 | // Parse a `for`/`in` and `for`/`of` loop, which are almost | |
| 1360 | // same from parser's perspective. | |
| 1361 | ||
| 1362 | pp$8.parseForIn = function(node, init) { | |
| 1363 | var isForIn = this.type === types$1._in; | |
| 1364 | this.next(); | |
| 1365 | ||
| 1366 | if ( | |
| 1367 | init.type === "VariableDeclaration" && | |
| 1368 | init.declarations[0].init != null && | |
| 1369 | ( | |
| 1370 | !isForIn || | |
| 1371 | this.options.ecmaVersion < 8 || | |
| 1372 | this.strict || | |
| 1373 | init.kind !== "var" || | |
| 1374 | init.declarations[0].id.type !== "Identifier" | |
| 1375 | ) | |
| 1376 | ) { | |
| 1377 | this.raise( | |
| 1378 | init.start, | |
| 1379 | ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer") | |
| 1380 | ); | |
| 1381 | } | |
| 1382 | node.left = init; | |
| 1383 | node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign(); | |
| 1384 | this.expect(types$1.parenR); | |
| 1385 | node.body = this.parseStatement("for"); | |
| 1386 | this.exitScope(); | |
| 1387 | this.labels.pop(); | |
| 1388 | return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement") | |
| 1389 | }; | |
| 1390 | ||
| 1391 | // Parse a list of variable declarations. | |
| 1392 | ||
| 1393 | pp$8.parseVar = function(node, isFor, kind, allowMissingInitializer) { | |
| 1394 | node.declarations = []; | |
| 1395 | node.kind = kind; | |
| 1396 | for (;;) { | |
| 1397 | var decl = this.startNode(); | |
| 1398 | this.parseVarId(decl, kind); | |
| 1399 | if (this.eat(types$1.eq)) { | |
| 1400 | decl.init = this.parseMaybeAssign(isFor); | |
| 1401 | } else if (!allowMissingInitializer && kind === "const" && !(this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { | |
| 1402 | this.unexpected(); | |
| 1403 | } else if (!allowMissingInitializer && (kind === "using" || kind === "await using") && this.options.ecmaVersion >= 17 && this.type !== types$1._in && !this.isContextual("of")) { | |
| 1404 | this.raise(this.lastTokEnd, ("Missing initializer in " + kind + " declaration")); | |
| 1405 | } else if (!allowMissingInitializer && decl.id.type !== "Identifier" && !(isFor && (this.type === types$1._in || this.isContextual("of")))) { | |
| 1406 | this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); | |
| 1407 | } else { | |
| 1408 | decl.init = null; | |
| 1409 | } | |
| 1410 | node.declarations.push(this.finishNode(decl, "VariableDeclarator")); | |
| 1411 | if (!this.eat(types$1.comma)) { break } | |
| 1412 | } | |
| 1413 | return node | |
| 1414 | }; | |
| 1415 | ||
| 1416 | pp$8.parseVarId = function(decl, kind) { | |
| 1417 | decl.id = kind === "using" || kind === "await using" | |
| 1418 | ? this.parseIdent() | |
| 1419 | : this.parseBindingAtom(); | |
| 1420 | ||
| 1421 | this.checkLValPattern(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); | |
| 1422 | }; | |
| 1423 | ||
| 1424 | var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4; | |
| 1425 | ||
| 1426 | // Parse a function declaration or literal (depending on the | |
| 1427 | // `statement & FUNC_STATEMENT`). | |
| 1428 | ||
| 1429 | // Remove `allowExpressionBody` for 7.0.0, as it is only called with false | |
| 1430 | pp$8.parseFunction = function(node, statement, allowExpressionBody, isAsync, forInit) { | |
| 1431 | this.initFunction(node); | |
| 1432 | if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { | |
| 1433 | if (this.type === types$1.star && (statement & FUNC_HANGING_STATEMENT)) | |
| 1434 | { this.unexpected(); } | |
| 1435 | node.generator = this.eat(types$1.star); | |
| 1436 | } | |
| 1437 | if (this.options.ecmaVersion >= 8) | |
| 1438 | { node.async = !!isAsync; } | |
| 1439 | ||
| 1440 | if (statement & FUNC_STATEMENT) { | |
| 1441 | node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types$1.name ? null : this.parseIdent(); | |
| 1442 | if (node.id && !(statement & FUNC_HANGING_STATEMENT)) | |
| 1443 | // If it is a regular function declaration in sloppy mode, then it is | |
| 1444 | // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding | |
| 1445 | // mode depends on properties of the current scope (see | |
| 1446 | // treatFunctionsAsVar). | |
| 1447 | { this.checkLValSimple(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); } | |
| 1448 | } | |
| 1449 | ||
| 1450 | var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
| 1451 | this.yieldPos = 0; | |
| 1452 | this.awaitPos = 0; | |
| 1453 | this.awaitIdentPos = 0; | |
| 1454 | this.enterScope(functionFlags(node.async, node.generator)); | |
| 1455 | ||
| 1456 | if (!(statement & FUNC_STATEMENT)) | |
| 1457 | { node.id = this.type === types$1.name ? this.parseIdent() : null; } | |
| 1458 | ||
| 1459 | this.parseFunctionParams(node); | |
| 1460 | this.parseFunctionBody(node, allowExpressionBody, false, forInit); | |
| 1461 | ||
| 1462 | this.yieldPos = oldYieldPos; | |
| 1463 | this.awaitPos = oldAwaitPos; | |
| 1464 | this.awaitIdentPos = oldAwaitIdentPos; | |
| 1465 | return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") | |
| 1466 | }; | |
| 1467 | ||
| 1468 | pp$8.parseFunctionParams = function(node) { | |
| 1469 | this.expect(types$1.parenL); | |
| 1470 | node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); | |
| 1471 | this.checkYieldAwaitInDefaultParams(); | |
| 1472 | }; | |
| 1473 | ||
| 1474 | // Parse a class declaration or literal (depending on the | |
| 1475 | // `isStatement` parameter). | |
| 1476 | ||
| 1477 | pp$8.parseClass = function(node, isStatement) { | |
| 1478 | this.next(); | |
| 1479 | ||
| 1480 | // ecma-262 14.6 Class Definitions | |
| 1481 | // A class definition is always strict mode code. | |
| 1482 | var oldStrict = this.strict; | |
| 1483 | this.strict = true; | |
| 1484 | ||
| 1485 | this.parseClassId(node, isStatement); | |
| 1486 | this.parseClassSuper(node); | |
| 1487 | var privateNameMap = this.enterClassBody(); | |
| 1488 | var classBody = this.startNode(); | |
| 1489 | var hadConstructor = false; | |
| 1490 | classBody.body = []; | |
| 1491 | this.expect(types$1.braceL); | |
| 1492 | while (this.type !== types$1.braceR) { | |
| 1493 | var element = this.parseClassElement(node.superClass !== null); | |
| 1494 | if (element) { | |
| 1495 | classBody.body.push(element); | |
| 1496 | if (element.type === "MethodDefinition" && element.kind === "constructor") { | |
| 1497 | if (hadConstructor) { this.raiseRecoverable(element.start, "Duplicate constructor in the same class"); } | |
| 1498 | hadConstructor = true; | |
| 1499 | } else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) { | |
| 1500 | this.raiseRecoverable(element.key.start, ("Identifier '#" + (element.key.name) + "' has already been declared")); | |
| 1501 | } | |
| 1502 | } | |
| 1503 | } | |
| 1504 | this.strict = oldStrict; | |
| 1505 | this.next(); | |
| 1506 | node.body = this.finishNode(classBody, "ClassBody"); | |
| 1507 | this.exitClassBody(); | |
| 1508 | return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") | |
| 1509 | }; | |
| 1510 | ||
| 1511 | pp$8.parseClassElement = function(constructorAllowsSuper) { | |
| 1512 | if (this.eat(types$1.semi)) { return null } | |
| 1513 | ||
| 1514 | var ecmaVersion = this.options.ecmaVersion; | |
| 1515 | var node = this.startNode(); | |
| 1516 | var keyName = ""; | |
| 1517 | var isGenerator = false; | |
| 1518 | var isAsync = false; | |
| 1519 | var kind = "method"; | |
| 1520 | var isStatic = false; | |
| 1521 | ||
| 1522 | if (this.eatContextual("static")) { | |
| 1523 | // Parse static init block | |
| 1524 | if (ecmaVersion >= 13 && this.eat(types$1.braceL)) { | |
| 1525 | this.parseClassStaticBlock(node); | |
| 1526 | return node | |
| 1527 | } | |
| 1528 | if (this.isClassElementNameStart() || this.type === types$1.star) { | |
| 1529 | isStatic = true; | |
| 1530 | } else { | |
| 1531 | keyName = "static"; | |
| 1532 | } | |
| 1533 | } | |
| 1534 | node.static = isStatic; | |
| 1535 | if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) { | |
| 1536 | if ((this.isClassElementNameStart() || this.type === types$1.star) && !this.canInsertSemicolon()) { | |
| 1537 | isAsync = true; | |
| 1538 | } else { | |
| 1539 | keyName = "async"; | |
| 1540 | } | |
| 1541 | } | |
| 1542 | if (!keyName && (ecmaVersion >= 9 || !isAsync) && this.eat(types$1.star)) { | |
| 1543 | isGenerator = true; | |
| 1544 | } | |
| 1545 | if (!keyName && !isAsync && !isGenerator) { | |
| 1546 | var lastValue = this.value; | |
| 1547 | if (this.eatContextual("get") || this.eatContextual("set")) { | |
| 1548 | if (this.isClassElementNameStart()) { | |
| 1549 | kind = lastValue; | |
| 1550 | } else { | |
| 1551 | keyName = lastValue; | |
| 1552 | } | |
| 1553 | } | |
| 1554 | } | |
| 1555 | ||
| 1556 | // Parse element name | |
| 1557 | if (keyName) { | |
| 1558 | // 'async', 'get', 'set', or 'static' were not a keyword contextually. | |
| 1559 | // The last token is any of those. Make it the element name. | |
| 1560 | node.computed = false; | |
| 1561 | node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); | |
| 1562 | node.key.name = keyName; | |
| 1563 | this.finishNode(node.key, "Identifier"); | |
| 1564 | } else { | |
| 1565 | this.parseClassElementName(node); | |
| 1566 | } | |
| 1567 | ||
| 1568 | // Parse element value | |
| 1569 | if (ecmaVersion < 13 || this.type === types$1.parenL || kind !== "method" || isGenerator || isAsync) { | |
| 1570 | var isConstructor = !node.static && checkKeyName(node, "constructor"); | |
| 1571 | var allowsDirectSuper = isConstructor && constructorAllowsSuper; | |
| 1572 | // Couldn't move this check into the 'parseClassMethod' method for backward compatibility. | |
| 1573 | if (isConstructor && kind !== "method") { this.raise(node.key.start, "Constructor can't have get/set modifier"); } | |
| 1574 | node.kind = isConstructor ? "constructor" : kind; | |
| 1575 | this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper); | |
| 1576 | } else { | |
| 1577 | this.parseClassField(node); | |
| 1578 | } | |
| 1579 | ||
| 1580 | return node | |
| 1581 | }; | |
| 1582 | ||
| 1583 | pp$8.isClassElementNameStart = function() { | |
| 1584 | return ( | |
| 1585 | this.type === types$1.name || | |
| 1586 | this.type === types$1.privateId || | |
| 1587 | this.type === types$1.num || | |
| 1588 | this.type === types$1.string || | |
| 1589 | this.type === types$1.bracketL || | |
| 1590 | this.type.keyword | |
| 1591 | ) | |
| 1592 | }; | |
| 1593 | ||
| 1594 | pp$8.parseClassElementName = function(element) { | |
| 1595 | if (this.type === types$1.privateId) { | |
| 1596 | if (this.value === "constructor") { | |
| 1597 | this.raise(this.start, "Classes can't have an element named '#constructor'"); | |
| 1598 | } | |
| 1599 | element.computed = false; | |
| 1600 | element.key = this.parsePrivateIdent(); | |
| 1601 | } else { | |
| 1602 | this.parsePropertyName(element); | |
| 1603 | } | |
| 1604 | }; | |
| 1605 | ||
| 1606 | pp$8.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) { | |
| 1607 | // Check key and flags | |
| 1608 | var key = method.key; | |
| 1609 | if (method.kind === "constructor") { | |
| 1610 | if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } | |
| 1611 | if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } | |
| 1612 | } else if (method.static && checkKeyName(method, "prototype")) { | |
| 1613 | this.raise(key.start, "Classes may not have a static property named prototype"); | |
| 1614 | } | |
| 1615 | ||
| 1616 | // Parse value | |
| 1617 | var value = method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); | |
| 1618 | ||
| 1619 | // Check value | |
| 1620 | if (method.kind === "get" && value.params.length !== 0) | |
| 1621 | { this.raiseRecoverable(value.start, "getter should have no params"); } | |
| 1622 | if (method.kind === "set" && value.params.length !== 1) | |
| 1623 | { this.raiseRecoverable(value.start, "setter should have exactly one param"); } | |
| 1624 | if (method.kind === "set" && value.params[0].type === "RestElement") | |
| 1625 | { this.raiseRecoverable(value.params[0].start, "Setter cannot use rest params"); } | |
| 1626 | ||
| 1627 | return this.finishNode(method, "MethodDefinition") | |
| 1628 | }; | |
| 1629 | ||
| 1630 | pp$8.parseClassField = function(field) { | |
| 1631 | if (checkKeyName(field, "constructor")) { | |
| 1632 | this.raise(field.key.start, "Classes can't have a field named 'constructor'"); | |
| 1633 | } else if (field.static && checkKeyName(field, "prototype")) { | |
| 1634 | this.raise(field.key.start, "Classes can't have a static field named 'prototype'"); | |
| 1635 | } | |
| 1636 | ||
| 1637 | if (this.eat(types$1.eq)) { | |
| 1638 | // To raise SyntaxError if 'arguments' exists in the initializer. | |
| 1639 | this.enterScope(SCOPE_CLASS_FIELD_INIT | SCOPE_SUPER); | |
| 1640 | field.value = this.parseMaybeAssign(); | |
| 1641 | this.exitScope(); | |
| 1642 | } else { | |
| 1643 | field.value = null; | |
| 1644 | } | |
| 1645 | this.semicolon(); | |
| 1646 | ||
| 1647 | return this.finishNode(field, "PropertyDefinition") | |
| 1648 | }; | |
| 1649 | ||
| 1650 | pp$8.parseClassStaticBlock = function(node) { | |
| 1651 | node.body = []; | |
| 1652 | ||
| 1653 | var oldLabels = this.labels; | |
| 1654 | this.labels = []; | |
| 1655 | this.enterScope(SCOPE_CLASS_STATIC_BLOCK | SCOPE_SUPER); | |
| 1656 | while (this.type !== types$1.braceR) { | |
| 1657 | var stmt = this.parseStatement(null); | |
| 1658 | node.body.push(stmt); | |
| 1659 | } | |
| 1660 | this.next(); | |
| 1661 | this.exitScope(); | |
| 1662 | this.labels = oldLabels; | |
| 1663 | ||
| 1664 | return this.finishNode(node, "StaticBlock") | |
| 1665 | }; | |
| 1666 | ||
| 1667 | pp$8.parseClassId = function(node, isStatement) { | |
| 1668 | if (this.type === types$1.name) { | |
| 1669 | node.id = this.parseIdent(); | |
| 1670 | if (isStatement) | |
| 1671 | { this.checkLValSimple(node.id, BIND_LEXICAL, false); } | |
| 1672 | } else { | |
| 1673 | if (isStatement === true) | |
| 1674 | { this.unexpected(); } | |
| 1675 | node.id = null; | |
| 1676 | } | |
| 1677 | }; | |
| 1678 | ||
| 1679 | pp$8.parseClassSuper = function(node) { | |
| 1680 | node.superClass = this.eat(types$1._extends) ? this.parseExprSubscripts(null, false) : null; | |
| 1681 | }; | |
| 1682 | ||
| 1683 | pp$8.enterClassBody = function() { | |
| 1684 | var element = {declared: Object.create(null), used: []}; | |
| 1685 | this.privateNameStack.push(element); | |
| 1686 | return element.declared | |
| 1687 | }; | |
| 1688 | ||
| 1689 | pp$8.exitClassBody = function() { | |
| 1690 | var ref = this.privateNameStack.pop(); | |
| 1691 | var declared = ref.declared; | |
| 1692 | var used = ref.used; | |
| 1693 | if (!this.options.checkPrivateFields) { return } | |
| 1694 | var len = this.privateNameStack.length; | |
| 1695 | var parent = len === 0 ? null : this.privateNameStack[len - 1]; | |
| 1696 | for (var i = 0; i < used.length; ++i) { | |
| 1697 | var id = used[i]; | |
| 1698 | if (!hasOwn(declared, id.name)) { | |
| 1699 | if (parent) { | |
| 1700 | parent.used.push(id); | |
| 1701 | } else { | |
| 1702 | this.raiseRecoverable(id.start, ("Private field '#" + (id.name) + "' must be declared in an enclosing class")); | |
| 1703 | } | |
| 1704 | } | |
| 1705 | } | |
| 1706 | }; | |
| 1707 | ||
| 1708 | function isPrivateNameConflicted(privateNameMap, element) { | |
| 1709 | var name = element.key.name; | |
| 1710 | var curr = privateNameMap[name]; | |
| 1711 | ||
| 1712 | var next = "true"; | |
| 1713 | if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) { | |
| 1714 | next = (element.static ? "s" : "i") + element.kind; | |
| 1715 | } | |
| 1716 | ||
| 1717 | // `class { get #a(){}; static set #a(_){} }` is also conflict. | |
| 1718 | if ( | |
| 1719 | curr === "iget" && next === "iset" || | |
| 1720 | curr === "iset" && next === "iget" || | |
| 1721 | curr === "sget" && next === "sset" || | |
| 1722 | curr === "sset" && next === "sget" | |
| 1723 | ) { | |
| 1724 | privateNameMap[name] = "true"; | |
| 1725 | return false | |
| 1726 | } else if (!curr) { | |
| 1727 | privateNameMap[name] = next; | |
| 1728 | return false | |
| 1729 | } else { | |
| 1730 | return true | |
| 1731 | } | |
| 1732 | } | |
| 1733 | ||
| 1734 | function checkKeyName(node, name) { | |
| 1735 | var computed = node.computed; | |
| 1736 | var key = node.key; | |
| 1737 | return !computed && ( | |
| 1738 | key.type === "Identifier" && key.name === name || | |
| 1739 | key.type === "Literal" && key.value === name | |
| 1740 | ) | |
| 1741 | } | |
| 1742 | ||
| 1743 | // Parses module export declaration. | |
| 1744 | ||
| 1745 | pp$8.parseExportAllDeclaration = function(node, exports) { | |
| 1746 | if (this.options.ecmaVersion >= 11) { | |
| 1747 | if (this.eatContextual("as")) { | |
| 1748 | node.exported = this.parseModuleExportName(); | |
| 1749 | this.checkExport(exports, node.exported, this.lastTokStart); | |
| 1750 | } else { | |
| 1751 | node.exported = null; | |
| 1752 | } | |
| 1753 | } | |
| 1754 | this.expectContextual("from"); | |
| 1755 | if (this.type !== types$1.string) { this.unexpected(); } | |
| 1756 | node.source = this.parseExprAtom(); | |
| 1757 | if (this.options.ecmaVersion >= 16) | |
| 1758 | { node.attributes = this.parseWithClause(); } | |
| 1759 | this.semicolon(); | |
| 1760 | return this.finishNode(node, "ExportAllDeclaration") | |
| 1761 | }; | |
| 1762 | ||
| 1763 | pp$8.parseExport = function(node, exports) { | |
| 1764 | this.next(); | |
| 1765 | // export * from '...' | |
| 1766 | if (this.eat(types$1.star)) { | |
| 1767 | return this.parseExportAllDeclaration(node, exports) | |
| 1768 | } | |
| 1769 | if (this.eat(types$1._default)) { // export default ... | |
| 1770 | this.checkExport(exports, "default", this.lastTokStart); | |
| 1771 | node.declaration = this.parseExportDefaultDeclaration(); | |
| 1772 | return this.finishNode(node, "ExportDefaultDeclaration") | |
| 1773 | } | |
| 1774 | // export var|const|let|function|class ... | |
| 1775 | if (this.shouldParseExportStatement()) { | |
| 1776 | node.declaration = this.parseExportDeclaration(node); | |
| 1777 | if (node.declaration.type === "VariableDeclaration") | |
| 1778 | { this.checkVariableExport(exports, node.declaration.declarations); } | |
| 1779 | else | |
| 1780 | { this.checkExport(exports, node.declaration.id, node.declaration.id.start); } | |
| 1781 | node.specifiers = []; | |
| 1782 | node.source = null; | |
| 1783 | if (this.options.ecmaVersion >= 16) | |
| 1784 | { node.attributes = []; } | |
| 1785 | } else { // export { x, y as z } [from '...'] | |
| 1786 | node.declaration = null; | |
| 1787 | node.specifiers = this.parseExportSpecifiers(exports); | |
| 1788 | if (this.eatContextual("from")) { | |
| 1789 | if (this.type !== types$1.string) { this.unexpected(); } | |
| 1790 | node.source = this.parseExprAtom(); | |
| 1791 | if (this.options.ecmaVersion >= 16) | |
| 1792 | { node.attributes = this.parseWithClause(); } | |
| 1793 | } else { | |
| 1794 | for (var i = 0, list = node.specifiers; i < list.length; i += 1) { | |
| 1795 | // check for keywords used as local names | |
| 1796 | var spec = list[i]; | |
| 1797 | ||
| 1798 | this.checkUnreserved(spec.local); | |
| 1799 | // check if export is defined | |
| 1800 | this.checkLocalExport(spec.local); | |
| 1801 | ||
| 1802 | if (spec.local.type === "Literal") { | |
| 1803 | this.raise(spec.local.start, "A string literal cannot be used as an exported binding without `from`."); | |
| 1804 | } | |
| 1805 | } | |
| 1806 | ||
| 1807 | node.source = null; | |
| 1808 | if (this.options.ecmaVersion >= 16) | |
| 1809 | { node.attributes = []; } | |
| 1810 | } | |
| 1811 | this.semicolon(); | |
| 1812 | } | |
| 1813 | return this.finishNode(node, "ExportNamedDeclaration") | |
| 1814 | }; | |
| 1815 | ||
| 1816 | pp$8.parseExportDeclaration = function(node) { | |
| 1817 | return this.parseStatement(null) | |
| 1818 | }; | |
| 1819 | ||
| 1820 | pp$8.parseExportDefaultDeclaration = function() { | |
| 1821 | var isAsync; | |
| 1822 | if (this.type === types$1._function || (isAsync = this.isAsyncFunction())) { | |
| 1823 | var fNode = this.startNode(); | |
| 1824 | this.next(); | |
| 1825 | if (isAsync) { this.next(); } | |
| 1826 | return this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync) | |
| 1827 | } else if (this.type === types$1._class) { | |
| 1828 | var cNode = this.startNode(); | |
| 1829 | return this.parseClass(cNode, "nullableID") | |
| 1830 | } else { | |
| 1831 | var declaration = this.parseMaybeAssign(); | |
| 1832 | this.semicolon(); | |
| 1833 | return declaration | |
| 1834 | } | |
| 1835 | }; | |
| 1836 | ||
| 1837 | pp$8.checkExport = function(exports, name, pos) { | |
| 1838 | if (!exports) { return } | |
| 1839 | if (typeof name !== "string") | |
| 1840 | { name = name.type === "Identifier" ? name.name : name.value; } | |
| 1841 | if (hasOwn(exports, name)) | |
| 1842 | { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } | |
| 1843 | exports[name] = true; | |
| 1844 | }; | |
| 1845 | ||
| 1846 | pp$8.checkPatternExport = function(exports, pat) { | |
| 1847 | var type = pat.type; | |
| 1848 | if (type === "Identifier") | |
| 1849 | { this.checkExport(exports, pat, pat.start); } | |
| 1850 | else if (type === "ObjectPattern") | |
| 1851 | { for (var i = 0, list = pat.properties; i < list.length; i += 1) | |
| 1852 | { | |
| 1853 | var prop = list[i]; | |
| 1854 | ||
| 1855 | this.checkPatternExport(exports, prop); | |
| 1856 | } } | |
| 1857 | else if (type === "ArrayPattern") | |
| 1858 | { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { | |
| 1859 | var elt = list$1[i$1]; | |
| 1860 | ||
| 1861 | if (elt) { this.checkPatternExport(exports, elt); } | |
| 1862 | } } | |
| 1863 | else if (type === "Property") | |
| 1864 | { this.checkPatternExport(exports, pat.value); } | |
| 1865 | else if (type === "AssignmentPattern") | |
| 1866 | { this.checkPatternExport(exports, pat.left); } | |
| 1867 | else if (type === "RestElement") | |
| 1868 | { this.checkPatternExport(exports, pat.argument); } | |
| 1869 | }; | |
| 1870 | ||
| 1871 | pp$8.checkVariableExport = function(exports, decls) { | |
| 1872 | if (!exports) { return } | |
| 1873 | for (var i = 0, list = decls; i < list.length; i += 1) | |
| 1874 | { | |
| 1875 | var decl = list[i]; | |
| 1876 | ||
| 1877 | this.checkPatternExport(exports, decl.id); | |
| 1878 | } | |
| 1879 | }; | |
| 1880 | ||
| 1881 | pp$8.shouldParseExportStatement = function() { | |
| 1882 | return this.type.keyword === "var" || | |
| 1883 | this.type.keyword === "const" || | |
| 1884 | this.type.keyword === "class" || | |
| 1885 | this.type.keyword === "function" || | |
| 1886 | this.isLet() || | |
| 1887 | this.isAsyncFunction() | |
| 1888 | }; | |
| 1889 | ||
| 1890 | // Parses a comma-separated list of module exports. | |
| 1891 | ||
| 1892 | pp$8.parseExportSpecifier = function(exports) { | |
| 1893 | var node = this.startNode(); | |
| 1894 | node.local = this.parseModuleExportName(); | |
| 1895 | ||
| 1896 | node.exported = this.eatContextual("as") ? this.parseModuleExportName() : node.local; | |
| 1897 | this.checkExport( | |
| 1898 | exports, | |
| 1899 | node.exported, | |
| 1900 | node.exported.start | |
| 1901 | ); | |
| 1902 | ||
| 1903 | return this.finishNode(node, "ExportSpecifier") | |
| 1904 | }; | |
| 1905 | ||
| 1906 | pp$8.parseExportSpecifiers = function(exports) { | |
| 1907 | var nodes = [], first = true; | |
| 1908 | // export { x, y as z } [from '...'] | |
| 1909 | this.expect(types$1.braceL); | |
| 1910 | while (!this.eat(types$1.braceR)) { | |
| 1911 | if (!first) { | |
| 1912 | this.expect(types$1.comma); | |
| 1913 | if (this.afterTrailingComma(types$1.braceR)) { break } | |
| 1914 | } else { first = false; } | |
| 1915 | ||
| 1916 | nodes.push(this.parseExportSpecifier(exports)); | |
| 1917 | } | |
| 1918 | return nodes | |
| 1919 | }; | |
| 1920 | ||
| 1921 | // Parses import declaration. | |
| 1922 | ||
| 1923 | pp$8.parseImport = function(node) { | |
| 1924 | this.next(); | |
| 1925 | ||
| 1926 | // import '...' | |
| 1927 | if (this.type === types$1.string) { | |
| 1928 | node.specifiers = empty$1; | |
| 1929 | node.source = this.parseExprAtom(); | |
| 1930 | } else { | |
| 1931 | node.specifiers = this.parseImportSpecifiers(); | |
| 1932 | this.expectContextual("from"); | |
| 1933 | node.source = this.type === types$1.string ? this.parseExprAtom() : this.unexpected(); | |
| 1934 | } | |
| 1935 | if (this.options.ecmaVersion >= 16) | |
| 1936 | { node.attributes = this.parseWithClause(); } | |
| 1937 | this.semicolon(); | |
| 1938 | return this.finishNode(node, "ImportDeclaration") | |
| 1939 | }; | |
| 1940 | ||
| 1941 | // Parses a comma-separated list of module imports. | |
| 1942 | ||
| 1943 | pp$8.parseImportSpecifier = function() { | |
| 1944 | var node = this.startNode(); | |
| 1945 | node.imported = this.parseModuleExportName(); | |
| 1946 | ||
| 1947 | if (this.eatContextual("as")) { | |
| 1948 | node.local = this.parseIdent(); | |
| 1949 | } else { | |
| 1950 | this.checkUnreserved(node.imported); | |
| 1951 | node.local = node.imported; | |
| 1952 | } | |
| 1953 | this.checkLValSimple(node.local, BIND_LEXICAL); | |
| 1954 | ||
| 1955 | return this.finishNode(node, "ImportSpecifier") | |
| 1956 | }; | |
| 1957 | ||
| 1958 | pp$8.parseImportDefaultSpecifier = function() { | |
| 1959 | // import defaultObj, { x, y as z } from '...' | |
| 1960 | var node = this.startNode(); | |
| 1961 | node.local = this.parseIdent(); | |
| 1962 | this.checkLValSimple(node.local, BIND_LEXICAL); | |
| 1963 | return this.finishNode(node, "ImportDefaultSpecifier") | |
| 1964 | }; | |
| 1965 | ||
| 1966 | pp$8.parseImportNamespaceSpecifier = function() { | |
| 1967 | var node = this.startNode(); | |
| 1968 | this.next(); | |
| 1969 | this.expectContextual("as"); | |
| 1970 | node.local = this.parseIdent(); | |
| 1971 | this.checkLValSimple(node.local, BIND_LEXICAL); | |
| 1972 | return this.finishNode(node, "ImportNamespaceSpecifier") | |
| 1973 | }; | |
| 1974 | ||
| 1975 | pp$8.parseImportSpecifiers = function() { | |
| 1976 | var nodes = [], first = true; | |
| 1977 | if (this.type === types$1.name) { | |
| 1978 | nodes.push(this.parseImportDefaultSpecifier()); | |
| 1979 | if (!this.eat(types$1.comma)) { return nodes } | |
| 1980 | } | |
| 1981 | if (this.type === types$1.star) { | |
| 1982 | nodes.push(this.parseImportNamespaceSpecifier()); | |
| 1983 | return nodes | |
| 1984 | } | |
| 1985 | this.expect(types$1.braceL); | |
| 1986 | while (!this.eat(types$1.braceR)) { | |
| 1987 | if (!first) { | |
| 1988 | this.expect(types$1.comma); | |
| 1989 | if (this.afterTrailingComma(types$1.braceR)) { break } | |
| 1990 | } else { first = false; } | |
| 1991 | ||
| 1992 | nodes.push(this.parseImportSpecifier()); | |
| 1993 | } | |
| 1994 | return nodes | |
| 1995 | }; | |
| 1996 | ||
| 1997 | pp$8.parseWithClause = function() { | |
| 1998 | var nodes = []; | |
| 1999 | if (!this.eat(types$1._with)) { | |
| 2000 | return nodes | |
| 2001 | } | |
| 2002 | this.expect(types$1.braceL); | |
| 2003 | var attributeKeys = {}; | |
| 2004 | var first = true; | |
| 2005 | while (!this.eat(types$1.braceR)) { | |
| 2006 | if (!first) { | |
| 2007 | this.expect(types$1.comma); | |
| 2008 | if (this.afterTrailingComma(types$1.braceR)) { break } | |
| 2009 | } else { first = false; } | |
| 2010 | ||
| 2011 | var attr = this.parseImportAttribute(); | |
| 2012 | var keyName = attr.key.type === "Identifier" ? attr.key.name : attr.key.value; | |
| 2013 | if (hasOwn(attributeKeys, keyName)) | |
| 2014 | { this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" + keyName + "'"); } | |
| 2015 | attributeKeys[keyName] = true; | |
| 2016 | nodes.push(attr); | |
| 2017 | } | |
| 2018 | return nodes | |
| 2019 | }; | |
| 2020 | ||
| 2021 | pp$8.parseImportAttribute = function() { | |
| 2022 | var node = this.startNode(); | |
| 2023 | node.key = this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never"); | |
| 2024 | this.expect(types$1.colon); | |
| 2025 | if (this.type !== types$1.string) { | |
| 2026 | this.unexpected(); | |
| 2027 | } | |
| 2028 | node.value = this.parseExprAtom(); | |
| 2029 | return this.finishNode(node, "ImportAttribute") | |
| 2030 | }; | |
| 2031 | ||
| 2032 | pp$8.parseModuleExportName = function() { | |
| 2033 | if (this.options.ecmaVersion >= 13 && this.type === types$1.string) { | |
| 2034 | var stringLiteral = this.parseLiteral(this.value); | |
| 2035 | if (loneSurrogate.test(stringLiteral.value)) { | |
| 2036 | this.raise(stringLiteral.start, "An export name cannot include a lone surrogate."); | |
| 2037 | } | |
| 2038 | return stringLiteral | |
| 2039 | } | |
| 2040 | return this.parseIdent(true) | |
| 2041 | }; | |
| 2042 | ||
| 2043 | // Set `ExpressionStatement#directive` property for directive prologues. | |
| 2044 | pp$8.adaptDirectivePrologue = function(statements) { | |
| 2045 | for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { | |
| 2046 | statements[i].directive = statements[i].expression.raw.slice(1, -1); | |
| 2047 | } | |
| 2048 | }; | |
| 2049 | pp$8.isDirectiveCandidate = function(statement) { | |
| 2050 | return ( | |
| 2051 | this.options.ecmaVersion >= 5 && | |
| 2052 | statement.type === "ExpressionStatement" && | |
| 2053 | statement.expression.type === "Literal" && | |
| 2054 | typeof statement.expression.value === "string" && | |
| 2055 | // Reject parenthesized strings. | |
| 2056 | (this.input[statement.start] === "\"" || this.input[statement.start] === "'") | |
| 2057 | ) | |
| 2058 | }; | |
| 2059 | ||
| 2060 | var pp$7 = Parser.prototype; | |
| 2061 | ||
| 2062 | // Convert existing expression atom to assignable pattern | |
| 2063 | // if possible. | |
| 2064 | ||
| 2065 | pp$7.toAssignable = function(node, isBinding, refDestructuringErrors) { | |
| 2066 | if (this.options.ecmaVersion >= 6 && node) { | |
| 2067 | switch (node.type) { | |
| 2068 | case "Identifier": | |
| 2069 | if (this.inAsync && node.name === "await") | |
| 2070 | { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); } | |
| 2071 | break | |
| 2072 | ||
| 2073 | case "ObjectPattern": | |
| 2074 | case "ArrayPattern": | |
| 2075 | case "AssignmentPattern": | |
| 2076 | case "RestElement": | |
| 2077 | break | |
| 2078 | ||
| 2079 | case "ObjectExpression": | |
| 2080 | node.type = "ObjectPattern"; | |
| 2081 | if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
| 2082 | for (var i = 0, list = node.properties; i < list.length; i += 1) { | |
| 2083 | var prop = list[i]; | |
| 2084 | ||
| 2085 | this.toAssignable(prop, isBinding); | |
| 2086 | // Early error: | |
| 2087 | // AssignmentRestProperty[Yield, Await] : | |
| 2088 | // `...` DestructuringAssignmentTarget[Yield, Await] | |
| 2089 | // | |
| 2090 | // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. | |
| 2091 | if ( | |
| 2092 | prop.type === "RestElement" && | |
| 2093 | (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") | |
| 2094 | ) { | |
| 2095 | this.raise(prop.argument.start, "Unexpected token"); | |
| 2096 | } | |
| 2097 | } | |
| 2098 | break | |
| 2099 | ||
| 2100 | case "Property": | |
| 2101 | // AssignmentProperty has type === "Property" | |
| 2102 | if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } | |
| 2103 | this.toAssignable(node.value, isBinding); | |
| 2104 | break | |
| 2105 | ||
| 2106 | case "ArrayExpression": | |
| 2107 | node.type = "ArrayPattern"; | |
| 2108 | if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
| 2109 | this.toAssignableList(node.elements, isBinding); | |
| 2110 | break | |
| 2111 | ||
| 2112 | case "SpreadElement": | |
| 2113 | node.type = "RestElement"; | |
| 2114 | this.toAssignable(node.argument, isBinding); | |
| 2115 | if (node.argument.type === "AssignmentPattern") | |
| 2116 | { this.raise(node.argument.start, "Rest elements cannot have a default value"); } | |
| 2117 | break | |
| 2118 | ||
| 2119 | case "AssignmentExpression": | |
| 2120 | if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } | |
| 2121 | node.type = "AssignmentPattern"; | |
| 2122 | delete node.operator; | |
| 2123 | this.toAssignable(node.left, isBinding); | |
| 2124 | break | |
| 2125 | ||
| 2126 | case "ParenthesizedExpression": | |
| 2127 | this.toAssignable(node.expression, isBinding, refDestructuringErrors); | |
| 2128 | break | |
| 2129 | ||
| 2130 | case "ChainExpression": | |
| 2131 | this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side"); | |
| 2132 | break | |
| 2133 | ||
| 2134 | case "MemberExpression": | |
| 2135 | if (!isBinding) { break } | |
| 2136 | ||
| 2137 | default: | |
| 2138 | this.raise(node.start, "Assigning to rvalue"); | |
| 2139 | } | |
| 2140 | } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } | |
| 2141 | return node | |
| 2142 | }; | |
| 2143 | ||
| 2144 | // Convert list of expression atoms to binding list. | |
| 2145 | ||
| 2146 | pp$7.toAssignableList = function(exprList, isBinding) { | |
| 2147 | var end = exprList.length; | |
| 2148 | for (var i = 0; i < end; i++) { | |
| 2149 | var elt = exprList[i]; | |
| 2150 | if (elt) { this.toAssignable(elt, isBinding); } | |
| 2151 | } | |
| 2152 | if (end) { | |
| 2153 | var last = exprList[end - 1]; | |
| 2154 | if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") | |
| 2155 | { this.unexpected(last.argument.start); } | |
| 2156 | } | |
| 2157 | return exprList | |
| 2158 | }; | |
| 2159 | ||
| 2160 | // Parses spread element. | |
| 2161 | ||
| 2162 | pp$7.parseSpread = function(refDestructuringErrors) { | |
| 2163 | var node = this.startNode(); | |
| 2164 | this.next(); | |
| 2165 | node.argument = this.parseMaybeAssign(false, refDestructuringErrors); | |
| 2166 | return this.finishNode(node, "SpreadElement") | |
| 2167 | }; | |
| 2168 | ||
| 2169 | pp$7.parseRestBinding = function() { | |
| 2170 | var node = this.startNode(); | |
| 2171 | this.next(); | |
| 2172 | ||
| 2173 | // RestElement inside of a function parameter must be an identifier | |
| 2174 | if (this.options.ecmaVersion === 6 && this.type !== types$1.name) | |
| 2175 | { this.unexpected(); } | |
| 2176 | ||
| 2177 | node.argument = this.parseBindingAtom(); | |
| 2178 | ||
| 2179 | return this.finishNode(node, "RestElement") | |
| 2180 | }; | |
| 2181 | ||
| 2182 | // Parses lvalue (assignable) atom. | |
| 2183 | ||
| 2184 | pp$7.parseBindingAtom = function() { | |
| 2185 | if (this.options.ecmaVersion >= 6) { | |
| 2186 | switch (this.type) { | |
| 2187 | case types$1.bracketL: | |
| 2188 | var node = this.startNode(); | |
| 2189 | this.next(); | |
| 2190 | node.elements = this.parseBindingList(types$1.bracketR, true, true); | |
| 2191 | return this.finishNode(node, "ArrayPattern") | |
| 2192 | ||
| 2193 | case types$1.braceL: | |
| 2194 | return this.parseObj(true) | |
| 2195 | } | |
| 2196 | } | |
| 2197 | return this.parseIdent() | |
| 2198 | }; | |
| 2199 | ||
| 2200 | pp$7.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowModifiers) { | |
| 2201 | var elts = [], first = true; | |
| 2202 | while (!this.eat(close)) { | |
| 2203 | if (first) { first = false; } | |
| 2204 | else { this.expect(types$1.comma); } | |
| 2205 | if (allowEmpty && this.type === types$1.comma) { | |
| 2206 | elts.push(null); | |
| 2207 | } else if (allowTrailingComma && this.afterTrailingComma(close)) { | |
| 2208 | break | |
| 2209 | } else if (this.type === types$1.ellipsis) { | |
| 2210 | var rest = this.parseRestBinding(); | |
| 2211 | this.parseBindingListItem(rest); | |
| 2212 | elts.push(rest); | |
| 2213 | if (this.type === types$1.comma) { this.raiseRecoverable(this.start, "Comma is not permitted after the rest element"); } | |
| 2214 | this.expect(close); | |
| 2215 | break | |
| 2216 | } else { | |
| 2217 | elts.push(this.parseAssignableListItem(allowModifiers)); | |
| 2218 | } | |
| 2219 | } | |
| 2220 | return elts | |
| 2221 | }; | |
| 2222 | ||
| 2223 | pp$7.parseAssignableListItem = function(allowModifiers) { | |
| 2224 | var elem = this.parseMaybeDefault(this.start, this.startLoc); | |
| 2225 | this.parseBindingListItem(elem); | |
| 2226 | return elem | |
| 2227 | }; | |
| 2228 | ||
| 2229 | pp$7.parseBindingListItem = function(param) { | |
| 2230 | return param | |
| 2231 | }; | |
| 2232 | ||
| 2233 | // Parses assignment pattern around given atom if possible. | |
| 2234 | ||
| 2235 | pp$7.parseMaybeDefault = function(startPos, startLoc, left) { | |
| 2236 | left = left || this.parseBindingAtom(); | |
| 2237 | if (this.options.ecmaVersion < 6 || !this.eat(types$1.eq)) { return left } | |
| 2238 | var node = this.startNodeAt(startPos, startLoc); | |
| 2239 | node.left = left; | |
| 2240 | node.right = this.parseMaybeAssign(); | |
| 2241 | return this.finishNode(node, "AssignmentPattern") | |
| 2242 | }; | |
| 2243 | ||
| 2244 | // The following three functions all verify that a node is an lvalue — | |
| 2245 | // something that can be bound, or assigned to. In order to do so, they perform | |
| 2246 | // a variety of checks: | |
| 2247 | // | |
| 2248 | // - Check that none of the bound/assigned-to identifiers are reserved words. | |
| 2249 | // - Record name declarations for bindings in the appropriate scope. | |
| 2250 | // - Check duplicate argument names, if checkClashes is set. | |
| 2251 | // | |
| 2252 | // If a complex binding pattern is encountered (e.g., object and array | |
| 2253 | // destructuring), the entire pattern is recursively checked. | |
| 2254 | // | |
| 2255 | // There are three versions of checkLVal*() appropriate for different | |
| 2256 | // circumstances: | |
| 2257 | // | |
| 2258 | // - checkLValSimple() shall be used if the syntactic construct supports | |
| 2259 | // nothing other than identifiers and member expressions. Parenthesized | |
| 2260 | // expressions are also correctly handled. This is generally appropriate for | |
| 2261 | // constructs for which the spec says | |
| 2262 | // | |
| 2263 | // > It is a Syntax Error if AssignmentTargetType of [the production] is not | |
| 2264 | // > simple. | |
| 2265 | // | |
| 2266 | // It is also appropriate for checking if an identifier is valid and not | |
| 2267 | // defined elsewhere, like import declarations or function/class identifiers. | |
| 2268 | // | |
| 2269 | // Examples where this is used include: | |
| 2270 | // a += …; | |
| 2271 | // import a from '…'; | |
| 2272 | // where a is the node to be checked. | |
| 2273 | // | |
| 2274 | // - checkLValPattern() shall be used if the syntactic construct supports | |
| 2275 | // anything checkLValSimple() supports, as well as object and array | |
| 2276 | // destructuring patterns. This is generally appropriate for constructs for | |
| 2277 | // which the spec says | |
| 2278 | // | |
| 2279 | // > It is a Syntax Error if [the production] is neither an ObjectLiteral nor | |
| 2280 | // > an ArrayLiteral and AssignmentTargetType of [the production] is not | |
| 2281 | // > simple. | |
| 2282 | // | |
| 2283 | // Examples where this is used include: | |
| 2284 | // (a = …); | |
| 2285 | // const a = …; | |
| 2286 | // try { … } catch (a) { … } | |
| 2287 | // where a is the node to be checked. | |
| 2288 | // | |
| 2289 | // - checkLValInnerPattern() shall be used if the syntactic construct supports | |
| 2290 | // anything checkLValPattern() supports, as well as default assignment | |
| 2291 | // patterns, rest elements, and other constructs that may appear within an | |
| 2292 | // object or array destructuring pattern. | |
| 2293 | // | |
| 2294 | // As a special case, function parameters also use checkLValInnerPattern(), | |
| 2295 | // as they also support defaults and rest constructs. | |
| 2296 | // | |
| 2297 | // These functions deliberately support both assignment and binding constructs, | |
| 2298 | // as the logic for both is exceedingly similar. If the node is the target of | |
| 2299 | // an assignment, then bindingType should be set to BIND_NONE. Otherwise, it | |
| 2300 | // should be set to the appropriate BIND_* constant, like BIND_VAR or | |
| 2301 | // BIND_LEXICAL. | |
| 2302 | // | |
| 2303 | // If the function is called with a non-BIND_NONE bindingType, then | |
| 2304 | // additionally a checkClashes object may be specified to allow checking for | |
| 2305 | // duplicate argument names. checkClashes is ignored if the provided construct | |
| 2306 | // is an assignment (i.e., bindingType is BIND_NONE). | |
| 2307 | ||
| 2308 | pp$7.checkLValSimple = function(expr, bindingType, checkClashes) { | |
| 2309 | if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
| 2310 | ||
| 2311 | var isBind = bindingType !== BIND_NONE; | |
| 2312 | ||
| 2313 | switch (expr.type) { | |
| 2314 | case "Identifier": | |
| 2315 | if (this.strict && this.reservedWordsStrictBind.test(expr.name)) | |
| 2316 | { this.raiseRecoverable(expr.start, (isBind ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } | |
| 2317 | if (isBind) { | |
| 2318 | if (bindingType === BIND_LEXICAL && expr.name === "let") | |
| 2319 | { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); } | |
| 2320 | if (checkClashes) { | |
| 2321 | if (hasOwn(checkClashes, expr.name)) | |
| 2322 | { this.raiseRecoverable(expr.start, "Argument name clash"); } | |
| 2323 | checkClashes[expr.name] = true; | |
| 2324 | } | |
| 2325 | if (bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); } | |
| 2326 | } | |
| 2327 | break | |
| 2328 | ||
| 2329 | case "ChainExpression": | |
| 2330 | this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side"); | |
| 2331 | break | |
| 2332 | ||
| 2333 | case "MemberExpression": | |
| 2334 | if (isBind) { this.raiseRecoverable(expr.start, "Binding member expression"); } | |
| 2335 | break | |
| 2336 | ||
| 2337 | case "ParenthesizedExpression": | |
| 2338 | if (isBind) { this.raiseRecoverable(expr.start, "Binding parenthesized expression"); } | |
| 2339 | return this.checkLValSimple(expr.expression, bindingType, checkClashes) | |
| 2340 | ||
| 2341 | default: | |
| 2342 | this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue"); | |
| 2343 | } | |
| 2344 | }; | |
| 2345 | ||
| 2346 | pp$7.checkLValPattern = function(expr, bindingType, checkClashes) { | |
| 2347 | if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
| 2348 | ||
| 2349 | switch (expr.type) { | |
| 2350 | case "ObjectPattern": | |
| 2351 | for (var i = 0, list = expr.properties; i < list.length; i += 1) { | |
| 2352 | var prop = list[i]; | |
| 2353 | ||
| 2354 | this.checkLValInnerPattern(prop, bindingType, checkClashes); | |
| 2355 | } | |
| 2356 | break | |
| 2357 | ||
| 2358 | case "ArrayPattern": | |
| 2359 | for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { | |
| 2360 | var elem = list$1[i$1]; | |
| 2361 | ||
| 2362 | if (elem) { this.checkLValInnerPattern(elem, bindingType, checkClashes); } | |
| 2363 | } | |
| 2364 | break | |
| 2365 | ||
| 2366 | default: | |
| 2367 | this.checkLValSimple(expr, bindingType, checkClashes); | |
| 2368 | } | |
| 2369 | }; | |
| 2370 | ||
| 2371 | pp$7.checkLValInnerPattern = function(expr, bindingType, checkClashes) { | |
| 2372 | if ( bindingType === void 0 ) bindingType = BIND_NONE; | |
| 2373 | ||
| 2374 | switch (expr.type) { | |
| 2375 | case "Property": | |
| 2376 | // AssignmentProperty has type === "Property" | |
| 2377 | this.checkLValInnerPattern(expr.value, bindingType, checkClashes); | |
| 2378 | break | |
| 2379 | ||
| 2380 | case "AssignmentPattern": | |
| 2381 | this.checkLValPattern(expr.left, bindingType, checkClashes); | |
| 2382 | break | |
| 2383 | ||
| 2384 | case "RestElement": | |
| 2385 | this.checkLValPattern(expr.argument, bindingType, checkClashes); | |
| 2386 | break | |
| 2387 | ||
| 2388 | default: | |
| 2389 | this.checkLValPattern(expr, bindingType, checkClashes); | |
| 2390 | } | |
| 2391 | }; | |
| 2392 | ||
| 2393 | // The algorithm used to determine whether a regexp can appear at a | |
| 2394 | // given point in the program is loosely based on sweet.js' approach. | |
| 2395 | // See https://github.com/mozilla/sweet.js/wiki/design | |
| 2396 | ||
| 2397 | ||
| 2398 | var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { | |
| 2399 | this.token = token; | |
| 2400 | this.isExpr = !!isExpr; | |
| 2401 | this.preserveSpace = !!preserveSpace; | |
| 2402 | this.override = override; | |
| 2403 | this.generator = !!generator; | |
| 2404 | }; | |
| 2405 | ||
| 2406 | var types = { | |
| 2407 | b_stat: new TokContext("{", false), | |
| 2408 | b_expr: new TokContext("{", true), | |
| 2409 | b_tmpl: new TokContext("${", false), | |
| 2410 | p_stat: new TokContext("(", false), | |
| 2411 | p_expr: new TokContext("(", true), | |
| 2412 | q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), | |
| 2413 | f_stat: new TokContext("function", false), | |
| 2414 | f_expr: new TokContext("function", true), | |
| 2415 | f_expr_gen: new TokContext("function", true, false, null, true), | |
| 2416 | f_gen: new TokContext("function", false, false, null, true) | |
| 2417 | }; | |
| 2418 | ||
| 2419 | var pp$6 = Parser.prototype; | |
| 2420 | ||
| 2421 | pp$6.initialContext = function() { | |
| 2422 | return [types.b_stat] | |
| 2423 | }; | |
| 2424 | ||
| 2425 | pp$6.curContext = function() { | |
| 2426 | return this.context[this.context.length - 1] | |
| 2427 | }; | |
| 2428 | ||
| 2429 | pp$6.braceIsBlock = function(prevType) { | |
| 2430 | var parent = this.curContext(); | |
| 2431 | if (parent === types.f_expr || parent === types.f_stat) | |
| 2432 | { return true } | |
| 2433 | if (prevType === types$1.colon && (parent === types.b_stat || parent === types.b_expr)) | |
| 2434 | { return !parent.isExpr } | |
| 2435 | ||
| 2436 | // The check for `tt.name && exprAllowed` detects whether we are | |
| 2437 | // after a `yield` or `of` construct. See the `updateContext` for | |
| 2438 | // `tt.name`. | |
| 2439 | if (prevType === types$1._return || prevType === types$1.name && this.exprAllowed) | |
| 2440 | { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } | |
| 2441 | if (prevType === types$1._else || prevType === types$1.semi || prevType === types$1.eof || prevType === types$1.parenR || prevType === types$1.arrow) | |
| 2442 | { return true } | |
| 2443 | if (prevType === types$1.braceL) | |
| 2444 | { return parent === types.b_stat } | |
| 2445 | if (prevType === types$1._var || prevType === types$1._const || prevType === types$1.name) | |
| 2446 | { return false } | |
| 2447 | return !this.exprAllowed | |
| 2448 | }; | |
| 2449 | ||
| 2450 | pp$6.inGeneratorContext = function() { | |
| 2451 | for (var i = this.context.length - 1; i >= 1; i--) { | |
| 2452 | var context = this.context[i]; | |
| 2453 | if (context.token === "function") | |
| 2454 | { return context.generator } | |
| 2455 | } | |
| 2456 | return false | |
| 2457 | }; | |
| 2458 | ||
| 2459 | pp$6.updateContext = function(prevType) { | |
| 2460 | var update, type = this.type; | |
| 2461 | if (type.keyword && prevType === types$1.dot) | |
| 2462 | { this.exprAllowed = false; } | |
| 2463 | else if (update = type.updateContext) | |
| 2464 | { update.call(this, prevType); } | |
| 2465 | else | |
| 2466 | { this.exprAllowed = type.beforeExpr; } | |
| 2467 | }; | |
| 2468 | ||
| 2469 | // Used to handle edge cases when token context could not be inferred correctly during tokenization phase | |
| 2470 | ||
| 2471 | pp$6.overrideContext = function(tokenCtx) { | |
| 2472 | if (this.curContext() !== tokenCtx) { | |
| 2473 | this.context[this.context.length - 1] = tokenCtx; | |
| 2474 | } | |
| 2475 | }; | |
| 2476 | ||
| 2477 | // Token-specific context update code | |
| 2478 | ||
| 2479 | types$1.parenR.updateContext = types$1.braceR.updateContext = function() { | |
| 2480 | if (this.context.length === 1) { | |
| 2481 | this.exprAllowed = true; | |
| 2482 | return | |
| 2483 | } | |
| 2484 | var out = this.context.pop(); | |
| 2485 | if (out === types.b_stat && this.curContext().token === "function") { | |
| 2486 | out = this.context.pop(); | |
| 2487 | } | |
| 2488 | this.exprAllowed = !out.isExpr; | |
| 2489 | }; | |
| 2490 | ||
| 2491 | types$1.braceL.updateContext = function(prevType) { | |
| 2492 | this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); | |
| 2493 | this.exprAllowed = true; | |
| 2494 | }; | |
| 2495 | ||
| 2496 | types$1.dollarBraceL.updateContext = function() { | |
| 2497 | this.context.push(types.b_tmpl); | |
| 2498 | this.exprAllowed = true; | |
| 2499 | }; | |
| 2500 | ||
| 2501 | types$1.parenL.updateContext = function(prevType) { | |
| 2502 | var statementParens = prevType === types$1._if || prevType === types$1._for || prevType === types$1._with || prevType === types$1._while; | |
| 2503 | this.context.push(statementParens ? types.p_stat : types.p_expr); | |
| 2504 | this.exprAllowed = true; | |
| 2505 | }; | |
| 2506 | ||
| 2507 | types$1.incDec.updateContext = function() { | |
| 2508 | // tokExprAllowed stays unchanged | |
| 2509 | }; | |
| 2510 | ||
| 2511 | types$1._function.updateContext = types$1._class.updateContext = function(prevType) { | |
| 2512 | if (prevType.beforeExpr && prevType !== types$1._else && | |
| 2513 | !(prevType === types$1.semi && this.curContext() !== types.p_stat) && | |
| 2514 | !(prevType === types$1._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && | |
| 2515 | !((prevType === types$1.colon || prevType === types$1.braceL) && this.curContext() === types.b_stat)) | |
| 2516 | { this.context.push(types.f_expr); } | |
| 2517 | else | |
| 2518 | { this.context.push(types.f_stat); } | |
| 2519 | this.exprAllowed = false; | |
| 2520 | }; | |
| 2521 | ||
| 2522 | types$1.colon.updateContext = function() { | |
| 2523 | if (this.curContext().token === "function") { this.context.pop(); } | |
| 2524 | this.exprAllowed = true; | |
| 2525 | }; | |
| 2526 | ||
| 2527 | types$1.backQuote.updateContext = function() { | |
| 2528 | if (this.curContext() === types.q_tmpl) | |
| 2529 | { this.context.pop(); } | |
| 2530 | else | |
| 2531 | { this.context.push(types.q_tmpl); } | |
| 2532 | this.exprAllowed = false; | |
| 2533 | }; | |
| 2534 | ||
| 2535 | types$1.star.updateContext = function(prevType) { | |
| 2536 | if (prevType === types$1._function) { | |
| 2537 | var index = this.context.length - 1; | |
| 2538 | if (this.context[index] === types.f_expr) | |
| 2539 | { this.context[index] = types.f_expr_gen; } | |
| 2540 | else | |
| 2541 | { this.context[index] = types.f_gen; } | |
| 2542 | } | |
| 2543 | this.exprAllowed = true; | |
| 2544 | }; | |
| 2545 | ||
| 2546 | types$1.name.updateContext = function(prevType) { | |
| 2547 | var allowed = false; | |
| 2548 | if (this.options.ecmaVersion >= 6 && prevType !== types$1.dot) { | |
| 2549 | if (this.value === "of" && !this.exprAllowed || | |
| 2550 | this.value === "yield" && this.inGeneratorContext()) | |
| 2551 | { allowed = true; } | |
| 2552 | } | |
| 2553 | this.exprAllowed = allowed; | |
| 2554 | }; | |
| 2555 | ||
| 2556 | // A recursive descent parser operates by defining functions for all | |
| 2557 | // syntactic elements, and recursively calling those, each function | |
| 2558 | // advancing the input stream and returning an AST node. Precedence | |
| 2559 | // of constructs (for example, the fact that `!x[1]` means `!(x[1])` | |
| 2560 | // instead of `(!x)[1]` is handled by the fact that the parser | |
| 2561 | // function that parses unary prefix operators is called first, and | |
| 2562 | // in turn calls the function that parses `[]` subscripts — that | |
| 2563 | // way, it'll receive the node for `x[1]` already parsed, and wraps | |
| 2564 | // *that* in the unary operator node. | |
| 2565 | // | |
| 2566 | // Acorn uses an [operator precedence parser][opp] to handle binary | |
| 2567 | // operator precedence, because it is much more compact than using | |
| 2568 | // the technique outlined above, which uses different, nesting | |
| 2569 | // functions to specify precedence, for all of the ten binary | |
| 2570 | // precedence levels that JavaScript defines. | |
| 2571 | // | |
| 2572 | // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser | |
| 2573 | ||
| 2574 | ||
| 2575 | var pp$5 = Parser.prototype; | |
| 2576 | ||
| 2577 | // Check if property name clashes with already added. | |
| 2578 | // Object/class getters and setters are not allowed to clash — | |
| 2579 | // either with each other or with an init property — and in | |
| 2580 | // strict mode, init properties are also not allowed to be repeated. | |
| 2581 | ||
| 2582 | pp$5.checkPropClash = function(prop, propHash, refDestructuringErrors) { | |
| 2583 | if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") | |
| 2584 | { return } | |
| 2585 | if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) | |
| 2586 | { return } | |
| 2587 | var key = prop.key; | |
| 2588 | var name; | |
| 2589 | switch (key.type) { | |
| 2590 | case "Identifier": name = key.name; break | |
| 2591 | case "Literal": name = String(key.value); break | |
| 2592 | default: return | |
| 2593 | } | |
| 2594 | var kind = prop.kind; | |
| 2595 | if (this.options.ecmaVersion >= 6) { | |
| 2596 | if (name === "__proto__" && kind === "init") { | |
| 2597 | if (propHash.proto) { | |
| 2598 | if (refDestructuringErrors) { | |
| 2599 | if (refDestructuringErrors.doubleProto < 0) { | |
| 2600 | refDestructuringErrors.doubleProto = key.start; | |
| 2601 | } | |
| 2602 | } else { | |
| 2603 | this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); | |
| 2604 | } | |
| 2605 | } | |
| 2606 | propHash.proto = true; | |
| 2607 | } | |
| 2608 | return | |
| 2609 | } | |
| 2610 | name = "$" + name; | |
| 2611 | var other = propHash[name]; | |
| 2612 | if (other) { | |
| 2613 | var redefinition; | |
| 2614 | if (kind === "init") { | |
| 2615 | redefinition = this.strict && other.init || other.get || other.set; | |
| 2616 | } else { | |
| 2617 | redefinition = other.init || other[kind]; | |
| 2618 | } | |
| 2619 | if (redefinition) | |
| 2620 | { this.raiseRecoverable(key.start, "Redefinition of property"); } | |
| 2621 | } else { | |
| 2622 | other = propHash[name] = { | |
| 2623 | init: false, | |
| 2624 | get: false, | |
| 2625 | set: false | |
| 2626 | }; | |
| 2627 | } | |
| 2628 | other[kind] = true; | |
| 2629 | }; | |
| 2630 | ||
| 2631 | // ### Expression parsing | |
| 2632 | ||
| 2633 | // These nest, from the most general expression type at the top to | |
| 2634 | // 'atomic', nondivisible expression types at the bottom. Most of | |
| 2635 | // the functions will simply let the function(s) below them parse, | |
| 2636 | // and, *if* the syntactic construct they handle is present, wrap | |
| 2637 | // the AST node that the inner parser gave them in another node. | |
| 2638 | ||
| 2639 | // Parse a full expression. The optional arguments are used to | |
| 2640 | // forbid the `in` operator (in for loops initalization expressions) | |
| 2641 | // and provide reference for storing '=' operator inside shorthand | |
| 2642 | // property assignment in contexts where both object expression | |
| 2643 | // and object pattern might appear (so it's possible to raise | |
| 2644 | // delayed syntax error at correct position). | |
| 2645 | ||
| 2646 | pp$5.parseExpression = function(forInit, refDestructuringErrors) { | |
| 2647 | var startPos = this.start, startLoc = this.startLoc; | |
| 2648 | var expr = this.parseMaybeAssign(forInit, refDestructuringErrors); | |
| 2649 | if (this.type === types$1.comma) { | |
| 2650 | var node = this.startNodeAt(startPos, startLoc); | |
| 2651 | node.expressions = [expr]; | |
| 2652 | while (this.eat(types$1.comma)) { node.expressions.push(this.parseMaybeAssign(forInit, refDestructuringErrors)); } | |
| 2653 | return this.finishNode(node, "SequenceExpression") | |
| 2654 | } | |
| 2655 | return expr | |
| 2656 | }; | |
| 2657 | ||
| 2658 | // Parse an assignment expression. This includes applications of | |
| 2659 | // operators like `+=`. | |
| 2660 | ||
| 2661 | pp$5.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse) { | |
| 2662 | if (this.isContextual("yield")) { | |
| 2663 | if (this.inGenerator) { return this.parseYield(forInit) } | |
| 2664 | // The tokenizer will assume an expression is allowed after | |
| 2665 | // `yield`, but this isn't that kind of yield | |
| 2666 | else { this.exprAllowed = false; } | |
| 2667 | } | |
| 2668 | ||
| 2669 | var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1; | |
| 2670 | if (refDestructuringErrors) { | |
| 2671 | oldParenAssign = refDestructuringErrors.parenthesizedAssign; | |
| 2672 | oldTrailingComma = refDestructuringErrors.trailingComma; | |
| 2673 | oldDoubleProto = refDestructuringErrors.doubleProto; | |
| 2674 | refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; | |
| 2675 | } else { | |
| 2676 | refDestructuringErrors = new DestructuringErrors; | |
| 2677 | ownDestructuringErrors = true; | |
| 2678 | } | |
| 2679 | ||
| 2680 | var startPos = this.start, startLoc = this.startLoc; | |
| 2681 | if (this.type === types$1.parenL || this.type === types$1.name) { | |
| 2682 | this.potentialArrowAt = this.start; | |
| 2683 | this.potentialArrowInForAwait = forInit === "await"; | |
| 2684 | } | |
| 2685 | var left = this.parseMaybeConditional(forInit, refDestructuringErrors); | |
| 2686 | if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } | |
| 2687 | if (this.type.isAssign) { | |
| 2688 | var node = this.startNodeAt(startPos, startLoc); | |
| 2689 | node.operator = this.value; | |
| 2690 | if (this.type === types$1.eq) | |
| 2691 | { left = this.toAssignable(left, false, refDestructuringErrors); } | |
| 2692 | if (!ownDestructuringErrors) { | |
| 2693 | refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1; | |
| 2694 | } | |
| 2695 | if (refDestructuringErrors.shorthandAssign >= left.start) | |
| 2696 | { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly | |
| 2697 | if (this.type === types$1.eq) | |
| 2698 | { this.checkLValPattern(left); } | |
| 2699 | else | |
| 2700 | { this.checkLValSimple(left); } | |
| 2701 | node.left = left; | |
| 2702 | this.next(); | |
| 2703 | node.right = this.parseMaybeAssign(forInit); | |
| 2704 | if (oldDoubleProto > -1) { refDestructuringErrors.doubleProto = oldDoubleProto; } | |
| 2705 | return this.finishNode(node, "AssignmentExpression") | |
| 2706 | } else { | |
| 2707 | if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } | |
| 2708 | } | |
| 2709 | if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } | |
| 2710 | if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } | |
| 2711 | return left | |
| 2712 | }; | |
| 2713 | ||
| 2714 | // Parse a ternary conditional (`?:`) operator. | |
| 2715 | ||
| 2716 | pp$5.parseMaybeConditional = function(forInit, refDestructuringErrors) { | |
| 2717 | var startPos = this.start, startLoc = this.startLoc; | |
| 2718 | var expr = this.parseExprOps(forInit, refDestructuringErrors); | |
| 2719 | if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
| 2720 | if (this.eat(types$1.question)) { | |
| 2721 | var node = this.startNodeAt(startPos, startLoc); | |
| 2722 | node.test = expr; | |
| 2723 | node.consequent = this.parseMaybeAssign(); | |
| 2724 | this.expect(types$1.colon); | |
| 2725 | node.alternate = this.parseMaybeAssign(forInit); | |
| 2726 | return this.finishNode(node, "ConditionalExpression") | |
| 2727 | } | |
| 2728 | return expr | |
| 2729 | }; | |
| 2730 | ||
| 2731 | // Start the precedence parser. | |
| 2732 | ||
| 2733 | pp$5.parseExprOps = function(forInit, refDestructuringErrors) { | |
| 2734 | var startPos = this.start, startLoc = this.startLoc; | |
| 2735 | var expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit); | |
| 2736 | if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
| 2737 | return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit) | |
| 2738 | }; | |
| 2739 | ||
| 2740 | // Parse binary operators with the operator precedence parsing | |
| 2741 | // algorithm. `left` is the left-hand side of the operator. | |
| 2742 | // `minPrec` provides context that allows the function to stop and | |
| 2743 | // defer further parser to one of its callers when it encounters an | |
| 2744 | // operator that has a lower precedence than the set it is parsing. | |
| 2745 | ||
| 2746 | pp$5.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, forInit) { | |
| 2747 | var prec = this.type.binop; | |
| 2748 | if (prec != null && (!forInit || this.type !== types$1._in)) { | |
| 2749 | if (prec > minPrec) { | |
| 2750 | var logical = this.type === types$1.logicalOR || this.type === types$1.logicalAND; | |
| 2751 | var coalesce = this.type === types$1.coalesce; | |
| 2752 | if (coalesce) { | |
| 2753 | // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions. | |
| 2754 | // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error. | |
| 2755 | prec = types$1.logicalAND.binop; | |
| 2756 | } | |
| 2757 | var op = this.value; | |
| 2758 | this.next(); | |
| 2759 | var startPos = this.start, startLoc = this.startLoc; | |
| 2760 | var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit); | |
| 2761 | var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce); | |
| 2762 | if ((logical && this.type === types$1.coalesce) || (coalesce && (this.type === types$1.logicalOR || this.type === types$1.logicalAND))) { | |
| 2763 | this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses"); | |
| 2764 | } | |
| 2765 | return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit) | |
| 2766 | } | |
| 2767 | } | |
| 2768 | return left | |
| 2769 | }; | |
| 2770 | ||
| 2771 | pp$5.buildBinary = function(startPos, startLoc, left, right, op, logical) { | |
| 2772 | if (right.type === "PrivateIdentifier") { this.raise(right.start, "Private identifier can only be left side of binary expression"); } | |
| 2773 | var node = this.startNodeAt(startPos, startLoc); | |
| 2774 | node.left = left; | |
| 2775 | node.operator = op; | |
| 2776 | node.right = right; | |
| 2777 | return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") | |
| 2778 | }; | |
| 2779 | ||
| 2780 | // Parse unary operators, both prefix and postfix. | |
| 2781 | ||
| 2782 | pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forInit) { | |
| 2783 | var startPos = this.start, startLoc = this.startLoc, expr; | |
| 2784 | if (this.isContextual("await") && this.canAwait) { | |
| 2785 | expr = this.parseAwait(forInit); | |
| 2786 | sawUnary = true; | |
| 2787 | } else if (this.type.prefix) { | |
| 2788 | var node = this.startNode(), update = this.type === types$1.incDec; | |
| 2789 | node.operator = this.value; | |
| 2790 | node.prefix = true; | |
| 2791 | this.next(); | |
| 2792 | node.argument = this.parseMaybeUnary(null, true, update, forInit); | |
| 2793 | this.checkExpressionErrors(refDestructuringErrors, true); | |
| 2794 | if (update) { this.checkLValSimple(node.argument); } | |
| 2795 | else if (this.strict && node.operator === "delete" && isLocalVariableAccess(node.argument)) | |
| 2796 | { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } | |
| 2797 | else if (node.operator === "delete" && isPrivateFieldAccess(node.argument)) | |
| 2798 | { this.raiseRecoverable(node.start, "Private fields can not be deleted"); } | |
| 2799 | else { sawUnary = true; } | |
| 2800 | expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); | |
| 2801 | } else if (!sawUnary && this.type === types$1.privateId) { | |
| 2802 | if ((forInit || this.privateNameStack.length === 0) && this.options.checkPrivateFields) { this.unexpected(); } | |
| 2803 | expr = this.parsePrivateIdent(); | |
| 2804 | // only could be private fields in 'in', such as #x in obj | |
| 2805 | if (this.type !== types$1._in) { this.unexpected(); } | |
| 2806 | } else { | |
| 2807 | expr = this.parseExprSubscripts(refDestructuringErrors, forInit); | |
| 2808 | if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } | |
| 2809 | while (this.type.postfix && !this.canInsertSemicolon()) { | |
| 2810 | var node$1 = this.startNodeAt(startPos, startLoc); | |
| 2811 | node$1.operator = this.value; | |
| 2812 | node$1.prefix = false; | |
| 2813 | node$1.argument = expr; | |
| 2814 | this.checkLValSimple(expr); | |
| 2815 | this.next(); | |
| 2816 | expr = this.finishNode(node$1, "UpdateExpression"); | |
| 2817 | } | |
| 2818 | } | |
| 2819 | ||
| 2820 | if (!incDec && this.eat(types$1.starstar)) { | |
| 2821 | if (sawUnary) | |
| 2822 | { this.unexpected(this.lastTokStart); } | |
| 2823 | else | |
| 2824 | { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false) } | |
| 2825 | } else { | |
| 2826 | return expr | |
| 2827 | } | |
| 2828 | }; | |
| 2829 | ||
| 2830 | function isLocalVariableAccess(node) { | |
| 2831 | return ( | |
| 2832 | node.type === "Identifier" || | |
| 2833 | node.type === "ParenthesizedExpression" && isLocalVariableAccess(node.expression) | |
| 2834 | ) | |
| 2835 | } | |
| 2836 | ||
| 2837 | function isPrivateFieldAccess(node) { | |
| 2838 | return ( | |
| 2839 | node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" || | |
| 2840 | node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) || | |
| 2841 | node.type === "ParenthesizedExpression" && isPrivateFieldAccess(node.expression) | |
| 2842 | ) | |
| 2843 | } | |
| 2844 | ||
| 2845 | // Parse call, dot, and `[]`-subscript expressions. | |
| 2846 | ||
| 2847 | pp$5.parseExprSubscripts = function(refDestructuringErrors, forInit) { | |
| 2848 | var startPos = this.start, startLoc = this.startLoc; | |
| 2849 | var expr = this.parseExprAtom(refDestructuringErrors, forInit); | |
| 2850 | if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")") | |
| 2851 | { return expr } | |
| 2852 | var result = this.parseSubscripts(expr, startPos, startLoc, false, forInit); | |
| 2853 | if (refDestructuringErrors && result.type === "MemberExpression") { | |
| 2854 | if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } | |
| 2855 | if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } | |
| 2856 | if (refDestructuringErrors.trailingComma >= result.start) { refDestructuringErrors.trailingComma = -1; } | |
| 2857 | } | |
| 2858 | return result | |
| 2859 | }; | |
| 2860 | ||
| 2861 | pp$5.parseSubscripts = function(base, startPos, startLoc, noCalls, forInit) { | |
| 2862 | var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && | |
| 2863 | this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && | |
| 2864 | this.potentialArrowAt === base.start; | |
| 2865 | var optionalChained = false; | |
| 2866 | ||
| 2867 | while (true) { | |
| 2868 | var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit); | |
| 2869 | ||
| 2870 | if (element.optional) { optionalChained = true; } | |
| 2871 | if (element === base || element.type === "ArrowFunctionExpression") { | |
| 2872 | if (optionalChained) { | |
| 2873 | var chainNode = this.startNodeAt(startPos, startLoc); | |
| 2874 | chainNode.expression = element; | |
| 2875 | element = this.finishNode(chainNode, "ChainExpression"); | |
| 2876 | } | |
| 2877 | return element | |
| 2878 | } | |
| 2879 | ||
| 2880 | base = element; | |
| 2881 | } | |
| 2882 | }; | |
| 2883 | ||
| 2884 | pp$5.shouldParseAsyncArrow = function() { | |
| 2885 | return !this.canInsertSemicolon() && this.eat(types$1.arrow) | |
| 2886 | }; | |
| 2887 | ||
| 2888 | pp$5.parseSubscriptAsyncArrow = function(startPos, startLoc, exprList, forInit) { | |
| 2889 | return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true, forInit) | |
| 2890 | }; | |
| 2891 | ||
| 2892 | pp$5.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) { | |
| 2893 | var optionalSupported = this.options.ecmaVersion >= 11; | |
| 2894 | var optional = optionalSupported && this.eat(types$1.questionDot); | |
| 2895 | if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); } | |
| 2896 | ||
| 2897 | var computed = this.eat(types$1.bracketL); | |
| 2898 | if (computed || (optional && this.type !== types$1.parenL && this.type !== types$1.backQuote) || this.eat(types$1.dot)) { | |
| 2899 | var node = this.startNodeAt(startPos, startLoc); | |
| 2900 | node.object = base; | |
| 2901 | if (computed) { | |
| 2902 | node.property = this.parseExpression(); | |
| 2903 | this.expect(types$1.bracketR); | |
| 2904 | } else if (this.type === types$1.privateId && base.type !== "Super") { | |
| 2905 | node.property = this.parsePrivateIdent(); | |
| 2906 | } else { | |
| 2907 | node.property = this.parseIdent(this.options.allowReserved !== "never"); | |
| 2908 | } | |
| 2909 | node.computed = !!computed; | |
| 2910 | if (optionalSupported) { | |
| 2911 | node.optional = optional; | |
| 2912 | } | |
| 2913 | base = this.finishNode(node, "MemberExpression"); | |
| 2914 | } else if (!noCalls && this.eat(types$1.parenL)) { | |
| 2915 | var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
| 2916 | this.yieldPos = 0; | |
| 2917 | this.awaitPos = 0; | |
| 2918 | this.awaitIdentPos = 0; | |
| 2919 | var exprList = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors); | |
| 2920 | if (maybeAsyncArrow && !optional && this.shouldParseAsyncArrow()) { | |
| 2921 | this.checkPatternErrors(refDestructuringErrors, false); | |
| 2922 | this.checkYieldAwaitInDefaultParams(); | |
| 2923 | if (this.awaitIdentPos > 0) | |
| 2924 | { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); } | |
| 2925 | this.yieldPos = oldYieldPos; | |
| 2926 | this.awaitPos = oldAwaitPos; | |
| 2927 | this.awaitIdentPos = oldAwaitIdentPos; | |
| 2928 | return this.parseSubscriptAsyncArrow(startPos, startLoc, exprList, forInit) | |
| 2929 | } | |
| 2930 | this.checkExpressionErrors(refDestructuringErrors, true); | |
| 2931 | this.yieldPos = oldYieldPos || this.yieldPos; | |
| 2932 | this.awaitPos = oldAwaitPos || this.awaitPos; | |
| 2933 | this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos; | |
| 2934 | var node$1 = this.startNodeAt(startPos, startLoc); | |
| 2935 | node$1.callee = base; | |
| 2936 | node$1.arguments = exprList; | |
| 2937 | if (optionalSupported) { | |
| 2938 | node$1.optional = optional; | |
| 2939 | } | |
| 2940 | base = this.finishNode(node$1, "CallExpression"); | |
| 2941 | } else if (this.type === types$1.backQuote) { | |
| 2942 | if (optional || optionalChained) { | |
| 2943 | this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions"); | |
| 2944 | } | |
| 2945 | var node$2 = this.startNodeAt(startPos, startLoc); | |
| 2946 | node$2.tag = base; | |
| 2947 | node$2.quasi = this.parseTemplate({isTagged: true}); | |
| 2948 | base = this.finishNode(node$2, "TaggedTemplateExpression"); | |
| 2949 | } | |
| 2950 | return base | |
| 2951 | }; | |
| 2952 | ||
| 2953 | // Parse an atomic expression — either a single token that is an | |
| 2954 | // expression, an expression started by a keyword like `function` or | |
| 2955 | // `new`, or an expression wrapped in punctuation like `()`, `[]`, | |
| 2956 | // or `{}`. | |
| 2957 | ||
| 2958 | pp$5.parseExprAtom = function(refDestructuringErrors, forInit, forNew) { | |
| 2959 | // If a division operator appears in an expression position, the | |
| 2960 | // tokenizer got confused, and we force it to read a regexp instead. | |
| 2961 | if (this.type === types$1.slash) { this.readRegexp(); } | |
| 2962 | ||
| 2963 | var node, canBeArrow = this.potentialArrowAt === this.start; | |
| 2964 | switch (this.type) { | |
| 2965 | case types$1._super: | |
| 2966 | if (!this.allowSuper) | |
| 2967 | { this.raise(this.start, "'super' keyword outside a method"); } | |
| 2968 | node = this.startNode(); | |
| 2969 | this.next(); | |
| 2970 | if (this.type === types$1.parenL && !this.allowDirectSuper) | |
| 2971 | { this.raise(node.start, "super() call outside constructor of a subclass"); } | |
| 2972 | // The `super` keyword can appear at below: | |
| 2973 | // SuperProperty: | |
| 2974 | // super [ Expression ] | |
| 2975 | // super . IdentifierName | |
| 2976 | // SuperCall: | |
| 2977 | // super ( Arguments ) | |
| 2978 | if (this.type !== types$1.dot && this.type !== types$1.bracketL && this.type !== types$1.parenL) | |
| 2979 | { this.unexpected(); } | |
| 2980 | return this.finishNode(node, "Super") | |
| 2981 | ||
| 2982 | case types$1._this: | |
| 2983 | node = this.startNode(); | |
| 2984 | this.next(); | |
| 2985 | return this.finishNode(node, "ThisExpression") | |
| 2986 | ||
| 2987 | case types$1.name: | |
| 2988 | var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; | |
| 2989 | var id = this.parseIdent(false); | |
| 2990 | if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types$1._function)) { | |
| 2991 | this.overrideContext(types.f_expr); | |
| 2992 | return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true, forInit) | |
| 2993 | } | |
| 2994 | if (canBeArrow && !this.canInsertSemicolon()) { | |
| 2995 | if (this.eat(types$1.arrow)) | |
| 2996 | { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false, forInit) } | |
| 2997 | if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types$1.name && !containsEsc && | |
| 2998 | (!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) { | |
| 2999 | id = this.parseIdent(false); | |
| 3000 | if (this.canInsertSemicolon() || !this.eat(types$1.arrow)) | |
| 3001 | { this.unexpected(); } | |
| 3002 | return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true, forInit) | |
| 3003 | } | |
| 3004 | } | |
| 3005 | return id | |
| 3006 | ||
| 3007 | case types$1.regexp: | |
| 3008 | var value = this.value; | |
| 3009 | node = this.parseLiteral(value.value); | |
| 3010 | node.regex = {pattern: value.pattern, flags: value.flags}; | |
| 3011 | return node | |
| 3012 | ||
| 3013 | case types$1.num: case types$1.string: | |
| 3014 | return this.parseLiteral(this.value) | |
| 3015 | ||
| 3016 | case types$1._null: case types$1._true: case types$1._false: | |
| 3017 | node = this.startNode(); | |
| 3018 | node.value = this.type === types$1._null ? null : this.type === types$1._true; | |
| 3019 | node.raw = this.type.keyword; | |
| 3020 | this.next(); | |
| 3021 | return this.finishNode(node, "Literal") | |
| 3022 | ||
| 3023 | case types$1.parenL: | |
| 3024 | var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow, forInit); | |
| 3025 | if (refDestructuringErrors) { | |
| 3026 | if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) | |
| 3027 | { refDestructuringErrors.parenthesizedAssign = start; } | |
| 3028 | if (refDestructuringErrors.parenthesizedBind < 0) | |
| 3029 | { refDestructuringErrors.parenthesizedBind = start; } | |
| 3030 | } | |
| 3031 | return expr | |
| 3032 | ||
| 3033 | case types$1.bracketL: | |
| 3034 | node = this.startNode(); | |
| 3035 | this.next(); | |
| 3036 | node.elements = this.parseExprList(types$1.bracketR, true, true, refDestructuringErrors); | |
| 3037 | return this.finishNode(node, "ArrayExpression") | |
| 3038 | ||
| 3039 | case types$1.braceL: | |
| 3040 | this.overrideContext(types.b_expr); | |
| 3041 | return this.parseObj(false, refDestructuringErrors) | |
| 3042 | ||
| 3043 | case types$1._function: | |
| 3044 | node = this.startNode(); | |
| 3045 | this.next(); | |
| 3046 | return this.parseFunction(node, 0) | |
| 3047 | ||
| 3048 | case types$1._class: | |
| 3049 | return this.parseClass(this.startNode(), false) | |
| 3050 | ||
| 3051 | case types$1._new: | |
| 3052 | return this.parseNew() | |
| 3053 | ||
| 3054 | case types$1.backQuote: | |
| 3055 | return this.parseTemplate() | |
| 3056 | ||
| 3057 | case types$1._import: | |
| 3058 | if (this.options.ecmaVersion >= 11) { | |
| 3059 | return this.parseExprImport(forNew) | |
| 3060 | } else { | |
| 3061 | return this.unexpected() | |
| 3062 | } | |
| 3063 | ||
| 3064 | default: | |
| 3065 | return this.parseExprAtomDefault() | |
| 3066 | } | |
| 3067 | }; | |
| 3068 | ||
| 3069 | pp$5.parseExprAtomDefault = function() { | |
| 3070 | this.unexpected(); | |
| 3071 | }; | |
| 3072 | ||
| 3073 | pp$5.parseExprImport = function(forNew) { | |
| 3074 | var node = this.startNode(); | |
| 3075 | ||
| 3076 | // Consume `import` as an identifier for `import.meta`. | |
| 3077 | // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`. | |
| 3078 | if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); } | |
| 3079 | this.next(); | |
| 3080 | ||
| 3081 | if (this.type === types$1.parenL && !forNew) { | |
| 3082 | return this.parseDynamicImport(node) | |
| 3083 | } else if (this.type === types$1.dot) { | |
| 3084 | var meta = this.startNodeAt(node.start, node.loc && node.loc.start); | |
| 3085 | meta.name = "import"; | |
| 3086 | node.meta = this.finishNode(meta, "Identifier"); | |
| 3087 | return this.parseImportMeta(node) | |
| 3088 | } else { | |
| 3089 | this.unexpected(); | |
| 3090 | } | |
| 3091 | }; | |
| 3092 | ||
| 3093 | pp$5.parseDynamicImport = function(node) { | |
| 3094 | this.next(); // skip `(` | |
| 3095 | ||
| 3096 | // Parse node.source. | |
| 3097 | node.source = this.parseMaybeAssign(); | |
| 3098 | ||
| 3099 | if (this.options.ecmaVersion >= 16) { | |
| 3100 | if (!this.eat(types$1.parenR)) { | |
| 3101 | this.expect(types$1.comma); | |
| 3102 | if (!this.afterTrailingComma(types$1.parenR)) { | |
| 3103 | node.options = this.parseMaybeAssign(); | |
| 3104 | if (!this.eat(types$1.parenR)) { | |
| 3105 | this.expect(types$1.comma); | |
| 3106 | if (!this.afterTrailingComma(types$1.parenR)) { | |
| 3107 | this.unexpected(); | |
| 3108 | } | |
| 3109 | } | |
| 3110 | } else { | |
| 3111 | node.options = null; | |
| 3112 | } | |
| 3113 | } else { | |
| 3114 | node.options = null; | |
| 3115 | } | |
| 3116 | } else { | |
| 3117 | // Verify ending. | |
| 3118 | if (!this.eat(types$1.parenR)) { | |
| 3119 | var errorPos = this.start; | |
| 3120 | if (this.eat(types$1.comma) && this.eat(types$1.parenR)) { | |
| 3121 | this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()"); | |
| 3122 | } else { | |
| 3123 | this.unexpected(errorPos); | |
| 3124 | } | |
| 3125 | } | |
| 3126 | } | |
| 3127 | ||
| 3128 | return this.finishNode(node, "ImportExpression") | |
| 3129 | }; | |
| 3130 | ||
| 3131 | pp$5.parseImportMeta = function(node) { | |
| 3132 | this.next(); // skip `.` | |
| 3133 | ||
| 3134 | var containsEsc = this.containsEsc; | |
| 3135 | node.property = this.parseIdent(true); | |
| 3136 | ||
| 3137 | if (node.property.name !== "meta") | |
| 3138 | { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); } | |
| 3139 | if (containsEsc) | |
| 3140 | { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); } | |
| 3141 | if (this.options.sourceType !== "module" && !this.options.allowImportExportEverywhere) | |
| 3142 | { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); } | |
| 3143 | ||
| 3144 | return this.finishNode(node, "MetaProperty") | |
| 3145 | }; | |
| 3146 | ||
| 3147 | pp$5.parseLiteral = function(value) { | |
| 3148 | var node = this.startNode(); | |
| 3149 | node.value = value; | |
| 3150 | node.raw = this.input.slice(this.start, this.end); | |
| 3151 | if (node.raw.charCodeAt(node.raw.length - 1) === 110) | |
| 3152 | { node.bigint = node.value != null ? node.value.toString() : node.raw.slice(0, -1).replace(/_/g, ""); } | |
| 3153 | this.next(); | |
| 3154 | return this.finishNode(node, "Literal") | |
| 3155 | }; | |
| 3156 | ||
| 3157 | pp$5.parseParenExpression = function() { | |
| 3158 | this.expect(types$1.parenL); | |
| 3159 | var val = this.parseExpression(); | |
| 3160 | this.expect(types$1.parenR); | |
| 3161 | return val | |
| 3162 | }; | |
| 3163 | ||
| 3164 | pp$5.shouldParseArrow = function(exprList) { | |
| 3165 | return !this.canInsertSemicolon() | |
| 3166 | }; | |
| 3167 | ||
| 3168 | pp$5.parseParenAndDistinguishExpression = function(canBeArrow, forInit) { | |
| 3169 | var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; | |
| 3170 | if (this.options.ecmaVersion >= 6) { | |
| 3171 | this.next(); | |
| 3172 | ||
| 3173 | var innerStartPos = this.start, innerStartLoc = this.startLoc; | |
| 3174 | var exprList = [], first = true, lastIsComma = false; | |
| 3175 | var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; | |
| 3176 | this.yieldPos = 0; | |
| 3177 | this.awaitPos = 0; | |
| 3178 | // Do not save awaitIdentPos to allow checking awaits nested in parameters | |
| 3179 | while (this.type !== types$1.parenR) { | |
| 3180 | first ? first = false : this.expect(types$1.comma); | |
| 3181 | if (allowTrailingComma && this.afterTrailingComma(types$1.parenR, true)) { | |
| 3182 | lastIsComma = true; | |
| 3183 | break | |
| 3184 | } else if (this.type === types$1.ellipsis) { | |
| 3185 | spreadStart = this.start; | |
| 3186 | exprList.push(this.parseParenItem(this.parseRestBinding())); | |
| 3187 | if (this.type === types$1.comma) { | |
| 3188 | this.raiseRecoverable( | |
| 3189 | this.start, | |
| 3190 | "Comma is not permitted after the rest element" | |
| 3191 | ); | |
| 3192 | } | |
| 3193 | break | |
| 3194 | } else { | |
| 3195 | exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); | |
| 3196 | } | |
| 3197 | } | |
| 3198 | var innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc; | |
| 3199 | this.expect(types$1.parenR); | |
| 3200 | ||
| 3201 | if (canBeArrow && this.shouldParseArrow(exprList) && this.eat(types$1.arrow)) { | |
| 3202 | this.checkPatternErrors(refDestructuringErrors, false); | |
| 3203 | this.checkYieldAwaitInDefaultParams(); | |
| 3204 | this.yieldPos = oldYieldPos; | |
| 3205 | this.awaitPos = oldAwaitPos; | |
| 3206 | return this.parseParenArrowList(startPos, startLoc, exprList, forInit) | |
| 3207 | } | |
| 3208 | ||
| 3209 | if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } | |
| 3210 | if (spreadStart) { this.unexpected(spreadStart); } | |
| 3211 | this.checkExpressionErrors(refDestructuringErrors, true); | |
| 3212 | this.yieldPos = oldYieldPos || this.yieldPos; | |
| 3213 | this.awaitPos = oldAwaitPos || this.awaitPos; | |
| 3214 | ||
| 3215 | if (exprList.length > 1) { | |
| 3216 | val = this.startNodeAt(innerStartPos, innerStartLoc); | |
| 3217 | val.expressions = exprList; | |
| 3218 | this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); | |
| 3219 | } else { | |
| 3220 | val = exprList[0]; | |
| 3221 | } | |
| 3222 | } else { | |
| 3223 | val = this.parseParenExpression(); | |
| 3224 | } | |
| 3225 | ||
| 3226 | if (this.options.preserveParens) { | |
| 3227 | var par = this.startNodeAt(startPos, startLoc); | |
| 3228 | par.expression = val; | |
| 3229 | return this.finishNode(par, "ParenthesizedExpression") | |
| 3230 | } else { | |
| 3231 | return val | |
| 3232 | } | |
| 3233 | }; | |
| 3234 | ||
| 3235 | pp$5.parseParenItem = function(item) { | |
| 3236 | return item | |
| 3237 | }; | |
| 3238 | ||
| 3239 | pp$5.parseParenArrowList = function(startPos, startLoc, exprList, forInit) { | |
| 3240 | return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit) | |
| 3241 | }; | |
| 3242 | ||
| 3243 | // New's precedence is slightly tricky. It must allow its argument to | |
| 3244 | // be a `[]` or dot subscript expression, but not a call — at least, | |
| 3245 | // not without wrapping it in parentheses. Thus, it uses the noCalls | |
| 3246 | // argument to parseSubscripts to prevent it from consuming the | |
| 3247 | // argument list. | |
| 3248 | ||
| 3249 | var empty = []; | |
| 3250 | ||
| 3251 | pp$5.parseNew = function() { | |
| 3252 | if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); } | |
| 3253 | var node = this.startNode(); | |
| 3254 | this.next(); | |
| 3255 | if (this.options.ecmaVersion >= 6 && this.type === types$1.dot) { | |
| 3256 | var meta = this.startNodeAt(node.start, node.loc && node.loc.start); | |
| 3257 | meta.name = "new"; | |
| 3258 | node.meta = this.finishNode(meta, "Identifier"); | |
| 3259 | this.next(); | |
| 3260 | var containsEsc = this.containsEsc; | |
| 3261 | node.property = this.parseIdent(true); | |
| 3262 | if (node.property.name !== "target") | |
| 3263 | { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); } | |
| 3264 | if (containsEsc) | |
| 3265 | { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); } | |
| 3266 | if (!this.allowNewDotTarget) | |
| 3267 | { this.raiseRecoverable(node.start, "'new.target' can only be used in functions and class static block"); } | |
| 3268 | return this.finishNode(node, "MetaProperty") | |
| 3269 | } | |
| 3270 | var startPos = this.start, startLoc = this.startLoc; | |
| 3271 | node.callee = this.parseSubscripts(this.parseExprAtom(null, false, true), startPos, startLoc, true, false); | |
| 3272 | if (this.eat(types$1.parenL)) { node.arguments = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false); } | |
| 3273 | else { node.arguments = empty; } | |
| 3274 | return this.finishNode(node, "NewExpression") | |
| 3275 | }; | |
| 3276 | ||
| 3277 | // Parse template expression. | |
| 3278 | ||
| 3279 | pp$5.parseTemplateElement = function(ref) { | |
| 3280 | var isTagged = ref.isTagged; | |
| 3281 | ||
| 3282 | var elem = this.startNode(); | |
| 3283 | if (this.type === types$1.invalidTemplate) { | |
| 3284 | if (!isTagged) { | |
| 3285 | this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); | |
| 3286 | } | |
| 3287 | elem.value = { | |
| 3288 | raw: this.value.replace(/\r\n?/g, "\n"), | |
| 3289 | cooked: null | |
| 3290 | }; | |
| 3291 | } else { | |
| 3292 | elem.value = { | |
| 3293 | raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), | |
| 3294 | cooked: this.value | |
| 3295 | }; | |
| 3296 | } | |
| 3297 | this.next(); | |
| 3298 | elem.tail = this.type === types$1.backQuote; | |
| 3299 | return this.finishNode(elem, "TemplateElement") | |
| 3300 | }; | |
| 3301 | ||
| 3302 | pp$5.parseTemplate = function(ref) { | |
| 3303 | if ( ref === void 0 ) ref = {}; | |
| 3304 | var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; | |
| 3305 | ||
| 3306 | var node = this.startNode(); | |
| 3307 | this.next(); | |
| 3308 | node.expressions = []; | |
| 3309 | var curElt = this.parseTemplateElement({isTagged: isTagged}); | |
| 3310 | node.quasis = [curElt]; | |
| 3311 | while (!curElt.tail) { | |
| 3312 | if (this.type === types$1.eof) { this.raise(this.pos, "Unterminated template literal"); } | |
| 3313 | this.expect(types$1.dollarBraceL); | |
| 3314 | node.expressions.push(this.parseExpression()); | |
| 3315 | this.expect(types$1.braceR); | |
| 3316 | node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged})); | |
| 3317 | } | |
| 3318 | this.next(); | |
| 3319 | return this.finishNode(node, "TemplateLiteral") | |
| 3320 | }; | |
| 3321 | ||
| 3322 | pp$5.isAsyncProp = function(prop) { | |
| 3323 | return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && | |
| 3324 | (this.type === types$1.name || this.type === types$1.num || this.type === types$1.string || this.type === types$1.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types$1.star)) && | |
| 3325 | !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) | |
| 3326 | }; | |
| 3327 | ||
| 3328 | // Parse an object literal or binding pattern. | |
| 3329 | ||
| 3330 | pp$5.parseObj = function(isPattern, refDestructuringErrors) { | |
| 3331 | var node = this.startNode(), first = true, propHash = {}; | |
| 3332 | node.properties = []; | |
| 3333 | this.next(); | |
| 3334 | while (!this.eat(types$1.braceR)) { | |
| 3335 | if (!first) { | |
| 3336 | this.expect(types$1.comma); | |
| 3337 | if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types$1.braceR)) { break } | |
| 3338 | } else { first = false; } | |
| 3339 | ||
| 3340 | var prop = this.parseProperty(isPattern, refDestructuringErrors); | |
| 3341 | if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); } | |
| 3342 | node.properties.push(prop); | |
| 3343 | } | |
| 3344 | return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") | |
| 3345 | }; | |
| 3346 | ||
| 3347 | pp$5.parseProperty = function(isPattern, refDestructuringErrors) { | |
| 3348 | var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; | |
| 3349 | if (this.options.ecmaVersion >= 9 && this.eat(types$1.ellipsis)) { | |
| 3350 | if (isPattern) { | |
| 3351 | prop.argument = this.parseIdent(false); | |
| 3352 | if (this.type === types$1.comma) { | |
| 3353 | this.raiseRecoverable(this.start, "Comma is not permitted after the rest element"); | |
| 3354 | } | |
| 3355 | return this.finishNode(prop, "RestElement") | |
| 3356 | } | |
| 3357 | // Parse argument. | |
| 3358 | prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); | |
| 3359 | // To disallow trailing comma via `this.toAssignable()`. | |
| 3360 | if (this.type === types$1.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { | |
| 3361 | refDestructuringErrors.trailingComma = this.start; | |
| 3362 | } | |
| 3363 | // Finish | |
| 3364 | return this.finishNode(prop, "SpreadElement") | |
| 3365 | } | |
| 3366 | if (this.options.ecmaVersion >= 6) { | |
| 3367 | prop.method = false; | |
| 3368 | prop.shorthand = false; | |
| 3369 | if (isPattern || refDestructuringErrors) { | |
| 3370 | startPos = this.start; | |
| 3371 | startLoc = this.startLoc; | |
| 3372 | } | |
| 3373 | if (!isPattern) | |
| 3374 | { isGenerator = this.eat(types$1.star); } | |
| 3375 | } | |
| 3376 | var containsEsc = this.containsEsc; | |
| 3377 | this.parsePropertyName(prop); | |
| 3378 | if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { | |
| 3379 | isAsync = true; | |
| 3380 | isGenerator = this.options.ecmaVersion >= 9 && this.eat(types$1.star); | |
| 3381 | this.parsePropertyName(prop); | |
| 3382 | } else { | |
| 3383 | isAsync = false; | |
| 3384 | } | |
| 3385 | this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); | |
| 3386 | return this.finishNode(prop, "Property") | |
| 3387 | }; | |
| 3388 | ||
| 3389 | pp$5.parseGetterSetter = function(prop) { | |
| 3390 | var kind = prop.key.name; | |
| 3391 | this.parsePropertyName(prop); | |
| 3392 | prop.value = this.parseMethod(false); | |
| 3393 | prop.kind = kind; | |
| 3394 | var paramCount = prop.kind === "get" ? 0 : 1; | |
| 3395 | if (prop.value.params.length !== paramCount) { | |
| 3396 | var start = prop.value.start; | |
| 3397 | if (prop.kind === "get") | |
| 3398 | { this.raiseRecoverable(start, "getter should have no params"); } | |
| 3399 | else | |
| 3400 | { this.raiseRecoverable(start, "setter should have exactly one param"); } | |
| 3401 | } else { | |
| 3402 | if (prop.kind === "set" && prop.value.params[0].type === "RestElement") | |
| 3403 | { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } | |
| 3404 | } | |
| 3405 | }; | |
| 3406 | ||
| 3407 | pp$5.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { | |
| 3408 | if ((isGenerator || isAsync) && this.type === types$1.colon) | |
| 3409 | { this.unexpected(); } | |
| 3410 | ||
| 3411 | if (this.eat(types$1.colon)) { | |
| 3412 | prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); | |
| 3413 | prop.kind = "init"; | |
| 3414 | } else if (this.options.ecmaVersion >= 6 && this.type === types$1.parenL) { | |
| 3415 | if (isPattern) { this.unexpected(); } | |
| 3416 | prop.method = true; | |
| 3417 | prop.value = this.parseMethod(isGenerator, isAsync); | |
| 3418 | prop.kind = "init"; | |
| 3419 | } else if (!isPattern && !containsEsc && | |
| 3420 | this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && | |
| 3421 | (prop.key.name === "get" || prop.key.name === "set") && | |
| 3422 | (this.type !== types$1.comma && this.type !== types$1.braceR && this.type !== types$1.eq)) { | |
| 3423 | if (isGenerator || isAsync) { this.unexpected(); } | |
| 3424 | this.parseGetterSetter(prop); | |
| 3425 | } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { | |
| 3426 | if (isGenerator || isAsync) { this.unexpected(); } | |
| 3427 | this.checkUnreserved(prop.key); | |
| 3428 | if (prop.key.name === "await" && !this.awaitIdentPos) | |
| 3429 | { this.awaitIdentPos = startPos; } | |
| 3430 | if (isPattern) { | |
| 3431 | prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); | |
| 3432 | } else if (this.type === types$1.eq && refDestructuringErrors) { | |
| 3433 | if (refDestructuringErrors.shorthandAssign < 0) | |
| 3434 | { refDestructuringErrors.shorthandAssign = this.start; } | |
| 3435 | prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); | |
| 3436 | } else { | |
| 3437 | prop.value = this.copyNode(prop.key); | |
| 3438 | } | |
| 3439 | prop.kind = "init"; | |
| 3440 | prop.shorthand = true; | |
| 3441 | } else { this.unexpected(); } | |
| 3442 | }; | |
| 3443 | ||
| 3444 | pp$5.parsePropertyName = function(prop) { | |
| 3445 | if (this.options.ecmaVersion >= 6) { | |
| 3446 | if (this.eat(types$1.bracketL)) { | |
| 3447 | prop.computed = true; | |
| 3448 | prop.key = this.parseMaybeAssign(); | |
| 3449 | this.expect(types$1.bracketR); | |
| 3450 | return prop.key | |
| 3451 | } else { | |
| 3452 | prop.computed = false; | |
| 3453 | } | |
| 3454 | } | |
| 3455 | return prop.key = this.type === types$1.num || this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never") | |
| 3456 | }; | |
| 3457 | ||
| 3458 | // Initialize empty function node. | |
| 3459 | ||
| 3460 | pp$5.initFunction = function(node) { | |
| 3461 | node.id = null; | |
| 3462 | if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; } | |
| 3463 | if (this.options.ecmaVersion >= 8) { node.async = false; } | |
| 3464 | }; | |
| 3465 | ||
| 3466 | // Parse object or class method. | |
| 3467 | ||
| 3468 | pp$5.parseMethod = function(isGenerator, isAsync, allowDirectSuper) { | |
| 3469 | var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
| 3470 | ||
| 3471 | this.initFunction(node); | |
| 3472 | if (this.options.ecmaVersion >= 6) | |
| 3473 | { node.generator = isGenerator; } | |
| 3474 | if (this.options.ecmaVersion >= 8) | |
| 3475 | { node.async = !!isAsync; } | |
| 3476 | ||
| 3477 | this.yieldPos = 0; | |
| 3478 | this.awaitPos = 0; | |
| 3479 | this.awaitIdentPos = 0; | |
| 3480 | this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0)); | |
| 3481 | ||
| 3482 | this.expect(types$1.parenL); | |
| 3483 | node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); | |
| 3484 | this.checkYieldAwaitInDefaultParams(); | |
| 3485 | this.parseFunctionBody(node, false, true, false); | |
| 3486 | ||
| 3487 | this.yieldPos = oldYieldPos; | |
| 3488 | this.awaitPos = oldAwaitPos; | |
| 3489 | this.awaitIdentPos = oldAwaitIdentPos; | |
| 3490 | return this.finishNode(node, "FunctionExpression") | |
| 3491 | }; | |
| 3492 | ||
| 3493 | // Parse arrow function expression with given parameters. | |
| 3494 | ||
| 3495 | pp$5.parseArrowExpression = function(node, params, isAsync, forInit) { | |
| 3496 | var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; | |
| 3497 | ||
| 3498 | this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW); | |
| 3499 | this.initFunction(node); | |
| 3500 | if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } | |
| 3501 | ||
| 3502 | this.yieldPos = 0; | |
| 3503 | this.awaitPos = 0; | |
| 3504 | this.awaitIdentPos = 0; | |
| 3505 | ||
| 3506 | node.params = this.toAssignableList(params, true); | |
| 3507 | this.parseFunctionBody(node, true, false, forInit); | |
| 3508 | ||
| 3509 | this.yieldPos = oldYieldPos; | |
| 3510 | this.awaitPos = oldAwaitPos; | |
| 3511 | this.awaitIdentPos = oldAwaitIdentPos; | |
| 3512 | return this.finishNode(node, "ArrowFunctionExpression") | |
| 3513 | }; | |
| 3514 | ||
| 3515 | // Parse function body and check parameters. | |
| 3516 | ||
| 3517 | pp$5.parseFunctionBody = function(node, isArrowFunction, isMethod, forInit) { | |
| 3518 | var isExpression = isArrowFunction && this.type !== types$1.braceL; | |
| 3519 | var oldStrict = this.strict, useStrict = false; | |
| 3520 | ||
| 3521 | if (isExpression) { | |
| 3522 | node.body = this.parseMaybeAssign(forInit); | |
| 3523 | node.expression = true; | |
| 3524 | this.checkParams(node, false); | |
| 3525 | } else { | |
| 3526 | var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); | |
| 3527 | if (!oldStrict || nonSimple) { | |
| 3528 | useStrict = this.strictDirective(this.end); | |
| 3529 | // If this is a strict mode function, verify that argument names | |
| 3530 | // are not repeated, and it does not try to bind the words `eval` | |
| 3531 | // or `arguments`. | |
| 3532 | if (useStrict && nonSimple) | |
| 3533 | { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } | |
| 3534 | } | |
| 3535 | // Start a new scope with regard to labels and the `inFunction` | |
| 3536 | // flag (restore them to their old value afterwards). | |
| 3537 | var oldLabels = this.labels; | |
| 3538 | this.labels = []; | |
| 3539 | if (useStrict) { this.strict = true; } | |
| 3540 | ||
| 3541 | // Add the params to varDeclaredNames to ensure that an error is thrown | |
| 3542 | // if a let/const declaration in the function clashes with one of the params. | |
| 3543 | this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); | |
| 3544 | // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' | |
| 3545 | if (this.strict && node.id) { this.checkLValSimple(node.id, BIND_OUTSIDE); } | |
| 3546 | node.body = this.parseBlock(false, undefined, useStrict && !oldStrict); | |
| 3547 | node.expression = false; | |
| 3548 | this.adaptDirectivePrologue(node.body.body); | |
| 3549 | this.labels = oldLabels; | |
| 3550 | } | |
| 3551 | this.exitScope(); | |
| 3552 | }; | |
| 3553 | ||
| 3554 | pp$5.isSimpleParamList = function(params) { | |
| 3555 | for (var i = 0, list = params; i < list.length; i += 1) | |
| 3556 | { | |
| 3557 | var param = list[i]; | |
| 3558 | ||
| 3559 | if (param.type !== "Identifier") { return false | |
| 3560 | } } | |
| 3561 | return true | |
| 3562 | }; | |
| 3563 | ||
| 3564 | // Checks function params for various disallowed patterns such as using "eval" | |
| 3565 | // or "arguments" and duplicate parameters. | |
| 3566 | ||
| 3567 | pp$5.checkParams = function(node, allowDuplicates) { | |
| 3568 | var nameHash = Object.create(null); | |
| 3569 | for (var i = 0, list = node.params; i < list.length; i += 1) | |
| 3570 | { | |
| 3571 | var param = list[i]; | |
| 3572 | ||
| 3573 | this.checkLValInnerPattern(param, BIND_VAR, allowDuplicates ? null : nameHash); | |
| 3574 | } | |
| 3575 | }; | |
| 3576 | ||
| 3577 | // Parses a comma-separated list of expressions, and returns them as | |
| 3578 | // an array. `close` is the token type that ends the list, and | |
| 3579 | // `allowEmpty` can be turned on to allow subsequent commas with | |
| 3580 | // nothing in between them to be parsed as `null` (which is needed | |
| 3581 | // for array literals). | |
| 3582 | ||
| 3583 | pp$5.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { | |
| 3584 | var elts = [], first = true; | |
| 3585 | while (!this.eat(close)) { | |
| 3586 | if (!first) { | |
| 3587 | this.expect(types$1.comma); | |
| 3588 | if (allowTrailingComma && this.afterTrailingComma(close)) { break } | |
| 3589 | } else { first = false; } | |
| 3590 | ||
| 3591 | var elt = (void 0); | |
| 3592 | if (allowEmpty && this.type === types$1.comma) | |
| 3593 | { elt = null; } | |
| 3594 | else if (this.type === types$1.ellipsis) { | |
| 3595 | elt = this.parseSpread(refDestructuringErrors); | |
| 3596 | if (refDestructuringErrors && this.type === types$1.comma && refDestructuringErrors.trailingComma < 0) | |
| 3597 | { refDestructuringErrors.trailingComma = this.start; } | |
| 3598 | } else { | |
| 3599 | elt = this.parseMaybeAssign(false, refDestructuringErrors); | |
| 3600 | } | |
| 3601 | elts.push(elt); | |
| 3602 | } | |
| 3603 | return elts | |
| 3604 | }; | |
| 3605 | ||
| 3606 | pp$5.checkUnreserved = function(ref) { | |
| 3607 | var start = ref.start; | |
| 3608 | var end = ref.end; | |
| 3609 | var name = ref.name; | |
| 3610 | ||
| 3611 | if (this.inGenerator && name === "yield") | |
| 3612 | { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); } | |
| 3613 | if (this.inAsync && name === "await") | |
| 3614 | { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); } | |
| 3615 | if (!(this.currentThisScope().flags & SCOPE_VAR) && name === "arguments") | |
| 3616 | { this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer"); } | |
| 3617 | if (this.inClassStaticBlock && (name === "arguments" || name === "await")) | |
| 3618 | { this.raise(start, ("Cannot use " + name + " in class static initialization block")); } | |
| 3619 | if (this.keywords.test(name)) | |
| 3620 | { this.raise(start, ("Unexpected keyword '" + name + "'")); } | |
| 3621 | if (this.options.ecmaVersion < 6 && | |
| 3622 | this.input.slice(start, end).indexOf("\\") !== -1) { return } | |
| 3623 | var re = this.strict ? this.reservedWordsStrict : this.reservedWords; | |
| 3624 | if (re.test(name)) { | |
| 3625 | if (!this.inAsync && name === "await") | |
| 3626 | { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); } | |
| 3627 | this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); | |
| 3628 | } | |
| 3629 | }; | |
| 3630 | ||
| 3631 | // Parse the next token as an identifier. If `liberal` is true (used | |
| 3632 | // when parsing properties), it will also convert keywords into | |
| 3633 | // identifiers. | |
| 3634 | ||
| 3635 | pp$5.parseIdent = function(liberal) { | |
| 3636 | var node = this.parseIdentNode(); | |
| 3637 | this.next(!!liberal); | |
| 3638 | this.finishNode(node, "Identifier"); | |
| 3639 | if (!liberal) { | |
| 3640 | this.checkUnreserved(node); | |
| 3641 | if (node.name === "await" && !this.awaitIdentPos) | |
| 3642 | { this.awaitIdentPos = node.start; } | |
| 3643 | } | |
| 3644 | return node | |
| 3645 | }; | |
| 3646 | ||
| 3647 | pp$5.parseIdentNode = function() { | |
| 3648 | var node = this.startNode(); | |
| 3649 | if (this.type === types$1.name) { | |
| 3650 | node.name = this.value; | |
| 3651 | } else if (this.type.keyword) { | |
| 3652 | node.name = this.type.keyword; | |
| 3653 | ||
| 3654 | // To fix https://github.com/acornjs/acorn/issues/575 | |
| 3655 | // `class` and `function` keywords push new context into this.context. | |
| 3656 | // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. | |
| 3657 | // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword | |
| 3658 | if ((node.name === "class" || node.name === "function") && | |
| 3659 | (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { | |
| 3660 | this.context.pop(); | |
| 3661 | } | |
| 3662 | this.type = types$1.name; | |
| 3663 | } else { | |
| 3664 | this.unexpected(); | |
| 3665 | } | |
| 3666 | return node | |
| 3667 | }; | |
| 3668 | ||
| 3669 | pp$5.parsePrivateIdent = function() { | |
| 3670 | var node = this.startNode(); | |
| 3671 | if (this.type === types$1.privateId) { | |
| 3672 | node.name = this.value; | |
| 3673 | } else { | |
| 3674 | this.unexpected(); | |
| 3675 | } | |
| 3676 | this.next(); | |
| 3677 | this.finishNode(node, "PrivateIdentifier"); | |
| 3678 | ||
| 3679 | // For validating existence | |
| 3680 | if (this.options.checkPrivateFields) { | |
| 3681 | if (this.privateNameStack.length === 0) { | |
| 3682 | this.raise(node.start, ("Private field '#" + (node.name) + "' must be declared in an enclosing class")); | |
| 3683 | } else { | |
| 3684 | this.privateNameStack[this.privateNameStack.length - 1].used.push(node); | |
| 3685 | } | |
| 3686 | } | |
| 3687 | ||
| 3688 | return node | |
| 3689 | }; | |
| 3690 | ||
| 3691 | // Parses yield expression inside generator. | |
| 3692 | ||
| 3693 | pp$5.parseYield = function(forInit) { | |
| 3694 | if (!this.yieldPos) { this.yieldPos = this.start; } | |
| 3695 | ||
| 3696 | var node = this.startNode(); | |
| 3697 | this.next(); | |
| 3698 | if (this.type === types$1.semi || this.canInsertSemicolon() || (this.type !== types$1.star && !this.type.startsExpr)) { | |
| 3699 | node.delegate = false; | |
| 3700 | node.argument = null; | |
| 3701 | } else { | |
| 3702 | node.delegate = this.eat(types$1.star); | |
| 3703 | node.argument = this.parseMaybeAssign(forInit); | |
| 3704 | } | |
| 3705 | return this.finishNode(node, "YieldExpression") | |
| 3706 | }; | |
| 3707 | ||
| 3708 | pp$5.parseAwait = function(forInit) { | |
| 3709 | if (!this.awaitPos) { this.awaitPos = this.start; } | |
| 3710 | ||
| 3711 | var node = this.startNode(); | |
| 3712 | this.next(); | |
| 3713 | node.argument = this.parseMaybeUnary(null, true, false, forInit); | |
| 3714 | return this.finishNode(node, "AwaitExpression") | |
| 3715 | }; | |
| 3716 | ||
| 3717 | var pp$4 = Parser.prototype; | |
| 3718 | ||
| 3719 | // This function is used to raise exceptions on parse errors. It | |
| 3720 | // takes an offset integer (into the current `input`) to indicate | |
| 3721 | // the location of the error, attaches the position to the end | |
| 3722 | // of the error message, and then raises a `SyntaxError` with that | |
| 3723 | // message. | |
| 3724 | ||
| 3725 | pp$4.raise = function(pos, message) { | |
| 3726 | var loc = getLineInfo(this.input, pos); | |
| 3727 | message += " (" + loc.line + ":" + loc.column + ")"; | |
| 3728 | if (this.sourceFile) { | |
| 3729 | message += " in " + this.sourceFile; | |
| 3730 | } | |
| 3731 | var err = new SyntaxError(message); | |
| 3732 | err.pos = pos; err.loc = loc; err.raisedAt = this.pos; | |
| 3733 | throw err | |
| 3734 | }; | |
| 3735 | ||
| 3736 | pp$4.raiseRecoverable = pp$4.raise; | |
| 3737 | ||
| 3738 | pp$4.curPosition = function() { | |
| 3739 | if (this.options.locations) { | |
| 3740 | return new Position(this.curLine, this.pos - this.lineStart) | |
| 3741 | } | |
| 3742 | }; | |
| 3743 | ||
| 3744 | var pp$3 = Parser.prototype; | |
| 3745 | ||
| 3746 | var Scope = function Scope(flags) { | |
| 3747 | this.flags = flags; | |
| 3748 | // A list of var-declared names in the current lexical scope | |
| 3749 | this.var = []; | |
| 3750 | // A list of lexically-declared names in the current lexical scope | |
| 3751 | this.lexical = []; | |
| 3752 | // A list of lexically-declared FunctionDeclaration names in the current lexical scope | |
| 3753 | this.functions = []; | |
| 3754 | }; | |
| 3755 | ||
| 3756 | // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. | |
| 3757 | ||
| 3758 | pp$3.enterScope = function(flags) { | |
| 3759 | this.scopeStack.push(new Scope(flags)); | |
| 3760 | }; | |
| 3761 | ||
| 3762 | pp$3.exitScope = function() { | |
| 3763 | this.scopeStack.pop(); | |
| 3764 | }; | |
| 3765 | ||
| 3766 | // The spec says: | |
| 3767 | // > At the top level of a function, or script, function declarations are | |
| 3768 | // > treated like var declarations rather than like lexical declarations. | |
| 3769 | pp$3.treatFunctionsAsVarInScope = function(scope) { | |
| 3770 | return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP) | |
| 3771 | }; | |
| 3772 | ||
| 3773 | pp$3.declareName = function(name, bindingType, pos) { | |
| 3774 | var redeclared = false; | |
| 3775 | if (bindingType === BIND_LEXICAL) { | |
| 3776 | var scope = this.currentScope(); | |
| 3777 | redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1; | |
| 3778 | scope.lexical.push(name); | |
| 3779 | if (this.inModule && (scope.flags & SCOPE_TOP)) | |
| 3780 | { delete this.undefinedExports[name]; } | |
| 3781 | } else if (bindingType === BIND_SIMPLE_CATCH) { | |
| 3782 | var scope$1 = this.currentScope(); | |
| 3783 | scope$1.lexical.push(name); | |
| 3784 | } else if (bindingType === BIND_FUNCTION) { | |
| 3785 | var scope$2 = this.currentScope(); | |
| 3786 | if (this.treatFunctionsAsVar) | |
| 3787 | { redeclared = scope$2.lexical.indexOf(name) > -1; } | |
| 3788 | else | |
| 3789 | { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; } | |
| 3790 | scope$2.functions.push(name); | |
| 3791 | } else { | |
| 3792 | for (var i = this.scopeStack.length - 1; i >= 0; --i) { | |
| 3793 | var scope$3 = this.scopeStack[i]; | |
| 3794 | if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) || | |
| 3795 | !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) { | |
| 3796 | redeclared = true; | |
| 3797 | break | |
| 3798 | } | |
| 3799 | scope$3.var.push(name); | |
| 3800 | if (this.inModule && (scope$3.flags & SCOPE_TOP)) | |
| 3801 | { delete this.undefinedExports[name]; } | |
| 3802 | if (scope$3.flags & SCOPE_VAR) { break } | |
| 3803 | } | |
| 3804 | } | |
| 3805 | if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); } | |
| 3806 | }; | |
| 3807 | ||
| 3808 | pp$3.checkLocalExport = function(id) { | |
| 3809 | // scope.functions must be empty as Module code is always strict. | |
| 3810 | if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && | |
| 3811 | this.scopeStack[0].var.indexOf(id.name) === -1) { | |
| 3812 | this.undefinedExports[id.name] = id; | |
| 3813 | } | |
| 3814 | }; | |
| 3815 | ||
| 3816 | pp$3.currentScope = function() { | |
| 3817 | return this.scopeStack[this.scopeStack.length - 1] | |
| 3818 | }; | |
| 3819 | ||
| 3820 | pp$3.currentVarScope = function() { | |
| 3821 | for (var i = this.scopeStack.length - 1;; i--) { | |
| 3822 | var scope = this.scopeStack[i]; | |
| 3823 | if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK)) { return scope } | |
| 3824 | } | |
| 3825 | }; | |
| 3826 | ||
| 3827 | // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. | |
| 3828 | pp$3.currentThisScope = function() { | |
| 3829 | for (var i = this.scopeStack.length - 1;; i--) { | |
| 3830 | var scope = this.scopeStack[i]; | |
| 3831 | if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK) && | |
| 3832 | !(scope.flags & SCOPE_ARROW)) { return scope } | |
| 3833 | } | |
| 3834 | }; | |
| 3835 | ||
| 3836 | var Node = function Node(parser, pos, loc) { | |
| 3837 | this.type = ""; | |
| 3838 | this.start = pos; | |
| 3839 | this.end = 0; | |
| 3840 | if (parser.options.locations) | |
| 3841 | { this.loc = new SourceLocation(parser, loc); } | |
| 3842 | if (parser.options.directSourceFile) | |
| 3843 | { this.sourceFile = parser.options.directSourceFile; } | |
| 3844 | if (parser.options.ranges) | |
| 3845 | { this.range = [pos, 0]; } | |
| 3846 | }; | |
| 3847 | ||
| 3848 | // Start an AST node, attaching a start offset. | |
| 3849 | ||
| 3850 | var pp$2 = Parser.prototype; | |
| 3851 | ||
| 3852 | pp$2.startNode = function() { | |
| 3853 | return new Node(this, this.start, this.startLoc) | |
| 3854 | }; | |
| 3855 | ||
| 3856 | pp$2.startNodeAt = function(pos, loc) { | |
| 3857 | return new Node(this, pos, loc) | |
| 3858 | }; | |
| 3859 | ||
| 3860 | // Finish an AST node, adding `type` and `end` properties. | |
| 3861 | ||
| 3862 | function finishNodeAt(node, type, pos, loc) { | |
| 3863 | node.type = type; | |
| 3864 | node.end = pos; | |
| 3865 | if (this.options.locations) | |
| 3866 | { node.loc.end = loc; } | |
| 3867 | if (this.options.ranges) | |
| 3868 | { node.range[1] = pos; } | |
| 3869 | return node | |
| 3870 | } | |
| 3871 | ||
| 3872 | pp$2.finishNode = function(node, type) { | |
| 3873 | return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) | |
| 3874 | }; | |
| 3875 | ||
| 3876 | // Finish node at given position | |
| 3877 | ||
| 3878 | pp$2.finishNodeAt = function(node, type, pos, loc) { | |
| 3879 | return finishNodeAt.call(this, node, type, pos, loc) | |
| 3880 | }; | |
| 3881 | ||
| 3882 | pp$2.copyNode = function(node) { | |
| 3883 | var newNode = new Node(this, node.start, this.startLoc); | |
| 3884 | for (var prop in node) { newNode[prop] = node[prop]; } | |
| 3885 | return newNode | |
| 3886 | }; | |
| 3887 | ||
| 3888 | // This file was generated by "bin/generate-unicode-script-values.js". Do not modify manually! | |
| 3889 | var scriptValuesAddedInUnicode = "Gara Garay Gukh Gurung_Khema Hrkt Katakana_Or_Hiragana Kawi Kirat_Rai Krai Nag_Mundari Nagm Ol_Onal Onao Sunu Sunuwar Todhri Todr Tulu_Tigalari Tutg Unknown Zzzz"; | |
| 3890 | ||
| 3891 | // This file contains Unicode properties extracted from the ECMAScript specification. | |
| 3892 | // The lists are extracted like so: | |
| 3893 | // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText) | |
| 3894 | ||
| 3895 | // #table-binary-unicode-properties | |
| 3896 | var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"; | |
| 3897 | var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"; | |
| 3898 | var ecma11BinaryProperties = ecma10BinaryProperties; | |
| 3899 | var ecma12BinaryProperties = ecma11BinaryProperties + " EBase EComp EMod EPres ExtPict"; | |
| 3900 | var ecma13BinaryProperties = ecma12BinaryProperties; | |
| 3901 | var ecma14BinaryProperties = ecma13BinaryProperties; | |
| 3902 | ||
| 3903 | var unicodeBinaryProperties = { | |
| 3904 | 9: ecma9BinaryProperties, | |
| 3905 | 10: ecma10BinaryProperties, | |
| 3906 | 11: ecma11BinaryProperties, | |
| 3907 | 12: ecma12BinaryProperties, | |
| 3908 | 13: ecma13BinaryProperties, | |
| 3909 | 14: ecma14BinaryProperties | |
| 3910 | }; | |
| 3911 | ||
| 3912 | // #table-binary-unicode-properties-of-strings | |
| 3913 | var ecma14BinaryPropertiesOfStrings = "Basic_Emoji Emoji_Keycap_Sequence RGI_Emoji_Modifier_Sequence RGI_Emoji_Flag_Sequence RGI_Emoji_Tag_Sequence RGI_Emoji_ZWJ_Sequence RGI_Emoji"; | |
| 3914 | ||
| 3915 | var unicodeBinaryPropertiesOfStrings = { | |
| 3916 | 9: "", | |
| 3917 | 10: "", | |
| 3918 | 11: "", | |
| 3919 | 12: "", | |
| 3920 | 13: "", | |
| 3921 | 14: ecma14BinaryPropertiesOfStrings | |
| 3922 | }; | |
| 3923 | ||
| 3924 | // #table-unicode-general-category-values | |
| 3925 | var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; | |
| 3926 | ||
| 3927 | // #table-unicode-script-values | |
| 3928 | var ecma9ScriptValues = "Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"; | |
| 3929 | var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"; | |
| 3930 | var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"; | |
| 3931 | var ecma12ScriptValues = ecma11ScriptValues + " Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi"; | |
| 3932 | var ecma13ScriptValues = ecma12ScriptValues + " Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith"; | |
| 3933 | var ecma14ScriptValues = ecma13ScriptValues + " " + scriptValuesAddedInUnicode; | |
| 3934 | ||
| 3935 | var unicodeScriptValues = { | |
| 3936 | 9: ecma9ScriptValues, | |
| 3937 | 10: ecma10ScriptValues, | |
| 3938 | 11: ecma11ScriptValues, | |
| 3939 | 12: ecma12ScriptValues, | |
| 3940 | 13: ecma13ScriptValues, | |
| 3941 | 14: ecma14ScriptValues | |
| 3942 | }; | |
| 3943 | ||
| 3944 | var data = {}; | |
| 3945 | function buildUnicodeData(ecmaVersion) { | |
| 3946 | var d = data[ecmaVersion] = { | |
| 3947 | binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues), | |
| 3948 | binaryOfStrings: wordsRegexp(unicodeBinaryPropertiesOfStrings[ecmaVersion]), | |
| 3949 | nonBinary: { | |
| 3950 | General_Category: wordsRegexp(unicodeGeneralCategoryValues), | |
| 3951 | Script: wordsRegexp(unicodeScriptValues[ecmaVersion]) | |
| 3952 | } | |
| 3953 | }; | |
| 3954 | d.nonBinary.Script_Extensions = d.nonBinary.Script; | |
| 3955 | ||
| 3956 | d.nonBinary.gc = d.nonBinary.General_Category; | |
| 3957 | d.nonBinary.sc = d.nonBinary.Script; | |
| 3958 | d.nonBinary.scx = d.nonBinary.Script_Extensions; | |
| 3959 | } | |
| 3960 | ||
| 3961 | for (var i = 0, list = [9, 10, 11, 12, 13, 14]; i < list.length; i += 1) { | |
| 3962 | var ecmaVersion = list[i]; | |
| 3963 | ||
| 3964 | buildUnicodeData(ecmaVersion); | |
| 3965 | } | |
| 3966 | ||
| 3967 | var pp$1 = Parser.prototype; | |
| 3968 | ||
| 3969 | // Track disjunction structure to determine whether a duplicate | |
| 3970 | // capture group name is allowed because it is in a separate branch. | |
| 3971 | var BranchID = function BranchID(parent, base) { | |
| 3972 | // Parent disjunction branch | |
| 3973 | this.parent = parent; | |
| 3974 | // Identifies this set of sibling branches | |
| 3975 | this.base = base || this; | |
| 3976 | }; | |
| 3977 | ||
| 3978 | BranchID.prototype.separatedFrom = function separatedFrom (alt) { | |
| 3979 | // A branch is separate from another branch if they or any of | |
| 3980 | // their parents are siblings in a given disjunction | |
| 3981 | for (var self = this; self; self = self.parent) { | |
| 3982 | for (var other = alt; other; other = other.parent) { | |
| 3983 | if (self.base === other.base && self !== other) { return true } | |
| 3984 | } | |
| 3985 | } | |
| 3986 | return false | |
| 3987 | }; | |
| 3988 | ||
| 3989 | BranchID.prototype.sibling = function sibling () { | |
| 3990 | return new BranchID(this.parent, this.base) | |
| 3991 | }; | |
| 3992 | ||
| 3993 | var RegExpValidationState = function RegExpValidationState(parser) { | |
| 3994 | this.parser = parser; | |
| 3995 | this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "") + (parser.options.ecmaVersion >= 13 ? "d" : "") + (parser.options.ecmaVersion >= 15 ? "v" : ""); | |
| 3996 | this.unicodeProperties = data[parser.options.ecmaVersion >= 14 ? 14 : parser.options.ecmaVersion]; | |
| 3997 | this.source = ""; | |
| 3998 | this.flags = ""; | |
| 3999 | this.start = 0; | |
| 4000 | this.switchU = false; | |
| 4001 | this.switchV = false; | |
| 4002 | this.switchN = false; | |
| 4003 | this.pos = 0; | |
| 4004 | this.lastIntValue = 0; | |
| 4005 | this.lastStringValue = ""; | |
| 4006 | this.lastAssertionIsQuantifiable = false; | |
| 4007 | this.numCapturingParens = 0; | |
| 4008 | this.maxBackReference = 0; | |
| 4009 | this.groupNames = Object.create(null); | |
| 4010 | this.backReferenceNames = []; | |
| 4011 | this.branchID = null; | |
| 4012 | }; | |
| 4013 | ||
| 4014 | RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { | |
| 4015 | var unicodeSets = flags.indexOf("v") !== -1; | |
| 4016 | var unicode = flags.indexOf("u") !== -1; | |
| 4017 | this.start = start | 0; | |
| 4018 | this.source = pattern + ""; | |
| 4019 | this.flags = flags; | |
| 4020 | if (unicodeSets && this.parser.options.ecmaVersion >= 15) { | |
| 4021 | this.switchU = true; | |
| 4022 | this.switchV = true; | |
| 4023 | this.switchN = true; | |
| 4024 | } else { | |
| 4025 | this.switchU = unicode && this.parser.options.ecmaVersion >= 6; | |
| 4026 | this.switchV = false; | |
| 4027 | this.switchN = unicode && this.parser.options.ecmaVersion >= 9; | |
| 4028 | } | |
| 4029 | }; | |
| 4030 | ||
| 4031 | RegExpValidationState.prototype.raise = function raise (message) { | |
| 4032 | this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); | |
| 4033 | }; | |
| 4034 | ||
| 4035 | // If u flag is given, this returns the code point at the index (it combines a surrogate pair). | |
| 4036 | // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). | |
| 4037 | RegExpValidationState.prototype.at = function at (i, forceU) { | |
| 4038 | if ( forceU === void 0 ) forceU = false; | |
| 4039 | ||
| 4040 | var s = this.source; | |
| 4041 | var l = s.length; | |
| 4042 | if (i >= l) { | |
| 4043 | return -1 | |
| 4044 | } | |
| 4045 | var c = s.charCodeAt(i); | |
| 4046 | if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { | |
| 4047 | return c | |
| 4048 | } | |
| 4049 | var next = s.charCodeAt(i + 1); | |
| 4050 | return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c | |
| 4051 | }; | |
| 4052 | ||
| 4053 | RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) { | |
| 4054 | if ( forceU === void 0 ) forceU = false; | |
| 4055 | ||
| 4056 | var s = this.source; | |
| 4057 | var l = s.length; | |
| 4058 | if (i >= l) { | |
| 4059 | return l | |
| 4060 | } | |
| 4061 | var c = s.charCodeAt(i), next; | |
| 4062 | if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || | |
| 4063 | (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) { | |
| 4064 | return i + 1 | |
| 4065 | } | |
| 4066 | return i + 2 | |
| 4067 | }; | |
| 4068 | ||
| 4069 | RegExpValidationState.prototype.current = function current (forceU) { | |
| 4070 | if ( forceU === void 0 ) forceU = false; | |
| 4071 | ||
| 4072 | return this.at(this.pos, forceU) | |
| 4073 | }; | |
| 4074 | ||
| 4075 | RegExpValidationState.prototype.lookahead = function lookahead (forceU) { | |
| 4076 | if ( forceU === void 0 ) forceU = false; | |
| 4077 | ||
| 4078 | return this.at(this.nextIndex(this.pos, forceU), forceU) | |
| 4079 | }; | |
| 4080 | ||
| 4081 | RegExpValidationState.prototype.advance = function advance (forceU) { | |
| 4082 | if ( forceU === void 0 ) forceU = false; | |
| 4083 | ||
| 4084 | this.pos = this.nextIndex(this.pos, forceU); | |
| 4085 | }; | |
| 4086 | ||
| 4087 | RegExpValidationState.prototype.eat = function eat (ch, forceU) { | |
| 4088 | if ( forceU === void 0 ) forceU = false; | |
| 4089 | ||
| 4090 | if (this.current(forceU) === ch) { | |
| 4091 | this.advance(forceU); | |
| 4092 | return true | |
| 4093 | } | |
| 4094 | return false | |
| 4095 | }; | |
| 4096 | ||
| 4097 | RegExpValidationState.prototype.eatChars = function eatChars (chs, forceU) { | |
| 4098 | if ( forceU === void 0 ) forceU = false; | |
| 4099 | ||
| 4100 | var pos = this.pos; | |
| 4101 | for (var i = 0, list = chs; i < list.length; i += 1) { | |
| 4102 | var ch = list[i]; | |
| 4103 | ||
| 4104 | var current = this.at(pos, forceU); | |
| 4105 | if (current === -1 || current !== ch) { | |
| 4106 | return false | |
| 4107 | } | |
| 4108 | pos = this.nextIndex(pos, forceU); | |
| 4109 | } | |
| 4110 | this.pos = pos; | |
| 4111 | return true | |
| 4112 | }; | |
| 4113 | ||
| 4114 | /** | |
| 4115 | * Validate the flags part of a given RegExpLiteral. | |
| 4116 | * | |
| 4117 | * @param {RegExpValidationState} state The state to validate RegExp. | |
| 4118 | * @returns {void} | |
| 4119 | */ | |
| 4120 | pp$1.validateRegExpFlags = function(state) { | |
| 4121 | var validFlags = state.validFlags; | |
| 4122 | var flags = state.flags; | |
| 4123 | ||
| 4124 | var u = false; | |
| 4125 | var v = false; | |
| 4126 | ||
| 4127 | for (var i = 0; i < flags.length; i++) { | |
| 4128 | var flag = flags.charAt(i); | |
| 4129 | if (validFlags.indexOf(flag) === -1) { | |
| 4130 | this.raise(state.start, "Invalid regular expression flag"); | |
| 4131 | } | |
| 4132 | if (flags.indexOf(flag, i + 1) > -1) { | |
| 4133 | this.raise(state.start, "Duplicate regular expression flag"); | |
| 4134 | } | |
| 4135 | if (flag === "u") { u = true; } | |
| 4136 | if (flag === "v") { v = true; } | |
| 4137 | } | |
| 4138 | if (this.options.ecmaVersion >= 15 && u && v) { | |
| 4139 | this.raise(state.start, "Invalid regular expression flag"); | |
| 4140 | } | |
| 4141 | }; | |
| 4142 | ||
| 4143 | function hasProp(obj) { | |
| 4144 | for (var _ in obj) { return true } | |
| 4145 | return false | |
| 4146 | } | |
| 4147 | ||
| 4148 | /** | |
| 4149 | * Validate the pattern part of a given RegExpLiteral. | |
| 4150 | * | |
| 4151 | * @param {RegExpValidationState} state The state to validate RegExp. | |
| 4152 | * @returns {void} | |
| 4153 | */ | |
| 4154 | pp$1.validateRegExpPattern = function(state) { | |
| 4155 | this.regexp_pattern(state); | |
| 4156 | ||
| 4157 | // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of | |
| 4158 | // parsing contains a |GroupName|, reparse with the goal symbol | |
| 4159 | // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* | |
| 4160 | // exception if _P_ did not conform to the grammar, if any elements of _P_ | |
| 4161 | // were not matched by the parse, or if any Early Error conditions exist. | |
| 4162 | if (!state.switchN && this.options.ecmaVersion >= 9 && hasProp(state.groupNames)) { | |
| 4163 | state.switchN = true; | |
| 4164 | this.regexp_pattern(state); | |
| 4165 | } | |
| 4166 | }; | |
| 4167 | ||
| 4168 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern | |
| 4169 | pp$1.regexp_pattern = function(state) { | |
| 4170 | state.pos = 0; | |
| 4171 | state.lastIntValue = 0; | |
| 4172 | state.lastStringValue = ""; | |
| 4173 | state.lastAssertionIsQuantifiable = false; | |
| 4174 | state.numCapturingParens = 0; | |
| 4175 | state.maxBackReference = 0; | |
| 4176 | state.groupNames = Object.create(null); | |
| 4177 | state.backReferenceNames.length = 0; | |
| 4178 | state.branchID = null; | |
| 4179 | ||
| 4180 | this.regexp_disjunction(state); | |
| 4181 | ||
| 4182 | if (state.pos !== state.source.length) { | |
| 4183 | // Make the same messages as V8. | |
| 4184 | if (state.eat(0x29 /* ) */)) { | |
| 4185 | state.raise("Unmatched ')'"); | |
| 4186 | } | |
| 4187 | if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) { | |
| 4188 | state.raise("Lone quantifier brackets"); | |
| 4189 | } | |
| 4190 | } | |
| 4191 | if (state.maxBackReference > state.numCapturingParens) { | |
| 4192 | state.raise("Invalid escape"); | |
| 4193 | } | |
| 4194 | for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { | |
| 4195 | var name = list[i]; | |
| 4196 | ||
| 4197 | if (!state.groupNames[name]) { | |
| 4198 | state.raise("Invalid named capture referenced"); | |
| 4199 | } | |
| 4200 | } | |
| 4201 | }; | |
| 4202 | ||
| 4203 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction | |
| 4204 | pp$1.regexp_disjunction = function(state) { | |
| 4205 | var trackDisjunction = this.options.ecmaVersion >= 16; | |
| 4206 | if (trackDisjunction) { state.branchID = new BranchID(state.branchID, null); } | |
| 4207 | this.regexp_alternative(state); | |
| 4208 | while (state.eat(0x7C /* | */)) { | |
| 4209 | if (trackDisjunction) { state.branchID = state.branchID.sibling(); } | |
| 4210 | this.regexp_alternative(state); | |
| 4211 | } | |
| 4212 | if (trackDisjunction) { state.branchID = state.branchID.parent; } | |
| 4213 | ||
| 4214 | // Make the same message as V8. | |
| 4215 | if (this.regexp_eatQuantifier(state, true)) { | |
| 4216 | state.raise("Nothing to repeat"); | |
| 4217 | } | |
| 4218 | if (state.eat(0x7B /* { */)) { | |
| 4219 | state.raise("Lone quantifier brackets"); | |
| 4220 | } | |
| 4221 | }; | |
| 4222 | ||
| 4223 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative | |
| 4224 | pp$1.regexp_alternative = function(state) { | |
| 4225 | while (state.pos < state.source.length && this.regexp_eatTerm(state)) {} | |
| 4226 | }; | |
| 4227 | ||
| 4228 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term | |
| 4229 | pp$1.regexp_eatTerm = function(state) { | |
| 4230 | if (this.regexp_eatAssertion(state)) { | |
| 4231 | // Handle `QuantifiableAssertion Quantifier` alternative. | |
| 4232 | // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion | |
| 4233 | // is a QuantifiableAssertion. | |
| 4234 | if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { | |
| 4235 | // Make the same message as V8. | |
| 4236 | if (state.switchU) { | |
| 4237 | state.raise("Invalid quantifier"); | |
| 4238 | } | |
| 4239 | } | |
| 4240 | return true | |
| 4241 | } | |
| 4242 | ||
| 4243 | if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { | |
| 4244 | this.regexp_eatQuantifier(state); | |
| 4245 | return true | |
| 4246 | } | |
| 4247 | ||
| 4248 | return false | |
| 4249 | }; | |
| 4250 | ||
| 4251 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion | |
| 4252 | pp$1.regexp_eatAssertion = function(state) { | |
| 4253 | var start = state.pos; | |
| 4254 | state.lastAssertionIsQuantifiable = false; | |
| 4255 | ||
| 4256 | // ^, $ | |
| 4257 | if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { | |
| 4258 | return true | |
| 4259 | } | |
| 4260 | ||
| 4261 | // \b \B | |
| 4262 | if (state.eat(0x5C /* \ */)) { | |
| 4263 | if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { | |
| 4264 | return true | |
| 4265 | } | |
| 4266 | state.pos = start; | |
| 4267 | } | |
| 4268 | ||
| 4269 | // Lookahead / Lookbehind | |
| 4270 | if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { | |
| 4271 | var lookbehind = false; | |
| 4272 | if (this.options.ecmaVersion >= 9) { | |
| 4273 | lookbehind = state.eat(0x3C /* < */); | |
| 4274 | } | |
| 4275 | if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { | |
| 4276 | this.regexp_disjunction(state); | |
| 4277 | if (!state.eat(0x29 /* ) */)) { | |
| 4278 | state.raise("Unterminated group"); | |
| 4279 | } | |
| 4280 | state.lastAssertionIsQuantifiable = !lookbehind; | |
| 4281 | return true | |
| 4282 | } | |
| 4283 | } | |
| 4284 | ||
| 4285 | state.pos = start; | |
| 4286 | return false | |
| 4287 | }; | |
| 4288 | ||
| 4289 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier | |
| 4290 | pp$1.regexp_eatQuantifier = function(state, noError) { | |
| 4291 | if ( noError === void 0 ) noError = false; | |
| 4292 | ||
| 4293 | if (this.regexp_eatQuantifierPrefix(state, noError)) { | |
| 4294 | state.eat(0x3F /* ? */); | |
| 4295 | return true | |
| 4296 | } | |
| 4297 | return false | |
| 4298 | }; | |
| 4299 | ||
| 4300 | // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix | |
| 4301 | pp$1.regexp_eatQuantifierPrefix = function(state, noError) { | |
| 4302 | return ( | |
| 4303 | state.eat(0x2A /* * */) || | |
| 4304 | state.eat(0x2B /* + */) || | |
| 4305 | state.eat(0x3F /* ? */) || | |
| 4306 | this.regexp_eatBracedQuantifier(state, noError) | |
| 4307 | ) | |
| 4308 | }; | |
| 4309 | pp$1.regexp_eatBracedQuantifier = function(state, noError) { | |
| 4310 | var start = state.pos; | |
| 4311 | if (state.eat(0x7B /* { */)) { | |
| 4312 | var min = 0, max = -1; | |
| 4313 | if (this.regexp_eatDecimalDigits(state)) { | |
| 4314 | min = state.lastIntValue; | |
| 4315 | if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { | |
| 4316 | max = state.lastIntValue; | |
| 4317 | } | |
| 4318 | if (state.eat(0x7D /* } */)) { | |
| 4319 | // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term | |
| 4320 | if (max !== -1 && max < min && !noError) { | |
| 4321 | state.raise("numbers out of order in {} quantifier"); | |
| 4322 | } | |
| 4323 | return true | |
| 4324 | } | |
| 4325 | } | |
| 4326 | if (state.switchU && !noError) { | |
| 4327 | state.raise("Incomplete quantifier"); | |
| 4328 | } | |
| 4329 | state.pos = start; | |
| 4330 | } | |
| 4331 | return false | |
| 4332 | }; | |
| 4333 | ||
| 4334 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom | |
| 4335 | pp$1.regexp_eatAtom = function(state) { | |
| 4336 | return ( | |
| 4337 | this.regexp_eatPatternCharacters(state) || | |
| 4338 | state.eat(0x2E /* . */) || | |
| 4339 | this.regexp_eatReverseSolidusAtomEscape(state) || | |
| 4340 | this.regexp_eatCharacterClass(state) || | |
| 4341 | this.regexp_eatUncapturingGroup(state) || | |
| 4342 | this.regexp_eatCapturingGroup(state) | |
| 4343 | ) | |
| 4344 | }; | |
| 4345 | pp$1.regexp_eatReverseSolidusAtomEscape = function(state) { | |
| 4346 | var start = state.pos; | |
| 4347 | if (state.eat(0x5C /* \ */)) { | |
| 4348 | if (this.regexp_eatAtomEscape(state)) { | |
| 4349 | return true | |
| 4350 | } | |
| 4351 | state.pos = start; | |
| 4352 | } | |
| 4353 | return false | |
| 4354 | }; | |
| 4355 | pp$1.regexp_eatUncapturingGroup = function(state) { | |
| 4356 | var start = state.pos; | |
| 4357 | if (state.eat(0x28 /* ( */)) { | |
| 4358 | if (state.eat(0x3F /* ? */)) { | |
| 4359 | if (this.options.ecmaVersion >= 16) { | |
| 4360 | var addModifiers = this.regexp_eatModifiers(state); | |
| 4361 | var hasHyphen = state.eat(0x2D /* - */); | |
| 4362 | if (addModifiers || hasHyphen) { | |
| 4363 | for (var i = 0; i < addModifiers.length; i++) { | |
| 4364 | var modifier = addModifiers.charAt(i); | |
| 4365 | if (addModifiers.indexOf(modifier, i + 1) > -1) { | |
| 4366 | state.raise("Duplicate regular expression modifiers"); | |
| 4367 | } | |
| 4368 | } | |
| 4369 | if (hasHyphen) { | |
| 4370 | var removeModifiers = this.regexp_eatModifiers(state); | |
| 4371 | if (!addModifiers && !removeModifiers && state.current() === 0x3A /* : */) { | |
| 4372 | state.raise("Invalid regular expression modifiers"); | |
| 4373 | } | |
| 4374 | for (var i$1 = 0; i$1 < removeModifiers.length; i$1++) { | |
| 4375 | var modifier$1 = removeModifiers.charAt(i$1); | |
| 4376 | if ( | |
| 4377 | removeModifiers.indexOf(modifier$1, i$1 + 1) > -1 || | |
| 4378 | addModifiers.indexOf(modifier$1) > -1 | |
| 4379 | ) { | |
| 4380 | state.raise("Duplicate regular expression modifiers"); | |
| 4381 | } | |
| 4382 | } | |
| 4383 | } | |
| 4384 | } | |
| 4385 | } | |
| 4386 | if (state.eat(0x3A /* : */)) { | |
| 4387 | this.regexp_disjunction(state); | |
| 4388 | if (state.eat(0x29 /* ) */)) { | |
| 4389 | return true | |
| 4390 | } | |
| 4391 | state.raise("Unterminated group"); | |
| 4392 | } | |
| 4393 | } | |
| 4394 | state.pos = start; | |
| 4395 | } | |
| 4396 | return false | |
| 4397 | }; | |
| 4398 | pp$1.regexp_eatCapturingGroup = function(state) { | |
| 4399 | if (state.eat(0x28 /* ( */)) { | |
| 4400 | if (this.options.ecmaVersion >= 9) { | |
| 4401 | this.regexp_groupSpecifier(state); | |
| 4402 | } else if (state.current() === 0x3F /* ? */) { | |
| 4403 | state.raise("Invalid group"); | |
| 4404 | } | |
| 4405 | this.regexp_disjunction(state); | |
| 4406 | if (state.eat(0x29 /* ) */)) { | |
| 4407 | state.numCapturingParens += 1; | |
| 4408 | return true | |
| 4409 | } | |
| 4410 | state.raise("Unterminated group"); | |
| 4411 | } | |
| 4412 | return false | |
| 4413 | }; | |
| 4414 | // RegularExpressionModifiers :: | |
| 4415 | // [empty] | |
| 4416 | // RegularExpressionModifiers RegularExpressionModifier | |
| 4417 | pp$1.regexp_eatModifiers = function(state) { | |
| 4418 | var modifiers = ""; | |
| 4419 | var ch = 0; | |
| 4420 | while ((ch = state.current()) !== -1 && isRegularExpressionModifier(ch)) { | |
| 4421 | modifiers += codePointToString(ch); | |
| 4422 | state.advance(); | |
| 4423 | } | |
| 4424 | return modifiers | |
| 4425 | }; | |
| 4426 | // RegularExpressionModifier :: one of | |
| 4427 | // `i` `m` `s` | |
| 4428 | function isRegularExpressionModifier(ch) { | |
| 4429 | return ch === 0x69 /* i */ || ch === 0x6d /* m */ || ch === 0x73 /* s */ | |
| 4430 | } | |
| 4431 | ||
| 4432 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom | |
| 4433 | pp$1.regexp_eatExtendedAtom = function(state) { | |
| 4434 | return ( | |
| 4435 | state.eat(0x2E /* . */) || | |
| 4436 | this.regexp_eatReverseSolidusAtomEscape(state) || | |
| 4437 | this.regexp_eatCharacterClass(state) || | |
| 4438 | this.regexp_eatUncapturingGroup(state) || | |
| 4439 | this.regexp_eatCapturingGroup(state) || | |
| 4440 | this.regexp_eatInvalidBracedQuantifier(state) || | |
| 4441 | this.regexp_eatExtendedPatternCharacter(state) | |
| 4442 | ) | |
| 4443 | }; | |
| 4444 | ||
| 4445 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier | |
| 4446 | pp$1.regexp_eatInvalidBracedQuantifier = function(state) { | |
| 4447 | if (this.regexp_eatBracedQuantifier(state, true)) { | |
| 4448 | state.raise("Nothing to repeat"); | |
| 4449 | } | |
| 4450 | return false | |
| 4451 | }; | |
| 4452 | ||
| 4453 | // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter | |
| 4454 | pp$1.regexp_eatSyntaxCharacter = function(state) { | |
| 4455 | var ch = state.current(); | |
| 4456 | if (isSyntaxCharacter(ch)) { | |
| 4457 | state.lastIntValue = ch; | |
| 4458 | state.advance(); | |
| 4459 | return true | |
| 4460 | } | |
| 4461 | return false | |
| 4462 | }; | |
| 4463 | function isSyntaxCharacter(ch) { | |
| 4464 | return ( | |
| 4465 | ch === 0x24 /* $ */ || | |
| 4466 | ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || | |
| 4467 | ch === 0x2E /* . */ || | |
| 4468 | ch === 0x3F /* ? */ || | |
| 4469 | ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || | |
| 4470 | ch >= 0x7B /* { */ && ch <= 0x7D /* } */ | |
| 4471 | ) | |
| 4472 | } | |
| 4473 | ||
| 4474 | // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter | |
| 4475 | // But eat eager. | |
| 4476 | pp$1.regexp_eatPatternCharacters = function(state) { | |
| 4477 | var start = state.pos; | |
| 4478 | var ch = 0; | |
| 4479 | while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { | |
| 4480 | state.advance(); | |
| 4481 | } | |
| 4482 | return state.pos !== start | |
| 4483 | }; | |
| 4484 | ||
| 4485 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter | |
| 4486 | pp$1.regexp_eatExtendedPatternCharacter = function(state) { | |
| 4487 | var ch = state.current(); | |
| 4488 | if ( | |
| 4489 | ch !== -1 && | |
| 4490 | ch !== 0x24 /* $ */ && | |
| 4491 | !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && | |
| 4492 | ch !== 0x2E /* . */ && | |
| 4493 | ch !== 0x3F /* ? */ && | |
| 4494 | ch !== 0x5B /* [ */ && | |
| 4495 | ch !== 0x5E /* ^ */ && | |
| 4496 | ch !== 0x7C /* | */ | |
| 4497 | ) { | |
| 4498 | state.advance(); | |
| 4499 | return true | |
| 4500 | } | |
| 4501 | return false | |
| 4502 | }; | |
| 4503 | ||
| 4504 | // GroupSpecifier :: | |
| 4505 | // [empty] | |
| 4506 | // `?` GroupName | |
| 4507 | pp$1.regexp_groupSpecifier = function(state) { | |
| 4508 | if (state.eat(0x3F /* ? */)) { | |
| 4509 | if (!this.regexp_eatGroupName(state)) { state.raise("Invalid group"); } | |
| 4510 | var trackDisjunction = this.options.ecmaVersion >= 16; | |
| 4511 | var known = state.groupNames[state.lastStringValue]; | |
| 4512 | if (known) { | |
| 4513 | if (trackDisjunction) { | |
| 4514 | for (var i = 0, list = known; i < list.length; i += 1) { | |
| 4515 | var altID = list[i]; | |
| 4516 | ||
| 4517 | if (!altID.separatedFrom(state.branchID)) | |
| 4518 | { state.raise("Duplicate capture group name"); } | |
| 4519 | } | |
| 4520 | } else { | |
| 4521 | state.raise("Duplicate capture group name"); | |
| 4522 | } | |
| 4523 | } | |
| 4524 | if (trackDisjunction) { | |
| 4525 | (known || (state.groupNames[state.lastStringValue] = [])).push(state.branchID); | |
| 4526 | } else { | |
| 4527 | state.groupNames[state.lastStringValue] = true; | |
| 4528 | } | |
| 4529 | } | |
| 4530 | }; | |
| 4531 | ||
| 4532 | // GroupName :: | |
| 4533 | // `<` RegExpIdentifierName `>` | |
| 4534 | // Note: this updates `state.lastStringValue` property with the eaten name. | |
| 4535 | pp$1.regexp_eatGroupName = function(state) { | |
| 4536 | state.lastStringValue = ""; | |
| 4537 | if (state.eat(0x3C /* < */)) { | |
| 4538 | if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { | |
| 4539 | return true | |
| 4540 | } | |
| 4541 | state.raise("Invalid capture group name"); | |
| 4542 | } | |
| 4543 | return false | |
| 4544 | }; | |
| 4545 | ||
| 4546 | // RegExpIdentifierName :: | |
| 4547 | // RegExpIdentifierStart | |
| 4548 | // RegExpIdentifierName RegExpIdentifierPart | |
| 4549 | // Note: this updates `state.lastStringValue` property with the eaten name. | |
| 4550 | pp$1.regexp_eatRegExpIdentifierName = function(state) { | |
| 4551 | state.lastStringValue = ""; | |
| 4552 | if (this.regexp_eatRegExpIdentifierStart(state)) { | |
| 4553 | state.lastStringValue += codePointToString(state.lastIntValue); | |
| 4554 | while (this.regexp_eatRegExpIdentifierPart(state)) { | |
| 4555 | state.lastStringValue += codePointToString(state.lastIntValue); | |
| 4556 | } | |
| 4557 | return true | |
| 4558 | } | |
| 4559 | return false | |
| 4560 | }; | |
| 4561 | ||
| 4562 | // RegExpIdentifierStart :: | |
| 4563 | // UnicodeIDStart | |
| 4564 | // `$` | |
| 4565 | // `_` | |
| 4566 | // `\` RegExpUnicodeEscapeSequence[+U] | |
| 4567 | pp$1.regexp_eatRegExpIdentifierStart = function(state) { | |
| 4568 | var start = state.pos; | |
| 4569 | var forceU = this.options.ecmaVersion >= 11; | |
| 4570 | var ch = state.current(forceU); | |
| 4571 | state.advance(forceU); | |
| 4572 | ||
| 4573 | if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { | |
| 4574 | ch = state.lastIntValue; | |
| 4575 | } | |
| 4576 | if (isRegExpIdentifierStart(ch)) { | |
| 4577 | state.lastIntValue = ch; | |
| 4578 | return true | |
| 4579 | } | |
| 4580 | ||
| 4581 | state.pos = start; | |
| 4582 | return false | |
| 4583 | }; | |
| 4584 | function isRegExpIdentifierStart(ch) { | |
| 4585 | return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ | |
| 4586 | } | |
| 4587 | ||
| 4588 | // RegExpIdentifierPart :: | |
| 4589 | // UnicodeIDContinue | |
| 4590 | // `$` | |
| 4591 | // `_` | |
| 4592 | // `\` RegExpUnicodeEscapeSequence[+U] | |
| 4593 | // <ZWNJ> | |
| 4594 | // <ZWJ> | |
| 4595 | pp$1.regexp_eatRegExpIdentifierPart = function(state) { | |
| 4596 | var start = state.pos; | |
| 4597 | var forceU = this.options.ecmaVersion >= 11; | |
| 4598 | var ch = state.current(forceU); | |
| 4599 | state.advance(forceU); | |
| 4600 | ||
| 4601 | if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { | |
| 4602 | ch = state.lastIntValue; | |
| 4603 | } | |
| 4604 | if (isRegExpIdentifierPart(ch)) { | |
| 4605 | state.lastIntValue = ch; | |
| 4606 | return true | |
| 4607 | } | |
| 4608 | ||
| 4609 | state.pos = start; | |
| 4610 | return false | |
| 4611 | }; | |
| 4612 | function isRegExpIdentifierPart(ch) { | |
| 4613 | return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */ | |
| 4614 | } | |
| 4615 | ||
| 4616 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape | |
| 4617 | pp$1.regexp_eatAtomEscape = function(state) { | |
| 4618 | if ( | |
| 4619 | this.regexp_eatBackReference(state) || | |
| 4620 | this.regexp_eatCharacterClassEscape(state) || | |
| 4621 | this.regexp_eatCharacterEscape(state) || | |
| 4622 | (state.switchN && this.regexp_eatKGroupName(state)) | |
| 4623 | ) { | |
| 4624 | return true | |
| 4625 | } | |
| 4626 | if (state.switchU) { | |
| 4627 | // Make the same message as V8. | |
| 4628 | if (state.current() === 0x63 /* c */) { | |
| 4629 | state.raise("Invalid unicode escape"); | |
| 4630 | } | |
| 4631 | state.raise("Invalid escape"); | |
| 4632 | } | |
| 4633 | return false | |
| 4634 | }; | |
| 4635 | pp$1.regexp_eatBackReference = function(state) { | |
| 4636 | var start = state.pos; | |
| 4637 | if (this.regexp_eatDecimalEscape(state)) { | |
| 4638 | var n = state.lastIntValue; | |
| 4639 | if (state.switchU) { | |
| 4640 | // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape | |
| 4641 | if (n > state.maxBackReference) { | |
| 4642 | state.maxBackReference = n; | |
| 4643 | } | |
| 4644 | return true | |
| 4645 | } | |
| 4646 | if (n <= state.numCapturingParens) { | |
| 4647 | return true | |
| 4648 | } | |
| 4649 | state.pos = start; | |
| 4650 | } | |
| 4651 | return false | |
| 4652 | }; | |
| 4653 | pp$1.regexp_eatKGroupName = function(state) { | |
| 4654 | if (state.eat(0x6B /* k */)) { | |
| 4655 | if (this.regexp_eatGroupName(state)) { | |
| 4656 | state.backReferenceNames.push(state.lastStringValue); | |
| 4657 | return true | |
| 4658 | } | |
| 4659 | state.raise("Invalid named reference"); | |
| 4660 | } | |
| 4661 | return false | |
| 4662 | }; | |
| 4663 | ||
| 4664 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape | |
| 4665 | pp$1.regexp_eatCharacterEscape = function(state) { | |
| 4666 | return ( | |
| 4667 | this.regexp_eatControlEscape(state) || | |
| 4668 | this.regexp_eatCControlLetter(state) || | |
| 4669 | this.regexp_eatZero(state) || | |
| 4670 | this.regexp_eatHexEscapeSequence(state) || | |
| 4671 | this.regexp_eatRegExpUnicodeEscapeSequence(state, false) || | |
| 4672 | (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || | |
| 4673 | this.regexp_eatIdentityEscape(state) | |
| 4674 | ) | |
| 4675 | }; | |
| 4676 | pp$1.regexp_eatCControlLetter = function(state) { | |
| 4677 | var start = state.pos; | |
| 4678 | if (state.eat(0x63 /* c */)) { | |
| 4679 | if (this.regexp_eatControlLetter(state)) { | |
| 4680 | return true | |
| 4681 | } | |
| 4682 | state.pos = start; | |
| 4683 | } | |
| 4684 | return false | |
| 4685 | }; | |
| 4686 | pp$1.regexp_eatZero = function(state) { | |
| 4687 | if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { | |
| 4688 | state.lastIntValue = 0; | |
| 4689 | state.advance(); | |
| 4690 | return true | |
| 4691 | } | |
| 4692 | return false | |
| 4693 | }; | |
| 4694 | ||
| 4695 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape | |
| 4696 | pp$1.regexp_eatControlEscape = function(state) { | |
| 4697 | var ch = state.current(); | |
| 4698 | if (ch === 0x74 /* t */) { | |
| 4699 | state.lastIntValue = 0x09; /* \t */ | |
| 4700 | state.advance(); | |
| 4701 | return true | |
| 4702 | } | |
| 4703 | if (ch === 0x6E /* n */) { | |
| 4704 | state.lastIntValue = 0x0A; /* \n */ | |
| 4705 | state.advance(); | |
| 4706 | return true | |
| 4707 | } | |
| 4708 | if (ch === 0x76 /* v */) { | |
| 4709 | state.lastIntValue = 0x0B; /* \v */ | |
| 4710 | state.advance(); | |
| 4711 | return true | |
| 4712 | } | |
| 4713 | if (ch === 0x66 /* f */) { | |
| 4714 | state.lastIntValue = 0x0C; /* \f */ | |
| 4715 | state.advance(); | |
| 4716 | return true | |
| 4717 | } | |
| 4718 | if (ch === 0x72 /* r */) { | |
| 4719 | state.lastIntValue = 0x0D; /* \r */ | |
| 4720 | state.advance(); | |
| 4721 | return true | |
| 4722 | } | |
| 4723 | return false | |
| 4724 | }; | |
| 4725 | ||
| 4726 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter | |
| 4727 | pp$1.regexp_eatControlLetter = function(state) { | |
| 4728 | var ch = state.current(); | |
| 4729 | if (isControlLetter(ch)) { | |
| 4730 | state.lastIntValue = ch % 0x20; | |
| 4731 | state.advance(); | |
| 4732 | return true | |
| 4733 | } | |
| 4734 | return false | |
| 4735 | }; | |
| 4736 | function isControlLetter(ch) { | |
| 4737 | return ( | |
| 4738 | (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || | |
| 4739 | (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) | |
| 4740 | ) | |
| 4741 | } | |
| 4742 | ||
| 4743 | // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence | |
| 4744 | pp$1.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) { | |
| 4745 | if ( forceU === void 0 ) forceU = false; | |
| 4746 | ||
| 4747 | var start = state.pos; | |
| 4748 | var switchU = forceU || state.switchU; | |
| 4749 | ||
| 4750 | if (state.eat(0x75 /* u */)) { | |
| 4751 | if (this.regexp_eatFixedHexDigits(state, 4)) { | |
| 4752 | var lead = state.lastIntValue; | |
| 4753 | if (switchU && lead >= 0xD800 && lead <= 0xDBFF) { | |
| 4754 | var leadSurrogateEnd = state.pos; | |
| 4755 | if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { | |
| 4756 | var trail = state.lastIntValue; | |
| 4757 | if (trail >= 0xDC00 && trail <= 0xDFFF) { | |
| 4758 | state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; | |
| 4759 | return true | |
| 4760 | } | |
| 4761 | } | |
| 4762 | state.pos = leadSurrogateEnd; | |
| 4763 | state.lastIntValue = lead; | |
| 4764 | } | |
| 4765 | return true | |
| 4766 | } | |
| 4767 | if ( | |
| 4768 | switchU && | |
| 4769 | state.eat(0x7B /* { */) && | |
| 4770 | this.regexp_eatHexDigits(state) && | |
| 4771 | state.eat(0x7D /* } */) && | |
| 4772 | isValidUnicode(state.lastIntValue) | |
| 4773 | ) { | |
| 4774 | return true | |
| 4775 | } | |
| 4776 | if (switchU) { | |
| 4777 | state.raise("Invalid unicode escape"); | |
| 4778 | } | |
| 4779 | state.pos = start; | |
| 4780 | } | |
| 4781 | ||
| 4782 | return false | |
| 4783 | }; | |
| 4784 | function isValidUnicode(ch) { | |
| 4785 | return ch >= 0 && ch <= 0x10FFFF | |
| 4786 | } | |
| 4787 | ||
| 4788 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape | |
| 4789 | pp$1.regexp_eatIdentityEscape = function(state) { | |
| 4790 | if (state.switchU) { | |
| 4791 | if (this.regexp_eatSyntaxCharacter(state)) { | |
| 4792 | return true | |
| 4793 | } | |
| 4794 | if (state.eat(0x2F /* / */)) { | |
| 4795 | state.lastIntValue = 0x2F; /* / */ | |
| 4796 | return true | |
| 4797 | } | |
| 4798 | return false | |
| 4799 | } | |
| 4800 | ||
| 4801 | var ch = state.current(); | |
| 4802 | if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { | |
| 4803 | state.lastIntValue = ch; | |
| 4804 | state.advance(); | |
| 4805 | return true | |
| 4806 | } | |
| 4807 | ||
| 4808 | return false | |
| 4809 | }; | |
| 4810 | ||
| 4811 | // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape | |
| 4812 | pp$1.regexp_eatDecimalEscape = function(state) { | |
| 4813 | state.lastIntValue = 0; | |
| 4814 | var ch = state.current(); | |
| 4815 | if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { | |
| 4816 | do { | |
| 4817 | state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); | |
| 4818 | state.advance(); | |
| 4819 | } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) | |
| 4820 | return true | |
| 4821 | } | |
| 4822 | return false | |
| 4823 | }; | |
| 4824 | ||
| 4825 | // Return values used by character set parsing methods, needed to | |
| 4826 | // forbid negation of sets that can match strings. | |
| 4827 | var CharSetNone = 0; // Nothing parsed | |
| 4828 | var CharSetOk = 1; // Construct parsed, cannot contain strings | |
| 4829 | var CharSetString = 2; // Construct parsed, can contain strings | |
| 4830 | ||
| 4831 | // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape | |
| 4832 | pp$1.regexp_eatCharacterClassEscape = function(state) { | |
| 4833 | var ch = state.current(); | |
| 4834 | ||
| 4835 | if (isCharacterClassEscape(ch)) { | |
| 4836 | state.lastIntValue = -1; | |
| 4837 | state.advance(); | |
| 4838 | return CharSetOk | |
| 4839 | } | |
| 4840 | ||
| 4841 | var negate = false; | |
| 4842 | if ( | |
| 4843 | state.switchU && | |
| 4844 | this.options.ecmaVersion >= 9 && | |
| 4845 | ((negate = ch === 0x50 /* P */) || ch === 0x70 /* p */) | |
| 4846 | ) { | |
| 4847 | state.lastIntValue = -1; | |
| 4848 | state.advance(); | |
| 4849 | var result; | |
| 4850 | if ( | |
| 4851 | state.eat(0x7B /* { */) && | |
| 4852 | (result = this.regexp_eatUnicodePropertyValueExpression(state)) && | |
| 4853 | state.eat(0x7D /* } */) | |
| 4854 | ) { | |
| 4855 | if (negate && result === CharSetString) { state.raise("Invalid property name"); } | |
| 4856 | return result | |
| 4857 | } | |
| 4858 | state.raise("Invalid property name"); | |
| 4859 | } | |
| 4860 | ||
| 4861 | return CharSetNone | |
| 4862 | }; | |
| 4863 | ||
| 4864 | function isCharacterClassEscape(ch) { | |
| 4865 | return ( | |
| 4866 | ch === 0x64 /* d */ || | |
| 4867 | ch === 0x44 /* D */ || | |
| 4868 | ch === 0x73 /* s */ || | |
| 4869 | ch === 0x53 /* S */ || | |
| 4870 | ch === 0x77 /* w */ || | |
| 4871 | ch === 0x57 /* W */ | |
| 4872 | ) | |
| 4873 | } | |
| 4874 | ||
| 4875 | // UnicodePropertyValueExpression :: | |
| 4876 | // UnicodePropertyName `=` UnicodePropertyValue | |
| 4877 | // LoneUnicodePropertyNameOrValue | |
| 4878 | pp$1.regexp_eatUnicodePropertyValueExpression = function(state) { | |
| 4879 | var start = state.pos; | |
| 4880 | ||
| 4881 | // UnicodePropertyName `=` UnicodePropertyValue | |
| 4882 | if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { | |
| 4883 | var name = state.lastStringValue; | |
| 4884 | if (this.regexp_eatUnicodePropertyValue(state)) { | |
| 4885 | var value = state.lastStringValue; | |
| 4886 | this.regexp_validateUnicodePropertyNameAndValue(state, name, value); | |
| 4887 | return CharSetOk | |
| 4888 | } | |
| 4889 | } | |
| 4890 | state.pos = start; | |
| 4891 | ||
| 4892 | // LoneUnicodePropertyNameOrValue | |
| 4893 | if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { | |
| 4894 | var nameOrValue = state.lastStringValue; | |
| 4895 | return this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue) | |
| 4896 | } | |
| 4897 | return CharSetNone | |
| 4898 | }; | |
| 4899 | ||
| 4900 | pp$1.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { | |
| 4901 | if (!hasOwn(state.unicodeProperties.nonBinary, name)) | |
| 4902 | { state.raise("Invalid property name"); } | |
| 4903 | if (!state.unicodeProperties.nonBinary[name].test(value)) | |
| 4904 | { state.raise("Invalid property value"); } | |
| 4905 | }; | |
| 4906 | ||
| 4907 | pp$1.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { | |
| 4908 | if (state.unicodeProperties.binary.test(nameOrValue)) { return CharSetOk } | |
| 4909 | if (state.switchV && state.unicodeProperties.binaryOfStrings.test(nameOrValue)) { return CharSetString } | |
| 4910 | state.raise("Invalid property name"); | |
| 4911 | }; | |
| 4912 | ||
| 4913 | // UnicodePropertyName :: | |
| 4914 | // UnicodePropertyNameCharacters | |
| 4915 | pp$1.regexp_eatUnicodePropertyName = function(state) { | |
| 4916 | var ch = 0; | |
| 4917 | state.lastStringValue = ""; | |
| 4918 | while (isUnicodePropertyNameCharacter(ch = state.current())) { | |
| 4919 | state.lastStringValue += codePointToString(ch); | |
| 4920 | state.advance(); | |
| 4921 | } | |
| 4922 | return state.lastStringValue !== "" | |
| 4923 | }; | |
| 4924 | ||
| 4925 | function isUnicodePropertyNameCharacter(ch) { | |
| 4926 | return isControlLetter(ch) || ch === 0x5F /* _ */ | |
| 4927 | } | |
| 4928 | ||
| 4929 | // UnicodePropertyValue :: | |
| 4930 | // UnicodePropertyValueCharacters | |
| 4931 | pp$1.regexp_eatUnicodePropertyValue = function(state) { | |
| 4932 | var ch = 0; | |
| 4933 | state.lastStringValue = ""; | |
| 4934 | while (isUnicodePropertyValueCharacter(ch = state.current())) { | |
| 4935 | state.lastStringValue += codePointToString(ch); | |
| 4936 | state.advance(); | |
| 4937 | } | |
| 4938 | return state.lastStringValue !== "" | |
| 4939 | }; | |
| 4940 | function isUnicodePropertyValueCharacter(ch) { | |
| 4941 | return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) | |
| 4942 | } | |
| 4943 | ||
| 4944 | // LoneUnicodePropertyNameOrValue :: | |
| 4945 | // UnicodePropertyValueCharacters | |
| 4946 | pp$1.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { | |
| 4947 | return this.regexp_eatUnicodePropertyValue(state) | |
| 4948 | }; | |
| 4949 | ||
| 4950 | // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass | |
| 4951 | pp$1.regexp_eatCharacterClass = function(state) { | |
| 4952 | if (state.eat(0x5B /* [ */)) { | |
| 4953 | var negate = state.eat(0x5E /* ^ */); | |
| 4954 | var result = this.regexp_classContents(state); | |
| 4955 | if (!state.eat(0x5D /* ] */)) | |
| 4956 | { state.raise("Unterminated character class"); } | |
| 4957 | if (negate && result === CharSetString) | |
| 4958 | { state.raise("Negated character class may contain strings"); } | |
| 4959 | return true | |
| 4960 | } | |
| 4961 | return false | |
| 4962 | }; | |
| 4963 | ||
| 4964 | // https://tc39.es/ecma262/#prod-ClassContents | |
| 4965 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges | |
| 4966 | pp$1.regexp_classContents = function(state) { | |
| 4967 | if (state.current() === 0x5D /* ] */) { return CharSetOk } | |
| 4968 | if (state.switchV) { return this.regexp_classSetExpression(state) } | |
| 4969 | this.regexp_nonEmptyClassRanges(state); | |
| 4970 | return CharSetOk | |
| 4971 | }; | |
| 4972 | ||
| 4973 | // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges | |
| 4974 | // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash | |
| 4975 | pp$1.regexp_nonEmptyClassRanges = function(state) { | |
| 4976 | while (this.regexp_eatClassAtom(state)) { | |
| 4977 | var left = state.lastIntValue; | |
| 4978 | if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { | |
| 4979 | var right = state.lastIntValue; | |
| 4980 | if (state.switchU && (left === -1 || right === -1)) { | |
| 4981 | state.raise("Invalid character class"); | |
| 4982 | } | |
| 4983 | if (left !== -1 && right !== -1 && left > right) { | |
| 4984 | state.raise("Range out of order in character class"); | |
| 4985 | } | |
| 4986 | } | |
| 4987 | } | |
| 4988 | }; | |
| 4989 | ||
| 4990 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom | |
| 4991 | // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash | |
| 4992 | pp$1.regexp_eatClassAtom = function(state) { | |
| 4993 | var start = state.pos; | |
| 4994 | ||
| 4995 | if (state.eat(0x5C /* \ */)) { | |
| 4996 | if (this.regexp_eatClassEscape(state)) { | |
| 4997 | return true | |
| 4998 | } | |
| 4999 | if (state.switchU) { | |
| 5000 | // Make the same message as V8. | |
| 5001 | var ch$1 = state.current(); | |
| 5002 | if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) { | |
| 5003 | state.raise("Invalid class escape"); | |
| 5004 | } | |
| 5005 | state.raise("Invalid escape"); | |
| 5006 | } | |
| 5007 | state.pos = start; | |
| 5008 | } | |
| 5009 | ||
| 5010 | var ch = state.current(); | |
| 5011 | if (ch !== 0x5D /* ] */) { | |
| 5012 | state.lastIntValue = ch; | |
| 5013 | state.advance(); | |
| 5014 | return true | |
| 5015 | } | |
| 5016 | ||
| 5017 | return false | |
| 5018 | }; | |
| 5019 | ||
| 5020 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape | |
| 5021 | pp$1.regexp_eatClassEscape = function(state) { | |
| 5022 | var start = state.pos; | |
| 5023 | ||
| 5024 | if (state.eat(0x62 /* b */)) { | |
| 5025 | state.lastIntValue = 0x08; /* <BS> */ | |
| 5026 | return true | |
| 5027 | } | |
| 5028 | ||
| 5029 | if (state.switchU && state.eat(0x2D /* - */)) { | |
| 5030 | state.lastIntValue = 0x2D; /* - */ | |
| 5031 | return true | |
| 5032 | } | |
| 5033 | ||
| 5034 | if (!state.switchU && state.eat(0x63 /* c */)) { | |
| 5035 | if (this.regexp_eatClassControlLetter(state)) { | |
| 5036 | return true | |
| 5037 | } | |
| 5038 | state.pos = start; | |
| 5039 | } | |
| 5040 | ||
| 5041 | return ( | |
| 5042 | this.regexp_eatCharacterClassEscape(state) || | |
| 5043 | this.regexp_eatCharacterEscape(state) | |
| 5044 | ) | |
| 5045 | }; | |
| 5046 | ||
| 5047 | // https://tc39.es/ecma262/#prod-ClassSetExpression | |
| 5048 | // https://tc39.es/ecma262/#prod-ClassUnion | |
| 5049 | // https://tc39.es/ecma262/#prod-ClassIntersection | |
| 5050 | // https://tc39.es/ecma262/#prod-ClassSubtraction | |
| 5051 | pp$1.regexp_classSetExpression = function(state) { | |
| 5052 | var result = CharSetOk, subResult; | |
| 5053 | if (this.regexp_eatClassSetRange(state)) ; else if (subResult = this.regexp_eatClassSetOperand(state)) { | |
| 5054 | if (subResult === CharSetString) { result = CharSetString; } | |
| 5055 | // https://tc39.es/ecma262/#prod-ClassIntersection | |
| 5056 | var start = state.pos; | |
| 5057 | while (state.eatChars([0x26, 0x26] /* && */)) { | |
| 5058 | if ( | |
| 5059 | state.current() !== 0x26 /* & */ && | |
| 5060 | (subResult = this.regexp_eatClassSetOperand(state)) | |
| 5061 | ) { | |
| 5062 | if (subResult !== CharSetString) { result = CharSetOk; } | |
| 5063 | continue | |
| 5064 | } | |
| 5065 | state.raise("Invalid character in character class"); | |
| 5066 | } | |
| 5067 | if (start !== state.pos) { return result } | |
| 5068 | // https://tc39.es/ecma262/#prod-ClassSubtraction | |
| 5069 | while (state.eatChars([0x2D, 0x2D] /* -- */)) { | |
| 5070 | if (this.regexp_eatClassSetOperand(state)) { continue } | |
| 5071 | state.raise("Invalid character in character class"); | |
| 5072 | } | |
| 5073 | if (start !== state.pos) { return result } | |
| 5074 | } else { | |
| 5075 | state.raise("Invalid character in character class"); | |
| 5076 | } | |
| 5077 | // https://tc39.es/ecma262/#prod-ClassUnion | |
| 5078 | for (;;) { | |
| 5079 | if (this.regexp_eatClassSetRange(state)) { continue } | |
| 5080 | subResult = this.regexp_eatClassSetOperand(state); | |
| 5081 | if (!subResult) { return result } | |
| 5082 | if (subResult === CharSetString) { result = CharSetString; } | |
| 5083 | } | |
| 5084 | }; | |
| 5085 | ||
| 5086 | // https://tc39.es/ecma262/#prod-ClassSetRange | |
| 5087 | pp$1.regexp_eatClassSetRange = function(state) { | |
| 5088 | var start = state.pos; | |
| 5089 | if (this.regexp_eatClassSetCharacter(state)) { | |
| 5090 | var left = state.lastIntValue; | |
| 5091 | if (state.eat(0x2D /* - */) && this.regexp_eatClassSetCharacter(state)) { | |
| 5092 | var right = state.lastIntValue; | |
| 5093 | if (left !== -1 && right !== -1 && left > right) { | |
| 5094 | state.raise("Range out of order in character class"); | |
| 5095 | } | |
| 5096 | return true | |
| 5097 | } | |
| 5098 | state.pos = start; | |
| 5099 | } | |
| 5100 | return false | |
| 5101 | }; | |
| 5102 | ||
| 5103 | // https://tc39.es/ecma262/#prod-ClassSetOperand | |
| 5104 | pp$1.regexp_eatClassSetOperand = function(state) { | |
| 5105 | if (this.regexp_eatClassSetCharacter(state)) { return CharSetOk } | |
| 5106 | return this.regexp_eatClassStringDisjunction(state) || this.regexp_eatNestedClass(state) | |
| 5107 | }; | |
| 5108 | ||
| 5109 | // https://tc39.es/ecma262/#prod-NestedClass | |
| 5110 | pp$1.regexp_eatNestedClass = function(state) { | |
| 5111 | var start = state.pos; | |
| 5112 | if (state.eat(0x5B /* [ */)) { | |
| 5113 | var negate = state.eat(0x5E /* ^ */); | |
| 5114 | var result = this.regexp_classContents(state); | |
| 5115 | if (state.eat(0x5D /* ] */)) { | |
| 5116 | if (negate && result === CharSetString) { | |
| 5117 | state.raise("Negated character class may contain strings"); | |
| 5118 | } | |
| 5119 | return result | |
| 5120 | } | |
| 5121 | state.pos = start; | |
| 5122 | } | |
| 5123 | if (state.eat(0x5C /* \ */)) { | |
| 5124 | var result$1 = this.regexp_eatCharacterClassEscape(state); | |
| 5125 | if (result$1) { | |
| 5126 | return result$1 | |
| 5127 | } | |
| 5128 | state.pos = start; | |
| 5129 | } | |
| 5130 | return null | |
| 5131 | }; | |
| 5132 | ||
| 5133 | // https://tc39.es/ecma262/#prod-ClassStringDisjunction | |
| 5134 | pp$1.regexp_eatClassStringDisjunction = function(state) { | |
| 5135 | var start = state.pos; | |
| 5136 | if (state.eatChars([0x5C, 0x71] /* \q */)) { | |
| 5137 | if (state.eat(0x7B /* { */)) { | |
| 5138 | var result = this.regexp_classStringDisjunctionContents(state); | |
| 5139 | if (state.eat(0x7D /* } */)) { | |
| 5140 | return result | |
| 5141 | } | |
| 5142 | } else { | |
| 5143 | // Make the same message as V8. | |
| 5144 | state.raise("Invalid escape"); | |
| 5145 | } | |
| 5146 | state.pos = start; | |
| 5147 | } | |
| 5148 | return null | |
| 5149 | }; | |
| 5150 | ||
| 5151 | // https://tc39.es/ecma262/#prod-ClassStringDisjunctionContents | |
| 5152 | pp$1.regexp_classStringDisjunctionContents = function(state) { | |
| 5153 | var result = this.regexp_classString(state); | |
| 5154 | while (state.eat(0x7C /* | */)) { | |
| 5155 | if (this.regexp_classString(state) === CharSetString) { result = CharSetString; } | |
| 5156 | } | |
| 5157 | return result | |
| 5158 | }; | |
| 5159 | ||
| 5160 | // https://tc39.es/ecma262/#prod-ClassString | |
| 5161 | // https://tc39.es/ecma262/#prod-NonEmptyClassString | |
| 5162 | pp$1.regexp_classString = function(state) { | |
| 5163 | var count = 0; | |
| 5164 | while (this.regexp_eatClassSetCharacter(state)) { count++; } | |
| 5165 | return count === 1 ? CharSetOk : CharSetString | |
| 5166 | }; | |
| 5167 | ||
| 5168 | // https://tc39.es/ecma262/#prod-ClassSetCharacter | |
| 5169 | pp$1.regexp_eatClassSetCharacter = function(state) { | |
| 5170 | var start = state.pos; | |
| 5171 | if (state.eat(0x5C /* \ */)) { | |
| 5172 | if ( | |
| 5173 | this.regexp_eatCharacterEscape(state) || | |
| 5174 | this.regexp_eatClassSetReservedPunctuator(state) | |
| 5175 | ) { | |
| 5176 | return true | |
| 5177 | } | |
| 5178 | if (state.eat(0x62 /* b */)) { | |
| 5179 | state.lastIntValue = 0x08; /* <BS> */ | |
| 5180 | return true | |
| 5181 | } | |
| 5182 | state.pos = start; | |
| 5183 | return false | |
| 5184 | } | |
| 5185 | var ch = state.current(); | |
| 5186 | if (ch < 0 || ch === state.lookahead() && isClassSetReservedDoublePunctuatorCharacter(ch)) { return false } | |
| 5187 | if (isClassSetSyntaxCharacter(ch)) { return false } | |
| 5188 | state.advance(); | |
| 5189 | state.lastIntValue = ch; | |
| 5190 | return true | |
| 5191 | }; | |
| 5192 | ||
| 5193 | // https://tc39.es/ecma262/#prod-ClassSetReservedDoublePunctuator | |
| 5194 | function isClassSetReservedDoublePunctuatorCharacter(ch) { | |
| 5195 | return ( | |
| 5196 | ch === 0x21 /* ! */ || | |
| 5197 | ch >= 0x23 /* # */ && ch <= 0x26 /* & */ || | |
| 5198 | ch >= 0x2A /* * */ && ch <= 0x2C /* , */ || | |
| 5199 | ch === 0x2E /* . */ || | |
| 5200 | ch >= 0x3A /* : */ && ch <= 0x40 /* @ */ || | |
| 5201 | ch === 0x5E /* ^ */ || | |
| 5202 | ch === 0x60 /* ` */ || | |
| 5203 | ch === 0x7E /* ~ */ | |
| 5204 | ) | |
| 5205 | } | |
| 5206 | ||
| 5207 | // https://tc39.es/ecma262/#prod-ClassSetSyntaxCharacter | |
| 5208 | function isClassSetSyntaxCharacter(ch) { | |
| 5209 | return ( | |
| 5210 | ch === 0x28 /* ( */ || | |
| 5211 | ch === 0x29 /* ) */ || | |
| 5212 | ch === 0x2D /* - */ || | |
| 5213 | ch === 0x2F /* / */ || | |
| 5214 | ch >= 0x5B /* [ */ && ch <= 0x5D /* ] */ || | |
| 5215 | ch >= 0x7B /* { */ && ch <= 0x7D /* } */ | |
| 5216 | ) | |
| 5217 | } | |
| 5218 | ||
| 5219 | // https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator | |
| 5220 | pp$1.regexp_eatClassSetReservedPunctuator = function(state) { | |
| 5221 | var ch = state.current(); | |
| 5222 | if (isClassSetReservedPunctuator(ch)) { | |
| 5223 | state.lastIntValue = ch; | |
| 5224 | state.advance(); | |
| 5225 | return true | |
| 5226 | } | |
| 5227 | return false | |
| 5228 | }; | |
| 5229 | ||
| 5230 | // https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator | |
| 5231 | function isClassSetReservedPunctuator(ch) { | |
| 5232 | return ( | |
| 5233 | ch === 0x21 /* ! */ || | |
| 5234 | ch === 0x23 /* # */ || | |
| 5235 | ch === 0x25 /* % */ || | |
| 5236 | ch === 0x26 /* & */ || | |
| 5237 | ch === 0x2C /* , */ || | |
| 5238 | ch === 0x2D /* - */ || | |
| 5239 | ch >= 0x3A /* : */ && ch <= 0x3E /* > */ || | |
| 5240 | ch === 0x40 /* @ */ || | |
| 5241 | ch === 0x60 /* ` */ || | |
| 5242 | ch === 0x7E /* ~ */ | |
| 5243 | ) | |
| 5244 | } | |
| 5245 | ||
| 5246 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter | |
| 5247 | pp$1.regexp_eatClassControlLetter = function(state) { | |
| 5248 | var ch = state.current(); | |
| 5249 | if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { | |
| 5250 | state.lastIntValue = ch % 0x20; | |
| 5251 | state.advance(); | |
| 5252 | return true | |
| 5253 | } | |
| 5254 | return false | |
| 5255 | }; | |
| 5256 | ||
| 5257 | // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence | |
| 5258 | pp$1.regexp_eatHexEscapeSequence = function(state) { | |
| 5259 | var start = state.pos; | |
| 5260 | if (state.eat(0x78 /* x */)) { | |
| 5261 | if (this.regexp_eatFixedHexDigits(state, 2)) { | |
| 5262 | return true | |
| 5263 | } | |
| 5264 | if (state.switchU) { | |
| 5265 | state.raise("Invalid escape"); | |
| 5266 | } | |
| 5267 | state.pos = start; | |
| 5268 | } | |
| 5269 | return false | |
| 5270 | }; | |
| 5271 | ||
| 5272 | // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits | |
| 5273 | pp$1.regexp_eatDecimalDigits = function(state) { | |
| 5274 | var start = state.pos; | |
| 5275 | var ch = 0; | |
| 5276 | state.lastIntValue = 0; | |
| 5277 | while (isDecimalDigit(ch = state.current())) { | |
| 5278 | state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); | |
| 5279 | state.advance(); | |
| 5280 | } | |
| 5281 | return state.pos !== start | |
| 5282 | }; | |
| 5283 | function isDecimalDigit(ch) { | |
| 5284 | return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ | |
| 5285 | } | |
| 5286 | ||
| 5287 | // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits | |
| 5288 | pp$1.regexp_eatHexDigits = function(state) { | |
| 5289 | var start = state.pos; | |
| 5290 | var ch = 0; | |
| 5291 | state.lastIntValue = 0; | |
| 5292 | while (isHexDigit(ch = state.current())) { | |
| 5293 | state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); | |
| 5294 | state.advance(); | |
| 5295 | } | |
| 5296 | return state.pos !== start | |
| 5297 | }; | |
| 5298 | function isHexDigit(ch) { | |
| 5299 | return ( | |
| 5300 | (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || | |
| 5301 | (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || | |
| 5302 | (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) | |
| 5303 | ) | |
| 5304 | } | |
| 5305 | function hexToInt(ch) { | |
| 5306 | if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { | |
| 5307 | return 10 + (ch - 0x41 /* A */) | |
| 5308 | } | |
| 5309 | if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { | |
| 5310 | return 10 + (ch - 0x61 /* a */) | |
| 5311 | } | |
| 5312 | return ch - 0x30 /* 0 */ | |
| 5313 | } | |
| 5314 | ||
| 5315 | // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence | |
| 5316 | // Allows only 0-377(octal) i.e. 0-255(decimal). | |
| 5317 | pp$1.regexp_eatLegacyOctalEscapeSequence = function(state) { | |
| 5318 | if (this.regexp_eatOctalDigit(state)) { | |
| 5319 | var n1 = state.lastIntValue; | |
| 5320 | if (this.regexp_eatOctalDigit(state)) { | |
| 5321 | var n2 = state.lastIntValue; | |
| 5322 | if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { | |
| 5323 | state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; | |
| 5324 | } else { | |
| 5325 | state.lastIntValue = n1 * 8 + n2; | |
| 5326 | } | |
| 5327 | } else { | |
| 5328 | state.lastIntValue = n1; | |
| 5329 | } | |
| 5330 | return true | |
| 5331 | } | |
| 5332 | return false | |
| 5333 | }; | |
| 5334 | ||
| 5335 | // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit | |
| 5336 | pp$1.regexp_eatOctalDigit = function(state) { | |
| 5337 | var ch = state.current(); | |
| 5338 | if (isOctalDigit(ch)) { | |
| 5339 | state.lastIntValue = ch - 0x30; /* 0 */ | |
| 5340 | state.advance(); | |
| 5341 | return true | |
| 5342 | } | |
| 5343 | state.lastIntValue = 0; | |
| 5344 | return false | |
| 5345 | }; | |
| 5346 | function isOctalDigit(ch) { | |
| 5347 | return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ | |
| 5348 | } | |
| 5349 | ||
| 5350 | // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits | |
| 5351 | // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit | |
| 5352 | // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence | |
| 5353 | pp$1.regexp_eatFixedHexDigits = function(state, length) { | |
| 5354 | var start = state.pos; | |
| 5355 | state.lastIntValue = 0; | |
| 5356 | for (var i = 0; i < length; ++i) { | |
| 5357 | var ch = state.current(); | |
| 5358 | if (!isHexDigit(ch)) { | |
| 5359 | state.pos = start; | |
| 5360 | return false | |
| 5361 | } | |
| 5362 | state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); | |
| 5363 | state.advance(); | |
| 5364 | } | |
| 5365 | return true | |
| 5366 | }; | |
| 5367 | ||
| 5368 | // Object type used to represent tokens. Note that normally, tokens | |
| 5369 | // simply exist as properties on the parser object. This is only | |
| 5370 | // used for the onToken callback and the external tokenizer. | |
| 5371 | ||
| 5372 | var Token = function Token(p) { | |
| 5373 | this.type = p.type; | |
| 5374 | this.value = p.value; | |
| 5375 | this.start = p.start; | |
| 5376 | this.end = p.end; | |
| 5377 | if (p.options.locations) | |
| 5378 | { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } | |
| 5379 | if (p.options.ranges) | |
| 5380 | { this.range = [p.start, p.end]; } | |
| 5381 | }; | |
| 5382 | ||
| 5383 | // ## Tokenizer | |
| 5384 | ||
| 5385 | var pp = Parser.prototype; | |
| 5386 | ||
| 5387 | // Move to the next token | |
| 5388 | ||
| 5389 | pp.next = function(ignoreEscapeSequenceInKeyword) { | |
| 5390 | if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc) | |
| 5391 | { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); } | |
| 5392 | if (this.options.onToken) | |
| 5393 | { this.options.onToken(new Token(this)); } | |
| 5394 | ||
| 5395 | this.lastTokEnd = this.end; | |
| 5396 | this.lastTokStart = this.start; | |
| 5397 | this.lastTokEndLoc = this.endLoc; | |
| 5398 | this.lastTokStartLoc = this.startLoc; | |
| 5399 | this.nextToken(); | |
| 5400 | }; | |
| 5401 | ||
| 5402 | pp.getToken = function() { | |
| 5403 | this.next(); | |
| 5404 | return new Token(this) | |
| 5405 | }; | |
| 5406 | ||
| 5407 | // If we're in an ES6 environment, make parsers iterable | |
| 5408 | if (typeof Symbol !== "undefined") | |
| 5409 | { pp[Symbol.iterator] = function() { | |
| 5410 | var this$1$1 = this; | |
| 5411 | ||
| 5412 | return { | |
| 5413 | next: function () { | |
| 5414 | var token = this$1$1.getToken(); | |
| 5415 | return { | |
| 5416 | done: token.type === types$1.eof, | |
| 5417 | value: token | |
| 5418 | } | |
| 5419 | } | |
| 5420 | } | |
| 5421 | }; } | |
| 5422 | ||
| 5423 | // Toggle strict mode. Re-reads the next number or string to please | |
| 5424 | // pedantic tests (`"use strict"; 010;` should fail). | |
| 5425 | ||
| 5426 | // Read a single token, updating the parser object's token-related | |
| 5427 | // properties. | |
| 5428 | ||
| 5429 | pp.nextToken = function() { | |
| 5430 | var curContext = this.curContext(); | |
| 5431 | if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } | |
| 5432 | ||
| 5433 | this.start = this.pos; | |
| 5434 | if (this.options.locations) { this.startLoc = this.curPosition(); } | |
| 5435 | if (this.pos >= this.input.length) { return this.finishToken(types$1.eof) } | |
| 5436 | ||
| 5437 | if (curContext.override) { return curContext.override(this) } | |
| 5438 | else { this.readToken(this.fullCharCodeAtPos()); } | |
| 5439 | }; | |
| 5440 | ||
| 5441 | pp.readToken = function(code) { | |
| 5442 | // Identifier or keyword. '\uXXXX' sequences are allowed in | |
| 5443 | // identifiers, so '\' also dispatches to that. | |
| 5444 | if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) | |
| 5445 | { return this.readWord() } | |
| 5446 | ||
| 5447 | return this.getTokenFromCode(code) | |
| 5448 | }; | |
| 5449 | ||
| 5450 | pp.fullCharCodeAtPos = function() { | |
| 5451 | var code = this.input.charCodeAt(this.pos); | |
| 5452 | if (code <= 0xd7ff || code >= 0xdc00) { return code } | |
| 5453 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5454 | return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00 | |
| 5455 | }; | |
| 5456 | ||
| 5457 | pp.skipBlockComment = function() { | |
| 5458 | var startLoc = this.options.onComment && this.curPosition(); | |
| 5459 | var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); | |
| 5460 | if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } | |
| 5461 | this.pos = end + 2; | |
| 5462 | if (this.options.locations) { | |
| 5463 | for (var nextBreak = (void 0), pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1;) { | |
| 5464 | ++this.curLine; | |
| 5465 | pos = this.lineStart = nextBreak; | |
| 5466 | } | |
| 5467 | } | |
| 5468 | if (this.options.onComment) | |
| 5469 | { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, | |
| 5470 | startLoc, this.curPosition()); } | |
| 5471 | }; | |
| 5472 | ||
| 5473 | pp.skipLineComment = function(startSkip) { | |
| 5474 | var start = this.pos; | |
| 5475 | var startLoc = this.options.onComment && this.curPosition(); | |
| 5476 | var ch = this.input.charCodeAt(this.pos += startSkip); | |
| 5477 | while (this.pos < this.input.length && !isNewLine(ch)) { | |
| 5478 | ch = this.input.charCodeAt(++this.pos); | |
| 5479 | } | |
| 5480 | if (this.options.onComment) | |
| 5481 | { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, | |
| 5482 | startLoc, this.curPosition()); } | |
| 5483 | }; | |
| 5484 | ||
| 5485 | // Called at the start of the parse and after every token. Skips | |
| 5486 | // whitespace and comments, and. | |
| 5487 | ||
| 5488 | pp.skipSpace = function() { | |
| 5489 | loop: while (this.pos < this.input.length) { | |
| 5490 | var ch = this.input.charCodeAt(this.pos); | |
| 5491 | switch (ch) { | |
| 5492 | case 32: case 160: // ' ' | |
| 5493 | ++this.pos; | |
| 5494 | break | |
| 5495 | case 13: | |
| 5496 | if (this.input.charCodeAt(this.pos + 1) === 10) { | |
| 5497 | ++this.pos; | |
| 5498 | } | |
| 5499 | case 10: case 8232: case 8233: | |
| 5500 | ++this.pos; | |
| 5501 | if (this.options.locations) { | |
| 5502 | ++this.curLine; | |
| 5503 | this.lineStart = this.pos; | |
| 5504 | } | |
| 5505 | break | |
| 5506 | case 47: // '/' | |
| 5507 | switch (this.input.charCodeAt(this.pos + 1)) { | |
| 5508 | case 42: // '*' | |
| 5509 | this.skipBlockComment(); | |
| 5510 | break | |
| 5511 | case 47: | |
| 5512 | this.skipLineComment(2); | |
| 5513 | break | |
| 5514 | default: | |
| 5515 | break loop | |
| 5516 | } | |
| 5517 | break | |
| 5518 | default: | |
| 5519 | if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { | |
| 5520 | ++this.pos; | |
| 5521 | } else { | |
| 5522 | break loop | |
| 5523 | } | |
| 5524 | } | |
| 5525 | } | |
| 5526 | }; | |
| 5527 | ||
| 5528 | // Called at the end of every token. Sets `end`, `val`, and | |
| 5529 | // maintains `context` and `exprAllowed`, and skips the space after | |
| 5530 | // the token, so that the next one's `start` will point at the | |
| 5531 | // right position. | |
| 5532 | ||
| 5533 | pp.finishToken = function(type, val) { | |
| 5534 | this.end = this.pos; | |
| 5535 | if (this.options.locations) { this.endLoc = this.curPosition(); } | |
| 5536 | var prevType = this.type; | |
| 5537 | this.type = type; | |
| 5538 | this.value = val; | |
| 5539 | ||
| 5540 | this.updateContext(prevType); | |
| 5541 | }; | |
| 5542 | ||
| 5543 | // ### Token reading | |
| 5544 | ||
| 5545 | // This is the function that is called to fetch the next token. It | |
| 5546 | // is somewhat obscure, because it works in character codes rather | |
| 5547 | // than characters, and because operator parsing has been inlined | |
| 5548 | // into it. | |
| 5549 | // | |
| 5550 | // All in the name of speed. | |
| 5551 | // | |
| 5552 | pp.readToken_dot = function() { | |
| 5553 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5554 | if (next >= 48 && next <= 57) { return this.readNumber(true) } | |
| 5555 | var next2 = this.input.charCodeAt(this.pos + 2); | |
| 5556 | if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' | |
| 5557 | this.pos += 3; | |
| 5558 | return this.finishToken(types$1.ellipsis) | |
| 5559 | } else { | |
| 5560 | ++this.pos; | |
| 5561 | return this.finishToken(types$1.dot) | |
| 5562 | } | |
| 5563 | }; | |
| 5564 | ||
| 5565 | pp.readToken_slash = function() { // '/' | |
| 5566 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5567 | if (this.exprAllowed) { ++this.pos; return this.readRegexp() } | |
| 5568 | if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
| 5569 | return this.finishOp(types$1.slash, 1) | |
| 5570 | }; | |
| 5571 | ||
| 5572 | pp.readToken_mult_modulo_exp = function(code) { // '%*' | |
| 5573 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5574 | var size = 1; | |
| 5575 | var tokentype = code === 42 ? types$1.star : types$1.modulo; | |
| 5576 | ||
| 5577 | // exponentiation operator ** and **= | |
| 5578 | if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { | |
| 5579 | ++size; | |
| 5580 | tokentype = types$1.starstar; | |
| 5581 | next = this.input.charCodeAt(this.pos + 2); | |
| 5582 | } | |
| 5583 | ||
| 5584 | if (next === 61) { return this.finishOp(types$1.assign, size + 1) } | |
| 5585 | return this.finishOp(tokentype, size) | |
| 5586 | }; | |
| 5587 | ||
| 5588 | pp.readToken_pipe_amp = function(code) { // '|&' | |
| 5589 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5590 | if (next === code) { | |
| 5591 | if (this.options.ecmaVersion >= 12) { | |
| 5592 | var next2 = this.input.charCodeAt(this.pos + 2); | |
| 5593 | if (next2 === 61) { return this.finishOp(types$1.assign, 3) } | |
| 5594 | } | |
| 5595 | return this.finishOp(code === 124 ? types$1.logicalOR : types$1.logicalAND, 2) | |
| 5596 | } | |
| 5597 | if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
| 5598 | return this.finishOp(code === 124 ? types$1.bitwiseOR : types$1.bitwiseAND, 1) | |
| 5599 | }; | |
| 5600 | ||
| 5601 | pp.readToken_caret = function() { // '^' | |
| 5602 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5603 | if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
| 5604 | return this.finishOp(types$1.bitwiseXOR, 1) | |
| 5605 | }; | |
| 5606 | ||
| 5607 | pp.readToken_plus_min = function(code) { // '+-' | |
| 5608 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5609 | if (next === code) { | |
| 5610 | if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && | |
| 5611 | (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { | |
| 5612 | // A `-->` line comment | |
| 5613 | this.skipLineComment(3); | |
| 5614 | this.skipSpace(); | |
| 5615 | return this.nextToken() | |
| 5616 | } | |
| 5617 | return this.finishOp(types$1.incDec, 2) | |
| 5618 | } | |
| 5619 | if (next === 61) { return this.finishOp(types$1.assign, 2) } | |
| 5620 | return this.finishOp(types$1.plusMin, 1) | |
| 5621 | }; | |
| 5622 | ||
| 5623 | pp.readToken_lt_gt = function(code) { // '<>' | |
| 5624 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5625 | var size = 1; | |
| 5626 | if (next === code) { | |
| 5627 | size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; | |
| 5628 | if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types$1.assign, size + 1) } | |
| 5629 | return this.finishOp(types$1.bitShift, size) | |
| 5630 | } | |
| 5631 | if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && | |
| 5632 | this.input.charCodeAt(this.pos + 3) === 45) { | |
| 5633 | // `<!--`, an XML-style comment that should be interpreted as a line comment | |
| 5634 | this.skipLineComment(4); | |
| 5635 | this.skipSpace(); | |
| 5636 | return this.nextToken() | |
| 5637 | } | |
| 5638 | if (next === 61) { size = 2; } | |
| 5639 | return this.finishOp(types$1.relational, size) | |
| 5640 | }; | |
| 5641 | ||
| 5642 | pp.readToken_eq_excl = function(code) { // '=!' | |
| 5643 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5644 | if (next === 61) { return this.finishOp(types$1.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) } | |
| 5645 | if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>' | |
| 5646 | this.pos += 2; | |
| 5647 | return this.finishToken(types$1.arrow) | |
| 5648 | } | |
| 5649 | return this.finishOp(code === 61 ? types$1.eq : types$1.prefix, 1) | |
| 5650 | }; | |
| 5651 | ||
| 5652 | pp.readToken_question = function() { // '?' | |
| 5653 | var ecmaVersion = this.options.ecmaVersion; | |
| 5654 | if (ecmaVersion >= 11) { | |
| 5655 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5656 | if (next === 46) { | |
| 5657 | var next2 = this.input.charCodeAt(this.pos + 2); | |
| 5658 | if (next2 < 48 || next2 > 57) { return this.finishOp(types$1.questionDot, 2) } | |
| 5659 | } | |
| 5660 | if (next === 63) { | |
| 5661 | if (ecmaVersion >= 12) { | |
| 5662 | var next2$1 = this.input.charCodeAt(this.pos + 2); | |
| 5663 | if (next2$1 === 61) { return this.finishOp(types$1.assign, 3) } | |
| 5664 | } | |
| 5665 | return this.finishOp(types$1.coalesce, 2) | |
| 5666 | } | |
| 5667 | } | |
| 5668 | return this.finishOp(types$1.question, 1) | |
| 5669 | }; | |
| 5670 | ||
| 5671 | pp.readToken_numberSign = function() { // '#' | |
| 5672 | var ecmaVersion = this.options.ecmaVersion; | |
| 5673 | var code = 35; // '#' | |
| 5674 | if (ecmaVersion >= 13) { | |
| 5675 | ++this.pos; | |
| 5676 | code = this.fullCharCodeAtPos(); | |
| 5677 | if (isIdentifierStart(code, true) || code === 92 /* '\' */) { | |
| 5678 | return this.finishToken(types$1.privateId, this.readWord1()) | |
| 5679 | } | |
| 5680 | } | |
| 5681 | ||
| 5682 | this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); | |
| 5683 | }; | |
| 5684 | ||
| 5685 | pp.getTokenFromCode = function(code) { | |
| 5686 | switch (code) { | |
| 5687 | // The interpretation of a dot depends on whether it is followed | |
| 5688 | // by a digit or another two dots. | |
| 5689 | case 46: // '.' | |
| 5690 | return this.readToken_dot() | |
| 5691 | ||
| 5692 | // Punctuation tokens. | |
| 5693 | case 40: ++this.pos; return this.finishToken(types$1.parenL) | |
| 5694 | case 41: ++this.pos; return this.finishToken(types$1.parenR) | |
| 5695 | case 59: ++this.pos; return this.finishToken(types$1.semi) | |
| 5696 | case 44: ++this.pos; return this.finishToken(types$1.comma) | |
| 5697 | case 91: ++this.pos; return this.finishToken(types$1.bracketL) | |
| 5698 | case 93: ++this.pos; return this.finishToken(types$1.bracketR) | |
| 5699 | case 123: ++this.pos; return this.finishToken(types$1.braceL) | |
| 5700 | case 125: ++this.pos; return this.finishToken(types$1.braceR) | |
| 5701 | case 58: ++this.pos; return this.finishToken(types$1.colon) | |
| 5702 | ||
| 5703 | case 96: // '`' | |
| 5704 | if (this.options.ecmaVersion < 6) { break } | |
| 5705 | ++this.pos; | |
| 5706 | return this.finishToken(types$1.backQuote) | |
| 5707 | ||
| 5708 | case 48: // '0' | |
| 5709 | var next = this.input.charCodeAt(this.pos + 1); | |
| 5710 | if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number | |
| 5711 | if (this.options.ecmaVersion >= 6) { | |
| 5712 | if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number | |
| 5713 | if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number | |
| 5714 | } | |
| 5715 | ||
| 5716 | // Anything else beginning with a digit is an integer, octal | |
| 5717 | // number, or float. | |
| 5718 | case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 | |
| 5719 | return this.readNumber(false) | |
| 5720 | ||
| 5721 | // Quotes produce strings. | |
| 5722 | case 34: case 39: // '"', "'" | |
| 5723 | return this.readString(code) | |
| 5724 | ||
| 5725 | // Operators are parsed inline in tiny state machines. '=' (61) is | |
| 5726 | // often referred to. `finishOp` simply skips the amount of | |
| 5727 | // characters it is given as second argument, and returns a token | |
| 5728 | // of the type given by its first argument. | |
| 5729 | case 47: // '/' | |
| 5730 | return this.readToken_slash() | |
| 5731 | ||
| 5732 | case 37: case 42: // '%*' | |
| 5733 | return this.readToken_mult_modulo_exp(code) | |
| 5734 | ||
| 5735 | case 124: case 38: // '|&' | |
| 5736 | return this.readToken_pipe_amp(code) | |
| 5737 | ||
| 5738 | case 94: // '^' | |
| 5739 | return this.readToken_caret() | |
| 5740 | ||
| 5741 | case 43: case 45: // '+-' | |
| 5742 | return this.readToken_plus_min(code) | |
| 5743 | ||
| 5744 | case 60: case 62: // '<>' | |
| 5745 | return this.readToken_lt_gt(code) | |
| 5746 | ||
| 5747 | case 61: case 33: // '=!' | |
| 5748 | return this.readToken_eq_excl(code) | |
| 5749 | ||
| 5750 | case 63: // '?' | |
| 5751 | return this.readToken_question() | |
| 5752 | ||
| 5753 | case 126: // '~' | |
| 5754 | return this.finishOp(types$1.prefix, 1) | |
| 5755 | ||
| 5756 | case 35: // '#' | |
| 5757 | return this.readToken_numberSign() | |
| 5758 | } | |
| 5759 | ||
| 5760 | this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); | |
| 5761 | }; | |
| 5762 | ||
| 5763 | pp.finishOp = function(type, size) { | |
| 5764 | var str = this.input.slice(this.pos, this.pos + size); | |
| 5765 | this.pos += size; | |
| 5766 | return this.finishToken(type, str) | |
| 5767 | }; | |
| 5768 | ||
| 5769 | pp.readRegexp = function() { | |
| 5770 | var escaped, inClass, start = this.pos; | |
| 5771 | for (;;) { | |
| 5772 | if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); } | |
| 5773 | var ch = this.input.charAt(this.pos); | |
| 5774 | if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); } | |
| 5775 | if (!escaped) { | |
| 5776 | if (ch === "[") { inClass = true; } | |
| 5777 | else if (ch === "]" && inClass) { inClass = false; } | |
| 5778 | else if (ch === "/" && !inClass) { break } | |
| 5779 | escaped = ch === "\\"; | |
| 5780 | } else { escaped = false; } | |
| 5781 | ++this.pos; | |
| 5782 | } | |
| 5783 | var pattern = this.input.slice(start, this.pos); | |
| 5784 | ++this.pos; | |
| 5785 | var flagsStart = this.pos; | |
| 5786 | var flags = this.readWord1(); | |
| 5787 | if (this.containsEsc) { this.unexpected(flagsStart); } | |
| 5788 | ||
| 5789 | // Validate pattern | |
| 5790 | var state = this.regexpState || (this.regexpState = new RegExpValidationState(this)); | |
| 5791 | state.reset(start, pattern, flags); | |
| 5792 | this.validateRegExpFlags(state); | |
| 5793 | this.validateRegExpPattern(state); | |
| 5794 | ||
| 5795 | // Create Literal#value property value. | |
| 5796 | var value = null; | |
| 5797 | try { | |
| 5798 | value = new RegExp(pattern, flags); | |
| 5799 | } catch (e) { | |
| 5800 | // ESTree requires null if it failed to instantiate RegExp object. | |
| 5801 | // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral | |
| 5802 | } | |
| 5803 | ||
| 5804 | return this.finishToken(types$1.regexp, {pattern: pattern, flags: flags, value: value}) | |
| 5805 | }; | |
| 5806 | ||
| 5807 | // Read an integer in the given radix. Return null if zero digits | |
| 5808 | // were read, the integer value otherwise. When `len` is given, this | |
| 5809 | // will return `null` unless the integer has exactly `len` digits. | |
| 5810 | ||
| 5811 | pp.readInt = function(radix, len, maybeLegacyOctalNumericLiteral) { | |
| 5812 | // `len` is used for character escape sequences. In that case, disallow separators. | |
| 5813 | var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined; | |
| 5814 | ||
| 5815 | // `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b) | |
| 5816 | // and isn't fraction part nor exponent part. In that case, if the first digit | |
| 5817 | // is zero then disallow separators. | |
| 5818 | var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48; | |
| 5819 | ||
| 5820 | var start = this.pos, total = 0, lastCode = 0; | |
| 5821 | for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) { | |
| 5822 | var code = this.input.charCodeAt(this.pos), val = (void 0); | |
| 5823 | ||
| 5824 | if (allowSeparators && code === 95) { | |
| 5825 | if (isLegacyOctalNumericLiteral) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals"); } | |
| 5826 | if (lastCode === 95) { this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore"); } | |
| 5827 | if (i === 0) { this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits"); } | |
| 5828 | lastCode = code; | |
| 5829 | continue | |
| 5830 | } | |
| 5831 | ||
| 5832 | if (code >= 97) { val = code - 97 + 10; } // a | |
| 5833 | else if (code >= 65) { val = code - 65 + 10; } // A | |
| 5834 | else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9 | |
| 5835 | else { val = Infinity; } | |
| 5836 | if (val >= radix) { break } | |
| 5837 | lastCode = code; | |
| 5838 | total = total * radix + val; | |
| 5839 | } | |
| 5840 | ||
| 5841 | if (allowSeparators && lastCode === 95) { this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits"); } | |
| 5842 | if (this.pos === start || len != null && this.pos - start !== len) { return null } | |
| 5843 | ||
| 5844 | return total | |
| 5845 | }; | |
| 5846 | ||
| 5847 | function stringToNumber(str, isLegacyOctalNumericLiteral) { | |
| 5848 | if (isLegacyOctalNumericLiteral) { | |
| 5849 | return parseInt(str, 8) | |
| 5850 | } | |
| 5851 | ||
| 5852 | // `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value. | |
| 5853 | return parseFloat(str.replace(/_/g, "")) | |
| 5854 | } | |
| 5855 | ||
| 5856 | function stringToBigInt(str) { | |
| 5857 | if (typeof BigInt !== "function") { | |
| 5858 | return null | |
| 5859 | } | |
| 5860 | ||
| 5861 | // `BigInt(value)` throws syntax error if the string contains numeric separators. | |
| 5862 | return BigInt(str.replace(/_/g, "")) | |
| 5863 | } | |
| 5864 | ||
| 5865 | pp.readRadixNumber = function(radix) { | |
| 5866 | var start = this.pos; | |
| 5867 | this.pos += 2; // 0x | |
| 5868 | var val = this.readInt(radix); | |
| 5869 | if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); } | |
| 5870 | if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) { | |
| 5871 | val = stringToBigInt(this.input.slice(start, this.pos)); | |
| 5872 | ++this.pos; | |
| 5873 | } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
| 5874 | return this.finishToken(types$1.num, val) | |
| 5875 | }; | |
| 5876 | ||
| 5877 | // Read an integer, octal integer, or floating-point number. | |
| 5878 | ||
| 5879 | pp.readNumber = function(startsWithDot) { | |
| 5880 | var start = this.pos; | |
| 5881 | if (!startsWithDot && this.readInt(10, undefined, true) === null) { this.raise(start, "Invalid number"); } | |
| 5882 | var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48; | |
| 5883 | if (octal && this.strict) { this.raise(start, "Invalid number"); } | |
| 5884 | var next = this.input.charCodeAt(this.pos); | |
| 5885 | if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) { | |
| 5886 | var val$1 = stringToBigInt(this.input.slice(start, this.pos)); | |
| 5887 | ++this.pos; | |
| 5888 | if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
| 5889 | return this.finishToken(types$1.num, val$1) | |
| 5890 | } | |
| 5891 | if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; } | |
| 5892 | if (next === 46 && !octal) { // '.' | |
| 5893 | ++this.pos; | |
| 5894 | this.readInt(10); | |
| 5895 | next = this.input.charCodeAt(this.pos); | |
| 5896 | } | |
| 5897 | if ((next === 69 || next === 101) && !octal) { // 'eE' | |
| 5898 | next = this.input.charCodeAt(++this.pos); | |
| 5899 | if (next === 43 || next === 45) { ++this.pos; } // '+-' | |
| 5900 | if (this.readInt(10) === null) { this.raise(start, "Invalid number"); } | |
| 5901 | } | |
| 5902 | if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } | |
| 5903 | ||
| 5904 | var val = stringToNumber(this.input.slice(start, this.pos), octal); | |
| 5905 | return this.finishToken(types$1.num, val) | |
| 5906 | }; | |
| 5907 | ||
| 5908 | // Read a string value, interpreting backslash-escapes. | |
| 5909 | ||
| 5910 | pp.readCodePoint = function() { | |
| 5911 | var ch = this.input.charCodeAt(this.pos), code; | |
| 5912 | ||
| 5913 | if (ch === 123) { // '{' | |
| 5914 | if (this.options.ecmaVersion < 6) { this.unexpected(); } | |
| 5915 | var codePos = ++this.pos; | |
| 5916 | code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos); | |
| 5917 | ++this.pos; | |
| 5918 | if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); } | |
| 5919 | } else { | |
| 5920 | code = this.readHexChar(4); | |
| 5921 | } | |
| 5922 | return code | |
| 5923 | }; | |
| 5924 | ||
| 5925 | pp.readString = function(quote) { | |
| 5926 | var out = "", chunkStart = ++this.pos; | |
| 5927 | for (;;) { | |
| 5928 | if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); } | |
| 5929 | var ch = this.input.charCodeAt(this.pos); | |
| 5930 | if (ch === quote) { break } | |
| 5931 | if (ch === 92) { // '\' | |
| 5932 | out += this.input.slice(chunkStart, this.pos); | |
| 5933 | out += this.readEscapedChar(false); | |
| 5934 | chunkStart = this.pos; | |
| 5935 | } else if (ch === 0x2028 || ch === 0x2029) { | |
| 5936 | if (this.options.ecmaVersion < 10) { this.raise(this.start, "Unterminated string constant"); } | |
| 5937 | ++this.pos; | |
| 5938 | if (this.options.locations) { | |
| 5939 | this.curLine++; | |
| 5940 | this.lineStart = this.pos; | |
| 5941 | } | |
| 5942 | } else { | |
| 5943 | if (isNewLine(ch)) { this.raise(this.start, "Unterminated string constant"); } | |
| 5944 | ++this.pos; | |
| 5945 | } | |
| 5946 | } | |
| 5947 | out += this.input.slice(chunkStart, this.pos++); | |
| 5948 | return this.finishToken(types$1.string, out) | |
| 5949 | }; | |
| 5950 | ||
| 5951 | // Reads template string tokens. | |
| 5952 | ||
| 5953 | var INVALID_TEMPLATE_ESCAPE_ERROR = {}; | |
| 5954 | ||
| 5955 | pp.tryReadTemplateToken = function() { | |
| 5956 | this.inTemplateElement = true; | |
| 5957 | try { | |
| 5958 | this.readTmplToken(); | |
| 5959 | } catch (err) { | |
| 5960 | if (err === INVALID_TEMPLATE_ESCAPE_ERROR) { | |
| 5961 | this.readInvalidTemplateToken(); | |
| 5962 | } else { | |
| 5963 | throw err | |
| 5964 | } | |
| 5965 | } | |
| 5966 | ||
| 5967 | this.inTemplateElement = false; | |
| 5968 | }; | |
| 5969 | ||
| 5970 | pp.invalidStringToken = function(position, message) { | |
| 5971 | if (this.inTemplateElement && this.options.ecmaVersion >= 9) { | |
| 5972 | throw INVALID_TEMPLATE_ESCAPE_ERROR | |
| 5973 | } else { | |
| 5974 | this.raise(position, message); | |
| 5975 | } | |
| 5976 | }; | |
| 5977 | ||
| 5978 | pp.readTmplToken = function() { | |
| 5979 | var out = "", chunkStart = this.pos; | |
| 5980 | for (;;) { | |
| 5981 | if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); } | |
| 5982 | var ch = this.input.charCodeAt(this.pos); | |
| 5983 | if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${' | |
| 5984 | if (this.pos === this.start && (this.type === types$1.template || this.type === types$1.invalidTemplate)) { | |
| 5985 | if (ch === 36) { | |
| 5986 | this.pos += 2; | |
| 5987 | return this.finishToken(types$1.dollarBraceL) | |
| 5988 | } else { | |
| 5989 | ++this.pos; | |
| 5990 | return this.finishToken(types$1.backQuote) | |
| 5991 | } | |
| 5992 | } | |
| 5993 | out += this.input.slice(chunkStart, this.pos); | |
| 5994 | return this.finishToken(types$1.template, out) | |
| 5995 | } | |
| 5996 | if (ch === 92) { // '\' | |
| 5997 | out += this.input.slice(chunkStart, this.pos); | |
| 5998 | out += this.readEscapedChar(true); | |
| 5999 | chunkStart = this.pos; | |
| 6000 | } else if (isNewLine(ch)) { | |
| 6001 | out += this.input.slice(chunkStart, this.pos); | |
| 6002 | ++this.pos; | |
| 6003 | switch (ch) { | |
| 6004 | case 13: | |
| 6005 | if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } | |
| 6006 | case 10: | |
| 6007 | out += "\n"; | |
| 6008 | break | |
| 6009 | default: | |
| 6010 | out += String.fromCharCode(ch); | |
| 6011 | break | |
| 6012 | } | |
| 6013 | if (this.options.locations) { | |
| 6014 | ++this.curLine; | |
| 6015 | this.lineStart = this.pos; | |
| 6016 | } | |
| 6017 | chunkStart = this.pos; | |
| 6018 | } else { | |
| 6019 | ++this.pos; | |
| 6020 | } | |
| 6021 | } | |
| 6022 | }; | |
| 6023 | ||
| 6024 | // Reads a template token to search for the end, without validating any escape sequences | |
| 6025 | pp.readInvalidTemplateToken = function() { | |
| 6026 | for (; this.pos < this.input.length; this.pos++) { | |
| 6027 | switch (this.input[this.pos]) { | |
| 6028 | case "\\": | |
| 6029 | ++this.pos; | |
| 6030 | break | |
| 6031 | ||
| 6032 | case "$": | |
| 6033 | if (this.input[this.pos + 1] !== "{") { break } | |
| 6034 | // fall through | |
| 6035 | case "`": | |
| 6036 | return this.finishToken(types$1.invalidTemplate, this.input.slice(this.start, this.pos)) | |
| 6037 | ||
| 6038 | case "\r": | |
| 6039 | if (this.input[this.pos + 1] === "\n") { ++this.pos; } | |
| 6040 | // fall through | |
| 6041 | case "\n": case "\u2028": case "\u2029": | |
| 6042 | ++this.curLine; | |
| 6043 | this.lineStart = this.pos + 1; | |
| 6044 | break | |
| 6045 | } | |
| 6046 | } | |
| 6047 | this.raise(this.start, "Unterminated template"); | |
| 6048 | }; | |
| 6049 | ||
| 6050 | // Used to read escaped characters | |
| 6051 | ||
| 6052 | pp.readEscapedChar = function(inTemplate) { | |
| 6053 | var ch = this.input.charCodeAt(++this.pos); | |
| 6054 | ++this.pos; | |
| 6055 | switch (ch) { | |
| 6056 | case 110: return "\n" // 'n' -> '\n' | |
| 6057 | case 114: return "\r" // 'r' -> '\r' | |
| 6058 | case 120: return String.fromCharCode(this.readHexChar(2)) // 'x' | |
| 6059 | case 117: return codePointToString(this.readCodePoint()) // 'u' | |
| 6060 | case 116: return "\t" // 't' -> '\t' | |
| 6061 | case 98: return "\b" // 'b' -> '\b' | |
| 6062 | case 118: return "\u000b" // 'v' -> '\u000b' | |
| 6063 | case 102: return "\f" // 'f' -> '\f' | |
| 6064 | case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n' | |
| 6065 | case 10: // ' \n' | |
| 6066 | if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } | |
| 6067 | return "" | |
| 6068 | case 56: | |
| 6069 | case 57: | |
| 6070 | if (this.strict) { | |
| 6071 | this.invalidStringToken( | |
| 6072 | this.pos - 1, | |
| 6073 | "Invalid escape sequence" | |
| 6074 | ); | |
| 6075 | } | |
| 6076 | if (inTemplate) { | |
| 6077 | var codePos = this.pos - 1; | |
| 6078 | ||
| 6079 | this.invalidStringToken( | |
| 6080 | codePos, | |
| 6081 | "Invalid escape sequence in template string" | |
| 6082 | ); | |
| 6083 | } | |
| 6084 | default: | |
| 6085 | if (ch >= 48 && ch <= 55) { | |
| 6086 | var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]; | |
| 6087 | var octal = parseInt(octalStr, 8); | |
| 6088 | if (octal > 255) { | |
| 6089 | octalStr = octalStr.slice(0, -1); | |
| 6090 | octal = parseInt(octalStr, 8); | |
| 6091 | } | |
| 6092 | this.pos += octalStr.length - 1; | |
| 6093 | ch = this.input.charCodeAt(this.pos); | |
| 6094 | if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) { | |
| 6095 | this.invalidStringToken( | |
| 6096 | this.pos - 1 - octalStr.length, | |
| 6097 | inTemplate | |
| 6098 | ? "Octal literal in template string" | |
| 6099 | : "Octal literal in strict mode" | |
| 6100 | ); | |
| 6101 | } | |
| 6102 | return String.fromCharCode(octal) | |
| 6103 | } | |
| 6104 | if (isNewLine(ch)) { | |
| 6105 | // Unicode new line characters after \ get removed from output in both | |
| 6106 | // template literals and strings | |
| 6107 | if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } | |
| 6108 | return "" | |
| 6109 | } | |
| 6110 | return String.fromCharCode(ch) | |
| 6111 | } | |
| 6112 | }; | |
| 6113 | ||
| 6114 | // Used to read character escape sequences ('\x', '\u', '\U'). | |
| 6115 | ||
| 6116 | pp.readHexChar = function(len) { | |
| 6117 | var codePos = this.pos; | |
| 6118 | var n = this.readInt(16, len); | |
| 6119 | if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); } | |
| 6120 | return n | |
| 6121 | }; | |
| 6122 | ||
| 6123 | // Read an identifier, and return it as a string. Sets `this.containsEsc` | |
| 6124 | // to whether the word contained a '\u' escape. | |
| 6125 | // | |
| 6126 | // Incrementally adds only escaped chars, adding other chunks as-is | |
| 6127 | // as a micro-optimization. | |
| 6128 | ||
| 6129 | pp.readWord1 = function() { | |
| 6130 | this.containsEsc = false; | |
| 6131 | var word = "", first = true, chunkStart = this.pos; | |
| 6132 | var astral = this.options.ecmaVersion >= 6; | |
| 6133 | while (this.pos < this.input.length) { | |
| 6134 | var ch = this.fullCharCodeAtPos(); | |
| 6135 | if (isIdentifierChar(ch, astral)) { | |
| 6136 | this.pos += ch <= 0xffff ? 1 : 2; | |
| 6137 | } else if (ch === 92) { // "\" | |
| 6138 | this.containsEsc = true; | |
| 6139 | word += this.input.slice(chunkStart, this.pos); | |
| 6140 | var escStart = this.pos; | |
| 6141 | if (this.input.charCodeAt(++this.pos) !== 117) // "u" | |
| 6142 | { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); } | |
| 6143 | ++this.pos; | |
| 6144 | var esc = this.readCodePoint(); | |
| 6145 | if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral)) | |
| 6146 | { this.invalidStringToken(escStart, "Invalid Unicode escape"); } | |
| 6147 | word += codePointToString(esc); | |
| 6148 | chunkStart = this.pos; | |
| 6149 | } else { | |
| 6150 | break | |
| 6151 | } | |
| 6152 | first = false; | |
| 6153 | } | |
| 6154 | return word + this.input.slice(chunkStart, this.pos) | |
| 6155 | }; | |
| 6156 | ||
| 6157 | // Read an identifier or keyword token. Will check for reserved | |
| 6158 | // words when necessary. | |
| 6159 | ||
| 6160 | pp.readWord = function() { | |
| 6161 | var word = this.readWord1(); | |
| 6162 | var type = types$1.name; | |
| 6163 | if (this.keywords.test(word)) { | |
| 6164 | type = keywords[word]; | |
| 6165 | } | |
| 6166 | return this.finishToken(type, word) | |
| 6167 | }; | |
| 6168 | ||
| 6169 | // Acorn is a tiny, fast JavaScript parser written in JavaScript. | |
| 6170 | // | |
| 6171 | // Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and | |
| 6172 | // various contributors and released under an MIT license. | |
| 6173 | // | |
| 6174 | // Git repositories for Acorn are available at | |
| 6175 | // | |
| 6176 | // http://marijnhaverbeke.nl/git/acorn | |
| 6177 | // https://github.com/acornjs/acorn.git | |
| 6178 | // | |
| 6179 | // Please use the [github bug tracker][ghbt] to report issues. | |
| 6180 | // | |
| 6181 | // [ghbt]: https://github.com/acornjs/acorn/issues | |
| 6182 | ||
| 6183 | ||
| 6184 | var version = "8.15.0"; | |
| 6185 | ||
| 6186 | Parser.acorn = { | |
| 6187 | Parser: Parser, | |
| 6188 | version: version, | |
| 6189 | defaultOptions: defaultOptions, | |
| 6190 | Position: Position, | |
| 6191 | SourceLocation: SourceLocation, | |
| 6192 | getLineInfo: getLineInfo, | |
| 6193 | Node: Node, | |
| 6194 | TokenType: TokenType, | |
| 6195 | tokTypes: types$1, | |
| 6196 | keywordTypes: keywords, | |
| 6197 | TokContext: TokContext, | |
| 6198 | tokContexts: types, | |
| 6199 | isIdentifierChar: isIdentifierChar, | |
| 6200 | isIdentifierStart: isIdentifierStart, | |
| 6201 | Token: Token, | |
| 6202 | isNewLine: isNewLine, | |
| 6203 | lineBreak: lineBreak, | |
| 6204 | lineBreakG: lineBreakG, | |
| 6205 | nonASCIIwhitespace: nonASCIIwhitespace | |
| 6206 | }; | |
| 6207 | ||
| 6208 | // The main exported interface (under `self.acorn` when in the | |
| 6209 | // browser) is a `parse` function that takes a code string and returns | |
| 6210 | // an abstract syntax tree as specified by the [ESTree spec][estree]. | |
| 6211 | // | |
| 6212 | // [estree]: https://github.com/estree/estree | |
| 6213 | ||
| 6214 | function parse(input, options) { | |
| 6215 | return Parser.parse(input, options) | |
| 6216 | } | |
| 6217 | ||
| 6218 | // This function tries to parse a single expression at a given | |
| 6219 | // offset in a string. Useful for parsing mixed-language formats | |
| 6220 | // that embed JavaScript expressions. | |
| 6221 | ||
| 6222 | function parseExpressionAt(input, pos, options) { | |
| 6223 | return Parser.parseExpressionAt(input, pos, options) | |
| 6224 | } | |
| 6225 | ||
| 6226 | // Acorn is organized as a tokenizer and a recursive-descent parser. | |
| 6227 | // The `tokenizer` export provides an interface to the tokenizer. | |
| 6228 | ||
| 6229 | function tokenizer(input, options) { | |
| 6230 | return Parser.tokenizer(input, options) | |
| 6231 | } | |
| 6232 | ||
| 6233 | export { Node, Parser, Position, SourceLocation, TokContext, Token, TokenType, defaultOptions, getLineInfo, isIdentifierChar, isIdentifierStart, isNewLine, keywords as keywordTypes, lineBreak, lineBreakG, nonASCIIwhitespace, parse, parseExpressionAt, types as tokContexts, types$1 as tokTypes, tokenizer, version }; |
| … | … | @@ -0,0 +1,90 @@ |
| 1 | 'use strict'; | |
| 2 | ||
| 3 | var path = require('path'); | |
| 4 | var fs = require('fs'); | |
| 5 | var acorn = require('./acorn.js'); | |
| 6 | ||
| 7 | function _interopNamespaceDefault(e) { | |
| 8 | var n = Object.create(null); | |
| 9 | if (e) { | |
| 10 | Object.keys(e).forEach(function (k) { | |
| 11 | if (k !== 'default') { | |
| 12 | var d = Object.getOwnPropertyDescriptor(e, k); | |
| 13 | Object.defineProperty(n, k, d.get ? d : { | |
| 14 | enumerable: true, | |
| 15 | get: function () { return e[k]; } | |
| 16 | }); | |
| 17 | } | |
| 18 | }); | |
| 19 | } | |
| 20 | n.default = e; | |
| 21 | return Object.freeze(n); | |
| 22 | } | |
| 23 | ||
| 24 | var acorn__namespace = /*#__PURE__*/_interopNamespaceDefault(acorn); | |
| 25 | ||
| 26 | var inputFilePaths = [], forceFileName = false, fileMode = false, silent = false, compact = false, tokenize = false; | |
| 27 | var options = {}; | |
| 28 | ||
| 29 | function help(status) { | |
| 30 | var print = (status === 0) ? console.log : console.error; | |
| 31 | print("usage: " + path.basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|...|--ecma2015|--ecma2016|--ecma2017|--ecma2018|...]"); | |
| 32 | print(" [--tokenize] [--locations] [--allow-hash-bang] [--allow-await-outside-function] [--compact] [--silent] [--module] [--help] [--] [<infile>...]"); | |
| 33 | process.exit(status); | |
| 34 | } | |
| 35 | ||
| 36 | for (var i = 2; i < process.argv.length; ++i) { | |
| 37 | var arg = process.argv[i]; | |
| 38 | if (arg[0] !== "-" || arg === "-") { inputFilePaths.push(arg); } | |
| 39 | else if (arg === "--") { | |
| 40 | inputFilePaths.push.apply(inputFilePaths, process.argv.slice(i + 1)); | |
| 41 | forceFileName = true; | |
| 42 | break | |
| 43 | } else if (arg === "--locations") { options.locations = true; } | |
| 44 | else if (arg === "--allow-hash-bang") { options.allowHashBang = true; } | |
| 45 | else if (arg === "--allow-await-outside-function") { options.allowAwaitOutsideFunction = true; } | |
| 46 | else if (arg === "--silent") { silent = true; } | |
| 47 | else if (arg === "--compact") { compact = true; } | |
| 48 | else if (arg === "--help") { help(0); } | |
| 49 | else if (arg === "--tokenize") { tokenize = true; } | |
| 50 | else if (arg === "--module") { options.sourceType = "module"; } | |
| 51 | else { | |
| 52 | var match = arg.match(/^--ecma(\d+)$/); | |
| 53 | if (match) | |
| 54 | { options.ecmaVersion = +match[1]; } | |
| 55 | else | |
| 56 | { help(1); } | |
| 57 | } | |
| 58 | } | |
| 59 | ||
| 60 | function run(codeList) { | |
| 61 | var result = [], fileIdx = 0; | |
| 62 | try { | |
| 63 | codeList.forEach(function (code, idx) { | |
| 64 | fileIdx = idx; | |
| 65 | if (!tokenize) { | |
| 66 | result = acorn__namespace.parse(code, options); | |
| 67 | options.program = result; | |
| 68 | } else { | |
| 69 | var tokenizer = acorn__namespace.tokenizer(code, options), token; | |
| 70 | do { | |
| 71 | token = tokenizer.getToken(); | |
| 72 | result.push(token); | |
| 73 | } while (token.type !== acorn__namespace.tokTypes.eof) | |
| 74 | } | |
| 75 | }); | |
| 76 | } catch (e) { | |
| 77 | console.error(fileMode ? e.message.replace(/\(\d+:\d+\)$/, function (m) { return m.slice(0, 1) + inputFilePaths[fileIdx] + " " + m.slice(1); }) : e.message); | |
| 78 | process.exit(1); | |
| 79 | } | |
| 80 | if (!silent) { console.log(JSON.stringify(result, function (_, value) { return typeof value === "bigint" ? null : value; }, compact ? null : 2)); } | |
| 81 | } | |
| 82 | ||
| 83 | if (fileMode = inputFilePaths.length && (forceFileName || !inputFilePaths.includes("-") || inputFilePaths.length !== 1)) { | |
| 84 | run(inputFilePaths.map(function (path) { return fs.readFileSync(path, "utf8"); })); | |
| 85 | } else { | |
| 86 | var code = ""; | |
| 87 | process.stdin.resume(); | |
| 88 | process.stdin.on("data", function (chunk) { return code += chunk; }); | |
| 89 | process.stdin.on("end", function () { return run([code]); }); | |
| 90 | } |
| … | … | @@ -0,0 +1,50 @@ |
| 1 | { | |
| 2 | "name": "acorn", | |
| 3 | "description": "ECMAScript parser", | |
| 4 | "homepage": "https://github.com/acornjs/acorn", | |
| 5 | "main": "dist/acorn.js", | |
| 6 | "types": "dist/acorn.d.ts", | |
| 7 | "module": "dist/acorn.mjs", | |
| 8 | "exports": { | |
| 9 | ".": [ | |
| 10 | { | |
| 11 | "import": "./dist/acorn.mjs", | |
| 12 | "require": "./dist/acorn.js", | |
| 13 | "default": "./dist/acorn.js" | |
| 14 | }, | |
| 15 | "./dist/acorn.js" | |
| 16 | ], | |
| 17 | "./package.json": "./package.json" | |
| 18 | }, | |
| 19 | "version": "8.15.0", | |
| 20 | "engines": { | |
| 21 | "node": ">=0.4.0" | |
| 22 | }, | |
| 23 | "maintainers": [ | |
| 24 | { | |
| 25 | "name": "Marijn Haverbeke", | |
| 26 | "email": "marijnh@gmail.com", | |
| 27 | "web": "https://marijnhaverbeke.nl" | |
| 28 | }, | |
| 29 | { | |
| 30 | "name": "Ingvar Stepanyan", | |
| 31 | "email": "me@rreverser.com", | |
| 32 | "web": "https://rreverser.com/" | |
| 33 | }, | |
| 34 | { | |
| 35 | "name": "Adrian Heine", | |
| 36 | "web": "http://adrianheine.de" | |
| 37 | } | |
| 38 | ], | |
| 39 | "repository": { | |
| 40 | "type": "git", | |
| 41 | "url": "git+https://github.com/acornjs/acorn.git" | |
| 42 | }, | |
| 43 | "license": "MIT", | |
| 44 | "scripts": { | |
| 45 | "prepare": "cd ..; npm run build:main" | |
| 46 | }, | |
| 47 | "bin": { | |
| 48 | "acorn": "bin/acorn" | |
| 49 | } | |
| 50 | } |
| … | … | @@ -0,0 +1,633 @@ |
| 1 | # Shaderfrog GLSL Compiler | |
| 2 | ||
| 3 | The [Shaderfrog](https://shaderfrog.com/app) GLSL compiler is an open source | |
| 4 | GLSL 1.00 and 3.00 parser and preprocessor that compiles [back to | |
| 5 | GLSL](src/parser/generator.ts). Both the parser and preprocessor can preserve | |
| 6 | comments and whitespace. | |
| 7 | ||
| 8 | The parser is built with a PEG grammar, via the [Peggy](https://peggyjs.org) | |
| 9 | Javascript library. The PEG grammars for both the preprocessor and parser | |
| 10 | are available [on Github](https://github.com/ShaderFrog/glsl-parser). | |
| 11 | ||
| 12 | See [the state of this library](#state-of-this-library) for limitations and | |
| 13 | goals of this compiler. | |
| 14 | ||
| 15 | # Table of Contents | |
| 16 | ||
| 17 | - [Installation](#installation) | |
| 18 | - [Parsing](#parsing) | |
| 19 | - [The program type](#the-program-type) | |
| 20 | - [Scope](#scope) | |
| 21 | - [Errors](#errors) | |
| 22 | - [Preprocessing](#preprocessing) | |
| 23 | - [Manipulating and Searching ASTs](#manipulating-and-searching-asts) | |
| 24 | - [Visitors](#visitors) | |
| 25 | - [Utility Functions](#utility-functions) | |
| 26 | - [What are "parsing" and "preprocessing"?](#what-are-parsing-and-preprocessing) | |
| 27 | - [State of this library](#state-of-this-library) | |
| 28 | - [Limitations of the Parser and Preprocessor](#limitations-of-the-parser-and-preprocessor) | |
| 29 | - [Local Development](#local-development) | |
| 30 | ||
| 31 | # Usage | |
| 32 | ||
| 33 | ## Installation | |
| 34 | ||
| 35 | ```bash | |
| 36 | npm install --save @shaderfrog/glsl-parser | |
| 37 | ``` | |
| 38 | ||
| 39 | ## Parsing | |
| 40 | ||
| 41 | ```typescript | |
| 42 | import { parse, generate } from '@shaderfrog/glsl-parser'; | |
| 43 | ||
| 44 | // To parse a GLSL program's source code into an AST: | |
| 45 | const program = parse('float a = 1.0;'); | |
| 46 | ||
| 47 | // To turn a parsed AST back into a source program | |
| 48 | const transpiled = generate(program); | |
| 49 | ``` | |
| 50 | ||
| 51 | The parser accepts an optional second `options` argument: | |
| 52 | ```js | |
| 53 | parse('float a = 1.0;', options); | |
| 54 | ``` | |
| 55 | ||
| 56 | Where `options` is: | |
| 57 | ||
| 58 | ```typescript | |
| 59 | type ParserOptions = { | |
| 60 | // The stage of the GLSL source, which defines the built in variables when | |
| 61 | // parsing, like gl_Position. If specified, when the compiler encounters an | |
| 62 | // expected variable for that stage, it will continue on normally (and add | |
| 63 | // that variable, like gl_Position, to the current scope). If it encounters an | |
| 64 | // unknown variable, it will log a warning or raise an exception, depending | |
| 65 | // on if `failOnWarn` is set. If the stage is set to 'either' - used in the | |
| 66 | // case when you don't yet know what stage the GLSL is, the compiler *won't* | |
| 67 | // warn on built-in variables for *either* stage. If this option is not set, | |
| 68 | // the compiler will warn on *all* built-in variables it encounters as not | |
| 69 | // defined. | |
| 70 | stage: 'vertex' | 'fragment' | 'either'; | |
| 71 | ||
| 72 | // Hide warnings. If set to false or not set, then the parser logs warnings | |
| 73 | // like undefined functions and variables. If `failOnWarn` is set to true, | |
| 74 | // warnings will still cause the parser to raise an error. Defaults to false. | |
| 75 | quiet?: boolean; | |
| 76 | ||
| 77 | // If true, sets location information on each AST node, in the form of | |
| 78 | // { column: number, line: number, offset: number }. Defaults to false. | |
| 79 | includeLocation?: boolean; | |
| 80 | ||
| 81 | // If true, causes the parser to raise an error instead of log a warning. | |
| 82 | // The parser does limited type checking, and things like undeclared variables | |
| 83 | // are treated as warnings. Defaults to false. | |
| 84 | failOnWarn?: boolean; | |
| 85 | ||
| 86 | // An optional string representing the file name of your GLSL For example, | |
| 87 | // you can pass "main.glsl" here. If an error is raised, the error message | |
| 88 | // will show "main.glsl:row:column". This is only used in the error message. | |
| 89 | grammarSource?: string; | |
| 90 | } | |
| 91 | ``` | |
| 92 | ||
| 93 | ## The program type | |
| 94 | `parse()` returns a `Program`, which is a special AST Node: | |
| 95 | ||
| 96 | ```typescript | |
| 97 | interface Program { | |
| 98 | // Hard coded AST node type of "program" | |
| 99 | type: 'program'; | |
| 100 | // The AST itself is an array of the top level statements | |
| 101 | program: AstNode[]; | |
| 102 | // All of the scopes found during parsing | |
| 103 | scopes: Scope[]; | |
| 104 | // Leading whitespace of the source code | |
| 105 | wsStart?: string; | |
| 106 | // Trailing whitespace of the source code | |
| 107 | wsEnd?: string; | |
| 108 | } | |
| 109 | ``` | |
| 110 | ||
| 111 | ## Scope | |
| 112 | ||
| 113 | `parse()` returns a [`Program`](#the-program-type), which has a `scopes` array on it. A scope looks | |
| 114 | like: | |
| 115 | ```typescript | |
| 116 | type Scope = { | |
| 117 | name: string; | |
| 118 | parent?: Scope; | |
| 119 | bindings: ScopeIndex; | |
| 120 | types: TypeScopeIndex; | |
| 121 | functions: FunctionScopeIndex; | |
| 122 | location?: LocationObject; | |
| 123 | } | |
| 124 | ``` | |
| 125 | ||
| 126 | The `name` of a scope is either `"global"`, the name of the function that | |
| 127 | introduced the scope, or in anonymous blocks, `"{"`. In each scope, `bindings` represents variables, | |
| 128 | `types` represents user-created types (structs in GLSL), and `functions` represents | |
| 129 | functions. | |
| 130 | ||
| 131 | For `bindings` and `types`, the scope index looks like: | |
| 132 | ```typescript | |
| 133 | type ScopeIndex = { | |
| 134 | [name: string]: { | |
| 135 | declaration?: AstNode; | |
| 136 | references: AstNode[]; | |
| 137 | } | |
| 138 | } | |
| 139 | ``` | |
| 140 | ||
| 141 | Where `name` is the name of the variable or type. `declaration` is the AST node | |
| 142 | where the variable was declared. In the case the variable is used without being | |
| 143 | declared, `declaration` won't be present. If you set the [`failOnWarn` parser | |
| 144 | option](#Parsing) to `true`, the parser will throw an error when encountering | |
| 145 | an undeclared variable, rather than allow a scope entry without a declaration. | |
| 146 | ||
| 147 | For `functions`, the scope index is slightly different: | |
| 148 | ```typescript | |
| 149 | type FunctionScopeIndex = { | |
| 150 | [name: string]: { | |
| 151 | [signature: string]: { | |
| 152 | returnType: string; | |
| 153 | parameterTypes: string[]; | |
| 154 | declaration?: FunctionNode; | |
| 155 | references: AstNode[]; | |
| 156 | } | |
| 157 | } | |
| 158 | }; | |
| 159 | ``` | |
| 160 | ||
| 161 | Where `name` is the name of the function, and `signature` is a string representing | |
| 162 | the function's return and parameter types, in the form of `"returnType: paramType1, paramType2, ..."` | |
| 163 | or `"returnType: void"` in the case of no arguments. Each `signature` in this | |
| 164 | index represents an "overloaded" function in GLSL, as in: | |
| 165 | ||
| 166 | ```glsl | |
| 167 | void someFunction(int x) {}; | |
| 168 | void someFunction(int x, int y) {}; | |
| 169 | ``` | |
| 170 | ||
| 171 | With this source code, there will be two entries under `name`, one for each | |
| 172 | overload signature. The `references` are the uses of that specific overloaded | |
| 173 | version of the function. `references` also contains the function prototypes | |
| 174 | for the overloaded function, if present. | |
| 175 | ||
| 176 | In the case there is only one declaration for a function, there will still be | |
| 177 | a single entry under `name` with the function's `signature`. | |
| 178 | ||
| 179 | ⚠️ Caution! This parser does very limited type checking. This leads to a known | |
| 180 | case where a function call can match to the wrong overload in scope: | |
| 181 | ||
| 182 | ```glsl | |
| 183 | void someFunction(float, float); | |
| 184 | void someFunction(bool, bool); | |
| 185 | someFunction(true, true); // This will be attributed to the wrong scope entry | |
| 186 | ``` | |
| 187 | ||
| 188 | The parser doesn't know the type of the operands in the function call, so it | |
| 189 | matches based on the name and arity of the functions. | |
| 190 | ||
| 191 | See also [Utility-Functions](#Utility-Functions) for renaming scope references. | |
| 192 | ||
| 193 | ## Errors | |
| 194 | ||
| 195 | If you have invalid GLSL, the parser throws a `GlslSyntaxError`. | |
| 196 | ||
| 197 | ```ts | |
| 198 | import { parse, GlslSyntaxError } from '@shaderfrog/glsl-parser'; | |
| 199 | ||
| 200 | let error: GlslSyntaxError | undefined; | |
| 201 | try { | |
| 202 | // Line without a semicolon | |
| 203 | parse(`float a`); | |
| 204 | } catch (e) { | |
| 205 | error = e as GlslSyntaxError; | |
| 206 | } | |
| 207 | ``` | |
| 208 | ||
| 209 | If you want to check if a caught error is an `instanceof` a `GlslSyntaxError`: | |
| 210 | ```ts | |
| 211 | console.log(error instanceof GlslSyntaxError) | |
| 212 | // true | |
| 213 | ``` | |
| 214 | ||
| 215 | The only error the parser intentionally throws is a `GlslSyntaxError`. You | |
| 216 | should be safe to cast it to a `GlslSyntaxError` with `as` in Typescript. | |
| 217 | ||
| 218 | The error message string is automatically generated by Peggy: | |
| 219 | ```ts | |
| 220 | console.log(error.message) | |
| 221 | /* | |
| 222 | Error: Expected ",", ";", "=", or array specifier but "f" found. | |
| 223 | --> undefined:2:1 | |
| 224 | | | |
| 225 | 2 | float b | |
| 226 | | ^ | |
| 227 | */ | |
| 228 | ``` | |
| 229 | ||
| 230 | The error object includes the location of the error. | |
| 231 | ||
| 232 | ```ts | |
| 233 | console.log(error.location) | |
| 234 | /* | |
| 235 | { | |
| 236 | source: undefined, | |
| 237 | start: { offset: 7, line: 1, column: 8 }, | |
| 238 | end: { offset: 7, line: 1, column: 8 } | |
| 239 | } | |
| 240 | */ | |
| 241 | ``` | |
| 242 | Note the `source` field on the error object is the `grammarSource` string | |
| 243 | provided to the parser options, which is `undefined` by default. If you pass in | |
| 244 | a `grammarSource` to `parse()`, it shows up in the error object. This is | |
| 245 | meant to help you track which source file you're parsing, for example you could | |
| 246 | enter `"myfile.glsl"` as an argument to `parse()` so that the error | |
| 247 | includes that your source GLSL came from your application's `myfile.glsl` file. | |
| 248 | ||
| 249 | ## Preprocessing | |
| 250 | ||
| 251 | The parser also ships with a `preprocess()` function. | |
| 252 | ||
| 253 | The preprocessor takes in a program source code string and produces a | |
| 254 | preprocessed program source code string. If you want to access and manipulate | |
| 255 | the AST produced by preprocessing, see the next sections. | |
| 256 | ||
| 257 | ```typescript | |
| 258 | import preprocess from '@shaderfrog/glsl-parser/preprocessor'; | |
| 259 | ||
| 260 | // Preprocess a program | |
| 261 | console.log(preprocess(` | |
| 262 | #define a 1 | |
| 263 | float b = a; | |
| 264 | `, options)); | |
| 265 | ``` | |
| 266 | ||
| 267 | Where `options` is: | |
| 268 | ||
| 269 | ```typescript | |
| 270 | type PreprocessorOptions = { | |
| 271 | // Don't strip comments before preprocessing | |
| 272 | preserveComments: boolean, | |
| 273 | // Macro definitions to use when preprocessing | |
| 274 | defines: { | |
| 275 | SOME_MACRO_NAME: 'macro body' | |
| 276 | }, | |
| 277 | // A list of callbacks evaluated for each node type, and returns whether or not | |
| 278 | // this AST node is subject to preprocessing | |
| 279 | preserve: { | |
| 280 | ast_node_name: (path) => boolean | |
| 281 | } | |
| 282 | } | |
| 283 | ``` | |
| 284 | ||
| 285 | A preprocessed program string can be handed off to the main GLSL parser. | |
| 286 | Preprocessing is optional, but a program string may not be valid until it is | |
| 287 | preprocessed. | |
| 288 | ||
| 289 | If you want more control over preprocessing, the `preprocess` function above is | |
| 290 | a convenience method for approximately the following: | |
| 291 | ||
| 292 | ```typescript | |
| 293 | import { | |
| 294 | preprocessAst, | |
| 295 | preprocessComments, | |
| 296 | generate, | |
| 297 | parse, | |
| 298 | } from '@shaderfrog/glsl-parser/preprocessor'; | |
| 299 | ||
| 300 | // Remove comments before preprocessing | |
| 301 | const commentsRemoved = preprocessComments(`float a = 1.0;`); | |
| 302 | ||
| 303 | // Parse the source text into an AST | |
| 304 | const ast = parse(commentsRemoved); | |
| 305 | ||
| 306 | // Then preprocess it, expanding #defines, evaluating #ifs, etc | |
| 307 | preprocessAst(ast); | |
| 308 | ||
| 309 | // Then convert it back into a program string, which can be passed to the | |
| 310 | // core glsl parser | |
| 311 | const preprocessed = generate(ast); | |
| 312 | ``` | |
| 313 | ||
| 314 | ## Accessing the raw Peggy parser | |
| 315 | ||
| 316 | If you need to access the Peggy compiled parser directly, import the `parser`. | |
| 317 | You can manually call `parser.parse()` if you prefer. Note if there are errors, | |
| 318 | rather than returning a `GlslSyntaxError`, it will return the underlying | |
| 319 | `peg$syntaxError`. | |
| 320 | ||
| 321 | ```typescript | |
| 322 | import { parser } from '@shaderfrog/glsl-parser'; | |
| 323 | import { parser as preprocessorParser } from '@shaderfrog/glsl-parser/preprocessor'; | |
| 324 | ||
| 325 | try { | |
| 326 | const ast = parser.parse('float f = 1.0;'); | |
| 327 | } catch (e) { | |
| 328 | console.log(e instanceof parser.SyntaxError); // true | |
| 329 | } | |
| 330 | ``` | |
| 331 | ||
| 332 | ## Manipulating and Searching ASTs | |
| 333 | ||
| 334 | ### Visitors | |
| 335 | ||
| 336 | The Shaderfrog parser provides a AST visitor function for manipulating and | |
| 337 | searching an AST. The visitor API loosely follows the [Babel visitor API](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-visitors). A visitor object looks | |
| 338 | like: | |
| 339 | ||
| 340 | ```typescript | |
| 341 | const visitors = { | |
| 342 | function_call: { | |
| 343 | enter: (path) => {}, | |
| 344 | exit: (path) => {}, | |
| 345 | } | |
| 346 | } | |
| 347 | ``` | |
| 348 | ||
| 349 | Where every key in the object is a node type, and every value is an object | |
| 350 | with optional `enter` and `exit` functions. What's passed to each function | |
| 351 | is **not** the AST node itself, instead it's a "path" object, which gives you | |
| 352 | information about the node's parents, methods to manipulate the node, and the | |
| 353 | node itself. The path object: | |
| 354 | ||
| 355 | ```typescript | |
| 356 | { | |
| 357 | // Properties: | |
| 358 | ||
| 359 | // The node itself | |
| 360 | node: AstNode; | |
| 361 | // The parent of this node | |
| 362 | parent: AstNode | null; | |
| 363 | // The parent path of this path | |
| 364 | parentPath: Path | null; | |
| 365 | // The key of this node in the parent object, if node parent is an object | |
| 366 | key: string | null; | |
| 367 | // The index of this node in the parent array, if node parent is an array | |
| 368 | index: number | null; | |
| 369 | ||
| 370 | // Methods: | |
| 371 | ||
| 372 | // Don't visit any children of this node | |
| 373 | skip: () => void; | |
| 374 | // Stop traversal entirely | |
| 375 | stop: () => void; | |
| 376 | // Remove this node from the AST | |
| 377 | remove: () => void; | |
| 378 | // Replace this node with another AST node. See replaceWith() documentation. | |
| 379 | replaceWith: (replacer: any) => void; | |
| 380 | // Search for parents of this node's parent using a test function | |
| 381 | findParent: (test: (p: Path) => boolean) => Path | null; | |
| 382 | } | |
| 383 | ``` | |
| 384 | ||
| 385 | Visit an AST by calling the visit method with an AST and visitors: | |
| 386 | ||
| 387 | ```typescript | |
| 388 | import { visit } from '@shaderfrog/glsl-parser/ast'; | |
| 389 | ||
| 390 | visit(ast, visitors); | |
| 391 | ``` | |
| 392 | ||
| 393 | The visit function doesn't return a value. If you want to collect data from the | |
| 394 | AST, use a variable in the outer scope to collect data. For example: | |
| 395 | ||
| 396 | ```typescript | |
| 397 | let numberOfFunctionCalls = 0; | |
| 398 | visit(ast, { | |
| 399 | function_call: { | |
| 400 | enter: (path) => { | |
| 401 | numberOfFunctionCalls += 1; | |
| 402 | }, | |
| 403 | } | |
| 404 | }); | |
| 405 | console.log('There are ', numberOfFunctionCalls, 'function calls'); | |
| 406 | ``` | |
| 407 | ||
| 408 | You can also visit the preprocessed AST with `visitPreprocessedAst`. Visitors | |
| 409 | follow the same convention outlined above. | |
| 410 | ||
| 411 | ```typescript | |
| 412 | import { | |
| 413 | parse, | |
| 414 | visitPreprocessedAst, | |
| 415 | } from '@shaderfrog/glsl-parser/preprocessor'; | |
| 416 | ||
| 417 | // Parse the source text into an AST | |
| 418 | const ast = parse(`float a = 1.0;`); | |
| 419 | visitPreprocessedAst(ast, visitors); | |
| 420 | ``` | |
| 421 | ||
| 422 | ### Stopping traversal | |
| 423 | ||
| 424 | To skip all children of a node, call `path.skip()`. | |
| 425 | ||
| 426 | To stop traversal entirely, call `path.stop()` in either `enter()` or `exit()`. | |
| 427 | No future `enter()` nor `exit()` callbacks will fire. | |
| 428 | ||
| 429 | ### Visitor `.replaceWith()` Behavior | |
| 430 | ||
| 431 | When you visit a node and call `path.replaceWith(otherNode)` inside the visitor's `enter()` method: | |
| 432 | 1. `otherNode` and its children **are** visited by the same visitors. | |
| 433 | 2. The `exit()` function of the visitor **is not called.** | |
| 434 | ||
| 435 | Notes: | |
| 436 | - Calling `.replaceWith()` in a visitor's `exit()` method is undefined behavior. | |
| 437 | - Replacing a node with the same type can cause infinite recursion, as the | |
| 438 | visitor will continue to visit the replaced node of the same type. You must | |
| 439 | handle this case manually. | |
| 440 | ||
| 441 | These rules apply to all visitors, both GLSL AST visitors and preprocessor AST | |
| 442 | visitors. | |
| 443 | ||
| 444 | ### Utility Functions | |
| 445 | ||
| 446 | #### Rename variables / identifiers in a program | |
| 447 | ||
| 448 | You can rename bindings (aka variables), functions, and types (aka structs) with `renameBindings`, `renameFunctions`, and `renameTypes` respectively. | |
| 449 | ||
| 450 | The signature for these methods: | |
| 451 | ||
| 452 | ```ts | |
| 453 | const renameBindings = ( | |
| 454 | // The scope to rename the bindings in. ast.scopes[0] is the global scope. | |
| 455 | // Passing this ast.scopes[0] renames all global variables | |
| 456 | bindings: ScopeIndex, | |
| 457 | ||
| 458 | // The rename function. This is called once per scope entry with the original | |
| 459 | // name in the scope, to generate the renamed variable. | |
| 460 | mangle: (name: string) => string | |
| 461 | ): ScopeIndex | |
| 462 | ``` | |
| 463 | ||
| 464 | These scope renaming functions, `renameBindings`, `renameFunctions`, and `renameTypes`, do two things: | |
| 465 | 1. Each function *mutates* the AST to rename identifiers in place. | |
| 466 | 2. They *return* an *immutable* new ScopeIndex where the scope references | |
| 467 | themselves are renamed. | |
| 468 | ||
| 469 | If you want your ast.scopes array to stay in sync with your AST, you need to | |
| 470 | re-assign it to the output of the functions! Examples: | |
| 471 | ||
| 472 | ```typescript | |
| 473 | import { renameBindings, renameFunctions, renameTypes } from '@shaderfrog/glsl-parser/parser/utils'; | |
| 474 | ||
| 475 | // Suffix top level variables with _x, and update the scope | |
| 476 | ast.scopes[0].bindings = renameBindings(ast.scopes[0].bindings, (name) => `${name}_x`); | |
| 477 | ||
| 478 | // Suffix function names with _x | |
| 479 | ast.scopes[0].functions = renameFunctions(ast.scopes[0].functions, (name) => `${name}_x`); | |
| 480 | ||
| 481 | // Suffix struct names and usages (including constructors) with _x | |
| 482 | ast.scopes[0].types = renameTypes(ast.scopes[0].types, (name) => `${name}_x`); | |
| 483 | ``` | |
| 484 | ||
| 485 | There are also functions to rename only one variable/identifier in a given | |
| 486 | scope. Use these if you know specifically which variable you want to rename. | |
| 487 | ||
| 488 | ```typescript | |
| 489 | import { renameBinding, renameFunction, renameType } from '@shaderfrog/glsl-parser/parser/utils'; | |
| 490 | ||
| 491 | // Replace all instances of "oldVar" with "newVar" in the global scope, and | |
| 492 | // creates a new global scope entry named "newVar" | |
| 493 | ast.scopes[0].bindings.newVar = renameBinding( | |
| 494 | ast.scopes[0].bindings.oldVar, | |
| 495 | 'newVar', | |
| 496 | ); | |
| 497 | // You need to manually delete the old scope entry if you want the scope to stay | |
| 498 | // in sync with your program AST | |
| 499 | delete ast.scopes[0].bindings.oldVar; | |
| 500 | ||
| 501 | // Rename a specific function | |
| 502 | ast.scopes[0].functions.newFn = renameFunction( | |
| 503 | ast.scopes[0].functions.oldFn, | |
| 504 | 'newFn', | |
| 505 | ); | |
| 506 | delete ast.scopes[0].functions.oldFn; | |
| 507 | ||
| 508 | // Rename a specific type/struct | |
| 509 | ast.scopes[0].functions.newType = renametype( | |
| 510 | ast.scopes[0].functions.oldType, | |
| 511 | 'newType', | |
| 512 | ); | |
| 513 | delete ast.scopes[0].functions.oldType; | |
| 514 | ``` | |
| 515 | ||
| 516 | #### Debugging utility functions | |
| 517 | ||
| 518 | The parser also exports a debugging function, useful for logging information | |
| 519 | about the AST. | |
| 520 | ||
| 521 | ```ts | |
| 522 | import { debugScopes } from '@shaderfrog/glsl-parser/parser/utils'; | |
| 523 | ||
| 524 | // Print a condensed representation of the AST scopes to the console | |
| 525 | debugScopes(ast); | |
| 526 | ``` | |
| 527 | ||
| 528 | ## What are "parsing" and "preprocessing"? | |
| 529 | ||
| 530 | In general, a parser is a computer program that analyzes source code and turn it | |
| 531 | into a data structure called an "abstract syntax tree" (AST). The AST is a tree | |
| 532 | representation of the source program, which can be analyzed or manipulated. A | |
| 533 | use of this GLSL parser could be to parse a program into an AST, find all | |
| 534 | variable names in the AST, rename them, and generate new GLSL source code with | |
| 535 | renamed variables. | |
| 536 | ||
| 537 | Preprocessing is a text manipulation step supported in shader source code. One | |
| 538 | way to think about preprocessing is it's a glorified find and replace language | |
| 539 | that's also part of your program's source code. Special lines starting with `#` | |
| 540 | tell the preprocessor how to manipulate other text in the program source code. | |
| 541 | Some programs are not parsable until they are preprocessed, because the source | |
| 542 | code may be invalid until the text find and replacements are done. During | |
| 543 | preprocessing, the source code is treated purely as text. Said another way, | |
| 544 | there is no consideration for the GLSL source code structure, like `float`, | |
| 545 | `vec2`, etc. Preprocessing only handles special lines and rules starting with | |
| 546 | `#`. | |
| 547 | ||
| 548 | See the [GLSL Langauge Spec](https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf) to learn more about GLSL preprocessing. Some notable | |
| 549 | differences from the C++ parser are no "stringize" operator (`#`), no `#include` | |
| 550 | operator, and `#if` expressions can only operate on integer constants, not other | |
| 551 | types of data. The Shaderfrog GLSL preprocessor can't be used as a C/C++ | |
| 552 | preprocessor without modification. | |
| 553 | ||
| 554 | Parsing, preprocessing, and code generation, are all phases of a compiler. This | |
| 555 | library is technically a source code > source code compiler, also known as a | |
| 556 | "transpiler." The input and output source code are both GLSL. | |
| 557 | ||
| 558 | # State of this library | |
| 559 | ||
| 560 | The Shaderfrog compiler [has tests](parser/parse.test.ts) for the more complex | |
| 561 | parts of the GLSL ES 3.00 grammar. This library is definitively the most | |
| 562 | complete GLSL compiler written in **Javascript.** | |
| 563 | ||
| 564 | This library is used by the experimental [Shaderfrog 2.0 shader | |
| 565 | composer](https://twitter.com/andrewray/status/1558307538063437826). The | |
| 566 | compiler has wide expoure to different GLSL programs. | |
| 567 | ||
| 568 | This library also exposed: | |
| 569 | - [A typo](https://github.com/KhronosGroup/GLSL/issues/161) in the official GLSL grammar specification. | |
| 570 | - [A bug](https://bugs.chromium.org/p/angleproject/issues/detail?id=6338#c1) in Chrome's ANGLE compiler. | |
| 571 | ||
| 572 | This library doesn't support full "semantic analysis" required by the Khronos | |
| 573 | GLSL specification. For example, some tokens are only valid in GLSL 1.00 vs | |
| 574 | 3.00, like `texture()` vs `texture2D()`. This parser considers both valid as | |
| 575 | they're both part of the grammar. However if you send compiled source code off | |
| 576 | to a native compiler like ANGLE with the wrong `texture` function, it will fail | |
| 577 | to compile. | |
| 578 | ||
| 579 | This library is mainly for manipulating ASTs before handing off a generated | |
| 580 | program to a downstream compilers like as ANGLE. | |
| 581 | ||
| 582 | The preprocessor supports full macro evaluations and expansions, with the | |
| 583 | exceptions of `__LINE__`. Additional control lines like `#error` and `#pragma` | |
| 584 | and `#extension` have no effect, and can be fully preserved as part of parsing. | |
| 585 | ||
| 586 | # Limitations of the Parser and Preprocessor | |
| 587 | ||
| 588 | ## Known Issues | |
| 589 | ||
| 590 | - There's probably some bugs in the preprocessor logic. I haven't yet verified | |
| 591 | all of the evaluations of "binary" expressions in `preprocessor.ts` | |
| 592 | - `preprocessor.ts` has lots of yucky typecasting | |
| 593 | ||
| 594 | ## Known missing semantic analysis compared to the specification | |
| 595 | ||
| 596 | - Compilers are supposed to raise an error if a switch body ends in a case or | |
| 597 | default label. | |
| 598 | - Currently no semantic analysis of vertex vs fragment shaders | |
| 599 | ||
| 600 | ## Deviations from the Khronos Grammar | |
| 601 | ||
| 602 | - The parser allows for programs to contain top level preprocessor statements, | |
| 603 | like `#define X`, as a convenience to avoid preprocessing some programs, and | |
| 604 | for simple programs lets you preserve preprocessor lines in the AST if you | |
| 605 | want to do something specific with them. However, preprocessor statements at | |
| 606 | any other part of the program are not allowed. The Khronos grammar does not | |
| 607 | include preprocessor statements. | |
| 608 | - `selection_statement` is renamed to `if_statement` | |
| 609 | - The grammar specifies `declaration` itself ends with a semicolon. I moved the | |
| 610 | semicolon into the `declaration_statement` rule. | |
| 611 | - The grammar has a left paren "(" in the function_call production. Due to how | |
| 612 | I de-left-recursed the function_call -> postfix_expression loop, I moved the | |
| 613 | left paren into the function_identifier production. | |
| 614 | - Function calls in the grammar are TYPE_NAME LEFT_PAREN, in my grammar they're | |
| 615 | IDENTIFIER LEFT_PAREN, because TYPE_NAME is only used for structs, and | |
| 616 | function names are stored in their own separate place in the scope. | |
| 617 | ||
| 618 | # Local Development | |
| 619 | ||
| 620 | To work on the tests, run `npx jest --watch`. | |
| 621 | ||
| 622 | The GLSL grammar definition lives in `src/parser/glsl-grammar.pegjs`. Peggy | |
| 623 | supports inlining Javascript code in the `.pegjs` file to define utility | |
| 624 | functions, but that means you have to write in vanilla Javascript, which is | |
| 625 | terrible. Instead, I've pulled out utility functions into the `grammar.ts` | |
| 626 | entrypoint. Some functions need access to Peggy's local variables, like | |
| 627 | `location(s)`, so the `makeLocals()` function uses a closure to provide that | |
| 628 | access. | |
| 629 | ||
| 630 | To submit a change, please open a pull request. Tests are appreciated! | |
| 631 | ||
| 632 | See [the Github workflow](.github/workflows/main.yml) for the checks run against | |
| 633 | each PR. |
| … | … | @@ -0,0 +1,28 @@ |
| 1 | # Vendored: @shaderfrog/glsl-parser | |
| 2 | ||
| 3 | - **Source**: https://www.npmjs.com/package/@shaderfrog/glsl-parser | |
| 4 | - **Homepage**: https://github.com/ShaderFrog/glsl-parser | |
| 5 | - **Version**: 7.0.1 | |
| 6 | - **License**: ISC (per package.json; no LICENSE file ships with npm package — see homepage) | |
| 7 | - **Bundled**: Self-contained (zero dependencies) | |
| 8 | - **Bundle size**: 489 KB | |
| 9 | ||
| 10 | ## Usage | |
| 11 | ||
| 12 | ```js | |
| 13 | import { parse } from '../vendor/glsl-parser/glsl-parser.mjs' | |
| 14 | const ast = parse(source) | |
| 15 | // ast.program is the top-level array of declarations | |
| 16 | ``` | |
| 17 | ||
| 18 | Exports: `parser`, `generate`, `parse`, `GlslSyntaxError` | |
| 19 | ||
| 20 | ## Regeneration | |
| 21 | ||
| 22 | ```sh | |
| 23 | cd /tmp && mkdir -p codetree-vendor && cd codetree-vendor | |
| 24 | npm init -y && echo '{"type":"module"}' > package.json | |
| 25 | npm install @shaderfrog/glsl-parser esbuild | |
| 26 | echo "export { parser, generate, parse, GlslSyntaxError } from '@shaderfrog/glsl-parser'" > bundle.js | |
| 27 | ./node_modules/.bin/esbuild bundle.js --bundle --format=esm --platform=neutral --outfile=glsl-parser.mjs | |
| 28 | ``` |
| … | … | @@ -0,0 +1,14488 @@ |
| 1 | var __defProp = Object.defineProperty; | |
| 2 | var __export = (target, all) => { | |
| 3 | for (var name in all) | |
| 4 | __defProp(target, name, { get: all[name], enumerable: true }); | |
| 5 | }; | |
| 6 | ||
| 7 | // node_modules/@shaderfrog/glsl-parser/ast/ast.js | |
| 8 | var makeGenerator = function(generators2) { | |
| 9 | var gen = function(ast) { | |
| 10 | return typeof ast === "string" ? ast : ast === null || ast === void 0 ? "" : Array.isArray(ast) ? ast.map(gen).join("") : ast.type in generators2 ? generators2[ast.type](ast) : "NO GENERATOR FOR ".concat(ast.type) + ast; | |
| 11 | }; | |
| 12 | return gen; | |
| 13 | }; | |
| 14 | var makeEveryOtherGenerator = function(generate2) { | |
| 15 | var everyOther = function(nodes, eo) { | |
| 16 | return nodes.reduce(function(output, node, index) { | |
| 17 | return output + generate2(node) + (index === nodes.length - 1 ? "" : generate2(eo[index])); | |
| 18 | }, ""); | |
| 19 | }; | |
| 20 | return everyOther; | |
| 21 | }; | |
| 22 | ||
| 23 | // node_modules/@shaderfrog/glsl-parser/parser/generator.js | |
| 24 | var generators = { | |
| 25 | program: function(node) { | |
| 26 | return generate(node.wsStart) + generate(node.program); | |
| 27 | }, | |
| 28 | preprocessor: function(node) { | |
| 29 | return generate(node.line) + generate(node._); | |
| 30 | }, | |
| 31 | keyword: function(node) { | |
| 32 | return generate(node.token) + generate(node.whitespace); | |
| 33 | }, | |
| 34 | precision: function(node) { | |
| 35 | return generate(node.prefix) + generate(node.qualifier) + generate(node.specifier); | |
| 36 | }, | |
| 37 | // Statements | |
| 38 | expression_statement: function(node) { | |
| 39 | return generate(node.expression) + generate(node.semi); | |
| 40 | }, | |
| 41 | if_statement: function(node) { | |
| 42 | return generate(node.if) + generate(node.lp) + generate(node.condition) + generate(node.rp) + generate(node.body) + generate(node.else); | |
| 43 | }, | |
| 44 | switch_statement: function(node) { | |
| 45 | return generate(node.switch) + generate(node.lp) + generate(node.expression) + generate(node.rp) + generate(node.lb) + generate(node.cases) + generate(node.rb); | |
| 46 | }, | |
| 47 | break_statement: function(node) { | |
| 48 | return generate(node.break) + generate(node.semi); | |
| 49 | }, | |
| 50 | do_statement: function(node) { | |
| 51 | return generate(node.do) + generate(node.body) + generate(node.while) + generate(node.lp) + generate(node.expression) + generate(node.rp) + generate(node.semi); | |
| 52 | }, | |
| 53 | continue_statement: function(node) { | |
| 54 | return generate(node.continue) + generate(node.semi); | |
| 55 | }, | |
| 56 | return_statement: function(node) { | |
| 57 | return generate(node.return) + generate(node.expression) + generate(node.semi); | |
| 58 | }, | |
| 59 | discard_statement: function(node) { | |
| 60 | return generate(node.discard) + generate(node.semi); | |
| 61 | }, | |
| 62 | while_statement: function(node) { | |
| 63 | return generate(node.while) + generate(node.lp) + generate(node.condition) + generate(node.rp) + generate(node.body); | |
| 64 | }, | |
| 65 | for_statement: function(node) { | |
| 66 | return generate(node.for) + generate(node.lp) + generate(node.init) + generate(node.initSemi) + generate(node.condition) + generate(node.conditionSemi) + generate(node.operation) + generate(node.rp) + generate(node.body); | |
| 67 | }, | |
| 68 | condition_expression: function(node) { | |
| 69 | return generate(node.specified_type) + generate(node.identifier) + generate(node.operator) + generate(node.initializer); | |
| 70 | }, | |
| 71 | declaration_statement: function(node) { | |
| 72 | return generate(node.declaration) + generate(node.semi); | |
| 73 | }, | |
| 74 | fully_specified_type: function(node) { | |
| 75 | return generate(node.qualifiers) + generate(node.specifier); | |
| 76 | }, | |
| 77 | layout_qualifier: function(node) { | |
| 78 | return generate(node.layout) + generate(node.lp) + generateWithEveryOther(node.qualifiers, node.commas) + generate(node.rp); | |
| 79 | }, | |
| 80 | layout_qualifier_id: function(node) { | |
| 81 | return generate(node.identifier) + generate(node.operator) + generate(node.expression); | |
| 82 | }, | |
| 83 | switch_case: function(node) { | |
| 84 | return generate(node.case) + generate(node.test) + generate(node.colon) + generate(node.statements); | |
| 85 | }, | |
| 86 | default_case: function(node) { | |
| 87 | return generate(node.default) + generate(node.colon) + generate(node.statements); | |
| 88 | }, | |
| 89 | declaration: function(node) { | |
| 90 | return generate(node.identifier) + generate(node.quantifier) + generate(node.equal) + generate(node.initializer); | |
| 91 | }, | |
| 92 | declarator_list: function(node) { | |
| 93 | return generate(node.specified_type) + generateWithEveryOther(node.declarations, node.commas); | |
| 94 | }, | |
| 95 | type_specifier: function(node) { | |
| 96 | return generate(node.specifier) + generate(node.quantifier); | |
| 97 | }, | |
| 98 | array_specifier: function(node) { | |
| 99 | return generate(node.lb) + generate(node.expression) + generate(node.rb); | |
| 100 | }, | |
| 101 | identifier: function(node) { | |
| 102 | return node.identifier + generate(node.whitespace); | |
| 103 | }, | |
| 104 | type_name: function(node) { | |
| 105 | return node.identifier + generate(node.whitespace); | |
| 106 | }, | |
| 107 | function_header: function(node) { | |
| 108 | return generate(node.returnType) + generate(node.name) + generate(node.lp); | |
| 109 | }, | |
| 110 | function_prototype: function(node) { | |
| 111 | return generate(node.header.returnType) + generate(node.header.name) + generate(node.header.lp) + (node.parameters ? generateWithEveryOther(node.parameters, node.commas) : "") + generate(node.rp); | |
| 112 | }, | |
| 113 | parameter_declaration: function(node) { | |
| 114 | return generate(node.qualifier) + generate(node.specifier) + generate(node.identifier) + generate(node.quantifier); | |
| 115 | }, | |
| 116 | compound_statement: function(node) { | |
| 117 | return generate(node.lb) + generate(node.statements) + generate(node.rb); | |
| 118 | }, | |
| 119 | function: function(node) { | |
| 120 | return generate(node["prototype"]) + generate(node.body); | |
| 121 | }, | |
| 122 | function_call: function(node) { | |
| 123 | return generate(node.identifier) + generate(node.lp) + generate(node.args) + generate(node.rp); | |
| 124 | }, | |
| 125 | postfix: function(node) { | |
| 126 | return generate(node.expression) + generate(node.postfix); | |
| 127 | }, | |
| 128 | quantifier: function(node) { | |
| 129 | return generate(node.lb) + generate(node.expression) + generate(node.rb); | |
| 130 | }, | |
| 131 | quantified_identifier: function(node) { | |
| 132 | return generate(node.identifier) + generate(node.quantifier); | |
| 133 | }, | |
| 134 | field_selection: function(node) { | |
| 135 | return generate(node.dot) + generate(node.selection); | |
| 136 | }, | |
| 137 | subroutine_qualifier: function(node) { | |
| 138 | return generate(node.subroutine) + generate(node.lp) + generate(node.type_names) + generate(node.commas) + generate(node.rp); | |
| 139 | }, | |
| 140 | assignment: function(node) { | |
| 141 | return generate(node.left) + generate(node.operator) + generate(node.right); | |
| 142 | }, | |
| 143 | ternary: function(node) { | |
| 144 | return generate(node.expression) + generate(node.question) + generate(node.left) + generate(node.colon) + generate(node.right); | |
| 145 | }, | |
| 146 | binary: function(node) { | |
| 147 | return generate(node.left) + generate(node.operator) + generate(node.right); | |
| 148 | }, | |
| 149 | group: function(node) { | |
| 150 | return generate(node.lp) + generate(node.expression) + generate(node.rp); | |
| 151 | }, | |
| 152 | unary: function(node) { | |
| 153 | return generate(node.operator) + generate(node.expression); | |
| 154 | }, | |
| 155 | float_constant: function(node) { | |
| 156 | return generate(node.token) + generate(node.whitespace); | |
| 157 | }, | |
| 158 | double_constant: function(node) { | |
| 159 | return generate(node.token) + generate(node.whitespace); | |
| 160 | }, | |
| 161 | int_constant: function(node) { | |
| 162 | return generate(node.token) + generate(node.whitespace); | |
| 163 | }, | |
| 164 | uint_constant: function(node) { | |
| 165 | return generate(node.token) + generate(node.whitespace); | |
| 166 | }, | |
| 167 | bool_constant: function(node) { | |
| 168 | return generate(node.token) + generate(node.whitespace); | |
| 169 | }, | |
| 170 | literal: function(node) { | |
| 171 | return generate(node.literal) + generate(node.whitespace); | |
| 172 | }, | |
| 173 | struct: function(node) { | |
| 174 | return generate(node.struct) + generate(node.typeName) + generate(node.lb) + generate(node.declarations) + generate(node.rb); | |
| 175 | }, | |
| 176 | struct_declaration: function(node) { | |
| 177 | return generate(node.declaration) + generate(node.semi); | |
| 178 | }, | |
| 179 | interface_declarator: function(node) { | |
| 180 | return generate(node.qualifiers) + generate(node.interface_type) + generate(node.lp) + generate(node.declarations) + generate(node.rp) + generate(node.identifier); | |
| 181 | }, | |
| 182 | struct_declarator: function(node) { | |
| 183 | return generate(node.specified_type) + generateWithEveryOther(node.declarations, node.commas); | |
| 184 | }, | |
| 185 | initializer_list: function(node) { | |
| 186 | return generate(node.lb) + generateWithEveryOther(node.initializers, node.commas) + generate(node.rb); | |
| 187 | }, | |
| 188 | qualifier_declarator: function(node) { | |
| 189 | return generate(node.qualifiers) + generateWithEveryOther(node.declarations, node.commas); | |
| 190 | } | |
| 191 | }; | |
| 192 | var generate = makeGenerator(generators); | |
| 193 | var generateWithEveryOther = makeEveryOtherGenerator(generate); | |
| 194 | var generator_default = generate; | |
| 195 | ||
| 196 | // node_modules/@shaderfrog/glsl-parser/parser/parser.js | |
| 197 | var parser_exports = {}; | |
| 198 | __export(parser_exports, { | |
| 199 | SyntaxError: () => peg$SyntaxError, | |
| 200 | parse: () => peg$parse | |
| 201 | }); | |
| 202 | ||
| 203 | // node_modules/@shaderfrog/glsl-parser/parser/utils.js | |
| 204 | var xor = function(a, b) { | |
| 205 | return (a || b) && !(a && b); | |
| 206 | }; | |
| 207 | ||
| 208 | // node_modules/@shaderfrog/glsl-parser/parser/scope.js | |
| 209 | var __spreadArray = function(to, from, pack) { | |
| 210 | if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | |
| 211 | if (ar || !(i in from)) { | |
| 212 | if (!ar) ar = Array.prototype.slice.call(from, 0, i); | |
| 213 | ar[i] = from[i]; | |
| 214 | } | |
| 215 | } | |
| 216 | return to.concat(ar || Array.prototype.slice.call(from)); | |
| 217 | }; | |
| 218 | var UNKNOWN_TYPE = "UNKNOWN TYPE"; | |
| 219 | var makeScopeIndex = function(firstReference, declaration) { | |
| 220 | return { | |
| 221 | declaration, | |
| 222 | references: [firstReference] | |
| 223 | }; | |
| 224 | }; | |
| 225 | var findTypeScope = function(scope, typeName) { | |
| 226 | if (!scope) { | |
| 227 | return null; | |
| 228 | } | |
| 229 | if (typeName in scope.types) { | |
| 230 | return scope; | |
| 231 | } | |
| 232 | return findTypeScope(scope.parent, typeName); | |
| 233 | }; | |
| 234 | var isDeclaredType = function(scope, typeName) { | |
| 235 | return findTypeScope(scope, typeName) !== null; | |
| 236 | }; | |
| 237 | var findBindingScope = function(scope, name) { | |
| 238 | if (!scope) { | |
| 239 | return null; | |
| 240 | } | |
| 241 | if (name in scope.bindings) { | |
| 242 | return scope; | |
| 243 | } | |
| 244 | return findBindingScope(scope.parent, name); | |
| 245 | }; | |
| 246 | var extractConstant = function(expression) { | |
| 247 | var result = UNKNOWN_TYPE; | |
| 248 | if ("token" in expression) { | |
| 249 | result = expression.token; | |
| 250 | } else if ("identifier" in expression && typeof expression.identifier === "string") { | |
| 251 | result = expression.identifier; | |
| 252 | } else { | |
| 253 | console.warn(result, expression); | |
| 254 | } | |
| 255 | return result; | |
| 256 | }; | |
| 257 | var quantifiersSignature = function(quantifier) { | |
| 258 | return quantifier.map(function(q) { | |
| 259 | return "[".concat(extractConstant(q.expression), "]"); | |
| 260 | }).join(""); | |
| 261 | }; | |
| 262 | var functionDeclarationSignature = function(node) { | |
| 263 | var _a; | |
| 264 | var proto = node.type === "function" ? node.prototype : node; | |
| 265 | var specifier = proto.header.returnType.specifier; | |
| 266 | var quantifiers = specifier.quantifier || []; | |
| 267 | var parameterTypes = ((_a = proto === null || proto === void 0 ? void 0 : proto.parameters) === null || _a === void 0 ? void 0 : _a.map(function(_a2) { | |
| 268 | var specifier2 = _a2.specifier, quantifier = _a2.quantifier; | |
| 269 | var quantifiers2 = ( | |
| 270 | // vec4[1][2] param | |
| 271 | specifier2.quantifier || // vec4 param[1][3] | |
| 272 | quantifier || [] | |
| 273 | ); | |
| 274 | return "".concat(extractConstant(specifier2.specifier)).concat(quantifiersSignature(quantifiers2)); | |
| 275 | })) || ["void"]; | |
| 276 | var returnType = "".concat(specifier.specifier.token).concat(quantifiersSignature(quantifiers)); | |
| 277 | return [ | |
| 278 | returnType, | |
| 279 | parameterTypes, | |
| 280 | "".concat(returnType, ": ").concat(parameterTypes.join(", ")) | |
| 281 | ]; | |
| 282 | }; | |
| 283 | var doSignaturesMatch = function(definitionSignature, definition, callSignature) { | |
| 284 | if (definitionSignature === callSignature[0]) { | |
| 285 | return true; | |
| 286 | } | |
| 287 | var left = __spreadArray([definition.returnType], definition.parameterTypes, true); | |
| 288 | var right = __spreadArray([callSignature[0]], callSignature[1], true); | |
| 289 | if (left.length === 2 && xor(left[1] === "void", right[1] === "void")) { | |
| 290 | return false; | |
| 291 | } | |
| 292 | return left.length === right.length && left.every(function(type, index) { | |
| 293 | return type === right[index] || type === UNKNOWN_TYPE || right[index] === UNKNOWN_TYPE; | |
| 294 | }); | |
| 295 | }; | |
| 296 | var findOverloadDefinition = function(signature, index) { | |
| 297 | return Object.entries(index).reduce(function(found, _a) { | |
| 298 | var overloadSignature = _a[0], overloadDefinition = _a[1]; | |
| 299 | return found || (doSignaturesMatch(overloadSignature, overloadDefinition, signature) ? overloadDefinition : void 0); | |
| 300 | }, void 0); | |
| 301 | }; | |
| 302 | var functionUseSignature = function(node) { | |
| 303 | var parameterTypes = node.args.length === 0 ? ["void"] : node.args.filter(function(arg) { | |
| 304 | return arg.literal !== ","; | |
| 305 | }).map(function() { | |
| 306 | return UNKNOWN_TYPE; | |
| 307 | }); | |
| 308 | var returnType = UNKNOWN_TYPE; | |
| 309 | return [ | |
| 310 | returnType, | |
| 311 | parameterTypes, | |
| 312 | "".concat(returnType, ": ").concat(parameterTypes.join(", ")) | |
| 313 | ]; | |
| 314 | }; | |
| 315 | var newOverloadIndex = function(returnType, parameterTypes, firstReference, declaration) { | |
| 316 | return { | |
| 317 | returnType, | |
| 318 | parameterTypes, | |
| 319 | declaration, | |
| 320 | references: [firstReference] | |
| 321 | }; | |
| 322 | }; | |
| 323 | var findGlobalScope = function(scope) { | |
| 324 | return scope.parent ? findGlobalScope(scope.parent) : scope; | |
| 325 | }; | |
| 326 | var isDeclaredFunction = function(scope, fnName) { | |
| 327 | return fnName in findGlobalScope(scope).functions; | |
| 328 | }; | |
| 329 | ||
| 330 | // node_modules/@shaderfrog/glsl-parser/parser/grammar.js | |
| 331 | var __assign = function() { | |
| 332 | __assign = Object.assign || function(t) { | |
| 333 | for (var s, i = 1, n = arguments.length; i < n; i++) { | |
| 334 | s = arguments[i]; | |
| 335 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | |
| 336 | t[p] = s[p]; | |
| 337 | } | |
| 338 | return t; | |
| 339 | }; | |
| 340 | return __assign.apply(this, arguments); | |
| 341 | }; | |
| 342 | var __spreadArray2 = function(to, from, pack) { | |
| 343 | if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | |
| 344 | if (ar || !(i in from)) { | |
| 345 | if (!ar) ar = Array.prototype.slice.call(from, 0, i); | |
| 346 | ar[i] = from[i]; | |
| 347 | } | |
| 348 | } | |
| 349 | return to.concat(ar || Array.prototype.slice.call(from)); | |
| 350 | }; | |
| 351 | var partial = function(typeNameOrAttrs, attrs) { | |
| 352 | return { | |
| 353 | partial: attrs === void 0 ? typeNameOrAttrs : __assign({ type: typeNameOrAttrs }, attrs) | |
| 354 | }; | |
| 355 | }; | |
| 356 | var xnil = function() { | |
| 357 | var args = []; | |
| 358 | for (var _i = 0; _i < arguments.length; _i++) { | |
| 359 | args[_i] = arguments[_i]; | |
| 360 | } | |
| 361 | return args.flat().filter(function(e) { | |
| 362 | return e !== void 0 && e !== null && e !== "" && e.length !== 0; | |
| 363 | }); | |
| 364 | }; | |
| 365 | var ifOnly = function(arr) { | |
| 366 | return arr.length > 1 ? arr : arr[0]; | |
| 367 | }; | |
| 368 | var collapse = function() { | |
| 369 | var args = []; | |
| 370 | for (var _i = 0; _i < arguments.length; _i++) { | |
| 371 | args[_i] = arguments[_i]; | |
| 372 | } | |
| 373 | return ifOnly(xnil(args)); | |
| 374 | }; | |
| 375 | var leftAssociate = function(head) { | |
| 376 | var tail = []; | |
| 377 | for (var _i = 1; _i < arguments.length; _i++) { | |
| 378 | tail[_i - 1] = arguments[_i]; | |
| 379 | } | |
| 380 | return tail.flat().reduce(function(left, _a) { | |
| 381 | var operator = _a[0], right = _a[1]; | |
| 382 | return { | |
| 383 | type: "binary", | |
| 384 | operator, | |
| 385 | left, | |
| 386 | right | |
| 387 | }; | |
| 388 | }, head); | |
| 389 | }; | |
| 390 | var BUILT_INS = { | |
| 391 | vertex: /* @__PURE__ */ new Set([ | |
| 392 | "gl_VertexID", | |
| 393 | "gl_InstanceID", | |
| 394 | "gl_DrawID", | |
| 395 | "gl_BaseVertex", | |
| 396 | "gl_BaseInstance", | |
| 397 | "gl_Position", | |
| 398 | "gl_PointSize", | |
| 399 | "gl_ClipDistance" | |
| 400 | ]), | |
| 401 | fragment: /* @__PURE__ */ new Set([ | |
| 402 | "gl_FragColor", | |
| 403 | "gl_FragData", | |
| 404 | "gl_FragCoord", | |
| 405 | "gl_FrontFacing", | |
| 406 | "gl_PointCoord", | |
| 407 | "gl_SampleID", | |
| 408 | "gl_SamplePosition", | |
| 409 | "gl_SampleMaskIn", | |
| 410 | "gl_ClipDistance", | |
| 411 | "gl_PrimitiveID", | |
| 412 | "gl_Layer", | |
| 413 | "gl_ViewportIndex", | |
| 414 | "gl_FragDepth", | |
| 415 | "gl_SampleMask" | |
| 416 | ]) | |
| 417 | }; | |
| 418 | var FN_BUILT_INS = /* @__PURE__ */ new Set([ | |
| 419 | "abs", | |
| 420 | "acos", | |
| 421 | "acosh", | |
| 422 | "all", | |
| 423 | "any", | |
| 424 | "asin", | |
| 425 | "asinh", | |
| 426 | "atan", | |
| 427 | "atanh", | |
| 428 | "atomicAdd", | |
| 429 | "atomicAnd", | |
| 430 | "atomicCompSwap", | |
| 431 | "atomicCounter", | |
| 432 | "atomicCounterDecrement", | |
| 433 | "atomicCounterIncrement", | |
| 434 | "atomicExchange", | |
| 435 | "atomicMax", | |
| 436 | "atomicMin", | |
| 437 | "atomicOr", | |
| 438 | "atomicXor", | |
| 439 | "barrier", | |
| 440 | "bitCount", | |
| 441 | "bitfieldExtract", | |
| 442 | "bitfieldInsert", | |
| 443 | "bitfieldReverse", | |
| 444 | "ceil", | |
| 445 | "clamp", | |
| 446 | "cos", | |
| 447 | "cosh", | |
| 448 | "cross", | |
| 449 | "degrees", | |
| 450 | "determinant", | |
| 451 | "dFdx", | |
| 452 | "dFdxCoarse", | |
| 453 | "dFdxFine", | |
| 454 | "dFdy", | |
| 455 | "dFdyCoarse", | |
| 456 | "dFdyFine", | |
| 457 | "distance", | |
| 458 | "dot", | |
| 459 | "EmitStreamVertex", | |
| 460 | "EmitVertex", | |
| 461 | "EndPrimitive", | |
| 462 | "EndStreamPrimitive", | |
| 463 | "equal", | |
| 464 | "exp", | |
| 465 | "exp2", | |
| 466 | "faceforward", | |
| 467 | "findLSB", | |
| 468 | "findMSB", | |
| 469 | "floatBitsToInt", | |
| 470 | "floatBitsToUint", | |
| 471 | "floor", | |
| 472 | "fma", | |
| 473 | "fract", | |
| 474 | "frexp", | |
| 475 | "fwidth", | |
| 476 | "fwidthCoarse", | |
| 477 | "fwidthFine", | |
| 478 | "greaterThan", | |
| 479 | "greaterThanEqual", | |
| 480 | "groupMemoryBarrier", | |
| 481 | "imageAtomicAdd", | |
| 482 | "imageAtomicAnd", | |
| 483 | "imageAtomicCompSwap", | |
| 484 | "imageAtomicExchange", | |
| 485 | "imageAtomicMax", | |
| 486 | "imageAtomicMin", | |
| 487 | "imageAtomicOr", | |
| 488 | "imageAtomicXor", | |
| 489 | "imageLoad", | |
| 490 | "imageSamples", | |
| 491 | "imageSize", | |
| 492 | "imageStore", | |
| 493 | "imulExtended", | |
| 494 | "intBitsToFloat", | |
| 495 | "interpolateAtCentroid", | |
| 496 | "interpolateAtOffset", | |
| 497 | "interpolateAtSample", | |
| 498 | "inverse", | |
| 499 | "inversesqrt", | |
| 500 | "isinf", | |
| 501 | "isnan", | |
| 502 | "ldexp", | |
| 503 | "length", | |
| 504 | "lessThan", | |
| 505 | "lessThanEqual", | |
| 506 | "log", | |
| 507 | "log2", | |
| 508 | "matrixCompMult", | |
| 509 | "max", | |
| 510 | "memoryBarrier", | |
| 511 | "memoryBarrierAtomicCounter", | |
| 512 | "memoryBarrierBuffer", | |
| 513 | "memoryBarrierImage", | |
| 514 | "memoryBarrierShared", | |
| 515 | "min", | |
| 516 | "mix", | |
| 517 | "mod", | |
| 518 | "modf", | |
| 519 | "noise", | |
| 520 | "noise1", | |
| 521 | "noise2", | |
| 522 | "noise3", | |
| 523 | "noise4", | |
| 524 | "normalize", | |
| 525 | "not", | |
| 526 | "notEqual", | |
| 527 | "outerProduct", | |
| 528 | "packDouble2x32", | |
| 529 | "packHalf2x16", | |
| 530 | "packSnorm2x16", | |
| 531 | "packSnorm4x8", | |
| 532 | "packUnorm", | |
| 533 | "packUnorm2x16", | |
| 534 | "packUnorm4x8", | |
| 535 | "pow", | |
| 536 | "radians", | |
| 537 | "reflect", | |
| 538 | "refract", | |
| 539 | "round", | |
| 540 | "roundEven", | |
| 541 | "sign", | |
| 542 | "sin", | |
| 543 | "sinh", | |
| 544 | "smoothstep", | |
| 545 | "sqrt", | |
| 546 | "step", | |
| 547 | "tan", | |
| 548 | "tanh", | |
| 549 | "texelFetch", | |
| 550 | "texelFetchOffset", | |
| 551 | "texture", | |
| 552 | "textureGather", | |
| 553 | "textureGatherOffset", | |
| 554 | "textureGatherOffsets", | |
| 555 | "textureGrad", | |
| 556 | "textureGradOffset", | |
| 557 | "textureLod", | |
| 558 | "textureLodOffset", | |
| 559 | "textureOffset", | |
| 560 | "textureProj", | |
| 561 | "textureProjGrad", | |
| 562 | "textureProjGradOffset", | |
| 563 | "textureProjLod", | |
| 564 | "textureProjLodOffset", | |
| 565 | "textureProjOffset", | |
| 566 | "textureQueryLevels", | |
| 567 | "textureQueryLod", | |
| 568 | "textureSamples", | |
| 569 | "textureSize", | |
| 570 | "transpose", | |
| 571 | "trunc", | |
| 572 | "uaddCarry", | |
| 573 | "uintBitsToFloat", | |
| 574 | "umulExtended", | |
| 575 | "unpackDouble2x32", | |
| 576 | "unpackHalf2x16", | |
| 577 | "unpackSnorm2x16", | |
| 578 | "unpackSnorm4x8", | |
| 579 | "unpackUnorm", | |
| 580 | "unpackUnorm2x16", | |
| 581 | "unpackUnorm4x8", | |
| 582 | "usubBorrow", | |
| 583 | // GLSL ES 1.00 | |
| 584 | "texture2D", | |
| 585 | "textureCube" | |
| 586 | ]); | |
| 587 | var makeLocals = function(context) { | |
| 588 | var getLocation = function(loc) { | |
| 589 | if (!context.options.includeLocation) { | |
| 590 | return; | |
| 591 | } | |
| 592 | var _a = loc || context.location(), start = _a.start, end = _a.end; | |
| 593 | return { start, end }; | |
| 594 | }; | |
| 595 | var node = function(type, attrs) { | |
| 596 | var n = __assign({ type }, attrs); | |
| 597 | if (context.options.includeLocation) { | |
| 598 | n.location = getLocation(); | |
| 599 | } | |
| 600 | return n; | |
| 601 | }; | |
| 602 | var makeScope = function(name, parent, startLocation) { | |
| 603 | var newLocation = getLocation(startLocation); | |
| 604 | return __assign(__assign({ name, parent }, newLocation ? { location: newLocation } : false), { bindings: {}, types: {}, functions: {} }); | |
| 605 | }; | |
| 606 | var warn = function(message) { | |
| 607 | if (context.options.failOnWarn) { | |
| 608 | throw new Error(message); | |
| 609 | } | |
| 610 | if (!context.options.quiet) { | |
| 611 | console.warn(message); | |
| 612 | } | |
| 613 | }; | |
| 614 | var pushScope = function(scope) { | |
| 615 | context.scopes.push(scope); | |
| 616 | return scope; | |
| 617 | }; | |
| 618 | var popScope = function(scope) { | |
| 619 | if (!scope.parent) { | |
| 620 | throw new Error("Popped bad scope ".concat(scope, " at ").concat(context.text())); | |
| 621 | } | |
| 622 | return scope.parent; | |
| 623 | }; | |
| 624 | var setScopeEnd = function(scope, end) { | |
| 625 | if (context.options.includeLocation) { | |
| 626 | if (!scope.location) { | |
| 627 | console.error("No end location at ".concat(context.text())); | |
| 628 | } else { | |
| 629 | scope.location.end = end; | |
| 630 | } | |
| 631 | } | |
| 632 | }; | |
| 633 | var addFunctionCallReference = function(scope, name, fnRef) { | |
| 634 | var _a; | |
| 635 | var global = findGlobalScope(scope); | |
| 636 | var signature = functionUseSignature(fnRef); | |
| 637 | if (!global.functions[name]) { | |
| 638 | warn('Encountered undeclared function: "'.concat(name, '" with signature "').concat(signature[2], '"')); | |
| 639 | global.functions[name] = (_a = {}, _a[signature[2]] = newOverloadIndex(signature[0], signature[1], fnRef), _a); | |
| 640 | } else { | |
| 641 | var existingOverload = findOverloadDefinition(signature, global.functions[name]); | |
| 642 | if (!existingOverload) { | |
| 643 | warn('No matching overload for function: "'.concat(name, '" with signature "').concat(signature[2], '"')); | |
| 644 | global.functions[name][signature[2]] = newOverloadIndex(signature[0], signature[1], fnRef); | |
| 645 | } else { | |
| 646 | existingOverload.references.push(fnRef); | |
| 647 | } | |
| 648 | } | |
| 649 | }; | |
| 650 | var createFunctionDefinition = function(scope, name, fnRef) { | |
| 651 | var global = findGlobalScope(scope); | |
| 652 | var signature = functionDeclarationSignature(fnRef); | |
| 653 | if (!global.functions[name]) { | |
| 654 | global.functions[name] = {}; | |
| 655 | } | |
| 656 | var existing = global.functions[name][signature[2]]; | |
| 657 | if (existing) { | |
| 658 | if (existing.declaration) { | |
| 659 | warn('Encountered duplicate function definition: "'.concat(name, '" with signature "').concat(signature[2], '"')); | |
| 660 | } else { | |
| 661 | existing.declaration = fnRef; | |
| 662 | } | |
| 663 | existing.references.push(fnRef); | |
| 664 | } else { | |
| 665 | global.functions[name][signature[2]] = newOverloadIndex(signature[0], signature[1], fnRef); | |
| 666 | global.functions[name][signature[2]].declaration = fnRef; | |
| 667 | } | |
| 668 | }; | |
| 669 | var createFunctionPrototype = function(scope, name, fnRef) { | |
| 670 | var global = findGlobalScope(scope); | |
| 671 | var signature = functionDeclarationSignature(fnRef); | |
| 672 | if (!global.functions[name]) { | |
| 673 | global.functions[name] = {}; | |
| 674 | } | |
| 675 | var existing = global.functions[name][signature[2]]; | |
| 676 | if (existing) { | |
| 677 | warn('Encountered duplicate function prototype: "'.concat(name, '" with signature "').concat(signature[2], '"')); | |
| 678 | existing.references.push(fnRef); | |
| 679 | } else { | |
| 680 | global.functions[name][signature[2]] = newOverloadIndex(signature[0], signature[1], fnRef); | |
| 681 | } | |
| 682 | }; | |
| 683 | var addTypeReference = function(scope, name, reference) { | |
| 684 | var declaredScope = findTypeScope(scope, name); | |
| 685 | if (declaredScope) { | |
| 686 | declaredScope.types[name].references.push(reference); | |
| 687 | } else { | |
| 688 | warn('Encountered undeclared type: "'.concat(name, '"')); | |
| 689 | scope.types[name] = { | |
| 690 | references: [reference] | |
| 691 | }; | |
| 692 | } | |
| 693 | }; | |
| 694 | var createType = function(scope, name, declaration) { | |
| 695 | if (name in scope.types) { | |
| 696 | if (scope.types[name].declaration) { | |
| 697 | warn('Encountered duplicate type declaration: "'.concat(name, '"')); | |
| 698 | } else { | |
| 699 | warn('Type "'.concat(name, '" was used before it was declared')); | |
| 700 | scope.types[name].declaration = declaration; | |
| 701 | } | |
| 702 | scope.types[name].references.push(declaration); | |
| 703 | } else { | |
| 704 | scope.types[name] = { | |
| 705 | declaration, | |
| 706 | references: [declaration] | |
| 707 | }; | |
| 708 | } | |
| 709 | }; | |
| 710 | var addTypeIfFound = function(scope, node2) { | |
| 711 | var _a; | |
| 712 | var specifier = node2.type === "fully_specified_type" ? (_a = node2 === null || node2 === void 0 ? void 0 : node2.specifier) === null || _a === void 0 ? void 0 : _a.specifier : node2 === null || node2 === void 0 ? void 0 : node2.specifier; | |
| 713 | if (specifier.type === "type_name") { | |
| 714 | var name = specifier.identifier; | |
| 715 | addTypeReference(scope, name, specifier); | |
| 716 | } else if (specifier.type !== "struct" && specifier.type !== "keyword") { | |
| 717 | console.warn("Unknown specifier", specifier); | |
| 718 | throw new Error("Unknown declarator specifier ".concat(specifier === null || specifier === void 0 ? void 0 : specifier.type, ". Please file a bug against @shaderfrog/glsl-parser and incldue your source grammar.")); | |
| 719 | } | |
| 720 | }; | |
| 721 | var createBindings = function(scope) { | |
| 722 | var bindings = []; | |
| 723 | for (var _i = 1; _i < arguments.length; _i++) { | |
| 724 | bindings[_i - 1] = arguments[_i]; | |
| 725 | } | |
| 726 | bindings.forEach(function(_a) { | |
| 727 | var identifier = _a[0], binding = _a[1]; | |
| 728 | var existing = scope.bindings[identifier]; | |
| 729 | if (existing) { | |
| 730 | warn('Encountered duplicate variable declaration: "'.concat(identifier, '"')); | |
| 731 | existing.references.unshift(binding); | |
| 732 | } else { | |
| 733 | scope.bindings[identifier] = makeScopeIndex(binding, binding); | |
| 734 | } | |
| 735 | }); | |
| 736 | }; | |
| 737 | var addOrCreateBindingReference = function(scope, name, reference) { | |
| 738 | var foundScope = findBindingScope(scope, name); | |
| 739 | if (foundScope) { | |
| 740 | foundScope.bindings[name].references.push(reference); | |
| 741 | } else { | |
| 742 | if (!context.options.stage || context.options.stage === "vertex" && !BUILT_INS.vertex.has(name) || context.options.stage === "fragment" && !BUILT_INS.fragment.has(name) || context.options.stage === "either" && !BUILT_INS.vertex.has(name) && !BUILT_INS.fragment) { | |
| 743 | warn('Encountered undefined variable: "'.concat(name, '"')); | |
| 744 | } | |
| 745 | scope.bindings[name] = makeScopeIndex(reference); | |
| 746 | } | |
| 747 | }; | |
| 748 | var groupCases = function(statements) { | |
| 749 | return statements.reduce(function(cases, stmt) { | |
| 750 | var partial2 = "partial" in stmt ? stmt.partial : {}; | |
| 751 | if (partial2.type === "case_label") { | |
| 752 | return __spreadArray2(__spreadArray2([], cases, true), [ | |
| 753 | node("switch_case", { | |
| 754 | statements: [], | |
| 755 | case: partial2.case, | |
| 756 | test: partial2.test, | |
| 757 | colon: partial2.colon | |
| 758 | }) | |
| 759 | ], false); | |
| 760 | } else if (partial2.type === "default_label") { | |
| 761 | return __spreadArray2(__spreadArray2([], cases, true), [ | |
| 762 | node("default_case", { | |
| 763 | statements: [], | |
| 764 | default: partial2.default, | |
| 765 | colon: partial2.colon | |
| 766 | }) | |
| 767 | ], false); | |
| 768 | } else if (!cases.length) { | |
| 769 | throw new Error("A switch statement body must start with a case or default label"); | |
| 770 | } else { | |
| 771 | var tail = cases.slice(-1)[0]; | |
| 772 | return __spreadArray2(__spreadArray2([], cases.slice(0, -1), true), [ | |
| 773 | __assign(__assign({}, tail), { statements: __spreadArray2(__spreadArray2([], tail.statements, true), [stmt], false) }) | |
| 774 | ], false); | |
| 775 | } | |
| 776 | }, []); | |
| 777 | }; | |
| 778 | context.scope = makeScope("global"); | |
| 779 | context.scopes = [context.scope]; | |
| 780 | return { | |
| 781 | getLocation, | |
| 782 | node, | |
| 783 | makeScope, | |
| 784 | warn, | |
| 785 | pushScope, | |
| 786 | popScope, | |
| 787 | setScopeEnd, | |
| 788 | createFunctionDefinition, | |
| 789 | addFunctionCallReference, | |
| 790 | createFunctionPrototype, | |
| 791 | groupCases, | |
| 792 | addTypeReference, | |
| 793 | addTypeIfFound, | |
| 794 | createType, | |
| 795 | createBindings, | |
| 796 | addOrCreateBindingReference | |
| 797 | }; | |
| 798 | }; | |
| 799 | ||
| 800 | // node_modules/@shaderfrog/glsl-parser/parser/parser.js | |
| 801 | var OPEN_CURLY = String.fromCharCode(123); | |
| 802 | function peg$subclass(child, parent) { | |
| 803 | function C() { | |
| 804 | this.constructor = child; | |
| 805 | } | |
| 806 | C.prototype = parent.prototype; | |
| 807 | child.prototype = new C(); | |
| 808 | } | |
| 809 | function peg$SyntaxError(message, expected, found, location) { | |
| 810 | var self = Error.call(this, message); | |
| 811 | if (Object.setPrototypeOf) { | |
| 812 | Object.setPrototypeOf(self, peg$SyntaxError.prototype); | |
| 813 | } | |
| 814 | self.expected = expected; | |
| 815 | self.found = found; | |
| 816 | self.location = location; | |
| 817 | self.name = "SyntaxError"; | |
| 818 | return self; | |
| 819 | } | |
| 820 | peg$subclass(peg$SyntaxError, Error); | |
| 821 | function peg$padEnd(str, targetLength, padString) { | |
| 822 | padString = padString || " "; | |
| 823 | if (str.length > targetLength) { | |
| 824 | return str; | |
| 825 | } | |
| 826 | targetLength -= str.length; | |
| 827 | padString += padString.repeat(targetLength); | |
| 828 | return str + padString.slice(0, targetLength); | |
| 829 | } | |
| 830 | peg$SyntaxError.prototype.format = function(sources) { | |
| 831 | var str = "Error: " + this.message; | |
| 832 | if (this.location) { | |
| 833 | var src = null; | |
| 834 | var k; | |
| 835 | for (k = 0; k < sources.length; k++) { | |
| 836 | if (sources[k].source === this.location.source) { | |
| 837 | src = sources[k].text.split(/\r\n|\n|\r/g); | |
| 838 | break; | |
| 839 | } | |
| 840 | } | |
| 841 | var s = this.location.start; | |
| 842 | var loc = this.location.source + ":" + s.line + ":" + s.column; | |
| 843 | if (src) { | |
| 844 | var e = this.location.end; | |
| 845 | var filler = peg$padEnd("", s.line.toString().length); | |
| 846 | var line = src[s.line - 1]; | |
| 847 | var last = s.line === e.line ? e.column : line.length + 1; | |
| 848 | str += "\n --> " + loc + "\n" + filler + " |\n" + s.line + " | " + line + "\n" + filler + " | " + peg$padEnd("", s.column - 1) + peg$padEnd("", last - s.column, "^"); | |
| 849 | } else { | |
| 850 | str += "\n at " + loc; | |
| 851 | } | |
| 852 | } | |
| 853 | return str; | |
| 854 | }; | |
| 855 | peg$SyntaxError.buildMessage = function(expected, found) { | |
| 856 | var DESCRIBE_EXPECTATION_FNS = { | |
| 857 | literal: function(expectation) { | |
| 858 | return '"' + literalEscape(expectation.text) + '"'; | |
| 859 | }, | |
| 860 | class: function(expectation) { | |
| 861 | var escapedParts = expectation.parts.map(function(part) { | |
| 862 | return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part); | |
| 863 | }); | |
| 864 | return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; | |
| 865 | }, | |
| 866 | any: function() { | |
| 867 | return "any character"; | |
| 868 | }, | |
| 869 | end: function() { | |
| 870 | return "end of input"; | |
| 871 | }, | |
| 872 | other: function(expectation) { | |
| 873 | return expectation.description; | |
| 874 | } | |
| 875 | }; | |
| 876 | function hex(ch) { | |
| 877 | return ch.charCodeAt(0).toString(16).toUpperCase(); | |
| 878 | } | |
| 879 | function literalEscape(s) { | |
| 880 | return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) { | |
| 881 | return "\\x0" + hex(ch); | |
| 882 | }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { | |
| 883 | return "\\x" + hex(ch); | |
| 884 | }); | |
| 885 | } | |
| 886 | function classEscape(s) { | |
| 887 | return s.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) { | |
| 888 | return "\\x0" + hex(ch); | |
| 889 | }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { | |
| 890 | return "\\x" + hex(ch); | |
| 891 | }); | |
| 892 | } | |
| 893 | function describeExpectation(expectation) { | |
| 894 | return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); | |
| 895 | } | |
| 896 | function describeExpected(expected2) { | |
| 897 | var descriptions = expected2.map(describeExpectation); | |
| 898 | var i, j; | |
| 899 | descriptions.sort(); | |
| 900 | if (descriptions.length > 0) { | |
| 901 | for (i = 1, j = 1; i < descriptions.length; i++) { | |
| 902 | if (descriptions[i - 1] !== descriptions[i]) { | |
| 903 | descriptions[j] = descriptions[i]; | |
| 904 | j++; | |
| 905 | } | |
| 906 | } | |
| 907 | descriptions.length = j; | |
| 908 | } | |
| 909 | switch (descriptions.length) { | |
| 910 | case 1: | |
| 911 | return descriptions[0]; | |
| 912 | case 2: | |
| 913 | return descriptions[0] + " or " + descriptions[1]; | |
| 914 | default: | |
| 915 | return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1]; | |
| 916 | } | |
| 917 | } | |
| 918 | function describeFound(found2) { | |
| 919 | return found2 ? '"' + literalEscape(found2) + '"' : "end of input"; | |
| 920 | } | |
| 921 | return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; | |
| 922 | }; | |
| 923 | function peg$parse(input, options) { | |
| 924 | options = options !== void 0 ? options : {}; | |
| 925 | var peg$FAILED = {}; | |
| 926 | var peg$source = options.grammarSource; | |
| 927 | var peg$startRuleFunctions = { start: peg$parsestart }; | |
| 928 | var peg$startRuleFunction = peg$parsestart; | |
| 929 | var peg$c0 = "attribute"; | |
| 930 | var peg$c1 = "varying"; | |
| 931 | var peg$c2 = "const"; | |
| 932 | var peg$c3 = "bool"; | |
| 933 | var peg$c4 = "float"; | |
| 934 | var peg$c5 = "double"; | |
| 935 | var peg$c6 = "int"; | |
| 936 | var peg$c7 = "uint"; | |
| 937 | var peg$c8 = "break"; | |
| 938 | var peg$c9 = "continue"; | |
| 939 | var peg$c10 = "do"; | |
| 940 | var peg$c11 = "else"; | |
| 941 | var peg$c12 = "for"; | |
| 942 | var peg$c13 = "if"; | |
| 943 | var peg$c14 = "discard"; | |
| 944 | var peg$c15 = "return"; | |
| 945 | var peg$c16 = "switch"; | |
| 946 | var peg$c17 = "case"; | |
| 947 | var peg$c18 = "default"; | |
| 948 | var peg$c19 = "subroutine"; | |
| 949 | var peg$c20 = "bvec2"; | |
| 950 | var peg$c21 = "bvec3"; | |
| 951 | var peg$c22 = "bvec4"; | |
| 952 | var peg$c23 = "ivec2"; | |
| 953 | var peg$c24 = "ivec3"; | |
| 954 | var peg$c25 = "ivec4"; | |
| 955 | var peg$c26 = "uvec2"; | |
| 956 | var peg$c27 = "uvec3"; | |
| 957 | var peg$c28 = "uvec4"; | |
| 958 | var peg$c29 = "vec2"; | |
| 959 | var peg$c30 = "vec3"; | |
| 960 | var peg$c31 = "vec4"; | |
| 961 | var peg$c32 = "mat2"; | |
| 962 | var peg$c33 = "mat3"; | |
| 963 | var peg$c34 = "mat4"; | |
| 964 | var peg$c35 = "centroid"; | |
| 965 | var peg$c36 = "in"; | |
| 966 | var peg$c37 = "out"; | |
| 967 | var peg$c38 = "inout"; | |
| 968 | var peg$c39 = "uniform"; | |
| 969 | var peg$c40 = "patch"; | |
| 970 | var peg$c41 = "sample"; | |
| 971 | var peg$c42 = "buffer"; | |
| 972 | var peg$c43 = "shared"; | |
| 973 | var peg$c44 = "coherent"; | |
| 974 | var peg$c45 = "volatile"; | |
| 975 | var peg$c46 = "restrict"; | |
| 976 | var peg$c47 = "readonly"; | |
| 977 | var peg$c48 = "writeonly"; | |
| 978 | var peg$c49 = "dvec2"; | |
| 979 | var peg$c50 = "dvec3"; | |
| 980 | var peg$c51 = "dvec4"; | |
| 981 | var peg$c52 = "dmat2"; | |
| 982 | var peg$c53 = "dmat3"; | |
| 983 | var peg$c54 = "dmat4"; | |
| 984 | var peg$c55 = "noperspective"; | |
| 985 | var peg$c56 = "flat"; | |
| 986 | var peg$c57 = "smooth"; | |
| 987 | var peg$c58 = "layout"; | |
| 988 | var peg$c59 = "mat2x2"; | |
| 989 | var peg$c60 = "mat2x3"; | |
| 990 | var peg$c61 = "mat2x4"; | |
| 991 | var peg$c62 = "mat3x2"; | |
| 992 | var peg$c63 = "mat3x3"; | |
| 993 | var peg$c64 = "mat3x4"; | |
| 994 | var peg$c65 = "mat4x2"; | |
| 995 | var peg$c66 = "mat4x3"; | |
| 996 | var peg$c67 = "mat4x4"; | |
| 997 | var peg$c68 = "dmat2x2"; | |
| 998 | var peg$c69 = "dmat2x3"; | |
| 999 | var peg$c70 = "dmat2x4"; | |
| 1000 | var peg$c71 = "dmat3x2"; | |
| 1001 | var peg$c72 = "dmat3x3"; | |
| 1002 | var peg$c73 = "dmat3x4"; | |
| 1003 | var peg$c74 = "dmat4x2"; | |
| 1004 | var peg$c75 = "dmat4x3"; | |
| 1005 | var peg$c76 = "dmat4x4"; | |
| 1006 | var peg$c77 = "atomic_uint"; | |
| 1007 | var peg$c78 = "sampler1D"; | |
| 1008 | var peg$c79 = "sampler2D"; | |
| 1009 | var peg$c80 = "sampler3D"; | |
| 1010 | var peg$c81 = "samplerCube"; | |
| 1011 | var peg$c82 = "sampler1DShadow"; | |
| 1012 | var peg$c83 = "sampler2DShadow"; | |
| 1013 | var peg$c84 = "samplerCubeShadow"; | |
| 1014 | var peg$c85 = "sampler1DArray"; | |
| 1015 | var peg$c86 = "sampler2DArray"; | |
| 1016 | var peg$c87 = "sampler1DArrayShadow"; | |
| 1017 | var peg$c88 = "sampler2DArrayShadow"; | |
| 1018 | var peg$c89 = "isampler1D"; | |
| 1019 | var peg$c90 = "isampler2D"; | |
| 1020 | var peg$c91 = "isampler3D"; | |
| 1021 | var peg$c92 = "isamplerCube"; | |
| 1022 | var peg$c93 = "isampler1Darray"; | |
| 1023 | var peg$c94 = "isampler2DArray"; | |
| 1024 | var peg$c95 = "usampler1D"; | |
| 1025 | var peg$c96 = "usampler2D"; | |
| 1026 | var peg$c97 = "usampler3D"; | |
| 1027 | var peg$c98 = "usamplerCube"; | |
| 1028 | var peg$c99 = "usampler1DArray"; | |
| 1029 | var peg$c100 = "usampler2DArray"; | |
| 1030 | var peg$c101 = "sampler2DRect"; | |
| 1031 | var peg$c102 = "sampler2DRectShadow"; | |
| 1032 | var peg$c103 = "isampler2DRect"; | |
| 1033 | var peg$c104 = "usampler2DRect"; | |
| 1034 | var peg$c105 = "samplerBuffer"; | |
| 1035 | var peg$c106 = "isamplerBuffer"; | |
| 1036 | var peg$c107 = "usamplerBuffer"; | |
| 1037 | var peg$c108 = "samplerCubeArray"; | |
| 1038 | var peg$c109 = "samplerCubeArrayShadow"; | |
| 1039 | var peg$c110 = "isamplerCubeArray"; | |
| 1040 | var peg$c111 = "usamplerCubeArray"; | |
| 1041 | var peg$c112 = "sampler2DMS"; | |
| 1042 | var peg$c113 = "isampler2DMS"; | |
| 1043 | var peg$c114 = "usampler2DMS"; | |
| 1044 | var peg$c115 = "sampler2DMSArray"; | |
| 1045 | var peg$c116 = "isampler2DMSArray"; | |
| 1046 | var peg$c117 = "usampler2DMSArray"; | |
| 1047 | var peg$c118 = "image1D"; | |
| 1048 | var peg$c119 = "iimage1D"; | |
| 1049 | var peg$c120 = "uimage1D"; | |
| 1050 | var peg$c121 = "image2D"; | |
| 1051 | var peg$c122 = "iimage2D"; | |
| 1052 | var peg$c123 = "uimage2D"; | |
| 1053 | var peg$c124 = "image3D"; | |
| 1054 | var peg$c125 = "iimage3D"; | |
| 1055 | var peg$c126 = "uimage3D"; | |
| 1056 | var peg$c127 = "image2DRect"; | |
| 1057 | var peg$c128 = "iimage2DRect"; | |
| 1058 | var peg$c129 = "uimage2DRect"; | |
| 1059 | var peg$c130 = "imageCube"; | |
| 1060 | var peg$c131 = "iimageCube"; | |
| 1061 | var peg$c132 = "uimageCube"; | |
| 1062 | var peg$c133 = "imageBuffer"; | |
| 1063 | var peg$c134 = "iimageBuffer"; | |
| 1064 | var peg$c135 = "uimageBuffer"; | |
| 1065 | var peg$c136 = "image1DArray"; | |
| 1066 | var peg$c137 = "iimage1DArray"; | |
| 1067 | var peg$c138 = "uimage1DArray"; | |
| 1068 | var peg$c139 = "image2DArray"; | |
| 1069 | var peg$c140 = "iimage2DArray"; | |
| 1070 | var peg$c141 = "uimage2DArray"; | |
| 1071 | var peg$c142 = "imageCubeArray"; | |
| 1072 | var peg$c143 = "iimageCubeArray"; | |
| 1073 | var peg$c144 = "uimageCubeArray"; | |
| 1074 | var peg$c145 = "image2DMS"; | |
| 1075 | var peg$c146 = "iimage2DMS"; | |
| 1076 | var peg$c147 = "uimage2DMS"; | |
| 1077 | var peg$c148 = "image2DMArray"; | |
| 1078 | var peg$c149 = "iimage2DMSArray"; | |
| 1079 | var peg$c150 = "uimage2DMSArray"; | |
| 1080 | var peg$c151 = "struct"; | |
| 1081 | var peg$c152 = "void"; | |
| 1082 | var peg$c153 = "while"; | |
| 1083 | var peg$c154 = "invariant"; | |
| 1084 | var peg$c155 = "precise"; | |
| 1085 | var peg$c156 = "highp"; | |
| 1086 | var peg$c157 = "mediump"; | |
| 1087 | var peg$c158 = "lowp"; | |
| 1088 | var peg$c159 = "precision"; | |
| 1089 | var peg$c160 = "true"; | |
| 1090 | var peg$c161 = "false"; | |
| 1091 | var peg$c162 = "<<"; | |
| 1092 | var peg$c163 = ">>"; | |
| 1093 | var peg$c164 = "++"; | |
| 1094 | var peg$c165 = "--"; | |
| 1095 | var peg$c166 = "<="; | |
| 1096 | var peg$c167 = ">="; | |
| 1097 | var peg$c168 = "=="; | |
| 1098 | var peg$c169 = "!="; | |
| 1099 | var peg$c170 = "&&"; | |
| 1100 | var peg$c171 = "||"; | |
| 1101 | var peg$c172 = "^^"; | |
| 1102 | var peg$c173 = "*="; | |
| 1103 | var peg$c174 = "/="; | |
| 1104 | var peg$c175 = "+="; | |
| 1105 | var peg$c176 = "%="; | |
| 1106 | var peg$c177 = "<<="; | |
| 1107 | var peg$c178 = ">>="; | |
| 1108 | var peg$c179 = "&="; | |
| 1109 | var peg$c180 = "^="; | |
| 1110 | var peg$c181 = "|="; | |
| 1111 | var peg$c182 = "-="; | |
| 1112 | var peg$c183 = "("; | |
| 1113 | var peg$c184 = ")"; | |
| 1114 | var peg$c185 = "["; | |
| 1115 | var peg$c186 = "]"; | |
| 1116 | var peg$c187 = "{"; | |
| 1117 | var peg$c188 = "}"; | |
| 1118 | var peg$c189 = "."; | |
| 1119 | var peg$c190 = ","; | |
| 1120 | var peg$c191 = ":"; | |
| 1121 | var peg$c192 = "="; | |
| 1122 | var peg$c193 = ";"; | |
| 1123 | var peg$c194 = "!"; | |
| 1124 | var peg$c195 = "-"; | |
| 1125 | var peg$c196 = "~"; | |
| 1126 | var peg$c197 = "+"; | |
| 1127 | var peg$c198 = "*"; | |
| 1128 | var peg$c199 = "/"; | |
| 1129 | var peg$c200 = "%"; | |
| 1130 | var peg$c201 = "<"; | |
| 1131 | var peg$c202 = ">"; | |
| 1132 | var peg$c203 = "|"; | |
| 1133 | var peg$c204 = "^"; | |
| 1134 | var peg$c205 = "&"; | |
| 1135 | var peg$c206 = "?"; | |
| 1136 | var peg$c207 = "0"; | |
| 1137 | var peg$c208 = "lf"; | |
| 1138 | var peg$c209 = "LF"; | |
| 1139 | var peg$c210 = "#"; | |
| 1140 | var peg$c211 = "//"; | |
| 1141 | var peg$c212 = "/*"; | |
| 1142 | var peg$c213 = "*/"; | |
| 1143 | var peg$r0 = /^[A-Za-z_]/; | |
| 1144 | var peg$r1 = /^[A-Za-z_0-9]/; | |
| 1145 | var peg$r2 = /^[uU]/; | |
| 1146 | var peg$r3 = /^[1-9]/; | |
| 1147 | var peg$r4 = /^[0-7]/; | |
| 1148 | var peg$r5 = /^[xX]/; | |
| 1149 | var peg$r6 = /^[0-9a-fA-F]/; | |
| 1150 | var peg$r7 = /^[0-9]/; | |
| 1151 | var peg$r8 = /^[eE]/; | |
| 1152 | var peg$r9 = /^[+\-]/; | |
| 1153 | var peg$r10 = /^[fF]/; | |
| 1154 | var peg$r11 = /^[^\n]/; | |
| 1155 | var peg$r12 = /^[ \t\n\r]/; | |
| 1156 | var peg$e0 = peg$literalExpectation("attribute", false); | |
| 1157 | var peg$e1 = peg$literalExpectation("varying", false); | |
| 1158 | var peg$e2 = peg$literalExpectation("const", false); | |
| 1159 | var peg$e3 = peg$literalExpectation("bool", false); | |
| 1160 | var peg$e4 = peg$literalExpectation("float", false); | |
| 1161 | var peg$e5 = peg$literalExpectation("double", false); | |
| 1162 | var peg$e6 = peg$literalExpectation("int", false); | |
| 1163 | var peg$e7 = peg$literalExpectation("uint", false); | |
| 1164 | var peg$e8 = peg$literalExpectation("break", false); | |
| 1165 | var peg$e9 = peg$literalExpectation("continue", false); | |
| 1166 | var peg$e10 = peg$literalExpectation("do", false); | |
| 1167 | var peg$e11 = peg$literalExpectation("else", false); | |
| 1168 | var peg$e12 = peg$literalExpectation("for", false); | |
| 1169 | var peg$e13 = peg$literalExpectation("if", false); | |
| 1170 | var peg$e14 = peg$literalExpectation("discard", false); | |
| 1171 | var peg$e15 = peg$literalExpectation("return", false); | |
| 1172 | var peg$e16 = peg$literalExpectation("switch", false); | |
| 1173 | var peg$e17 = peg$literalExpectation("case", false); | |
| 1174 | var peg$e18 = peg$literalExpectation("default", false); | |
| 1175 | var peg$e19 = peg$literalExpectation("subroutine", false); | |
| 1176 | var peg$e20 = peg$literalExpectation("bvec2", false); | |
| 1177 | var peg$e21 = peg$literalExpectation("bvec3", false); | |
| 1178 | var peg$e22 = peg$literalExpectation("bvec4", false); | |
| 1179 | var peg$e23 = peg$literalExpectation("ivec2", false); | |
| 1180 | var peg$e24 = peg$literalExpectation("ivec3", false); | |
| 1181 | var peg$e25 = peg$literalExpectation("ivec4", false); | |
| 1182 | var peg$e26 = peg$literalExpectation("uvec2", false); | |
| 1183 | var peg$e27 = peg$literalExpectation("uvec3", false); | |
| 1184 | var peg$e28 = peg$literalExpectation("uvec4", false); | |
| 1185 | var peg$e29 = peg$literalExpectation("vec2", false); | |
| 1186 | var peg$e30 = peg$literalExpectation("vec3", false); | |
| 1187 | var peg$e31 = peg$literalExpectation("vec4", false); | |
| 1188 | var peg$e32 = peg$literalExpectation("mat2", false); | |
| 1189 | var peg$e33 = peg$literalExpectation("mat3", false); | |
| 1190 | var peg$e34 = peg$literalExpectation("mat4", false); | |
| 1191 | var peg$e35 = peg$literalExpectation("centroid", false); | |
| 1192 | var peg$e36 = peg$literalExpectation("in", false); | |
| 1193 | var peg$e37 = peg$literalExpectation("out", false); | |
| 1194 | var peg$e38 = peg$literalExpectation("inout", false); | |
| 1195 | var peg$e39 = peg$literalExpectation("uniform", false); | |
| 1196 | var peg$e40 = peg$literalExpectation("patch", false); | |
| 1197 | var peg$e41 = peg$literalExpectation("sample", false); | |
| 1198 | var peg$e42 = peg$literalExpectation("buffer", false); | |
| 1199 | var peg$e43 = peg$literalExpectation("shared", false); | |
| 1200 | var peg$e44 = peg$literalExpectation("coherent", false); | |
| 1201 | var peg$e45 = peg$literalExpectation("volatile", false); | |
| 1202 | var peg$e46 = peg$literalExpectation("restrict", false); | |
| 1203 | var peg$e47 = peg$literalExpectation("readonly", false); | |
| 1204 | var peg$e48 = peg$literalExpectation("writeonly", false); | |
| 1205 | var peg$e49 = peg$literalExpectation("dvec2", false); | |
| 1206 | var peg$e50 = peg$literalExpectation("dvec3", false); | |
| 1207 | var peg$e51 = peg$literalExpectation("dvec4", false); | |
| 1208 | var peg$e52 = peg$literalExpectation("dmat2", false); | |
| 1209 | var peg$e53 = peg$literalExpectation("dmat3", false); | |
| 1210 | var peg$e54 = peg$literalExpectation("dmat4", false); | |
| 1211 | var peg$e55 = peg$literalExpectation("noperspective", false); | |
| 1212 | var peg$e56 = peg$literalExpectation("flat", false); | |
| 1213 | var peg$e57 = peg$literalExpectation("smooth", false); | |
| 1214 | var peg$e58 = peg$literalExpectation("layout", false); | |
| 1215 | var peg$e59 = peg$literalExpectation("mat2x2", false); | |
| 1216 | var peg$e60 = peg$literalExpectation("mat2x3", false); | |
| 1217 | var peg$e61 = peg$literalExpectation("mat2x4", false); | |
| 1218 | var peg$e62 = peg$literalExpectation("mat3x2", false); | |
| 1219 | var peg$e63 = peg$literalExpectation("mat3x3", false); | |
| 1220 | var peg$e64 = peg$literalExpectation("mat3x4", false); | |
| 1221 | var peg$e65 = peg$literalExpectation("mat4x2", false); | |
| 1222 | var peg$e66 = peg$literalExpectation("mat4x3", false); | |
| 1223 | var peg$e67 = peg$literalExpectation("mat4x4", false); | |
| 1224 | var peg$e68 = peg$literalExpectation("dmat2x2", false); | |
| 1225 | var peg$e69 = peg$literalExpectation("dmat2x3", false); | |
| 1226 | var peg$e70 = peg$literalExpectation("dmat2x4", false); | |
| 1227 | var peg$e71 = peg$literalExpectation("dmat3x2", false); | |
| 1228 | var peg$e72 = peg$literalExpectation("dmat3x3", false); | |
| 1229 | var peg$e73 = peg$literalExpectation("dmat3x4", false); | |
| 1230 | var peg$e74 = peg$literalExpectation("dmat4x2", false); | |
| 1231 | var peg$e75 = peg$literalExpectation("dmat4x3", false); | |
| 1232 | var peg$e76 = peg$literalExpectation("dmat4x4", false); | |
| 1233 | var peg$e77 = peg$literalExpectation("atomic_uint", false); | |
| 1234 | var peg$e78 = peg$literalExpectation("sampler1D", false); | |
| 1235 | var peg$e79 = peg$literalExpectation("sampler2D", false); | |
| 1236 | var peg$e80 = peg$literalExpectation("sampler3D", false); | |
| 1237 | var peg$e81 = peg$literalExpectation("samplerCube", false); | |
| 1238 | var peg$e82 = peg$literalExpectation("sampler1DShadow", false); | |
| 1239 | var peg$e83 = peg$literalExpectation("sampler2DShadow", false); | |
| 1240 | var peg$e84 = peg$literalExpectation("samplerCubeShadow", false); | |
| 1241 | var peg$e85 = peg$literalExpectation("sampler1DArray", false); | |
| 1242 | var peg$e86 = peg$literalExpectation("sampler2DArray", false); | |
| 1243 | var peg$e87 = peg$literalExpectation("sampler1DArrayShadow", false); | |
| 1244 | var peg$e88 = peg$literalExpectation("sampler2DArrayShadow", false); | |
| 1245 | var peg$e89 = peg$literalExpectation("isampler1D", false); | |
| 1246 | var peg$e90 = peg$literalExpectation("isampler2D", false); | |
| 1247 | var peg$e91 = peg$literalExpectation("isampler3D", false); | |
| 1248 | var peg$e92 = peg$literalExpectation("isamplerCube", false); | |
| 1249 | var peg$e93 = peg$literalExpectation("isampler1Darray", false); | |
| 1250 | var peg$e94 = peg$literalExpectation("isampler2DArray", false); | |
| 1251 | var peg$e95 = peg$literalExpectation("usampler1D", false); | |
| 1252 | var peg$e96 = peg$literalExpectation("usampler2D", false); | |
| 1253 | var peg$e97 = peg$literalExpectation("usampler3D", false); | |
| 1254 | var peg$e98 = peg$literalExpectation("usamplerCube", false); | |
| 1255 | var peg$e99 = peg$literalExpectation("usampler1DArray", false); | |
| 1256 | var peg$e100 = peg$literalExpectation("usampler2DArray", false); | |
| 1257 | var peg$e101 = peg$literalExpectation("sampler2DRect", false); | |
| 1258 | var peg$e102 = peg$literalExpectation("sampler2DRectShadow", false); | |
| 1259 | var peg$e103 = peg$literalExpectation("isampler2DRect", false); | |
| 1260 | var peg$e104 = peg$literalExpectation("usampler2DRect", false); | |
| 1261 | var peg$e105 = peg$literalExpectation("samplerBuffer", false); | |
| 1262 | var peg$e106 = peg$literalExpectation("isamplerBuffer", false); | |
| 1263 | var peg$e107 = peg$literalExpectation("usamplerBuffer", false); | |
| 1264 | var peg$e108 = peg$literalExpectation("samplerCubeArray", false); | |
| 1265 | var peg$e109 = peg$literalExpectation("samplerCubeArrayShadow", false); | |
| 1266 | var peg$e110 = peg$literalExpectation("isamplerCubeArray", false); | |
| 1267 | var peg$e111 = peg$literalExpectation("usamplerCubeArray", false); | |
| 1268 | var peg$e112 = peg$literalExpectation("sampler2DMS", false); | |
| 1269 | var peg$e113 = peg$literalExpectation("isampler2DMS", false); | |
| 1270 | var peg$e114 = peg$literalExpectation("usampler2DMS", false); | |
| 1271 | var peg$e115 = peg$literalExpectation("sampler2DMSArray", false); | |
| 1272 | var peg$e116 = peg$literalExpectation("isampler2DMSArray", false); | |
| 1273 | var peg$e117 = peg$literalExpectation("usampler2DMSArray", false); | |
| 1274 | var peg$e118 = peg$literalExpectation("image1D", false); | |
| 1275 | var peg$e119 = peg$literalExpectation("iimage1D", false); | |
| 1276 | var peg$e120 = peg$literalExpectation("uimage1D", false); | |
| 1277 | var peg$e121 = peg$literalExpectation("image2D", false); | |
| 1278 | var peg$e122 = peg$literalExpectation("iimage2D", false); | |
| 1279 | var peg$e123 = peg$literalExpectation("uimage2D", false); | |
| 1280 | var peg$e124 = peg$literalExpectation("image3D", false); | |
| 1281 | var peg$e125 = peg$literalExpectation("iimage3D", false); | |
| 1282 | var peg$e126 = peg$literalExpectation("uimage3D", false); | |
| 1283 | var peg$e127 = peg$literalExpectation("image2DRect", false); | |
| 1284 | var peg$e128 = peg$literalExpectation("iimage2DRect", false); | |
| 1285 | var peg$e129 = peg$literalExpectation("uimage2DRect", false); | |
| 1286 | var peg$e130 = peg$literalExpectation("imageCube", false); | |
| 1287 | var peg$e131 = peg$literalExpectation("iimageCube", false); | |
| 1288 | var peg$e132 = peg$literalExpectation("uimageCube", false); | |
| 1289 | var peg$e133 = peg$literalExpectation("imageBuffer", false); | |
| 1290 | var peg$e134 = peg$literalExpectation("iimageBuffer", false); | |
| 1291 | var peg$e135 = peg$literalExpectation("uimageBuffer", false); | |
| 1292 | var peg$e136 = peg$literalExpectation("image1DArray", false); | |
| 1293 | var peg$e137 = peg$literalExpectation("iimage1DArray", false); | |
| 1294 | var peg$e138 = peg$literalExpectation("uimage1DArray", false); | |
| 1295 | var peg$e139 = peg$literalExpectation("image2DArray", false); | |
| 1296 | var peg$e140 = peg$literalExpectation("iimage2DArray", false); | |
| 1297 | var peg$e141 = peg$literalExpectation("uimage2DArray", false); | |
| 1298 | var peg$e142 = peg$literalExpectation("imageCubeArray", false); | |
| 1299 | var peg$e143 = peg$literalExpectation("iimageCubeArray", false); | |
| 1300 | var peg$e144 = peg$literalExpectation("uimageCubeArray", false); | |
| 1301 | var peg$e145 = peg$literalExpectation("image2DMS", false); | |
| 1302 | var peg$e146 = peg$literalExpectation("iimage2DMS", false); | |
| 1303 | var peg$e147 = peg$literalExpectation("uimage2DMS", false); | |
| 1304 | var peg$e148 = peg$literalExpectation("image2DMArray", false); | |
| 1305 | var peg$e149 = peg$literalExpectation("iimage2DMSArray", false); | |
| 1306 | var peg$e150 = peg$literalExpectation("uimage2DMSArray", false); | |
| 1307 | var peg$e151 = peg$literalExpectation("struct", false); | |
| 1308 | var peg$e152 = peg$literalExpectation("void", false); | |
| 1309 | var peg$e153 = peg$literalExpectation("while", false); | |
| 1310 | var peg$e154 = peg$literalExpectation("invariant", false); | |
| 1311 | var peg$e155 = peg$literalExpectation("precise", false); | |
| 1312 | var peg$e156 = peg$literalExpectation("highp", false); | |
| 1313 | var peg$e157 = peg$literalExpectation("mediump", false); | |
| 1314 | var peg$e158 = peg$literalExpectation("lowp", false); | |
| 1315 | var peg$e159 = peg$literalExpectation("precision", false); | |
| 1316 | var peg$e160 = peg$literalExpectation("true", false); | |
| 1317 | var peg$e161 = peg$literalExpectation("false", false); | |
| 1318 | var peg$e162 = peg$otherExpectation("keyword"); | |
| 1319 | var peg$e163 = peg$literalExpectation("<<", false); | |
| 1320 | var peg$e164 = peg$literalExpectation(">>", false); | |
| 1321 | var peg$e165 = peg$literalExpectation("++", false); | |
| 1322 | var peg$e166 = peg$literalExpectation("--", false); | |
| 1323 | var peg$e167 = peg$literalExpectation("<=", false); | |
| 1324 | var peg$e168 = peg$literalExpectation(">=", false); | |
| 1325 | var peg$e169 = peg$literalExpectation("==", false); | |
| 1326 | var peg$e170 = peg$literalExpectation("!=", false); | |
| 1327 | var peg$e171 = peg$literalExpectation("&&", false); | |
| 1328 | var peg$e172 = peg$literalExpectation("||", false); | |
| 1329 | var peg$e173 = peg$literalExpectation("^^", false); | |
| 1330 | var peg$e174 = peg$literalExpectation("*=", false); | |
| 1331 | var peg$e175 = peg$literalExpectation("/=", false); | |
| 1332 | var peg$e176 = peg$literalExpectation("+=", false); | |
| 1333 | var peg$e177 = peg$literalExpectation("%=", false); | |
| 1334 | var peg$e178 = peg$literalExpectation("<<=", false); | |
| 1335 | var peg$e179 = peg$literalExpectation(">>=", false); | |
| 1336 | var peg$e180 = peg$literalExpectation("&=", false); | |
| 1337 | var peg$e181 = peg$literalExpectation("^=", false); | |
| 1338 | var peg$e182 = peg$literalExpectation("|=", false); | |
| 1339 | var peg$e183 = peg$literalExpectation("-=", false); | |
| 1340 | var peg$e184 = peg$literalExpectation("(", false); | |
| 1341 | var peg$e185 = peg$literalExpectation(")", false); | |
| 1342 | var peg$e186 = peg$literalExpectation("[", false); | |
| 1343 | var peg$e187 = peg$literalExpectation("]", false); | |
| 1344 | var peg$e188 = peg$literalExpectation("{", false); | |
| 1345 | var peg$e189 = peg$literalExpectation("}", false); | |
| 1346 | var peg$e190 = peg$literalExpectation(".", false); | |
| 1347 | var peg$e191 = peg$literalExpectation(",", false); | |
| 1348 | var peg$e192 = peg$literalExpectation(":", false); | |
| 1349 | var peg$e193 = peg$literalExpectation("=", false); | |
| 1350 | var peg$e194 = peg$literalExpectation(";", false); | |
| 1351 | var peg$e195 = peg$literalExpectation("!", false); | |
| 1352 | var peg$e196 = peg$literalExpectation("-", false); | |
| 1353 | var peg$e197 = peg$literalExpectation("~", false); | |
| 1354 | var peg$e198 = peg$literalExpectation("+", false); | |
| 1355 | var peg$e199 = peg$literalExpectation("*", false); | |
| 1356 | var peg$e200 = peg$literalExpectation("/", false); | |
| 1357 | var peg$e201 = peg$literalExpectation("%", false); | |
| 1358 | var peg$e202 = peg$literalExpectation("<", false); | |
| 1359 | var peg$e203 = peg$literalExpectation(">", false); | |
| 1360 | var peg$e204 = peg$literalExpectation("|", false); | |
| 1361 | var peg$e205 = peg$literalExpectation("^", false); | |
| 1362 | var peg$e206 = peg$literalExpectation("&", false); | |
| 1363 | var peg$e207 = peg$literalExpectation("?", false); | |
| 1364 | var peg$e208 = peg$classExpectation([["A", "Z"], ["a", "z"], "_"], false, false); | |
| 1365 | var peg$e209 = peg$classExpectation([["A", "Z"], ["a", "z"], "_", ["0", "9"]], false, false); | |
| 1366 | var peg$e210 = peg$classExpectation(["u", "U"], false, false); | |
| 1367 | var peg$e211 = peg$classExpectation([["1", "9"]], false, false); | |
| 1368 | var peg$e212 = peg$literalExpectation("0", false); | |
| 1369 | var peg$e213 = peg$classExpectation([["0", "7"]], false, false); | |
| 1370 | var peg$e214 = peg$classExpectation(["x", "X"], false, false); | |
| 1371 | var peg$e215 = peg$classExpectation([["0", "9"], ["a", "f"], ["A", "F"]], false, false); | |
| 1372 | var peg$e216 = peg$classExpectation([["0", "9"]], false, false); | |
| 1373 | var peg$e217 = peg$otherExpectation("exponent"); | |
| 1374 | var peg$e218 = peg$classExpectation(["e", "E"], false, false); | |
| 1375 | var peg$e219 = peg$classExpectation(["+", "-"], false, false); | |
| 1376 | var peg$e220 = peg$classExpectation(["f", "F"], false, false); | |
| 1377 | var peg$e221 = peg$literalExpectation("lf", false); | |
| 1378 | var peg$e222 = peg$literalExpectation("LF", false); | |
| 1379 | var peg$e223 = peg$otherExpectation("primary expression"); | |
| 1380 | var peg$e224 = peg$otherExpectation("unary expression"); | |
| 1381 | var peg$e225 = peg$otherExpectation("equality expression"); | |
| 1382 | var peg$e226 = peg$otherExpectation("and expression"); | |
| 1383 | var peg$e227 = peg$otherExpectation("asignment"); | |
| 1384 | var peg$e228 = peg$otherExpectation("expression"); | |
| 1385 | var peg$e229 = peg$otherExpectation("precision statement"); | |
| 1386 | var peg$e230 = peg$otherExpectation("function prototype"); | |
| 1387 | var peg$e231 = peg$otherExpectation("function header"); | |
| 1388 | var peg$e232 = peg$otherExpectation("function prototype scope"); | |
| 1389 | var peg$e233 = peg$otherExpectation("function header scope"); | |
| 1390 | var peg$e234 = peg$otherExpectation("function parameters"); | |
| 1391 | var peg$e235 = peg$otherExpectation("parameter declaration"); | |
| 1392 | var peg$e236 = peg$otherExpectation("single type qualifier"); | |
| 1393 | var peg$e237 = peg$otherExpectation("interpolation qualifier"); | |
| 1394 | var peg$e238 = peg$otherExpectation("storage qualifier"); | |
| 1395 | var peg$e239 = peg$otherExpectation("type specifier"); | |
| 1396 | var peg$e240 = peg$otherExpectation("array specifier"); | |
| 1397 | var peg$e241 = peg$otherExpectation("precision qualifier"); | |
| 1398 | var peg$e242 = peg$otherExpectation("struct specifier"); | |
| 1399 | var peg$e243 = peg$otherExpectation("iteration statement"); | |
| 1400 | var peg$e244 = peg$otherExpectation("jump statement"); | |
| 1401 | var peg$e245 = peg$otherExpectation("prepocessor"); | |
| 1402 | var peg$e246 = peg$literalExpectation("#", false); | |
| 1403 | var peg$e247 = peg$classExpectation(["\n"], true, false); | |
| 1404 | var peg$e248 = peg$otherExpectation("whitespace"); | |
| 1405 | var peg$e249 = peg$literalExpectation("//", false); | |
| 1406 | var peg$e250 = peg$literalExpectation("/*", false); | |
| 1407 | var peg$e251 = peg$literalExpectation("*/", false); | |
| 1408 | var peg$e252 = peg$anyExpectation(); | |
| 1409 | var peg$e253 = peg$classExpectation([" ", " ", "\n", "\r"], false, false); | |
| 1410 | var peg$f0 = function(wsStart, program) { | |
| 1411 | setScopeEnd(context.scope, getLocation()?.end); | |
| 1412 | return node("program", { wsStart, program, scopes: context.scopes }); | |
| 1413 | }; | |
| 1414 | var peg$f1 = function(token, t) { | |
| 1415 | return node("keyword", { token, whitespace: t }); | |
| 1416 | }; | |
| 1417 | var peg$f2 = function(token, _) { | |
| 1418 | return node("float_constant", { token, whitespace: _ }); | |
| 1419 | }; | |
| 1420 | var peg$f3 = function(token, _) { | |
| 1421 | return node("double_constant", { token, whitespace: _ }); | |
| 1422 | }; | |
| 1423 | var peg$f4 = function(token, _) { | |
| 1424 | return node("int_constant", { token, whitespace: _ }); | |
| 1425 | }; | |
| 1426 | var peg$f5 = function(token, _) { | |
| 1427 | return node("uint_constant", { token, whitespace: _ }); | |
| 1428 | }; | |
| 1429 | var peg$f6 = function(token, t) { | |
| 1430 | return node("bool_constant", { token, whitespace: t }); | |
| 1431 | }; | |
| 1432 | var peg$f7 = function(token, _) { | |
| 1433 | return node("literal", { literal: token, whitespace: _ }); | |
| 1434 | }; | |
| 1435 | var peg$f8 = function(identifier, _) { | |
| 1436 | return node("identifier", { identifier, whitespace: _ }); | |
| 1437 | }; | |
| 1438 | var peg$f9 = function(identifier, _) { | |
| 1439 | return node("type_name", { identifier, whitespace: _ }); | |
| 1440 | }; | |
| 1441 | var peg$f10 = function(lp, expression, rp) { | |
| 1442 | return node("group", { lp, expression, rp }); | |
| 1443 | }; | |
| 1444 | var peg$f11 = function(ident) { | |
| 1445 | const { identifier } = ident; | |
| 1446 | addOrCreateBindingReference(context.scope, identifier, ident); | |
| 1447 | return ident; | |
| 1448 | }; | |
| 1449 | var peg$f12 = function(body) { | |
| 1450 | return body.flat().reduceRight( | |
| 1451 | (postfix, expression) => postfix ? node("postfix", { expression, postfix }) : expression | |
| 1452 | ); | |
| 1453 | }; | |
| 1454 | var peg$f13 = function(lb, expression, rb) { | |
| 1455 | return node("quantifier", { lb, expression, rb }); | |
| 1456 | }; | |
| 1457 | var peg$f14 = function(dot, selection) { | |
| 1458 | return node("field_selection", { dot, selection }); | |
| 1459 | }; | |
| 1460 | var peg$f15 = function(function_identifier, args, rp) { | |
| 1461 | const identifierPartial = function_identifier.partial; | |
| 1462 | const { identifier } = identifierPartial; | |
| 1463 | let fnIdentifier = identifier.type === "postfix" ? identifier.expression.identifier ? identifier.expression.identifier.specifier : identifier.expression.specifier : identifier.specifier; | |
| 1464 | let fnName = fnIdentifier.identifier; | |
| 1465 | const n = node("function_call", { ...identifierPartial, args: args || [], rp }); | |
| 1466 | const isDeclaredFn = isDeclaredFunction(context.scope, fnName); | |
| 1467 | const isBuiltIn = FN_BUILT_INS.has(fnName); | |
| 1468 | const isType = isDeclaredType(context.scope, fnName); | |
| 1469 | if (fnName) { | |
| 1470 | if (!isType && fnIdentifier.type === "type_name" && (!isDeclaredFn || isBuiltIn)) { | |
| 1471 | fnIdentifier = node("identifier", { | |
| 1472 | identifier: fnIdentifier.identifier, | |
| 1473 | whitespace: fnIdentifier.whitespace | |
| 1474 | }); | |
| 1475 | if (n.identifier.type === "postfix") { | |
| 1476 | n.identifier.expression.identifier = fnIdentifier; | |
| 1477 | } else { | |
| 1478 | n.identifier = fnIdentifier; | |
| 1479 | } | |
| 1480 | } | |
| 1481 | if ( | |
| 1482 | // You can override built-in functions like "noise", so only add | |
| 1483 | // "noise" to scope usage if it's declared by the user | |
| 1484 | isDeclaredFn || !isBuiltIn | |
| 1485 | ) { | |
| 1486 | if (isType) { | |
| 1487 | if (identifier.type === "type_specifier") { | |
| 1488 | addTypeReference( | |
| 1489 | context.scope, | |
| 1490 | fnName, | |
| 1491 | identifier.specifier | |
| 1492 | ); | |
| 1493 | } else { | |
| 1494 | throw new Error(`Unknown function call identifier type ${identifier.type}. Please file a bug against @shaderfrog/glsl-parser and incldue your source grammar.`); | |
| 1495 | } | |
| 1496 | } else { | |
| 1497 | addFunctionCallReference(context.scope, fnName, n); | |
| 1498 | } | |
| 1499 | } | |
| 1500 | } | |
| 1501 | return n; | |
| 1502 | }; | |
| 1503 | var peg$f16 = function(v) { | |
| 1504 | return [v]; | |
| 1505 | }; | |
| 1506 | var peg$f17 = function(head, tail) { | |
| 1507 | return [head, ...tail.flat()]; | |
| 1508 | }; | |
| 1509 | var peg$f18 = function(head, suffix, lp) { | |
| 1510 | return partial({ head: [head, suffix], lp }); | |
| 1511 | }; | |
| 1512 | var peg$f19 = function(identifier) { | |
| 1513 | return partial({ | |
| 1514 | lp: identifier.partial.lp, | |
| 1515 | identifier: [identifier.partial.head].flat().reduceRight( | |
| 1516 | (postfix, expression) => postfix ? node("postfix", { expression, postfix }) : expression | |
| 1517 | ) | |
| 1518 | }); | |
| 1519 | }; | |
| 1520 | var peg$f20 = function(identifier, lp, args, rp) { | |
| 1521 | return node("function_call", { identifier, lp, args, rp }); | |
| 1522 | }; | |
| 1523 | var peg$f21 = function(operator, expression) { | |
| 1524 | return node("unary", { operator, expression }); | |
| 1525 | }; | |
| 1526 | var peg$f22 = function(head, tail) { | |
| 1527 | return leftAssociate(head, tail); | |
| 1528 | }; | |
| 1529 | var peg$f23 = function(expression, question, left, colon, right) { | |
| 1530 | return { question, left, right, colon }; | |
| 1531 | }; | |
| 1532 | var peg$f24 = function(expression, suffix) { | |
| 1533 | return suffix ? node("ternary", { expression, ...suffix }) : expression; | |
| 1534 | }; | |
| 1535 | var peg$f25 = function(left, operator, right) { | |
| 1536 | return node("assignment", { left, operator, right }); | |
| 1537 | }; | |
| 1538 | var peg$f26 = function(declaration) { | |
| 1539 | return node( | |
| 1540 | "declaration_statement", | |
| 1541 | { | |
| 1542 | declaration: declaration.partial.node, | |
| 1543 | semi: declaration.partial.semi | |
| 1544 | } | |
| 1545 | ); | |
| 1546 | }; | |
| 1547 | var peg$f27 = function(qualifiers, head, tail, semi) { | |
| 1548 | return partial({ | |
| 1549 | node: node( | |
| 1550 | "qualifier_declarator", | |
| 1551 | { | |
| 1552 | qualifiers, | |
| 1553 | // Head is optional, so remove falsey | |
| 1554 | declarations: xnil([head, ...tail.map((t) => t[1])]), | |
| 1555 | commas: tail.map((t) => t[0]) | |
| 1556 | } | |
| 1557 | ), | |
| 1558 | semi | |
| 1559 | }); | |
| 1560 | }; | |
| 1561 | var peg$f28 = function(qualifiers, interface_type, lp, declarations, rp, identifier, semi) { | |
| 1562 | const n = node( | |
| 1563 | "interface_declarator", | |
| 1564 | { qualifiers, interface_type, lp, declarations, rp, identifier } | |
| 1565 | ); | |
| 1566 | createBindings(context.scope, [interface_type.identifier, n]); | |
| 1567 | return partial({ | |
| 1568 | node: n, | |
| 1569 | semi | |
| 1570 | }); | |
| 1571 | }; | |
| 1572 | var peg$f29 = function(prefix, qualifier, specifier, semi) { | |
| 1573 | return partial({ | |
| 1574 | node: node("precision", { prefix, qualifier, specifier }), | |
| 1575 | semi | |
| 1576 | }); | |
| 1577 | }; | |
| 1578 | var peg$f30 = function(header, params, rp) { | |
| 1579 | const bindings = (params?.parameters || []).filter((p) => !!p.identifier).map((p) => [p.identifier.identifier, p]); | |
| 1580 | createBindings(context.scope, ...bindings); | |
| 1581 | return node("function_prototype", { header, ...params, rp }); | |
| 1582 | }; | |
| 1583 | var peg$f31 = function(returnType, name, lp) { | |
| 1584 | const n = node( | |
| 1585 | "function_header", | |
| 1586 | { returnType, name, lp } | |
| 1587 | ); | |
| 1588 | context.scope = pushScope(makeScope(name.identifier, context.scope, lp.location)); | |
| 1589 | return n; | |
| 1590 | }; | |
| 1591 | var peg$f32 = function(header, params, rp) { | |
| 1592 | return node("function_prototype", { header, ...params, rp }); | |
| 1593 | }; | |
| 1594 | var peg$f33 = function(returnType, name, lp) { | |
| 1595 | return node( | |
| 1596 | "function_header", | |
| 1597 | { returnType, name, lp } | |
| 1598 | ); | |
| 1599 | }; | |
| 1600 | var peg$f34 = function(head, tail) { | |
| 1601 | return { | |
| 1602 | parameters: [head, ...tail.map((t) => t[1])], | |
| 1603 | commas: tail.map((t) => t[0]) | |
| 1604 | }; | |
| 1605 | }; | |
| 1606 | var peg$f35 = function(qualifier, specifier, declaration) { | |
| 1607 | return node( | |
| 1608 | "parameter_declaration", | |
| 1609 | { | |
| 1610 | qualifier, | |
| 1611 | specifier, | |
| 1612 | identifier: declaration?.[0], | |
| 1613 | quantifier: declaration?.[1] | |
| 1614 | } | |
| 1615 | ); | |
| 1616 | }; | |
| 1617 | var peg$f36 = function(head, tail, semi) { | |
| 1618 | const declarations = [ | |
| 1619 | head.partial.declaration, | |
| 1620 | ...tail.map((t) => t[1]) | |
| 1621 | ].filter((decl) => !!decl.identifier); | |
| 1622 | addTypeIfFound(context.scope, head.partial.specified_type); | |
| 1623 | createBindings(context.scope, ...tail.map((t) => t[1]).map((decl) => [decl.identifier.identifier, decl])); | |
| 1624 | return partial({ | |
| 1625 | node: node( | |
| 1626 | "declarator_list", | |
| 1627 | { | |
| 1628 | specified_type: head.partial.specified_type, | |
| 1629 | declarations, | |
| 1630 | commas: tail.map((t) => t[0]) | |
| 1631 | } | |
| 1632 | ), | |
| 1633 | semi | |
| 1634 | }); | |
| 1635 | }; | |
| 1636 | var peg$f37 = function(identifier, quantifier, suffix) { | |
| 1637 | const [equal, initializer] = suffix || []; | |
| 1638 | return node( | |
| 1639 | "declaration", | |
| 1640 | { identifier, quantifier, equal, initializer } | |
| 1641 | ); | |
| 1642 | }; | |
| 1643 | var peg$f38 = function(specified_type, suffix) { | |
| 1644 | const [identifier, quantifier, suffix_tail] = suffix || []; | |
| 1645 | const [equal, initializer] = suffix_tail || []; | |
| 1646 | if (identifier) { | |
| 1647 | createBindings(context.scope, [identifier.identifier, identifier]); | |
| 1648 | } | |
| 1649 | return partial({ | |
| 1650 | declaration: node( | |
| 1651 | "declaration", | |
| 1652 | { identifier, quantifier, equal, initializer } | |
| 1653 | ), | |
| 1654 | specified_type | |
| 1655 | }); | |
| 1656 | }; | |
| 1657 | var peg$f39 = function(qualifiers, specifier) { | |
| 1658 | return node( | |
| 1659 | "fully_specified_type", | |
| 1660 | { qualifiers, specifier } | |
| 1661 | ); | |
| 1662 | }; | |
| 1663 | var peg$f40 = function(layout, lp, head, tail) { | |
| 1664 | return partial({ | |
| 1665 | qualifiers: [head, ...tail.map((t) => t[1])], | |
| 1666 | commas: tail.map((t) => t[0]) | |
| 1667 | }); | |
| 1668 | }; | |
| 1669 | var peg$f41 = function(layout, lp, qualifiers, rp) { | |
| 1670 | return node( | |
| 1671 | "layout_qualifier", | |
| 1672 | { layout, lp, ...qualifiers.partial, rp } | |
| 1673 | ); | |
| 1674 | }; | |
| 1675 | var peg$f42 = function(identifier, tail) { | |
| 1676 | const [operator, expression] = tail || []; | |
| 1677 | return node("layout_qualifier_id", { identifier, operator, expression }); | |
| 1678 | }; | |
| 1679 | var peg$f43 = function(subroutine, lp, head, tail, rp) { | |
| 1680 | return partial({ | |
| 1681 | lp, | |
| 1682 | type_names: [head, ...tail.map((t) => t[1])], | |
| 1683 | commas: tail.map((t) => t[0]), | |
| 1684 | rp | |
| 1685 | }); | |
| 1686 | }; | |
| 1687 | var peg$f44 = function(subroutine, type_names) { | |
| 1688 | return node( | |
| 1689 | "subroutine_qualifier", | |
| 1690 | { | |
| 1691 | subroutine, | |
| 1692 | ...type_names?.partial | |
| 1693 | } | |
| 1694 | ); | |
| 1695 | }; | |
| 1696 | var peg$f45 = function(specifier, quantifier) { | |
| 1697 | return node("type_specifier", { specifier, quantifier }); | |
| 1698 | }; | |
| 1699 | var peg$f46 = function(lb, expression, rb) { | |
| 1700 | return node("array_specifier", { lb, expression, rb }); | |
| 1701 | }; | |
| 1702 | var peg$f47 = function(specifiers) { | |
| 1703 | return specifiers; | |
| 1704 | }; | |
| 1705 | var peg$f48 = function(struct, typeName, lb, declarations, rb) { | |
| 1706 | const n = node("struct", { lb, declarations, rb, struct, typeName }); | |
| 1707 | if (typeName) { | |
| 1708 | createType(context.scope, typeName.identifier, n.typeName); | |
| 1709 | } | |
| 1710 | return n; | |
| 1711 | }; | |
| 1712 | var peg$f49 = function(declaration, semi) { | |
| 1713 | addTypeIfFound(context.scope, declaration.specified_type); | |
| 1714 | return node("struct_declaration", { declaration, semi }); | |
| 1715 | }; | |
| 1716 | var peg$f50 = function(specified_type, head, tail) { | |
| 1717 | if (specified_type) | |
| 1718 | return node( | |
| 1719 | "struct_declarator", | |
| 1720 | { | |
| 1721 | specified_type, | |
| 1722 | declarations: [head, ...tail.map((t) => t[1])], | |
| 1723 | commas: tail.map((t) => t[0]) | |
| 1724 | } | |
| 1725 | ); | |
| 1726 | }; | |
| 1727 | var peg$f51 = function(identifier, quantifier) { | |
| 1728 | return node("quantified_identifier", { identifier, quantifier }); | |
| 1729 | }; | |
| 1730 | var peg$f52 = function(lb, head, tail, trailing, rb) { | |
| 1731 | return node( | |
| 1732 | "initializer_list", | |
| 1733 | { | |
| 1734 | lb, | |
| 1735 | initializers: [head, ...tail.map((t) => t[1])], | |
| 1736 | commas: xnil(tail.map((t) => t[0]), trailing), | |
| 1737 | rb | |
| 1738 | } | |
| 1739 | ); | |
| 1740 | }; | |
| 1741 | var peg$f53 = function(sym) { | |
| 1742 | context.scope = pushScope(makeScope(OPEN_CURLY, context.scope)); | |
| 1743 | return sym; | |
| 1744 | }; | |
| 1745 | var peg$f54 = function(lb, statements, rb) { | |
| 1746 | setScopeEnd(context.scope, rb.location?.start); | |
| 1747 | context.scope = popScope(context.scope); | |
| 1748 | return node( | |
| 1749 | "compound_statement", | |
| 1750 | { lb, statements: (statements || []).flat(), rb } | |
| 1751 | ); | |
| 1752 | }; | |
| 1753 | var peg$f55 = function(lb, statements, rb) { | |
| 1754 | return node( | |
| 1755 | "compound_statement", | |
| 1756 | { lb, statements: (statements || []).flat(), rb } | |
| 1757 | ); | |
| 1758 | }; | |
| 1759 | var peg$f56 = function(expression, semi) { | |
| 1760 | return node("expression_statement", { expression, semi }); | |
| 1761 | }; | |
| 1762 | var peg$f57 = function(ifSymbol, lp, condition, rp, tail) { | |
| 1763 | const [body, elseBranch] = tail; | |
| 1764 | return node( | |
| 1765 | "if_statement", | |
| 1766 | { | |
| 1767 | "if": ifSymbol, | |
| 1768 | body, | |
| 1769 | lp, | |
| 1770 | condition, | |
| 1771 | rp, | |
| 1772 | ...elseBranch && { "else": elseBranch.flat() } | |
| 1773 | } | |
| 1774 | ); | |
| 1775 | }; | |
| 1776 | var peg$f58 = function(switchSymbol, lp, expression, rp, lb, statements, rb) { | |
| 1777 | return node( | |
| 1778 | "switch_statement", | |
| 1779 | { | |
| 1780 | switch: switchSymbol, | |
| 1781 | lp, | |
| 1782 | expression, | |
| 1783 | rp, | |
| 1784 | lb, | |
| 1785 | cases: groupCases(statements), | |
| 1786 | rb | |
| 1787 | } | |
| 1788 | ); | |
| 1789 | }; | |
| 1790 | var peg$f59 = function(caseSymbol, test, colon) { | |
| 1791 | return partial("case_label", { "case": caseSymbol, test, colon }); | |
| 1792 | }; | |
| 1793 | var peg$f60 = function(defaultSymbol, colon) { | |
| 1794 | return partial("default_label", { default: defaultSymbol, colon }); | |
| 1795 | }; | |
| 1796 | var peg$f61 = function(sym) { | |
| 1797 | context.scope = pushScope(makeScope("while", context.scope)); | |
| 1798 | return sym; | |
| 1799 | }; | |
| 1800 | var peg$f62 = function(whileSymbol, lp, condition, rp, body) { | |
| 1801 | const end = body.rb ? body.rb.location?.start : body.location?.end; | |
| 1802 | setScopeEnd(context.scope, end); | |
| 1803 | context.scope = popScope(context.scope); | |
| 1804 | return node( | |
| 1805 | "while_statement", | |
| 1806 | { | |
| 1807 | while: whileSymbol, | |
| 1808 | lp, | |
| 1809 | condition, | |
| 1810 | rp, | |
| 1811 | body | |
| 1812 | } | |
| 1813 | ); | |
| 1814 | }; | |
| 1815 | var peg$f63 = function(doSymbol, body, whileSymbol, lp, expression, rp, semi) { | |
| 1816 | return node( | |
| 1817 | "do_statement", | |
| 1818 | { | |
| 1819 | do: doSymbol, | |
| 1820 | body, | |
| 1821 | while: whileSymbol, | |
| 1822 | lp, | |
| 1823 | expression, | |
| 1824 | rp, | |
| 1825 | semi | |
| 1826 | } | |
| 1827 | ); | |
| 1828 | }; | |
| 1829 | var peg$f64 = function(sym) { | |
| 1830 | context.scope = pushScope(makeScope("for", context.scope)); | |
| 1831 | return sym; | |
| 1832 | }; | |
| 1833 | var peg$f65 = function(forSymbol, lp, init, condition, conditionSemi, operation, rp, body) { | |
| 1834 | const end = body.rb ? body.rb.location?.start : body.location?.end; | |
| 1835 | setScopeEnd(context.scope, end); | |
| 1836 | context.scope = popScope(context.scope); | |
| 1837 | return node( | |
| 1838 | "for_statement", | |
| 1839 | { | |
| 1840 | "for": forSymbol, | |
| 1841 | body, | |
| 1842 | lp, | |
| 1843 | init: init.expression || init.declaration, | |
| 1844 | initSemi: init.semi, | |
| 1845 | condition, | |
| 1846 | conditionSemi, | |
| 1847 | operation, | |
| 1848 | rp | |
| 1849 | } | |
| 1850 | ); | |
| 1851 | }; | |
| 1852 | var peg$f66 = function(specified_type, identifier, operator, initializer) { | |
| 1853 | const n = node( | |
| 1854 | "condition_expression", | |
| 1855 | { specified_type, identifier, operator, initializer } | |
| 1856 | ); | |
| 1857 | createBindings(context.scope, [identifier.identifier, n]); | |
| 1858 | return n; | |
| 1859 | }; | |
| 1860 | var peg$f67 = function(jump, semi) { | |
| 1861 | return node("continue_statement", { continue: jump, semi }); | |
| 1862 | }; | |
| 1863 | var peg$f68 = function(jump, semi) { | |
| 1864 | return node("break_statement", { break: jump, semi }); | |
| 1865 | }; | |
| 1866 | var peg$f69 = function(jump, expression, semi) { | |
| 1867 | return node("return_statement", { return: jump, expression, semi }); | |
| 1868 | }; | |
| 1869 | var peg$f70 = function(jump, semi) { | |
| 1870 | return node("discard_statement", { discard: jump, semi }); | |
| 1871 | }; | |
| 1872 | var peg$f71 = function(line, _) { | |
| 1873 | return node("preprocessor", { line, _ }); | |
| 1874 | }; | |
| 1875 | var peg$f72 = function(declaration, semi) { | |
| 1876 | (declaration.parameters || []).forEach((p) => addTypeIfFound(context.scope, p.specifier)); | |
| 1877 | addTypeIfFound(context.scope, declaration.header.returnType); | |
| 1878 | createFunctionPrototype(context.scope, declaration.header.name.identifier, declaration); | |
| 1879 | const n = node( | |
| 1880 | "declaration_statement", | |
| 1881 | { | |
| 1882 | declaration, | |
| 1883 | semi | |
| 1884 | } | |
| 1885 | ); | |
| 1886 | return n; | |
| 1887 | }; | |
| 1888 | var peg$f73 = function(prototype, body) { | |
| 1889 | const n = node("function", { prototype, body }); | |
| 1890 | setScopeEnd(context.scope, body.rb.location?.start); | |
| 1891 | context.scope = popScope(context.scope); | |
| 1892 | (prototype.parameters || []).forEach((p) => addTypeIfFound(context.scope, p.specifier)); | |
| 1893 | addTypeIfFound(context.scope, prototype.header.returnType); | |
| 1894 | createFunctionDefinition(context.scope, prototype.header.name.identifier, n, n); | |
| 1895 | return n; | |
| 1896 | }; | |
| 1897 | var peg$f74 = function(w, rest) { | |
| 1898 | return collapse(w, rest); | |
| 1899 | }; | |
| 1900 | var peg$f75 = function(a, x, cc) { | |
| 1901 | return xnil(x, cc); | |
| 1902 | }; | |
| 1903 | var peg$f76 = function(a, d) { | |
| 1904 | return xnil(a, d.flat()); | |
| 1905 | }; | |
| 1906 | var peg$f77 = function(i) { | |
| 1907 | return i; | |
| 1908 | }; | |
| 1909 | var peg$f78 = function(_) { | |
| 1910 | return _; | |
| 1911 | }; | |
| 1912 | var peg$currPos = 0; | |
| 1913 | var peg$savedPos = 0; | |
| 1914 | var peg$posDetailsCache = [{ line: 1, column: 1 }]; | |
| 1915 | var peg$maxFailPos = 0; | |
| 1916 | var peg$maxFailExpected = []; | |
| 1917 | var peg$silentFails = 0; | |
| 1918 | var peg$resultsCache = {}; | |
| 1919 | var peg$result; | |
| 1920 | if ("startRule" in options) { | |
| 1921 | if (!(options.startRule in peg$startRuleFunctions)) { | |
| 1922 | throw new Error(`Can't start parsing from rule "` + options.startRule + '".'); | |
| 1923 | } | |
| 1924 | peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; | |
| 1925 | } | |
| 1926 | function text() { | |
| 1927 | return input.substring(peg$savedPos, peg$currPos); | |
| 1928 | } | |
| 1929 | function offset() { | |
| 1930 | return peg$savedPos; | |
| 1931 | } | |
| 1932 | function range() { | |
| 1933 | return { | |
| 1934 | source: peg$source, | |
| 1935 | start: peg$savedPos, | |
| 1936 | end: peg$currPos | |
| 1937 | }; | |
| 1938 | } | |
| 1939 | function location() { | |
| 1940 | return peg$computeLocation(peg$savedPos, peg$currPos); | |
| 1941 | } | |
| 1942 | function expected(description, location2) { | |
| 1943 | location2 = location2 !== void 0 ? location2 : peg$computeLocation(peg$savedPos, peg$currPos); | |
| 1944 | throw peg$buildStructuredError( | |
| 1945 | [peg$otherExpectation(description)], | |
| 1946 | input.substring(peg$savedPos, peg$currPos), | |
| 1947 | location2 | |
| 1948 | ); | |
| 1949 | } | |
| 1950 | function error(message, location2) { | |
| 1951 | location2 = location2 !== void 0 ? location2 : peg$computeLocation(peg$savedPos, peg$currPos); | |
| 1952 | throw peg$buildSimpleError(message, location2); | |
| 1953 | } | |
| 1954 | function peg$literalExpectation(text2, ignoreCase) { | |
| 1955 | return { type: "literal", text: text2, ignoreCase }; | |
| 1956 | } | |
| 1957 | function peg$classExpectation(parts, inverted, ignoreCase) { | |
| 1958 | return { type: "class", parts, inverted, ignoreCase }; | |
| 1959 | } | |
| 1960 | function peg$anyExpectation() { | |
| 1961 | return { type: "any" }; | |
| 1962 | } | |
| 1963 | function peg$endExpectation() { | |
| 1964 | return { type: "end" }; | |
| 1965 | } | |
| 1966 | function peg$otherExpectation(description) { | |
| 1967 | return { type: "other", description }; | |
| 1968 | } | |
| 1969 | function peg$computePosDetails(pos) { | |
| 1970 | var details = peg$posDetailsCache[pos]; | |
| 1971 | var p; | |
| 1972 | if (details) { | |
| 1973 | return details; | |
| 1974 | } else { | |
| 1975 | p = pos - 1; | |
| 1976 | while (!peg$posDetailsCache[p]) { | |
| 1977 | p--; | |
| 1978 | } | |
| 1979 | details = peg$posDetailsCache[p]; | |
| 1980 | details = { | |
| 1981 | line: details.line, | |
| 1982 | column: details.column | |
| 1983 | }; | |
| 1984 | while (p < pos) { | |
| 1985 | if (input.charCodeAt(p) === 10) { | |
| 1986 | details.line++; | |
| 1987 | details.column = 1; | |
| 1988 | } else { | |
| 1989 | details.column++; | |
| 1990 | } | |
| 1991 | p++; | |
| 1992 | } | |
| 1993 | peg$posDetailsCache[pos] = details; | |
| 1994 | return details; | |
| 1995 | } | |
| 1996 | } | |
| 1997 | function peg$computeLocation(startPos, endPos) { | |
| 1998 | var startPosDetails = peg$computePosDetails(startPos); | |
| 1999 | var endPosDetails = peg$computePosDetails(endPos); | |
| 2000 | return { | |
| 2001 | source: peg$source, | |
| 2002 | start: { | |
| 2003 | offset: startPos, | |
| 2004 | line: startPosDetails.line, | |
| 2005 | column: startPosDetails.column | |
| 2006 | }, | |
| 2007 | end: { | |
| 2008 | offset: endPos, | |
| 2009 | line: endPosDetails.line, | |
| 2010 | column: endPosDetails.column | |
| 2011 | } | |
| 2012 | }; | |
| 2013 | } | |
| 2014 | function peg$fail(expected2) { | |
| 2015 | if (peg$currPos < peg$maxFailPos) { | |
| 2016 | return; | |
| 2017 | } | |
| 2018 | if (peg$currPos > peg$maxFailPos) { | |
| 2019 | peg$maxFailPos = peg$currPos; | |
| 2020 | peg$maxFailExpected = []; | |
| 2021 | } | |
| 2022 | peg$maxFailExpected.push(expected2); | |
| 2023 | } | |
| 2024 | function peg$buildSimpleError(message, location2) { | |
| 2025 | return new peg$SyntaxError(message, null, null, location2); | |
| 2026 | } | |
| 2027 | function peg$buildStructuredError(expected2, found, location2) { | |
| 2028 | return new peg$SyntaxError( | |
| 2029 | peg$SyntaxError.buildMessage(expected2, found), | |
| 2030 | expected2, | |
| 2031 | found, | |
| 2032 | location2 | |
| 2033 | ); | |
| 2034 | } | |
| 2035 | function peg$parsestart() { | |
| 2036 | var s0, s1, s2; | |
| 2037 | var key = peg$currPos * 306 + 0; | |
| 2038 | var cached = peg$resultsCache[key]; | |
| 2039 | if (cached) { | |
| 2040 | peg$currPos = cached.nextPos; | |
| 2041 | return cached.result; | |
| 2042 | } | |
| 2043 | s0 = peg$currPos; | |
| 2044 | s1 = peg$parse_(); | |
| 2045 | s2 = peg$parsetranslation_unit(); | |
| 2046 | if (s2 !== peg$FAILED) { | |
| 2047 | peg$savedPos = s0; | |
| 2048 | s0 = peg$f0(s1, s2); | |
| 2049 | } else { | |
| 2050 | peg$currPos = s0; | |
| 2051 | s0 = peg$FAILED; | |
| 2052 | } | |
| 2053 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2054 | return s0; | |
| 2055 | } | |
| 2056 | function peg$parseATTRIBUTE() { | |
| 2057 | var s0, s1, s2; | |
| 2058 | var key = peg$currPos * 306 + 1; | |
| 2059 | var cached = peg$resultsCache[key]; | |
| 2060 | if (cached) { | |
| 2061 | peg$currPos = cached.nextPos; | |
| 2062 | return cached.result; | |
| 2063 | } | |
| 2064 | s0 = peg$currPos; | |
| 2065 | if (input.substr(peg$currPos, 9) === peg$c0) { | |
| 2066 | s1 = peg$c0; | |
| 2067 | peg$currPos += 9; | |
| 2068 | } else { | |
| 2069 | s1 = peg$FAILED; | |
| 2070 | if (peg$silentFails === 0) { | |
| 2071 | peg$fail(peg$e0); | |
| 2072 | } | |
| 2073 | } | |
| 2074 | if (s1 !== peg$FAILED) { | |
| 2075 | s2 = peg$parseterminal(); | |
| 2076 | if (s2 !== peg$FAILED) { | |
| 2077 | peg$savedPos = s0; | |
| 2078 | s0 = peg$f1(s1, s2); | |
| 2079 | } else { | |
| 2080 | peg$currPos = s0; | |
| 2081 | s0 = peg$FAILED; | |
| 2082 | } | |
| 2083 | } else { | |
| 2084 | peg$currPos = s0; | |
| 2085 | s0 = peg$FAILED; | |
| 2086 | } | |
| 2087 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2088 | return s0; | |
| 2089 | } | |
| 2090 | function peg$parseVARYING() { | |
| 2091 | var s0, s1, s2; | |
| 2092 | var key = peg$currPos * 306 + 2; | |
| 2093 | var cached = peg$resultsCache[key]; | |
| 2094 | if (cached) { | |
| 2095 | peg$currPos = cached.nextPos; | |
| 2096 | return cached.result; | |
| 2097 | } | |
| 2098 | s0 = peg$currPos; | |
| 2099 | if (input.substr(peg$currPos, 7) === peg$c1) { | |
| 2100 | s1 = peg$c1; | |
| 2101 | peg$currPos += 7; | |
| 2102 | } else { | |
| 2103 | s1 = peg$FAILED; | |
| 2104 | if (peg$silentFails === 0) { | |
| 2105 | peg$fail(peg$e1); | |
| 2106 | } | |
| 2107 | } | |
| 2108 | if (s1 !== peg$FAILED) { | |
| 2109 | s2 = peg$parseterminal(); | |
| 2110 | if (s2 !== peg$FAILED) { | |
| 2111 | peg$savedPos = s0; | |
| 2112 | s0 = peg$f1(s1, s2); | |
| 2113 | } else { | |
| 2114 | peg$currPos = s0; | |
| 2115 | s0 = peg$FAILED; | |
| 2116 | } | |
| 2117 | } else { | |
| 2118 | peg$currPos = s0; | |
| 2119 | s0 = peg$FAILED; | |
| 2120 | } | |
| 2121 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2122 | return s0; | |
| 2123 | } | |
| 2124 | function peg$parseCONST() { | |
| 2125 | var s0, s1, s2; | |
| 2126 | var key = peg$currPos * 306 + 3; | |
| 2127 | var cached = peg$resultsCache[key]; | |
| 2128 | if (cached) { | |
| 2129 | peg$currPos = cached.nextPos; | |
| 2130 | return cached.result; | |
| 2131 | } | |
| 2132 | s0 = peg$currPos; | |
| 2133 | if (input.substr(peg$currPos, 5) === peg$c2) { | |
| 2134 | s1 = peg$c2; | |
| 2135 | peg$currPos += 5; | |
| 2136 | } else { | |
| 2137 | s1 = peg$FAILED; | |
| 2138 | if (peg$silentFails === 0) { | |
| 2139 | peg$fail(peg$e2); | |
| 2140 | } | |
| 2141 | } | |
| 2142 | if (s1 !== peg$FAILED) { | |
| 2143 | s2 = peg$parseterminal(); | |
| 2144 | if (s2 !== peg$FAILED) { | |
| 2145 | peg$savedPos = s0; | |
| 2146 | s0 = peg$f1(s1, s2); | |
| 2147 | } else { | |
| 2148 | peg$currPos = s0; | |
| 2149 | s0 = peg$FAILED; | |
| 2150 | } | |
| 2151 | } else { | |
| 2152 | peg$currPos = s0; | |
| 2153 | s0 = peg$FAILED; | |
| 2154 | } | |
| 2155 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2156 | return s0; | |
| 2157 | } | |
| 2158 | function peg$parseBOOL() { | |
| 2159 | var s0, s1, s2; | |
| 2160 | var key = peg$currPos * 306 + 4; | |
| 2161 | var cached = peg$resultsCache[key]; | |
| 2162 | if (cached) { | |
| 2163 | peg$currPos = cached.nextPos; | |
| 2164 | return cached.result; | |
| 2165 | } | |
| 2166 | s0 = peg$currPos; | |
| 2167 | if (input.substr(peg$currPos, 4) === peg$c3) { | |
| 2168 | s1 = peg$c3; | |
| 2169 | peg$currPos += 4; | |
| 2170 | } else { | |
| 2171 | s1 = peg$FAILED; | |
| 2172 | if (peg$silentFails === 0) { | |
| 2173 | peg$fail(peg$e3); | |
| 2174 | } | |
| 2175 | } | |
| 2176 | if (s1 !== peg$FAILED) { | |
| 2177 | s2 = peg$parseterminal(); | |
| 2178 | if (s2 !== peg$FAILED) { | |
| 2179 | peg$savedPos = s0; | |
| 2180 | s0 = peg$f1(s1, s2); | |
| 2181 | } else { | |
| 2182 | peg$currPos = s0; | |
| 2183 | s0 = peg$FAILED; | |
| 2184 | } | |
| 2185 | } else { | |
| 2186 | peg$currPos = s0; | |
| 2187 | s0 = peg$FAILED; | |
| 2188 | } | |
| 2189 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2190 | return s0; | |
| 2191 | } | |
| 2192 | function peg$parseFLOAT() { | |
| 2193 | var s0, s1, s2; | |
| 2194 | var key = peg$currPos * 306 + 5; | |
| 2195 | var cached = peg$resultsCache[key]; | |
| 2196 | if (cached) { | |
| 2197 | peg$currPos = cached.nextPos; | |
| 2198 | return cached.result; | |
| 2199 | } | |
| 2200 | s0 = peg$currPos; | |
| 2201 | if (input.substr(peg$currPos, 5) === peg$c4) { | |
| 2202 | s1 = peg$c4; | |
| 2203 | peg$currPos += 5; | |
| 2204 | } else { | |
| 2205 | s1 = peg$FAILED; | |
| 2206 | if (peg$silentFails === 0) { | |
| 2207 | peg$fail(peg$e4); | |
| 2208 | } | |
| 2209 | } | |
| 2210 | if (s1 !== peg$FAILED) { | |
| 2211 | s2 = peg$parseterminal(); | |
| 2212 | if (s2 !== peg$FAILED) { | |
| 2213 | peg$savedPos = s0; | |
| 2214 | s0 = peg$f1(s1, s2); | |
| 2215 | } else { | |
| 2216 | peg$currPos = s0; | |
| 2217 | s0 = peg$FAILED; | |
| 2218 | } | |
| 2219 | } else { | |
| 2220 | peg$currPos = s0; | |
| 2221 | s0 = peg$FAILED; | |
| 2222 | } | |
| 2223 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2224 | return s0; | |
| 2225 | } | |
| 2226 | function peg$parseDOUBLE() { | |
| 2227 | var s0, s1, s2; | |
| 2228 | var key = peg$currPos * 306 + 6; | |
| 2229 | var cached = peg$resultsCache[key]; | |
| 2230 | if (cached) { | |
| 2231 | peg$currPos = cached.nextPos; | |
| 2232 | return cached.result; | |
| 2233 | } | |
| 2234 | s0 = peg$currPos; | |
| 2235 | if (input.substr(peg$currPos, 6) === peg$c5) { | |
| 2236 | s1 = peg$c5; | |
| 2237 | peg$currPos += 6; | |
| 2238 | } else { | |
| 2239 | s1 = peg$FAILED; | |
| 2240 | if (peg$silentFails === 0) { | |
| 2241 | peg$fail(peg$e5); | |
| 2242 | } | |
| 2243 | } | |
| 2244 | if (s1 !== peg$FAILED) { | |
| 2245 | s2 = peg$parseterminal(); | |
| 2246 | if (s2 !== peg$FAILED) { | |
| 2247 | peg$savedPos = s0; | |
| 2248 | s0 = peg$f1(s1, s2); | |
| 2249 | } else { | |
| 2250 | peg$currPos = s0; | |
| 2251 | s0 = peg$FAILED; | |
| 2252 | } | |
| 2253 | } else { | |
| 2254 | peg$currPos = s0; | |
| 2255 | s0 = peg$FAILED; | |
| 2256 | } | |
| 2257 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2258 | return s0; | |
| 2259 | } | |
| 2260 | function peg$parseINT() { | |
| 2261 | var s0, s1, s2; | |
| 2262 | var key = peg$currPos * 306 + 7; | |
| 2263 | var cached = peg$resultsCache[key]; | |
| 2264 | if (cached) { | |
| 2265 | peg$currPos = cached.nextPos; | |
| 2266 | return cached.result; | |
| 2267 | } | |
| 2268 | s0 = peg$currPos; | |
| 2269 | if (input.substr(peg$currPos, 3) === peg$c6) { | |
| 2270 | s1 = peg$c6; | |
| 2271 | peg$currPos += 3; | |
| 2272 | } else { | |
| 2273 | s1 = peg$FAILED; | |
| 2274 | if (peg$silentFails === 0) { | |
| 2275 | peg$fail(peg$e6); | |
| 2276 | } | |
| 2277 | } | |
| 2278 | if (s1 !== peg$FAILED) { | |
| 2279 | s2 = peg$parseterminal(); | |
| 2280 | if (s2 !== peg$FAILED) { | |
| 2281 | peg$savedPos = s0; | |
| 2282 | s0 = peg$f1(s1, s2); | |
| 2283 | } else { | |
| 2284 | peg$currPos = s0; | |
| 2285 | s0 = peg$FAILED; | |
| 2286 | } | |
| 2287 | } else { | |
| 2288 | peg$currPos = s0; | |
| 2289 | s0 = peg$FAILED; | |
| 2290 | } | |
| 2291 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2292 | return s0; | |
| 2293 | } | |
| 2294 | function peg$parseUINT() { | |
| 2295 | var s0, s1, s2; | |
| 2296 | var key = peg$currPos * 306 + 8; | |
| 2297 | var cached = peg$resultsCache[key]; | |
| 2298 | if (cached) { | |
| 2299 | peg$currPos = cached.nextPos; | |
| 2300 | return cached.result; | |
| 2301 | } | |
| 2302 | s0 = peg$currPos; | |
| 2303 | if (input.substr(peg$currPos, 4) === peg$c7) { | |
| 2304 | s1 = peg$c7; | |
| 2305 | peg$currPos += 4; | |
| 2306 | } else { | |
| 2307 | s1 = peg$FAILED; | |
| 2308 | if (peg$silentFails === 0) { | |
| 2309 | peg$fail(peg$e7); | |
| 2310 | } | |
| 2311 | } | |
| 2312 | if (s1 !== peg$FAILED) { | |
| 2313 | s2 = peg$parseterminal(); | |
| 2314 | if (s2 !== peg$FAILED) { | |
| 2315 | peg$savedPos = s0; | |
| 2316 | s0 = peg$f1(s1, s2); | |
| 2317 | } else { | |
| 2318 | peg$currPos = s0; | |
| 2319 | s0 = peg$FAILED; | |
| 2320 | } | |
| 2321 | } else { | |
| 2322 | peg$currPos = s0; | |
| 2323 | s0 = peg$FAILED; | |
| 2324 | } | |
| 2325 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2326 | return s0; | |
| 2327 | } | |
| 2328 | function peg$parseBREAK() { | |
| 2329 | var s0, s1, s2; | |
| 2330 | var key = peg$currPos * 306 + 9; | |
| 2331 | var cached = peg$resultsCache[key]; | |
| 2332 | if (cached) { | |
| 2333 | peg$currPos = cached.nextPos; | |
| 2334 | return cached.result; | |
| 2335 | } | |
| 2336 | s0 = peg$currPos; | |
| 2337 | if (input.substr(peg$currPos, 5) === peg$c8) { | |
| 2338 | s1 = peg$c8; | |
| 2339 | peg$currPos += 5; | |
| 2340 | } else { | |
| 2341 | s1 = peg$FAILED; | |
| 2342 | if (peg$silentFails === 0) { | |
| 2343 | peg$fail(peg$e8); | |
| 2344 | } | |
| 2345 | } | |
| 2346 | if (s1 !== peg$FAILED) { | |
| 2347 | s2 = peg$parseterminal(); | |
| 2348 | if (s2 !== peg$FAILED) { | |
| 2349 | peg$savedPos = s0; | |
| 2350 | s0 = peg$f1(s1, s2); | |
| 2351 | } else { | |
| 2352 | peg$currPos = s0; | |
| 2353 | s0 = peg$FAILED; | |
| 2354 | } | |
| 2355 | } else { | |
| 2356 | peg$currPos = s0; | |
| 2357 | s0 = peg$FAILED; | |
| 2358 | } | |
| 2359 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2360 | return s0; | |
| 2361 | } | |
| 2362 | function peg$parseCONTINUE() { | |
| 2363 | var s0, s1, s2; | |
| 2364 | var key = peg$currPos * 306 + 10; | |
| 2365 | var cached = peg$resultsCache[key]; | |
| 2366 | if (cached) { | |
| 2367 | peg$currPos = cached.nextPos; | |
| 2368 | return cached.result; | |
| 2369 | } | |
| 2370 | s0 = peg$currPos; | |
| 2371 | if (input.substr(peg$currPos, 8) === peg$c9) { | |
| 2372 | s1 = peg$c9; | |
| 2373 | peg$currPos += 8; | |
| 2374 | } else { | |
| 2375 | s1 = peg$FAILED; | |
| 2376 | if (peg$silentFails === 0) { | |
| 2377 | peg$fail(peg$e9); | |
| 2378 | } | |
| 2379 | } | |
| 2380 | if (s1 !== peg$FAILED) { | |
| 2381 | s2 = peg$parseterminal(); | |
| 2382 | if (s2 !== peg$FAILED) { | |
| 2383 | peg$savedPos = s0; | |
| 2384 | s0 = peg$f1(s1, s2); | |
| 2385 | } else { | |
| 2386 | peg$currPos = s0; | |
| 2387 | s0 = peg$FAILED; | |
| 2388 | } | |
| 2389 | } else { | |
| 2390 | peg$currPos = s0; | |
| 2391 | s0 = peg$FAILED; | |
| 2392 | } | |
| 2393 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2394 | return s0; | |
| 2395 | } | |
| 2396 | function peg$parseDO() { | |
| 2397 | var s0, s1, s2; | |
| 2398 | var key = peg$currPos * 306 + 11; | |
| 2399 | var cached = peg$resultsCache[key]; | |
| 2400 | if (cached) { | |
| 2401 | peg$currPos = cached.nextPos; | |
| 2402 | return cached.result; | |
| 2403 | } | |
| 2404 | s0 = peg$currPos; | |
| 2405 | if (input.substr(peg$currPos, 2) === peg$c10) { | |
| 2406 | s1 = peg$c10; | |
| 2407 | peg$currPos += 2; | |
| 2408 | } else { | |
| 2409 | s1 = peg$FAILED; | |
| 2410 | if (peg$silentFails === 0) { | |
| 2411 | peg$fail(peg$e10); | |
| 2412 | } | |
| 2413 | } | |
| 2414 | if (s1 !== peg$FAILED) { | |
| 2415 | s2 = peg$parseterminal(); | |
| 2416 | if (s2 !== peg$FAILED) { | |
| 2417 | peg$savedPos = s0; | |
| 2418 | s0 = peg$f1(s1, s2); | |
| 2419 | } else { | |
| 2420 | peg$currPos = s0; | |
| 2421 | s0 = peg$FAILED; | |
| 2422 | } | |
| 2423 | } else { | |
| 2424 | peg$currPos = s0; | |
| 2425 | s0 = peg$FAILED; | |
| 2426 | } | |
| 2427 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2428 | return s0; | |
| 2429 | } | |
| 2430 | function peg$parseELSE() { | |
| 2431 | var s0, s1, s2; | |
| 2432 | var key = peg$currPos * 306 + 12; | |
| 2433 | var cached = peg$resultsCache[key]; | |
| 2434 | if (cached) { | |
| 2435 | peg$currPos = cached.nextPos; | |
| 2436 | return cached.result; | |
| 2437 | } | |
| 2438 | s0 = peg$currPos; | |
| 2439 | if (input.substr(peg$currPos, 4) === peg$c11) { | |
| 2440 | s1 = peg$c11; | |
| 2441 | peg$currPos += 4; | |
| 2442 | } else { | |
| 2443 | s1 = peg$FAILED; | |
| 2444 | if (peg$silentFails === 0) { | |
| 2445 | peg$fail(peg$e11); | |
| 2446 | } | |
| 2447 | } | |
| 2448 | if (s1 !== peg$FAILED) { | |
| 2449 | s2 = peg$parseterminal(); | |
| 2450 | if (s2 !== peg$FAILED) { | |
| 2451 | peg$savedPos = s0; | |
| 2452 | s0 = peg$f1(s1, s2); | |
| 2453 | } else { | |
| 2454 | peg$currPos = s0; | |
| 2455 | s0 = peg$FAILED; | |
| 2456 | } | |
| 2457 | } else { | |
| 2458 | peg$currPos = s0; | |
| 2459 | s0 = peg$FAILED; | |
| 2460 | } | |
| 2461 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2462 | return s0; | |
| 2463 | } | |
| 2464 | function peg$parseFOR() { | |
| 2465 | var s0, s1, s2; | |
| 2466 | var key = peg$currPos * 306 + 13; | |
| 2467 | var cached = peg$resultsCache[key]; | |
| 2468 | if (cached) { | |
| 2469 | peg$currPos = cached.nextPos; | |
| 2470 | return cached.result; | |
| 2471 | } | |
| 2472 | s0 = peg$currPos; | |
| 2473 | if (input.substr(peg$currPos, 3) === peg$c12) { | |
| 2474 | s1 = peg$c12; | |
| 2475 | peg$currPos += 3; | |
| 2476 | } else { | |
| 2477 | s1 = peg$FAILED; | |
| 2478 | if (peg$silentFails === 0) { | |
| 2479 | peg$fail(peg$e12); | |
| 2480 | } | |
| 2481 | } | |
| 2482 | if (s1 !== peg$FAILED) { | |
| 2483 | s2 = peg$parseterminal(); | |
| 2484 | if (s2 !== peg$FAILED) { | |
| 2485 | peg$savedPos = s0; | |
| 2486 | s0 = peg$f1(s1, s2); | |
| 2487 | } else { | |
| 2488 | peg$currPos = s0; | |
| 2489 | s0 = peg$FAILED; | |
| 2490 | } | |
| 2491 | } else { | |
| 2492 | peg$currPos = s0; | |
| 2493 | s0 = peg$FAILED; | |
| 2494 | } | |
| 2495 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2496 | return s0; | |
| 2497 | } | |
| 2498 | function peg$parseIF() { | |
| 2499 | var s0, s1, s2; | |
| 2500 | var key = peg$currPos * 306 + 14; | |
| 2501 | var cached = peg$resultsCache[key]; | |
| 2502 | if (cached) { | |
| 2503 | peg$currPos = cached.nextPos; | |
| 2504 | return cached.result; | |
| 2505 | } | |
| 2506 | s0 = peg$currPos; | |
| 2507 | if (input.substr(peg$currPos, 2) === peg$c13) { | |
| 2508 | s1 = peg$c13; | |
| 2509 | peg$currPos += 2; | |
| 2510 | } else { | |
| 2511 | s1 = peg$FAILED; | |
| 2512 | if (peg$silentFails === 0) { | |
| 2513 | peg$fail(peg$e13); | |
| 2514 | } | |
| 2515 | } | |
| 2516 | if (s1 !== peg$FAILED) { | |
| 2517 | s2 = peg$parseterminal(); | |
| 2518 | if (s2 !== peg$FAILED) { | |
| 2519 | peg$savedPos = s0; | |
| 2520 | s0 = peg$f1(s1, s2); | |
| 2521 | } else { | |
| 2522 | peg$currPos = s0; | |
| 2523 | s0 = peg$FAILED; | |
| 2524 | } | |
| 2525 | } else { | |
| 2526 | peg$currPos = s0; | |
| 2527 | s0 = peg$FAILED; | |
| 2528 | } | |
| 2529 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2530 | return s0; | |
| 2531 | } | |
| 2532 | function peg$parseDISCARD() { | |
| 2533 | var s0, s1, s2; | |
| 2534 | var key = peg$currPos * 306 + 15; | |
| 2535 | var cached = peg$resultsCache[key]; | |
| 2536 | if (cached) { | |
| 2537 | peg$currPos = cached.nextPos; | |
| 2538 | return cached.result; | |
| 2539 | } | |
| 2540 | s0 = peg$currPos; | |
| 2541 | if (input.substr(peg$currPos, 7) === peg$c14) { | |
| 2542 | s1 = peg$c14; | |
| 2543 | peg$currPos += 7; | |
| 2544 | } else { | |
| 2545 | s1 = peg$FAILED; | |
| 2546 | if (peg$silentFails === 0) { | |
| 2547 | peg$fail(peg$e14); | |
| 2548 | } | |
| 2549 | } | |
| 2550 | if (s1 !== peg$FAILED) { | |
| 2551 | s2 = peg$parseterminal(); | |
| 2552 | if (s2 !== peg$FAILED) { | |
| 2553 | peg$savedPos = s0; | |
| 2554 | s0 = peg$f1(s1, s2); | |
| 2555 | } else { | |
| 2556 | peg$currPos = s0; | |
| 2557 | s0 = peg$FAILED; | |
| 2558 | } | |
| 2559 | } else { | |
| 2560 | peg$currPos = s0; | |
| 2561 | s0 = peg$FAILED; | |
| 2562 | } | |
| 2563 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2564 | return s0; | |
| 2565 | } | |
| 2566 | function peg$parseRETURN() { | |
| 2567 | var s0, s1, s2; | |
| 2568 | var key = peg$currPos * 306 + 16; | |
| 2569 | var cached = peg$resultsCache[key]; | |
| 2570 | if (cached) { | |
| 2571 | peg$currPos = cached.nextPos; | |
| 2572 | return cached.result; | |
| 2573 | } | |
| 2574 | s0 = peg$currPos; | |
| 2575 | if (input.substr(peg$currPos, 6) === peg$c15) { | |
| 2576 | s1 = peg$c15; | |
| 2577 | peg$currPos += 6; | |
| 2578 | } else { | |
| 2579 | s1 = peg$FAILED; | |
| 2580 | if (peg$silentFails === 0) { | |
| 2581 | peg$fail(peg$e15); | |
| 2582 | } | |
| 2583 | } | |
| 2584 | if (s1 !== peg$FAILED) { | |
| 2585 | s2 = peg$parseterminal(); | |
| 2586 | if (s2 !== peg$FAILED) { | |
| 2587 | peg$savedPos = s0; | |
| 2588 | s0 = peg$f1(s1, s2); | |
| 2589 | } else { | |
| 2590 | peg$currPos = s0; | |
| 2591 | s0 = peg$FAILED; | |
| 2592 | } | |
| 2593 | } else { | |
| 2594 | peg$currPos = s0; | |
| 2595 | s0 = peg$FAILED; | |
| 2596 | } | |
| 2597 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2598 | return s0; | |
| 2599 | } | |
| 2600 | function peg$parseSWITCH() { | |
| 2601 | var s0, s1, s2; | |
| 2602 | var key = peg$currPos * 306 + 17; | |
| 2603 | var cached = peg$resultsCache[key]; | |
| 2604 | if (cached) { | |
| 2605 | peg$currPos = cached.nextPos; | |
| 2606 | return cached.result; | |
| 2607 | } | |
| 2608 | s0 = peg$currPos; | |
| 2609 | if (input.substr(peg$currPos, 6) === peg$c16) { | |
| 2610 | s1 = peg$c16; | |
| 2611 | peg$currPos += 6; | |
| 2612 | } else { | |
| 2613 | s1 = peg$FAILED; | |
| 2614 | if (peg$silentFails === 0) { | |
| 2615 | peg$fail(peg$e16); | |
| 2616 | } | |
| 2617 | } | |
| 2618 | if (s1 !== peg$FAILED) { | |
| 2619 | s2 = peg$parseterminal(); | |
| 2620 | if (s2 !== peg$FAILED) { | |
| 2621 | peg$savedPos = s0; | |
| 2622 | s0 = peg$f1(s1, s2); | |
| 2623 | } else { | |
| 2624 | peg$currPos = s0; | |
| 2625 | s0 = peg$FAILED; | |
| 2626 | } | |
| 2627 | } else { | |
| 2628 | peg$currPos = s0; | |
| 2629 | s0 = peg$FAILED; | |
| 2630 | } | |
| 2631 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2632 | return s0; | |
| 2633 | } | |
| 2634 | function peg$parseCASE() { | |
| 2635 | var s0, s1, s2; | |
| 2636 | var key = peg$currPos * 306 + 18; | |
| 2637 | var cached = peg$resultsCache[key]; | |
| 2638 | if (cached) { | |
| 2639 | peg$currPos = cached.nextPos; | |
| 2640 | return cached.result; | |
| 2641 | } | |
| 2642 | s0 = peg$currPos; | |
| 2643 | if (input.substr(peg$currPos, 4) === peg$c17) { | |
| 2644 | s1 = peg$c17; | |
| 2645 | peg$currPos += 4; | |
| 2646 | } else { | |
| 2647 | s1 = peg$FAILED; | |
| 2648 | if (peg$silentFails === 0) { | |
| 2649 | peg$fail(peg$e17); | |
| 2650 | } | |
| 2651 | } | |
| 2652 | if (s1 !== peg$FAILED) { | |
| 2653 | s2 = peg$parseterminal(); | |
| 2654 | if (s2 !== peg$FAILED) { | |
| 2655 | peg$savedPos = s0; | |
| 2656 | s0 = peg$f1(s1, s2); | |
| 2657 | } else { | |
| 2658 | peg$currPos = s0; | |
| 2659 | s0 = peg$FAILED; | |
| 2660 | } | |
| 2661 | } else { | |
| 2662 | peg$currPos = s0; | |
| 2663 | s0 = peg$FAILED; | |
| 2664 | } | |
| 2665 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2666 | return s0; | |
| 2667 | } | |
| 2668 | function peg$parseDEFAULT() { | |
| 2669 | var s0, s1, s2; | |
| 2670 | var key = peg$currPos * 306 + 19; | |
| 2671 | var cached = peg$resultsCache[key]; | |
| 2672 | if (cached) { | |
| 2673 | peg$currPos = cached.nextPos; | |
| 2674 | return cached.result; | |
| 2675 | } | |
| 2676 | s0 = peg$currPos; | |
| 2677 | if (input.substr(peg$currPos, 7) === peg$c18) { | |
| 2678 | s1 = peg$c18; | |
| 2679 | peg$currPos += 7; | |
| 2680 | } else { | |
| 2681 | s1 = peg$FAILED; | |
| 2682 | if (peg$silentFails === 0) { | |
| 2683 | peg$fail(peg$e18); | |
| 2684 | } | |
| 2685 | } | |
| 2686 | if (s1 !== peg$FAILED) { | |
| 2687 | s2 = peg$parseterminal(); | |
| 2688 | if (s2 !== peg$FAILED) { | |
| 2689 | peg$savedPos = s0; | |
| 2690 | s0 = peg$f1(s1, s2); | |
| 2691 | } else { | |
| 2692 | peg$currPos = s0; | |
| 2693 | s0 = peg$FAILED; | |
| 2694 | } | |
| 2695 | } else { | |
| 2696 | peg$currPos = s0; | |
| 2697 | s0 = peg$FAILED; | |
| 2698 | } | |
| 2699 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2700 | return s0; | |
| 2701 | } | |
| 2702 | function peg$parseSUBROUTINE() { | |
| 2703 | var s0, s1, s2; | |
| 2704 | var key = peg$currPos * 306 + 20; | |
| 2705 | var cached = peg$resultsCache[key]; | |
| 2706 | if (cached) { | |
| 2707 | peg$currPos = cached.nextPos; | |
| 2708 | return cached.result; | |
| 2709 | } | |
| 2710 | s0 = peg$currPos; | |
| 2711 | if (input.substr(peg$currPos, 10) === peg$c19) { | |
| 2712 | s1 = peg$c19; | |
| 2713 | peg$currPos += 10; | |
| 2714 | } else { | |
| 2715 | s1 = peg$FAILED; | |
| 2716 | if (peg$silentFails === 0) { | |
| 2717 | peg$fail(peg$e19); | |
| 2718 | } | |
| 2719 | } | |
| 2720 | if (s1 !== peg$FAILED) { | |
| 2721 | s2 = peg$parseterminal(); | |
| 2722 | if (s2 !== peg$FAILED) { | |
| 2723 | peg$savedPos = s0; | |
| 2724 | s0 = peg$f1(s1, s2); | |
| 2725 | } else { | |
| 2726 | peg$currPos = s0; | |
| 2727 | s0 = peg$FAILED; | |
| 2728 | } | |
| 2729 | } else { | |
| 2730 | peg$currPos = s0; | |
| 2731 | s0 = peg$FAILED; | |
| 2732 | } | |
| 2733 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2734 | return s0; | |
| 2735 | } | |
| 2736 | function peg$parseBVEC2() { | |
| 2737 | var s0, s1, s2; | |
| 2738 | var key = peg$currPos * 306 + 21; | |
| 2739 | var cached = peg$resultsCache[key]; | |
| 2740 | if (cached) { | |
| 2741 | peg$currPos = cached.nextPos; | |
| 2742 | return cached.result; | |
| 2743 | } | |
| 2744 | s0 = peg$currPos; | |
| 2745 | if (input.substr(peg$currPos, 5) === peg$c20) { | |
| 2746 | s1 = peg$c20; | |
| 2747 | peg$currPos += 5; | |
| 2748 | } else { | |
| 2749 | s1 = peg$FAILED; | |
| 2750 | if (peg$silentFails === 0) { | |
| 2751 | peg$fail(peg$e20); | |
| 2752 | } | |
| 2753 | } | |
| 2754 | if (s1 !== peg$FAILED) { | |
| 2755 | s2 = peg$parseterminal(); | |
| 2756 | if (s2 !== peg$FAILED) { | |
| 2757 | peg$savedPos = s0; | |
| 2758 | s0 = peg$f1(s1, s2); | |
| 2759 | } else { | |
| 2760 | peg$currPos = s0; | |
| 2761 | s0 = peg$FAILED; | |
| 2762 | } | |
| 2763 | } else { | |
| 2764 | peg$currPos = s0; | |
| 2765 | s0 = peg$FAILED; | |
| 2766 | } | |
| 2767 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2768 | return s0; | |
| 2769 | } | |
| 2770 | function peg$parseBVEC3() { | |
| 2771 | var s0, s1, s2; | |
| 2772 | var key = peg$currPos * 306 + 22; | |
| 2773 | var cached = peg$resultsCache[key]; | |
| 2774 | if (cached) { | |
| 2775 | peg$currPos = cached.nextPos; | |
| 2776 | return cached.result; | |
| 2777 | } | |
| 2778 | s0 = peg$currPos; | |
| 2779 | if (input.substr(peg$currPos, 5) === peg$c21) { | |
| 2780 | s1 = peg$c21; | |
| 2781 | peg$currPos += 5; | |
| 2782 | } else { | |
| 2783 | s1 = peg$FAILED; | |
| 2784 | if (peg$silentFails === 0) { | |
| 2785 | peg$fail(peg$e21); | |
| 2786 | } | |
| 2787 | } | |
| 2788 | if (s1 !== peg$FAILED) { | |
| 2789 | s2 = peg$parseterminal(); | |
| 2790 | if (s2 !== peg$FAILED) { | |
| 2791 | peg$savedPos = s0; | |
| 2792 | s0 = peg$f1(s1, s2); | |
| 2793 | } else { | |
| 2794 | peg$currPos = s0; | |
| 2795 | s0 = peg$FAILED; | |
| 2796 | } | |
| 2797 | } else { | |
| 2798 | peg$currPos = s0; | |
| 2799 | s0 = peg$FAILED; | |
| 2800 | } | |
| 2801 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2802 | return s0; | |
| 2803 | } | |
| 2804 | function peg$parseBVEC4() { | |
| 2805 | var s0, s1, s2; | |
| 2806 | var key = peg$currPos * 306 + 23; | |
| 2807 | var cached = peg$resultsCache[key]; | |
| 2808 | if (cached) { | |
| 2809 | peg$currPos = cached.nextPos; | |
| 2810 | return cached.result; | |
| 2811 | } | |
| 2812 | s0 = peg$currPos; | |
| 2813 | if (input.substr(peg$currPos, 5) === peg$c22) { | |
| 2814 | s1 = peg$c22; | |
| 2815 | peg$currPos += 5; | |
| 2816 | } else { | |
| 2817 | s1 = peg$FAILED; | |
| 2818 | if (peg$silentFails === 0) { | |
| 2819 | peg$fail(peg$e22); | |
| 2820 | } | |
| 2821 | } | |
| 2822 | if (s1 !== peg$FAILED) { | |
| 2823 | s2 = peg$parseterminal(); | |
| 2824 | if (s2 !== peg$FAILED) { | |
| 2825 | peg$savedPos = s0; | |
| 2826 | s0 = peg$f1(s1, s2); | |
| 2827 | } else { | |
| 2828 | peg$currPos = s0; | |
| 2829 | s0 = peg$FAILED; | |
| 2830 | } | |
| 2831 | } else { | |
| 2832 | peg$currPos = s0; | |
| 2833 | s0 = peg$FAILED; | |
| 2834 | } | |
| 2835 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2836 | return s0; | |
| 2837 | } | |
| 2838 | function peg$parseIVEC2() { | |
| 2839 | var s0, s1, s2; | |
| 2840 | var key = peg$currPos * 306 + 24; | |
| 2841 | var cached = peg$resultsCache[key]; | |
| 2842 | if (cached) { | |
| 2843 | peg$currPos = cached.nextPos; | |
| 2844 | return cached.result; | |
| 2845 | } | |
| 2846 | s0 = peg$currPos; | |
| 2847 | if (input.substr(peg$currPos, 5) === peg$c23) { | |
| 2848 | s1 = peg$c23; | |
| 2849 | peg$currPos += 5; | |
| 2850 | } else { | |
| 2851 | s1 = peg$FAILED; | |
| 2852 | if (peg$silentFails === 0) { | |
| 2853 | peg$fail(peg$e23); | |
| 2854 | } | |
| 2855 | } | |
| 2856 | if (s1 !== peg$FAILED) { | |
| 2857 | s2 = peg$parseterminal(); | |
| 2858 | if (s2 !== peg$FAILED) { | |
| 2859 | peg$savedPos = s0; | |
| 2860 | s0 = peg$f1(s1, s2); | |
| 2861 | } else { | |
| 2862 | peg$currPos = s0; | |
| 2863 | s0 = peg$FAILED; | |
| 2864 | } | |
| 2865 | } else { | |
| 2866 | peg$currPos = s0; | |
| 2867 | s0 = peg$FAILED; | |
| 2868 | } | |
| 2869 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2870 | return s0; | |
| 2871 | } | |
| 2872 | function peg$parseIVEC3() { | |
| 2873 | var s0, s1, s2; | |
| 2874 | var key = peg$currPos * 306 + 25; | |
| 2875 | var cached = peg$resultsCache[key]; | |
| 2876 | if (cached) { | |
| 2877 | peg$currPos = cached.nextPos; | |
| 2878 | return cached.result; | |
| 2879 | } | |
| 2880 | s0 = peg$currPos; | |
| 2881 | if (input.substr(peg$currPos, 5) === peg$c24) { | |
| 2882 | s1 = peg$c24; | |
| 2883 | peg$currPos += 5; | |
| 2884 | } else { | |
| 2885 | s1 = peg$FAILED; | |
| 2886 | if (peg$silentFails === 0) { | |
| 2887 | peg$fail(peg$e24); | |
| 2888 | } | |
| 2889 | } | |
| 2890 | if (s1 !== peg$FAILED) { | |
| 2891 | s2 = peg$parseterminal(); | |
| 2892 | if (s2 !== peg$FAILED) { | |
| 2893 | peg$savedPos = s0; | |
| 2894 | s0 = peg$f1(s1, s2); | |
| 2895 | } else { | |
| 2896 | peg$currPos = s0; | |
| 2897 | s0 = peg$FAILED; | |
| 2898 | } | |
| 2899 | } else { | |
| 2900 | peg$currPos = s0; | |
| 2901 | s0 = peg$FAILED; | |
| 2902 | } | |
| 2903 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2904 | return s0; | |
| 2905 | } | |
| 2906 | function peg$parseIVEC4() { | |
| 2907 | var s0, s1, s2; | |
| 2908 | var key = peg$currPos * 306 + 26; | |
| 2909 | var cached = peg$resultsCache[key]; | |
| 2910 | if (cached) { | |
| 2911 | peg$currPos = cached.nextPos; | |
| 2912 | return cached.result; | |
| 2913 | } | |
| 2914 | s0 = peg$currPos; | |
| 2915 | if (input.substr(peg$currPos, 5) === peg$c25) { | |
| 2916 | s1 = peg$c25; | |
| 2917 | peg$currPos += 5; | |
| 2918 | } else { | |
| 2919 | s1 = peg$FAILED; | |
| 2920 | if (peg$silentFails === 0) { | |
| 2921 | peg$fail(peg$e25); | |
| 2922 | } | |
| 2923 | } | |
| 2924 | if (s1 !== peg$FAILED) { | |
| 2925 | s2 = peg$parseterminal(); | |
| 2926 | if (s2 !== peg$FAILED) { | |
| 2927 | peg$savedPos = s0; | |
| 2928 | s0 = peg$f1(s1, s2); | |
| 2929 | } else { | |
| 2930 | peg$currPos = s0; | |
| 2931 | s0 = peg$FAILED; | |
| 2932 | } | |
| 2933 | } else { | |
| 2934 | peg$currPos = s0; | |
| 2935 | s0 = peg$FAILED; | |
| 2936 | } | |
| 2937 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2938 | return s0; | |
| 2939 | } | |
| 2940 | function peg$parseUVEC2() { | |
| 2941 | var s0, s1, s2; | |
| 2942 | var key = peg$currPos * 306 + 27; | |
| 2943 | var cached = peg$resultsCache[key]; | |
| 2944 | if (cached) { | |
| 2945 | peg$currPos = cached.nextPos; | |
| 2946 | return cached.result; | |
| 2947 | } | |
| 2948 | s0 = peg$currPos; | |
| 2949 | if (input.substr(peg$currPos, 5) === peg$c26) { | |
| 2950 | s1 = peg$c26; | |
| 2951 | peg$currPos += 5; | |
| 2952 | } else { | |
| 2953 | s1 = peg$FAILED; | |
| 2954 | if (peg$silentFails === 0) { | |
| 2955 | peg$fail(peg$e26); | |
| 2956 | } | |
| 2957 | } | |
| 2958 | if (s1 !== peg$FAILED) { | |
| 2959 | s2 = peg$parseterminal(); | |
| 2960 | if (s2 !== peg$FAILED) { | |
| 2961 | peg$savedPos = s0; | |
| 2962 | s0 = peg$f1(s1, s2); | |
| 2963 | } else { | |
| 2964 | peg$currPos = s0; | |
| 2965 | s0 = peg$FAILED; | |
| 2966 | } | |
| 2967 | } else { | |
| 2968 | peg$currPos = s0; | |
| 2969 | s0 = peg$FAILED; | |
| 2970 | } | |
| 2971 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 2972 | return s0; | |
| 2973 | } | |
| 2974 | function peg$parseUVEC3() { | |
| 2975 | var s0, s1, s2; | |
| 2976 | var key = peg$currPos * 306 + 28; | |
| 2977 | var cached = peg$resultsCache[key]; | |
| 2978 | if (cached) { | |
| 2979 | peg$currPos = cached.nextPos; | |
| 2980 | return cached.result; | |
| 2981 | } | |
| 2982 | s0 = peg$currPos; | |
| 2983 | if (input.substr(peg$currPos, 5) === peg$c27) { | |
| 2984 | s1 = peg$c27; | |
| 2985 | peg$currPos += 5; | |
| 2986 | } else { | |
| 2987 | s1 = peg$FAILED; | |
| 2988 | if (peg$silentFails === 0) { | |
| 2989 | peg$fail(peg$e27); | |
| 2990 | } | |
| 2991 | } | |
| 2992 | if (s1 !== peg$FAILED) { | |
| 2993 | s2 = peg$parseterminal(); | |
| 2994 | if (s2 !== peg$FAILED) { | |
| 2995 | peg$savedPos = s0; | |
| 2996 | s0 = peg$f1(s1, s2); | |
| 2997 | } else { | |
| 2998 | peg$currPos = s0; | |
| 2999 | s0 = peg$FAILED; | |
| 3000 | } | |
| 3001 | } else { | |
| 3002 | peg$currPos = s0; | |
| 3003 | s0 = peg$FAILED; | |
| 3004 | } | |
| 3005 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3006 | return s0; | |
| 3007 | } | |
| 3008 | function peg$parseUVEC4() { | |
| 3009 | var s0, s1, s2; | |
| 3010 | var key = peg$currPos * 306 + 29; | |
| 3011 | var cached = peg$resultsCache[key]; | |
| 3012 | if (cached) { | |
| 3013 | peg$currPos = cached.nextPos; | |
| 3014 | return cached.result; | |
| 3015 | } | |
| 3016 | s0 = peg$currPos; | |
| 3017 | if (input.substr(peg$currPos, 5) === peg$c28) { | |
| 3018 | s1 = peg$c28; | |
| 3019 | peg$currPos += 5; | |
| 3020 | } else { | |
| 3021 | s1 = peg$FAILED; | |
| 3022 | if (peg$silentFails === 0) { | |
| 3023 | peg$fail(peg$e28); | |
| 3024 | } | |
| 3025 | } | |
| 3026 | if (s1 !== peg$FAILED) { | |
| 3027 | s2 = peg$parseterminal(); | |
| 3028 | if (s2 !== peg$FAILED) { | |
| 3029 | peg$savedPos = s0; | |
| 3030 | s0 = peg$f1(s1, s2); | |
| 3031 | } else { | |
| 3032 | peg$currPos = s0; | |
| 3033 | s0 = peg$FAILED; | |
| 3034 | } | |
| 3035 | } else { | |
| 3036 | peg$currPos = s0; | |
| 3037 | s0 = peg$FAILED; | |
| 3038 | } | |
| 3039 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3040 | return s0; | |
| 3041 | } | |
| 3042 | function peg$parseVEC2() { | |
| 3043 | var s0, s1, s2; | |
| 3044 | var key = peg$currPos * 306 + 30; | |
| 3045 | var cached = peg$resultsCache[key]; | |
| 3046 | if (cached) { | |
| 3047 | peg$currPos = cached.nextPos; | |
| 3048 | return cached.result; | |
| 3049 | } | |
| 3050 | s0 = peg$currPos; | |
| 3051 | if (input.substr(peg$currPos, 4) === peg$c29) { | |
| 3052 | s1 = peg$c29; | |
| 3053 | peg$currPos += 4; | |
| 3054 | } else { | |
| 3055 | s1 = peg$FAILED; | |
| 3056 | if (peg$silentFails === 0) { | |
| 3057 | peg$fail(peg$e29); | |
| 3058 | } | |
| 3059 | } | |
| 3060 | if (s1 !== peg$FAILED) { | |
| 3061 | s2 = peg$parseterminal(); | |
| 3062 | if (s2 !== peg$FAILED) { | |
| 3063 | peg$savedPos = s0; | |
| 3064 | s0 = peg$f1(s1, s2); | |
| 3065 | } else { | |
| 3066 | peg$currPos = s0; | |
| 3067 | s0 = peg$FAILED; | |
| 3068 | } | |
| 3069 | } else { | |
| 3070 | peg$currPos = s0; | |
| 3071 | s0 = peg$FAILED; | |
| 3072 | } | |
| 3073 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3074 | return s0; | |
| 3075 | } | |
| 3076 | function peg$parseVEC3() { | |
| 3077 | var s0, s1, s2; | |
| 3078 | var key = peg$currPos * 306 + 31; | |
| 3079 | var cached = peg$resultsCache[key]; | |
| 3080 | if (cached) { | |
| 3081 | peg$currPos = cached.nextPos; | |
| 3082 | return cached.result; | |
| 3083 | } | |
| 3084 | s0 = peg$currPos; | |
| 3085 | if (input.substr(peg$currPos, 4) === peg$c30) { | |
| 3086 | s1 = peg$c30; | |
| 3087 | peg$currPos += 4; | |
| 3088 | } else { | |
| 3089 | s1 = peg$FAILED; | |
| 3090 | if (peg$silentFails === 0) { | |
| 3091 | peg$fail(peg$e30); | |
| 3092 | } | |
| 3093 | } | |
| 3094 | if (s1 !== peg$FAILED) { | |
| 3095 | s2 = peg$parseterminal(); | |
| 3096 | if (s2 !== peg$FAILED) { | |
| 3097 | peg$savedPos = s0; | |
| 3098 | s0 = peg$f1(s1, s2); | |
| 3099 | } else { | |
| 3100 | peg$currPos = s0; | |
| 3101 | s0 = peg$FAILED; | |
| 3102 | } | |
| 3103 | } else { | |
| 3104 | peg$currPos = s0; | |
| 3105 | s0 = peg$FAILED; | |
| 3106 | } | |
| 3107 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3108 | return s0; | |
| 3109 | } | |
| 3110 | function peg$parseVEC4() { | |
| 3111 | var s0, s1, s2; | |
| 3112 | var key = peg$currPos * 306 + 32; | |
| 3113 | var cached = peg$resultsCache[key]; | |
| 3114 | if (cached) { | |
| 3115 | peg$currPos = cached.nextPos; | |
| 3116 | return cached.result; | |
| 3117 | } | |
| 3118 | s0 = peg$currPos; | |
| 3119 | if (input.substr(peg$currPos, 4) === peg$c31) { | |
| 3120 | s1 = peg$c31; | |
| 3121 | peg$currPos += 4; | |
| 3122 | } else { | |
| 3123 | s1 = peg$FAILED; | |
| 3124 | if (peg$silentFails === 0) { | |
| 3125 | peg$fail(peg$e31); | |
| 3126 | } | |
| 3127 | } | |
| 3128 | if (s1 !== peg$FAILED) { | |
| 3129 | s2 = peg$parseterminal(); | |
| 3130 | if (s2 !== peg$FAILED) { | |
| 3131 | peg$savedPos = s0; | |
| 3132 | s0 = peg$f1(s1, s2); | |
| 3133 | } else { | |
| 3134 | peg$currPos = s0; | |
| 3135 | s0 = peg$FAILED; | |
| 3136 | } | |
| 3137 | } else { | |
| 3138 | peg$currPos = s0; | |
| 3139 | s0 = peg$FAILED; | |
| 3140 | } | |
| 3141 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3142 | return s0; | |
| 3143 | } | |
| 3144 | function peg$parseMAT2() { | |
| 3145 | var s0, s1, s2; | |
| 3146 | var key = peg$currPos * 306 + 33; | |
| 3147 | var cached = peg$resultsCache[key]; | |
| 3148 | if (cached) { | |
| 3149 | peg$currPos = cached.nextPos; | |
| 3150 | return cached.result; | |
| 3151 | } | |
| 3152 | s0 = peg$currPos; | |
| 3153 | if (input.substr(peg$currPos, 4) === peg$c32) { | |
| 3154 | s1 = peg$c32; | |
| 3155 | peg$currPos += 4; | |
| 3156 | } else { | |
| 3157 | s1 = peg$FAILED; | |
| 3158 | if (peg$silentFails === 0) { | |
| 3159 | peg$fail(peg$e32); | |
| 3160 | } | |
| 3161 | } | |
| 3162 | if (s1 !== peg$FAILED) { | |
| 3163 | s2 = peg$parseterminal(); | |
| 3164 | if (s2 !== peg$FAILED) { | |
| 3165 | peg$savedPos = s0; | |
| 3166 | s0 = peg$f1(s1, s2); | |
| 3167 | } else { | |
| 3168 | peg$currPos = s0; | |
| 3169 | s0 = peg$FAILED; | |
| 3170 | } | |
| 3171 | } else { | |
| 3172 | peg$currPos = s0; | |
| 3173 | s0 = peg$FAILED; | |
| 3174 | } | |
| 3175 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3176 | return s0; | |
| 3177 | } | |
| 3178 | function peg$parseMAT3() { | |
| 3179 | var s0, s1, s2; | |
| 3180 | var key = peg$currPos * 306 + 34; | |
| 3181 | var cached = peg$resultsCache[key]; | |
| 3182 | if (cached) { | |
| 3183 | peg$currPos = cached.nextPos; | |
| 3184 | return cached.result; | |
| 3185 | } | |
| 3186 | s0 = peg$currPos; | |
| 3187 | if (input.substr(peg$currPos, 4) === peg$c33) { | |
| 3188 | s1 = peg$c33; | |
| 3189 | peg$currPos += 4; | |
| 3190 | } else { | |
| 3191 | s1 = peg$FAILED; | |
| 3192 | if (peg$silentFails === 0) { | |
| 3193 | peg$fail(peg$e33); | |
| 3194 | } | |
| 3195 | } | |
| 3196 | if (s1 !== peg$FAILED) { | |
| 3197 | s2 = peg$parseterminal(); | |
| 3198 | if (s2 !== peg$FAILED) { | |
| 3199 | peg$savedPos = s0; | |
| 3200 | s0 = peg$f1(s1, s2); | |
| 3201 | } else { | |
| 3202 | peg$currPos = s0; | |
| 3203 | s0 = peg$FAILED; | |
| 3204 | } | |
| 3205 | } else { | |
| 3206 | peg$currPos = s0; | |
| 3207 | s0 = peg$FAILED; | |
| 3208 | } | |
| 3209 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3210 | return s0; | |
| 3211 | } | |
| 3212 | function peg$parseMAT4() { | |
| 3213 | var s0, s1, s2; | |
| 3214 | var key = peg$currPos * 306 + 35; | |
| 3215 | var cached = peg$resultsCache[key]; | |
| 3216 | if (cached) { | |
| 3217 | peg$currPos = cached.nextPos; | |
| 3218 | return cached.result; | |
| 3219 | } | |
| 3220 | s0 = peg$currPos; | |
| 3221 | if (input.substr(peg$currPos, 4) === peg$c34) { | |
| 3222 | s1 = peg$c34; | |
| 3223 | peg$currPos += 4; | |
| 3224 | } else { | |
| 3225 | s1 = peg$FAILED; | |
| 3226 | if (peg$silentFails === 0) { | |
| 3227 | peg$fail(peg$e34); | |
| 3228 | } | |
| 3229 | } | |
| 3230 | if (s1 !== peg$FAILED) { | |
| 3231 | s2 = peg$parseterminal(); | |
| 3232 | if (s2 !== peg$FAILED) { | |
| 3233 | peg$savedPos = s0; | |
| 3234 | s0 = peg$f1(s1, s2); | |
| 3235 | } else { | |
| 3236 | peg$currPos = s0; | |
| 3237 | s0 = peg$FAILED; | |
| 3238 | } | |
| 3239 | } else { | |
| 3240 | peg$currPos = s0; | |
| 3241 | s0 = peg$FAILED; | |
| 3242 | } | |
| 3243 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3244 | return s0; | |
| 3245 | } | |
| 3246 | function peg$parseCENTROID() { | |
| 3247 | var s0, s1, s2; | |
| 3248 | var key = peg$currPos * 306 + 36; | |
| 3249 | var cached = peg$resultsCache[key]; | |
| 3250 | if (cached) { | |
| 3251 | peg$currPos = cached.nextPos; | |
| 3252 | return cached.result; | |
| 3253 | } | |
| 3254 | s0 = peg$currPos; | |
| 3255 | if (input.substr(peg$currPos, 8) === peg$c35) { | |
| 3256 | s1 = peg$c35; | |
| 3257 | peg$currPos += 8; | |
| 3258 | } else { | |
| 3259 | s1 = peg$FAILED; | |
| 3260 | if (peg$silentFails === 0) { | |
| 3261 | peg$fail(peg$e35); | |
| 3262 | } | |
| 3263 | } | |
| 3264 | if (s1 !== peg$FAILED) { | |
| 3265 | s2 = peg$parseterminal(); | |
| 3266 | if (s2 !== peg$FAILED) { | |
| 3267 | peg$savedPos = s0; | |
| 3268 | s0 = peg$f1(s1, s2); | |
| 3269 | } else { | |
| 3270 | peg$currPos = s0; | |
| 3271 | s0 = peg$FAILED; | |
| 3272 | } | |
| 3273 | } else { | |
| 3274 | peg$currPos = s0; | |
| 3275 | s0 = peg$FAILED; | |
| 3276 | } | |
| 3277 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3278 | return s0; | |
| 3279 | } | |
| 3280 | function peg$parseIN() { | |
| 3281 | var s0, s1, s2; | |
| 3282 | var key = peg$currPos * 306 + 37; | |
| 3283 | var cached = peg$resultsCache[key]; | |
| 3284 | if (cached) { | |
| 3285 | peg$currPos = cached.nextPos; | |
| 3286 | return cached.result; | |
| 3287 | } | |
| 3288 | s0 = peg$currPos; | |
| 3289 | if (input.substr(peg$currPos, 2) === peg$c36) { | |
| 3290 | s1 = peg$c36; | |
| 3291 | peg$currPos += 2; | |
| 3292 | } else { | |
| 3293 | s1 = peg$FAILED; | |
| 3294 | if (peg$silentFails === 0) { | |
| 3295 | peg$fail(peg$e36); | |
| 3296 | } | |
| 3297 | } | |
| 3298 | if (s1 !== peg$FAILED) { | |
| 3299 | s2 = peg$parseterminal(); | |
| 3300 | if (s2 !== peg$FAILED) { | |
| 3301 | peg$savedPos = s0; | |
| 3302 | s0 = peg$f1(s1, s2); | |
| 3303 | } else { | |
| 3304 | peg$currPos = s0; | |
| 3305 | s0 = peg$FAILED; | |
| 3306 | } | |
| 3307 | } else { | |
| 3308 | peg$currPos = s0; | |
| 3309 | s0 = peg$FAILED; | |
| 3310 | } | |
| 3311 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3312 | return s0; | |
| 3313 | } | |
| 3314 | function peg$parseOUT() { | |
| 3315 | var s0, s1, s2; | |
| 3316 | var key = peg$currPos * 306 + 38; | |
| 3317 | var cached = peg$resultsCache[key]; | |
| 3318 | if (cached) { | |
| 3319 | peg$currPos = cached.nextPos; | |
| 3320 | return cached.result; | |
| 3321 | } | |
| 3322 | s0 = peg$currPos; | |
| 3323 | if (input.substr(peg$currPos, 3) === peg$c37) { | |
| 3324 | s1 = peg$c37; | |
| 3325 | peg$currPos += 3; | |
| 3326 | } else { | |
| 3327 | s1 = peg$FAILED; | |
| 3328 | if (peg$silentFails === 0) { | |
| 3329 | peg$fail(peg$e37); | |
| 3330 | } | |
| 3331 | } | |
| 3332 | if (s1 !== peg$FAILED) { | |
| 3333 | s2 = peg$parseterminal(); | |
| 3334 | if (s2 !== peg$FAILED) { | |
| 3335 | peg$savedPos = s0; | |
| 3336 | s0 = peg$f1(s1, s2); | |
| 3337 | } else { | |
| 3338 | peg$currPos = s0; | |
| 3339 | s0 = peg$FAILED; | |
| 3340 | } | |
| 3341 | } else { | |
| 3342 | peg$currPos = s0; | |
| 3343 | s0 = peg$FAILED; | |
| 3344 | } | |
| 3345 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3346 | return s0; | |
| 3347 | } | |
| 3348 | function peg$parseINOUT() { | |
| 3349 | var s0, s1, s2; | |
| 3350 | var key = peg$currPos * 306 + 39; | |
| 3351 | var cached = peg$resultsCache[key]; | |
| 3352 | if (cached) { | |
| 3353 | peg$currPos = cached.nextPos; | |
| 3354 | return cached.result; | |
| 3355 | } | |
| 3356 | s0 = peg$currPos; | |
| 3357 | if (input.substr(peg$currPos, 5) === peg$c38) { | |
| 3358 | s1 = peg$c38; | |
| 3359 | peg$currPos += 5; | |
| 3360 | } else { | |
| 3361 | s1 = peg$FAILED; | |
| 3362 | if (peg$silentFails === 0) { | |
| 3363 | peg$fail(peg$e38); | |
| 3364 | } | |
| 3365 | } | |
| 3366 | if (s1 !== peg$FAILED) { | |
| 3367 | s2 = peg$parseterminal(); | |
| 3368 | if (s2 !== peg$FAILED) { | |
| 3369 | peg$savedPos = s0; | |
| 3370 | s0 = peg$f1(s1, s2); | |
| 3371 | } else { | |
| 3372 | peg$currPos = s0; | |
| 3373 | s0 = peg$FAILED; | |
| 3374 | } | |
| 3375 | } else { | |
| 3376 | peg$currPos = s0; | |
| 3377 | s0 = peg$FAILED; | |
| 3378 | } | |
| 3379 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3380 | return s0; | |
| 3381 | } | |
| 3382 | function peg$parseUNIFORM() { | |
| 3383 | var s0, s1, s2; | |
| 3384 | var key = peg$currPos * 306 + 40; | |
| 3385 | var cached = peg$resultsCache[key]; | |
| 3386 | if (cached) { | |
| 3387 | peg$currPos = cached.nextPos; | |
| 3388 | return cached.result; | |
| 3389 | } | |
| 3390 | s0 = peg$currPos; | |
| 3391 | if (input.substr(peg$currPos, 7) === peg$c39) { | |
| 3392 | s1 = peg$c39; | |
| 3393 | peg$currPos += 7; | |
| 3394 | } else { | |
| 3395 | s1 = peg$FAILED; | |
| 3396 | if (peg$silentFails === 0) { | |
| 3397 | peg$fail(peg$e39); | |
| 3398 | } | |
| 3399 | } | |
| 3400 | if (s1 !== peg$FAILED) { | |
| 3401 | s2 = peg$parseterminal(); | |
| 3402 | if (s2 !== peg$FAILED) { | |
| 3403 | peg$savedPos = s0; | |
| 3404 | s0 = peg$f1(s1, s2); | |
| 3405 | } else { | |
| 3406 | peg$currPos = s0; | |
| 3407 | s0 = peg$FAILED; | |
| 3408 | } | |
| 3409 | } else { | |
| 3410 | peg$currPos = s0; | |
| 3411 | s0 = peg$FAILED; | |
| 3412 | } | |
| 3413 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3414 | return s0; | |
| 3415 | } | |
| 3416 | function peg$parsePATCH() { | |
| 3417 | var s0, s1, s2; | |
| 3418 | var key = peg$currPos * 306 + 41; | |
| 3419 | var cached = peg$resultsCache[key]; | |
| 3420 | if (cached) { | |
| 3421 | peg$currPos = cached.nextPos; | |
| 3422 | return cached.result; | |
| 3423 | } | |
| 3424 | s0 = peg$currPos; | |
| 3425 | if (input.substr(peg$currPos, 5) === peg$c40) { | |
| 3426 | s1 = peg$c40; | |
| 3427 | peg$currPos += 5; | |
| 3428 | } else { | |
| 3429 | s1 = peg$FAILED; | |
| 3430 | if (peg$silentFails === 0) { | |
| 3431 | peg$fail(peg$e40); | |
| 3432 | } | |
| 3433 | } | |
| 3434 | if (s1 !== peg$FAILED) { | |
| 3435 | s2 = peg$parseterminal(); | |
| 3436 | if (s2 !== peg$FAILED) { | |
| 3437 | peg$savedPos = s0; | |
| 3438 | s0 = peg$f1(s1, s2); | |
| 3439 | } else { | |
| 3440 | peg$currPos = s0; | |
| 3441 | s0 = peg$FAILED; | |
| 3442 | } | |
| 3443 | } else { | |
| 3444 | peg$currPos = s0; | |
| 3445 | s0 = peg$FAILED; | |
| 3446 | } | |
| 3447 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3448 | return s0; | |
| 3449 | } | |
| 3450 | function peg$parseSAMPLE() { | |
| 3451 | var s0, s1, s2; | |
| 3452 | var key = peg$currPos * 306 + 42; | |
| 3453 | var cached = peg$resultsCache[key]; | |
| 3454 | if (cached) { | |
| 3455 | peg$currPos = cached.nextPos; | |
| 3456 | return cached.result; | |
| 3457 | } | |
| 3458 | s0 = peg$currPos; | |
| 3459 | if (input.substr(peg$currPos, 6) === peg$c41) { | |
| 3460 | s1 = peg$c41; | |
| 3461 | peg$currPos += 6; | |
| 3462 | } else { | |
| 3463 | s1 = peg$FAILED; | |
| 3464 | if (peg$silentFails === 0) { | |
| 3465 | peg$fail(peg$e41); | |
| 3466 | } | |
| 3467 | } | |
| 3468 | if (s1 !== peg$FAILED) { | |
| 3469 | s2 = peg$parseterminal(); | |
| 3470 | if (s2 !== peg$FAILED) { | |
| 3471 | peg$savedPos = s0; | |
| 3472 | s0 = peg$f1(s1, s2); | |
| 3473 | } else { | |
| 3474 | peg$currPos = s0; | |
| 3475 | s0 = peg$FAILED; | |
| 3476 | } | |
| 3477 | } else { | |
| 3478 | peg$currPos = s0; | |
| 3479 | s0 = peg$FAILED; | |
| 3480 | } | |
| 3481 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3482 | return s0; | |
| 3483 | } | |
| 3484 | function peg$parseBUFFER() { | |
| 3485 | var s0, s1, s2; | |
| 3486 | var key = peg$currPos * 306 + 43; | |
| 3487 | var cached = peg$resultsCache[key]; | |
| 3488 | if (cached) { | |
| 3489 | peg$currPos = cached.nextPos; | |
| 3490 | return cached.result; | |
| 3491 | } | |
| 3492 | s0 = peg$currPos; | |
| 3493 | if (input.substr(peg$currPos, 6) === peg$c42) { | |
| 3494 | s1 = peg$c42; | |
| 3495 | peg$currPos += 6; | |
| 3496 | } else { | |
| 3497 | s1 = peg$FAILED; | |
| 3498 | if (peg$silentFails === 0) { | |
| 3499 | peg$fail(peg$e42); | |
| 3500 | } | |
| 3501 | } | |
| 3502 | if (s1 !== peg$FAILED) { | |
| 3503 | s2 = peg$parseterminal(); | |
| 3504 | if (s2 !== peg$FAILED) { | |
| 3505 | peg$savedPos = s0; | |
| 3506 | s0 = peg$f1(s1, s2); | |
| 3507 | } else { | |
| 3508 | peg$currPos = s0; | |
| 3509 | s0 = peg$FAILED; | |
| 3510 | } | |
| 3511 | } else { | |
| 3512 | peg$currPos = s0; | |
| 3513 | s0 = peg$FAILED; | |
| 3514 | } | |
| 3515 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3516 | return s0; | |
| 3517 | } | |
| 3518 | function peg$parseSHARED() { | |
| 3519 | var s0, s1, s2; | |
| 3520 | var key = peg$currPos * 306 + 44; | |
| 3521 | var cached = peg$resultsCache[key]; | |
| 3522 | if (cached) { | |
| 3523 | peg$currPos = cached.nextPos; | |
| 3524 | return cached.result; | |
| 3525 | } | |
| 3526 | s0 = peg$currPos; | |
| 3527 | if (input.substr(peg$currPos, 6) === peg$c43) { | |
| 3528 | s1 = peg$c43; | |
| 3529 | peg$currPos += 6; | |
| 3530 | } else { | |
| 3531 | s1 = peg$FAILED; | |
| 3532 | if (peg$silentFails === 0) { | |
| 3533 | peg$fail(peg$e43); | |
| 3534 | } | |
| 3535 | } | |
| 3536 | if (s1 !== peg$FAILED) { | |
| 3537 | s2 = peg$parseterminal(); | |
| 3538 | if (s2 !== peg$FAILED) { | |
| 3539 | peg$savedPos = s0; | |
| 3540 | s0 = peg$f1(s1, s2); | |
| 3541 | } else { | |
| 3542 | peg$currPos = s0; | |
| 3543 | s0 = peg$FAILED; | |
| 3544 | } | |
| 3545 | } else { | |
| 3546 | peg$currPos = s0; | |
| 3547 | s0 = peg$FAILED; | |
| 3548 | } | |
| 3549 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3550 | return s0; | |
| 3551 | } | |
| 3552 | function peg$parseCOHERENT() { | |
| 3553 | var s0, s1, s2; | |
| 3554 | var key = peg$currPos * 306 + 45; | |
| 3555 | var cached = peg$resultsCache[key]; | |
| 3556 | if (cached) { | |
| 3557 | peg$currPos = cached.nextPos; | |
| 3558 | return cached.result; | |
| 3559 | } | |
| 3560 | s0 = peg$currPos; | |
| 3561 | if (input.substr(peg$currPos, 8) === peg$c44) { | |
| 3562 | s1 = peg$c44; | |
| 3563 | peg$currPos += 8; | |
| 3564 | } else { | |
| 3565 | s1 = peg$FAILED; | |
| 3566 | if (peg$silentFails === 0) { | |
| 3567 | peg$fail(peg$e44); | |
| 3568 | } | |
| 3569 | } | |
| 3570 | if (s1 !== peg$FAILED) { | |
| 3571 | s2 = peg$parseterminal(); | |
| 3572 | if (s2 !== peg$FAILED) { | |
| 3573 | peg$savedPos = s0; | |
| 3574 | s0 = peg$f1(s1, s2); | |
| 3575 | } else { | |
| 3576 | peg$currPos = s0; | |
| 3577 | s0 = peg$FAILED; | |
| 3578 | } | |
| 3579 | } else { | |
| 3580 | peg$currPos = s0; | |
| 3581 | s0 = peg$FAILED; | |
| 3582 | } | |
| 3583 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3584 | return s0; | |
| 3585 | } | |
| 3586 | function peg$parseVOLATILE() { | |
| 3587 | var s0, s1, s2; | |
| 3588 | var key = peg$currPos * 306 + 46; | |
| 3589 | var cached = peg$resultsCache[key]; | |
| 3590 | if (cached) { | |
| 3591 | peg$currPos = cached.nextPos; | |
| 3592 | return cached.result; | |
| 3593 | } | |
| 3594 | s0 = peg$currPos; | |
| 3595 | if (input.substr(peg$currPos, 8) === peg$c45) { | |
| 3596 | s1 = peg$c45; | |
| 3597 | peg$currPos += 8; | |
| 3598 | } else { | |
| 3599 | s1 = peg$FAILED; | |
| 3600 | if (peg$silentFails === 0) { | |
| 3601 | peg$fail(peg$e45); | |
| 3602 | } | |
| 3603 | } | |
| 3604 | if (s1 !== peg$FAILED) { | |
| 3605 | s2 = peg$parseterminal(); | |
| 3606 | if (s2 !== peg$FAILED) { | |
| 3607 | peg$savedPos = s0; | |
| 3608 | s0 = peg$f1(s1, s2); | |
| 3609 | } else { | |
| 3610 | peg$currPos = s0; | |
| 3611 | s0 = peg$FAILED; | |
| 3612 | } | |
| 3613 | } else { | |
| 3614 | peg$currPos = s0; | |
| 3615 | s0 = peg$FAILED; | |
| 3616 | } | |
| 3617 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3618 | return s0; | |
| 3619 | } | |
| 3620 | function peg$parseRESTRICT() { | |
| 3621 | var s0, s1, s2; | |
| 3622 | var key = peg$currPos * 306 + 47; | |
| 3623 | var cached = peg$resultsCache[key]; | |
| 3624 | if (cached) { | |
| 3625 | peg$currPos = cached.nextPos; | |
| 3626 | return cached.result; | |
| 3627 | } | |
| 3628 | s0 = peg$currPos; | |
| 3629 | if (input.substr(peg$currPos, 8) === peg$c46) { | |
| 3630 | s1 = peg$c46; | |
| 3631 | peg$currPos += 8; | |
| 3632 | } else { | |
| 3633 | s1 = peg$FAILED; | |
| 3634 | if (peg$silentFails === 0) { | |
| 3635 | peg$fail(peg$e46); | |
| 3636 | } | |
| 3637 | } | |
| 3638 | if (s1 !== peg$FAILED) { | |
| 3639 | s2 = peg$parseterminal(); | |
| 3640 | if (s2 !== peg$FAILED) { | |
| 3641 | peg$savedPos = s0; | |
| 3642 | s0 = peg$f1(s1, s2); | |
| 3643 | } else { | |
| 3644 | peg$currPos = s0; | |
| 3645 | s0 = peg$FAILED; | |
| 3646 | } | |
| 3647 | } else { | |
| 3648 | peg$currPos = s0; | |
| 3649 | s0 = peg$FAILED; | |
| 3650 | } | |
| 3651 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3652 | return s0; | |
| 3653 | } | |
| 3654 | function peg$parseREADONLY() { | |
| 3655 | var s0, s1, s2; | |
| 3656 | var key = peg$currPos * 306 + 48; | |
| 3657 | var cached = peg$resultsCache[key]; | |
| 3658 | if (cached) { | |
| 3659 | peg$currPos = cached.nextPos; | |
| 3660 | return cached.result; | |
| 3661 | } | |
| 3662 | s0 = peg$currPos; | |
| 3663 | if (input.substr(peg$currPos, 8) === peg$c47) { | |
| 3664 | s1 = peg$c47; | |
| 3665 | peg$currPos += 8; | |
| 3666 | } else { | |
| 3667 | s1 = peg$FAILED; | |
| 3668 | if (peg$silentFails === 0) { | |
| 3669 | peg$fail(peg$e47); | |
| 3670 | } | |
| 3671 | } | |
| 3672 | if (s1 !== peg$FAILED) { | |
| 3673 | s2 = peg$parseterminal(); | |
| 3674 | if (s2 !== peg$FAILED) { | |
| 3675 | peg$savedPos = s0; | |
| 3676 | s0 = peg$f1(s1, s2); | |
| 3677 | } else { | |
| 3678 | peg$currPos = s0; | |
| 3679 | s0 = peg$FAILED; | |
| 3680 | } | |
| 3681 | } else { | |
| 3682 | peg$currPos = s0; | |
| 3683 | s0 = peg$FAILED; | |
| 3684 | } | |
| 3685 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3686 | return s0; | |
| 3687 | } | |
| 3688 | function peg$parseWRITEONLY() { | |
| 3689 | var s0, s1, s2; | |
| 3690 | var key = peg$currPos * 306 + 49; | |
| 3691 | var cached = peg$resultsCache[key]; | |
| 3692 | if (cached) { | |
| 3693 | peg$currPos = cached.nextPos; | |
| 3694 | return cached.result; | |
| 3695 | } | |
| 3696 | s0 = peg$currPos; | |
| 3697 | if (input.substr(peg$currPos, 9) === peg$c48) { | |
| 3698 | s1 = peg$c48; | |
| 3699 | peg$currPos += 9; | |
| 3700 | } else { | |
| 3701 | s1 = peg$FAILED; | |
| 3702 | if (peg$silentFails === 0) { | |
| 3703 | peg$fail(peg$e48); | |
| 3704 | } | |
| 3705 | } | |
| 3706 | if (s1 !== peg$FAILED) { | |
| 3707 | s2 = peg$parseterminal(); | |
| 3708 | if (s2 !== peg$FAILED) { | |
| 3709 | peg$savedPos = s0; | |
| 3710 | s0 = peg$f1(s1, s2); | |
| 3711 | } else { | |
| 3712 | peg$currPos = s0; | |
| 3713 | s0 = peg$FAILED; | |
| 3714 | } | |
| 3715 | } else { | |
| 3716 | peg$currPos = s0; | |
| 3717 | s0 = peg$FAILED; | |
| 3718 | } | |
| 3719 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3720 | return s0; | |
| 3721 | } | |
| 3722 | function peg$parseDVEC2() { | |
| 3723 | var s0, s1, s2; | |
| 3724 | var key = peg$currPos * 306 + 50; | |
| 3725 | var cached = peg$resultsCache[key]; | |
| 3726 | if (cached) { | |
| 3727 | peg$currPos = cached.nextPos; | |
| 3728 | return cached.result; | |
| 3729 | } | |
| 3730 | s0 = peg$currPos; | |
| 3731 | if (input.substr(peg$currPos, 5) === peg$c49) { | |
| 3732 | s1 = peg$c49; | |
| 3733 | peg$currPos += 5; | |
| 3734 | } else { | |
| 3735 | s1 = peg$FAILED; | |
| 3736 | if (peg$silentFails === 0) { | |
| 3737 | peg$fail(peg$e49); | |
| 3738 | } | |
| 3739 | } | |
| 3740 | if (s1 !== peg$FAILED) { | |
| 3741 | s2 = peg$parseterminal(); | |
| 3742 | if (s2 !== peg$FAILED) { | |
| 3743 | peg$savedPos = s0; | |
| 3744 | s0 = peg$f1(s1, s2); | |
| 3745 | } else { | |
| 3746 | peg$currPos = s0; | |
| 3747 | s0 = peg$FAILED; | |
| 3748 | } | |
| 3749 | } else { | |
| 3750 | peg$currPos = s0; | |
| 3751 | s0 = peg$FAILED; | |
| 3752 | } | |
| 3753 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3754 | return s0; | |
| 3755 | } | |
| 3756 | function peg$parseDVEC3() { | |
| 3757 | var s0, s1, s2; | |
| 3758 | var key = peg$currPos * 306 + 51; | |
| 3759 | var cached = peg$resultsCache[key]; | |
| 3760 | if (cached) { | |
| 3761 | peg$currPos = cached.nextPos; | |
| 3762 | return cached.result; | |
| 3763 | } | |
| 3764 | s0 = peg$currPos; | |
| 3765 | if (input.substr(peg$currPos, 5) === peg$c50) { | |
| 3766 | s1 = peg$c50; | |
| 3767 | peg$currPos += 5; | |
| 3768 | } else { | |
| 3769 | s1 = peg$FAILED; | |
| 3770 | if (peg$silentFails === 0) { | |
| 3771 | peg$fail(peg$e50); | |
| 3772 | } | |
| 3773 | } | |
| 3774 | if (s1 !== peg$FAILED) { | |
| 3775 | s2 = peg$parseterminal(); | |
| 3776 | if (s2 !== peg$FAILED) { | |
| 3777 | peg$savedPos = s0; | |
| 3778 | s0 = peg$f1(s1, s2); | |
| 3779 | } else { | |
| 3780 | peg$currPos = s0; | |
| 3781 | s0 = peg$FAILED; | |
| 3782 | } | |
| 3783 | } else { | |
| 3784 | peg$currPos = s0; | |
| 3785 | s0 = peg$FAILED; | |
| 3786 | } | |
| 3787 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3788 | return s0; | |
| 3789 | } | |
| 3790 | function peg$parseDVEC4() { | |
| 3791 | var s0, s1, s2; | |
| 3792 | var key = peg$currPos * 306 + 52; | |
| 3793 | var cached = peg$resultsCache[key]; | |
| 3794 | if (cached) { | |
| 3795 | peg$currPos = cached.nextPos; | |
| 3796 | return cached.result; | |
| 3797 | } | |
| 3798 | s0 = peg$currPos; | |
| 3799 | if (input.substr(peg$currPos, 5) === peg$c51) { | |
| 3800 | s1 = peg$c51; | |
| 3801 | peg$currPos += 5; | |
| 3802 | } else { | |
| 3803 | s1 = peg$FAILED; | |
| 3804 | if (peg$silentFails === 0) { | |
| 3805 | peg$fail(peg$e51); | |
| 3806 | } | |
| 3807 | } | |
| 3808 | if (s1 !== peg$FAILED) { | |
| 3809 | s2 = peg$parseterminal(); | |
| 3810 | if (s2 !== peg$FAILED) { | |
| 3811 | peg$savedPos = s0; | |
| 3812 | s0 = peg$f1(s1, s2); | |
| 3813 | } else { | |
| 3814 | peg$currPos = s0; | |
| 3815 | s0 = peg$FAILED; | |
| 3816 | } | |
| 3817 | } else { | |
| 3818 | peg$currPos = s0; | |
| 3819 | s0 = peg$FAILED; | |
| 3820 | } | |
| 3821 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3822 | return s0; | |
| 3823 | } | |
| 3824 | function peg$parseDMAT2() { | |
| 3825 | var s0, s1, s2; | |
| 3826 | var key = peg$currPos * 306 + 53; | |
| 3827 | var cached = peg$resultsCache[key]; | |
| 3828 | if (cached) { | |
| 3829 | peg$currPos = cached.nextPos; | |
| 3830 | return cached.result; | |
| 3831 | } | |
| 3832 | s0 = peg$currPos; | |
| 3833 | if (input.substr(peg$currPos, 5) === peg$c52) { | |
| 3834 | s1 = peg$c52; | |
| 3835 | peg$currPos += 5; | |
| 3836 | } else { | |
| 3837 | s1 = peg$FAILED; | |
| 3838 | if (peg$silentFails === 0) { | |
| 3839 | peg$fail(peg$e52); | |
| 3840 | } | |
| 3841 | } | |
| 3842 | if (s1 !== peg$FAILED) { | |
| 3843 | s2 = peg$parseterminal(); | |
| 3844 | if (s2 !== peg$FAILED) { | |
| 3845 | peg$savedPos = s0; | |
| 3846 | s0 = peg$f1(s1, s2); | |
| 3847 | } else { | |
| 3848 | peg$currPos = s0; | |
| 3849 | s0 = peg$FAILED; | |
| 3850 | } | |
| 3851 | } else { | |
| 3852 | peg$currPos = s0; | |
| 3853 | s0 = peg$FAILED; | |
| 3854 | } | |
| 3855 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3856 | return s0; | |
| 3857 | } | |
| 3858 | function peg$parseDMAT3() { | |
| 3859 | var s0, s1, s2; | |
| 3860 | var key = peg$currPos * 306 + 54; | |
| 3861 | var cached = peg$resultsCache[key]; | |
| 3862 | if (cached) { | |
| 3863 | peg$currPos = cached.nextPos; | |
| 3864 | return cached.result; | |
| 3865 | } | |
| 3866 | s0 = peg$currPos; | |
| 3867 | if (input.substr(peg$currPos, 5) === peg$c53) { | |
| 3868 | s1 = peg$c53; | |
| 3869 | peg$currPos += 5; | |
| 3870 | } else { | |
| 3871 | s1 = peg$FAILED; | |
| 3872 | if (peg$silentFails === 0) { | |
| 3873 | peg$fail(peg$e53); | |
| 3874 | } | |
| 3875 | } | |
| 3876 | if (s1 !== peg$FAILED) { | |
| 3877 | s2 = peg$parseterminal(); | |
| 3878 | if (s2 !== peg$FAILED) { | |
| 3879 | peg$savedPos = s0; | |
| 3880 | s0 = peg$f1(s1, s2); | |
| 3881 | } else { | |
| 3882 | peg$currPos = s0; | |
| 3883 | s0 = peg$FAILED; | |
| 3884 | } | |
| 3885 | } else { | |
| 3886 | peg$currPos = s0; | |
| 3887 | s0 = peg$FAILED; | |
| 3888 | } | |
| 3889 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3890 | return s0; | |
| 3891 | } | |
| 3892 | function peg$parseDMAT4() { | |
| 3893 | var s0, s1, s2; | |
| 3894 | var key = peg$currPos * 306 + 55; | |
| 3895 | var cached = peg$resultsCache[key]; | |
| 3896 | if (cached) { | |
| 3897 | peg$currPos = cached.nextPos; | |
| 3898 | return cached.result; | |
| 3899 | } | |
| 3900 | s0 = peg$currPos; | |
| 3901 | if (input.substr(peg$currPos, 5) === peg$c54) { | |
| 3902 | s1 = peg$c54; | |
| 3903 | peg$currPos += 5; | |
| 3904 | } else { | |
| 3905 | s1 = peg$FAILED; | |
| 3906 | if (peg$silentFails === 0) { | |
| 3907 | peg$fail(peg$e54); | |
| 3908 | } | |
| 3909 | } | |
| 3910 | if (s1 !== peg$FAILED) { | |
| 3911 | s2 = peg$parseterminal(); | |
| 3912 | if (s2 !== peg$FAILED) { | |
| 3913 | peg$savedPos = s0; | |
| 3914 | s0 = peg$f1(s1, s2); | |
| 3915 | } else { | |
| 3916 | peg$currPos = s0; | |
| 3917 | s0 = peg$FAILED; | |
| 3918 | } | |
| 3919 | } else { | |
| 3920 | peg$currPos = s0; | |
| 3921 | s0 = peg$FAILED; | |
| 3922 | } | |
| 3923 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3924 | return s0; | |
| 3925 | } | |
| 3926 | function peg$parseNOPERSPECTIVE() { | |
| 3927 | var s0, s1, s2; | |
| 3928 | var key = peg$currPos * 306 + 56; | |
| 3929 | var cached = peg$resultsCache[key]; | |
| 3930 | if (cached) { | |
| 3931 | peg$currPos = cached.nextPos; | |
| 3932 | return cached.result; | |
| 3933 | } | |
| 3934 | s0 = peg$currPos; | |
| 3935 | if (input.substr(peg$currPos, 13) === peg$c55) { | |
| 3936 | s1 = peg$c55; | |
| 3937 | peg$currPos += 13; | |
| 3938 | } else { | |
| 3939 | s1 = peg$FAILED; | |
| 3940 | if (peg$silentFails === 0) { | |
| 3941 | peg$fail(peg$e55); | |
| 3942 | } | |
| 3943 | } | |
| 3944 | if (s1 !== peg$FAILED) { | |
| 3945 | s2 = peg$parseterminal(); | |
| 3946 | if (s2 !== peg$FAILED) { | |
| 3947 | peg$savedPos = s0; | |
| 3948 | s0 = peg$f1(s1, s2); | |
| 3949 | } else { | |
| 3950 | peg$currPos = s0; | |
| 3951 | s0 = peg$FAILED; | |
| 3952 | } | |
| 3953 | } else { | |
| 3954 | peg$currPos = s0; | |
| 3955 | s0 = peg$FAILED; | |
| 3956 | } | |
| 3957 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3958 | return s0; | |
| 3959 | } | |
| 3960 | function peg$parseFLAT() { | |
| 3961 | var s0, s1, s2; | |
| 3962 | var key = peg$currPos * 306 + 57; | |
| 3963 | var cached = peg$resultsCache[key]; | |
| 3964 | if (cached) { | |
| 3965 | peg$currPos = cached.nextPos; | |
| 3966 | return cached.result; | |
| 3967 | } | |
| 3968 | s0 = peg$currPos; | |
| 3969 | if (input.substr(peg$currPos, 4) === peg$c56) { | |
| 3970 | s1 = peg$c56; | |
| 3971 | peg$currPos += 4; | |
| 3972 | } else { | |
| 3973 | s1 = peg$FAILED; | |
| 3974 | if (peg$silentFails === 0) { | |
| 3975 | peg$fail(peg$e56); | |
| 3976 | } | |
| 3977 | } | |
| 3978 | if (s1 !== peg$FAILED) { | |
| 3979 | s2 = peg$parseterminal(); | |
| 3980 | if (s2 !== peg$FAILED) { | |
| 3981 | peg$savedPos = s0; | |
| 3982 | s0 = peg$f1(s1, s2); | |
| 3983 | } else { | |
| 3984 | peg$currPos = s0; | |
| 3985 | s0 = peg$FAILED; | |
| 3986 | } | |
| 3987 | } else { | |
| 3988 | peg$currPos = s0; | |
| 3989 | s0 = peg$FAILED; | |
| 3990 | } | |
| 3991 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 3992 | return s0; | |
| 3993 | } | |
| 3994 | function peg$parseSMOOTH() { | |
| 3995 | var s0, s1, s2; | |
| 3996 | var key = peg$currPos * 306 + 58; | |
| 3997 | var cached = peg$resultsCache[key]; | |
| 3998 | if (cached) { | |
| 3999 | peg$currPos = cached.nextPos; | |
| 4000 | return cached.result; | |
| 4001 | } | |
| 4002 | s0 = peg$currPos; | |
| 4003 | if (input.substr(peg$currPos, 6) === peg$c57) { | |
| 4004 | s1 = peg$c57; | |
| 4005 | peg$currPos += 6; | |
| 4006 | } else { | |
| 4007 | s1 = peg$FAILED; | |
| 4008 | if (peg$silentFails === 0) { | |
| 4009 | peg$fail(peg$e57); | |
| 4010 | } | |
| 4011 | } | |
| 4012 | if (s1 !== peg$FAILED) { | |
| 4013 | s2 = peg$parseterminal(); | |
| 4014 | if (s2 !== peg$FAILED) { | |
| 4015 | peg$savedPos = s0; | |
| 4016 | s0 = peg$f1(s1, s2); | |
| 4017 | } else { | |
| 4018 | peg$currPos = s0; | |
| 4019 | s0 = peg$FAILED; | |
| 4020 | } | |
| 4021 | } else { | |
| 4022 | peg$currPos = s0; | |
| 4023 | s0 = peg$FAILED; | |
| 4024 | } | |
| 4025 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4026 | return s0; | |
| 4027 | } | |
| 4028 | function peg$parseLAYOUT() { | |
| 4029 | var s0, s1, s2; | |
| 4030 | var key = peg$currPos * 306 + 59; | |
| 4031 | var cached = peg$resultsCache[key]; | |
| 4032 | if (cached) { | |
| 4033 | peg$currPos = cached.nextPos; | |
| 4034 | return cached.result; | |
| 4035 | } | |
| 4036 | s0 = peg$currPos; | |
| 4037 | if (input.substr(peg$currPos, 6) === peg$c58) { | |
| 4038 | s1 = peg$c58; | |
| 4039 | peg$currPos += 6; | |
| 4040 | } else { | |
| 4041 | s1 = peg$FAILED; | |
| 4042 | if (peg$silentFails === 0) { | |
| 4043 | peg$fail(peg$e58); | |
| 4044 | } | |
| 4045 | } | |
| 4046 | if (s1 !== peg$FAILED) { | |
| 4047 | s2 = peg$parseterminal(); | |
| 4048 | if (s2 !== peg$FAILED) { | |
| 4049 | peg$savedPos = s0; | |
| 4050 | s0 = peg$f1(s1, s2); | |
| 4051 | } else { | |
| 4052 | peg$currPos = s0; | |
| 4053 | s0 = peg$FAILED; | |
| 4054 | } | |
| 4055 | } else { | |
| 4056 | peg$currPos = s0; | |
| 4057 | s0 = peg$FAILED; | |
| 4058 | } | |
| 4059 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4060 | return s0; | |
| 4061 | } | |
| 4062 | function peg$parseMAT2X2() { | |
| 4063 | var s0, s1, s2; | |
| 4064 | var key = peg$currPos * 306 + 60; | |
| 4065 | var cached = peg$resultsCache[key]; | |
| 4066 | if (cached) { | |
| 4067 | peg$currPos = cached.nextPos; | |
| 4068 | return cached.result; | |
| 4069 | } | |
| 4070 | s0 = peg$currPos; | |
| 4071 | if (input.substr(peg$currPos, 6) === peg$c59) { | |
| 4072 | s1 = peg$c59; | |
| 4073 | peg$currPos += 6; | |
| 4074 | } else { | |
| 4075 | s1 = peg$FAILED; | |
| 4076 | if (peg$silentFails === 0) { | |
| 4077 | peg$fail(peg$e59); | |
| 4078 | } | |
| 4079 | } | |
| 4080 | if (s1 !== peg$FAILED) { | |
| 4081 | s2 = peg$parseterminal(); | |
| 4082 | if (s2 !== peg$FAILED) { | |
| 4083 | peg$savedPos = s0; | |
| 4084 | s0 = peg$f1(s1, s2); | |
| 4085 | } else { | |
| 4086 | peg$currPos = s0; | |
| 4087 | s0 = peg$FAILED; | |
| 4088 | } | |
| 4089 | } else { | |
| 4090 | peg$currPos = s0; | |
| 4091 | s0 = peg$FAILED; | |
| 4092 | } | |
| 4093 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4094 | return s0; | |
| 4095 | } | |
| 4096 | function peg$parseMAT2X3() { | |
| 4097 | var s0, s1, s2; | |
| 4098 | var key = peg$currPos * 306 + 61; | |
| 4099 | var cached = peg$resultsCache[key]; | |
| 4100 | if (cached) { | |
| 4101 | peg$currPos = cached.nextPos; | |
| 4102 | return cached.result; | |
| 4103 | } | |
| 4104 | s0 = peg$currPos; | |
| 4105 | if (input.substr(peg$currPos, 6) === peg$c60) { | |
| 4106 | s1 = peg$c60; | |
| 4107 | peg$currPos += 6; | |
| 4108 | } else { | |
| 4109 | s1 = peg$FAILED; | |
| 4110 | if (peg$silentFails === 0) { | |
| 4111 | peg$fail(peg$e60); | |
| 4112 | } | |
| 4113 | } | |
| 4114 | if (s1 !== peg$FAILED) { | |
| 4115 | s2 = peg$parseterminal(); | |
| 4116 | if (s2 !== peg$FAILED) { | |
| 4117 | peg$savedPos = s0; | |
| 4118 | s0 = peg$f1(s1, s2); | |
| 4119 | } else { | |
| 4120 | peg$currPos = s0; | |
| 4121 | s0 = peg$FAILED; | |
| 4122 | } | |
| 4123 | } else { | |
| 4124 | peg$currPos = s0; | |
| 4125 | s0 = peg$FAILED; | |
| 4126 | } | |
| 4127 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4128 | return s0; | |
| 4129 | } | |
| 4130 | function peg$parseMAT2X4() { | |
| 4131 | var s0, s1, s2; | |
| 4132 | var key = peg$currPos * 306 + 62; | |
| 4133 | var cached = peg$resultsCache[key]; | |
| 4134 | if (cached) { | |
| 4135 | peg$currPos = cached.nextPos; | |
| 4136 | return cached.result; | |
| 4137 | } | |
| 4138 | s0 = peg$currPos; | |
| 4139 | if (input.substr(peg$currPos, 6) === peg$c61) { | |
| 4140 | s1 = peg$c61; | |
| 4141 | peg$currPos += 6; | |
| 4142 | } else { | |
| 4143 | s1 = peg$FAILED; | |
| 4144 | if (peg$silentFails === 0) { | |
| 4145 | peg$fail(peg$e61); | |
| 4146 | } | |
| 4147 | } | |
| 4148 | if (s1 !== peg$FAILED) { | |
| 4149 | s2 = peg$parseterminal(); | |
| 4150 | if (s2 !== peg$FAILED) { | |
| 4151 | peg$savedPos = s0; | |
| 4152 | s0 = peg$f1(s1, s2); | |
| 4153 | } else { | |
| 4154 | peg$currPos = s0; | |
| 4155 | s0 = peg$FAILED; | |
| 4156 | } | |
| 4157 | } else { | |
| 4158 | peg$currPos = s0; | |
| 4159 | s0 = peg$FAILED; | |
| 4160 | } | |
| 4161 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4162 | return s0; | |
| 4163 | } | |
| 4164 | function peg$parseMAT3X2() { | |
| 4165 | var s0, s1, s2; | |
| 4166 | var key = peg$currPos * 306 + 63; | |
| 4167 | var cached = peg$resultsCache[key]; | |
| 4168 | if (cached) { | |
| 4169 | peg$currPos = cached.nextPos; | |
| 4170 | return cached.result; | |
| 4171 | } | |
| 4172 | s0 = peg$currPos; | |
| 4173 | if (input.substr(peg$currPos, 6) === peg$c62) { | |
| 4174 | s1 = peg$c62; | |
| 4175 | peg$currPos += 6; | |
| 4176 | } else { | |
| 4177 | s1 = peg$FAILED; | |
| 4178 | if (peg$silentFails === 0) { | |
| 4179 | peg$fail(peg$e62); | |
| 4180 | } | |
| 4181 | } | |
| 4182 | if (s1 !== peg$FAILED) { | |
| 4183 | s2 = peg$parseterminal(); | |
| 4184 | if (s2 !== peg$FAILED) { | |
| 4185 | peg$savedPos = s0; | |
| 4186 | s0 = peg$f1(s1, s2); | |
| 4187 | } else { | |
| 4188 | peg$currPos = s0; | |
| 4189 | s0 = peg$FAILED; | |
| 4190 | } | |
| 4191 | } else { | |
| 4192 | peg$currPos = s0; | |
| 4193 | s0 = peg$FAILED; | |
| 4194 | } | |
| 4195 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4196 | return s0; | |
| 4197 | } | |
| 4198 | function peg$parseMAT3X3() { | |
| 4199 | var s0, s1, s2; | |
| 4200 | var key = peg$currPos * 306 + 64; | |
| 4201 | var cached = peg$resultsCache[key]; | |
| 4202 | if (cached) { | |
| 4203 | peg$currPos = cached.nextPos; | |
| 4204 | return cached.result; | |
| 4205 | } | |
| 4206 | s0 = peg$currPos; | |
| 4207 | if (input.substr(peg$currPos, 6) === peg$c63) { | |
| 4208 | s1 = peg$c63; | |
| 4209 | peg$currPos += 6; | |
| 4210 | } else { | |
| 4211 | s1 = peg$FAILED; | |
| 4212 | if (peg$silentFails === 0) { | |
| 4213 | peg$fail(peg$e63); | |
| 4214 | } | |
| 4215 | } | |
| 4216 | if (s1 !== peg$FAILED) { | |
| 4217 | s2 = peg$parseterminal(); | |
| 4218 | if (s2 !== peg$FAILED) { | |
| 4219 | peg$savedPos = s0; | |
| 4220 | s0 = peg$f1(s1, s2); | |
| 4221 | } else { | |
| 4222 | peg$currPos = s0; | |
| 4223 | s0 = peg$FAILED; | |
| 4224 | } | |
| 4225 | } else { | |
| 4226 | peg$currPos = s0; | |
| 4227 | s0 = peg$FAILED; | |
| 4228 | } | |
| 4229 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4230 | return s0; | |
| 4231 | } | |
| 4232 | function peg$parseMAT3X4() { | |
| 4233 | var s0, s1, s2; | |
| 4234 | var key = peg$currPos * 306 + 65; | |
| 4235 | var cached = peg$resultsCache[key]; | |
| 4236 | if (cached) { | |
| 4237 | peg$currPos = cached.nextPos; | |
| 4238 | return cached.result; | |
| 4239 | } | |
| 4240 | s0 = peg$currPos; | |
| 4241 | if (input.substr(peg$currPos, 6) === peg$c64) { | |
| 4242 | s1 = peg$c64; | |
| 4243 | peg$currPos += 6; | |
| 4244 | } else { | |
| 4245 | s1 = peg$FAILED; | |
| 4246 | if (peg$silentFails === 0) { | |
| 4247 | peg$fail(peg$e64); | |
| 4248 | } | |
| 4249 | } | |
| 4250 | if (s1 !== peg$FAILED) { | |
| 4251 | s2 = peg$parseterminal(); | |
| 4252 | if (s2 !== peg$FAILED) { | |
| 4253 | peg$savedPos = s0; | |
| 4254 | s0 = peg$f1(s1, s2); | |
| 4255 | } else { | |
| 4256 | peg$currPos = s0; | |
| 4257 | s0 = peg$FAILED; | |
| 4258 | } | |
| 4259 | } else { | |
| 4260 | peg$currPos = s0; | |
| 4261 | s0 = peg$FAILED; | |
| 4262 | } | |
| 4263 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4264 | return s0; | |
| 4265 | } | |
| 4266 | function peg$parseMAT4X2() { | |
| 4267 | var s0, s1, s2; | |
| 4268 | var key = peg$currPos * 306 + 66; | |
| 4269 | var cached = peg$resultsCache[key]; | |
| 4270 | if (cached) { | |
| 4271 | peg$currPos = cached.nextPos; | |
| 4272 | return cached.result; | |
| 4273 | } | |
| 4274 | s0 = peg$currPos; | |
| 4275 | if (input.substr(peg$currPos, 6) === peg$c65) { | |
| 4276 | s1 = peg$c65; | |
| 4277 | peg$currPos += 6; | |
| 4278 | } else { | |
| 4279 | s1 = peg$FAILED; | |
| 4280 | if (peg$silentFails === 0) { | |
| 4281 | peg$fail(peg$e65); | |
| 4282 | } | |
| 4283 | } | |
| 4284 | if (s1 !== peg$FAILED) { | |
| 4285 | s2 = peg$parseterminal(); | |
| 4286 | if (s2 !== peg$FAILED) { | |
| 4287 | peg$savedPos = s0; | |
| 4288 | s0 = peg$f1(s1, s2); | |
| 4289 | } else { | |
| 4290 | peg$currPos = s0; | |
| 4291 | s0 = peg$FAILED; | |
| 4292 | } | |
| 4293 | } else { | |
| 4294 | peg$currPos = s0; | |
| 4295 | s0 = peg$FAILED; | |
| 4296 | } | |
| 4297 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4298 | return s0; | |
| 4299 | } | |
| 4300 | function peg$parseMAT4X3() { | |
| 4301 | var s0, s1, s2; | |
| 4302 | var key = peg$currPos * 306 + 67; | |
| 4303 | var cached = peg$resultsCache[key]; | |
| 4304 | if (cached) { | |
| 4305 | peg$currPos = cached.nextPos; | |
| 4306 | return cached.result; | |
| 4307 | } | |
| 4308 | s0 = peg$currPos; | |
| 4309 | if (input.substr(peg$currPos, 6) === peg$c66) { | |
| 4310 | s1 = peg$c66; | |
| 4311 | peg$currPos += 6; | |
| 4312 | } else { | |
| 4313 | s1 = peg$FAILED; | |
| 4314 | if (peg$silentFails === 0) { | |
| 4315 | peg$fail(peg$e66); | |
| 4316 | } | |
| 4317 | } | |
| 4318 | if (s1 !== peg$FAILED) { | |
| 4319 | s2 = peg$parseterminal(); | |
| 4320 | if (s2 !== peg$FAILED) { | |
| 4321 | peg$savedPos = s0; | |
| 4322 | s0 = peg$f1(s1, s2); | |
| 4323 | } else { | |
| 4324 | peg$currPos = s0; | |
| 4325 | s0 = peg$FAILED; | |
| 4326 | } | |
| 4327 | } else { | |
| 4328 | peg$currPos = s0; | |
| 4329 | s0 = peg$FAILED; | |
| 4330 | } | |
| 4331 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4332 | return s0; | |
| 4333 | } | |
| 4334 | function peg$parseMAT4X4() { | |
| 4335 | var s0, s1, s2; | |
| 4336 | var key = peg$currPos * 306 + 68; | |
| 4337 | var cached = peg$resultsCache[key]; | |
| 4338 | if (cached) { | |
| 4339 | peg$currPos = cached.nextPos; | |
| 4340 | return cached.result; | |
| 4341 | } | |
| 4342 | s0 = peg$currPos; | |
| 4343 | if (input.substr(peg$currPos, 6) === peg$c67) { | |
| 4344 | s1 = peg$c67; | |
| 4345 | peg$currPos += 6; | |
| 4346 | } else { | |
| 4347 | s1 = peg$FAILED; | |
| 4348 | if (peg$silentFails === 0) { | |
| 4349 | peg$fail(peg$e67); | |
| 4350 | } | |
| 4351 | } | |
| 4352 | if (s1 !== peg$FAILED) { | |
| 4353 | s2 = peg$parseterminal(); | |
| 4354 | if (s2 !== peg$FAILED) { | |
| 4355 | peg$savedPos = s0; | |
| 4356 | s0 = peg$f1(s1, s2); | |
| 4357 | } else { | |
| 4358 | peg$currPos = s0; | |
| 4359 | s0 = peg$FAILED; | |
| 4360 | } | |
| 4361 | } else { | |
| 4362 | peg$currPos = s0; | |
| 4363 | s0 = peg$FAILED; | |
| 4364 | } | |
| 4365 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4366 | return s0; | |
| 4367 | } | |
| 4368 | function peg$parseDMAT2X2() { | |
| 4369 | var s0, s1, s2; | |
| 4370 | var key = peg$currPos * 306 + 69; | |
| 4371 | var cached = peg$resultsCache[key]; | |
| 4372 | if (cached) { | |
| 4373 | peg$currPos = cached.nextPos; | |
| 4374 | return cached.result; | |
| 4375 | } | |
| 4376 | s0 = peg$currPos; | |
| 4377 | if (input.substr(peg$currPos, 7) === peg$c68) { | |
| 4378 | s1 = peg$c68; | |
| 4379 | peg$currPos += 7; | |
| 4380 | } else { | |
| 4381 | s1 = peg$FAILED; | |
| 4382 | if (peg$silentFails === 0) { | |
| 4383 | peg$fail(peg$e68); | |
| 4384 | } | |
| 4385 | } | |
| 4386 | if (s1 !== peg$FAILED) { | |
| 4387 | s2 = peg$parseterminal(); | |
| 4388 | if (s2 !== peg$FAILED) { | |
| 4389 | peg$savedPos = s0; | |
| 4390 | s0 = peg$f1(s1, s2); | |
| 4391 | } else { | |
| 4392 | peg$currPos = s0; | |
| 4393 | s0 = peg$FAILED; | |
| 4394 | } | |
| 4395 | } else { | |
| 4396 | peg$currPos = s0; | |
| 4397 | s0 = peg$FAILED; | |
| 4398 | } | |
| 4399 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4400 | return s0; | |
| 4401 | } | |
| 4402 | function peg$parseDMAT2X3() { | |
| 4403 | var s0, s1, s2; | |
| 4404 | var key = peg$currPos * 306 + 70; | |
| 4405 | var cached = peg$resultsCache[key]; | |
| 4406 | if (cached) { | |
| 4407 | peg$currPos = cached.nextPos; | |
| 4408 | return cached.result; | |
| 4409 | } | |
| 4410 | s0 = peg$currPos; | |
| 4411 | if (input.substr(peg$currPos, 7) === peg$c69) { | |
| 4412 | s1 = peg$c69; | |
| 4413 | peg$currPos += 7; | |
| 4414 | } else { | |
| 4415 | s1 = peg$FAILED; | |
| 4416 | if (peg$silentFails === 0) { | |
| 4417 | peg$fail(peg$e69); | |
| 4418 | } | |
| 4419 | } | |
| 4420 | if (s1 !== peg$FAILED) { | |
| 4421 | s2 = peg$parseterminal(); | |
| 4422 | if (s2 !== peg$FAILED) { | |
| 4423 | peg$savedPos = s0; | |
| 4424 | s0 = peg$f1(s1, s2); | |
| 4425 | } else { | |
| 4426 | peg$currPos = s0; | |
| 4427 | s0 = peg$FAILED; | |
| 4428 | } | |
| 4429 | } else { | |
| 4430 | peg$currPos = s0; | |
| 4431 | s0 = peg$FAILED; | |
| 4432 | } | |
| 4433 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4434 | return s0; | |
| 4435 | } | |
| 4436 | function peg$parseDMAT2X4() { | |
| 4437 | var s0, s1, s2; | |
| 4438 | var key = peg$currPos * 306 + 71; | |
| 4439 | var cached = peg$resultsCache[key]; | |
| 4440 | if (cached) { | |
| 4441 | peg$currPos = cached.nextPos; | |
| 4442 | return cached.result; | |
| 4443 | } | |
| 4444 | s0 = peg$currPos; | |
| 4445 | if (input.substr(peg$currPos, 7) === peg$c70) { | |
| 4446 | s1 = peg$c70; | |
| 4447 | peg$currPos += 7; | |
| 4448 | } else { | |
| 4449 | s1 = peg$FAILED; | |
| 4450 | if (peg$silentFails === 0) { | |
| 4451 | peg$fail(peg$e70); | |
| 4452 | } | |
| 4453 | } | |
| 4454 | if (s1 !== peg$FAILED) { | |
| 4455 | s2 = peg$parseterminal(); | |
| 4456 | if (s2 !== peg$FAILED) { | |
| 4457 | peg$savedPos = s0; | |
| 4458 | s0 = peg$f1(s1, s2); | |
| 4459 | } else { | |
| 4460 | peg$currPos = s0; | |
| 4461 | s0 = peg$FAILED; | |
| 4462 | } | |
| 4463 | } else { | |
| 4464 | peg$currPos = s0; | |
| 4465 | s0 = peg$FAILED; | |
| 4466 | } | |
| 4467 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4468 | return s0; | |
| 4469 | } | |
| 4470 | function peg$parseDMAT3X2() { | |
| 4471 | var s0, s1, s2; | |
| 4472 | var key = peg$currPos * 306 + 72; | |
| 4473 | var cached = peg$resultsCache[key]; | |
| 4474 | if (cached) { | |
| 4475 | peg$currPos = cached.nextPos; | |
| 4476 | return cached.result; | |
| 4477 | } | |
| 4478 | s0 = peg$currPos; | |
| 4479 | if (input.substr(peg$currPos, 7) === peg$c71) { | |
| 4480 | s1 = peg$c71; | |
| 4481 | peg$currPos += 7; | |
| 4482 | } else { | |
| 4483 | s1 = peg$FAILED; | |
| 4484 | if (peg$silentFails === 0) { | |
| 4485 | peg$fail(peg$e71); | |
| 4486 | } | |
| 4487 | } | |
| 4488 | if (s1 !== peg$FAILED) { | |
| 4489 | s2 = peg$parseterminal(); | |
| 4490 | if (s2 !== peg$FAILED) { | |
| 4491 | peg$savedPos = s0; | |
| 4492 | s0 = peg$f1(s1, s2); | |
| 4493 | } else { | |
| 4494 | peg$currPos = s0; | |
| 4495 | s0 = peg$FAILED; | |
| 4496 | } | |
| 4497 | } else { | |
| 4498 | peg$currPos = s0; | |
| 4499 | s0 = peg$FAILED; | |
| 4500 | } | |
| 4501 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4502 | return s0; | |
| 4503 | } | |
| 4504 | function peg$parseDMAT3X3() { | |
| 4505 | var s0, s1, s2; | |
| 4506 | var key = peg$currPos * 306 + 73; | |
| 4507 | var cached = peg$resultsCache[key]; | |
| 4508 | if (cached) { | |
| 4509 | peg$currPos = cached.nextPos; | |
| 4510 | return cached.result; | |
| 4511 | } | |
| 4512 | s0 = peg$currPos; | |
| 4513 | if (input.substr(peg$currPos, 7) === peg$c72) { | |
| 4514 | s1 = peg$c72; | |
| 4515 | peg$currPos += 7; | |
| 4516 | } else { | |
| 4517 | s1 = peg$FAILED; | |
| 4518 | if (peg$silentFails === 0) { | |
| 4519 | peg$fail(peg$e72); | |
| 4520 | } | |
| 4521 | } | |
| 4522 | if (s1 !== peg$FAILED) { | |
| 4523 | s2 = peg$parseterminal(); | |
| 4524 | if (s2 !== peg$FAILED) { | |
| 4525 | peg$savedPos = s0; | |
| 4526 | s0 = peg$f1(s1, s2); | |
| 4527 | } else { | |
| 4528 | peg$currPos = s0; | |
| 4529 | s0 = peg$FAILED; | |
| 4530 | } | |
| 4531 | } else { | |
| 4532 | peg$currPos = s0; | |
| 4533 | s0 = peg$FAILED; | |
| 4534 | } | |
| 4535 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4536 | return s0; | |
| 4537 | } | |
| 4538 | function peg$parseDMAT3X4() { | |
| 4539 | var s0, s1, s2; | |
| 4540 | var key = peg$currPos * 306 + 74; | |
| 4541 | var cached = peg$resultsCache[key]; | |
| 4542 | if (cached) { | |
| 4543 | peg$currPos = cached.nextPos; | |
| 4544 | return cached.result; | |
| 4545 | } | |
| 4546 | s0 = peg$currPos; | |
| 4547 | if (input.substr(peg$currPos, 7) === peg$c73) { | |
| 4548 | s1 = peg$c73; | |
| 4549 | peg$currPos += 7; | |
| 4550 | } else { | |
| 4551 | s1 = peg$FAILED; | |
| 4552 | if (peg$silentFails === 0) { | |
| 4553 | peg$fail(peg$e73); | |
| 4554 | } | |
| 4555 | } | |
| 4556 | if (s1 !== peg$FAILED) { | |
| 4557 | s2 = peg$parseterminal(); | |
| 4558 | if (s2 !== peg$FAILED) { | |
| 4559 | peg$savedPos = s0; | |
| 4560 | s0 = peg$f1(s1, s2); | |
| 4561 | } else { | |
| 4562 | peg$currPos = s0; | |
| 4563 | s0 = peg$FAILED; | |
| 4564 | } | |
| 4565 | } else { | |
| 4566 | peg$currPos = s0; | |
| 4567 | s0 = peg$FAILED; | |
| 4568 | } | |
| 4569 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4570 | return s0; | |
| 4571 | } | |
| 4572 | function peg$parseDMAT4X2() { | |
| 4573 | var s0, s1, s2; | |
| 4574 | var key = peg$currPos * 306 + 75; | |
| 4575 | var cached = peg$resultsCache[key]; | |
| 4576 | if (cached) { | |
| 4577 | peg$currPos = cached.nextPos; | |
| 4578 | return cached.result; | |
| 4579 | } | |
| 4580 | s0 = peg$currPos; | |
| 4581 | if (input.substr(peg$currPos, 7) === peg$c74) { | |
| 4582 | s1 = peg$c74; | |
| 4583 | peg$currPos += 7; | |
| 4584 | } else { | |
| 4585 | s1 = peg$FAILED; | |
| 4586 | if (peg$silentFails === 0) { | |
| 4587 | peg$fail(peg$e74); | |
| 4588 | } | |
| 4589 | } | |
| 4590 | if (s1 !== peg$FAILED) { | |
| 4591 | s2 = peg$parseterminal(); | |
| 4592 | if (s2 !== peg$FAILED) { | |
| 4593 | peg$savedPos = s0; | |
| 4594 | s0 = peg$f1(s1, s2); | |
| 4595 | } else { | |
| 4596 | peg$currPos = s0; | |
| 4597 | s0 = peg$FAILED; | |
| 4598 | } | |
| 4599 | } else { | |
| 4600 | peg$currPos = s0; | |
| 4601 | s0 = peg$FAILED; | |
| 4602 | } | |
| 4603 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4604 | return s0; | |
| 4605 | } | |
| 4606 | function peg$parseDMAT4X3() { | |
| 4607 | var s0, s1, s2; | |
| 4608 | var key = peg$currPos * 306 + 76; | |
| 4609 | var cached = peg$resultsCache[key]; | |
| 4610 | if (cached) { | |
| 4611 | peg$currPos = cached.nextPos; | |
| 4612 | return cached.result; | |
| 4613 | } | |
| 4614 | s0 = peg$currPos; | |
| 4615 | if (input.substr(peg$currPos, 7) === peg$c75) { | |
| 4616 | s1 = peg$c75; | |
| 4617 | peg$currPos += 7; | |
| 4618 | } else { | |
| 4619 | s1 = peg$FAILED; | |
| 4620 | if (peg$silentFails === 0) { | |
| 4621 | peg$fail(peg$e75); | |
| 4622 | } | |
| 4623 | } | |
| 4624 | if (s1 !== peg$FAILED) { | |
| 4625 | s2 = peg$parseterminal(); | |
| 4626 | if (s2 !== peg$FAILED) { | |
| 4627 | peg$savedPos = s0; | |
| 4628 | s0 = peg$f1(s1, s2); | |
| 4629 | } else { | |
| 4630 | peg$currPos = s0; | |
| 4631 | s0 = peg$FAILED; | |
| 4632 | } | |
| 4633 | } else { | |
| 4634 | peg$currPos = s0; | |
| 4635 | s0 = peg$FAILED; | |
| 4636 | } | |
| 4637 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4638 | return s0; | |
| 4639 | } | |
| 4640 | function peg$parseDMAT4X4() { | |
| 4641 | var s0, s1, s2; | |
| 4642 | var key = peg$currPos * 306 + 77; | |
| 4643 | var cached = peg$resultsCache[key]; | |
| 4644 | if (cached) { | |
| 4645 | peg$currPos = cached.nextPos; | |
| 4646 | return cached.result; | |
| 4647 | } | |
| 4648 | s0 = peg$currPos; | |
| 4649 | if (input.substr(peg$currPos, 7) === peg$c76) { | |
| 4650 | s1 = peg$c76; | |
| 4651 | peg$currPos += 7; | |
| 4652 | } else { | |
| 4653 | s1 = peg$FAILED; | |
| 4654 | if (peg$silentFails === 0) { | |
| 4655 | peg$fail(peg$e76); | |
| 4656 | } | |
| 4657 | } | |
| 4658 | if (s1 !== peg$FAILED) { | |
| 4659 | s2 = peg$parseterminal(); | |
| 4660 | if (s2 !== peg$FAILED) { | |
| 4661 | peg$savedPos = s0; | |
| 4662 | s0 = peg$f1(s1, s2); | |
| 4663 | } else { | |
| 4664 | peg$currPos = s0; | |
| 4665 | s0 = peg$FAILED; | |
| 4666 | } | |
| 4667 | } else { | |
| 4668 | peg$currPos = s0; | |
| 4669 | s0 = peg$FAILED; | |
| 4670 | } | |
| 4671 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4672 | return s0; | |
| 4673 | } | |
| 4674 | function peg$parseATOMIC_UINT() { | |
| 4675 | var s0, s1, s2; | |
| 4676 | var key = peg$currPos * 306 + 78; | |
| 4677 | var cached = peg$resultsCache[key]; | |
| 4678 | if (cached) { | |
| 4679 | peg$currPos = cached.nextPos; | |
| 4680 | return cached.result; | |
| 4681 | } | |
| 4682 | s0 = peg$currPos; | |
| 4683 | if (input.substr(peg$currPos, 11) === peg$c77) { | |
| 4684 | s1 = peg$c77; | |
| 4685 | peg$currPos += 11; | |
| 4686 | } else { | |
| 4687 | s1 = peg$FAILED; | |
| 4688 | if (peg$silentFails === 0) { | |
| 4689 | peg$fail(peg$e77); | |
| 4690 | } | |
| 4691 | } | |
| 4692 | if (s1 !== peg$FAILED) { | |
| 4693 | s2 = peg$parseterminal(); | |
| 4694 | if (s2 !== peg$FAILED) { | |
| 4695 | peg$savedPos = s0; | |
| 4696 | s0 = peg$f1(s1, s2); | |
| 4697 | } else { | |
| 4698 | peg$currPos = s0; | |
| 4699 | s0 = peg$FAILED; | |
| 4700 | } | |
| 4701 | } else { | |
| 4702 | peg$currPos = s0; | |
| 4703 | s0 = peg$FAILED; | |
| 4704 | } | |
| 4705 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4706 | return s0; | |
| 4707 | } | |
| 4708 | function peg$parseSAMPLER1D() { | |
| 4709 | var s0, s1, s2; | |
| 4710 | var key = peg$currPos * 306 + 79; | |
| 4711 | var cached = peg$resultsCache[key]; | |
| 4712 | if (cached) { | |
| 4713 | peg$currPos = cached.nextPos; | |
| 4714 | return cached.result; | |
| 4715 | } | |
| 4716 | s0 = peg$currPos; | |
| 4717 | if (input.substr(peg$currPos, 9) === peg$c78) { | |
| 4718 | s1 = peg$c78; | |
| 4719 | peg$currPos += 9; | |
| 4720 | } else { | |
| 4721 | s1 = peg$FAILED; | |
| 4722 | if (peg$silentFails === 0) { | |
| 4723 | peg$fail(peg$e78); | |
| 4724 | } | |
| 4725 | } | |
| 4726 | if (s1 !== peg$FAILED) { | |
| 4727 | s2 = peg$parseterminal(); | |
| 4728 | if (s2 !== peg$FAILED) { | |
| 4729 | peg$savedPos = s0; | |
| 4730 | s0 = peg$f1(s1, s2); | |
| 4731 | } else { | |
| 4732 | peg$currPos = s0; | |
| 4733 | s0 = peg$FAILED; | |
| 4734 | } | |
| 4735 | } else { | |
| 4736 | peg$currPos = s0; | |
| 4737 | s0 = peg$FAILED; | |
| 4738 | } | |
| 4739 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4740 | return s0; | |
| 4741 | } | |
| 4742 | function peg$parseSAMPLER2D() { | |
| 4743 | var s0, s1, s2; | |
| 4744 | var key = peg$currPos * 306 + 80; | |
| 4745 | var cached = peg$resultsCache[key]; | |
| 4746 | if (cached) { | |
| 4747 | peg$currPos = cached.nextPos; | |
| 4748 | return cached.result; | |
| 4749 | } | |
| 4750 | s0 = peg$currPos; | |
| 4751 | if (input.substr(peg$currPos, 9) === peg$c79) { | |
| 4752 | s1 = peg$c79; | |
| 4753 | peg$currPos += 9; | |
| 4754 | } else { | |
| 4755 | s1 = peg$FAILED; | |
| 4756 | if (peg$silentFails === 0) { | |
| 4757 | peg$fail(peg$e79); | |
| 4758 | } | |
| 4759 | } | |
| 4760 | if (s1 !== peg$FAILED) { | |
| 4761 | s2 = peg$parseterminal(); | |
| 4762 | if (s2 !== peg$FAILED) { | |
| 4763 | peg$savedPos = s0; | |
| 4764 | s0 = peg$f1(s1, s2); | |
| 4765 | } else { | |
| 4766 | peg$currPos = s0; | |
| 4767 | s0 = peg$FAILED; | |
| 4768 | } | |
| 4769 | } else { | |
| 4770 | peg$currPos = s0; | |
| 4771 | s0 = peg$FAILED; | |
| 4772 | } | |
| 4773 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4774 | return s0; | |
| 4775 | } | |
| 4776 | function peg$parseSAMPLER3D() { | |
| 4777 | var s0, s1, s2; | |
| 4778 | var key = peg$currPos * 306 + 81; | |
| 4779 | var cached = peg$resultsCache[key]; | |
| 4780 | if (cached) { | |
| 4781 | peg$currPos = cached.nextPos; | |
| 4782 | return cached.result; | |
| 4783 | } | |
| 4784 | s0 = peg$currPos; | |
| 4785 | if (input.substr(peg$currPos, 9) === peg$c80) { | |
| 4786 | s1 = peg$c80; | |
| 4787 | peg$currPos += 9; | |
| 4788 | } else { | |
| 4789 | s1 = peg$FAILED; | |
| 4790 | if (peg$silentFails === 0) { | |
| 4791 | peg$fail(peg$e80); | |
| 4792 | } | |
| 4793 | } | |
| 4794 | if (s1 !== peg$FAILED) { | |
| 4795 | s2 = peg$parseterminal(); | |
| 4796 | if (s2 !== peg$FAILED) { | |
| 4797 | peg$savedPos = s0; | |
| 4798 | s0 = peg$f1(s1, s2); | |
| 4799 | } else { | |
| 4800 | peg$currPos = s0; | |
| 4801 | s0 = peg$FAILED; | |
| 4802 | } | |
| 4803 | } else { | |
| 4804 | peg$currPos = s0; | |
| 4805 | s0 = peg$FAILED; | |
| 4806 | } | |
| 4807 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4808 | return s0; | |
| 4809 | } | |
| 4810 | function peg$parseSAMPLERCUBE() { | |
| 4811 | var s0, s1, s2; | |
| 4812 | var key = peg$currPos * 306 + 82; | |
| 4813 | var cached = peg$resultsCache[key]; | |
| 4814 | if (cached) { | |
| 4815 | peg$currPos = cached.nextPos; | |
| 4816 | return cached.result; | |
| 4817 | } | |
| 4818 | s0 = peg$currPos; | |
| 4819 | if (input.substr(peg$currPos, 11) === peg$c81) { | |
| 4820 | s1 = peg$c81; | |
| 4821 | peg$currPos += 11; | |
| 4822 | } else { | |
| 4823 | s1 = peg$FAILED; | |
| 4824 | if (peg$silentFails === 0) { | |
| 4825 | peg$fail(peg$e81); | |
| 4826 | } | |
| 4827 | } | |
| 4828 | if (s1 !== peg$FAILED) { | |
| 4829 | s2 = peg$parseterminal(); | |
| 4830 | if (s2 !== peg$FAILED) { | |
| 4831 | peg$savedPos = s0; | |
| 4832 | s0 = peg$f1(s1, s2); | |
| 4833 | } else { | |
| 4834 | peg$currPos = s0; | |
| 4835 | s0 = peg$FAILED; | |
| 4836 | } | |
| 4837 | } else { | |
| 4838 | peg$currPos = s0; | |
| 4839 | s0 = peg$FAILED; | |
| 4840 | } | |
| 4841 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4842 | return s0; | |
| 4843 | } | |
| 4844 | function peg$parseSAMPLER1DSHADOW() { | |
| 4845 | var s0, s1, s2; | |
| 4846 | var key = peg$currPos * 306 + 83; | |
| 4847 | var cached = peg$resultsCache[key]; | |
| 4848 | if (cached) { | |
| 4849 | peg$currPos = cached.nextPos; | |
| 4850 | return cached.result; | |
| 4851 | } | |
| 4852 | s0 = peg$currPos; | |
| 4853 | if (input.substr(peg$currPos, 15) === peg$c82) { | |
| 4854 | s1 = peg$c82; | |
| 4855 | peg$currPos += 15; | |
| 4856 | } else { | |
| 4857 | s1 = peg$FAILED; | |
| 4858 | if (peg$silentFails === 0) { | |
| 4859 | peg$fail(peg$e82); | |
| 4860 | } | |
| 4861 | } | |
| 4862 | if (s1 !== peg$FAILED) { | |
| 4863 | s2 = peg$parseterminal(); | |
| 4864 | if (s2 !== peg$FAILED) { | |
| 4865 | peg$savedPos = s0; | |
| 4866 | s0 = peg$f1(s1, s2); | |
| 4867 | } else { | |
| 4868 | peg$currPos = s0; | |
| 4869 | s0 = peg$FAILED; | |
| 4870 | } | |
| 4871 | } else { | |
| 4872 | peg$currPos = s0; | |
| 4873 | s0 = peg$FAILED; | |
| 4874 | } | |
| 4875 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4876 | return s0; | |
| 4877 | } | |
| 4878 | function peg$parseSAMPLER2DSHADOW() { | |
| 4879 | var s0, s1, s2; | |
| 4880 | var key = peg$currPos * 306 + 84; | |
| 4881 | var cached = peg$resultsCache[key]; | |
| 4882 | if (cached) { | |
| 4883 | peg$currPos = cached.nextPos; | |
| 4884 | return cached.result; | |
| 4885 | } | |
| 4886 | s0 = peg$currPos; | |
| 4887 | if (input.substr(peg$currPos, 15) === peg$c83) { | |
| 4888 | s1 = peg$c83; | |
| 4889 | peg$currPos += 15; | |
| 4890 | } else { | |
| 4891 | s1 = peg$FAILED; | |
| 4892 | if (peg$silentFails === 0) { | |
| 4893 | peg$fail(peg$e83); | |
| 4894 | } | |
| 4895 | } | |
| 4896 | if (s1 !== peg$FAILED) { | |
| 4897 | s2 = peg$parseterminal(); | |
| 4898 | if (s2 !== peg$FAILED) { | |
| 4899 | peg$savedPos = s0; | |
| 4900 | s0 = peg$f1(s1, s2); | |
| 4901 | } else { | |
| 4902 | peg$currPos = s0; | |
| 4903 | s0 = peg$FAILED; | |
| 4904 | } | |
| 4905 | } else { | |
| 4906 | peg$currPos = s0; | |
| 4907 | s0 = peg$FAILED; | |
| 4908 | } | |
| 4909 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4910 | return s0; | |
| 4911 | } | |
| 4912 | function peg$parseSAMPLERCUBESHADOW() { | |
| 4913 | var s0, s1, s2; | |
| 4914 | var key = peg$currPos * 306 + 85; | |
| 4915 | var cached = peg$resultsCache[key]; | |
| 4916 | if (cached) { | |
| 4917 | peg$currPos = cached.nextPos; | |
| 4918 | return cached.result; | |
| 4919 | } | |
| 4920 | s0 = peg$currPos; | |
| 4921 | if (input.substr(peg$currPos, 17) === peg$c84) { | |
| 4922 | s1 = peg$c84; | |
| 4923 | peg$currPos += 17; | |
| 4924 | } else { | |
| 4925 | s1 = peg$FAILED; | |
| 4926 | if (peg$silentFails === 0) { | |
| 4927 | peg$fail(peg$e84); | |
| 4928 | } | |
| 4929 | } | |
| 4930 | if (s1 !== peg$FAILED) { | |
| 4931 | s2 = peg$parseterminal(); | |
| 4932 | if (s2 !== peg$FAILED) { | |
| 4933 | peg$savedPos = s0; | |
| 4934 | s0 = peg$f1(s1, s2); | |
| 4935 | } else { | |
| 4936 | peg$currPos = s0; | |
| 4937 | s0 = peg$FAILED; | |
| 4938 | } | |
| 4939 | } else { | |
| 4940 | peg$currPos = s0; | |
| 4941 | s0 = peg$FAILED; | |
| 4942 | } | |
| 4943 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4944 | return s0; | |
| 4945 | } | |
| 4946 | function peg$parseSAMPLER1DARRAY() { | |
| 4947 | var s0, s1, s2; | |
| 4948 | var key = peg$currPos * 306 + 86; | |
| 4949 | var cached = peg$resultsCache[key]; | |
| 4950 | if (cached) { | |
| 4951 | peg$currPos = cached.nextPos; | |
| 4952 | return cached.result; | |
| 4953 | } | |
| 4954 | s0 = peg$currPos; | |
| 4955 | if (input.substr(peg$currPos, 14) === peg$c85) { | |
| 4956 | s1 = peg$c85; | |
| 4957 | peg$currPos += 14; | |
| 4958 | } else { | |
| 4959 | s1 = peg$FAILED; | |
| 4960 | if (peg$silentFails === 0) { | |
| 4961 | peg$fail(peg$e85); | |
| 4962 | } | |
| 4963 | } | |
| 4964 | if (s1 !== peg$FAILED) { | |
| 4965 | s2 = peg$parseterminal(); | |
| 4966 | if (s2 !== peg$FAILED) { | |
| 4967 | peg$savedPos = s0; | |
| 4968 | s0 = peg$f1(s1, s2); | |
| 4969 | } else { | |
| 4970 | peg$currPos = s0; | |
| 4971 | s0 = peg$FAILED; | |
| 4972 | } | |
| 4973 | } else { | |
| 4974 | peg$currPos = s0; | |
| 4975 | s0 = peg$FAILED; | |
| 4976 | } | |
| 4977 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 4978 | return s0; | |
| 4979 | } | |
| 4980 | function peg$parseSAMPLER2DARRAY() { | |
| 4981 | var s0, s1, s2; | |
| 4982 | var key = peg$currPos * 306 + 87; | |
| 4983 | var cached = peg$resultsCache[key]; | |
| 4984 | if (cached) { | |
| 4985 | peg$currPos = cached.nextPos; | |
| 4986 | return cached.result; | |
| 4987 | } | |
| 4988 | s0 = peg$currPos; | |
| 4989 | if (input.substr(peg$currPos, 14) === peg$c86) { | |
| 4990 | s1 = peg$c86; | |
| 4991 | peg$currPos += 14; | |
| 4992 | } else { | |
| 4993 | s1 = peg$FAILED; | |
| 4994 | if (peg$silentFails === 0) { | |
| 4995 | peg$fail(peg$e86); | |
| 4996 | } | |
| 4997 | } | |
| 4998 | if (s1 !== peg$FAILED) { | |
| 4999 | s2 = peg$parseterminal(); | |
| 5000 | if (s2 !== peg$FAILED) { | |
| 5001 | peg$savedPos = s0; | |
| 5002 | s0 = peg$f1(s1, s2); | |
| 5003 | } else { | |
| 5004 | peg$currPos = s0; | |
| 5005 | s0 = peg$FAILED; | |
| 5006 | } | |
| 5007 | } else { | |
| 5008 | peg$currPos = s0; | |
| 5009 | s0 = peg$FAILED; | |
| 5010 | } | |
| 5011 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5012 | return s0; | |
| 5013 | } | |
| 5014 | function peg$parseSAMPLER1DARRAYSHADOW() { | |
| 5015 | var s0, s1, s2; | |
| 5016 | var key = peg$currPos * 306 + 88; | |
| 5017 | var cached = peg$resultsCache[key]; | |
| 5018 | if (cached) { | |
| 5019 | peg$currPos = cached.nextPos; | |
| 5020 | return cached.result; | |
| 5021 | } | |
| 5022 | s0 = peg$currPos; | |
| 5023 | if (input.substr(peg$currPos, 20) === peg$c87) { | |
| 5024 | s1 = peg$c87; | |
| 5025 | peg$currPos += 20; | |
| 5026 | } else { | |
| 5027 | s1 = peg$FAILED; | |
| 5028 | if (peg$silentFails === 0) { | |
| 5029 | peg$fail(peg$e87); | |
| 5030 | } | |
| 5031 | } | |
| 5032 | if (s1 !== peg$FAILED) { | |
| 5033 | s2 = peg$parseterminal(); | |
| 5034 | if (s2 !== peg$FAILED) { | |
| 5035 | peg$savedPos = s0; | |
| 5036 | s0 = peg$f1(s1, s2); | |
| 5037 | } else { | |
| 5038 | peg$currPos = s0; | |
| 5039 | s0 = peg$FAILED; | |
| 5040 | } | |
| 5041 | } else { | |
| 5042 | peg$currPos = s0; | |
| 5043 | s0 = peg$FAILED; | |
| 5044 | } | |
| 5045 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5046 | return s0; | |
| 5047 | } | |
| 5048 | function peg$parseSAMPLER2DARRAYSHADOW() { | |
| 5049 | var s0, s1, s2; | |
| 5050 | var key = peg$currPos * 306 + 89; | |
| 5051 | var cached = peg$resultsCache[key]; | |
| 5052 | if (cached) { | |
| 5053 | peg$currPos = cached.nextPos; | |
| 5054 | return cached.result; | |
| 5055 | } | |
| 5056 | s0 = peg$currPos; | |
| 5057 | if (input.substr(peg$currPos, 20) === peg$c88) { | |
| 5058 | s1 = peg$c88; | |
| 5059 | peg$currPos += 20; | |
| 5060 | } else { | |
| 5061 | s1 = peg$FAILED; | |
| 5062 | if (peg$silentFails === 0) { | |
| 5063 | peg$fail(peg$e88); | |
| 5064 | } | |
| 5065 | } | |
| 5066 | if (s1 !== peg$FAILED) { | |
| 5067 | s2 = peg$parseterminal(); | |
| 5068 | if (s2 !== peg$FAILED) { | |
| 5069 | peg$savedPos = s0; | |
| 5070 | s0 = peg$f1(s1, s2); | |
| 5071 | } else { | |
| 5072 | peg$currPos = s0; | |
| 5073 | s0 = peg$FAILED; | |
| 5074 | } | |
| 5075 | } else { | |
| 5076 | peg$currPos = s0; | |
| 5077 | s0 = peg$FAILED; | |
| 5078 | } | |
| 5079 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5080 | return s0; | |
| 5081 | } | |
| 5082 | function peg$parseISAMPLER1D() { | |
| 5083 | var s0, s1, s2; | |
| 5084 | var key = peg$currPos * 306 + 90; | |
| 5085 | var cached = peg$resultsCache[key]; | |
| 5086 | if (cached) { | |
| 5087 | peg$currPos = cached.nextPos; | |
| 5088 | return cached.result; | |
| 5089 | } | |
| 5090 | s0 = peg$currPos; | |
| 5091 | if (input.substr(peg$currPos, 10) === peg$c89) { | |
| 5092 | s1 = peg$c89; | |
| 5093 | peg$currPos += 10; | |
| 5094 | } else { | |
| 5095 | s1 = peg$FAILED; | |
| 5096 | if (peg$silentFails === 0) { | |
| 5097 | peg$fail(peg$e89); | |
| 5098 | } | |
| 5099 | } | |
| 5100 | if (s1 !== peg$FAILED) { | |
| 5101 | s2 = peg$parseterminal(); | |
| 5102 | if (s2 !== peg$FAILED) { | |
| 5103 | peg$savedPos = s0; | |
| 5104 | s0 = peg$f1(s1, s2); | |
| 5105 | } else { | |
| 5106 | peg$currPos = s0; | |
| 5107 | s0 = peg$FAILED; | |
| 5108 | } | |
| 5109 | } else { | |
| 5110 | peg$currPos = s0; | |
| 5111 | s0 = peg$FAILED; | |
| 5112 | } | |
| 5113 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5114 | return s0; | |
| 5115 | } | |
| 5116 | function peg$parseISAMPLER2D() { | |
| 5117 | var s0, s1, s2; | |
| 5118 | var key = peg$currPos * 306 + 91; | |
| 5119 | var cached = peg$resultsCache[key]; | |
| 5120 | if (cached) { | |
| 5121 | peg$currPos = cached.nextPos; | |
| 5122 | return cached.result; | |
| 5123 | } | |
| 5124 | s0 = peg$currPos; | |
| 5125 | if (input.substr(peg$currPos, 10) === peg$c90) { | |
| 5126 | s1 = peg$c90; | |
| 5127 | peg$currPos += 10; | |
| 5128 | } else { | |
| 5129 | s1 = peg$FAILED; | |
| 5130 | if (peg$silentFails === 0) { | |
| 5131 | peg$fail(peg$e90); | |
| 5132 | } | |
| 5133 | } | |
| 5134 | if (s1 !== peg$FAILED) { | |
| 5135 | s2 = peg$parseterminal(); | |
| 5136 | if (s2 !== peg$FAILED) { | |
| 5137 | peg$savedPos = s0; | |
| 5138 | s0 = peg$f1(s1, s2); | |
| 5139 | } else { | |
| 5140 | peg$currPos = s0; | |
| 5141 | s0 = peg$FAILED; | |
| 5142 | } | |
| 5143 | } else { | |
| 5144 | peg$currPos = s0; | |
| 5145 | s0 = peg$FAILED; | |
| 5146 | } | |
| 5147 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5148 | return s0; | |
| 5149 | } | |
| 5150 | function peg$parseISAMPLER3D() { | |
| 5151 | var s0, s1, s2; | |
| 5152 | var key = peg$currPos * 306 + 92; | |
| 5153 | var cached = peg$resultsCache[key]; | |
| 5154 | if (cached) { | |
| 5155 | peg$currPos = cached.nextPos; | |
| 5156 | return cached.result; | |
| 5157 | } | |
| 5158 | s0 = peg$currPos; | |
| 5159 | if (input.substr(peg$currPos, 10) === peg$c91) { | |
| 5160 | s1 = peg$c91; | |
| 5161 | peg$currPos += 10; | |
| 5162 | } else { | |
| 5163 | s1 = peg$FAILED; | |
| 5164 | if (peg$silentFails === 0) { | |
| 5165 | peg$fail(peg$e91); | |
| 5166 | } | |
| 5167 | } | |
| 5168 | if (s1 !== peg$FAILED) { | |
| 5169 | s2 = peg$parseterminal(); | |
| 5170 | if (s2 !== peg$FAILED) { | |
| 5171 | peg$savedPos = s0; | |
| 5172 | s0 = peg$f1(s1, s2); | |
| 5173 | } else { | |
| 5174 | peg$currPos = s0; | |
| 5175 | s0 = peg$FAILED; | |
| 5176 | } | |
| 5177 | } else { | |
| 5178 | peg$currPos = s0; | |
| 5179 | s0 = peg$FAILED; | |
| 5180 | } | |
| 5181 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5182 | return s0; | |
| 5183 | } | |
| 5184 | function peg$parseISAMPLERCUBE() { | |
| 5185 | var s0, s1, s2; | |
| 5186 | var key = peg$currPos * 306 + 93; | |
| 5187 | var cached = peg$resultsCache[key]; | |
| 5188 | if (cached) { | |
| 5189 | peg$currPos = cached.nextPos; | |
| 5190 | return cached.result; | |
| 5191 | } | |
| 5192 | s0 = peg$currPos; | |
| 5193 | if (input.substr(peg$currPos, 12) === peg$c92) { | |
| 5194 | s1 = peg$c92; | |
| 5195 | peg$currPos += 12; | |
| 5196 | } else { | |
| 5197 | s1 = peg$FAILED; | |
| 5198 | if (peg$silentFails === 0) { | |
| 5199 | peg$fail(peg$e92); | |
| 5200 | } | |
| 5201 | } | |
| 5202 | if (s1 !== peg$FAILED) { | |
| 5203 | s2 = peg$parseterminal(); | |
| 5204 | if (s2 !== peg$FAILED) { | |
| 5205 | peg$savedPos = s0; | |
| 5206 | s0 = peg$f1(s1, s2); | |
| 5207 | } else { | |
| 5208 | peg$currPos = s0; | |
| 5209 | s0 = peg$FAILED; | |
| 5210 | } | |
| 5211 | } else { | |
| 5212 | peg$currPos = s0; | |
| 5213 | s0 = peg$FAILED; | |
| 5214 | } | |
| 5215 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5216 | return s0; | |
| 5217 | } | |
| 5218 | function peg$parseISAMPLER1DARRAY() { | |
| 5219 | var s0, s1, s2; | |
| 5220 | var key = peg$currPos * 306 + 94; | |
| 5221 | var cached = peg$resultsCache[key]; | |
| 5222 | if (cached) { | |
| 5223 | peg$currPos = cached.nextPos; | |
| 5224 | return cached.result; | |
| 5225 | } | |
| 5226 | s0 = peg$currPos; | |
| 5227 | if (input.substr(peg$currPos, 15) === peg$c93) { | |
| 5228 | s1 = peg$c93; | |
| 5229 | peg$currPos += 15; | |
| 5230 | } else { | |
| 5231 | s1 = peg$FAILED; | |
| 5232 | if (peg$silentFails === 0) { | |
| 5233 | peg$fail(peg$e93); | |
| 5234 | } | |
| 5235 | } | |
| 5236 | if (s1 !== peg$FAILED) { | |
| 5237 | s2 = peg$parseterminal(); | |
| 5238 | if (s2 !== peg$FAILED) { | |
| 5239 | peg$savedPos = s0; | |
| 5240 | s0 = peg$f1(s1, s2); | |
| 5241 | } else { | |
| 5242 | peg$currPos = s0; | |
| 5243 | s0 = peg$FAILED; | |
| 5244 | } | |
| 5245 | } else { | |
| 5246 | peg$currPos = s0; | |
| 5247 | s0 = peg$FAILED; | |
| 5248 | } | |
| 5249 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5250 | return s0; | |
| 5251 | } | |
| 5252 | function peg$parseISAMPLER2DARRAY() { | |
| 5253 | var s0, s1, s2; | |
| 5254 | var key = peg$currPos * 306 + 95; | |
| 5255 | var cached = peg$resultsCache[key]; | |
| 5256 | if (cached) { | |
| 5257 | peg$currPos = cached.nextPos; | |
| 5258 | return cached.result; | |
| 5259 | } | |
| 5260 | s0 = peg$currPos; | |
| 5261 | if (input.substr(peg$currPos, 15) === peg$c94) { | |
| 5262 | s1 = peg$c94; | |
| 5263 | peg$currPos += 15; | |
| 5264 | } else { | |
| 5265 | s1 = peg$FAILED; | |
| 5266 | if (peg$silentFails === 0) { | |
| 5267 | peg$fail(peg$e94); | |
| 5268 | } | |
| 5269 | } | |
| 5270 | if (s1 !== peg$FAILED) { | |
| 5271 | s2 = peg$parseterminal(); | |
| 5272 | if (s2 !== peg$FAILED) { | |
| 5273 | peg$savedPos = s0; | |
| 5274 | s0 = peg$f1(s1, s2); | |
| 5275 | } else { | |
| 5276 | peg$currPos = s0; | |
| 5277 | s0 = peg$FAILED; | |
| 5278 | } | |
| 5279 | } else { | |
| 5280 | peg$currPos = s0; | |
| 5281 | s0 = peg$FAILED; | |
| 5282 | } | |
| 5283 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5284 | return s0; | |
| 5285 | } | |
| 5286 | function peg$parseUSAMPLER1D() { | |
| 5287 | var s0, s1, s2; | |
| 5288 | var key = peg$currPos * 306 + 96; | |
| 5289 | var cached = peg$resultsCache[key]; | |
| 5290 | if (cached) { | |
| 5291 | peg$currPos = cached.nextPos; | |
| 5292 | return cached.result; | |
| 5293 | } | |
| 5294 | s0 = peg$currPos; | |
| 5295 | if (input.substr(peg$currPos, 10) === peg$c95) { | |
| 5296 | s1 = peg$c95; | |
| 5297 | peg$currPos += 10; | |
| 5298 | } else { | |
| 5299 | s1 = peg$FAILED; | |
| 5300 | if (peg$silentFails === 0) { | |
| 5301 | peg$fail(peg$e95); | |
| 5302 | } | |
| 5303 | } | |
| 5304 | if (s1 !== peg$FAILED) { | |
| 5305 | s2 = peg$parseterminal(); | |
| 5306 | if (s2 !== peg$FAILED) { | |
| 5307 | peg$savedPos = s0; | |
| 5308 | s0 = peg$f1(s1, s2); | |
| 5309 | } else { | |
| 5310 | peg$currPos = s0; | |
| 5311 | s0 = peg$FAILED; | |
| 5312 | } | |
| 5313 | } else { | |
| 5314 | peg$currPos = s0; | |
| 5315 | s0 = peg$FAILED; | |
| 5316 | } | |
| 5317 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5318 | return s0; | |
| 5319 | } | |
| 5320 | function peg$parseUSAMPLER2D() { | |
| 5321 | var s0, s1, s2; | |
| 5322 | var key = peg$currPos * 306 + 97; | |
| 5323 | var cached = peg$resultsCache[key]; | |
| 5324 | if (cached) { | |
| 5325 | peg$currPos = cached.nextPos; | |
| 5326 | return cached.result; | |
| 5327 | } | |
| 5328 | s0 = peg$currPos; | |
| 5329 | if (input.substr(peg$currPos, 10) === peg$c96) { | |
| 5330 | s1 = peg$c96; | |
| 5331 | peg$currPos += 10; | |
| 5332 | } else { | |
| 5333 | s1 = peg$FAILED; | |
| 5334 | if (peg$silentFails === 0) { | |
| 5335 | peg$fail(peg$e96); | |
| 5336 | } | |
| 5337 | } | |
| 5338 | if (s1 !== peg$FAILED) { | |
| 5339 | s2 = peg$parseterminal(); | |
| 5340 | if (s2 !== peg$FAILED) { | |
| 5341 | peg$savedPos = s0; | |
| 5342 | s0 = peg$f1(s1, s2); | |
| 5343 | } else { | |
| 5344 | peg$currPos = s0; | |
| 5345 | s0 = peg$FAILED; | |
| 5346 | } | |
| 5347 | } else { | |
| 5348 | peg$currPos = s0; | |
| 5349 | s0 = peg$FAILED; | |
| 5350 | } | |
| 5351 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5352 | return s0; | |
| 5353 | } | |
| 5354 | function peg$parseUSAMPLER3D() { | |
| 5355 | var s0, s1, s2; | |
| 5356 | var key = peg$currPos * 306 + 98; | |
| 5357 | var cached = peg$resultsCache[key]; | |
| 5358 | if (cached) { | |
| 5359 | peg$currPos = cached.nextPos; | |
| 5360 | return cached.result; | |
| 5361 | } | |
| 5362 | s0 = peg$currPos; | |
| 5363 | if (input.substr(peg$currPos, 10) === peg$c97) { | |
| 5364 | s1 = peg$c97; | |
| 5365 | peg$currPos += 10; | |
| 5366 | } else { | |
| 5367 | s1 = peg$FAILED; | |
| 5368 | if (peg$silentFails === 0) { | |
| 5369 | peg$fail(peg$e97); | |
| 5370 | } | |
| 5371 | } | |
| 5372 | if (s1 !== peg$FAILED) { | |
| 5373 | s2 = peg$parseterminal(); | |
| 5374 | if (s2 !== peg$FAILED) { | |
| 5375 | peg$savedPos = s0; | |
| 5376 | s0 = peg$f1(s1, s2); | |
| 5377 | } else { | |
| 5378 | peg$currPos = s0; | |
| 5379 | s0 = peg$FAILED; | |
| 5380 | } | |
| 5381 | } else { | |
| 5382 | peg$currPos = s0; | |
| 5383 | s0 = peg$FAILED; | |
| 5384 | } | |
| 5385 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5386 | return s0; | |
| 5387 | } | |
| 5388 | function peg$parseUSAMPLERCUBE() { | |
| 5389 | var s0, s1, s2; | |
| 5390 | var key = peg$currPos * 306 + 99; | |
| 5391 | var cached = peg$resultsCache[key]; | |
| 5392 | if (cached) { | |
| 5393 | peg$currPos = cached.nextPos; | |
| 5394 | return cached.result; | |
| 5395 | } | |
| 5396 | s0 = peg$currPos; | |
| 5397 | if (input.substr(peg$currPos, 12) === peg$c98) { | |
| 5398 | s1 = peg$c98; | |
| 5399 | peg$currPos += 12; | |
| 5400 | } else { | |
| 5401 | s1 = peg$FAILED; | |
| 5402 | if (peg$silentFails === 0) { | |
| 5403 | peg$fail(peg$e98); | |
| 5404 | } | |
| 5405 | } | |
| 5406 | if (s1 !== peg$FAILED) { | |
| 5407 | s2 = peg$parseterminal(); | |
| 5408 | if (s2 !== peg$FAILED) { | |
| 5409 | peg$savedPos = s0; | |
| 5410 | s0 = peg$f1(s1, s2); | |
| 5411 | } else { | |
| 5412 | peg$currPos = s0; | |
| 5413 | s0 = peg$FAILED; | |
| 5414 | } | |
| 5415 | } else { | |
| 5416 | peg$currPos = s0; | |
| 5417 | s0 = peg$FAILED; | |
| 5418 | } | |
| 5419 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5420 | return s0; | |
| 5421 | } | |
| 5422 | function peg$parseUSAMPLER1DARRAY() { | |
| 5423 | var s0, s1, s2; | |
| 5424 | var key = peg$currPos * 306 + 100; | |
| 5425 | var cached = peg$resultsCache[key]; | |
| 5426 | if (cached) { | |
| 5427 | peg$currPos = cached.nextPos; | |
| 5428 | return cached.result; | |
| 5429 | } | |
| 5430 | s0 = peg$currPos; | |
| 5431 | if (input.substr(peg$currPos, 15) === peg$c99) { | |
| 5432 | s1 = peg$c99; | |
| 5433 | peg$currPos += 15; | |
| 5434 | } else { | |
| 5435 | s1 = peg$FAILED; | |
| 5436 | if (peg$silentFails === 0) { | |
| 5437 | peg$fail(peg$e99); | |
| 5438 | } | |
| 5439 | } | |
| 5440 | if (s1 !== peg$FAILED) { | |
| 5441 | s2 = peg$parseterminal(); | |
| 5442 | if (s2 !== peg$FAILED) { | |
| 5443 | peg$savedPos = s0; | |
| 5444 | s0 = peg$f1(s1, s2); | |
| 5445 | } else { | |
| 5446 | peg$currPos = s0; | |
| 5447 | s0 = peg$FAILED; | |
| 5448 | } | |
| 5449 | } else { | |
| 5450 | peg$currPos = s0; | |
| 5451 | s0 = peg$FAILED; | |
| 5452 | } | |
| 5453 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5454 | return s0; | |
| 5455 | } | |
| 5456 | function peg$parseUSAMPLER2DARRAY() { | |
| 5457 | var s0, s1, s2; | |
| 5458 | var key = peg$currPos * 306 + 101; | |
| 5459 | var cached = peg$resultsCache[key]; | |
| 5460 | if (cached) { | |
| 5461 | peg$currPos = cached.nextPos; | |
| 5462 | return cached.result; | |
| 5463 | } | |
| 5464 | s0 = peg$currPos; | |
| 5465 | if (input.substr(peg$currPos, 15) === peg$c100) { | |
| 5466 | s1 = peg$c100; | |
| 5467 | peg$currPos += 15; | |
| 5468 | } else { | |
| 5469 | s1 = peg$FAILED; | |
| 5470 | if (peg$silentFails === 0) { | |
| 5471 | peg$fail(peg$e100); | |
| 5472 | } | |
| 5473 | } | |
| 5474 | if (s1 !== peg$FAILED) { | |
| 5475 | s2 = peg$parseterminal(); | |
| 5476 | if (s2 !== peg$FAILED) { | |
| 5477 | peg$savedPos = s0; | |
| 5478 | s0 = peg$f1(s1, s2); | |
| 5479 | } else { | |
| 5480 | peg$currPos = s0; | |
| 5481 | s0 = peg$FAILED; | |
| 5482 | } | |
| 5483 | } else { | |
| 5484 | peg$currPos = s0; | |
| 5485 | s0 = peg$FAILED; | |
| 5486 | } | |
| 5487 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5488 | return s0; | |
| 5489 | } | |
| 5490 | function peg$parseSAMPLER2DRECT() { | |
| 5491 | var s0, s1, s2; | |
| 5492 | var key = peg$currPos * 306 + 102; | |
| 5493 | var cached = peg$resultsCache[key]; | |
| 5494 | if (cached) { | |
| 5495 | peg$currPos = cached.nextPos; | |
| 5496 | return cached.result; | |
| 5497 | } | |
| 5498 | s0 = peg$currPos; | |
| 5499 | if (input.substr(peg$currPos, 13) === peg$c101) { | |
| 5500 | s1 = peg$c101; | |
| 5501 | peg$currPos += 13; | |
| 5502 | } else { | |
| 5503 | s1 = peg$FAILED; | |
| 5504 | if (peg$silentFails === 0) { | |
| 5505 | peg$fail(peg$e101); | |
| 5506 | } | |
| 5507 | } | |
| 5508 | if (s1 !== peg$FAILED) { | |
| 5509 | s2 = peg$parseterminal(); | |
| 5510 | if (s2 !== peg$FAILED) { | |
| 5511 | peg$savedPos = s0; | |
| 5512 | s0 = peg$f1(s1, s2); | |
| 5513 | } else { | |
| 5514 | peg$currPos = s0; | |
| 5515 | s0 = peg$FAILED; | |
| 5516 | } | |
| 5517 | } else { | |
| 5518 | peg$currPos = s0; | |
| 5519 | s0 = peg$FAILED; | |
| 5520 | } | |
| 5521 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5522 | return s0; | |
| 5523 | } | |
| 5524 | function peg$parseSAMPLER2DRECTSHADOW() { | |
| 5525 | var s0, s1, s2; | |
| 5526 | var key = peg$currPos * 306 + 103; | |
| 5527 | var cached = peg$resultsCache[key]; | |
| 5528 | if (cached) { | |
| 5529 | peg$currPos = cached.nextPos; | |
| 5530 | return cached.result; | |
| 5531 | } | |
| 5532 | s0 = peg$currPos; | |
| 5533 | if (input.substr(peg$currPos, 19) === peg$c102) { | |
| 5534 | s1 = peg$c102; | |
| 5535 | peg$currPos += 19; | |
| 5536 | } else { | |
| 5537 | s1 = peg$FAILED; | |
| 5538 | if (peg$silentFails === 0) { | |
| 5539 | peg$fail(peg$e102); | |
| 5540 | } | |
| 5541 | } | |
| 5542 | if (s1 !== peg$FAILED) { | |
| 5543 | s2 = peg$parseterminal(); | |
| 5544 | if (s2 !== peg$FAILED) { | |
| 5545 | peg$savedPos = s0; | |
| 5546 | s0 = peg$f1(s1, s2); | |
| 5547 | } else { | |
| 5548 | peg$currPos = s0; | |
| 5549 | s0 = peg$FAILED; | |
| 5550 | } | |
| 5551 | } else { | |
| 5552 | peg$currPos = s0; | |
| 5553 | s0 = peg$FAILED; | |
| 5554 | } | |
| 5555 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5556 | return s0; | |
| 5557 | } | |
| 5558 | function peg$parseISAMPLER2DRECT() { | |
| 5559 | var s0, s1, s2; | |
| 5560 | var key = peg$currPos * 306 + 104; | |
| 5561 | var cached = peg$resultsCache[key]; | |
| 5562 | if (cached) { | |
| 5563 | peg$currPos = cached.nextPos; | |
| 5564 | return cached.result; | |
| 5565 | } | |
| 5566 | s0 = peg$currPos; | |
| 5567 | if (input.substr(peg$currPos, 14) === peg$c103) { | |
| 5568 | s1 = peg$c103; | |
| 5569 | peg$currPos += 14; | |
| 5570 | } else { | |
| 5571 | s1 = peg$FAILED; | |
| 5572 | if (peg$silentFails === 0) { | |
| 5573 | peg$fail(peg$e103); | |
| 5574 | } | |
| 5575 | } | |
| 5576 | if (s1 !== peg$FAILED) { | |
| 5577 | s2 = peg$parseterminal(); | |
| 5578 | if (s2 !== peg$FAILED) { | |
| 5579 | peg$savedPos = s0; | |
| 5580 | s0 = peg$f1(s1, s2); | |
| 5581 | } else { | |
| 5582 | peg$currPos = s0; | |
| 5583 | s0 = peg$FAILED; | |
| 5584 | } | |
| 5585 | } else { | |
| 5586 | peg$currPos = s0; | |
| 5587 | s0 = peg$FAILED; | |
| 5588 | } | |
| 5589 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5590 | return s0; | |
| 5591 | } | |
| 5592 | function peg$parseUSAMPLER2DRECT() { | |
| 5593 | var s0, s1, s2; | |
| 5594 | var key = peg$currPos * 306 + 105; | |
| 5595 | var cached = peg$resultsCache[key]; | |
| 5596 | if (cached) { | |
| 5597 | peg$currPos = cached.nextPos; | |
| 5598 | return cached.result; | |
| 5599 | } | |
| 5600 | s0 = peg$currPos; | |
| 5601 | if (input.substr(peg$currPos, 14) === peg$c104) { | |
| 5602 | s1 = peg$c104; | |
| 5603 | peg$currPos += 14; | |
| 5604 | } else { | |
| 5605 | s1 = peg$FAILED; | |
| 5606 | if (peg$silentFails === 0) { | |
| 5607 | peg$fail(peg$e104); | |
| 5608 | } | |
| 5609 | } | |
| 5610 | if (s1 !== peg$FAILED) { | |
| 5611 | s2 = peg$parseterminal(); | |
| 5612 | if (s2 !== peg$FAILED) { | |
| 5613 | peg$savedPos = s0; | |
| 5614 | s0 = peg$f1(s1, s2); | |
| 5615 | } else { | |
| 5616 | peg$currPos = s0; | |
| 5617 | s0 = peg$FAILED; | |
| 5618 | } | |
| 5619 | } else { | |
| 5620 | peg$currPos = s0; | |
| 5621 | s0 = peg$FAILED; | |
| 5622 | } | |
| 5623 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5624 | return s0; | |
| 5625 | } | |
| 5626 | function peg$parseSAMPLERBUFFER() { | |
| 5627 | var s0, s1, s2; | |
| 5628 | var key = peg$currPos * 306 + 106; | |
| 5629 | var cached = peg$resultsCache[key]; | |
| 5630 | if (cached) { | |
| 5631 | peg$currPos = cached.nextPos; | |
| 5632 | return cached.result; | |
| 5633 | } | |
| 5634 | s0 = peg$currPos; | |
| 5635 | if (input.substr(peg$currPos, 13) === peg$c105) { | |
| 5636 | s1 = peg$c105; | |
| 5637 | peg$currPos += 13; | |
| 5638 | } else { | |
| 5639 | s1 = peg$FAILED; | |
| 5640 | if (peg$silentFails === 0) { | |
| 5641 | peg$fail(peg$e105); | |
| 5642 | } | |
| 5643 | } | |
| 5644 | if (s1 !== peg$FAILED) { | |
| 5645 | s2 = peg$parseterminal(); | |
| 5646 | if (s2 !== peg$FAILED) { | |
| 5647 | peg$savedPos = s0; | |
| 5648 | s0 = peg$f1(s1, s2); | |
| 5649 | } else { | |
| 5650 | peg$currPos = s0; | |
| 5651 | s0 = peg$FAILED; | |
| 5652 | } | |
| 5653 | } else { | |
| 5654 | peg$currPos = s0; | |
| 5655 | s0 = peg$FAILED; | |
| 5656 | } | |
| 5657 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5658 | return s0; | |
| 5659 | } | |
| 5660 | function peg$parseISAMPLERBUFFER() { | |
| 5661 | var s0, s1, s2; | |
| 5662 | var key = peg$currPos * 306 + 107; | |
| 5663 | var cached = peg$resultsCache[key]; | |
| 5664 | if (cached) { | |
| 5665 | peg$currPos = cached.nextPos; | |
| 5666 | return cached.result; | |
| 5667 | } | |
| 5668 | s0 = peg$currPos; | |
| 5669 | if (input.substr(peg$currPos, 14) === peg$c106) { | |
| 5670 | s1 = peg$c106; | |
| 5671 | peg$currPos += 14; | |
| 5672 | } else { | |
| 5673 | s1 = peg$FAILED; | |
| 5674 | if (peg$silentFails === 0) { | |
| 5675 | peg$fail(peg$e106); | |
| 5676 | } | |
| 5677 | } | |
| 5678 | if (s1 !== peg$FAILED) { | |
| 5679 | s2 = peg$parseterminal(); | |
| 5680 | if (s2 !== peg$FAILED) { | |
| 5681 | peg$savedPos = s0; | |
| 5682 | s0 = peg$f1(s1, s2); | |
| 5683 | } else { | |
| 5684 | peg$currPos = s0; | |
| 5685 | s0 = peg$FAILED; | |
| 5686 | } | |
| 5687 | } else { | |
| 5688 | peg$currPos = s0; | |
| 5689 | s0 = peg$FAILED; | |
| 5690 | } | |
| 5691 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5692 | return s0; | |
| 5693 | } | |
| 5694 | function peg$parseUSAMPLERBUFFER() { | |
| 5695 | var s0, s1, s2; | |
| 5696 | var key = peg$currPos * 306 + 108; | |
| 5697 | var cached = peg$resultsCache[key]; | |
| 5698 | if (cached) { | |
| 5699 | peg$currPos = cached.nextPos; | |
| 5700 | return cached.result; | |
| 5701 | } | |
| 5702 | s0 = peg$currPos; | |
| 5703 | if (input.substr(peg$currPos, 14) === peg$c107) { | |
| 5704 | s1 = peg$c107; | |
| 5705 | peg$currPos += 14; | |
| 5706 | } else { | |
| 5707 | s1 = peg$FAILED; | |
| 5708 | if (peg$silentFails === 0) { | |
| 5709 | peg$fail(peg$e107); | |
| 5710 | } | |
| 5711 | } | |
| 5712 | if (s1 !== peg$FAILED) { | |
| 5713 | s2 = peg$parseterminal(); | |
| 5714 | if (s2 !== peg$FAILED) { | |
| 5715 | peg$savedPos = s0; | |
| 5716 | s0 = peg$f1(s1, s2); | |
| 5717 | } else { | |
| 5718 | peg$currPos = s0; | |
| 5719 | s0 = peg$FAILED; | |
| 5720 | } | |
| 5721 | } else { | |
| 5722 | peg$currPos = s0; | |
| 5723 | s0 = peg$FAILED; | |
| 5724 | } | |
| 5725 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5726 | return s0; | |
| 5727 | } | |
| 5728 | function peg$parseSAMPLERCUBEARRAY() { | |
| 5729 | var s0, s1, s2; | |
| 5730 | var key = peg$currPos * 306 + 109; | |
| 5731 | var cached = peg$resultsCache[key]; | |
| 5732 | if (cached) { | |
| 5733 | peg$currPos = cached.nextPos; | |
| 5734 | return cached.result; | |
| 5735 | } | |
| 5736 | s0 = peg$currPos; | |
| 5737 | if (input.substr(peg$currPos, 16) === peg$c108) { | |
| 5738 | s1 = peg$c108; | |
| 5739 | peg$currPos += 16; | |
| 5740 | } else { | |
| 5741 | s1 = peg$FAILED; | |
| 5742 | if (peg$silentFails === 0) { | |
| 5743 | peg$fail(peg$e108); | |
| 5744 | } | |
| 5745 | } | |
| 5746 | if (s1 !== peg$FAILED) { | |
| 5747 | s2 = peg$parseterminal(); | |
| 5748 | if (s2 !== peg$FAILED) { | |
| 5749 | peg$savedPos = s0; | |
| 5750 | s0 = peg$f1(s1, s2); | |
| 5751 | } else { | |
| 5752 | peg$currPos = s0; | |
| 5753 | s0 = peg$FAILED; | |
| 5754 | } | |
| 5755 | } else { | |
| 5756 | peg$currPos = s0; | |
| 5757 | s0 = peg$FAILED; | |
| 5758 | } | |
| 5759 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5760 | return s0; | |
| 5761 | } | |
| 5762 | function peg$parseSAMPLERCUBEARRAYSHADOW() { | |
| 5763 | var s0, s1, s2; | |
| 5764 | var key = peg$currPos * 306 + 110; | |
| 5765 | var cached = peg$resultsCache[key]; | |
| 5766 | if (cached) { | |
| 5767 | peg$currPos = cached.nextPos; | |
| 5768 | return cached.result; | |
| 5769 | } | |
| 5770 | s0 = peg$currPos; | |
| 5771 | if (input.substr(peg$currPos, 22) === peg$c109) { | |
| 5772 | s1 = peg$c109; | |
| 5773 | peg$currPos += 22; | |
| 5774 | } else { | |
| 5775 | s1 = peg$FAILED; | |
| 5776 | if (peg$silentFails === 0) { | |
| 5777 | peg$fail(peg$e109); | |
| 5778 | } | |
| 5779 | } | |
| 5780 | if (s1 !== peg$FAILED) { | |
| 5781 | s2 = peg$parseterminal(); | |
| 5782 | if (s2 !== peg$FAILED) { | |
| 5783 | peg$savedPos = s0; | |
| 5784 | s0 = peg$f1(s1, s2); | |
| 5785 | } else { | |
| 5786 | peg$currPos = s0; | |
| 5787 | s0 = peg$FAILED; | |
| 5788 | } | |
| 5789 | } else { | |
| 5790 | peg$currPos = s0; | |
| 5791 | s0 = peg$FAILED; | |
| 5792 | } | |
| 5793 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5794 | return s0; | |
| 5795 | } | |
| 5796 | function peg$parseISAMPLERCUBEARRAY() { | |
| 5797 | var s0, s1, s2; | |
| 5798 | var key = peg$currPos * 306 + 111; | |
| 5799 | var cached = peg$resultsCache[key]; | |
| 5800 | if (cached) { | |
| 5801 | peg$currPos = cached.nextPos; | |
| 5802 | return cached.result; | |
| 5803 | } | |
| 5804 | s0 = peg$currPos; | |
| 5805 | if (input.substr(peg$currPos, 17) === peg$c110) { | |
| 5806 | s1 = peg$c110; | |
| 5807 | peg$currPos += 17; | |
| 5808 | } else { | |
| 5809 | s1 = peg$FAILED; | |
| 5810 | if (peg$silentFails === 0) { | |
| 5811 | peg$fail(peg$e110); | |
| 5812 | } | |
| 5813 | } | |
| 5814 | if (s1 !== peg$FAILED) { | |
| 5815 | s2 = peg$parseterminal(); | |
| 5816 | if (s2 !== peg$FAILED) { | |
| 5817 | peg$savedPos = s0; | |
| 5818 | s0 = peg$f1(s1, s2); | |
| 5819 | } else { | |
| 5820 | peg$currPos = s0; | |
| 5821 | s0 = peg$FAILED; | |
| 5822 | } | |
| 5823 | } else { | |
| 5824 | peg$currPos = s0; | |
| 5825 | s0 = peg$FAILED; | |
| 5826 | } | |
| 5827 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5828 | return s0; | |
| 5829 | } | |
| 5830 | function peg$parseUSAMPLERCUBEARRAY() { | |
| 5831 | var s0, s1, s2; | |
| 5832 | var key = peg$currPos * 306 + 112; | |
| 5833 | var cached = peg$resultsCache[key]; | |
| 5834 | if (cached) { | |
| 5835 | peg$currPos = cached.nextPos; | |
| 5836 | return cached.result; | |
| 5837 | } | |
| 5838 | s0 = peg$currPos; | |
| 5839 | if (input.substr(peg$currPos, 17) === peg$c111) { | |
| 5840 | s1 = peg$c111; | |
| 5841 | peg$currPos += 17; | |
| 5842 | } else { | |
| 5843 | s1 = peg$FAILED; | |
| 5844 | if (peg$silentFails === 0) { | |
| 5845 | peg$fail(peg$e111); | |
| 5846 | } | |
| 5847 | } | |
| 5848 | if (s1 !== peg$FAILED) { | |
| 5849 | s2 = peg$parseterminal(); | |
| 5850 | if (s2 !== peg$FAILED) { | |
| 5851 | peg$savedPos = s0; | |
| 5852 | s0 = peg$f1(s1, s2); | |
| 5853 | } else { | |
| 5854 | peg$currPos = s0; | |
| 5855 | s0 = peg$FAILED; | |
| 5856 | } | |
| 5857 | } else { | |
| 5858 | peg$currPos = s0; | |
| 5859 | s0 = peg$FAILED; | |
| 5860 | } | |
| 5861 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5862 | return s0; | |
| 5863 | } | |
| 5864 | function peg$parseSAMPLER2DMS() { | |
| 5865 | var s0, s1, s2; | |
| 5866 | var key = peg$currPos * 306 + 113; | |
| 5867 | var cached = peg$resultsCache[key]; | |
| 5868 | if (cached) { | |
| 5869 | peg$currPos = cached.nextPos; | |
| 5870 | return cached.result; | |
| 5871 | } | |
| 5872 | s0 = peg$currPos; | |
| 5873 | if (input.substr(peg$currPos, 11) === peg$c112) { | |
| 5874 | s1 = peg$c112; | |
| 5875 | peg$currPos += 11; | |
| 5876 | } else { | |
| 5877 | s1 = peg$FAILED; | |
| 5878 | if (peg$silentFails === 0) { | |
| 5879 | peg$fail(peg$e112); | |
| 5880 | } | |
| 5881 | } | |
| 5882 | if (s1 !== peg$FAILED) { | |
| 5883 | s2 = peg$parseterminal(); | |
| 5884 | if (s2 !== peg$FAILED) { | |
| 5885 | peg$savedPos = s0; | |
| 5886 | s0 = peg$f1(s1, s2); | |
| 5887 | } else { | |
| 5888 | peg$currPos = s0; | |
| 5889 | s0 = peg$FAILED; | |
| 5890 | } | |
| 5891 | } else { | |
| 5892 | peg$currPos = s0; | |
| 5893 | s0 = peg$FAILED; | |
| 5894 | } | |
| 5895 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5896 | return s0; | |
| 5897 | } | |
| 5898 | function peg$parseISAMPLER2DMS() { | |
| 5899 | var s0, s1, s2; | |
| 5900 | var key = peg$currPos * 306 + 114; | |
| 5901 | var cached = peg$resultsCache[key]; | |
| 5902 | if (cached) { | |
| 5903 | peg$currPos = cached.nextPos; | |
| 5904 | return cached.result; | |
| 5905 | } | |
| 5906 | s0 = peg$currPos; | |
| 5907 | if (input.substr(peg$currPos, 12) === peg$c113) { | |
| 5908 | s1 = peg$c113; | |
| 5909 | peg$currPos += 12; | |
| 5910 | } else { | |
| 5911 | s1 = peg$FAILED; | |
| 5912 | if (peg$silentFails === 0) { | |
| 5913 | peg$fail(peg$e113); | |
| 5914 | } | |
| 5915 | } | |
| 5916 | if (s1 !== peg$FAILED) { | |
| 5917 | s2 = peg$parseterminal(); | |
| 5918 | if (s2 !== peg$FAILED) { | |
| 5919 | peg$savedPos = s0; | |
| 5920 | s0 = peg$f1(s1, s2); | |
| 5921 | } else { | |
| 5922 | peg$currPos = s0; | |
| 5923 | s0 = peg$FAILED; | |
| 5924 | } | |
| 5925 | } else { | |
| 5926 | peg$currPos = s0; | |
| 5927 | s0 = peg$FAILED; | |
| 5928 | } | |
| 5929 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5930 | return s0; | |
| 5931 | } | |
| 5932 | function peg$parseUSAMPLER2DMS() { | |
| 5933 | var s0, s1, s2; | |
| 5934 | var key = peg$currPos * 306 + 115; | |
| 5935 | var cached = peg$resultsCache[key]; | |
| 5936 | if (cached) { | |
| 5937 | peg$currPos = cached.nextPos; | |
| 5938 | return cached.result; | |
| 5939 | } | |
| 5940 | s0 = peg$currPos; | |
| 5941 | if (input.substr(peg$currPos, 12) === peg$c114) { | |
| 5942 | s1 = peg$c114; | |
| 5943 | peg$currPos += 12; | |
| 5944 | } else { | |
| 5945 | s1 = peg$FAILED; | |
| 5946 | if (peg$silentFails === 0) { | |
| 5947 | peg$fail(peg$e114); | |
| 5948 | } | |
| 5949 | } | |
| 5950 | if (s1 !== peg$FAILED) { | |
| 5951 | s2 = peg$parseterminal(); | |
| 5952 | if (s2 !== peg$FAILED) { | |
| 5953 | peg$savedPos = s0; | |
| 5954 | s0 = peg$f1(s1, s2); | |
| 5955 | } else { | |
| 5956 | peg$currPos = s0; | |
| 5957 | s0 = peg$FAILED; | |
| 5958 | } | |
| 5959 | } else { | |
| 5960 | peg$currPos = s0; | |
| 5961 | s0 = peg$FAILED; | |
| 5962 | } | |
| 5963 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5964 | return s0; | |
| 5965 | } | |
| 5966 | function peg$parseSAMPLER2DMSARRAY() { | |
| 5967 | var s0, s1, s2; | |
| 5968 | var key = peg$currPos * 306 + 116; | |
| 5969 | var cached = peg$resultsCache[key]; | |
| 5970 | if (cached) { | |
| 5971 | peg$currPos = cached.nextPos; | |
| 5972 | return cached.result; | |
| 5973 | } | |
| 5974 | s0 = peg$currPos; | |
| 5975 | if (input.substr(peg$currPos, 16) === peg$c115) { | |
| 5976 | s1 = peg$c115; | |
| 5977 | peg$currPos += 16; | |
| 5978 | } else { | |
| 5979 | s1 = peg$FAILED; | |
| 5980 | if (peg$silentFails === 0) { | |
| 5981 | peg$fail(peg$e115); | |
| 5982 | } | |
| 5983 | } | |
| 5984 | if (s1 !== peg$FAILED) { | |
| 5985 | s2 = peg$parseterminal(); | |
| 5986 | if (s2 !== peg$FAILED) { | |
| 5987 | peg$savedPos = s0; | |
| 5988 | s0 = peg$f1(s1, s2); | |
| 5989 | } else { | |
| 5990 | peg$currPos = s0; | |
| 5991 | s0 = peg$FAILED; | |
| 5992 | } | |
| 5993 | } else { | |
| 5994 | peg$currPos = s0; | |
| 5995 | s0 = peg$FAILED; | |
| 5996 | } | |
| 5997 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 5998 | return s0; | |
| 5999 | } | |
| 6000 | function peg$parseISAMPLER2DMSARRAY() { | |
| 6001 | var s0, s1, s2; | |
| 6002 | var key = peg$currPos * 306 + 117; | |
| 6003 | var cached = peg$resultsCache[key]; | |
| 6004 | if (cached) { | |
| 6005 | peg$currPos = cached.nextPos; | |
| 6006 | return cached.result; | |
| 6007 | } | |
| 6008 | s0 = peg$currPos; | |
| 6009 | if (input.substr(peg$currPos, 17) === peg$c116) { | |
| 6010 | s1 = peg$c116; | |
| 6011 | peg$currPos += 17; | |
| 6012 | } else { | |
| 6013 | s1 = peg$FAILED; | |
| 6014 | if (peg$silentFails === 0) { | |
| 6015 | peg$fail(peg$e116); | |
| 6016 | } | |
| 6017 | } | |
| 6018 | if (s1 !== peg$FAILED) { | |
| 6019 | s2 = peg$parseterminal(); | |
| 6020 | if (s2 !== peg$FAILED) { | |
| 6021 | peg$savedPos = s0; | |
| 6022 | s0 = peg$f1(s1, s2); | |
| 6023 | } else { | |
| 6024 | peg$currPos = s0; | |
| 6025 | s0 = peg$FAILED; | |
| 6026 | } | |
| 6027 | } else { | |
| 6028 | peg$currPos = s0; | |
| 6029 | s0 = peg$FAILED; | |
| 6030 | } | |
| 6031 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6032 | return s0; | |
| 6033 | } | |
| 6034 | function peg$parseUSAMPLER2DMSARRAY() { | |
| 6035 | var s0, s1, s2; | |
| 6036 | var key = peg$currPos * 306 + 118; | |
| 6037 | var cached = peg$resultsCache[key]; | |
| 6038 | if (cached) { | |
| 6039 | peg$currPos = cached.nextPos; | |
| 6040 | return cached.result; | |
| 6041 | } | |
| 6042 | s0 = peg$currPos; | |
| 6043 | if (input.substr(peg$currPos, 17) === peg$c117) { | |
| 6044 | s1 = peg$c117; | |
| 6045 | peg$currPos += 17; | |
| 6046 | } else { | |
| 6047 | s1 = peg$FAILED; | |
| 6048 | if (peg$silentFails === 0) { | |
| 6049 | peg$fail(peg$e117); | |
| 6050 | } | |
| 6051 | } | |
| 6052 | if (s1 !== peg$FAILED) { | |
| 6053 | s2 = peg$parseterminal(); | |
| 6054 | if (s2 !== peg$FAILED) { | |
| 6055 | peg$savedPos = s0; | |
| 6056 | s0 = peg$f1(s1, s2); | |
| 6057 | } else { | |
| 6058 | peg$currPos = s0; | |
| 6059 | s0 = peg$FAILED; | |
| 6060 | } | |
| 6061 | } else { | |
| 6062 | peg$currPos = s0; | |
| 6063 | s0 = peg$FAILED; | |
| 6064 | } | |
| 6065 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6066 | return s0; | |
| 6067 | } | |
| 6068 | function peg$parseIMAGE1D() { | |
| 6069 | var s0, s1, s2; | |
| 6070 | var key = peg$currPos * 306 + 119; | |
| 6071 | var cached = peg$resultsCache[key]; | |
| 6072 | if (cached) { | |
| 6073 | peg$currPos = cached.nextPos; | |
| 6074 | return cached.result; | |
| 6075 | } | |
| 6076 | s0 = peg$currPos; | |
| 6077 | if (input.substr(peg$currPos, 7) === peg$c118) { | |
| 6078 | s1 = peg$c118; | |
| 6079 | peg$currPos += 7; | |
| 6080 | } else { | |
| 6081 | s1 = peg$FAILED; | |
| 6082 | if (peg$silentFails === 0) { | |
| 6083 | peg$fail(peg$e118); | |
| 6084 | } | |
| 6085 | } | |
| 6086 | if (s1 !== peg$FAILED) { | |
| 6087 | s2 = peg$parseterminal(); | |
| 6088 | if (s2 !== peg$FAILED) { | |
| 6089 | peg$savedPos = s0; | |
| 6090 | s0 = peg$f1(s1, s2); | |
| 6091 | } else { | |
| 6092 | peg$currPos = s0; | |
| 6093 | s0 = peg$FAILED; | |
| 6094 | } | |
| 6095 | } else { | |
| 6096 | peg$currPos = s0; | |
| 6097 | s0 = peg$FAILED; | |
| 6098 | } | |
| 6099 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6100 | return s0; | |
| 6101 | } | |
| 6102 | function peg$parseIIMAGE1D() { | |
| 6103 | var s0, s1, s2; | |
| 6104 | var key = peg$currPos * 306 + 120; | |
| 6105 | var cached = peg$resultsCache[key]; | |
| 6106 | if (cached) { | |
| 6107 | peg$currPos = cached.nextPos; | |
| 6108 | return cached.result; | |
| 6109 | } | |
| 6110 | s0 = peg$currPos; | |
| 6111 | if (input.substr(peg$currPos, 8) === peg$c119) { | |
| 6112 | s1 = peg$c119; | |
| 6113 | peg$currPos += 8; | |
| 6114 | } else { | |
| 6115 | s1 = peg$FAILED; | |
| 6116 | if (peg$silentFails === 0) { | |
| 6117 | peg$fail(peg$e119); | |
| 6118 | } | |
| 6119 | } | |
| 6120 | if (s1 !== peg$FAILED) { | |
| 6121 | s2 = peg$parseterminal(); | |
| 6122 | if (s2 !== peg$FAILED) { | |
| 6123 | peg$savedPos = s0; | |
| 6124 | s0 = peg$f1(s1, s2); | |
| 6125 | } else { | |
| 6126 | peg$currPos = s0; | |
| 6127 | s0 = peg$FAILED; | |
| 6128 | } | |
| 6129 | } else { | |
| 6130 | peg$currPos = s0; | |
| 6131 | s0 = peg$FAILED; | |
| 6132 | } | |
| 6133 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6134 | return s0; | |
| 6135 | } | |
| 6136 | function peg$parseUIMAGE1D() { | |
| 6137 | var s0, s1, s2; | |
| 6138 | var key = peg$currPos * 306 + 121; | |
| 6139 | var cached = peg$resultsCache[key]; | |
| 6140 | if (cached) { | |
| 6141 | peg$currPos = cached.nextPos; | |
| 6142 | return cached.result; | |
| 6143 | } | |
| 6144 | s0 = peg$currPos; | |
| 6145 | if (input.substr(peg$currPos, 8) === peg$c120) { | |
| 6146 | s1 = peg$c120; | |
| 6147 | peg$currPos += 8; | |
| 6148 | } else { | |
| 6149 | s1 = peg$FAILED; | |
| 6150 | if (peg$silentFails === 0) { | |
| 6151 | peg$fail(peg$e120); | |
| 6152 | } | |
| 6153 | } | |
| 6154 | if (s1 !== peg$FAILED) { | |
| 6155 | s2 = peg$parseterminal(); | |
| 6156 | if (s2 !== peg$FAILED) { | |
| 6157 | peg$savedPos = s0; | |
| 6158 | s0 = peg$f1(s1, s2); | |
| 6159 | } else { | |
| 6160 | peg$currPos = s0; | |
| 6161 | s0 = peg$FAILED; | |
| 6162 | } | |
| 6163 | } else { | |
| 6164 | peg$currPos = s0; | |
| 6165 | s0 = peg$FAILED; | |
| 6166 | } | |
| 6167 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6168 | return s0; | |
| 6169 | } | |
| 6170 | function peg$parseIMAGE2D() { | |
| 6171 | var s0, s1, s2; | |
| 6172 | var key = peg$currPos * 306 + 122; | |
| 6173 | var cached = peg$resultsCache[key]; | |
| 6174 | if (cached) { | |
| 6175 | peg$currPos = cached.nextPos; | |
| 6176 | return cached.result; | |
| 6177 | } | |
| 6178 | s0 = peg$currPos; | |
| 6179 | if (input.substr(peg$currPos, 7) === peg$c121) { | |
| 6180 | s1 = peg$c121; | |
| 6181 | peg$currPos += 7; | |
| 6182 | } else { | |
| 6183 | s1 = peg$FAILED; | |
| 6184 | if (peg$silentFails === 0) { | |
| 6185 | peg$fail(peg$e121); | |
| 6186 | } | |
| 6187 | } | |
| 6188 | if (s1 !== peg$FAILED) { | |
| 6189 | s2 = peg$parseterminal(); | |
| 6190 | if (s2 !== peg$FAILED) { | |
| 6191 | peg$savedPos = s0; | |
| 6192 | s0 = peg$f1(s1, s2); | |
| 6193 | } else { | |
| 6194 | peg$currPos = s0; | |
| 6195 | s0 = peg$FAILED; | |
| 6196 | } | |
| 6197 | } else { | |
| 6198 | peg$currPos = s0; | |
| 6199 | s0 = peg$FAILED; | |
| 6200 | } | |
| 6201 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6202 | return s0; | |
| 6203 | } | |
| 6204 | function peg$parseIIMAGE2D() { | |
| 6205 | var s0, s1, s2; | |
| 6206 | var key = peg$currPos * 306 + 123; | |
| 6207 | var cached = peg$resultsCache[key]; | |
| 6208 | if (cached) { | |
| 6209 | peg$currPos = cached.nextPos; | |
| 6210 | return cached.result; | |
| 6211 | } | |
| 6212 | s0 = peg$currPos; | |
| 6213 | if (input.substr(peg$currPos, 8) === peg$c122) { | |
| 6214 | s1 = peg$c122; | |
| 6215 | peg$currPos += 8; | |
| 6216 | } else { | |
| 6217 | s1 = peg$FAILED; | |
| 6218 | if (peg$silentFails === 0) { | |
| 6219 | peg$fail(peg$e122); | |
| 6220 | } | |
| 6221 | } | |
| 6222 | if (s1 !== peg$FAILED) { | |
| 6223 | s2 = peg$parseterminal(); | |
| 6224 | if (s2 !== peg$FAILED) { | |
| 6225 | peg$savedPos = s0; | |
| 6226 | s0 = peg$f1(s1, s2); | |
| 6227 | } else { | |
| 6228 | peg$currPos = s0; | |
| 6229 | s0 = peg$FAILED; | |
| 6230 | } | |
| 6231 | } else { | |
| 6232 | peg$currPos = s0; | |
| 6233 | s0 = peg$FAILED; | |
| 6234 | } | |
| 6235 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6236 | return s0; | |
| 6237 | } | |
| 6238 | function peg$parseUIMAGE2D() { | |
| 6239 | var s0, s1, s2; | |
| 6240 | var key = peg$currPos * 306 + 124; | |
| 6241 | var cached = peg$resultsCache[key]; | |
| 6242 | if (cached) { | |
| 6243 | peg$currPos = cached.nextPos; | |
| 6244 | return cached.result; | |
| 6245 | } | |
| 6246 | s0 = peg$currPos; | |
| 6247 | if (input.substr(peg$currPos, 8) === peg$c123) { | |
| 6248 | s1 = peg$c123; | |
| 6249 | peg$currPos += 8; | |
| 6250 | } else { | |
| 6251 | s1 = peg$FAILED; | |
| 6252 | if (peg$silentFails === 0) { | |
| 6253 | peg$fail(peg$e123); | |
| 6254 | } | |
| 6255 | } | |
| 6256 | if (s1 !== peg$FAILED) { | |
| 6257 | s2 = peg$parseterminal(); | |
| 6258 | if (s2 !== peg$FAILED) { | |
| 6259 | peg$savedPos = s0; | |
| 6260 | s0 = peg$f1(s1, s2); | |
| 6261 | } else { | |
| 6262 | peg$currPos = s0; | |
| 6263 | s0 = peg$FAILED; | |
| 6264 | } | |
| 6265 | } else { | |
| 6266 | peg$currPos = s0; | |
| 6267 | s0 = peg$FAILED; | |
| 6268 | } | |
| 6269 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6270 | return s0; | |
| 6271 | } | |
| 6272 | function peg$parseIMAGE3D() { | |
| 6273 | var s0, s1, s2; | |
| 6274 | var key = peg$currPos * 306 + 125; | |
| 6275 | var cached = peg$resultsCache[key]; | |
| 6276 | if (cached) { | |
| 6277 | peg$currPos = cached.nextPos; | |
| 6278 | return cached.result; | |
| 6279 | } | |
| 6280 | s0 = peg$currPos; | |
| 6281 | if (input.substr(peg$currPos, 7) === peg$c124) { | |
| 6282 | s1 = peg$c124; | |
| 6283 | peg$currPos += 7; | |
| 6284 | } else { | |
| 6285 | s1 = peg$FAILED; | |
| 6286 | if (peg$silentFails === 0) { | |
| 6287 | peg$fail(peg$e124); | |
| 6288 | } | |
| 6289 | } | |
| 6290 | if (s1 !== peg$FAILED) { | |
| 6291 | s2 = peg$parseterminal(); | |
| 6292 | if (s2 !== peg$FAILED) { | |
| 6293 | peg$savedPos = s0; | |
| 6294 | s0 = peg$f1(s1, s2); | |
| 6295 | } else { | |
| 6296 | peg$currPos = s0; | |
| 6297 | s0 = peg$FAILED; | |
| 6298 | } | |
| 6299 | } else { | |
| 6300 | peg$currPos = s0; | |
| 6301 | s0 = peg$FAILED; | |
| 6302 | } | |
| 6303 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6304 | return s0; | |
| 6305 | } | |
| 6306 | function peg$parseIIMAGE3D() { | |
| 6307 | var s0, s1, s2; | |
| 6308 | var key = peg$currPos * 306 + 126; | |
| 6309 | var cached = peg$resultsCache[key]; | |
| 6310 | if (cached) { | |
| 6311 | peg$currPos = cached.nextPos; | |
| 6312 | return cached.result; | |
| 6313 | } | |
| 6314 | s0 = peg$currPos; | |
| 6315 | if (input.substr(peg$currPos, 8) === peg$c125) { | |
| 6316 | s1 = peg$c125; | |
| 6317 | peg$currPos += 8; | |
| 6318 | } else { | |
| 6319 | s1 = peg$FAILED; | |
| 6320 | if (peg$silentFails === 0) { | |
| 6321 | peg$fail(peg$e125); | |
| 6322 | } | |
| 6323 | } | |
| 6324 | if (s1 !== peg$FAILED) { | |
| 6325 | s2 = peg$parseterminal(); | |
| 6326 | if (s2 !== peg$FAILED) { | |
| 6327 | peg$savedPos = s0; | |
| 6328 | s0 = peg$f1(s1, s2); | |
| 6329 | } else { | |
| 6330 | peg$currPos = s0; | |
| 6331 | s0 = peg$FAILED; | |
| 6332 | } | |
| 6333 | } else { | |
| 6334 | peg$currPos = s0; | |
| 6335 | s0 = peg$FAILED; | |
| 6336 | } | |
| 6337 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6338 | return s0; | |
| 6339 | } | |
| 6340 | function peg$parseUIMAGE3D() { | |
| 6341 | var s0, s1, s2; | |
| 6342 | var key = peg$currPos * 306 + 127; | |
| 6343 | var cached = peg$resultsCache[key]; | |
| 6344 | if (cached) { | |
| 6345 | peg$currPos = cached.nextPos; | |
| 6346 | return cached.result; | |
| 6347 | } | |
| 6348 | s0 = peg$currPos; | |
| 6349 | if (input.substr(peg$currPos, 8) === peg$c126) { | |
| 6350 | s1 = peg$c126; | |
| 6351 | peg$currPos += 8; | |
| 6352 | } else { | |
| 6353 | s1 = peg$FAILED; | |
| 6354 | if (peg$silentFails === 0) { | |
| 6355 | peg$fail(peg$e126); | |
| 6356 | } | |
| 6357 | } | |
| 6358 | if (s1 !== peg$FAILED) { | |
| 6359 | s2 = peg$parseterminal(); | |
| 6360 | if (s2 !== peg$FAILED) { | |
| 6361 | peg$savedPos = s0; | |
| 6362 | s0 = peg$f1(s1, s2); | |
| 6363 | } else { | |
| 6364 | peg$currPos = s0; | |
| 6365 | s0 = peg$FAILED; | |
| 6366 | } | |
| 6367 | } else { | |
| 6368 | peg$currPos = s0; | |
| 6369 | s0 = peg$FAILED; | |
| 6370 | } | |
| 6371 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6372 | return s0; | |
| 6373 | } | |
| 6374 | function peg$parseIMAGE2DRECT() { | |
| 6375 | var s0, s1, s2; | |
| 6376 | var key = peg$currPos * 306 + 128; | |
| 6377 | var cached = peg$resultsCache[key]; | |
| 6378 | if (cached) { | |
| 6379 | peg$currPos = cached.nextPos; | |
| 6380 | return cached.result; | |
| 6381 | } | |
| 6382 | s0 = peg$currPos; | |
| 6383 | if (input.substr(peg$currPos, 11) === peg$c127) { | |
| 6384 | s1 = peg$c127; | |
| 6385 | peg$currPos += 11; | |
| 6386 | } else { | |
| 6387 | s1 = peg$FAILED; | |
| 6388 | if (peg$silentFails === 0) { | |
| 6389 | peg$fail(peg$e127); | |
| 6390 | } | |
| 6391 | } | |
| 6392 | if (s1 !== peg$FAILED) { | |
| 6393 | s2 = peg$parseterminal(); | |
| 6394 | if (s2 !== peg$FAILED) { | |
| 6395 | peg$savedPos = s0; | |
| 6396 | s0 = peg$f1(s1, s2); | |
| 6397 | } else { | |
| 6398 | peg$currPos = s0; | |
| 6399 | s0 = peg$FAILED; | |
| 6400 | } | |
| 6401 | } else { | |
| 6402 | peg$currPos = s0; | |
| 6403 | s0 = peg$FAILED; | |
| 6404 | } | |
| 6405 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6406 | return s0; | |
| 6407 | } | |
| 6408 | function peg$parseIIMAGE2DRECT() { | |
| 6409 | var s0, s1, s2; | |
| 6410 | var key = peg$currPos * 306 + 129; | |
| 6411 | var cached = peg$resultsCache[key]; | |
| 6412 | if (cached) { | |
| 6413 | peg$currPos = cached.nextPos; | |
| 6414 | return cached.result; | |
| 6415 | } | |
| 6416 | s0 = peg$currPos; | |
| 6417 | if (input.substr(peg$currPos, 12) === peg$c128) { | |
| 6418 | s1 = peg$c128; | |
| 6419 | peg$currPos += 12; | |
| 6420 | } else { | |
| 6421 | s1 = peg$FAILED; | |
| 6422 | if (peg$silentFails === 0) { | |
| 6423 | peg$fail(peg$e128); | |
| 6424 | } | |
| 6425 | } | |
| 6426 | if (s1 !== peg$FAILED) { | |
| 6427 | s2 = peg$parseterminal(); | |
| 6428 | if (s2 !== peg$FAILED) { | |
| 6429 | peg$savedPos = s0; | |
| 6430 | s0 = peg$f1(s1, s2); | |
| 6431 | } else { | |
| 6432 | peg$currPos = s0; | |
| 6433 | s0 = peg$FAILED; | |
| 6434 | } | |
| 6435 | } else { | |
| 6436 | peg$currPos = s0; | |
| 6437 | s0 = peg$FAILED; | |
| 6438 | } | |
| 6439 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6440 | return s0; | |
| 6441 | } | |
| 6442 | function peg$parseUIMAGE2DRECT() { | |
| 6443 | var s0, s1, s2; | |
| 6444 | var key = peg$currPos * 306 + 130; | |
| 6445 | var cached = peg$resultsCache[key]; | |
| 6446 | if (cached) { | |
| 6447 | peg$currPos = cached.nextPos; | |
| 6448 | return cached.result; | |
| 6449 | } | |
| 6450 | s0 = peg$currPos; | |
| 6451 | if (input.substr(peg$currPos, 12) === peg$c129) { | |
| 6452 | s1 = peg$c129; | |
| 6453 | peg$currPos += 12; | |
| 6454 | } else { | |
| 6455 | s1 = peg$FAILED; | |
| 6456 | if (peg$silentFails === 0) { | |
| 6457 | peg$fail(peg$e129); | |
| 6458 | } | |
| 6459 | } | |
| 6460 | if (s1 !== peg$FAILED) { | |
| 6461 | s2 = peg$parseterminal(); | |
| 6462 | if (s2 !== peg$FAILED) { | |
| 6463 | peg$savedPos = s0; | |
| 6464 | s0 = peg$f1(s1, s2); | |
| 6465 | } else { | |
| 6466 | peg$currPos = s0; | |
| 6467 | s0 = peg$FAILED; | |
| 6468 | } | |
| 6469 | } else { | |
| 6470 | peg$currPos = s0; | |
| 6471 | s0 = peg$FAILED; | |
| 6472 | } | |
| 6473 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6474 | return s0; | |
| 6475 | } | |
| 6476 | function peg$parseIMAGECUBE() { | |
| 6477 | var s0, s1, s2; | |
| 6478 | var key = peg$currPos * 306 + 131; | |
| 6479 | var cached = peg$resultsCache[key]; | |
| 6480 | if (cached) { | |
| 6481 | peg$currPos = cached.nextPos; | |
| 6482 | return cached.result; | |
| 6483 | } | |
| 6484 | s0 = peg$currPos; | |
| 6485 | if (input.substr(peg$currPos, 9) === peg$c130) { | |
| 6486 | s1 = peg$c130; | |
| 6487 | peg$currPos += 9; | |
| 6488 | } else { | |
| 6489 | s1 = peg$FAILED; | |
| 6490 | if (peg$silentFails === 0) { | |
| 6491 | peg$fail(peg$e130); | |
| 6492 | } | |
| 6493 | } | |
| 6494 | if (s1 !== peg$FAILED) { | |
| 6495 | s2 = peg$parseterminal(); | |
| 6496 | if (s2 !== peg$FAILED) { | |
| 6497 | peg$savedPos = s0; | |
| 6498 | s0 = peg$f1(s1, s2); | |
| 6499 | } else { | |
| 6500 | peg$currPos = s0; | |
| 6501 | s0 = peg$FAILED; | |
| 6502 | } | |
| 6503 | } else { | |
| 6504 | peg$currPos = s0; | |
| 6505 | s0 = peg$FAILED; | |
| 6506 | } | |
| 6507 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6508 | return s0; | |
| 6509 | } | |
| 6510 | function peg$parseIIMAGECUBE() { | |
| 6511 | var s0, s1, s2; | |
| 6512 | var key = peg$currPos * 306 + 132; | |
| 6513 | var cached = peg$resultsCache[key]; | |
| 6514 | if (cached) { | |
| 6515 | peg$currPos = cached.nextPos; | |
| 6516 | return cached.result; | |
| 6517 | } | |
| 6518 | s0 = peg$currPos; | |
| 6519 | if (input.substr(peg$currPos, 10) === peg$c131) { | |
| 6520 | s1 = peg$c131; | |
| 6521 | peg$currPos += 10; | |
| 6522 | } else { | |
| 6523 | s1 = peg$FAILED; | |
| 6524 | if (peg$silentFails === 0) { | |
| 6525 | peg$fail(peg$e131); | |
| 6526 | } | |
| 6527 | } | |
| 6528 | if (s1 !== peg$FAILED) { | |
| 6529 | s2 = peg$parseterminal(); | |
| 6530 | if (s2 !== peg$FAILED) { | |
| 6531 | peg$savedPos = s0; | |
| 6532 | s0 = peg$f1(s1, s2); | |
| 6533 | } else { | |
| 6534 | peg$currPos = s0; | |
| 6535 | s0 = peg$FAILED; | |
| 6536 | } | |
| 6537 | } else { | |
| 6538 | peg$currPos = s0; | |
| 6539 | s0 = peg$FAILED; | |
| 6540 | } | |
| 6541 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6542 | return s0; | |
| 6543 | } | |
| 6544 | function peg$parseUIMAGECUBE() { | |
| 6545 | var s0, s1, s2; | |
| 6546 | var key = peg$currPos * 306 + 133; | |
| 6547 | var cached = peg$resultsCache[key]; | |
| 6548 | if (cached) { | |
| 6549 | peg$currPos = cached.nextPos; | |
| 6550 | return cached.result; | |
| 6551 | } | |
| 6552 | s0 = peg$currPos; | |
| 6553 | if (input.substr(peg$currPos, 10) === peg$c132) { | |
| 6554 | s1 = peg$c132; | |
| 6555 | peg$currPos += 10; | |
| 6556 | } else { | |
| 6557 | s1 = peg$FAILED; | |
| 6558 | if (peg$silentFails === 0) { | |
| 6559 | peg$fail(peg$e132); | |
| 6560 | } | |
| 6561 | } | |
| 6562 | if (s1 !== peg$FAILED) { | |
| 6563 | s2 = peg$parseterminal(); | |
| 6564 | if (s2 !== peg$FAILED) { | |
| 6565 | peg$savedPos = s0; | |
| 6566 | s0 = peg$f1(s1, s2); | |
| 6567 | } else { | |
| 6568 | peg$currPos = s0; | |
| 6569 | s0 = peg$FAILED; | |
| 6570 | } | |
| 6571 | } else { | |
| 6572 | peg$currPos = s0; | |
| 6573 | s0 = peg$FAILED; | |
| 6574 | } | |
| 6575 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6576 | return s0; | |
| 6577 | } | |
| 6578 | function peg$parseIMAGEBUFFER() { | |
| 6579 | var s0, s1, s2; | |
| 6580 | var key = peg$currPos * 306 + 134; | |
| 6581 | var cached = peg$resultsCache[key]; | |
| 6582 | if (cached) { | |
| 6583 | peg$currPos = cached.nextPos; | |
| 6584 | return cached.result; | |
| 6585 | } | |
| 6586 | s0 = peg$currPos; | |
| 6587 | if (input.substr(peg$currPos, 11) === peg$c133) { | |
| 6588 | s1 = peg$c133; | |
| 6589 | peg$currPos += 11; | |
| 6590 | } else { | |
| 6591 | s1 = peg$FAILED; | |
| 6592 | if (peg$silentFails === 0) { | |
| 6593 | peg$fail(peg$e133); | |
| 6594 | } | |
| 6595 | } | |
| 6596 | if (s1 !== peg$FAILED) { | |
| 6597 | s2 = peg$parseterminal(); | |
| 6598 | if (s2 !== peg$FAILED) { | |
| 6599 | peg$savedPos = s0; | |
| 6600 | s0 = peg$f1(s1, s2); | |
| 6601 | } else { | |
| 6602 | peg$currPos = s0; | |
| 6603 | s0 = peg$FAILED; | |
| 6604 | } | |
| 6605 | } else { | |
| 6606 | peg$currPos = s0; | |
| 6607 | s0 = peg$FAILED; | |
| 6608 | } | |
| 6609 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6610 | return s0; | |
| 6611 | } | |
| 6612 | function peg$parseIIMAGEBUFFER() { | |
| 6613 | var s0, s1, s2; | |
| 6614 | var key = peg$currPos * 306 + 135; | |
| 6615 | var cached = peg$resultsCache[key]; | |
| 6616 | if (cached) { | |
| 6617 | peg$currPos = cached.nextPos; | |
| 6618 | return cached.result; | |
| 6619 | } | |
| 6620 | s0 = peg$currPos; | |
| 6621 | if (input.substr(peg$currPos, 12) === peg$c134) { | |
| 6622 | s1 = peg$c134; | |
| 6623 | peg$currPos += 12; | |
| 6624 | } else { | |
| 6625 | s1 = peg$FAILED; | |
| 6626 | if (peg$silentFails === 0) { | |
| 6627 | peg$fail(peg$e134); | |
| 6628 | } | |
| 6629 | } | |
| 6630 | if (s1 !== peg$FAILED) { | |
| 6631 | s2 = peg$parseterminal(); | |
| 6632 | if (s2 !== peg$FAILED) { | |
| 6633 | peg$savedPos = s0; | |
| 6634 | s0 = peg$f1(s1, s2); | |
| 6635 | } else { | |
| 6636 | peg$currPos = s0; | |
| 6637 | s0 = peg$FAILED; | |
| 6638 | } | |
| 6639 | } else { | |
| 6640 | peg$currPos = s0; | |
| 6641 | s0 = peg$FAILED; | |
| 6642 | } | |
| 6643 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6644 | return s0; | |
| 6645 | } | |
| 6646 | function peg$parseUIMAGEBUFFER() { | |
| 6647 | var s0, s1, s2; | |
| 6648 | var key = peg$currPos * 306 + 136; | |
| 6649 | var cached = peg$resultsCache[key]; | |
| 6650 | if (cached) { | |
| 6651 | peg$currPos = cached.nextPos; | |
| 6652 | return cached.result; | |
| 6653 | } | |
| 6654 | s0 = peg$currPos; | |
| 6655 | if (input.substr(peg$currPos, 12) === peg$c135) { | |
| 6656 | s1 = peg$c135; | |
| 6657 | peg$currPos += 12; | |
| 6658 | } else { | |
| 6659 | s1 = peg$FAILED; | |
| 6660 | if (peg$silentFails === 0) { | |
| 6661 | peg$fail(peg$e135); | |
| 6662 | } | |
| 6663 | } | |
| 6664 | if (s1 !== peg$FAILED) { | |
| 6665 | s2 = peg$parseterminal(); | |
| 6666 | if (s2 !== peg$FAILED) { | |
| 6667 | peg$savedPos = s0; | |
| 6668 | s0 = peg$f1(s1, s2); | |
| 6669 | } else { | |
| 6670 | peg$currPos = s0; | |
| 6671 | s0 = peg$FAILED; | |
| 6672 | } | |
| 6673 | } else { | |
| 6674 | peg$currPos = s0; | |
| 6675 | s0 = peg$FAILED; | |
| 6676 | } | |
| 6677 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6678 | return s0; | |
| 6679 | } | |
| 6680 | function peg$parseIMAGE1DARRAY() { | |
| 6681 | var s0, s1, s2; | |
| 6682 | var key = peg$currPos * 306 + 137; | |
| 6683 | var cached = peg$resultsCache[key]; | |
| 6684 | if (cached) { | |
| 6685 | peg$currPos = cached.nextPos; | |
| 6686 | return cached.result; | |
| 6687 | } | |
| 6688 | s0 = peg$currPos; | |
| 6689 | if (input.substr(peg$currPos, 12) === peg$c136) { | |
| 6690 | s1 = peg$c136; | |
| 6691 | peg$currPos += 12; | |
| 6692 | } else { | |
| 6693 | s1 = peg$FAILED; | |
| 6694 | if (peg$silentFails === 0) { | |
| 6695 | peg$fail(peg$e136); | |
| 6696 | } | |
| 6697 | } | |
| 6698 | if (s1 !== peg$FAILED) { | |
| 6699 | s2 = peg$parseterminal(); | |
| 6700 | if (s2 !== peg$FAILED) { | |
| 6701 | peg$savedPos = s0; | |
| 6702 | s0 = peg$f1(s1, s2); | |
| 6703 | } else { | |
| 6704 | peg$currPos = s0; | |
| 6705 | s0 = peg$FAILED; | |
| 6706 | } | |
| 6707 | } else { | |
| 6708 | peg$currPos = s0; | |
| 6709 | s0 = peg$FAILED; | |
| 6710 | } | |
| 6711 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6712 | return s0; | |
| 6713 | } | |
| 6714 | function peg$parseIIMAGE1DARRAY() { | |
| 6715 | var s0, s1, s2; | |
| 6716 | var key = peg$currPos * 306 + 138; | |
| 6717 | var cached = peg$resultsCache[key]; | |
| 6718 | if (cached) { | |
| 6719 | peg$currPos = cached.nextPos; | |
| 6720 | return cached.result; | |
| 6721 | } | |
| 6722 | s0 = peg$currPos; | |
| 6723 | if (input.substr(peg$currPos, 13) === peg$c137) { | |
| 6724 | s1 = peg$c137; | |
| 6725 | peg$currPos += 13; | |
| 6726 | } else { | |
| 6727 | s1 = peg$FAILED; | |
| 6728 | if (peg$silentFails === 0) { | |
| 6729 | peg$fail(peg$e137); | |
| 6730 | } | |
| 6731 | } | |
| 6732 | if (s1 !== peg$FAILED) { | |
| 6733 | s2 = peg$parseterminal(); | |
| 6734 | if (s2 !== peg$FAILED) { | |
| 6735 | peg$savedPos = s0; | |
| 6736 | s0 = peg$f1(s1, s2); | |
| 6737 | } else { | |
| 6738 | peg$currPos = s0; | |
| 6739 | s0 = peg$FAILED; | |
| 6740 | } | |
| 6741 | } else { | |
| 6742 | peg$currPos = s0; | |
| 6743 | s0 = peg$FAILED; | |
| 6744 | } | |
| 6745 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6746 | return s0; | |
| 6747 | } | |
| 6748 | function peg$parseUIMAGE1DARRAY() { | |
| 6749 | var s0, s1, s2; | |
| 6750 | var key = peg$currPos * 306 + 139; | |
| 6751 | var cached = peg$resultsCache[key]; | |
| 6752 | if (cached) { | |
| 6753 | peg$currPos = cached.nextPos; | |
| 6754 | return cached.result; | |
| 6755 | } | |
| 6756 | s0 = peg$currPos; | |
| 6757 | if (input.substr(peg$currPos, 13) === peg$c138) { | |
| 6758 | s1 = peg$c138; | |
| 6759 | peg$currPos += 13; | |
| 6760 | } else { | |
| 6761 | s1 = peg$FAILED; | |
| 6762 | if (peg$silentFails === 0) { | |
| 6763 | peg$fail(peg$e138); | |
| 6764 | } | |
| 6765 | } | |
| 6766 | if (s1 !== peg$FAILED) { | |
| 6767 | s2 = peg$parseterminal(); | |
| 6768 | if (s2 !== peg$FAILED) { | |
| 6769 | peg$savedPos = s0; | |
| 6770 | s0 = peg$f1(s1, s2); | |
| 6771 | } else { | |
| 6772 | peg$currPos = s0; | |
| 6773 | s0 = peg$FAILED; | |
| 6774 | } | |
| 6775 | } else { | |
| 6776 | peg$currPos = s0; | |
| 6777 | s0 = peg$FAILED; | |
| 6778 | } | |
| 6779 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6780 | return s0; | |
| 6781 | } | |
| 6782 | function peg$parseIMAGE2DARRAY() { | |
| 6783 | var s0, s1, s2; | |
| 6784 | var key = peg$currPos * 306 + 140; | |
| 6785 | var cached = peg$resultsCache[key]; | |
| 6786 | if (cached) { | |
| 6787 | peg$currPos = cached.nextPos; | |
| 6788 | return cached.result; | |
| 6789 | } | |
| 6790 | s0 = peg$currPos; | |
| 6791 | if (input.substr(peg$currPos, 12) === peg$c139) { | |
| 6792 | s1 = peg$c139; | |
| 6793 | peg$currPos += 12; | |
| 6794 | } else { | |
| 6795 | s1 = peg$FAILED; | |
| 6796 | if (peg$silentFails === 0) { | |
| 6797 | peg$fail(peg$e139); | |
| 6798 | } | |
| 6799 | } | |
| 6800 | if (s1 !== peg$FAILED) { | |
| 6801 | s2 = peg$parseterminal(); | |
| 6802 | if (s2 !== peg$FAILED) { | |
| 6803 | peg$savedPos = s0; | |
| 6804 | s0 = peg$f1(s1, s2); | |
| 6805 | } else { | |
| 6806 | peg$currPos = s0; | |
| 6807 | s0 = peg$FAILED; | |
| 6808 | } | |
| 6809 | } else { | |
| 6810 | peg$currPos = s0; | |
| 6811 | s0 = peg$FAILED; | |
| 6812 | } | |
| 6813 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6814 | return s0; | |
| 6815 | } | |
| 6816 | function peg$parseIIMAGE2DARRAY() { | |
| 6817 | var s0, s1, s2; | |
| 6818 | var key = peg$currPos * 306 + 141; | |
| 6819 | var cached = peg$resultsCache[key]; | |
| 6820 | if (cached) { | |
| 6821 | peg$currPos = cached.nextPos; | |
| 6822 | return cached.result; | |
| 6823 | } | |
| 6824 | s0 = peg$currPos; | |
| 6825 | if (input.substr(peg$currPos, 13) === peg$c140) { | |
| 6826 | s1 = peg$c140; | |
| 6827 | peg$currPos += 13; | |
| 6828 | } else { | |
| 6829 | s1 = peg$FAILED; | |
| 6830 | if (peg$silentFails === 0) { | |
| 6831 | peg$fail(peg$e140); | |
| 6832 | } | |
| 6833 | } | |
| 6834 | if (s1 !== peg$FAILED) { | |
| 6835 | s2 = peg$parseterminal(); | |
| 6836 | if (s2 !== peg$FAILED) { | |
| 6837 | peg$savedPos = s0; | |
| 6838 | s0 = peg$f1(s1, s2); | |
| 6839 | } else { | |
| 6840 | peg$currPos = s0; | |
| 6841 | s0 = peg$FAILED; | |
| 6842 | } | |
| 6843 | } else { | |
| 6844 | peg$currPos = s0; | |
| 6845 | s0 = peg$FAILED; | |
| 6846 | } | |
| 6847 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6848 | return s0; | |
| 6849 | } | |
| 6850 | function peg$parseUIMAGE2DARRAY() { | |
| 6851 | var s0, s1, s2; | |
| 6852 | var key = peg$currPos * 306 + 142; | |
| 6853 | var cached = peg$resultsCache[key]; | |
| 6854 | if (cached) { | |
| 6855 | peg$currPos = cached.nextPos; | |
| 6856 | return cached.result; | |
| 6857 | } | |
| 6858 | s0 = peg$currPos; | |
| 6859 | if (input.substr(peg$currPos, 13) === peg$c141) { | |
| 6860 | s1 = peg$c141; | |
| 6861 | peg$currPos += 13; | |
| 6862 | } else { | |
| 6863 | s1 = peg$FAILED; | |
| 6864 | if (peg$silentFails === 0) { | |
| 6865 | peg$fail(peg$e141); | |
| 6866 | } | |
| 6867 | } | |
| 6868 | if (s1 !== peg$FAILED) { | |
| 6869 | s2 = peg$parseterminal(); | |
| 6870 | if (s2 !== peg$FAILED) { | |
| 6871 | peg$savedPos = s0; | |
| 6872 | s0 = peg$f1(s1, s2); | |
| 6873 | } else { | |
| 6874 | peg$currPos = s0; | |
| 6875 | s0 = peg$FAILED; | |
| 6876 | } | |
| 6877 | } else { | |
| 6878 | peg$currPos = s0; | |
| 6879 | s0 = peg$FAILED; | |
| 6880 | } | |
| 6881 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6882 | return s0; | |
| 6883 | } | |
| 6884 | function peg$parseIMAGECUBEARRAY() { | |
| 6885 | var s0, s1, s2; | |
| 6886 | var key = peg$currPos * 306 + 143; | |
| 6887 | var cached = peg$resultsCache[key]; | |
| 6888 | if (cached) { | |
| 6889 | peg$currPos = cached.nextPos; | |
| 6890 | return cached.result; | |
| 6891 | } | |
| 6892 | s0 = peg$currPos; | |
| 6893 | if (input.substr(peg$currPos, 14) === peg$c142) { | |
| 6894 | s1 = peg$c142; | |
| 6895 | peg$currPos += 14; | |
| 6896 | } else { | |
| 6897 | s1 = peg$FAILED; | |
| 6898 | if (peg$silentFails === 0) { | |
| 6899 | peg$fail(peg$e142); | |
| 6900 | } | |
| 6901 | } | |
| 6902 | if (s1 !== peg$FAILED) { | |
| 6903 | s2 = peg$parseterminal(); | |
| 6904 | if (s2 !== peg$FAILED) { | |
| 6905 | peg$savedPos = s0; | |
| 6906 | s0 = peg$f1(s1, s2); | |
| 6907 | } else { | |
| 6908 | peg$currPos = s0; | |
| 6909 | s0 = peg$FAILED; | |
| 6910 | } | |
| 6911 | } else { | |
| 6912 | peg$currPos = s0; | |
| 6913 | s0 = peg$FAILED; | |
| 6914 | } | |
| 6915 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6916 | return s0; | |
| 6917 | } | |
| 6918 | function peg$parseIIMAGECUBEARRAY() { | |
| 6919 | var s0, s1, s2; | |
| 6920 | var key = peg$currPos * 306 + 144; | |
| 6921 | var cached = peg$resultsCache[key]; | |
| 6922 | if (cached) { | |
| 6923 | peg$currPos = cached.nextPos; | |
| 6924 | return cached.result; | |
| 6925 | } | |
| 6926 | s0 = peg$currPos; | |
| 6927 | if (input.substr(peg$currPos, 15) === peg$c143) { | |
| 6928 | s1 = peg$c143; | |
| 6929 | peg$currPos += 15; | |
| 6930 | } else { | |
| 6931 | s1 = peg$FAILED; | |
| 6932 | if (peg$silentFails === 0) { | |
| 6933 | peg$fail(peg$e143); | |
| 6934 | } | |
| 6935 | } | |
| 6936 | if (s1 !== peg$FAILED) { | |
| 6937 | s2 = peg$parseterminal(); | |
| 6938 | if (s2 !== peg$FAILED) { | |
| 6939 | peg$savedPos = s0; | |
| 6940 | s0 = peg$f1(s1, s2); | |
| 6941 | } else { | |
| 6942 | peg$currPos = s0; | |
| 6943 | s0 = peg$FAILED; | |
| 6944 | } | |
| 6945 | } else { | |
| 6946 | peg$currPos = s0; | |
| 6947 | s0 = peg$FAILED; | |
| 6948 | } | |
| 6949 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6950 | return s0; | |
| 6951 | } | |
| 6952 | function peg$parseUIMAGECUBEARRAY() { | |
| 6953 | var s0, s1, s2; | |
| 6954 | var key = peg$currPos * 306 + 145; | |
| 6955 | var cached = peg$resultsCache[key]; | |
| 6956 | if (cached) { | |
| 6957 | peg$currPos = cached.nextPos; | |
| 6958 | return cached.result; | |
| 6959 | } | |
| 6960 | s0 = peg$currPos; | |
| 6961 | if (input.substr(peg$currPos, 15) === peg$c144) { | |
| 6962 | s1 = peg$c144; | |
| 6963 | peg$currPos += 15; | |
| 6964 | } else { | |
| 6965 | s1 = peg$FAILED; | |
| 6966 | if (peg$silentFails === 0) { | |
| 6967 | peg$fail(peg$e144); | |
| 6968 | } | |
| 6969 | } | |
| 6970 | if (s1 !== peg$FAILED) { | |
| 6971 | s2 = peg$parseterminal(); | |
| 6972 | if (s2 !== peg$FAILED) { | |
| 6973 | peg$savedPos = s0; | |
| 6974 | s0 = peg$f1(s1, s2); | |
| 6975 | } else { | |
| 6976 | peg$currPos = s0; | |
| 6977 | s0 = peg$FAILED; | |
| 6978 | } | |
| 6979 | } else { | |
| 6980 | peg$currPos = s0; | |
| 6981 | s0 = peg$FAILED; | |
| 6982 | } | |
| 6983 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 6984 | return s0; | |
| 6985 | } | |
| 6986 | function peg$parseIMAGE2DMS() { | |
| 6987 | var s0, s1, s2; | |
| 6988 | var key = peg$currPos * 306 + 146; | |
| 6989 | var cached = peg$resultsCache[key]; | |
| 6990 | if (cached) { | |
| 6991 | peg$currPos = cached.nextPos; | |
| 6992 | return cached.result; | |
| 6993 | } | |
| 6994 | s0 = peg$currPos; | |
| 6995 | if (input.substr(peg$currPos, 9) === peg$c145) { | |
| 6996 | s1 = peg$c145; | |
| 6997 | peg$currPos += 9; | |
| 6998 | } else { | |
| 6999 | s1 = peg$FAILED; | |
| 7000 | if (peg$silentFails === 0) { | |
| 7001 | peg$fail(peg$e145); | |
| 7002 | } | |
| 7003 | } | |
| 7004 | if (s1 !== peg$FAILED) { | |
| 7005 | s2 = peg$parseterminal(); | |
| 7006 | if (s2 !== peg$FAILED) { | |
| 7007 | peg$savedPos = s0; | |
| 7008 | s0 = peg$f1(s1, s2); | |
| 7009 | } else { | |
| 7010 | peg$currPos = s0; | |
| 7011 | s0 = peg$FAILED; | |
| 7012 | } | |
| 7013 | } else { | |
| 7014 | peg$currPos = s0; | |
| 7015 | s0 = peg$FAILED; | |
| 7016 | } | |
| 7017 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7018 | return s0; | |
| 7019 | } | |
| 7020 | function peg$parseIIMAGE2DMS() { | |
| 7021 | var s0, s1, s2; | |
| 7022 | var key = peg$currPos * 306 + 147; | |
| 7023 | var cached = peg$resultsCache[key]; | |
| 7024 | if (cached) { | |
| 7025 | peg$currPos = cached.nextPos; | |
| 7026 | return cached.result; | |
| 7027 | } | |
| 7028 | s0 = peg$currPos; | |
| 7029 | if (input.substr(peg$currPos, 10) === peg$c146) { | |
| 7030 | s1 = peg$c146; | |
| 7031 | peg$currPos += 10; | |
| 7032 | } else { | |
| 7033 | s1 = peg$FAILED; | |
| 7034 | if (peg$silentFails === 0) { | |
| 7035 | peg$fail(peg$e146); | |
| 7036 | } | |
| 7037 | } | |
| 7038 | if (s1 !== peg$FAILED) { | |
| 7039 | s2 = peg$parseterminal(); | |
| 7040 | if (s2 !== peg$FAILED) { | |
| 7041 | peg$savedPos = s0; | |
| 7042 | s0 = peg$f1(s1, s2); | |
| 7043 | } else { | |
| 7044 | peg$currPos = s0; | |
| 7045 | s0 = peg$FAILED; | |
| 7046 | } | |
| 7047 | } else { | |
| 7048 | peg$currPos = s0; | |
| 7049 | s0 = peg$FAILED; | |
| 7050 | } | |
| 7051 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7052 | return s0; | |
| 7053 | } | |
| 7054 | function peg$parseUIMAGE2DMS() { | |
| 7055 | var s0, s1, s2; | |
| 7056 | var key = peg$currPos * 306 + 148; | |
| 7057 | var cached = peg$resultsCache[key]; | |
| 7058 | if (cached) { | |
| 7059 | peg$currPos = cached.nextPos; | |
| 7060 | return cached.result; | |
| 7061 | } | |
| 7062 | s0 = peg$currPos; | |
| 7063 | if (input.substr(peg$currPos, 10) === peg$c147) { | |
| 7064 | s1 = peg$c147; | |
| 7065 | peg$currPos += 10; | |
| 7066 | } else { | |
| 7067 | s1 = peg$FAILED; | |
| 7068 | if (peg$silentFails === 0) { | |
| 7069 | peg$fail(peg$e147); | |
| 7070 | } | |
| 7071 | } | |
| 7072 | if (s1 !== peg$FAILED) { | |
| 7073 | s2 = peg$parseterminal(); | |
| 7074 | if (s2 !== peg$FAILED) { | |
| 7075 | peg$savedPos = s0; | |
| 7076 | s0 = peg$f1(s1, s2); | |
| 7077 | } else { | |
| 7078 | peg$currPos = s0; | |
| 7079 | s0 = peg$FAILED; | |
| 7080 | } | |
| 7081 | } else { | |
| 7082 | peg$currPos = s0; | |
| 7083 | s0 = peg$FAILED; | |
| 7084 | } | |
| 7085 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7086 | return s0; | |
| 7087 | } | |
| 7088 | function peg$parseIMAGE2DMSARRAY() { | |
| 7089 | var s0, s1, s2; | |
| 7090 | var key = peg$currPos * 306 + 149; | |
| 7091 | var cached = peg$resultsCache[key]; | |
| 7092 | if (cached) { | |
| 7093 | peg$currPos = cached.nextPos; | |
| 7094 | return cached.result; | |
| 7095 | } | |
| 7096 | s0 = peg$currPos; | |
| 7097 | if (input.substr(peg$currPos, 13) === peg$c148) { | |
| 7098 | s1 = peg$c148; | |
| 7099 | peg$currPos += 13; | |
| 7100 | } else { | |
| 7101 | s1 = peg$FAILED; | |
| 7102 | if (peg$silentFails === 0) { | |
| 7103 | peg$fail(peg$e148); | |
| 7104 | } | |
| 7105 | } | |
| 7106 | if (s1 !== peg$FAILED) { | |
| 7107 | s2 = peg$parseterminal(); | |
| 7108 | if (s2 !== peg$FAILED) { | |
| 7109 | peg$savedPos = s0; | |
| 7110 | s0 = peg$f1(s1, s2); | |
| 7111 | } else { | |
| 7112 | peg$currPos = s0; | |
| 7113 | s0 = peg$FAILED; | |
| 7114 | } | |
| 7115 | } else { | |
| 7116 | peg$currPos = s0; | |
| 7117 | s0 = peg$FAILED; | |
| 7118 | } | |
| 7119 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7120 | return s0; | |
| 7121 | } | |
| 7122 | function peg$parseIIMAGE2DMSARRAY() { | |
| 7123 | var s0, s1, s2; | |
| 7124 | var key = peg$currPos * 306 + 150; | |
| 7125 | var cached = peg$resultsCache[key]; | |
| 7126 | if (cached) { | |
| 7127 | peg$currPos = cached.nextPos; | |
| 7128 | return cached.result; | |
| 7129 | } | |
| 7130 | s0 = peg$currPos; | |
| 7131 | if (input.substr(peg$currPos, 15) === peg$c149) { | |
| 7132 | s1 = peg$c149; | |
| 7133 | peg$currPos += 15; | |
| 7134 | } else { | |
| 7135 | s1 = peg$FAILED; | |
| 7136 | if (peg$silentFails === 0) { | |
| 7137 | peg$fail(peg$e149); | |
| 7138 | } | |
| 7139 | } | |
| 7140 | if (s1 !== peg$FAILED) { | |
| 7141 | s2 = peg$parseterminal(); | |
| 7142 | if (s2 !== peg$FAILED) { | |
| 7143 | peg$savedPos = s0; | |
| 7144 | s0 = peg$f1(s1, s2); | |
| 7145 | } else { | |
| 7146 | peg$currPos = s0; | |
| 7147 | s0 = peg$FAILED; | |
| 7148 | } | |
| 7149 | } else { | |
| 7150 | peg$currPos = s0; | |
| 7151 | s0 = peg$FAILED; | |
| 7152 | } | |
| 7153 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7154 | return s0; | |
| 7155 | } | |
| 7156 | function peg$parseUIMAGE2DMSARRAY() { | |
| 7157 | var s0, s1, s2; | |
| 7158 | var key = peg$currPos * 306 + 151; | |
| 7159 | var cached = peg$resultsCache[key]; | |
| 7160 | if (cached) { | |
| 7161 | peg$currPos = cached.nextPos; | |
| 7162 | return cached.result; | |
| 7163 | } | |
| 7164 | s0 = peg$currPos; | |
| 7165 | if (input.substr(peg$currPos, 15) === peg$c150) { | |
| 7166 | s1 = peg$c150; | |
| 7167 | peg$currPos += 15; | |
| 7168 | } else { | |
| 7169 | s1 = peg$FAILED; | |
| 7170 | if (peg$silentFails === 0) { | |
| 7171 | peg$fail(peg$e150); | |
| 7172 | } | |
| 7173 | } | |
| 7174 | if (s1 !== peg$FAILED) { | |
| 7175 | s2 = peg$parseterminal(); | |
| 7176 | if (s2 !== peg$FAILED) { | |
| 7177 | peg$savedPos = s0; | |
| 7178 | s0 = peg$f1(s1, s2); | |
| 7179 | } else { | |
| 7180 | peg$currPos = s0; | |
| 7181 | s0 = peg$FAILED; | |
| 7182 | } | |
| 7183 | } else { | |
| 7184 | peg$currPos = s0; | |
| 7185 | s0 = peg$FAILED; | |
| 7186 | } | |
| 7187 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7188 | return s0; | |
| 7189 | } | |
| 7190 | function peg$parseSTRUCT() { | |
| 7191 | var s0, s1, s2; | |
| 7192 | var key = peg$currPos * 306 + 152; | |
| 7193 | var cached = peg$resultsCache[key]; | |
| 7194 | if (cached) { | |
| 7195 | peg$currPos = cached.nextPos; | |
| 7196 | return cached.result; | |
| 7197 | } | |
| 7198 | s0 = peg$currPos; | |
| 7199 | if (input.substr(peg$currPos, 6) === peg$c151) { | |
| 7200 | s1 = peg$c151; | |
| 7201 | peg$currPos += 6; | |
| 7202 | } else { | |
| 7203 | s1 = peg$FAILED; | |
| 7204 | if (peg$silentFails === 0) { | |
| 7205 | peg$fail(peg$e151); | |
| 7206 | } | |
| 7207 | } | |
| 7208 | if (s1 !== peg$FAILED) { | |
| 7209 | s2 = peg$parseterminal(); | |
| 7210 | if (s2 !== peg$FAILED) { | |
| 7211 | peg$savedPos = s0; | |
| 7212 | s0 = peg$f1(s1, s2); | |
| 7213 | } else { | |
| 7214 | peg$currPos = s0; | |
| 7215 | s0 = peg$FAILED; | |
| 7216 | } | |
| 7217 | } else { | |
| 7218 | peg$currPos = s0; | |
| 7219 | s0 = peg$FAILED; | |
| 7220 | } | |
| 7221 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7222 | return s0; | |
| 7223 | } | |
| 7224 | function peg$parseVOID() { | |
| 7225 | var s0, s1, s2; | |
| 7226 | var key = peg$currPos * 306 + 153; | |
| 7227 | var cached = peg$resultsCache[key]; | |
| 7228 | if (cached) { | |
| 7229 | peg$currPos = cached.nextPos; | |
| 7230 | return cached.result; | |
| 7231 | } | |
| 7232 | s0 = peg$currPos; | |
| 7233 | if (input.substr(peg$currPos, 4) === peg$c152) { | |
| 7234 | s1 = peg$c152; | |
| 7235 | peg$currPos += 4; | |
| 7236 | } else { | |
| 7237 | s1 = peg$FAILED; | |
| 7238 | if (peg$silentFails === 0) { | |
| 7239 | peg$fail(peg$e152); | |
| 7240 | } | |
| 7241 | } | |
| 7242 | if (s1 !== peg$FAILED) { | |
| 7243 | s2 = peg$parseterminal(); | |
| 7244 | if (s2 !== peg$FAILED) { | |
| 7245 | peg$savedPos = s0; | |
| 7246 | s0 = peg$f1(s1, s2); | |
| 7247 | } else { | |
| 7248 | peg$currPos = s0; | |
| 7249 | s0 = peg$FAILED; | |
| 7250 | } | |
| 7251 | } else { | |
| 7252 | peg$currPos = s0; | |
| 7253 | s0 = peg$FAILED; | |
| 7254 | } | |
| 7255 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7256 | return s0; | |
| 7257 | } | |
| 7258 | function peg$parseWHILE() { | |
| 7259 | var s0, s1, s2; | |
| 7260 | var key = peg$currPos * 306 + 154; | |
| 7261 | var cached = peg$resultsCache[key]; | |
| 7262 | if (cached) { | |
| 7263 | peg$currPos = cached.nextPos; | |
| 7264 | return cached.result; | |
| 7265 | } | |
| 7266 | s0 = peg$currPos; | |
| 7267 | if (input.substr(peg$currPos, 5) === peg$c153) { | |
| 7268 | s1 = peg$c153; | |
| 7269 | peg$currPos += 5; | |
| 7270 | } else { | |
| 7271 | s1 = peg$FAILED; | |
| 7272 | if (peg$silentFails === 0) { | |
| 7273 | peg$fail(peg$e153); | |
| 7274 | } | |
| 7275 | } | |
| 7276 | if (s1 !== peg$FAILED) { | |
| 7277 | s2 = peg$parseterminal(); | |
| 7278 | if (s2 !== peg$FAILED) { | |
| 7279 | peg$savedPos = s0; | |
| 7280 | s0 = peg$f1(s1, s2); | |
| 7281 | } else { | |
| 7282 | peg$currPos = s0; | |
| 7283 | s0 = peg$FAILED; | |
| 7284 | } | |
| 7285 | } else { | |
| 7286 | peg$currPos = s0; | |
| 7287 | s0 = peg$FAILED; | |
| 7288 | } | |
| 7289 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7290 | return s0; | |
| 7291 | } | |
| 7292 | function peg$parseINVARIANT() { | |
| 7293 | var s0, s1, s2; | |
| 7294 | var key = peg$currPos * 306 + 155; | |
| 7295 | var cached = peg$resultsCache[key]; | |
| 7296 | if (cached) { | |
| 7297 | peg$currPos = cached.nextPos; | |
| 7298 | return cached.result; | |
| 7299 | } | |
| 7300 | s0 = peg$currPos; | |
| 7301 | if (input.substr(peg$currPos, 9) === peg$c154) { | |
| 7302 | s1 = peg$c154; | |
| 7303 | peg$currPos += 9; | |
| 7304 | } else { | |
| 7305 | s1 = peg$FAILED; | |
| 7306 | if (peg$silentFails === 0) { | |
| 7307 | peg$fail(peg$e154); | |
| 7308 | } | |
| 7309 | } | |
| 7310 | if (s1 !== peg$FAILED) { | |
| 7311 | s2 = peg$parseterminal(); | |
| 7312 | if (s2 !== peg$FAILED) { | |
| 7313 | peg$savedPos = s0; | |
| 7314 | s0 = peg$f1(s1, s2); | |
| 7315 | } else { | |
| 7316 | peg$currPos = s0; | |
| 7317 | s0 = peg$FAILED; | |
| 7318 | } | |
| 7319 | } else { | |
| 7320 | peg$currPos = s0; | |
| 7321 | s0 = peg$FAILED; | |
| 7322 | } | |
| 7323 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7324 | return s0; | |
| 7325 | } | |
| 7326 | function peg$parsePRECISE() { | |
| 7327 | var s0, s1, s2; | |
| 7328 | var key = peg$currPos * 306 + 156; | |
| 7329 | var cached = peg$resultsCache[key]; | |
| 7330 | if (cached) { | |
| 7331 | peg$currPos = cached.nextPos; | |
| 7332 | return cached.result; | |
| 7333 | } | |
| 7334 | s0 = peg$currPos; | |
| 7335 | if (input.substr(peg$currPos, 7) === peg$c155) { | |
| 7336 | s1 = peg$c155; | |
| 7337 | peg$currPos += 7; | |
| 7338 | } else { | |
| 7339 | s1 = peg$FAILED; | |
| 7340 | if (peg$silentFails === 0) { | |
| 7341 | peg$fail(peg$e155); | |
| 7342 | } | |
| 7343 | } | |
| 7344 | if (s1 !== peg$FAILED) { | |
| 7345 | s2 = peg$parseterminal(); | |
| 7346 | if (s2 !== peg$FAILED) { | |
| 7347 | peg$savedPos = s0; | |
| 7348 | s0 = peg$f1(s1, s2); | |
| 7349 | } else { | |
| 7350 | peg$currPos = s0; | |
| 7351 | s0 = peg$FAILED; | |
| 7352 | } | |
| 7353 | } else { | |
| 7354 | peg$currPos = s0; | |
| 7355 | s0 = peg$FAILED; | |
| 7356 | } | |
| 7357 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7358 | return s0; | |
| 7359 | } | |
| 7360 | function peg$parseHIGH_PRECISION() { | |
| 7361 | var s0, s1, s2; | |
| 7362 | var key = peg$currPos * 306 + 157; | |
| 7363 | var cached = peg$resultsCache[key]; | |
| 7364 | if (cached) { | |
| 7365 | peg$currPos = cached.nextPos; | |
| 7366 | return cached.result; | |
| 7367 | } | |
| 7368 | s0 = peg$currPos; | |
| 7369 | if (input.substr(peg$currPos, 5) === peg$c156) { | |
| 7370 | s1 = peg$c156; | |
| 7371 | peg$currPos += 5; | |
| 7372 | } else { | |
| 7373 | s1 = peg$FAILED; | |
| 7374 | if (peg$silentFails === 0) { | |
| 7375 | peg$fail(peg$e156); | |
| 7376 | } | |
| 7377 | } | |
| 7378 | if (s1 !== peg$FAILED) { | |
| 7379 | s2 = peg$parseterminal(); | |
| 7380 | if (s2 !== peg$FAILED) { | |
| 7381 | peg$savedPos = s0; | |
| 7382 | s0 = peg$f1(s1, s2); | |
| 7383 | } else { | |
| 7384 | peg$currPos = s0; | |
| 7385 | s0 = peg$FAILED; | |
| 7386 | } | |
| 7387 | } else { | |
| 7388 | peg$currPos = s0; | |
| 7389 | s0 = peg$FAILED; | |
| 7390 | } | |
| 7391 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7392 | return s0; | |
| 7393 | } | |
| 7394 | function peg$parseMEDIUM_PRECISION() { | |
| 7395 | var s0, s1, s2; | |
| 7396 | var key = peg$currPos * 306 + 158; | |
| 7397 | var cached = peg$resultsCache[key]; | |
| 7398 | if (cached) { | |
| 7399 | peg$currPos = cached.nextPos; | |
| 7400 | return cached.result; | |
| 7401 | } | |
| 7402 | s0 = peg$currPos; | |
| 7403 | if (input.substr(peg$currPos, 7) === peg$c157) { | |
| 7404 | s1 = peg$c157; | |
| 7405 | peg$currPos += 7; | |
| 7406 | } else { | |
| 7407 | s1 = peg$FAILED; | |
| 7408 | if (peg$silentFails === 0) { | |
| 7409 | peg$fail(peg$e157); | |
| 7410 | } | |
| 7411 | } | |
| 7412 | if (s1 !== peg$FAILED) { | |
| 7413 | s2 = peg$parseterminal(); | |
| 7414 | if (s2 !== peg$FAILED) { | |
| 7415 | peg$savedPos = s0; | |
| 7416 | s0 = peg$f1(s1, s2); | |
| 7417 | } else { | |
| 7418 | peg$currPos = s0; | |
| 7419 | s0 = peg$FAILED; | |
| 7420 | } | |
| 7421 | } else { | |
| 7422 | peg$currPos = s0; | |
| 7423 | s0 = peg$FAILED; | |
| 7424 | } | |
| 7425 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7426 | return s0; | |
| 7427 | } | |
| 7428 | function peg$parseLOW_PRECISION() { | |
| 7429 | var s0, s1, s2; | |
| 7430 | var key = peg$currPos * 306 + 159; | |
| 7431 | var cached = peg$resultsCache[key]; | |
| 7432 | if (cached) { | |
| 7433 | peg$currPos = cached.nextPos; | |
| 7434 | return cached.result; | |
| 7435 | } | |
| 7436 | s0 = peg$currPos; | |
| 7437 | if (input.substr(peg$currPos, 4) === peg$c158) { | |
| 7438 | s1 = peg$c158; | |
| 7439 | peg$currPos += 4; | |
| 7440 | } else { | |
| 7441 | s1 = peg$FAILED; | |
| 7442 | if (peg$silentFails === 0) { | |
| 7443 | peg$fail(peg$e158); | |
| 7444 | } | |
| 7445 | } | |
| 7446 | if (s1 !== peg$FAILED) { | |
| 7447 | s2 = peg$parseterminal(); | |
| 7448 | if (s2 !== peg$FAILED) { | |
| 7449 | peg$savedPos = s0; | |
| 7450 | s0 = peg$f1(s1, s2); | |
| 7451 | } else { | |
| 7452 | peg$currPos = s0; | |
| 7453 | s0 = peg$FAILED; | |
| 7454 | } | |
| 7455 | } else { | |
| 7456 | peg$currPos = s0; | |
| 7457 | s0 = peg$FAILED; | |
| 7458 | } | |
| 7459 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7460 | return s0; | |
| 7461 | } | |
| 7462 | function peg$parsePRECISION() { | |
| 7463 | var s0, s1, s2; | |
| 7464 | var key = peg$currPos * 306 + 160; | |
| 7465 | var cached = peg$resultsCache[key]; | |
| 7466 | if (cached) { | |
| 7467 | peg$currPos = cached.nextPos; | |
| 7468 | return cached.result; | |
| 7469 | } | |
| 7470 | s0 = peg$currPos; | |
| 7471 | if (input.substr(peg$currPos, 9) === peg$c159) { | |
| 7472 | s1 = peg$c159; | |
| 7473 | peg$currPos += 9; | |
| 7474 | } else { | |
| 7475 | s1 = peg$FAILED; | |
| 7476 | if (peg$silentFails === 0) { | |
| 7477 | peg$fail(peg$e159); | |
| 7478 | } | |
| 7479 | } | |
| 7480 | if (s1 !== peg$FAILED) { | |
| 7481 | s2 = peg$parseterminal(); | |
| 7482 | if (s2 !== peg$FAILED) { | |
| 7483 | peg$savedPos = s0; | |
| 7484 | s0 = peg$f1(s1, s2); | |
| 7485 | } else { | |
| 7486 | peg$currPos = s0; | |
| 7487 | s0 = peg$FAILED; | |
| 7488 | } | |
| 7489 | } else { | |
| 7490 | peg$currPos = s0; | |
| 7491 | s0 = peg$FAILED; | |
| 7492 | } | |
| 7493 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7494 | return s0; | |
| 7495 | } | |
| 7496 | function peg$parseFLOATCONSTANT() { | |
| 7497 | var s0, s1, s2; | |
| 7498 | var key = peg$currPos * 306 + 161; | |
| 7499 | var cached = peg$resultsCache[key]; | |
| 7500 | if (cached) { | |
| 7501 | peg$currPos = cached.nextPos; | |
| 7502 | return cached.result; | |
| 7503 | } | |
| 7504 | s0 = peg$currPos; | |
| 7505 | s1 = peg$parsefloating_constant(); | |
| 7506 | if (s1 !== peg$FAILED) { | |
| 7507 | s2 = peg$parse_(); | |
| 7508 | peg$savedPos = s0; | |
| 7509 | s0 = peg$f2(s1, s2); | |
| 7510 | } else { | |
| 7511 | peg$currPos = s0; | |
| 7512 | s0 = peg$FAILED; | |
| 7513 | } | |
| 7514 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7515 | return s0; | |
| 7516 | } | |
| 7517 | function peg$parseDOUBLECONSTANT() { | |
| 7518 | var s0, s1, s2; | |
| 7519 | var key = peg$currPos * 306 + 162; | |
| 7520 | var cached = peg$resultsCache[key]; | |
| 7521 | if (cached) { | |
| 7522 | peg$currPos = cached.nextPos; | |
| 7523 | return cached.result; | |
| 7524 | } | |
| 7525 | s0 = peg$currPos; | |
| 7526 | s1 = peg$parsefloating_constant(); | |
| 7527 | if (s1 !== peg$FAILED) { | |
| 7528 | s2 = peg$parse_(); | |
| 7529 | peg$savedPos = s0; | |
| 7530 | s0 = peg$f3(s1, s2); | |
| 7531 | } else { | |
| 7532 | peg$currPos = s0; | |
| 7533 | s0 = peg$FAILED; | |
| 7534 | } | |
| 7535 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7536 | return s0; | |
| 7537 | } | |
| 7538 | function peg$parseINTCONSTANT() { | |
| 7539 | var s0, s1, s2; | |
| 7540 | var key = peg$currPos * 306 + 163; | |
| 7541 | var cached = peg$resultsCache[key]; | |
| 7542 | if (cached) { | |
| 7543 | peg$currPos = cached.nextPos; | |
| 7544 | return cached.result; | |
| 7545 | } | |
| 7546 | s0 = peg$currPos; | |
| 7547 | s1 = peg$parseinteger_constant(); | |
| 7548 | if (s1 !== peg$FAILED) { | |
| 7549 | s2 = peg$parse_(); | |
| 7550 | peg$savedPos = s0; | |
| 7551 | s0 = peg$f4(s1, s2); | |
| 7552 | } else { | |
| 7553 | peg$currPos = s0; | |
| 7554 | s0 = peg$FAILED; | |
| 7555 | } | |
| 7556 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7557 | return s0; | |
| 7558 | } | |
| 7559 | function peg$parseUINTCONSTANT() { | |
| 7560 | var s0, s1, s2; | |
| 7561 | var key = peg$currPos * 306 + 164; | |
| 7562 | var cached = peg$resultsCache[key]; | |
| 7563 | if (cached) { | |
| 7564 | peg$currPos = cached.nextPos; | |
| 7565 | return cached.result; | |
| 7566 | } | |
| 7567 | s0 = peg$currPos; | |
| 7568 | s1 = peg$parseinteger_constant(); | |
| 7569 | if (s1 !== peg$FAILED) { | |
| 7570 | s2 = peg$parse_(); | |
| 7571 | peg$savedPos = s0; | |
| 7572 | s0 = peg$f5(s1, s2); | |
| 7573 | } else { | |
| 7574 | peg$currPos = s0; | |
| 7575 | s0 = peg$FAILED; | |
| 7576 | } | |
| 7577 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7578 | return s0; | |
| 7579 | } | |
| 7580 | function peg$parseBOOLCONSTANT() { | |
| 7581 | var s0, s1, s2; | |
| 7582 | var key = peg$currPos * 306 + 165; | |
| 7583 | var cached = peg$resultsCache[key]; | |
| 7584 | if (cached) { | |
| 7585 | peg$currPos = cached.nextPos; | |
| 7586 | return cached.result; | |
| 7587 | } | |
| 7588 | s0 = peg$currPos; | |
| 7589 | if (input.substr(peg$currPos, 4) === peg$c160) { | |
| 7590 | s1 = peg$c160; | |
| 7591 | peg$currPos += 4; | |
| 7592 | } else { | |
| 7593 | s1 = peg$FAILED; | |
| 7594 | if (peg$silentFails === 0) { | |
| 7595 | peg$fail(peg$e160); | |
| 7596 | } | |
| 7597 | } | |
| 7598 | if (s1 === peg$FAILED) { | |
| 7599 | if (input.substr(peg$currPos, 5) === peg$c161) { | |
| 7600 | s1 = peg$c161; | |
| 7601 | peg$currPos += 5; | |
| 7602 | } else { | |
| 7603 | s1 = peg$FAILED; | |
| 7604 | if (peg$silentFails === 0) { | |
| 7605 | peg$fail(peg$e161); | |
| 7606 | } | |
| 7607 | } | |
| 7608 | } | |
| 7609 | if (s1 !== peg$FAILED) { | |
| 7610 | s2 = peg$parseterminal(); | |
| 7611 | if (s2 !== peg$FAILED) { | |
| 7612 | peg$savedPos = s0; | |
| 7613 | s0 = peg$f6(s1, s2); | |
| 7614 | } else { | |
| 7615 | peg$currPos = s0; | |
| 7616 | s0 = peg$FAILED; | |
| 7617 | } | |
| 7618 | } else { | |
| 7619 | peg$currPos = s0; | |
| 7620 | s0 = peg$FAILED; | |
| 7621 | } | |
| 7622 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 7623 | return s0; | |
| 7624 | } | |
| 7625 | function peg$parsekeyword() { | |
| 7626 | var s0, s1; | |
| 7627 | var key = peg$currPos * 306 + 166; | |
| 7628 | var cached = peg$resultsCache[key]; | |
| 7629 | if (cached) { | |
| 7630 | peg$currPos = cached.nextPos; | |
| 7631 | return cached.result; | |
| 7632 | } | |
| 7633 | peg$silentFails++; | |
| 7634 | s0 = peg$parseATTRIBUTE(); | |
| 7635 | if (s0 === peg$FAILED) { | |
| 7636 | s0 = peg$parseVARYING(); | |
| 7637 | if (s0 === peg$FAILED) { | |
| 7638 | s0 = peg$parseCONST(); | |
| 7639 | if (s0 === peg$FAILED) { | |
| 7640 | s0 = peg$parseBOOL(); | |
| 7641 | if (s0 === peg$FAILED) { | |
| 7642 | s0 = peg$parseFLOAT(); | |
| 7643 | if (s0 === peg$FAILED) { | |
| 7644 | s0 = peg$parseDOUBLE(); | |
| 7645 | if (s0 === peg$FAILED) { | |
| 7646 | s0 = peg$parseINT(); | |
| 7647 | if (s0 === peg$FAILED) { | |
| 7648 | s0 = peg$parseUINT(); | |
| 7649 | if (s0 === peg$FAILED) { | |
| 7650 | s0 = peg$parseBREAK(); | |
| 7651 | if (s0 === peg$FAILED) { | |
| 7652 | s0 = peg$parseCONTINUE(); | |
| 7653 | if (s0 === peg$FAILED) { | |
| 7654 | s0 = peg$parseDO(); | |
| 7655 | if (s0 === peg$FAILED) { | |
| 7656 | s0 = peg$parseELSE(); | |
| 7657 | if (s0 === peg$FAILED) { | |
| 7658 | s0 = peg$parseFOR(); | |
| 7659 | if (s0 === peg$FAILED) { | |
| 7660 | s0 = peg$parseIF(); | |
| 7661 | if (s0 === peg$FAILED) { | |
| 7662 | s0 = peg$parseDISCARD(); | |
| 7663 | if (s0 === peg$FAILED) { | |
| 7664 | s0 = peg$parseRETURN(); | |
| 7665 | if (s0 === peg$FAILED) { | |
| 7666 | s0 = peg$parseSWITCH(); | |
| 7667 | if (s0 === peg$FAILED) { | |
| 7668 | s0 = peg$parseCASE(); | |
| 7669 | if (s0 === peg$FAILED) { | |
| 7670 | s0 = peg$parseDEFAULT(); | |
| 7671 | if (s0 === peg$FAILED) { | |
| 7672 | s0 = peg$parseSUBROUTINE(); | |
| 7673 | if (s0 === peg$FAILED) { | |
| 7674 | s0 = peg$parseBVEC2(); | |
| 7675 | if (s0 === peg$FAILED) { | |
| 7676 | s0 = peg$parseBVEC3(); | |
| 7677 | if (s0 === peg$FAILED) { | |
| 7678 | s0 = peg$parseBVEC4(); | |
| 7679 | if (s0 === peg$FAILED) { | |
| 7680 | s0 = peg$parseIVEC2(); | |
| 7681 | if (s0 === peg$FAILED) { | |
| 7682 | s0 = peg$parseIVEC3(); | |
| 7683 | if (s0 === peg$FAILED) { | |
| 7684 | s0 = peg$parseIVEC4(); | |
| 7685 | if (s0 === peg$FAILED) { | |
| 7686 | s0 = peg$parseUVEC2(); | |
| 7687 | if (s0 === peg$FAILED) { | |
| 7688 | s0 = peg$parseUVEC3(); | |
| 7689 | if (s0 === peg$FAILED) { | |
| 7690 | s0 = peg$parseUVEC4(); | |
| 7691 | if (s0 === peg$FAILED) { | |
| 7692 | s0 = peg$parseVEC2(); | |
| 7693 | if (s0 === peg$FAILED) { | |
| 7694 | s0 = peg$parseVEC3(); | |
| 7695 | if (s0 === peg$FAILED) { | |
| 7696 | s0 = peg$parseVEC4(); | |
| 7697 | if (s0 === peg$FAILED) { | |
| 7698 | s0 = peg$parseMAT2(); | |
| 7699 | if (s0 === peg$FAILED) { | |
| 7700 | s0 = peg$parseMAT3(); | |
| 7701 | if (s0 === peg$FAILED) { | |
| 7702 | s0 = peg$parseMAT4(); | |
| 7703 | if (s0 === peg$FAILED) { | |
| 7704 | s0 = peg$parseCENTROID(); | |
| 7705 | if (s0 === peg$FAILED) { | |
| 7706 | s0 = peg$parseIN(); | |
| 7707 | if (s0 === peg$FAILED) { | |
| 7708 | s0 = peg$parseOUT(); | |
| 7709 | if (s0 === peg$FAILED) { | |
| 7710 | s0 = peg$parseINOUT(); | |
| 7711 | if (s0 === peg$FAILED) { | |
| 7712 | s0 = peg$parseUNIFORM(); | |
| 7713 | if (s0 === peg$FAILED) { | |
| 7714 | s0 = peg$parsePATCH(); | |
| 7715 | if (s0 === peg$FAILED) { | |
| 7716 | s0 = peg$parseSAMPLE(); | |
| 7717 | if (s0 === peg$FAILED) { | |
| 7718 | s0 = peg$parseBUFFER(); | |
| 7719 | if (s0 === peg$FAILED) { | |
| 7720 | s0 = peg$parseSHARED(); | |
| 7721 | if (s0 === peg$FAILED) { | |
| 7722 | s0 = peg$parseCOHERENT(); | |
| 7723 | if (s0 === peg$FAILED) { | |
| 7724 | s0 = peg$parseVOLATILE(); | |
| 7725 | if (s0 === peg$FAILED) { | |
| 7726 | s0 = peg$parseRESTRICT(); | |
| 7727 | if (s0 === peg$FAILED) { | |
| 7728 | s0 = peg$parseREADONLY(); | |
| 7729 | if (s0 === peg$FAILED) { | |
| 7730 | s0 = peg$parseWRITEONLY(); | |
| 7731 | if (s0 === peg$FAILED) { | |
| 7732 | s0 = peg$parseDVEC2(); | |
| 7733 | if (s0 === peg$FAILED) { | |
| 7734 | s0 = peg$parseDVEC3(); | |
| 7735 | if (s0 === peg$FAILED) { | |
| 7736 | s0 = peg$parseDVEC4(); | |
| 7737 | if (s0 === peg$FAILED) { | |
| 7738 | s0 = peg$parseDMAT2(); | |
| 7739 | if (s0 === peg$FAILED) { | |
| 7740 | s0 = peg$parseDMAT3(); | |
| 7741 | if (s0 === peg$FAILED) { | |
| 7742 | s0 = peg$parseDMAT4(); | |
| 7743 | if (s0 === peg$FAILED) { | |
| 7744 | s0 = peg$parseNOPERSPECTIVE(); | |
| 7745 | if (s0 === peg$FAILED) { | |
| 7746 | s0 = peg$parseFLAT(); | |
| 7747 | if (s0 === peg$FAILED) { | |
| 7748 | s0 = peg$parseSMOOTH(); | |
| 7749 | if (s0 === peg$FAILED) { | |
| 7750 | s0 = peg$parseLAYOUT(); | |
| 7751 | if (s0 === peg$FAILED) { | |
| 7752 | s0 = peg$parseMAT2X2(); | |
| 7753 | if (s0 === peg$FAILED) { | |
| 7754 | s0 = peg$parseMAT2X3(); | |
| 7755 | if (s0 === peg$FAILED) { | |
| 7756 | s0 = peg$parseMAT2X4(); | |
| 7757 | if (s0 === peg$FAILED) { | |
| 7758 | s0 = peg$parseMAT3X2(); | |
| 7759 | if (s0 === peg$FAILED) { | |
| 7760 | s0 = peg$parseMAT3X3(); | |
| 7761 | if (s0 === peg$FAILED) { | |
| 7762 | s0 = peg$parseMAT3X4(); | |
| 7763 | if (s0 === peg$FAILED) { | |
| 7764 | s0 = peg$parseMAT4X2(); | |
| 7765 | if (s0 === peg$FAILED) { | |
| 7766 | s0 = peg$parseMAT4X3(); | |
| 7767 | if (s0 === peg$FAILED) { | |
| 7768 | s0 = peg$parseMAT4X4(); | |
| 7769 | if (s0 === peg$FAILED) { | |
| 7770 | s0 = peg$parseDMAT2X2(); | |
| 7771 | if (s0 === peg$FAILED) { | |
| 7772 | s0 = peg$parseDMAT2X3(); | |
| 7773 | if (s0 === peg$FAILED) { | |
| 7774 | s0 = peg$parseDMAT2X4(); | |
| 7775 | if (s0 === peg$FAILED) { | |
| 7776 | s0 = peg$parseDMAT3X2(); | |
| 7777 | if (s0 === peg$FAILED) { | |
| 7778 | s0 = peg$parseDMAT3X3(); | |
| 7779 | if (s0 === peg$FAILED) { | |
| 7780 | s0 = peg$parseDMAT3X4(); | |
| 7781 | if (s0 === peg$FAILED) { | |
| 7782 | s0 = peg$parseDMAT4X2(); | |
| 7783 | if (s0 === peg$FAILED) { | |
| 7784 | s0 = peg$parseDMAT4X3(); | |
| 7785 | if (s0 === peg$FAILED) { | |
| 7786 | s0 = peg$parseDMAT4X4(); | |
| 7787 | if (s0 === peg$FAILED) { | |
| 7788 | s0 = peg$parseATOMIC_UINT(); | |
| 7789 | if (s0 === peg$FAILED) { | |
| 7790 | s0 = peg$parseSAMPLER1D(); | |
| 7791 | if (s0 === peg$FAILED) { | |
| 7792 | s0 = peg$parseSAMPLER2D(); | |
| 7793 | if (s0 === peg$FAILED) { | |
| 7794 | s0 = peg$parseSAMPLER3D(); | |
| 7795 | if (s0 === peg$FAILED) { | |
| 7796 | s0 = peg$parseSAMPLERCUBE(); | |
| 7797 | if (s0 === peg$FAILED) { | |
| 7798 | s0 = peg$parseSAMPLER1DSHADOW(); | |
| 7799 | if (s0 === peg$FAILED) { | |
| 7800 | s0 = peg$parseSAMPLER2DSHADOW(); | |
| 7801 | if (s0 === peg$FAILED) { | |
| 7802 | s0 = peg$parseSAMPLERCUBESHADOW(); | |
| 7803 | if (s0 === peg$FAILED) { | |
| 7804 | s0 = peg$parseSAMPLER1DARRAY(); | |
| 7805 | if (s0 === peg$FAILED) { | |
| 7806 | s0 = peg$parseSAMPLER2DARRAY(); | |
| 7807 | if (s0 === peg$FAILED) { | |
| 7808 | s0 = peg$parseSAMPLER1DARRAYSHADOW(); | |
| 7809 | if (s0 === peg$FAILED) { | |
| 7810 | s0 = peg$parseSAMPLER2DARRAYSHADOW(); | |
| 7811 | if (s0 === peg$FAILED) { | |
| 7812 | s0 = peg$parseISAMPLER1D(); | |
| 7813 | if (s0 === peg$FAILED) { | |
| 7814 | s0 = peg$parseISAMPLER2D(); | |
| 7815 | if (s0 === peg$FAILED) { | |
| 7816 | s0 = peg$parseISAMPLER3D(); | |
| 7817 | if (s0 === peg$FAILED) { | |
| 7818 | s0 = peg$parseISAMPLERCUBE(); | |
| 7819 | if (s0 === peg$FAILED) { | |
| 7820 | s0 = peg$parseISAMPLER1DARRAY(); | |
| 7821 | if (s0 === peg$FAILED) { | |
| 7822 | s0 = peg$parseISAMPLER2DARRAY(); | |
| 7823 | if (s0 === peg$FAILED) { | |
| 7824 | s0 = peg$parseUSAMPLER1D(); | |
| 7825 | if (s0 === peg$FAILED) { | |
| 7826 | s0 = peg$parseUSAMPLER2D(); | |
| 7827 | if (s0 === peg$FAILED) { | |
| 7828 | s0 = peg$parseUSAMPLER3D(); | |
| 7829 | if (s0 === peg$FAILED) { | |
| 7830 | s0 = peg$parseUSAMPLERCUBE(); | |
| 7831 | if (s0 === peg$FAILED) { | |
| 7832 | s0 = peg$parseUSAMPLER1DARRAY(); | |
| 7833 | if (s0 === peg$FAILED) { | |
| 7834 | s0 = peg$parseUSAMPLER2DARRAY(); | |
| 7835 | if (s0 === peg$FAILED) { | |
| 7836 | s0 = peg$parseSAMPLER2DRECT(); | |
| 7837 | if (s0 === peg$FAILED) { | |
| 7838 | s0 = peg$parseSAMPLER2DRECTSHADOW(); | |
| 7839 | if (s0 === peg$FAILED) { | |
| 7840 | s0 = peg$parseISAMPLER2DRECT(); | |
| 7841 | if (s0 === peg$FAILED) { | |
| 7842 | s0 = peg$parseUSAMPLER2DRECT(); | |
| 7843 | if (s0 === peg$FAILED) { | |
| 7844 | s0 = peg$parseSAMPLERBUFFER(); | |
| 7845 | if (s0 === peg$FAILED) { | |
| 7846 | s0 = peg$parseISAMPLERBUFFER(); | |
| 7847 | if (s0 === peg$FAILED) { | |
| 7848 | s0 = peg$parseUSAMPLERBUFFER(); | |
| 7849 | if (s0 === peg$FAILED) { | |
| 7850 | s0 = peg$parseSAMPLERCUBEARRAY(); | |
| 7851 | if (s0 === peg$FAILED) { | |
| 7852 | s0 = peg$parseSAMPLERCUBEARRAYSHADOW(); | |
| 7853 | if (s0 === peg$FAILED) { | |
| 7854 | s0 = peg$parseISAMPLERCUBEARRAY(); | |
| 7855 | if (s0 === peg$FAILED) { | |
| 7856 | s0 = peg$parseUSAMPLERCUBEARRAY(); | |
| 7857 | if (s0 === peg$FAILED) { | |
| 7858 | s0 = peg$parseSAMPLER2DMS(); | |
| 7859 | if (s0 === peg$FAILED) { | |
| 7860 | s0 = peg$parseISAMPLER2DMS(); | |
| 7861 | if (s0 === peg$FAILED) { | |
| 7862 | s0 = peg$parseUSAMPLER2DMS(); | |
| 7863 | if (s0 === peg$FAILED) { | |
| 7864 | s0 = peg$parseSAMPLER2DMSARRAY(); | |
| 7865 | if (s0 === peg$FAILED) { | |
| 7866 | s0 = peg$parseISAMPLER2DMSARRAY(); | |
| 7867 | if (s0 === peg$FAILED) { | |
| 7868 | s0 = peg$parseUSAMPLER2DMSARRAY(); | |
| 7869 | if (s0 === peg$FAILED) { | |
| 7870 | s0 = peg$parseIMAGE1D(); | |
| 7871 | if (s0 === peg$FAILED) { | |
| 7872 | s0 = peg$parseIIMAGE1D(); | |
| 7873 | if (s0 === peg$FAILED) { | |
| 7874 | s0 = peg$parseUIMAGE1D(); | |
| 7875 | if (s0 === peg$FAILED) { | |
| 7876 | s0 = peg$parseIMAGE2D(); | |
| 7877 | if (s0 === peg$FAILED) { | |
| 7878 | s0 = peg$parseIIMAGE2D(); | |
| 7879 | if (s0 === peg$FAILED) { | |
| 7880 | s0 = peg$parseUIMAGE2D(); | |
| 7881 | if (s0 === peg$FAILED) { | |
| 7882 | s0 = peg$parseIMAGE3D(); | |
| 7883 | if (s0 === peg$FAILED) { | |
| 7884 | s0 = peg$parseIIMAGE3D(); | |
| 7885 | if (s0 === peg$FAILED) { | |
| 7886 | s0 = peg$parseUIMAGE3D(); | |
| 7887 | if (s0 === peg$FAILED) { | |
| 7888 | s0 = peg$parseIMAGE2DRECT(); | |
| 7889 | if (s0 === peg$FAILED) { | |
| 7890 | s0 = peg$parseIIMAGE2DRECT(); | |
| 7891 | if (s0 === peg$FAILED) { | |
| 7892 | s0 = peg$parseUIMAGE2DRECT(); | |
| 7893 | if (s0 === peg$FAILED) { | |
| 7894 | s0 = peg$parseIMAGECUBE(); | |
| 7895 | if (s0 === peg$FAILED) { | |
| 7896 | s0 = peg$parseIIMAGECUBE(); | |
| 7897 | if (s0 === peg$FAILED) { | |
| 7898 | s0 = peg$parseUIMAGECUBE(); | |
| 7899 | if (s0 === peg$FAILED) { | |
| 7900 | s0 = peg$parseIMAGEBUFFER(); | |
| 7901 | if (s0 === peg$FAILED) { | |
| 7902 | s0 = peg$parseIIMAGEBUFFER(); | |
| 7903 | if (s0 === peg$FAILED) { | |
| 7904 | s0 = peg$parseUIMAGEBUFFER(); | |
| 7905 | if (s0 === peg$FAILED) { | |
| 7906 | s0 = peg$parseIMAGE1DARRAY(); | |
| 7907 | if (s0 === peg$FAILED) { | |
| 7908 | s0 = peg$parseIIMAGE1DARRAY(); | |
| 7909 | if (s0 === peg$FAILED) { | |
| 7910 | s0 = peg$parseUIMAGE1DARRAY(); | |
| 7911 | if (s0 === peg$FAILED) { | |
| 7912 | s0 = peg$parseIMAGE2DARRAY(); | |
| 7913 | if (s0 === peg$FAILED) { | |
| 7914 | s0 = peg$parseIIMAGE2DARRAY(); | |
| 7915 | if (s0 === peg$FAILED) { | |
| 7916 | s0 = peg$parseUIMAGE2DARRAY(); | |
| 7917 | if (s0 === peg$FAILED) { | |
| 7918 | s0 = peg$parseIMAGECUBEARRAY(); | |
| 7919 | if (s0 === peg$FAILED) { | |
| 7920 | s0 = peg$parseIIMAGECUBEARRAY(); | |
| 7921 | if (s0 === peg$FAILED) { | |
| 7922 | s0 = peg$parseUIMAGECUBEARRAY(); | |
| 7923 | if (s0 === peg$FAILED) { | |
| 7924 | s0 = peg$parseIMAGE2DMS(); | |
| 7925 | if (s0 === peg$FAILED) { | |
| 7926 | s0 = peg$parseIIMAGE2DMS(); | |
| 7927 | if (s0 === peg$FAILED) { | |
| 7928 | s0 = peg$parseUIMAGE2DMS(); | |
| 7929 | if (s0 === peg$FAILED) { | |
| 7930 | s0 = peg$parseIMAGE2DMSARRAY(); | |
| 7931 | if (s0 === peg$FAILED) { | |
| 7932 | s0 = peg$parseIIMAGE2DMSARRAY(); | |
| 7933 | if (s0 === peg$FAILED) { | |
| 7934 | s0 = peg$parseUIMAGE2DMSARRAY(); | |
| 7935 | if (s0 === peg$FAILED) { | |
| 7936 | s0 = peg$parseSTRUCT(); | |
| 7937 | if (s0 === peg$FAILED) { | |
| 7938 | s0 = peg$parseVOID(); | |
| 7939 | if (s0 === peg$FAILED) { | |
| 7940 | s0 = peg$parseWHILE(); | |
| 7941 | if (s0 === peg$FAILED) { | |
| 7942 | s0 = peg$parseINVARIANT(); | |
| 7943 | if (s0 === peg$FAILED) { | |
| 7944 | s0 = peg$parsePRECISE(); | |
| 7945 | if (s0 === peg$FAILED) { | |
| 7946 | s0 = peg$parseHIGH_PRECISION(); | |
| 7947 | if (s0 === peg$FAILED) { | |
| 7948 | s0 = peg$parseMEDIUM_PRECISION(); | |
| 7949 | if (s0 === peg$FAILED) { | |
| 7950 | s0 = peg$parseLOW_PRECISION(); | |
| 7951 | if (s0 === peg$FAILED) { | |
| 7952 | s0 = peg$parsePRECISION(); | |
| 7953 | } | |
| 7954 | } | |
| 7955 | } | |
| 7956 | } | |
| 7957 | } | |
| 7958 | } | |
| 7959 | } | |
| 7960 | } | |
| 7961 | } | |
| 7962 | } | |
| 7963 | } | |
| 7964 | } | |
| 7965 | } | |
| 7966 | } | |
| 7967 | } | |
| 7968 | } | |
| 7969 | } | |
| 7970 | } | |
| 7971 | } | |
| 7972 | } | |
| 7973 | } | |
| 7974 | } | |
| 7975 | } | |
| 7976 | } | |
| 7977 | } | |
| 7978 | } | |
| 7979 | } | |
| 7980 | } | |
| 7981 | } | |
| 7982 | } | |
| 7983 | } | |
| 7984 | } | |
| 7985 | } | |
| 7986 | } | |
| 7987 | } | |
| 7988 | } | |
| 7989 | } | |
| 7990 | } | |
| 7991 | } | |
| 7992 | } | |
| 7993 | } | |
| 7994 | } | |
| 7995 | } | |
| 7996 | } | |
| 7997 | } | |
| 7998 | } | |
| 7999 | } | |
| 8000 | } | |
| 8001 | } | |
| 8002 | } | |
| 8003 | } | |
| 8004 | } | |
| 8005 | } | |
| 8006 | } | |
| 8007 | } | |
| 8008 | } | |
| 8009 | } | |
| 8010 | } | |
| 8011 | } | |
| 8012 | } | |
| 8013 | } | |
| 8014 | } | |
| 8015 | } | |
| 8016 | } | |
| 8017 | } | |
| 8018 | } | |
| 8019 | } | |
| 8020 | } | |
| 8021 | } | |
| 8022 | } | |
| 8023 | } | |
| 8024 | } | |
| 8025 | } | |
| 8026 | } | |
| 8027 | } | |
| 8028 | } | |
| 8029 | } | |
| 8030 | } | |
| 8031 | } | |
| 8032 | } | |
| 8033 | } | |
| 8034 | } | |
| 8035 | } | |
| 8036 | } | |
| 8037 | } | |
| 8038 | } | |
| 8039 | } | |
| 8040 | } | |
| 8041 | } | |
| 8042 | } | |
| 8043 | } | |
| 8044 | } | |
| 8045 | } | |
| 8046 | } | |
| 8047 | } | |
| 8048 | } | |
| 8049 | } | |
| 8050 | } | |
| 8051 | } | |
| 8052 | } | |
| 8053 | } | |
| 8054 | } | |
| 8055 | } | |
| 8056 | } | |
| 8057 | } | |
| 8058 | } | |
| 8059 | } | |
| 8060 | } | |
| 8061 | } | |
| 8062 | } | |
| 8063 | } | |
| 8064 | } | |
| 8065 | } | |
| 8066 | } | |
| 8067 | } | |
| 8068 | } | |
| 8069 | } | |
| 8070 | } | |
| 8071 | } | |
| 8072 | } | |
| 8073 | } | |
| 8074 | } | |
| 8075 | } | |
| 8076 | } | |
| 8077 | } | |
| 8078 | } | |
| 8079 | } | |
| 8080 | } | |
| 8081 | } | |
| 8082 | } | |
| 8083 | } | |
| 8084 | } | |
| 8085 | } | |
| 8086 | } | |
| 8087 | } | |
| 8088 | } | |
| 8089 | } | |
| 8090 | } | |
| 8091 | } | |
| 8092 | } | |
| 8093 | } | |
| 8094 | } | |
| 8095 | } | |
| 8096 | } | |
| 8097 | } | |
| 8098 | } | |
| 8099 | } | |
| 8100 | } | |
| 8101 | } | |
| 8102 | } | |
| 8103 | } | |
| 8104 | } | |
| 8105 | } | |
| 8106 | } | |
| 8107 | } | |
| 8108 | } | |
| 8109 | } | |
| 8110 | } | |
| 8111 | } | |
| 8112 | peg$silentFails--; | |
| 8113 | if (s0 === peg$FAILED) { | |
| 8114 | s1 = peg$FAILED; | |
| 8115 | if (peg$silentFails === 0) { | |
| 8116 | peg$fail(peg$e162); | |
| 8117 | } | |
| 8118 | } | |
| 8119 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8120 | return s0; | |
| 8121 | } | |
| 8122 | function peg$parseLEFT_OP() { | |
| 8123 | var s0, s1, s2; | |
| 8124 | var key = peg$currPos * 306 + 167; | |
| 8125 | var cached = peg$resultsCache[key]; | |
| 8126 | if (cached) { | |
| 8127 | peg$currPos = cached.nextPos; | |
| 8128 | return cached.result; | |
| 8129 | } | |
| 8130 | s0 = peg$currPos; | |
| 8131 | if (input.substr(peg$currPos, 2) === peg$c162) { | |
| 8132 | s1 = peg$c162; | |
| 8133 | peg$currPos += 2; | |
| 8134 | } else { | |
| 8135 | s1 = peg$FAILED; | |
| 8136 | if (peg$silentFails === 0) { | |
| 8137 | peg$fail(peg$e163); | |
| 8138 | } | |
| 8139 | } | |
| 8140 | if (s1 !== peg$FAILED) { | |
| 8141 | s2 = peg$parse_(); | |
| 8142 | peg$savedPos = s0; | |
| 8143 | s0 = peg$f7(s1, s2); | |
| 8144 | } else { | |
| 8145 | peg$currPos = s0; | |
| 8146 | s0 = peg$FAILED; | |
| 8147 | } | |
| 8148 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8149 | return s0; | |
| 8150 | } | |
| 8151 | function peg$parseRIGHT_OP() { | |
| 8152 | var s0, s1, s2; | |
| 8153 | var key = peg$currPos * 306 + 168; | |
| 8154 | var cached = peg$resultsCache[key]; | |
| 8155 | if (cached) { | |
| 8156 | peg$currPos = cached.nextPos; | |
| 8157 | return cached.result; | |
| 8158 | } | |
| 8159 | s0 = peg$currPos; | |
| 8160 | if (input.substr(peg$currPos, 2) === peg$c163) { | |
| 8161 | s1 = peg$c163; | |
| 8162 | peg$currPos += 2; | |
| 8163 | } else { | |
| 8164 | s1 = peg$FAILED; | |
| 8165 | if (peg$silentFails === 0) { | |
| 8166 | peg$fail(peg$e164); | |
| 8167 | } | |
| 8168 | } | |
| 8169 | if (s1 !== peg$FAILED) { | |
| 8170 | s2 = peg$parse_(); | |
| 8171 | peg$savedPos = s0; | |
| 8172 | s0 = peg$f7(s1, s2); | |
| 8173 | } else { | |
| 8174 | peg$currPos = s0; | |
| 8175 | s0 = peg$FAILED; | |
| 8176 | } | |
| 8177 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8178 | return s0; | |
| 8179 | } | |
| 8180 | function peg$parseINC_OP() { | |
| 8181 | var s0, s1, s2; | |
| 8182 | var key = peg$currPos * 306 + 169; | |
| 8183 | var cached = peg$resultsCache[key]; | |
| 8184 | if (cached) { | |
| 8185 | peg$currPos = cached.nextPos; | |
| 8186 | return cached.result; | |
| 8187 | } | |
| 8188 | s0 = peg$currPos; | |
| 8189 | if (input.substr(peg$currPos, 2) === peg$c164) { | |
| 8190 | s1 = peg$c164; | |
| 8191 | peg$currPos += 2; | |
| 8192 | } else { | |
| 8193 | s1 = peg$FAILED; | |
| 8194 | if (peg$silentFails === 0) { | |
| 8195 | peg$fail(peg$e165); | |
| 8196 | } | |
| 8197 | } | |
| 8198 | if (s1 !== peg$FAILED) { | |
| 8199 | s2 = peg$parse_(); | |
| 8200 | peg$savedPos = s0; | |
| 8201 | s0 = peg$f7(s1, s2); | |
| 8202 | } else { | |
| 8203 | peg$currPos = s0; | |
| 8204 | s0 = peg$FAILED; | |
| 8205 | } | |
| 8206 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8207 | return s0; | |
| 8208 | } | |
| 8209 | function peg$parseDEC_OP() { | |
| 8210 | var s0, s1, s2; | |
| 8211 | var key = peg$currPos * 306 + 170; | |
| 8212 | var cached = peg$resultsCache[key]; | |
| 8213 | if (cached) { | |
| 8214 | peg$currPos = cached.nextPos; | |
| 8215 | return cached.result; | |
| 8216 | } | |
| 8217 | s0 = peg$currPos; | |
| 8218 | if (input.substr(peg$currPos, 2) === peg$c165) { | |
| 8219 | s1 = peg$c165; | |
| 8220 | peg$currPos += 2; | |
| 8221 | } else { | |
| 8222 | s1 = peg$FAILED; | |
| 8223 | if (peg$silentFails === 0) { | |
| 8224 | peg$fail(peg$e166); | |
| 8225 | } | |
| 8226 | } | |
| 8227 | if (s1 !== peg$FAILED) { | |
| 8228 | s2 = peg$parse_(); | |
| 8229 | peg$savedPos = s0; | |
| 8230 | s0 = peg$f7(s1, s2); | |
| 8231 | } else { | |
| 8232 | peg$currPos = s0; | |
| 8233 | s0 = peg$FAILED; | |
| 8234 | } | |
| 8235 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8236 | return s0; | |
| 8237 | } | |
| 8238 | function peg$parseLE_OP() { | |
| 8239 | var s0, s1, s2; | |
| 8240 | var key = peg$currPos * 306 + 171; | |
| 8241 | var cached = peg$resultsCache[key]; | |
| 8242 | if (cached) { | |
| 8243 | peg$currPos = cached.nextPos; | |
| 8244 | return cached.result; | |
| 8245 | } | |
| 8246 | s0 = peg$currPos; | |
| 8247 | if (input.substr(peg$currPos, 2) === peg$c166) { | |
| 8248 | s1 = peg$c166; | |
| 8249 | peg$currPos += 2; | |
| 8250 | } else { | |
| 8251 | s1 = peg$FAILED; | |
| 8252 | if (peg$silentFails === 0) { | |
| 8253 | peg$fail(peg$e167); | |
| 8254 | } | |
| 8255 | } | |
| 8256 | if (s1 !== peg$FAILED) { | |
| 8257 | s2 = peg$parse_(); | |
| 8258 | peg$savedPos = s0; | |
| 8259 | s0 = peg$f7(s1, s2); | |
| 8260 | } else { | |
| 8261 | peg$currPos = s0; | |
| 8262 | s0 = peg$FAILED; | |
| 8263 | } | |
| 8264 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8265 | return s0; | |
| 8266 | } | |
| 8267 | function peg$parseGE_OP() { | |
| 8268 | var s0, s1, s2; | |
| 8269 | var key = peg$currPos * 306 + 172; | |
| 8270 | var cached = peg$resultsCache[key]; | |
| 8271 | if (cached) { | |
| 8272 | peg$currPos = cached.nextPos; | |
| 8273 | return cached.result; | |
| 8274 | } | |
| 8275 | s0 = peg$currPos; | |
| 8276 | if (input.substr(peg$currPos, 2) === peg$c167) { | |
| 8277 | s1 = peg$c167; | |
| 8278 | peg$currPos += 2; | |
| 8279 | } else { | |
| 8280 | s1 = peg$FAILED; | |
| 8281 | if (peg$silentFails === 0) { | |
| 8282 | peg$fail(peg$e168); | |
| 8283 | } | |
| 8284 | } | |
| 8285 | if (s1 !== peg$FAILED) { | |
| 8286 | s2 = peg$parse_(); | |
| 8287 | peg$savedPos = s0; | |
| 8288 | s0 = peg$f7(s1, s2); | |
| 8289 | } else { | |
| 8290 | peg$currPos = s0; | |
| 8291 | s0 = peg$FAILED; | |
| 8292 | } | |
| 8293 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8294 | return s0; | |
| 8295 | } | |
| 8296 | function peg$parseEQ_OP() { | |
| 8297 | var s0, s1, s2; | |
| 8298 | var key = peg$currPos * 306 + 173; | |
| 8299 | var cached = peg$resultsCache[key]; | |
| 8300 | if (cached) { | |
| 8301 | peg$currPos = cached.nextPos; | |
| 8302 | return cached.result; | |
| 8303 | } | |
| 8304 | s0 = peg$currPos; | |
| 8305 | if (input.substr(peg$currPos, 2) === peg$c168) { | |
| 8306 | s1 = peg$c168; | |
| 8307 | peg$currPos += 2; | |
| 8308 | } else { | |
| 8309 | s1 = peg$FAILED; | |
| 8310 | if (peg$silentFails === 0) { | |
| 8311 | peg$fail(peg$e169); | |
| 8312 | } | |
| 8313 | } | |
| 8314 | if (s1 !== peg$FAILED) { | |
| 8315 | s2 = peg$parse_(); | |
| 8316 | peg$savedPos = s0; | |
| 8317 | s0 = peg$f7(s1, s2); | |
| 8318 | } else { | |
| 8319 | peg$currPos = s0; | |
| 8320 | s0 = peg$FAILED; | |
| 8321 | } | |
| 8322 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8323 | return s0; | |
| 8324 | } | |
| 8325 | function peg$parseNE_OP() { | |
| 8326 | var s0, s1, s2; | |
| 8327 | var key = peg$currPos * 306 + 174; | |
| 8328 | var cached = peg$resultsCache[key]; | |
| 8329 | if (cached) { | |
| 8330 | peg$currPos = cached.nextPos; | |
| 8331 | return cached.result; | |
| 8332 | } | |
| 8333 | s0 = peg$currPos; | |
| 8334 | if (input.substr(peg$currPos, 2) === peg$c169) { | |
| 8335 | s1 = peg$c169; | |
| 8336 | peg$currPos += 2; | |
| 8337 | } else { | |
| 8338 | s1 = peg$FAILED; | |
| 8339 | if (peg$silentFails === 0) { | |
| 8340 | peg$fail(peg$e170); | |
| 8341 | } | |
| 8342 | } | |
| 8343 | if (s1 !== peg$FAILED) { | |
| 8344 | s2 = peg$parse_(); | |
| 8345 | peg$savedPos = s0; | |
| 8346 | s0 = peg$f7(s1, s2); | |
| 8347 | } else { | |
| 8348 | peg$currPos = s0; | |
| 8349 | s0 = peg$FAILED; | |
| 8350 | } | |
| 8351 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8352 | return s0; | |
| 8353 | } | |
| 8354 | function peg$parseAND_OP() { | |
| 8355 | var s0, s1, s2; | |
| 8356 | var key = peg$currPos * 306 + 175; | |
| 8357 | var cached = peg$resultsCache[key]; | |
| 8358 | if (cached) { | |
| 8359 | peg$currPos = cached.nextPos; | |
| 8360 | return cached.result; | |
| 8361 | } | |
| 8362 | s0 = peg$currPos; | |
| 8363 | if (input.substr(peg$currPos, 2) === peg$c170) { | |
| 8364 | s1 = peg$c170; | |
| 8365 | peg$currPos += 2; | |
| 8366 | } else { | |
| 8367 | s1 = peg$FAILED; | |
| 8368 | if (peg$silentFails === 0) { | |
| 8369 | peg$fail(peg$e171); | |
| 8370 | } | |
| 8371 | } | |
| 8372 | if (s1 !== peg$FAILED) { | |
| 8373 | s2 = peg$parse_(); | |
| 8374 | peg$savedPos = s0; | |
| 8375 | s0 = peg$f7(s1, s2); | |
| 8376 | } else { | |
| 8377 | peg$currPos = s0; | |
| 8378 | s0 = peg$FAILED; | |
| 8379 | } | |
| 8380 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8381 | return s0; | |
| 8382 | } | |
| 8383 | function peg$parseOR_OP() { | |
| 8384 | var s0, s1, s2; | |
| 8385 | var key = peg$currPos * 306 + 176; | |
| 8386 | var cached = peg$resultsCache[key]; | |
| 8387 | if (cached) { | |
| 8388 | peg$currPos = cached.nextPos; | |
| 8389 | return cached.result; | |
| 8390 | } | |
| 8391 | s0 = peg$currPos; | |
| 8392 | if (input.substr(peg$currPos, 2) === peg$c171) { | |
| 8393 | s1 = peg$c171; | |
| 8394 | peg$currPos += 2; | |
| 8395 | } else { | |
| 8396 | s1 = peg$FAILED; | |
| 8397 | if (peg$silentFails === 0) { | |
| 8398 | peg$fail(peg$e172); | |
| 8399 | } | |
| 8400 | } | |
| 8401 | if (s1 !== peg$FAILED) { | |
| 8402 | s2 = peg$parse_(); | |
| 8403 | peg$savedPos = s0; | |
| 8404 | s0 = peg$f7(s1, s2); | |
| 8405 | } else { | |
| 8406 | peg$currPos = s0; | |
| 8407 | s0 = peg$FAILED; | |
| 8408 | } | |
| 8409 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8410 | return s0; | |
| 8411 | } | |
| 8412 | function peg$parseXOR_OP() { | |
| 8413 | var s0, s1, s2; | |
| 8414 | var key = peg$currPos * 306 + 177; | |
| 8415 | var cached = peg$resultsCache[key]; | |
| 8416 | if (cached) { | |
| 8417 | peg$currPos = cached.nextPos; | |
| 8418 | return cached.result; | |
| 8419 | } | |
| 8420 | s0 = peg$currPos; | |
| 8421 | if (input.substr(peg$currPos, 2) === peg$c172) { | |
| 8422 | s1 = peg$c172; | |
| 8423 | peg$currPos += 2; | |
| 8424 | } else { | |
| 8425 | s1 = peg$FAILED; | |
| 8426 | if (peg$silentFails === 0) { | |
| 8427 | peg$fail(peg$e173); | |
| 8428 | } | |
| 8429 | } | |
| 8430 | if (s1 !== peg$FAILED) { | |
| 8431 | s2 = peg$parse_(); | |
| 8432 | peg$savedPos = s0; | |
| 8433 | s0 = peg$f7(s1, s2); | |
| 8434 | } else { | |
| 8435 | peg$currPos = s0; | |
| 8436 | s0 = peg$FAILED; | |
| 8437 | } | |
| 8438 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8439 | return s0; | |
| 8440 | } | |
| 8441 | function peg$parseMUL_ASSIGN() { | |
| 8442 | var s0, s1, s2; | |
| 8443 | var key = peg$currPos * 306 + 178; | |
| 8444 | var cached = peg$resultsCache[key]; | |
| 8445 | if (cached) { | |
| 8446 | peg$currPos = cached.nextPos; | |
| 8447 | return cached.result; | |
| 8448 | } | |
| 8449 | s0 = peg$currPos; | |
| 8450 | if (input.substr(peg$currPos, 2) === peg$c173) { | |
| 8451 | s1 = peg$c173; | |
| 8452 | peg$currPos += 2; | |
| 8453 | } else { | |
| 8454 | s1 = peg$FAILED; | |
| 8455 | if (peg$silentFails === 0) { | |
| 8456 | peg$fail(peg$e174); | |
| 8457 | } | |
| 8458 | } | |
| 8459 | if (s1 !== peg$FAILED) { | |
| 8460 | s2 = peg$parse_(); | |
| 8461 | peg$savedPos = s0; | |
| 8462 | s0 = peg$f7(s1, s2); | |
| 8463 | } else { | |
| 8464 | peg$currPos = s0; | |
| 8465 | s0 = peg$FAILED; | |
| 8466 | } | |
| 8467 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8468 | return s0; | |
| 8469 | } | |
| 8470 | function peg$parseDIV_ASSIGN() { | |
| 8471 | var s0, s1, s2; | |
| 8472 | var key = peg$currPos * 306 + 179; | |
| 8473 | var cached = peg$resultsCache[key]; | |
| 8474 | if (cached) { | |
| 8475 | peg$currPos = cached.nextPos; | |
| 8476 | return cached.result; | |
| 8477 | } | |
| 8478 | s0 = peg$currPos; | |
| 8479 | if (input.substr(peg$currPos, 2) === peg$c174) { | |
| 8480 | s1 = peg$c174; | |
| 8481 | peg$currPos += 2; | |
| 8482 | } else { | |
| 8483 | s1 = peg$FAILED; | |
| 8484 | if (peg$silentFails === 0) { | |
| 8485 | peg$fail(peg$e175); | |
| 8486 | } | |
| 8487 | } | |
| 8488 | if (s1 !== peg$FAILED) { | |
| 8489 | s2 = peg$parse_(); | |
| 8490 | peg$savedPos = s0; | |
| 8491 | s0 = peg$f7(s1, s2); | |
| 8492 | } else { | |
| 8493 | peg$currPos = s0; | |
| 8494 | s0 = peg$FAILED; | |
| 8495 | } | |
| 8496 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8497 | return s0; | |
| 8498 | } | |
| 8499 | function peg$parseADD_ASSIGN() { | |
| 8500 | var s0, s1, s2; | |
| 8501 | var key = peg$currPos * 306 + 180; | |
| 8502 | var cached = peg$resultsCache[key]; | |
| 8503 | if (cached) { | |
| 8504 | peg$currPos = cached.nextPos; | |
| 8505 | return cached.result; | |
| 8506 | } | |
| 8507 | s0 = peg$currPos; | |
| 8508 | if (input.substr(peg$currPos, 2) === peg$c175) { | |
| 8509 | s1 = peg$c175; | |
| 8510 | peg$currPos += 2; | |
| 8511 | } else { | |
| 8512 | s1 = peg$FAILED; | |
| 8513 | if (peg$silentFails === 0) { | |
| 8514 | peg$fail(peg$e176); | |
| 8515 | } | |
| 8516 | } | |
| 8517 | if (s1 !== peg$FAILED) { | |
| 8518 | s2 = peg$parse_(); | |
| 8519 | peg$savedPos = s0; | |
| 8520 | s0 = peg$f7(s1, s2); | |
| 8521 | } else { | |
| 8522 | peg$currPos = s0; | |
| 8523 | s0 = peg$FAILED; | |
| 8524 | } | |
| 8525 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8526 | return s0; | |
| 8527 | } | |
| 8528 | function peg$parseMOD_ASSIGN() { | |
| 8529 | var s0, s1, s2; | |
| 8530 | var key = peg$currPos * 306 + 181; | |
| 8531 | var cached = peg$resultsCache[key]; | |
| 8532 | if (cached) { | |
| 8533 | peg$currPos = cached.nextPos; | |
| 8534 | return cached.result; | |
| 8535 | } | |
| 8536 | s0 = peg$currPos; | |
| 8537 | if (input.substr(peg$currPos, 2) === peg$c176) { | |
| 8538 | s1 = peg$c176; | |
| 8539 | peg$currPos += 2; | |
| 8540 | } else { | |
| 8541 | s1 = peg$FAILED; | |
| 8542 | if (peg$silentFails === 0) { | |
| 8543 | peg$fail(peg$e177); | |
| 8544 | } | |
| 8545 | } | |
| 8546 | if (s1 !== peg$FAILED) { | |
| 8547 | s2 = peg$parse_(); | |
| 8548 | peg$savedPos = s0; | |
| 8549 | s0 = peg$f7(s1, s2); | |
| 8550 | } else { | |
| 8551 | peg$currPos = s0; | |
| 8552 | s0 = peg$FAILED; | |
| 8553 | } | |
| 8554 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8555 | return s0; | |
| 8556 | } | |
| 8557 | function peg$parseLEFT_ASSIGN() { | |
| 8558 | var s0, s1, s2; | |
| 8559 | var key = peg$currPos * 306 + 182; | |
| 8560 | var cached = peg$resultsCache[key]; | |
| 8561 | if (cached) { | |
| 8562 | peg$currPos = cached.nextPos; | |
| 8563 | return cached.result; | |
| 8564 | } | |
| 8565 | s0 = peg$currPos; | |
| 8566 | if (input.substr(peg$currPos, 3) === peg$c177) { | |
| 8567 | s1 = peg$c177; | |
| 8568 | peg$currPos += 3; | |
| 8569 | } else { | |
| 8570 | s1 = peg$FAILED; | |
| 8571 | if (peg$silentFails === 0) { | |
| 8572 | peg$fail(peg$e178); | |
| 8573 | } | |
| 8574 | } | |
| 8575 | if (s1 !== peg$FAILED) { | |
| 8576 | s2 = peg$parse_(); | |
| 8577 | peg$savedPos = s0; | |
| 8578 | s0 = peg$f7(s1, s2); | |
| 8579 | } else { | |
| 8580 | peg$currPos = s0; | |
| 8581 | s0 = peg$FAILED; | |
| 8582 | } | |
| 8583 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8584 | return s0; | |
| 8585 | } | |
| 8586 | function peg$parseRIGHT_ASSIGN() { | |
| 8587 | var s0, s1, s2; | |
| 8588 | var key = peg$currPos * 306 + 183; | |
| 8589 | var cached = peg$resultsCache[key]; | |
| 8590 | if (cached) { | |
| 8591 | peg$currPos = cached.nextPos; | |
| 8592 | return cached.result; | |
| 8593 | } | |
| 8594 | s0 = peg$currPos; | |
| 8595 | if (input.substr(peg$currPos, 3) === peg$c178) { | |
| 8596 | s1 = peg$c178; | |
| 8597 | peg$currPos += 3; | |
| 8598 | } else { | |
| 8599 | s1 = peg$FAILED; | |
| 8600 | if (peg$silentFails === 0) { | |
| 8601 | peg$fail(peg$e179); | |
| 8602 | } | |
| 8603 | } | |
| 8604 | if (s1 !== peg$FAILED) { | |
| 8605 | s2 = peg$parse_(); | |
| 8606 | peg$savedPos = s0; | |
| 8607 | s0 = peg$f7(s1, s2); | |
| 8608 | } else { | |
| 8609 | peg$currPos = s0; | |
| 8610 | s0 = peg$FAILED; | |
| 8611 | } | |
| 8612 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8613 | return s0; | |
| 8614 | } | |
| 8615 | function peg$parseAND_ASSIGN() { | |
| 8616 | var s0, s1, s2; | |
| 8617 | var key = peg$currPos * 306 + 184; | |
| 8618 | var cached = peg$resultsCache[key]; | |
| 8619 | if (cached) { | |
| 8620 | peg$currPos = cached.nextPos; | |
| 8621 | return cached.result; | |
| 8622 | } | |
| 8623 | s0 = peg$currPos; | |
| 8624 | if (input.substr(peg$currPos, 2) === peg$c179) { | |
| 8625 | s1 = peg$c179; | |
| 8626 | peg$currPos += 2; | |
| 8627 | } else { | |
| 8628 | s1 = peg$FAILED; | |
| 8629 | if (peg$silentFails === 0) { | |
| 8630 | peg$fail(peg$e180); | |
| 8631 | } | |
| 8632 | } | |
| 8633 | if (s1 !== peg$FAILED) { | |
| 8634 | s2 = peg$parse_(); | |
| 8635 | peg$savedPos = s0; | |
| 8636 | s0 = peg$f7(s1, s2); | |
| 8637 | } else { | |
| 8638 | peg$currPos = s0; | |
| 8639 | s0 = peg$FAILED; | |
| 8640 | } | |
| 8641 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8642 | return s0; | |
| 8643 | } | |
| 8644 | function peg$parseXOR_ASSIGN() { | |
| 8645 | var s0, s1, s2; | |
| 8646 | var key = peg$currPos * 306 + 185; | |
| 8647 | var cached = peg$resultsCache[key]; | |
| 8648 | if (cached) { | |
| 8649 | peg$currPos = cached.nextPos; | |
| 8650 | return cached.result; | |
| 8651 | } | |
| 8652 | s0 = peg$currPos; | |
| 8653 | if (input.substr(peg$currPos, 2) === peg$c180) { | |
| 8654 | s1 = peg$c180; | |
| 8655 | peg$currPos += 2; | |
| 8656 | } else { | |
| 8657 | s1 = peg$FAILED; | |
| 8658 | if (peg$silentFails === 0) { | |
| 8659 | peg$fail(peg$e181); | |
| 8660 | } | |
| 8661 | } | |
| 8662 | if (s1 !== peg$FAILED) { | |
| 8663 | s2 = peg$parse_(); | |
| 8664 | peg$savedPos = s0; | |
| 8665 | s0 = peg$f7(s1, s2); | |
| 8666 | } else { | |
| 8667 | peg$currPos = s0; | |
| 8668 | s0 = peg$FAILED; | |
| 8669 | } | |
| 8670 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8671 | return s0; | |
| 8672 | } | |
| 8673 | function peg$parseOR_ASSIGN() { | |
| 8674 | var s0, s1, s2; | |
| 8675 | var key = peg$currPos * 306 + 186; | |
| 8676 | var cached = peg$resultsCache[key]; | |
| 8677 | if (cached) { | |
| 8678 | peg$currPos = cached.nextPos; | |
| 8679 | return cached.result; | |
| 8680 | } | |
| 8681 | s0 = peg$currPos; | |
| 8682 | if (input.substr(peg$currPos, 2) === peg$c181) { | |
| 8683 | s1 = peg$c181; | |
| 8684 | peg$currPos += 2; | |
| 8685 | } else { | |
| 8686 | s1 = peg$FAILED; | |
| 8687 | if (peg$silentFails === 0) { | |
| 8688 | peg$fail(peg$e182); | |
| 8689 | } | |
| 8690 | } | |
| 8691 | if (s1 !== peg$FAILED) { | |
| 8692 | s2 = peg$parse_(); | |
| 8693 | peg$savedPos = s0; | |
| 8694 | s0 = peg$f7(s1, s2); | |
| 8695 | } else { | |
| 8696 | peg$currPos = s0; | |
| 8697 | s0 = peg$FAILED; | |
| 8698 | } | |
| 8699 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8700 | return s0; | |
| 8701 | } | |
| 8702 | function peg$parseSUB_ASSIGN() { | |
| 8703 | var s0, s1, s2; | |
| 8704 | var key = peg$currPos * 306 + 187; | |
| 8705 | var cached = peg$resultsCache[key]; | |
| 8706 | if (cached) { | |
| 8707 | peg$currPos = cached.nextPos; | |
| 8708 | return cached.result; | |
| 8709 | } | |
| 8710 | s0 = peg$currPos; | |
| 8711 | if (input.substr(peg$currPos, 2) === peg$c182) { | |
| 8712 | s1 = peg$c182; | |
| 8713 | peg$currPos += 2; | |
| 8714 | } else { | |
| 8715 | s1 = peg$FAILED; | |
| 8716 | if (peg$silentFails === 0) { | |
| 8717 | peg$fail(peg$e183); | |
| 8718 | } | |
| 8719 | } | |
| 8720 | if (s1 !== peg$FAILED) { | |
| 8721 | s2 = peg$parse_(); | |
| 8722 | peg$savedPos = s0; | |
| 8723 | s0 = peg$f7(s1, s2); | |
| 8724 | } else { | |
| 8725 | peg$currPos = s0; | |
| 8726 | s0 = peg$FAILED; | |
| 8727 | } | |
| 8728 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8729 | return s0; | |
| 8730 | } | |
| 8731 | function peg$parseLEFT_PAREN() { | |
| 8732 | var s0, s1, s2; | |
| 8733 | var key = peg$currPos * 306 + 188; | |
| 8734 | var cached = peg$resultsCache[key]; | |
| 8735 | if (cached) { | |
| 8736 | peg$currPos = cached.nextPos; | |
| 8737 | return cached.result; | |
| 8738 | } | |
| 8739 | s0 = peg$currPos; | |
| 8740 | if (input.charCodeAt(peg$currPos) === 40) { | |
| 8741 | s1 = peg$c183; | |
| 8742 | peg$currPos++; | |
| 8743 | } else { | |
| 8744 | s1 = peg$FAILED; | |
| 8745 | if (peg$silentFails === 0) { | |
| 8746 | peg$fail(peg$e184); | |
| 8747 | } | |
| 8748 | } | |
| 8749 | if (s1 !== peg$FAILED) { | |
| 8750 | s2 = peg$parse_(); | |
| 8751 | peg$savedPos = s0; | |
| 8752 | s0 = peg$f7(s1, s2); | |
| 8753 | } else { | |
| 8754 | peg$currPos = s0; | |
| 8755 | s0 = peg$FAILED; | |
| 8756 | } | |
| 8757 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8758 | return s0; | |
| 8759 | } | |
| 8760 | function peg$parseRIGHT_PAREN() { | |
| 8761 | var s0, s1, s2; | |
| 8762 | var key = peg$currPos * 306 + 189; | |
| 8763 | var cached = peg$resultsCache[key]; | |
| 8764 | if (cached) { | |
| 8765 | peg$currPos = cached.nextPos; | |
| 8766 | return cached.result; | |
| 8767 | } | |
| 8768 | s0 = peg$currPos; | |
| 8769 | if (input.charCodeAt(peg$currPos) === 41) { | |
| 8770 | s1 = peg$c184; | |
| 8771 | peg$currPos++; | |
| 8772 | } else { | |
| 8773 | s1 = peg$FAILED; | |
| 8774 | if (peg$silentFails === 0) { | |
| 8775 | peg$fail(peg$e185); | |
| 8776 | } | |
| 8777 | } | |
| 8778 | if (s1 !== peg$FAILED) { | |
| 8779 | s2 = peg$parse_(); | |
| 8780 | peg$savedPos = s0; | |
| 8781 | s0 = peg$f7(s1, s2); | |
| 8782 | } else { | |
| 8783 | peg$currPos = s0; | |
| 8784 | s0 = peg$FAILED; | |
| 8785 | } | |
| 8786 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8787 | return s0; | |
| 8788 | } | |
| 8789 | function peg$parseLEFT_BRACKET() { | |
| 8790 | var s0, s1, s2; | |
| 8791 | var key = peg$currPos * 306 + 190; | |
| 8792 | var cached = peg$resultsCache[key]; | |
| 8793 | if (cached) { | |
| 8794 | peg$currPos = cached.nextPos; | |
| 8795 | return cached.result; | |
| 8796 | } | |
| 8797 | s0 = peg$currPos; | |
| 8798 | if (input.charCodeAt(peg$currPos) === 91) { | |
| 8799 | s1 = peg$c185; | |
| 8800 | peg$currPos++; | |
| 8801 | } else { | |
| 8802 | s1 = peg$FAILED; | |
| 8803 | if (peg$silentFails === 0) { | |
| 8804 | peg$fail(peg$e186); | |
| 8805 | } | |
| 8806 | } | |
| 8807 | if (s1 !== peg$FAILED) { | |
| 8808 | s2 = peg$parse_(); | |
| 8809 | peg$savedPos = s0; | |
| 8810 | s0 = peg$f7(s1, s2); | |
| 8811 | } else { | |
| 8812 | peg$currPos = s0; | |
| 8813 | s0 = peg$FAILED; | |
| 8814 | } | |
| 8815 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8816 | return s0; | |
| 8817 | } | |
| 8818 | function peg$parseRIGHT_BRACKET() { | |
| 8819 | var s0, s1, s2; | |
| 8820 | var key = peg$currPos * 306 + 191; | |
| 8821 | var cached = peg$resultsCache[key]; | |
| 8822 | if (cached) { | |
| 8823 | peg$currPos = cached.nextPos; | |
| 8824 | return cached.result; | |
| 8825 | } | |
| 8826 | s0 = peg$currPos; | |
| 8827 | if (input.charCodeAt(peg$currPos) === 93) { | |
| 8828 | s1 = peg$c186; | |
| 8829 | peg$currPos++; | |
| 8830 | } else { | |
| 8831 | s1 = peg$FAILED; | |
| 8832 | if (peg$silentFails === 0) { | |
| 8833 | peg$fail(peg$e187); | |
| 8834 | } | |
| 8835 | } | |
| 8836 | if (s1 !== peg$FAILED) { | |
| 8837 | s2 = peg$parse_(); | |
| 8838 | peg$savedPos = s0; | |
| 8839 | s0 = peg$f7(s1, s2); | |
| 8840 | } else { | |
| 8841 | peg$currPos = s0; | |
| 8842 | s0 = peg$FAILED; | |
| 8843 | } | |
| 8844 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8845 | return s0; | |
| 8846 | } | |
| 8847 | function peg$parseLEFT_BRACE() { | |
| 8848 | var s0, s1, s2; | |
| 8849 | var key = peg$currPos * 306 + 192; | |
| 8850 | var cached = peg$resultsCache[key]; | |
| 8851 | if (cached) { | |
| 8852 | peg$currPos = cached.nextPos; | |
| 8853 | return cached.result; | |
| 8854 | } | |
| 8855 | s0 = peg$currPos; | |
| 8856 | if (input.charCodeAt(peg$currPos) === 123) { | |
| 8857 | s1 = peg$c187; | |
| 8858 | peg$currPos++; | |
| 8859 | } else { | |
| 8860 | s1 = peg$FAILED; | |
| 8861 | if (peg$silentFails === 0) { | |
| 8862 | peg$fail(peg$e188); | |
| 8863 | } | |
| 8864 | } | |
| 8865 | if (s1 !== peg$FAILED) { | |
| 8866 | s2 = peg$parse_(); | |
| 8867 | peg$savedPos = s0; | |
| 8868 | s0 = peg$f7(s1, s2); | |
| 8869 | } else { | |
| 8870 | peg$currPos = s0; | |
| 8871 | s0 = peg$FAILED; | |
| 8872 | } | |
| 8873 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8874 | return s0; | |
| 8875 | } | |
| 8876 | function peg$parseRIGHT_BRACE() { | |
| 8877 | var s0, s1, s2; | |
| 8878 | var key = peg$currPos * 306 + 193; | |
| 8879 | var cached = peg$resultsCache[key]; | |
| 8880 | if (cached) { | |
| 8881 | peg$currPos = cached.nextPos; | |
| 8882 | return cached.result; | |
| 8883 | } | |
| 8884 | s0 = peg$currPos; | |
| 8885 | if (input.charCodeAt(peg$currPos) === 125) { | |
| 8886 | s1 = peg$c188; | |
| 8887 | peg$currPos++; | |
| 8888 | } else { | |
| 8889 | s1 = peg$FAILED; | |
| 8890 | if (peg$silentFails === 0) { | |
| 8891 | peg$fail(peg$e189); | |
| 8892 | } | |
| 8893 | } | |
| 8894 | if (s1 !== peg$FAILED) { | |
| 8895 | s2 = peg$parse_(); | |
| 8896 | peg$savedPos = s0; | |
| 8897 | s0 = peg$f7(s1, s2); | |
| 8898 | } else { | |
| 8899 | peg$currPos = s0; | |
| 8900 | s0 = peg$FAILED; | |
| 8901 | } | |
| 8902 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8903 | return s0; | |
| 8904 | } | |
| 8905 | function peg$parseDOT() { | |
| 8906 | var s0, s1, s2; | |
| 8907 | var key = peg$currPos * 306 + 194; | |
| 8908 | var cached = peg$resultsCache[key]; | |
| 8909 | if (cached) { | |
| 8910 | peg$currPos = cached.nextPos; | |
| 8911 | return cached.result; | |
| 8912 | } | |
| 8913 | s0 = peg$currPos; | |
| 8914 | if (input.charCodeAt(peg$currPos) === 46) { | |
| 8915 | s1 = peg$c189; | |
| 8916 | peg$currPos++; | |
| 8917 | } else { | |
| 8918 | s1 = peg$FAILED; | |
| 8919 | if (peg$silentFails === 0) { | |
| 8920 | peg$fail(peg$e190); | |
| 8921 | } | |
| 8922 | } | |
| 8923 | if (s1 !== peg$FAILED) { | |
| 8924 | s2 = peg$parse_(); | |
| 8925 | peg$savedPos = s0; | |
| 8926 | s0 = peg$f7(s1, s2); | |
| 8927 | } else { | |
| 8928 | peg$currPos = s0; | |
| 8929 | s0 = peg$FAILED; | |
| 8930 | } | |
| 8931 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8932 | return s0; | |
| 8933 | } | |
| 8934 | function peg$parseCOMMA() { | |
| 8935 | var s0, s1, s2; | |
| 8936 | var key = peg$currPos * 306 + 195; | |
| 8937 | var cached = peg$resultsCache[key]; | |
| 8938 | if (cached) { | |
| 8939 | peg$currPos = cached.nextPos; | |
| 8940 | return cached.result; | |
| 8941 | } | |
| 8942 | s0 = peg$currPos; | |
| 8943 | if (input.charCodeAt(peg$currPos) === 44) { | |
| 8944 | s1 = peg$c190; | |
| 8945 | peg$currPos++; | |
| 8946 | } else { | |
| 8947 | s1 = peg$FAILED; | |
| 8948 | if (peg$silentFails === 0) { | |
| 8949 | peg$fail(peg$e191); | |
| 8950 | } | |
| 8951 | } | |
| 8952 | if (s1 !== peg$FAILED) { | |
| 8953 | s2 = peg$parse_(); | |
| 8954 | peg$savedPos = s0; | |
| 8955 | s0 = peg$f7(s1, s2); | |
| 8956 | } else { | |
| 8957 | peg$currPos = s0; | |
| 8958 | s0 = peg$FAILED; | |
| 8959 | } | |
| 8960 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8961 | return s0; | |
| 8962 | } | |
| 8963 | function peg$parseCOLON() { | |
| 8964 | var s0, s1, s2; | |
| 8965 | var key = peg$currPos * 306 + 196; | |
| 8966 | var cached = peg$resultsCache[key]; | |
| 8967 | if (cached) { | |
| 8968 | peg$currPos = cached.nextPos; | |
| 8969 | return cached.result; | |
| 8970 | } | |
| 8971 | s0 = peg$currPos; | |
| 8972 | if (input.charCodeAt(peg$currPos) === 58) { | |
| 8973 | s1 = peg$c191; | |
| 8974 | peg$currPos++; | |
| 8975 | } else { | |
| 8976 | s1 = peg$FAILED; | |
| 8977 | if (peg$silentFails === 0) { | |
| 8978 | peg$fail(peg$e192); | |
| 8979 | } | |
| 8980 | } | |
| 8981 | if (s1 !== peg$FAILED) { | |
| 8982 | s2 = peg$parse_(); | |
| 8983 | peg$savedPos = s0; | |
| 8984 | s0 = peg$f7(s1, s2); | |
| 8985 | } else { | |
| 8986 | peg$currPos = s0; | |
| 8987 | s0 = peg$FAILED; | |
| 8988 | } | |
| 8989 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 8990 | return s0; | |
| 8991 | } | |
| 8992 | function peg$parseEQUAL() { | |
| 8993 | var s0, s1, s2; | |
| 8994 | var key = peg$currPos * 306 + 197; | |
| 8995 | var cached = peg$resultsCache[key]; | |
| 8996 | if (cached) { | |
| 8997 | peg$currPos = cached.nextPos; | |
| 8998 | return cached.result; | |
| 8999 | } | |
| 9000 | s0 = peg$currPos; | |
| 9001 | if (input.charCodeAt(peg$currPos) === 61) { | |
| 9002 | s1 = peg$c192; | |
| 9003 | peg$currPos++; | |
| 9004 | } else { | |
| 9005 | s1 = peg$FAILED; | |
| 9006 | if (peg$silentFails === 0) { | |
| 9007 | peg$fail(peg$e193); | |
| 9008 | } | |
| 9009 | } | |
| 9010 | if (s1 !== peg$FAILED) { | |
| 9011 | s2 = peg$parse_(); | |
| 9012 | peg$savedPos = s0; | |
| 9013 | s0 = peg$f7(s1, s2); | |
| 9014 | } else { | |
| 9015 | peg$currPos = s0; | |
| 9016 | s0 = peg$FAILED; | |
| 9017 | } | |
| 9018 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9019 | return s0; | |
| 9020 | } | |
| 9021 | function peg$parseSEMICOLON() { | |
| 9022 | var s0, s1, s2; | |
| 9023 | var key = peg$currPos * 306 + 198; | |
| 9024 | var cached = peg$resultsCache[key]; | |
| 9025 | if (cached) { | |
| 9026 | peg$currPos = cached.nextPos; | |
| 9027 | return cached.result; | |
| 9028 | } | |
| 9029 | s0 = peg$currPos; | |
| 9030 | if (input.charCodeAt(peg$currPos) === 59) { | |
| 9031 | s1 = peg$c193; | |
| 9032 | peg$currPos++; | |
| 9033 | } else { | |
| 9034 | s1 = peg$FAILED; | |
| 9035 | if (peg$silentFails === 0) { | |
| 9036 | peg$fail(peg$e194); | |
| 9037 | } | |
| 9038 | } | |
| 9039 | if (s1 !== peg$FAILED) { | |
| 9040 | s2 = peg$parse_(); | |
| 9041 | peg$savedPos = s0; | |
| 9042 | s0 = peg$f7(s1, s2); | |
| 9043 | } else { | |
| 9044 | peg$currPos = s0; | |
| 9045 | s0 = peg$FAILED; | |
| 9046 | } | |
| 9047 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9048 | return s0; | |
| 9049 | } | |
| 9050 | function peg$parseBANG() { | |
| 9051 | var s0, s1, s2; | |
| 9052 | var key = peg$currPos * 306 + 199; | |
| 9053 | var cached = peg$resultsCache[key]; | |
| 9054 | if (cached) { | |
| 9055 | peg$currPos = cached.nextPos; | |
| 9056 | return cached.result; | |
| 9057 | } | |
| 9058 | s0 = peg$currPos; | |
| 9059 | if (input.charCodeAt(peg$currPos) === 33) { | |
| 9060 | s1 = peg$c194; | |
| 9061 | peg$currPos++; | |
| 9062 | } else { | |
| 9063 | s1 = peg$FAILED; | |
| 9064 | if (peg$silentFails === 0) { | |
| 9065 | peg$fail(peg$e195); | |
| 9066 | } | |
| 9067 | } | |
| 9068 | if (s1 !== peg$FAILED) { | |
| 9069 | s2 = peg$parse_(); | |
| 9070 | peg$savedPos = s0; | |
| 9071 | s0 = peg$f7(s1, s2); | |
| 9072 | } else { | |
| 9073 | peg$currPos = s0; | |
| 9074 | s0 = peg$FAILED; | |
| 9075 | } | |
| 9076 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9077 | return s0; | |
| 9078 | } | |
| 9079 | function peg$parseDASH() { | |
| 9080 | var s0, s1, s2; | |
| 9081 | var key = peg$currPos * 306 + 200; | |
| 9082 | var cached = peg$resultsCache[key]; | |
| 9083 | if (cached) { | |
| 9084 | peg$currPos = cached.nextPos; | |
| 9085 | return cached.result; | |
| 9086 | } | |
| 9087 | s0 = peg$currPos; | |
| 9088 | if (input.charCodeAt(peg$currPos) === 45) { | |
| 9089 | s1 = peg$c195; | |
| 9090 | peg$currPos++; | |
| 9091 | } else { | |
| 9092 | s1 = peg$FAILED; | |
| 9093 | if (peg$silentFails === 0) { | |
| 9094 | peg$fail(peg$e196); | |
| 9095 | } | |
| 9096 | } | |
| 9097 | if (s1 !== peg$FAILED) { | |
| 9098 | s2 = peg$parse_(); | |
| 9099 | peg$savedPos = s0; | |
| 9100 | s0 = peg$f7(s1, s2); | |
| 9101 | } else { | |
| 9102 | peg$currPos = s0; | |
| 9103 | s0 = peg$FAILED; | |
| 9104 | } | |
| 9105 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9106 | return s0; | |
| 9107 | } | |
| 9108 | function peg$parseTILDE() { | |
| 9109 | var s0, s1, s2; | |
| 9110 | var key = peg$currPos * 306 + 201; | |
| 9111 | var cached = peg$resultsCache[key]; | |
| 9112 | if (cached) { | |
| 9113 | peg$currPos = cached.nextPos; | |
| 9114 | return cached.result; | |
| 9115 | } | |
| 9116 | s0 = peg$currPos; | |
| 9117 | if (input.charCodeAt(peg$currPos) === 126) { | |
| 9118 | s1 = peg$c196; | |
| 9119 | peg$currPos++; | |
| 9120 | } else { | |
| 9121 | s1 = peg$FAILED; | |
| 9122 | if (peg$silentFails === 0) { | |
| 9123 | peg$fail(peg$e197); | |
| 9124 | } | |
| 9125 | } | |
| 9126 | if (s1 !== peg$FAILED) { | |
| 9127 | s2 = peg$parse_(); | |
| 9128 | peg$savedPos = s0; | |
| 9129 | s0 = peg$f7(s1, s2); | |
| 9130 | } else { | |
| 9131 | peg$currPos = s0; | |
| 9132 | s0 = peg$FAILED; | |
| 9133 | } | |
| 9134 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9135 | return s0; | |
| 9136 | } | |
| 9137 | function peg$parsePLUS() { | |
| 9138 | var s0, s1, s2; | |
| 9139 | var key = peg$currPos * 306 + 202; | |
| 9140 | var cached = peg$resultsCache[key]; | |
| 9141 | if (cached) { | |
| 9142 | peg$currPos = cached.nextPos; | |
| 9143 | return cached.result; | |
| 9144 | } | |
| 9145 | s0 = peg$currPos; | |
| 9146 | if (input.charCodeAt(peg$currPos) === 43) { | |
| 9147 | s1 = peg$c197; | |
| 9148 | peg$currPos++; | |
| 9149 | } else { | |
| 9150 | s1 = peg$FAILED; | |
| 9151 | if (peg$silentFails === 0) { | |
| 9152 | peg$fail(peg$e198); | |
| 9153 | } | |
| 9154 | } | |
| 9155 | if (s1 !== peg$FAILED) { | |
| 9156 | s2 = peg$parse_(); | |
| 9157 | peg$savedPos = s0; | |
| 9158 | s0 = peg$f7(s1, s2); | |
| 9159 | } else { | |
| 9160 | peg$currPos = s0; | |
| 9161 | s0 = peg$FAILED; | |
| 9162 | } | |
| 9163 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9164 | return s0; | |
| 9165 | } | |
| 9166 | function peg$parseSTAR() { | |
| 9167 | var s0, s1, s2; | |
| 9168 | var key = peg$currPos * 306 + 203; | |
| 9169 | var cached = peg$resultsCache[key]; | |
| 9170 | if (cached) { | |
| 9171 | peg$currPos = cached.nextPos; | |
| 9172 | return cached.result; | |
| 9173 | } | |
| 9174 | s0 = peg$currPos; | |
| 9175 | if (input.charCodeAt(peg$currPos) === 42) { | |
| 9176 | s1 = peg$c198; | |
| 9177 | peg$currPos++; | |
| 9178 | } else { | |
| 9179 | s1 = peg$FAILED; | |
| 9180 | if (peg$silentFails === 0) { | |
| 9181 | peg$fail(peg$e199); | |
| 9182 | } | |
| 9183 | } | |
| 9184 | if (s1 !== peg$FAILED) { | |
| 9185 | s2 = peg$parse_(); | |
| 9186 | peg$savedPos = s0; | |
| 9187 | s0 = peg$f7(s1, s2); | |
| 9188 | } else { | |
| 9189 | peg$currPos = s0; | |
| 9190 | s0 = peg$FAILED; | |
| 9191 | } | |
| 9192 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9193 | return s0; | |
| 9194 | } | |
| 9195 | function peg$parseSLASH() { | |
| 9196 | var s0, s1, s2; | |
| 9197 | var key = peg$currPos * 306 + 204; | |
| 9198 | var cached = peg$resultsCache[key]; | |
| 9199 | if (cached) { | |
| 9200 | peg$currPos = cached.nextPos; | |
| 9201 | return cached.result; | |
| 9202 | } | |
| 9203 | s0 = peg$currPos; | |
| 9204 | if (input.charCodeAt(peg$currPos) === 47) { | |
| 9205 | s1 = peg$c199; | |
| 9206 | peg$currPos++; | |
| 9207 | } else { | |
| 9208 | s1 = peg$FAILED; | |
| 9209 | if (peg$silentFails === 0) { | |
| 9210 | peg$fail(peg$e200); | |
| 9211 | } | |
| 9212 | } | |
| 9213 | if (s1 !== peg$FAILED) { | |
| 9214 | s2 = peg$parse_(); | |
| 9215 | peg$savedPos = s0; | |
| 9216 | s0 = peg$f7(s1, s2); | |
| 9217 | } else { | |
| 9218 | peg$currPos = s0; | |
| 9219 | s0 = peg$FAILED; | |
| 9220 | } | |
| 9221 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9222 | return s0; | |
| 9223 | } | |
| 9224 | function peg$parsePERCENT() { | |
| 9225 | var s0, s1, s2; | |
| 9226 | var key = peg$currPos * 306 + 205; | |
| 9227 | var cached = peg$resultsCache[key]; | |
| 9228 | if (cached) { | |
| 9229 | peg$currPos = cached.nextPos; | |
| 9230 | return cached.result; | |
| 9231 | } | |
| 9232 | s0 = peg$currPos; | |
| 9233 | if (input.charCodeAt(peg$currPos) === 37) { | |
| 9234 | s1 = peg$c200; | |
| 9235 | peg$currPos++; | |
| 9236 | } else { | |
| 9237 | s1 = peg$FAILED; | |
| 9238 | if (peg$silentFails === 0) { | |
| 9239 | peg$fail(peg$e201); | |
| 9240 | } | |
| 9241 | } | |
| 9242 | if (s1 !== peg$FAILED) { | |
| 9243 | s2 = peg$parse_(); | |
| 9244 | peg$savedPos = s0; | |
| 9245 | s0 = peg$f7(s1, s2); | |
| 9246 | } else { | |
| 9247 | peg$currPos = s0; | |
| 9248 | s0 = peg$FAILED; | |
| 9249 | } | |
| 9250 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9251 | return s0; | |
| 9252 | } | |
| 9253 | function peg$parseLEFT_ANGLE() { | |
| 9254 | var s0, s1, s2; | |
| 9255 | var key = peg$currPos * 306 + 206; | |
| 9256 | var cached = peg$resultsCache[key]; | |
| 9257 | if (cached) { | |
| 9258 | peg$currPos = cached.nextPos; | |
| 9259 | return cached.result; | |
| 9260 | } | |
| 9261 | s0 = peg$currPos; | |
| 9262 | if (input.charCodeAt(peg$currPos) === 60) { | |
| 9263 | s1 = peg$c201; | |
| 9264 | peg$currPos++; | |
| 9265 | } else { | |
| 9266 | s1 = peg$FAILED; | |
| 9267 | if (peg$silentFails === 0) { | |
| 9268 | peg$fail(peg$e202); | |
| 9269 | } | |
| 9270 | } | |
| 9271 | if (s1 !== peg$FAILED) { | |
| 9272 | s2 = peg$parse_(); | |
| 9273 | peg$savedPos = s0; | |
| 9274 | s0 = peg$f7(s1, s2); | |
| 9275 | } else { | |
| 9276 | peg$currPos = s0; | |
| 9277 | s0 = peg$FAILED; | |
| 9278 | } | |
| 9279 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9280 | return s0; | |
| 9281 | } | |
| 9282 | function peg$parseRIGHT_ANGLE() { | |
| 9283 | var s0, s1, s2; | |
| 9284 | var key = peg$currPos * 306 + 207; | |
| 9285 | var cached = peg$resultsCache[key]; | |
| 9286 | if (cached) { | |
| 9287 | peg$currPos = cached.nextPos; | |
| 9288 | return cached.result; | |
| 9289 | } | |
| 9290 | s0 = peg$currPos; | |
| 9291 | if (input.charCodeAt(peg$currPos) === 62) { | |
| 9292 | s1 = peg$c202; | |
| 9293 | peg$currPos++; | |
| 9294 | } else { | |
| 9295 | s1 = peg$FAILED; | |
| 9296 | if (peg$silentFails === 0) { | |
| 9297 | peg$fail(peg$e203); | |
| 9298 | } | |
| 9299 | } | |
| 9300 | if (s1 !== peg$FAILED) { | |
| 9301 | s2 = peg$parse_(); | |
| 9302 | peg$savedPos = s0; | |
| 9303 | s0 = peg$f7(s1, s2); | |
| 9304 | } else { | |
| 9305 | peg$currPos = s0; | |
| 9306 | s0 = peg$FAILED; | |
| 9307 | } | |
| 9308 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9309 | return s0; | |
| 9310 | } | |
| 9311 | function peg$parseVERTICAL_BAR() { | |
| 9312 | var s0, s1, s2; | |
| 9313 | var key = peg$currPos * 306 + 208; | |
| 9314 | var cached = peg$resultsCache[key]; | |
| 9315 | if (cached) { | |
| 9316 | peg$currPos = cached.nextPos; | |
| 9317 | return cached.result; | |
| 9318 | } | |
| 9319 | s0 = peg$currPos; | |
| 9320 | if (input.charCodeAt(peg$currPos) === 124) { | |
| 9321 | s1 = peg$c203; | |
| 9322 | peg$currPos++; | |
| 9323 | } else { | |
| 9324 | s1 = peg$FAILED; | |
| 9325 | if (peg$silentFails === 0) { | |
| 9326 | peg$fail(peg$e204); | |
| 9327 | } | |
| 9328 | } | |
| 9329 | if (s1 !== peg$FAILED) { | |
| 9330 | s2 = peg$parse_(); | |
| 9331 | peg$savedPos = s0; | |
| 9332 | s0 = peg$f7(s1, s2); | |
| 9333 | } else { | |
| 9334 | peg$currPos = s0; | |
| 9335 | s0 = peg$FAILED; | |
| 9336 | } | |
| 9337 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9338 | return s0; | |
| 9339 | } | |
| 9340 | function peg$parseCARET() { | |
| 9341 | var s0, s1, s2; | |
| 9342 | var key = peg$currPos * 306 + 209; | |
| 9343 | var cached = peg$resultsCache[key]; | |
| 9344 | if (cached) { | |
| 9345 | peg$currPos = cached.nextPos; | |
| 9346 | return cached.result; | |
| 9347 | } | |
| 9348 | s0 = peg$currPos; | |
| 9349 | if (input.charCodeAt(peg$currPos) === 94) { | |
| 9350 | s1 = peg$c204; | |
| 9351 | peg$currPos++; | |
| 9352 | } else { | |
| 9353 | s1 = peg$FAILED; | |
| 9354 | if (peg$silentFails === 0) { | |
| 9355 | peg$fail(peg$e205); | |
| 9356 | } | |
| 9357 | } | |
| 9358 | if (s1 !== peg$FAILED) { | |
| 9359 | s2 = peg$parse_(); | |
| 9360 | peg$savedPos = s0; | |
| 9361 | s0 = peg$f7(s1, s2); | |
| 9362 | } else { | |
| 9363 | peg$currPos = s0; | |
| 9364 | s0 = peg$FAILED; | |
| 9365 | } | |
| 9366 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9367 | return s0; | |
| 9368 | } | |
| 9369 | function peg$parseAMPERSAND() { | |
| 9370 | var s0, s1, s2; | |
| 9371 | var key = peg$currPos * 306 + 210; | |
| 9372 | var cached = peg$resultsCache[key]; | |
| 9373 | if (cached) { | |
| 9374 | peg$currPos = cached.nextPos; | |
| 9375 | return cached.result; | |
| 9376 | } | |
| 9377 | s0 = peg$currPos; | |
| 9378 | if (input.charCodeAt(peg$currPos) === 38) { | |
| 9379 | s1 = peg$c205; | |
| 9380 | peg$currPos++; | |
| 9381 | } else { | |
| 9382 | s1 = peg$FAILED; | |
| 9383 | if (peg$silentFails === 0) { | |
| 9384 | peg$fail(peg$e206); | |
| 9385 | } | |
| 9386 | } | |
| 9387 | if (s1 !== peg$FAILED) { | |
| 9388 | s2 = peg$parse_(); | |
| 9389 | peg$savedPos = s0; | |
| 9390 | s0 = peg$f7(s1, s2); | |
| 9391 | } else { | |
| 9392 | peg$currPos = s0; | |
| 9393 | s0 = peg$FAILED; | |
| 9394 | } | |
| 9395 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9396 | return s0; | |
| 9397 | } | |
| 9398 | function peg$parseQUESTION() { | |
| 9399 | var s0, s1, s2; | |
| 9400 | var key = peg$currPos * 306 + 211; | |
| 9401 | var cached = peg$resultsCache[key]; | |
| 9402 | if (cached) { | |
| 9403 | peg$currPos = cached.nextPos; | |
| 9404 | return cached.result; | |
| 9405 | } | |
| 9406 | s0 = peg$currPos; | |
| 9407 | if (input.charCodeAt(peg$currPos) === 63) { | |
| 9408 | s1 = peg$c206; | |
| 9409 | peg$currPos++; | |
| 9410 | } else { | |
| 9411 | s1 = peg$FAILED; | |
| 9412 | if (peg$silentFails === 0) { | |
| 9413 | peg$fail(peg$e207); | |
| 9414 | } | |
| 9415 | } | |
| 9416 | if (s1 !== peg$FAILED) { | |
| 9417 | s2 = peg$parse_(); | |
| 9418 | peg$savedPos = s0; | |
| 9419 | s0 = peg$f7(s1, s2); | |
| 9420 | } else { | |
| 9421 | peg$currPos = s0; | |
| 9422 | s0 = peg$FAILED; | |
| 9423 | } | |
| 9424 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9425 | return s0; | |
| 9426 | } | |
| 9427 | function peg$parseIDENTIFIER() { | |
| 9428 | var s0, s1, s2, s3, s4, s5, s6; | |
| 9429 | var key = peg$currPos * 306 + 212; | |
| 9430 | var cached = peg$resultsCache[key]; | |
| 9431 | if (cached) { | |
| 9432 | peg$currPos = cached.nextPos; | |
| 9433 | return cached.result; | |
| 9434 | } | |
| 9435 | s0 = peg$currPos; | |
| 9436 | s1 = peg$currPos; | |
| 9437 | peg$silentFails++; | |
| 9438 | s2 = peg$parsekeyword(); | |
| 9439 | peg$silentFails--; | |
| 9440 | if (s2 === peg$FAILED) { | |
| 9441 | s1 = void 0; | |
| 9442 | } else { | |
| 9443 | peg$currPos = s1; | |
| 9444 | s1 = peg$FAILED; | |
| 9445 | } | |
| 9446 | if (s1 !== peg$FAILED) { | |
| 9447 | s2 = peg$currPos; | |
| 9448 | s3 = peg$currPos; | |
| 9449 | if (peg$r0.test(input.charAt(peg$currPos))) { | |
| 9450 | s4 = input.charAt(peg$currPos); | |
| 9451 | peg$currPos++; | |
| 9452 | } else { | |
| 9453 | s4 = peg$FAILED; | |
| 9454 | if (peg$silentFails === 0) { | |
| 9455 | peg$fail(peg$e208); | |
| 9456 | } | |
| 9457 | } | |
| 9458 | if (s4 !== peg$FAILED) { | |
| 9459 | s5 = []; | |
| 9460 | if (peg$r1.test(input.charAt(peg$currPos))) { | |
| 9461 | s6 = input.charAt(peg$currPos); | |
| 9462 | peg$currPos++; | |
| 9463 | } else { | |
| 9464 | s6 = peg$FAILED; | |
| 9465 | if (peg$silentFails === 0) { | |
| 9466 | peg$fail(peg$e209); | |
| 9467 | } | |
| 9468 | } | |
| 9469 | while (s6 !== peg$FAILED) { | |
| 9470 | s5.push(s6); | |
| 9471 | if (peg$r1.test(input.charAt(peg$currPos))) { | |
| 9472 | s6 = input.charAt(peg$currPos); | |
| 9473 | peg$currPos++; | |
| 9474 | } else { | |
| 9475 | s6 = peg$FAILED; | |
| 9476 | if (peg$silentFails === 0) { | |
| 9477 | peg$fail(peg$e209); | |
| 9478 | } | |
| 9479 | } | |
| 9480 | } | |
| 9481 | s4 = [s4, s5]; | |
| 9482 | s3 = s4; | |
| 9483 | } else { | |
| 9484 | peg$currPos = s3; | |
| 9485 | s3 = peg$FAILED; | |
| 9486 | } | |
| 9487 | if (s3 !== peg$FAILED) { | |
| 9488 | s2 = input.substring(s2, peg$currPos); | |
| 9489 | } else { | |
| 9490 | s2 = s3; | |
| 9491 | } | |
| 9492 | if (s2 !== peg$FAILED) { | |
| 9493 | s3 = peg$parse_(); | |
| 9494 | peg$savedPos = s0; | |
| 9495 | s0 = peg$f8(s2, s3); | |
| 9496 | } else { | |
| 9497 | peg$currPos = s0; | |
| 9498 | s0 = peg$FAILED; | |
| 9499 | } | |
| 9500 | } else { | |
| 9501 | peg$currPos = s0; | |
| 9502 | s0 = peg$FAILED; | |
| 9503 | } | |
| 9504 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9505 | return s0; | |
| 9506 | } | |
| 9507 | function peg$parseTYPE_NAME() { | |
| 9508 | var s0, s1, s2, s3, s4, s5, s6; | |
| 9509 | var key = peg$currPos * 306 + 213; | |
| 9510 | var cached = peg$resultsCache[key]; | |
| 9511 | if (cached) { | |
| 9512 | peg$currPos = cached.nextPos; | |
| 9513 | return cached.result; | |
| 9514 | } | |
| 9515 | s0 = peg$currPos; | |
| 9516 | s1 = peg$currPos; | |
| 9517 | peg$silentFails++; | |
| 9518 | s2 = peg$parsekeyword(); | |
| 9519 | peg$silentFails--; | |
| 9520 | if (s2 === peg$FAILED) { | |
| 9521 | s1 = void 0; | |
| 9522 | } else { | |
| 9523 | peg$currPos = s1; | |
| 9524 | s1 = peg$FAILED; | |
| 9525 | } | |
| 9526 | if (s1 !== peg$FAILED) { | |
| 9527 | s2 = peg$currPos; | |
| 9528 | s3 = peg$currPos; | |
| 9529 | if (peg$r0.test(input.charAt(peg$currPos))) { | |
| 9530 | s4 = input.charAt(peg$currPos); | |
| 9531 | peg$currPos++; | |
| 9532 | } else { | |
| 9533 | s4 = peg$FAILED; | |
| 9534 | if (peg$silentFails === 0) { | |
| 9535 | peg$fail(peg$e208); | |
| 9536 | } | |
| 9537 | } | |
| 9538 | if (s4 !== peg$FAILED) { | |
| 9539 | s5 = []; | |
| 9540 | if (peg$r1.test(input.charAt(peg$currPos))) { | |
| 9541 | s6 = input.charAt(peg$currPos); | |
| 9542 | peg$currPos++; | |
| 9543 | } else { | |
| 9544 | s6 = peg$FAILED; | |
| 9545 | if (peg$silentFails === 0) { | |
| 9546 | peg$fail(peg$e209); | |
| 9547 | } | |
| 9548 | } | |
| 9549 | while (s6 !== peg$FAILED) { | |
| 9550 | s5.push(s6); | |
| 9551 | if (peg$r1.test(input.charAt(peg$currPos))) { | |
| 9552 | s6 = input.charAt(peg$currPos); | |
| 9553 | peg$currPos++; | |
| 9554 | } else { | |
| 9555 | s6 = peg$FAILED; | |
| 9556 | if (peg$silentFails === 0) { | |
| 9557 | peg$fail(peg$e209); | |
| 9558 | } | |
| 9559 | } | |
| 9560 | } | |
| 9561 | s4 = [s4, s5]; | |
| 9562 | s3 = s4; | |
| 9563 | } else { | |
| 9564 | peg$currPos = s3; | |
| 9565 | s3 = peg$FAILED; | |
| 9566 | } | |
| 9567 | if (s3 !== peg$FAILED) { | |
| 9568 | s2 = input.substring(s2, peg$currPos); | |
| 9569 | } else { | |
| 9570 | s2 = s3; | |
| 9571 | } | |
| 9572 | if (s2 !== peg$FAILED) { | |
| 9573 | s3 = peg$parse_(); | |
| 9574 | peg$savedPos = s0; | |
| 9575 | s0 = peg$f9(s2, s3); | |
| 9576 | } else { | |
| 9577 | peg$currPos = s0; | |
| 9578 | s0 = peg$FAILED; | |
| 9579 | } | |
| 9580 | } else { | |
| 9581 | peg$currPos = s0; | |
| 9582 | s0 = peg$FAILED; | |
| 9583 | } | |
| 9584 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9585 | return s0; | |
| 9586 | } | |
| 9587 | function peg$parseinteger_constant() { | |
| 9588 | var s0, s1, s2, s3; | |
| 9589 | var key = peg$currPos * 306 + 214; | |
| 9590 | var cached = peg$resultsCache[key]; | |
| 9591 | if (cached) { | |
| 9592 | peg$currPos = cached.nextPos; | |
| 9593 | return cached.result; | |
| 9594 | } | |
| 9595 | s0 = peg$currPos; | |
| 9596 | s1 = peg$currPos; | |
| 9597 | s2 = peg$parsehexadecimal_constant(); | |
| 9598 | if (s2 !== peg$FAILED) { | |
| 9599 | s3 = peg$parseinteger_suffix(); | |
| 9600 | if (s3 === peg$FAILED) { | |
| 9601 | s3 = null; | |
| 9602 | } | |
| 9603 | s2 = [s2, s3]; | |
| 9604 | s1 = s2; | |
| 9605 | } else { | |
| 9606 | peg$currPos = s1; | |
| 9607 | s1 = peg$FAILED; | |
| 9608 | } | |
| 9609 | if (s1 !== peg$FAILED) { | |
| 9610 | s0 = input.substring(s0, peg$currPos); | |
| 9611 | } else { | |
| 9612 | s0 = s1; | |
| 9613 | } | |
| 9614 | if (s0 === peg$FAILED) { | |
| 9615 | s0 = peg$currPos; | |
| 9616 | s1 = peg$currPos; | |
| 9617 | s2 = peg$parsedecimal_constant(); | |
| 9618 | if (s2 !== peg$FAILED) { | |
| 9619 | s3 = peg$parseinteger_suffix(); | |
| 9620 | if (s3 === peg$FAILED) { | |
| 9621 | s3 = null; | |
| 9622 | } | |
| 9623 | s2 = [s2, s3]; | |
| 9624 | s1 = s2; | |
| 9625 | } else { | |
| 9626 | peg$currPos = s1; | |
| 9627 | s1 = peg$FAILED; | |
| 9628 | } | |
| 9629 | if (s1 !== peg$FAILED) { | |
| 9630 | s0 = input.substring(s0, peg$currPos); | |
| 9631 | } else { | |
| 9632 | s0 = s1; | |
| 9633 | } | |
| 9634 | if (s0 === peg$FAILED) { | |
| 9635 | s0 = peg$currPos; | |
| 9636 | s1 = peg$currPos; | |
| 9637 | s2 = peg$parseoctal_constant(); | |
| 9638 | if (s2 !== peg$FAILED) { | |
| 9639 | s3 = peg$parseinteger_suffix(); | |
| 9640 | if (s3 === peg$FAILED) { | |
| 9641 | s3 = null; | |
| 9642 | } | |
| 9643 | s2 = [s2, s3]; | |
| 9644 | s1 = s2; | |
| 9645 | } else { | |
| 9646 | peg$currPos = s1; | |
| 9647 | s1 = peg$FAILED; | |
| 9648 | } | |
| 9649 | if (s1 !== peg$FAILED) { | |
| 9650 | s0 = input.substring(s0, peg$currPos); | |
| 9651 | } else { | |
| 9652 | s0 = s1; | |
| 9653 | } | |
| 9654 | } | |
| 9655 | } | |
| 9656 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9657 | return s0; | |
| 9658 | } | |
| 9659 | function peg$parseinteger_suffix() { | |
| 9660 | var s0; | |
| 9661 | var key = peg$currPos * 306 + 215; | |
| 9662 | var cached = peg$resultsCache[key]; | |
| 9663 | if (cached) { | |
| 9664 | peg$currPos = cached.nextPos; | |
| 9665 | return cached.result; | |
| 9666 | } | |
| 9667 | if (peg$r2.test(input.charAt(peg$currPos))) { | |
| 9668 | s0 = input.charAt(peg$currPos); | |
| 9669 | peg$currPos++; | |
| 9670 | } else { | |
| 9671 | s0 = peg$FAILED; | |
| 9672 | if (peg$silentFails === 0) { | |
| 9673 | peg$fail(peg$e210); | |
| 9674 | } | |
| 9675 | } | |
| 9676 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9677 | return s0; | |
| 9678 | } | |
| 9679 | function peg$parsedecimal_constant() { | |
| 9680 | var s0, s1, s2, s3, s4; | |
| 9681 | var key = peg$currPos * 306 + 216; | |
| 9682 | var cached = peg$resultsCache[key]; | |
| 9683 | if (cached) { | |
| 9684 | peg$currPos = cached.nextPos; | |
| 9685 | return cached.result; | |
| 9686 | } | |
| 9687 | s0 = peg$currPos; | |
| 9688 | s1 = peg$currPos; | |
| 9689 | if (peg$r3.test(input.charAt(peg$currPos))) { | |
| 9690 | s2 = input.charAt(peg$currPos); | |
| 9691 | peg$currPos++; | |
| 9692 | } else { | |
| 9693 | s2 = peg$FAILED; | |
| 9694 | if (peg$silentFails === 0) { | |
| 9695 | peg$fail(peg$e211); | |
| 9696 | } | |
| 9697 | } | |
| 9698 | if (s2 !== peg$FAILED) { | |
| 9699 | s3 = []; | |
| 9700 | s4 = peg$parsedigit(); | |
| 9701 | while (s4 !== peg$FAILED) { | |
| 9702 | s3.push(s4); | |
| 9703 | s4 = peg$parsedigit(); | |
| 9704 | } | |
| 9705 | s2 = [s2, s3]; | |
| 9706 | s1 = s2; | |
| 9707 | } else { | |
| 9708 | peg$currPos = s1; | |
| 9709 | s1 = peg$FAILED; | |
| 9710 | } | |
| 9711 | if (s1 !== peg$FAILED) { | |
| 9712 | s0 = input.substring(s0, peg$currPos); | |
| 9713 | } else { | |
| 9714 | s0 = s1; | |
| 9715 | } | |
| 9716 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9717 | return s0; | |
| 9718 | } | |
| 9719 | function peg$parseoctal_constant() { | |
| 9720 | var s0, s1, s2, s3; | |
| 9721 | var key = peg$currPos * 306 + 217; | |
| 9722 | var cached = peg$resultsCache[key]; | |
| 9723 | if (cached) { | |
| 9724 | peg$currPos = cached.nextPos; | |
| 9725 | return cached.result; | |
| 9726 | } | |
| 9727 | s0 = peg$currPos; | |
| 9728 | if (input.charCodeAt(peg$currPos) === 48) { | |
| 9729 | s1 = peg$c207; | |
| 9730 | peg$currPos++; | |
| 9731 | } else { | |
| 9732 | s1 = peg$FAILED; | |
| 9733 | if (peg$silentFails === 0) { | |
| 9734 | peg$fail(peg$e212); | |
| 9735 | } | |
| 9736 | } | |
| 9737 | if (s1 !== peg$FAILED) { | |
| 9738 | s2 = []; | |
| 9739 | if (peg$r4.test(input.charAt(peg$currPos))) { | |
| 9740 | s3 = input.charAt(peg$currPos); | |
| 9741 | peg$currPos++; | |
| 9742 | } else { | |
| 9743 | s3 = peg$FAILED; | |
| 9744 | if (peg$silentFails === 0) { | |
| 9745 | peg$fail(peg$e213); | |
| 9746 | } | |
| 9747 | } | |
| 9748 | while (s3 !== peg$FAILED) { | |
| 9749 | s2.push(s3); | |
| 9750 | if (peg$r4.test(input.charAt(peg$currPos))) { | |
| 9751 | s3 = input.charAt(peg$currPos); | |
| 9752 | peg$currPos++; | |
| 9753 | } else { | |
| 9754 | s3 = peg$FAILED; | |
| 9755 | if (peg$silentFails === 0) { | |
| 9756 | peg$fail(peg$e213); | |
| 9757 | } | |
| 9758 | } | |
| 9759 | } | |
| 9760 | s1 = [s1, s2]; | |
| 9761 | s0 = s1; | |
| 9762 | } else { | |
| 9763 | peg$currPos = s0; | |
| 9764 | s0 = peg$FAILED; | |
| 9765 | } | |
| 9766 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9767 | return s0; | |
| 9768 | } | |
| 9769 | function peg$parsehexadecimal_constant() { | |
| 9770 | var s0, s1, s2, s3, s4; | |
| 9771 | var key = peg$currPos * 306 + 218; | |
| 9772 | var cached = peg$resultsCache[key]; | |
| 9773 | if (cached) { | |
| 9774 | peg$currPos = cached.nextPos; | |
| 9775 | return cached.result; | |
| 9776 | } | |
| 9777 | s0 = peg$currPos; | |
| 9778 | if (input.charCodeAt(peg$currPos) === 48) { | |
| 9779 | s1 = peg$c207; | |
| 9780 | peg$currPos++; | |
| 9781 | } else { | |
| 9782 | s1 = peg$FAILED; | |
| 9783 | if (peg$silentFails === 0) { | |
| 9784 | peg$fail(peg$e212); | |
| 9785 | } | |
| 9786 | } | |
| 9787 | if (s1 !== peg$FAILED) { | |
| 9788 | if (peg$r5.test(input.charAt(peg$currPos))) { | |
| 9789 | s2 = input.charAt(peg$currPos); | |
| 9790 | peg$currPos++; | |
| 9791 | } else { | |
| 9792 | s2 = peg$FAILED; | |
| 9793 | if (peg$silentFails === 0) { | |
| 9794 | peg$fail(peg$e214); | |
| 9795 | } | |
| 9796 | } | |
| 9797 | if (s2 !== peg$FAILED) { | |
| 9798 | s3 = []; | |
| 9799 | if (peg$r6.test(input.charAt(peg$currPos))) { | |
| 9800 | s4 = input.charAt(peg$currPos); | |
| 9801 | peg$currPos++; | |
| 9802 | } else { | |
| 9803 | s4 = peg$FAILED; | |
| 9804 | if (peg$silentFails === 0) { | |
| 9805 | peg$fail(peg$e215); | |
| 9806 | } | |
| 9807 | } | |
| 9808 | while (s4 !== peg$FAILED) { | |
| 9809 | s3.push(s4); | |
| 9810 | if (peg$r6.test(input.charAt(peg$currPos))) { | |
| 9811 | s4 = input.charAt(peg$currPos); | |
| 9812 | peg$currPos++; | |
| 9813 | } else { | |
| 9814 | s4 = peg$FAILED; | |
| 9815 | if (peg$silentFails === 0) { | |
| 9816 | peg$fail(peg$e215); | |
| 9817 | } | |
| 9818 | } | |
| 9819 | } | |
| 9820 | s1 = [s1, s2, s3]; | |
| 9821 | s0 = s1; | |
| 9822 | } else { | |
| 9823 | peg$currPos = s0; | |
| 9824 | s0 = peg$FAILED; | |
| 9825 | } | |
| 9826 | } else { | |
| 9827 | peg$currPos = s0; | |
| 9828 | s0 = peg$FAILED; | |
| 9829 | } | |
| 9830 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9831 | return s0; | |
| 9832 | } | |
| 9833 | function peg$parsedigit() { | |
| 9834 | var s0; | |
| 9835 | var key = peg$currPos * 306 + 219; | |
| 9836 | var cached = peg$resultsCache[key]; | |
| 9837 | if (cached) { | |
| 9838 | peg$currPos = cached.nextPos; | |
| 9839 | return cached.result; | |
| 9840 | } | |
| 9841 | if (peg$r7.test(input.charAt(peg$currPos))) { | |
| 9842 | s0 = input.charAt(peg$currPos); | |
| 9843 | peg$currPos++; | |
| 9844 | } else { | |
| 9845 | s0 = peg$FAILED; | |
| 9846 | if (peg$silentFails === 0) { | |
| 9847 | peg$fail(peg$e216); | |
| 9848 | } | |
| 9849 | } | |
| 9850 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9851 | return s0; | |
| 9852 | } | |
| 9853 | function peg$parsefloating_constant() { | |
| 9854 | var s0, s1, s2, s3, s4; | |
| 9855 | var key = peg$currPos * 306 + 220; | |
| 9856 | var cached = peg$resultsCache[key]; | |
| 9857 | if (cached) { | |
| 9858 | peg$currPos = cached.nextPos; | |
| 9859 | return cached.result; | |
| 9860 | } | |
| 9861 | s0 = peg$currPos; | |
| 9862 | s1 = peg$currPos; | |
| 9863 | s2 = peg$parsefractional_constant(); | |
| 9864 | if (s2 !== peg$FAILED) { | |
| 9865 | s3 = peg$parseexponent_part(); | |
| 9866 | if (s3 === peg$FAILED) { | |
| 9867 | s3 = null; | |
| 9868 | } | |
| 9869 | s4 = peg$parsefloating_suffix(); | |
| 9870 | if (s4 === peg$FAILED) { | |
| 9871 | s4 = null; | |
| 9872 | } | |
| 9873 | s2 = [s2, s3, s4]; | |
| 9874 | s1 = s2; | |
| 9875 | } else { | |
| 9876 | peg$currPos = s1; | |
| 9877 | s1 = peg$FAILED; | |
| 9878 | } | |
| 9879 | if (s1 !== peg$FAILED) { | |
| 9880 | s0 = input.substring(s0, peg$currPos); | |
| 9881 | } else { | |
| 9882 | s0 = s1; | |
| 9883 | } | |
| 9884 | if (s0 === peg$FAILED) { | |
| 9885 | s0 = peg$currPos; | |
| 9886 | s1 = peg$currPos; | |
| 9887 | s2 = peg$parsedigit_sequence(); | |
| 9888 | if (s2 !== peg$FAILED) { | |
| 9889 | s3 = peg$parseexponent_part(); | |
| 9890 | if (s3 !== peg$FAILED) { | |
| 9891 | s4 = peg$parsefloating_suffix(); | |
| 9892 | if (s4 === peg$FAILED) { | |
| 9893 | s4 = null; | |
| 9894 | } | |
| 9895 | s2 = [s2, s3, s4]; | |
| 9896 | s1 = s2; | |
| 9897 | } else { | |
| 9898 | peg$currPos = s1; | |
| 9899 | s1 = peg$FAILED; | |
| 9900 | } | |
| 9901 | } else { | |
| 9902 | peg$currPos = s1; | |
| 9903 | s1 = peg$FAILED; | |
| 9904 | } | |
| 9905 | if (s1 !== peg$FAILED) { | |
| 9906 | s0 = input.substring(s0, peg$currPos); | |
| 9907 | } else { | |
| 9908 | s0 = s1; | |
| 9909 | } | |
| 9910 | } | |
| 9911 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9912 | return s0; | |
| 9913 | } | |
| 9914 | function peg$parsefractional_constant() { | |
| 9915 | var s0, s1, s2, s3, s4; | |
| 9916 | var key = peg$currPos * 306 + 221; | |
| 9917 | var cached = peg$resultsCache[key]; | |
| 9918 | if (cached) { | |
| 9919 | peg$currPos = cached.nextPos; | |
| 9920 | return cached.result; | |
| 9921 | } | |
| 9922 | s0 = peg$currPos; | |
| 9923 | s1 = peg$currPos; | |
| 9924 | s2 = peg$parsedigit_sequence(); | |
| 9925 | if (s2 === peg$FAILED) { | |
| 9926 | s2 = null; | |
| 9927 | } | |
| 9928 | if (input.charCodeAt(peg$currPos) === 46) { | |
| 9929 | s3 = peg$c189; | |
| 9930 | peg$currPos++; | |
| 9931 | } else { | |
| 9932 | s3 = peg$FAILED; | |
| 9933 | if (peg$silentFails === 0) { | |
| 9934 | peg$fail(peg$e190); | |
| 9935 | } | |
| 9936 | } | |
| 9937 | if (s3 !== peg$FAILED) { | |
| 9938 | s4 = peg$parsedigit_sequence(); | |
| 9939 | if (s4 === peg$FAILED) { | |
| 9940 | s4 = null; | |
| 9941 | } | |
| 9942 | s2 = [s2, s3, s4]; | |
| 9943 | s1 = s2; | |
| 9944 | } else { | |
| 9945 | peg$currPos = s1; | |
| 9946 | s1 = peg$FAILED; | |
| 9947 | } | |
| 9948 | if (s1 !== peg$FAILED) { | |
| 9949 | s0 = input.substring(s0, peg$currPos); | |
| 9950 | } else { | |
| 9951 | s0 = s1; | |
| 9952 | } | |
| 9953 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 9954 | return s0; | |
| 9955 | } | |
| 9956 | function peg$parseexponent_part() { | |
| 9957 | var s0, s1, s2, s3, s4; | |
| 9958 | var key = peg$currPos * 306 + 222; | |
| 9959 | var cached = peg$resultsCache[key]; | |
| 9960 | if (cached) { | |
| 9961 | peg$currPos = cached.nextPos; | |
| 9962 | return cached.result; | |
| 9963 | } | |
| 9964 | peg$silentFails++; | |
| 9965 | s0 = peg$currPos; | |
| 9966 | s1 = peg$currPos; | |
| 9967 | if (peg$r8.test(input.charAt(peg$currPos))) { | |
| 9968 | s2 = input.charAt(peg$currPos); | |
| 9969 | peg$currPos++; | |
| 9970 | } else { | |
| 9971 | s2 = peg$FAILED; | |
| 9972 | if (peg$silentFails === 0) { | |
| 9973 | peg$fail(peg$e218); | |
| 9974 | } | |
| 9975 | } | |
| 9976 | if (s2 !== peg$FAILED) { | |
| 9977 | if (peg$r9.test(input.charAt(peg$currPos))) { | |
| 9978 | s3 = input.charAt(peg$currPos); | |
| 9979 | peg$currPos++; | |
| 9980 | } else { | |
| 9981 | s3 = peg$FAILED; | |
| 9982 | if (peg$silentFails === 0) { | |
| 9983 | peg$fail(peg$e219); | |
| 9984 | } | |
| 9985 | } | |
| 9986 | if (s3 === peg$FAILED) { | |
| 9987 | s3 = null; | |
| 9988 | } | |
| 9989 | s4 = peg$parsedigit_sequence(); | |
| 9990 | if (s4 !== peg$FAILED) { | |
| 9991 | s2 = [s2, s3, s4]; | |
| 9992 | s1 = s2; | |
| 9993 | } else { | |
| 9994 | peg$currPos = s1; | |
| 9995 | s1 = peg$FAILED; | |
| 9996 | } | |
| 9997 | } else { | |
| 9998 | peg$currPos = s1; | |
| 9999 | s1 = peg$FAILED; | |
| 10000 | } | |
| 10001 | if (s1 !== peg$FAILED) { | |
| 10002 | s0 = input.substring(s0, peg$currPos); | |
| 10003 | } else { | |
| 10004 | s0 = s1; | |
| 10005 | } | |
| 10006 | peg$silentFails--; | |
| 10007 | if (s0 === peg$FAILED) { | |
| 10008 | s1 = peg$FAILED; | |
| 10009 | if (peg$silentFails === 0) { | |
| 10010 | peg$fail(peg$e217); | |
| 10011 | } | |
| 10012 | } | |
| 10013 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10014 | return s0; | |
| 10015 | } | |
| 10016 | function peg$parsedigit_sequence() { | |
| 10017 | var s0, s1, s2; | |
| 10018 | var key = peg$currPos * 306 + 223; | |
| 10019 | var cached = peg$resultsCache[key]; | |
| 10020 | if (cached) { | |
| 10021 | peg$currPos = cached.nextPos; | |
| 10022 | return cached.result; | |
| 10023 | } | |
| 10024 | s0 = peg$currPos; | |
| 10025 | s1 = []; | |
| 10026 | s2 = peg$parsedigit(); | |
| 10027 | if (s2 !== peg$FAILED) { | |
| 10028 | while (s2 !== peg$FAILED) { | |
| 10029 | s1.push(s2); | |
| 10030 | s2 = peg$parsedigit(); | |
| 10031 | } | |
| 10032 | } else { | |
| 10033 | s1 = peg$FAILED; | |
| 10034 | } | |
| 10035 | if (s1 !== peg$FAILED) { | |
| 10036 | s0 = input.substring(s0, peg$currPos); | |
| 10037 | } else { | |
| 10038 | s0 = s1; | |
| 10039 | } | |
| 10040 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10041 | return s0; | |
| 10042 | } | |
| 10043 | function peg$parsefloating_suffix() { | |
| 10044 | var s0; | |
| 10045 | var key = peg$currPos * 306 + 224; | |
| 10046 | var cached = peg$resultsCache[key]; | |
| 10047 | if (cached) { | |
| 10048 | peg$currPos = cached.nextPos; | |
| 10049 | return cached.result; | |
| 10050 | } | |
| 10051 | if (peg$r10.test(input.charAt(peg$currPos))) { | |
| 10052 | s0 = input.charAt(peg$currPos); | |
| 10053 | peg$currPos++; | |
| 10054 | } else { | |
| 10055 | s0 = peg$FAILED; | |
| 10056 | if (peg$silentFails === 0) { | |
| 10057 | peg$fail(peg$e220); | |
| 10058 | } | |
| 10059 | } | |
| 10060 | if (s0 === peg$FAILED) { | |
| 10061 | if (input.substr(peg$currPos, 2) === peg$c208) { | |
| 10062 | s0 = peg$c208; | |
| 10063 | peg$currPos += 2; | |
| 10064 | } else { | |
| 10065 | s0 = peg$FAILED; | |
| 10066 | if (peg$silentFails === 0) { | |
| 10067 | peg$fail(peg$e221); | |
| 10068 | } | |
| 10069 | } | |
| 10070 | if (s0 === peg$FAILED) { | |
| 10071 | if (input.substr(peg$currPos, 2) === peg$c209) { | |
| 10072 | s0 = peg$c209; | |
| 10073 | peg$currPos += 2; | |
| 10074 | } else { | |
| 10075 | s0 = peg$FAILED; | |
| 10076 | if (peg$silentFails === 0) { | |
| 10077 | peg$fail(peg$e222); | |
| 10078 | } | |
| 10079 | } | |
| 10080 | } | |
| 10081 | } | |
| 10082 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10083 | return s0; | |
| 10084 | } | |
| 10085 | function peg$parseprimary_expression() { | |
| 10086 | var s0, s1, s2, s3; | |
| 10087 | var key = peg$currPos * 306 + 225; | |
| 10088 | var cached = peg$resultsCache[key]; | |
| 10089 | if (cached) { | |
| 10090 | peg$currPos = cached.nextPos; | |
| 10091 | return cached.result; | |
| 10092 | } | |
| 10093 | peg$silentFails++; | |
| 10094 | s0 = peg$parseFLOATCONSTANT(); | |
| 10095 | if (s0 === peg$FAILED) { | |
| 10096 | s0 = peg$parseINTCONSTANT(); | |
| 10097 | if (s0 === peg$FAILED) { | |
| 10098 | s0 = peg$parseUINTCONSTANT(); | |
| 10099 | if (s0 === peg$FAILED) { | |
| 10100 | s0 = peg$parseBOOLCONSTANT(); | |
| 10101 | if (s0 === peg$FAILED) { | |
| 10102 | s0 = peg$parseDOUBLECONSTANT(); | |
| 10103 | if (s0 === peg$FAILED) { | |
| 10104 | s0 = peg$currPos; | |
| 10105 | s1 = peg$parseLEFT_PAREN(); | |
| 10106 | if (s1 !== peg$FAILED) { | |
| 10107 | s2 = peg$parseexpression(); | |
| 10108 | if (s2 !== peg$FAILED) { | |
| 10109 | s3 = peg$parseRIGHT_PAREN(); | |
| 10110 | if (s3 !== peg$FAILED) { | |
| 10111 | peg$savedPos = s0; | |
| 10112 | s0 = peg$f10(s1, s2, s3); | |
| 10113 | } else { | |
| 10114 | peg$currPos = s0; | |
| 10115 | s0 = peg$FAILED; | |
| 10116 | } | |
| 10117 | } else { | |
| 10118 | peg$currPos = s0; | |
| 10119 | s0 = peg$FAILED; | |
| 10120 | } | |
| 10121 | } else { | |
| 10122 | peg$currPos = s0; | |
| 10123 | s0 = peg$FAILED; | |
| 10124 | } | |
| 10125 | if (s0 === peg$FAILED) { | |
| 10126 | s0 = peg$currPos; | |
| 10127 | s1 = peg$parseIDENTIFIER(); | |
| 10128 | if (s1 !== peg$FAILED) { | |
| 10129 | peg$savedPos = s0; | |
| 10130 | s1 = peg$f11(s1); | |
| 10131 | } | |
| 10132 | s0 = s1; | |
| 10133 | } | |
| 10134 | } | |
| 10135 | } | |
| 10136 | } | |
| 10137 | } | |
| 10138 | } | |
| 10139 | peg$silentFails--; | |
| 10140 | if (s0 === peg$FAILED) { | |
| 10141 | s1 = peg$FAILED; | |
| 10142 | if (peg$silentFails === 0) { | |
| 10143 | peg$fail(peg$e223); | |
| 10144 | } | |
| 10145 | } | |
| 10146 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10147 | return s0; | |
| 10148 | } | |
| 10149 | function peg$parsepostfix_expression() { | |
| 10150 | var s0, s1, s2, s3, s4; | |
| 10151 | var key = peg$currPos * 306 + 226; | |
| 10152 | var cached = peg$resultsCache[key]; | |
| 10153 | if (cached) { | |
| 10154 | peg$currPos = cached.nextPos; | |
| 10155 | return cached.result; | |
| 10156 | } | |
| 10157 | s0 = peg$currPos; | |
| 10158 | s1 = peg$currPos; | |
| 10159 | s2 = peg$parsefunction_call(); | |
| 10160 | if (s2 !== peg$FAILED) { | |
| 10161 | s3 = []; | |
| 10162 | s4 = peg$parsepostfix_expression_suffix(); | |
| 10163 | while (s4 !== peg$FAILED) { | |
| 10164 | s3.push(s4); | |
| 10165 | s4 = peg$parsepostfix_expression_suffix(); | |
| 10166 | } | |
| 10167 | s2 = [s2, s3]; | |
| 10168 | s1 = s2; | |
| 10169 | } else { | |
| 10170 | peg$currPos = s1; | |
| 10171 | s1 = peg$FAILED; | |
| 10172 | } | |
| 10173 | if (s1 === peg$FAILED) { | |
| 10174 | s1 = peg$currPos; | |
| 10175 | s2 = peg$parseprimary_expression(); | |
| 10176 | if (s2 !== peg$FAILED) { | |
| 10177 | s3 = []; | |
| 10178 | s4 = peg$parsepostfix_expression_suffix(); | |
| 10179 | while (s4 !== peg$FAILED) { | |
| 10180 | s3.push(s4); | |
| 10181 | s4 = peg$parsepostfix_expression_suffix(); | |
| 10182 | } | |
| 10183 | s2 = [s2, s3]; | |
| 10184 | s1 = s2; | |
| 10185 | } else { | |
| 10186 | peg$currPos = s1; | |
| 10187 | s1 = peg$FAILED; | |
| 10188 | } | |
| 10189 | } | |
| 10190 | if (s1 !== peg$FAILED) { | |
| 10191 | peg$savedPos = s0; | |
| 10192 | s1 = peg$f12(s1); | |
| 10193 | } | |
| 10194 | s0 = s1; | |
| 10195 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10196 | return s0; | |
| 10197 | } | |
| 10198 | function peg$parsepostfix_expression_suffix() { | |
| 10199 | var s0; | |
| 10200 | var key = peg$currPos * 306 + 227; | |
| 10201 | var cached = peg$resultsCache[key]; | |
| 10202 | if (cached) { | |
| 10203 | peg$currPos = cached.nextPos; | |
| 10204 | return cached.result; | |
| 10205 | } | |
| 10206 | s0 = peg$parseinteger_index(); | |
| 10207 | if (s0 === peg$FAILED) { | |
| 10208 | s0 = peg$parsefield_selection(); | |
| 10209 | if (s0 === peg$FAILED) { | |
| 10210 | s0 = peg$parseINC_OP(); | |
| 10211 | if (s0 === peg$FAILED) { | |
| 10212 | s0 = peg$parseDEC_OP(); | |
| 10213 | } | |
| 10214 | } | |
| 10215 | } | |
| 10216 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10217 | return s0; | |
| 10218 | } | |
| 10219 | function peg$parseinteger_index() { | |
| 10220 | var s0, s1, s2, s3; | |
| 10221 | var key = peg$currPos * 306 + 228; | |
| 10222 | var cached = peg$resultsCache[key]; | |
| 10223 | if (cached) { | |
| 10224 | peg$currPos = cached.nextPos; | |
| 10225 | return cached.result; | |
| 10226 | } | |
| 10227 | s0 = peg$currPos; | |
| 10228 | s1 = peg$parseLEFT_BRACKET(); | |
| 10229 | if (s1 !== peg$FAILED) { | |
| 10230 | s2 = peg$parseexpression(); | |
| 10231 | if (s2 !== peg$FAILED) { | |
| 10232 | s3 = peg$parseRIGHT_BRACKET(); | |
| 10233 | if (s3 !== peg$FAILED) { | |
| 10234 | peg$savedPos = s0; | |
| 10235 | s0 = peg$f13(s1, s2, s3); | |
| 10236 | } else { | |
| 10237 | peg$currPos = s0; | |
| 10238 | s0 = peg$FAILED; | |
| 10239 | } | |
| 10240 | } else { | |
| 10241 | peg$currPos = s0; | |
| 10242 | s0 = peg$FAILED; | |
| 10243 | } | |
| 10244 | } else { | |
| 10245 | peg$currPos = s0; | |
| 10246 | s0 = peg$FAILED; | |
| 10247 | } | |
| 10248 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10249 | return s0; | |
| 10250 | } | |
| 10251 | function peg$parsefield_selection() { | |
| 10252 | var s0, s1, s2; | |
| 10253 | var key = peg$currPos * 306 + 229; | |
| 10254 | var cached = peg$resultsCache[key]; | |
| 10255 | if (cached) { | |
| 10256 | peg$currPos = cached.nextPos; | |
| 10257 | return cached.result; | |
| 10258 | } | |
| 10259 | s0 = peg$currPos; | |
| 10260 | s1 = peg$parseDOT(); | |
| 10261 | if (s1 !== peg$FAILED) { | |
| 10262 | s2 = peg$parseIDENTIFIER(); | |
| 10263 | if (s2 !== peg$FAILED) { | |
| 10264 | peg$savedPos = s0; | |
| 10265 | s0 = peg$f14(s1, s2); | |
| 10266 | } else { | |
| 10267 | peg$currPos = s0; | |
| 10268 | s0 = peg$FAILED; | |
| 10269 | } | |
| 10270 | } else { | |
| 10271 | peg$currPos = s0; | |
| 10272 | s0 = peg$FAILED; | |
| 10273 | } | |
| 10274 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10275 | return s0; | |
| 10276 | } | |
| 10277 | function peg$parsefunction_call() { | |
| 10278 | var s0, s1, s2, s3; | |
| 10279 | var key = peg$currPos * 306 + 230; | |
| 10280 | var cached = peg$resultsCache[key]; | |
| 10281 | if (cached) { | |
| 10282 | peg$currPos = cached.nextPos; | |
| 10283 | return cached.result; | |
| 10284 | } | |
| 10285 | s0 = peg$currPos; | |
| 10286 | s1 = peg$parsefunction_identifier(); | |
| 10287 | if (s1 !== peg$FAILED) { | |
| 10288 | s2 = peg$parsefunction_arguments(); | |
| 10289 | if (s2 === peg$FAILED) { | |
| 10290 | s2 = null; | |
| 10291 | } | |
| 10292 | s3 = peg$parseRIGHT_PAREN(); | |
| 10293 | if (s3 !== peg$FAILED) { | |
| 10294 | peg$savedPos = s0; | |
| 10295 | s0 = peg$f15(s1, s2, s3); | |
| 10296 | } else { | |
| 10297 | peg$currPos = s0; | |
| 10298 | s0 = peg$FAILED; | |
| 10299 | } | |
| 10300 | } else { | |
| 10301 | peg$currPos = s0; | |
| 10302 | s0 = peg$FAILED; | |
| 10303 | } | |
| 10304 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10305 | return s0; | |
| 10306 | } | |
| 10307 | function peg$parsefunction_arguments() { | |
| 10308 | var s0, s1, s2, s3, s4, s5; | |
| 10309 | var key = peg$currPos * 306 + 231; | |
| 10310 | var cached = peg$resultsCache[key]; | |
| 10311 | if (cached) { | |
| 10312 | peg$currPos = cached.nextPos; | |
| 10313 | return cached.result; | |
| 10314 | } | |
| 10315 | s0 = peg$currPos; | |
| 10316 | s1 = peg$parseVOID(); | |
| 10317 | if (s1 !== peg$FAILED) { | |
| 10318 | peg$savedPos = s0; | |
| 10319 | s1 = peg$f16(s1); | |
| 10320 | } | |
| 10321 | s0 = s1; | |
| 10322 | if (s0 === peg$FAILED) { | |
| 10323 | s0 = peg$currPos; | |
| 10324 | s1 = peg$parseassignment_expression(); | |
| 10325 | if (s1 !== peg$FAILED) { | |
| 10326 | s2 = []; | |
| 10327 | s3 = peg$currPos; | |
| 10328 | s4 = peg$parseCOMMA(); | |
| 10329 | if (s4 !== peg$FAILED) { | |
| 10330 | s5 = peg$parseassignment_expression(); | |
| 10331 | if (s5 !== peg$FAILED) { | |
| 10332 | s4 = [s4, s5]; | |
| 10333 | s3 = s4; | |
| 10334 | } else { | |
| 10335 | peg$currPos = s3; | |
| 10336 | s3 = peg$FAILED; | |
| 10337 | } | |
| 10338 | } else { | |
| 10339 | peg$currPos = s3; | |
| 10340 | s3 = peg$FAILED; | |
| 10341 | } | |
| 10342 | while (s3 !== peg$FAILED) { | |
| 10343 | s2.push(s3); | |
| 10344 | s3 = peg$currPos; | |
| 10345 | s4 = peg$parseCOMMA(); | |
| 10346 | if (s4 !== peg$FAILED) { | |
| 10347 | s5 = peg$parseassignment_expression(); | |
| 10348 | if (s5 !== peg$FAILED) { | |
| 10349 | s4 = [s4, s5]; | |
| 10350 | s3 = s4; | |
| 10351 | } else { | |
| 10352 | peg$currPos = s3; | |
| 10353 | s3 = peg$FAILED; | |
| 10354 | } | |
| 10355 | } else { | |
| 10356 | peg$currPos = s3; | |
| 10357 | s3 = peg$FAILED; | |
| 10358 | } | |
| 10359 | } | |
| 10360 | peg$savedPos = s0; | |
| 10361 | s0 = peg$f17(s1, s2); | |
| 10362 | } else { | |
| 10363 | peg$currPos = s0; | |
| 10364 | s0 = peg$FAILED; | |
| 10365 | } | |
| 10366 | } | |
| 10367 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10368 | return s0; | |
| 10369 | } | |
| 10370 | function peg$parsefunction_identifier() { | |
| 10371 | var s0, s1, s2, s3, s4; | |
| 10372 | var key = peg$currPos * 306 + 232; | |
| 10373 | var cached = peg$resultsCache[key]; | |
| 10374 | if (cached) { | |
| 10375 | peg$currPos = cached.nextPos; | |
| 10376 | return cached.result; | |
| 10377 | } | |
| 10378 | s0 = peg$currPos; | |
| 10379 | s1 = peg$currPos; | |
| 10380 | s2 = peg$parsechained_function_call(); | |
| 10381 | if (s2 !== peg$FAILED) { | |
| 10382 | s3 = peg$parsefunction_suffix(); | |
| 10383 | if (s3 !== peg$FAILED) { | |
| 10384 | s4 = peg$parseLEFT_PAREN(); | |
| 10385 | if (s4 !== peg$FAILED) { | |
| 10386 | peg$savedPos = s1; | |
| 10387 | s1 = peg$f18(s2, s3, s4); | |
| 10388 | } else { | |
| 10389 | peg$currPos = s1; | |
| 10390 | s1 = peg$FAILED; | |
| 10391 | } | |
| 10392 | } else { | |
| 10393 | peg$currPos = s1; | |
| 10394 | s1 = peg$FAILED; | |
| 10395 | } | |
| 10396 | } else { | |
| 10397 | peg$currPos = s1; | |
| 10398 | s1 = peg$FAILED; | |
| 10399 | } | |
| 10400 | if (s1 === peg$FAILED) { | |
| 10401 | s1 = peg$currPos; | |
| 10402 | s2 = peg$parsetype_specifier(); | |
| 10403 | if (s2 !== peg$FAILED) { | |
| 10404 | s3 = peg$parsefunction_suffix(); | |
| 10405 | if (s3 === peg$FAILED) { | |
| 10406 | s3 = null; | |
| 10407 | } | |
| 10408 | s4 = peg$parseLEFT_PAREN(); | |
| 10409 | if (s4 !== peg$FAILED) { | |
| 10410 | peg$savedPos = s1; | |
| 10411 | s1 = peg$f18(s2, s3, s4); | |
| 10412 | } else { | |
| 10413 | peg$currPos = s1; | |
| 10414 | s1 = peg$FAILED; | |
| 10415 | } | |
| 10416 | } else { | |
| 10417 | peg$currPos = s1; | |
| 10418 | s1 = peg$FAILED; | |
| 10419 | } | |
| 10420 | } | |
| 10421 | if (s1 !== peg$FAILED) { | |
| 10422 | peg$savedPos = s0; | |
| 10423 | s1 = peg$f19(s1); | |
| 10424 | } | |
| 10425 | s0 = s1; | |
| 10426 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10427 | return s0; | |
| 10428 | } | |
| 10429 | function peg$parsefunction_suffix() { | |
| 10430 | var s0; | |
| 10431 | var key = peg$currPos * 306 + 233; | |
| 10432 | var cached = peg$resultsCache[key]; | |
| 10433 | if (cached) { | |
| 10434 | peg$currPos = cached.nextPos; | |
| 10435 | return cached.result; | |
| 10436 | } | |
| 10437 | s0 = peg$parseinteger_index(); | |
| 10438 | if (s0 === peg$FAILED) { | |
| 10439 | s0 = peg$parsefield_selection(); | |
| 10440 | } | |
| 10441 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10442 | return s0; | |
| 10443 | } | |
| 10444 | function peg$parsechained_function_call() { | |
| 10445 | var s0, s1, s2, s3, s4; | |
| 10446 | var key = peg$currPos * 306 + 234; | |
| 10447 | var cached = peg$resultsCache[key]; | |
| 10448 | if (cached) { | |
| 10449 | peg$currPos = cached.nextPos; | |
| 10450 | return cached.result; | |
| 10451 | } | |
| 10452 | s0 = peg$currPos; | |
| 10453 | s1 = peg$parsetype_specifier(); | |
| 10454 | if (s1 !== peg$FAILED) { | |
| 10455 | s2 = peg$parseLEFT_PAREN(); | |
| 10456 | if (s2 !== peg$FAILED) { | |
| 10457 | s3 = peg$parsefunction_arguments(); | |
| 10458 | if (s3 === peg$FAILED) { | |
| 10459 | s3 = null; | |
| 10460 | } | |
| 10461 | s4 = peg$parseRIGHT_PAREN(); | |
| 10462 | if (s4 !== peg$FAILED) { | |
| 10463 | peg$savedPos = s0; | |
| 10464 | s0 = peg$f20(s1, s2, s3, s4); | |
| 10465 | } else { | |
| 10466 | peg$currPos = s0; | |
| 10467 | s0 = peg$FAILED; | |
| 10468 | } | |
| 10469 | } else { | |
| 10470 | peg$currPos = s0; | |
| 10471 | s0 = peg$FAILED; | |
| 10472 | } | |
| 10473 | } else { | |
| 10474 | peg$currPos = s0; | |
| 10475 | s0 = peg$FAILED; | |
| 10476 | } | |
| 10477 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10478 | return s0; | |
| 10479 | } | |
| 10480 | function peg$parseunary_expression() { | |
| 10481 | var s0, s1, s2; | |
| 10482 | var key = peg$currPos * 306 + 235; | |
| 10483 | var cached = peg$resultsCache[key]; | |
| 10484 | if (cached) { | |
| 10485 | peg$currPos = cached.nextPos; | |
| 10486 | return cached.result; | |
| 10487 | } | |
| 10488 | peg$silentFails++; | |
| 10489 | s0 = peg$parsepostfix_expression(); | |
| 10490 | if (s0 === peg$FAILED) { | |
| 10491 | s0 = peg$currPos; | |
| 10492 | s1 = peg$parseINC_OP(); | |
| 10493 | if (s1 === peg$FAILED) { | |
| 10494 | s1 = peg$parseDEC_OP(); | |
| 10495 | if (s1 === peg$FAILED) { | |
| 10496 | s1 = peg$parsePLUS(); | |
| 10497 | if (s1 === peg$FAILED) { | |
| 10498 | s1 = peg$parseDASH(); | |
| 10499 | if (s1 === peg$FAILED) { | |
| 10500 | s1 = peg$parseBANG(); | |
| 10501 | if (s1 === peg$FAILED) { | |
| 10502 | s1 = peg$parseTILDE(); | |
| 10503 | } | |
| 10504 | } | |
| 10505 | } | |
| 10506 | } | |
| 10507 | } | |
| 10508 | if (s1 !== peg$FAILED) { | |
| 10509 | s2 = peg$parseunary_expression(); | |
| 10510 | if (s2 !== peg$FAILED) { | |
| 10511 | peg$savedPos = s0; | |
| 10512 | s0 = peg$f21(s1, s2); | |
| 10513 | } else { | |
| 10514 | peg$currPos = s0; | |
| 10515 | s0 = peg$FAILED; | |
| 10516 | } | |
| 10517 | } else { | |
| 10518 | peg$currPos = s0; | |
| 10519 | s0 = peg$FAILED; | |
| 10520 | } | |
| 10521 | } | |
| 10522 | peg$silentFails--; | |
| 10523 | if (s0 === peg$FAILED) { | |
| 10524 | s1 = peg$FAILED; | |
| 10525 | if (peg$silentFails === 0) { | |
| 10526 | peg$fail(peg$e224); | |
| 10527 | } | |
| 10528 | } | |
| 10529 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10530 | return s0; | |
| 10531 | } | |
| 10532 | function peg$parsemultiplicative_expression() { | |
| 10533 | var s0, s1, s2, s3, s4, s5; | |
| 10534 | var key = peg$currPos * 306 + 236; | |
| 10535 | var cached = peg$resultsCache[key]; | |
| 10536 | if (cached) { | |
| 10537 | peg$currPos = cached.nextPos; | |
| 10538 | return cached.result; | |
| 10539 | } | |
| 10540 | s0 = peg$currPos; | |
| 10541 | s1 = peg$parseunary_expression(); | |
| 10542 | if (s1 !== peg$FAILED) { | |
| 10543 | s2 = []; | |
| 10544 | s3 = peg$currPos; | |
| 10545 | s4 = peg$parseSTAR(); | |
| 10546 | if (s4 === peg$FAILED) { | |
| 10547 | s4 = peg$parseSLASH(); | |
| 10548 | if (s4 === peg$FAILED) { | |
| 10549 | s4 = peg$parsePERCENT(); | |
| 10550 | } | |
| 10551 | } | |
| 10552 | if (s4 !== peg$FAILED) { | |
| 10553 | s5 = peg$parseunary_expression(); | |
| 10554 | if (s5 !== peg$FAILED) { | |
| 10555 | s4 = [s4, s5]; | |
| 10556 | s3 = s4; | |
| 10557 | } else { | |
| 10558 | peg$currPos = s3; | |
| 10559 | s3 = peg$FAILED; | |
| 10560 | } | |
| 10561 | } else { | |
| 10562 | peg$currPos = s3; | |
| 10563 | s3 = peg$FAILED; | |
| 10564 | } | |
| 10565 | while (s3 !== peg$FAILED) { | |
| 10566 | s2.push(s3); | |
| 10567 | s3 = peg$currPos; | |
| 10568 | s4 = peg$parseSTAR(); | |
| 10569 | if (s4 === peg$FAILED) { | |
| 10570 | s4 = peg$parseSLASH(); | |
| 10571 | if (s4 === peg$FAILED) { | |
| 10572 | s4 = peg$parsePERCENT(); | |
| 10573 | } | |
| 10574 | } | |
| 10575 | if (s4 !== peg$FAILED) { | |
| 10576 | s5 = peg$parseunary_expression(); | |
| 10577 | if (s5 !== peg$FAILED) { | |
| 10578 | s4 = [s4, s5]; | |
| 10579 | s3 = s4; | |
| 10580 | } else { | |
| 10581 | peg$currPos = s3; | |
| 10582 | s3 = peg$FAILED; | |
| 10583 | } | |
| 10584 | } else { | |
| 10585 | peg$currPos = s3; | |
| 10586 | s3 = peg$FAILED; | |
| 10587 | } | |
| 10588 | } | |
| 10589 | peg$savedPos = s0; | |
| 10590 | s0 = peg$f22(s1, s2); | |
| 10591 | } else { | |
| 10592 | peg$currPos = s0; | |
| 10593 | s0 = peg$FAILED; | |
| 10594 | } | |
| 10595 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10596 | return s0; | |
| 10597 | } | |
| 10598 | function peg$parseadditive_expression() { | |
| 10599 | var s0, s1, s2, s3, s4, s5; | |
| 10600 | var key = peg$currPos * 306 + 237; | |
| 10601 | var cached = peg$resultsCache[key]; | |
| 10602 | if (cached) { | |
| 10603 | peg$currPos = cached.nextPos; | |
| 10604 | return cached.result; | |
| 10605 | } | |
| 10606 | s0 = peg$currPos; | |
| 10607 | s1 = peg$parsemultiplicative_expression(); | |
| 10608 | if (s1 !== peg$FAILED) { | |
| 10609 | s2 = []; | |
| 10610 | s3 = peg$currPos; | |
| 10611 | s4 = peg$parsePLUS(); | |
| 10612 | if (s4 === peg$FAILED) { | |
| 10613 | s4 = peg$parseDASH(); | |
| 10614 | } | |
| 10615 | if (s4 !== peg$FAILED) { | |
| 10616 | s5 = peg$parsemultiplicative_expression(); | |
| 10617 | if (s5 !== peg$FAILED) { | |
| 10618 | s4 = [s4, s5]; | |
| 10619 | s3 = s4; | |
| 10620 | } else { | |
| 10621 | peg$currPos = s3; | |
| 10622 | s3 = peg$FAILED; | |
| 10623 | } | |
| 10624 | } else { | |
| 10625 | peg$currPos = s3; | |
| 10626 | s3 = peg$FAILED; | |
| 10627 | } | |
| 10628 | while (s3 !== peg$FAILED) { | |
| 10629 | s2.push(s3); | |
| 10630 | s3 = peg$currPos; | |
| 10631 | s4 = peg$parsePLUS(); | |
| 10632 | if (s4 === peg$FAILED) { | |
| 10633 | s4 = peg$parseDASH(); | |
| 10634 | } | |
| 10635 | if (s4 !== peg$FAILED) { | |
| 10636 | s5 = peg$parsemultiplicative_expression(); | |
| 10637 | if (s5 !== peg$FAILED) { | |
| 10638 | s4 = [s4, s5]; | |
| 10639 | s3 = s4; | |
| 10640 | } else { | |
| 10641 | peg$currPos = s3; | |
| 10642 | s3 = peg$FAILED; | |
| 10643 | } | |
| 10644 | } else { | |
| 10645 | peg$currPos = s3; | |
| 10646 | s3 = peg$FAILED; | |
| 10647 | } | |
| 10648 | } | |
| 10649 | peg$savedPos = s0; | |
| 10650 | s0 = peg$f22(s1, s2); | |
| 10651 | } else { | |
| 10652 | peg$currPos = s0; | |
| 10653 | s0 = peg$FAILED; | |
| 10654 | } | |
| 10655 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10656 | return s0; | |
| 10657 | } | |
| 10658 | function peg$parseshift_expression() { | |
| 10659 | var s0, s1, s2, s3, s4, s5; | |
| 10660 | var key = peg$currPos * 306 + 238; | |
| 10661 | var cached = peg$resultsCache[key]; | |
| 10662 | if (cached) { | |
| 10663 | peg$currPos = cached.nextPos; | |
| 10664 | return cached.result; | |
| 10665 | } | |
| 10666 | s0 = peg$currPos; | |
| 10667 | s1 = peg$parseadditive_expression(); | |
| 10668 | if (s1 !== peg$FAILED) { | |
| 10669 | s2 = []; | |
| 10670 | s3 = peg$currPos; | |
| 10671 | s4 = peg$parseRIGHT_OP(); | |
| 10672 | if (s4 === peg$FAILED) { | |
| 10673 | s4 = peg$parseLEFT_OP(); | |
| 10674 | } | |
| 10675 | if (s4 !== peg$FAILED) { | |
| 10676 | s5 = peg$parseadditive_expression(); | |
| 10677 | if (s5 !== peg$FAILED) { | |
| 10678 | s4 = [s4, s5]; | |
| 10679 | s3 = s4; | |
| 10680 | } else { | |
| 10681 | peg$currPos = s3; | |
| 10682 | s3 = peg$FAILED; | |
| 10683 | } | |
| 10684 | } else { | |
| 10685 | peg$currPos = s3; | |
| 10686 | s3 = peg$FAILED; | |
| 10687 | } | |
| 10688 | while (s3 !== peg$FAILED) { | |
| 10689 | s2.push(s3); | |
| 10690 | s3 = peg$currPos; | |
| 10691 | s4 = peg$parseRIGHT_OP(); | |
| 10692 | if (s4 === peg$FAILED) { | |
| 10693 | s4 = peg$parseLEFT_OP(); | |
| 10694 | } | |
| 10695 | if (s4 !== peg$FAILED) { | |
| 10696 | s5 = peg$parseadditive_expression(); | |
| 10697 | if (s5 !== peg$FAILED) { | |
| 10698 | s4 = [s4, s5]; | |
| 10699 | s3 = s4; | |
| 10700 | } else { | |
| 10701 | peg$currPos = s3; | |
| 10702 | s3 = peg$FAILED; | |
| 10703 | } | |
| 10704 | } else { | |
| 10705 | peg$currPos = s3; | |
| 10706 | s3 = peg$FAILED; | |
| 10707 | } | |
| 10708 | } | |
| 10709 | peg$savedPos = s0; | |
| 10710 | s0 = peg$f22(s1, s2); | |
| 10711 | } else { | |
| 10712 | peg$currPos = s0; | |
| 10713 | s0 = peg$FAILED; | |
| 10714 | } | |
| 10715 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10716 | return s0; | |
| 10717 | } | |
| 10718 | function peg$parserelational_expression() { | |
| 10719 | var s0, s1, s2, s3, s4, s5; | |
| 10720 | var key = peg$currPos * 306 + 239; | |
| 10721 | var cached = peg$resultsCache[key]; | |
| 10722 | if (cached) { | |
| 10723 | peg$currPos = cached.nextPos; | |
| 10724 | return cached.result; | |
| 10725 | } | |
| 10726 | s0 = peg$currPos; | |
| 10727 | s1 = peg$parseshift_expression(); | |
| 10728 | if (s1 !== peg$FAILED) { | |
| 10729 | s2 = []; | |
| 10730 | s3 = peg$currPos; | |
| 10731 | s4 = peg$parseLE_OP(); | |
| 10732 | if (s4 === peg$FAILED) { | |
| 10733 | s4 = peg$parseGE_OP(); | |
| 10734 | if (s4 === peg$FAILED) { | |
| 10735 | s4 = peg$parseLEFT_ANGLE(); | |
| 10736 | if (s4 === peg$FAILED) { | |
| 10737 | s4 = peg$parseRIGHT_ANGLE(); | |
| 10738 | } | |
| 10739 | } | |
| 10740 | } | |
| 10741 | if (s4 !== peg$FAILED) { | |
| 10742 | s5 = peg$parseshift_expression(); | |
| 10743 | if (s5 !== peg$FAILED) { | |
| 10744 | s4 = [s4, s5]; | |
| 10745 | s3 = s4; | |
| 10746 | } else { | |
| 10747 | peg$currPos = s3; | |
| 10748 | s3 = peg$FAILED; | |
| 10749 | } | |
| 10750 | } else { | |
| 10751 | peg$currPos = s3; | |
| 10752 | s3 = peg$FAILED; | |
| 10753 | } | |
| 10754 | while (s3 !== peg$FAILED) { | |
| 10755 | s2.push(s3); | |
| 10756 | s3 = peg$currPos; | |
| 10757 | s4 = peg$parseLE_OP(); | |
| 10758 | if (s4 === peg$FAILED) { | |
| 10759 | s4 = peg$parseGE_OP(); | |
| 10760 | if (s4 === peg$FAILED) { | |
| 10761 | s4 = peg$parseLEFT_ANGLE(); | |
| 10762 | if (s4 === peg$FAILED) { | |
| 10763 | s4 = peg$parseRIGHT_ANGLE(); | |
| 10764 | } | |
| 10765 | } | |
| 10766 | } | |
| 10767 | if (s4 !== peg$FAILED) { | |
| 10768 | s5 = peg$parseshift_expression(); | |
| 10769 | if (s5 !== peg$FAILED) { | |
| 10770 | s4 = [s4, s5]; | |
| 10771 | s3 = s4; | |
| 10772 | } else { | |
| 10773 | peg$currPos = s3; | |
| 10774 | s3 = peg$FAILED; | |
| 10775 | } | |
| 10776 | } else { | |
| 10777 | peg$currPos = s3; | |
| 10778 | s3 = peg$FAILED; | |
| 10779 | } | |
| 10780 | } | |
| 10781 | peg$savedPos = s0; | |
| 10782 | s0 = peg$f22(s1, s2); | |
| 10783 | } else { | |
| 10784 | peg$currPos = s0; | |
| 10785 | s0 = peg$FAILED; | |
| 10786 | } | |
| 10787 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10788 | return s0; | |
| 10789 | } | |
| 10790 | function peg$parseequality_expression() { | |
| 10791 | var s0, s1, s2, s3, s4, s5; | |
| 10792 | var key = peg$currPos * 306 + 240; | |
| 10793 | var cached = peg$resultsCache[key]; | |
| 10794 | if (cached) { | |
| 10795 | peg$currPos = cached.nextPos; | |
| 10796 | return cached.result; | |
| 10797 | } | |
| 10798 | peg$silentFails++; | |
| 10799 | s0 = peg$currPos; | |
| 10800 | s1 = peg$parserelational_expression(); | |
| 10801 | if (s1 !== peg$FAILED) { | |
| 10802 | s2 = []; | |
| 10803 | s3 = peg$currPos; | |
| 10804 | s4 = peg$parseEQ_OP(); | |
| 10805 | if (s4 === peg$FAILED) { | |
| 10806 | s4 = peg$parseNE_OP(); | |
| 10807 | } | |
| 10808 | if (s4 !== peg$FAILED) { | |
| 10809 | s5 = peg$parserelational_expression(); | |
| 10810 | if (s5 !== peg$FAILED) { | |
| 10811 | s4 = [s4, s5]; | |
| 10812 | s3 = s4; | |
| 10813 | } else { | |
| 10814 | peg$currPos = s3; | |
| 10815 | s3 = peg$FAILED; | |
| 10816 | } | |
| 10817 | } else { | |
| 10818 | peg$currPos = s3; | |
| 10819 | s3 = peg$FAILED; | |
| 10820 | } | |
| 10821 | while (s3 !== peg$FAILED) { | |
| 10822 | s2.push(s3); | |
| 10823 | s3 = peg$currPos; | |
| 10824 | s4 = peg$parseEQ_OP(); | |
| 10825 | if (s4 === peg$FAILED) { | |
| 10826 | s4 = peg$parseNE_OP(); | |
| 10827 | } | |
| 10828 | if (s4 !== peg$FAILED) { | |
| 10829 | s5 = peg$parserelational_expression(); | |
| 10830 | if (s5 !== peg$FAILED) { | |
| 10831 | s4 = [s4, s5]; | |
| 10832 | s3 = s4; | |
| 10833 | } else { | |
| 10834 | peg$currPos = s3; | |
| 10835 | s3 = peg$FAILED; | |
| 10836 | } | |
| 10837 | } else { | |
| 10838 | peg$currPos = s3; | |
| 10839 | s3 = peg$FAILED; | |
| 10840 | } | |
| 10841 | } | |
| 10842 | peg$savedPos = s0; | |
| 10843 | s0 = peg$f22(s1, s2); | |
| 10844 | } else { | |
| 10845 | peg$currPos = s0; | |
| 10846 | s0 = peg$FAILED; | |
| 10847 | } | |
| 10848 | peg$silentFails--; | |
| 10849 | if (s0 === peg$FAILED) { | |
| 10850 | s1 = peg$FAILED; | |
| 10851 | if (peg$silentFails === 0) { | |
| 10852 | peg$fail(peg$e225); | |
| 10853 | } | |
| 10854 | } | |
| 10855 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10856 | return s0; | |
| 10857 | } | |
| 10858 | function peg$parseand_expression() { | |
| 10859 | var s0, s1, s2, s3, s4, s5; | |
| 10860 | var key = peg$currPos * 306 + 241; | |
| 10861 | var cached = peg$resultsCache[key]; | |
| 10862 | if (cached) { | |
| 10863 | peg$currPos = cached.nextPos; | |
| 10864 | return cached.result; | |
| 10865 | } | |
| 10866 | peg$silentFails++; | |
| 10867 | s0 = peg$currPos; | |
| 10868 | s1 = peg$parseequality_expression(); | |
| 10869 | if (s1 !== peg$FAILED) { | |
| 10870 | s2 = []; | |
| 10871 | s3 = peg$currPos; | |
| 10872 | s4 = peg$parseAMPERSAND(); | |
| 10873 | if (s4 !== peg$FAILED) { | |
| 10874 | s5 = peg$parseequality_expression(); | |
| 10875 | if (s5 !== peg$FAILED) { | |
| 10876 | s4 = [s4, s5]; | |
| 10877 | s3 = s4; | |
| 10878 | } else { | |
| 10879 | peg$currPos = s3; | |
| 10880 | s3 = peg$FAILED; | |
| 10881 | } | |
| 10882 | } else { | |
| 10883 | peg$currPos = s3; | |
| 10884 | s3 = peg$FAILED; | |
| 10885 | } | |
| 10886 | while (s3 !== peg$FAILED) { | |
| 10887 | s2.push(s3); | |
| 10888 | s3 = peg$currPos; | |
| 10889 | s4 = peg$parseAMPERSAND(); | |
| 10890 | if (s4 !== peg$FAILED) { | |
| 10891 | s5 = peg$parseequality_expression(); | |
| 10892 | if (s5 !== peg$FAILED) { | |
| 10893 | s4 = [s4, s5]; | |
| 10894 | s3 = s4; | |
| 10895 | } else { | |
| 10896 | peg$currPos = s3; | |
| 10897 | s3 = peg$FAILED; | |
| 10898 | } | |
| 10899 | } else { | |
| 10900 | peg$currPos = s3; | |
| 10901 | s3 = peg$FAILED; | |
| 10902 | } | |
| 10903 | } | |
| 10904 | peg$savedPos = s0; | |
| 10905 | s0 = peg$f22(s1, s2); | |
| 10906 | } else { | |
| 10907 | peg$currPos = s0; | |
| 10908 | s0 = peg$FAILED; | |
| 10909 | } | |
| 10910 | peg$silentFails--; | |
| 10911 | if (s0 === peg$FAILED) { | |
| 10912 | s1 = peg$FAILED; | |
| 10913 | if (peg$silentFails === 0) { | |
| 10914 | peg$fail(peg$e226); | |
| 10915 | } | |
| 10916 | } | |
| 10917 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10918 | return s0; | |
| 10919 | } | |
| 10920 | function peg$parseexclusive_or_expression() { | |
| 10921 | var s0, s1, s2, s3, s4, s5; | |
| 10922 | var key = peg$currPos * 306 + 242; | |
| 10923 | var cached = peg$resultsCache[key]; | |
| 10924 | if (cached) { | |
| 10925 | peg$currPos = cached.nextPos; | |
| 10926 | return cached.result; | |
| 10927 | } | |
| 10928 | s0 = peg$currPos; | |
| 10929 | s1 = peg$parseand_expression(); | |
| 10930 | if (s1 !== peg$FAILED) { | |
| 10931 | s2 = []; | |
| 10932 | s3 = peg$currPos; | |
| 10933 | s4 = peg$parseCARET(); | |
| 10934 | if (s4 !== peg$FAILED) { | |
| 10935 | s5 = peg$parseand_expression(); | |
| 10936 | if (s5 !== peg$FAILED) { | |
| 10937 | s4 = [s4, s5]; | |
| 10938 | s3 = s4; | |
| 10939 | } else { | |
| 10940 | peg$currPos = s3; | |
| 10941 | s3 = peg$FAILED; | |
| 10942 | } | |
| 10943 | } else { | |
| 10944 | peg$currPos = s3; | |
| 10945 | s3 = peg$FAILED; | |
| 10946 | } | |
| 10947 | while (s3 !== peg$FAILED) { | |
| 10948 | s2.push(s3); | |
| 10949 | s3 = peg$currPos; | |
| 10950 | s4 = peg$parseCARET(); | |
| 10951 | if (s4 !== peg$FAILED) { | |
| 10952 | s5 = peg$parseand_expression(); | |
| 10953 | if (s5 !== peg$FAILED) { | |
| 10954 | s4 = [s4, s5]; | |
| 10955 | s3 = s4; | |
| 10956 | } else { | |
| 10957 | peg$currPos = s3; | |
| 10958 | s3 = peg$FAILED; | |
| 10959 | } | |
| 10960 | } else { | |
| 10961 | peg$currPos = s3; | |
| 10962 | s3 = peg$FAILED; | |
| 10963 | } | |
| 10964 | } | |
| 10965 | peg$savedPos = s0; | |
| 10966 | s0 = peg$f22(s1, s2); | |
| 10967 | } else { | |
| 10968 | peg$currPos = s0; | |
| 10969 | s0 = peg$FAILED; | |
| 10970 | } | |
| 10971 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 10972 | return s0; | |
| 10973 | } | |
| 10974 | function peg$parseinclusive_or_expression() { | |
| 10975 | var s0, s1, s2, s3, s4, s5; | |
| 10976 | var key = peg$currPos * 306 + 243; | |
| 10977 | var cached = peg$resultsCache[key]; | |
| 10978 | if (cached) { | |
| 10979 | peg$currPos = cached.nextPos; | |
| 10980 | return cached.result; | |
| 10981 | } | |
| 10982 | s0 = peg$currPos; | |
| 10983 | s1 = peg$parseexclusive_or_expression(); | |
| 10984 | if (s1 !== peg$FAILED) { | |
| 10985 | s2 = []; | |
| 10986 | s3 = peg$currPos; | |
| 10987 | s4 = peg$parseVERTICAL_BAR(); | |
| 10988 | if (s4 !== peg$FAILED) { | |
| 10989 | s5 = peg$parseexclusive_or_expression(); | |
| 10990 | if (s5 !== peg$FAILED) { | |
| 10991 | s4 = [s4, s5]; | |
| 10992 | s3 = s4; | |
| 10993 | } else { | |
| 10994 | peg$currPos = s3; | |
| 10995 | s3 = peg$FAILED; | |
| 10996 | } | |
| 10997 | } else { | |
| 10998 | peg$currPos = s3; | |
| 10999 | s3 = peg$FAILED; | |
| 11000 | } | |
| 11001 | while (s3 !== peg$FAILED) { | |
| 11002 | s2.push(s3); | |
| 11003 | s3 = peg$currPos; | |
| 11004 | s4 = peg$parseVERTICAL_BAR(); | |
| 11005 | if (s4 !== peg$FAILED) { | |
| 11006 | s5 = peg$parseexclusive_or_expression(); | |
| 11007 | if (s5 !== peg$FAILED) { | |
| 11008 | s4 = [s4, s5]; | |
| 11009 | s3 = s4; | |
| 11010 | } else { | |
| 11011 | peg$currPos = s3; | |
| 11012 | s3 = peg$FAILED; | |
| 11013 | } | |
| 11014 | } else { | |
| 11015 | peg$currPos = s3; | |
| 11016 | s3 = peg$FAILED; | |
| 11017 | } | |
| 11018 | } | |
| 11019 | peg$savedPos = s0; | |
| 11020 | s0 = peg$f22(s1, s2); | |
| 11021 | } else { | |
| 11022 | peg$currPos = s0; | |
| 11023 | s0 = peg$FAILED; | |
| 11024 | } | |
| 11025 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11026 | return s0; | |
| 11027 | } | |
| 11028 | function peg$parselogical_and_expression() { | |
| 11029 | var s0, s1, s2, s3, s4, s5; | |
| 11030 | var key = peg$currPos * 306 + 244; | |
| 11031 | var cached = peg$resultsCache[key]; | |
| 11032 | if (cached) { | |
| 11033 | peg$currPos = cached.nextPos; | |
| 11034 | return cached.result; | |
| 11035 | } | |
| 11036 | s0 = peg$currPos; | |
| 11037 | s1 = peg$parseinclusive_or_expression(); | |
| 11038 | if (s1 !== peg$FAILED) { | |
| 11039 | s2 = []; | |
| 11040 | s3 = peg$currPos; | |
| 11041 | s4 = peg$parseAND_OP(); | |
| 11042 | if (s4 !== peg$FAILED) { | |
| 11043 | s5 = peg$parseinclusive_or_expression(); | |
| 11044 | if (s5 !== peg$FAILED) { | |
| 11045 | s4 = [s4, s5]; | |
| 11046 | s3 = s4; | |
| 11047 | } else { | |
| 11048 | peg$currPos = s3; | |
| 11049 | s3 = peg$FAILED; | |
| 11050 | } | |
| 11051 | } else { | |
| 11052 | peg$currPos = s3; | |
| 11053 | s3 = peg$FAILED; | |
| 11054 | } | |
| 11055 | while (s3 !== peg$FAILED) { | |
| 11056 | s2.push(s3); | |
| 11057 | s3 = peg$currPos; | |
| 11058 | s4 = peg$parseAND_OP(); | |
| 11059 | if (s4 !== peg$FAILED) { | |
| 11060 | s5 = peg$parseinclusive_or_expression(); | |
| 11061 | if (s5 !== peg$FAILED) { | |
| 11062 | s4 = [s4, s5]; | |
| 11063 | s3 = s4; | |
| 11064 | } else { | |
| 11065 | peg$currPos = s3; | |
| 11066 | s3 = peg$FAILED; | |
| 11067 | } | |
| 11068 | } else { | |
| 11069 | peg$currPos = s3; | |
| 11070 | s3 = peg$FAILED; | |
| 11071 | } | |
| 11072 | } | |
| 11073 | peg$savedPos = s0; | |
| 11074 | s0 = peg$f22(s1, s2); | |
| 11075 | } else { | |
| 11076 | peg$currPos = s0; | |
| 11077 | s0 = peg$FAILED; | |
| 11078 | } | |
| 11079 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11080 | return s0; | |
| 11081 | } | |
| 11082 | function peg$parselogical_xor_expression() { | |
| 11083 | var s0, s1, s2, s3, s4, s5; | |
| 11084 | var key = peg$currPos * 306 + 245; | |
| 11085 | var cached = peg$resultsCache[key]; | |
| 11086 | if (cached) { | |
| 11087 | peg$currPos = cached.nextPos; | |
| 11088 | return cached.result; | |
| 11089 | } | |
| 11090 | s0 = peg$currPos; | |
| 11091 | s1 = peg$parselogical_and_expression(); | |
| 11092 | if (s1 !== peg$FAILED) { | |
| 11093 | s2 = []; | |
| 11094 | s3 = peg$currPos; | |
| 11095 | s4 = peg$parseXOR_OP(); | |
| 11096 | if (s4 !== peg$FAILED) { | |
| 11097 | s5 = peg$parselogical_and_expression(); | |
| 11098 | if (s5 !== peg$FAILED) { | |
| 11099 | s4 = [s4, s5]; | |
| 11100 | s3 = s4; | |
| 11101 | } else { | |
| 11102 | peg$currPos = s3; | |
| 11103 | s3 = peg$FAILED; | |
| 11104 | } | |
| 11105 | } else { | |
| 11106 | peg$currPos = s3; | |
| 11107 | s3 = peg$FAILED; | |
| 11108 | } | |
| 11109 | while (s3 !== peg$FAILED) { | |
| 11110 | s2.push(s3); | |
| 11111 | s3 = peg$currPos; | |
| 11112 | s4 = peg$parseXOR_OP(); | |
| 11113 | if (s4 !== peg$FAILED) { | |
| 11114 | s5 = peg$parselogical_and_expression(); | |
| 11115 | if (s5 !== peg$FAILED) { | |
| 11116 | s4 = [s4, s5]; | |
| 11117 | s3 = s4; | |
| 11118 | } else { | |
| 11119 | peg$currPos = s3; | |
| 11120 | s3 = peg$FAILED; | |
| 11121 | } | |
| 11122 | } else { | |
| 11123 | peg$currPos = s3; | |
| 11124 | s3 = peg$FAILED; | |
| 11125 | } | |
| 11126 | } | |
| 11127 | peg$savedPos = s0; | |
| 11128 | s0 = peg$f22(s1, s2); | |
| 11129 | } else { | |
| 11130 | peg$currPos = s0; | |
| 11131 | s0 = peg$FAILED; | |
| 11132 | } | |
| 11133 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11134 | return s0; | |
| 11135 | } | |
| 11136 | function peg$parselogical_or_expression() { | |
| 11137 | var s0, s1, s2, s3, s4, s5; | |
| 11138 | var key = peg$currPos * 306 + 246; | |
| 11139 | var cached = peg$resultsCache[key]; | |
| 11140 | if (cached) { | |
| 11141 | peg$currPos = cached.nextPos; | |
| 11142 | return cached.result; | |
| 11143 | } | |
| 11144 | s0 = peg$currPos; | |
| 11145 | s1 = peg$parselogical_xor_expression(); | |
| 11146 | if (s1 !== peg$FAILED) { | |
| 11147 | s2 = []; | |
| 11148 | s3 = peg$currPos; | |
| 11149 | s4 = peg$parseOR_OP(); | |
| 11150 | if (s4 !== peg$FAILED) { | |
| 11151 | s5 = peg$parselogical_xor_expression(); | |
| 11152 | if (s5 !== peg$FAILED) { | |
| 11153 | s4 = [s4, s5]; | |
| 11154 | s3 = s4; | |
| 11155 | } else { | |
| 11156 | peg$currPos = s3; | |
| 11157 | s3 = peg$FAILED; | |
| 11158 | } | |
| 11159 | } else { | |
| 11160 | peg$currPos = s3; | |
| 11161 | s3 = peg$FAILED; | |
| 11162 | } | |
| 11163 | while (s3 !== peg$FAILED) { | |
| 11164 | s2.push(s3); | |
| 11165 | s3 = peg$currPos; | |
| 11166 | s4 = peg$parseOR_OP(); | |
| 11167 | if (s4 !== peg$FAILED) { | |
| 11168 | s5 = peg$parselogical_xor_expression(); | |
| 11169 | if (s5 !== peg$FAILED) { | |
| 11170 | s4 = [s4, s5]; | |
| 11171 | s3 = s4; | |
| 11172 | } else { | |
| 11173 | peg$currPos = s3; | |
| 11174 | s3 = peg$FAILED; | |
| 11175 | } | |
| 11176 | } else { | |
| 11177 | peg$currPos = s3; | |
| 11178 | s3 = peg$FAILED; | |
| 11179 | } | |
| 11180 | } | |
| 11181 | peg$savedPos = s0; | |
| 11182 | s0 = peg$f22(s1, s2); | |
| 11183 | } else { | |
| 11184 | peg$currPos = s0; | |
| 11185 | s0 = peg$FAILED; | |
| 11186 | } | |
| 11187 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11188 | return s0; | |
| 11189 | } | |
| 11190 | function peg$parseternary_expression() { | |
| 11191 | var s0, s1, s2, s3, s4, s5, s6; | |
| 11192 | var key = peg$currPos * 306 + 247; | |
| 11193 | var cached = peg$resultsCache[key]; | |
| 11194 | if (cached) { | |
| 11195 | peg$currPos = cached.nextPos; | |
| 11196 | return cached.result; | |
| 11197 | } | |
| 11198 | s0 = peg$currPos; | |
| 11199 | s1 = peg$parselogical_or_expression(); | |
| 11200 | if (s1 !== peg$FAILED) { | |
| 11201 | s2 = peg$currPos; | |
| 11202 | s3 = peg$parseQUESTION(); | |
| 11203 | if (s3 !== peg$FAILED) { | |
| 11204 | s4 = peg$parseexpression(); | |
| 11205 | if (s4 !== peg$FAILED) { | |
| 11206 | s5 = peg$parseCOLON(); | |
| 11207 | if (s5 !== peg$FAILED) { | |
| 11208 | s6 = peg$parseassignment_expression(); | |
| 11209 | if (s6 !== peg$FAILED) { | |
| 11210 | peg$savedPos = s2; | |
| 11211 | s2 = peg$f23(s1, s3, s4, s5, s6); | |
| 11212 | } else { | |
| 11213 | peg$currPos = s2; | |
| 11214 | s2 = peg$FAILED; | |
| 11215 | } | |
| 11216 | } else { | |
| 11217 | peg$currPos = s2; | |
| 11218 | s2 = peg$FAILED; | |
| 11219 | } | |
| 11220 | } else { | |
| 11221 | peg$currPos = s2; | |
| 11222 | s2 = peg$FAILED; | |
| 11223 | } | |
| 11224 | } else { | |
| 11225 | peg$currPos = s2; | |
| 11226 | s2 = peg$FAILED; | |
| 11227 | } | |
| 11228 | if (s2 === peg$FAILED) { | |
| 11229 | s2 = null; | |
| 11230 | } | |
| 11231 | peg$savedPos = s0; | |
| 11232 | s0 = peg$f24(s1, s2); | |
| 11233 | } else { | |
| 11234 | peg$currPos = s0; | |
| 11235 | s0 = peg$FAILED; | |
| 11236 | } | |
| 11237 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11238 | return s0; | |
| 11239 | } | |
| 11240 | function peg$parseassignment_expression() { | |
| 11241 | var s0, s1, s2, s3; | |
| 11242 | var key = peg$currPos * 306 + 248; | |
| 11243 | var cached = peg$resultsCache[key]; | |
| 11244 | if (cached) { | |
| 11245 | peg$currPos = cached.nextPos; | |
| 11246 | return cached.result; | |
| 11247 | } | |
| 11248 | s0 = peg$currPos; | |
| 11249 | s1 = peg$parseunary_expression(); | |
| 11250 | if (s1 !== peg$FAILED) { | |
| 11251 | s2 = peg$parseassignment_operator(); | |
| 11252 | if (s2 !== peg$FAILED) { | |
| 11253 | s3 = peg$parseassignment_expression(); | |
| 11254 | if (s3 !== peg$FAILED) { | |
| 11255 | peg$savedPos = s0; | |
| 11256 | s0 = peg$f25(s1, s2, s3); | |
| 11257 | } else { | |
| 11258 | peg$currPos = s0; | |
| 11259 | s0 = peg$FAILED; | |
| 11260 | } | |
| 11261 | } else { | |
| 11262 | peg$currPos = s0; | |
| 11263 | s0 = peg$FAILED; | |
| 11264 | } | |
| 11265 | } else { | |
| 11266 | peg$currPos = s0; | |
| 11267 | s0 = peg$FAILED; | |
| 11268 | } | |
| 11269 | if (s0 === peg$FAILED) { | |
| 11270 | s0 = peg$parseternary_expression(); | |
| 11271 | } | |
| 11272 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11273 | return s0; | |
| 11274 | } | |
| 11275 | function peg$parseassignment_operator() { | |
| 11276 | var s0, s1; | |
| 11277 | var key = peg$currPos * 306 + 249; | |
| 11278 | var cached = peg$resultsCache[key]; | |
| 11279 | if (cached) { | |
| 11280 | peg$currPos = cached.nextPos; | |
| 11281 | return cached.result; | |
| 11282 | } | |
| 11283 | peg$silentFails++; | |
| 11284 | s0 = peg$parseEQUAL(); | |
| 11285 | if (s0 === peg$FAILED) { | |
| 11286 | s0 = peg$parseMUL_ASSIGN(); | |
| 11287 | if (s0 === peg$FAILED) { | |
| 11288 | s0 = peg$parseDIV_ASSIGN(); | |
| 11289 | if (s0 === peg$FAILED) { | |
| 11290 | s0 = peg$parseMOD_ASSIGN(); | |
| 11291 | if (s0 === peg$FAILED) { | |
| 11292 | s0 = peg$parseADD_ASSIGN(); | |
| 11293 | if (s0 === peg$FAILED) { | |
| 11294 | s0 = peg$parseSUB_ASSIGN(); | |
| 11295 | if (s0 === peg$FAILED) { | |
| 11296 | s0 = peg$parseLEFT_ASSIGN(); | |
| 11297 | if (s0 === peg$FAILED) { | |
| 11298 | s0 = peg$parseRIGHT_ASSIGN(); | |
| 11299 | if (s0 === peg$FAILED) { | |
| 11300 | s0 = peg$parseAND_ASSIGN(); | |
| 11301 | if (s0 === peg$FAILED) { | |
| 11302 | s0 = peg$parseXOR_ASSIGN(); | |
| 11303 | if (s0 === peg$FAILED) { | |
| 11304 | s0 = peg$parseOR_ASSIGN(); | |
| 11305 | } | |
| 11306 | } | |
| 11307 | } | |
| 11308 | } | |
| 11309 | } | |
| 11310 | } | |
| 11311 | } | |
| 11312 | } | |
| 11313 | } | |
| 11314 | } | |
| 11315 | peg$silentFails--; | |
| 11316 | if (s0 === peg$FAILED) { | |
| 11317 | s1 = peg$FAILED; | |
| 11318 | if (peg$silentFails === 0) { | |
| 11319 | peg$fail(peg$e227); | |
| 11320 | } | |
| 11321 | } | |
| 11322 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11323 | return s0; | |
| 11324 | } | |
| 11325 | function peg$parseexpression() { | |
| 11326 | var s0, s1, s2, s3, s4, s5; | |
| 11327 | var key = peg$currPos * 306 + 250; | |
| 11328 | var cached = peg$resultsCache[key]; | |
| 11329 | if (cached) { | |
| 11330 | peg$currPos = cached.nextPos; | |
| 11331 | return cached.result; | |
| 11332 | } | |
| 11333 | peg$silentFails++; | |
| 11334 | s0 = peg$currPos; | |
| 11335 | s1 = peg$parseassignment_expression(); | |
| 11336 | if (s1 !== peg$FAILED) { | |
| 11337 | s2 = []; | |
| 11338 | s3 = peg$currPos; | |
| 11339 | s4 = peg$parseCOMMA(); | |
| 11340 | if (s4 !== peg$FAILED) { | |
| 11341 | s5 = peg$parseassignment_expression(); | |
| 11342 | if (s5 !== peg$FAILED) { | |
| 11343 | s4 = [s4, s5]; | |
| 11344 | s3 = s4; | |
| 11345 | } else { | |
| 11346 | peg$currPos = s3; | |
| 11347 | s3 = peg$FAILED; | |
| 11348 | } | |
| 11349 | } else { | |
| 11350 | peg$currPos = s3; | |
| 11351 | s3 = peg$FAILED; | |
| 11352 | } | |
| 11353 | while (s3 !== peg$FAILED) { | |
| 11354 | s2.push(s3); | |
| 11355 | s3 = peg$currPos; | |
| 11356 | s4 = peg$parseCOMMA(); | |
| 11357 | if (s4 !== peg$FAILED) { | |
| 11358 | s5 = peg$parseassignment_expression(); | |
| 11359 | if (s5 !== peg$FAILED) { | |
| 11360 | s4 = [s4, s5]; | |
| 11361 | s3 = s4; | |
| 11362 | } else { | |
| 11363 | peg$currPos = s3; | |
| 11364 | s3 = peg$FAILED; | |
| 11365 | } | |
| 11366 | } else { | |
| 11367 | peg$currPos = s3; | |
| 11368 | s3 = peg$FAILED; | |
| 11369 | } | |
| 11370 | } | |
| 11371 | peg$savedPos = s0; | |
| 11372 | s0 = peg$f22(s1, s2); | |
| 11373 | } else { | |
| 11374 | peg$currPos = s0; | |
| 11375 | s0 = peg$FAILED; | |
| 11376 | } | |
| 11377 | peg$silentFails--; | |
| 11378 | if (s0 === peg$FAILED) { | |
| 11379 | s1 = peg$FAILED; | |
| 11380 | if (peg$silentFails === 0) { | |
| 11381 | peg$fail(peg$e228); | |
| 11382 | } | |
| 11383 | } | |
| 11384 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11385 | return s0; | |
| 11386 | } | |
| 11387 | function peg$parsedeclaration_statement() { | |
| 11388 | var s0, s1; | |
| 11389 | var key = peg$currPos * 306 + 251; | |
| 11390 | var cached = peg$resultsCache[key]; | |
| 11391 | if (cached) { | |
| 11392 | peg$currPos = cached.nextPos; | |
| 11393 | return cached.result; | |
| 11394 | } | |
| 11395 | s0 = peg$currPos; | |
| 11396 | s1 = peg$parseprecision_declarator_statement(); | |
| 11397 | if (s1 === peg$FAILED) { | |
| 11398 | s1 = peg$parseinterface_declarator_statement(); | |
| 11399 | if (s1 === peg$FAILED) { | |
| 11400 | s1 = peg$parsequalifier_declarator_statement(); | |
| 11401 | if (s1 === peg$FAILED) { | |
| 11402 | s1 = peg$parseinit_declarator_list_statement(); | |
| 11403 | } | |
| 11404 | } | |
| 11405 | } | |
| 11406 | if (s1 !== peg$FAILED) { | |
| 11407 | peg$savedPos = s0; | |
| 11408 | s1 = peg$f26(s1); | |
| 11409 | } | |
| 11410 | s0 = s1; | |
| 11411 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11412 | return s0; | |
| 11413 | } | |
| 11414 | function peg$parsequalifier_declarator_statement() { | |
| 11415 | var s0, s1, s2, s3, s4, s5, s6; | |
| 11416 | var key = peg$currPos * 306 + 252; | |
| 11417 | var cached = peg$resultsCache[key]; | |
| 11418 | if (cached) { | |
| 11419 | peg$currPos = cached.nextPos; | |
| 11420 | return cached.result; | |
| 11421 | } | |
| 11422 | s0 = peg$currPos; | |
| 11423 | s1 = peg$parsetype_qualifiers(); | |
| 11424 | if (s1 !== peg$FAILED) { | |
| 11425 | s2 = peg$parseIDENTIFIER(); | |
| 11426 | if (s2 === peg$FAILED) { | |
| 11427 | s2 = null; | |
| 11428 | } | |
| 11429 | s3 = []; | |
| 11430 | s4 = peg$currPos; | |
| 11431 | s5 = peg$parseCOMMA(); | |
| 11432 | if (s5 !== peg$FAILED) { | |
| 11433 | s6 = peg$parseIDENTIFIER(); | |
| 11434 | if (s6 !== peg$FAILED) { | |
| 11435 | s5 = [s5, s6]; | |
| 11436 | s4 = s5; | |
| 11437 | } else { | |
| 11438 | peg$currPos = s4; | |
| 11439 | s4 = peg$FAILED; | |
| 11440 | } | |
| 11441 | } else { | |
| 11442 | peg$currPos = s4; | |
| 11443 | s4 = peg$FAILED; | |
| 11444 | } | |
| 11445 | while (s4 !== peg$FAILED) { | |
| 11446 | s3.push(s4); | |
| 11447 | s4 = peg$currPos; | |
| 11448 | s5 = peg$parseCOMMA(); | |
| 11449 | if (s5 !== peg$FAILED) { | |
| 11450 | s6 = peg$parseIDENTIFIER(); | |
| 11451 | if (s6 !== peg$FAILED) { | |
| 11452 | s5 = [s5, s6]; | |
| 11453 | s4 = s5; | |
| 11454 | } else { | |
| 11455 | peg$currPos = s4; | |
| 11456 | s4 = peg$FAILED; | |
| 11457 | } | |
| 11458 | } else { | |
| 11459 | peg$currPos = s4; | |
| 11460 | s4 = peg$FAILED; | |
| 11461 | } | |
| 11462 | } | |
| 11463 | s4 = peg$parseSEMICOLON(); | |
| 11464 | if (s4 !== peg$FAILED) { | |
| 11465 | peg$savedPos = s0; | |
| 11466 | s0 = peg$f27(s1, s2, s3, s4); | |
| 11467 | } else { | |
| 11468 | peg$currPos = s0; | |
| 11469 | s0 = peg$FAILED; | |
| 11470 | } | |
| 11471 | } else { | |
| 11472 | peg$currPos = s0; | |
| 11473 | s0 = peg$FAILED; | |
| 11474 | } | |
| 11475 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11476 | return s0; | |
| 11477 | } | |
| 11478 | function peg$parseinterface_declarator_statement() { | |
| 11479 | var s0, s1, s2, s3, s4, s5, s6, s7; | |
| 11480 | var key = peg$currPos * 306 + 253; | |
| 11481 | var cached = peg$resultsCache[key]; | |
| 11482 | if (cached) { | |
| 11483 | peg$currPos = cached.nextPos; | |
| 11484 | return cached.result; | |
| 11485 | } | |
| 11486 | s0 = peg$currPos; | |
| 11487 | s1 = peg$parsetype_qualifiers(); | |
| 11488 | if (s1 !== peg$FAILED) { | |
| 11489 | s2 = peg$parseIDENTIFIER(); | |
| 11490 | if (s2 !== peg$FAILED) { | |
| 11491 | s3 = peg$parseLEFT_BRACE(); | |
| 11492 | if (s3 !== peg$FAILED) { | |
| 11493 | s4 = peg$parsestruct_declaration_list(); | |
| 11494 | if (s4 !== peg$FAILED) { | |
| 11495 | s5 = peg$parseRIGHT_BRACE(); | |
| 11496 | if (s5 !== peg$FAILED) { | |
| 11497 | s6 = peg$parsequantified_identifier(); | |
| 11498 | if (s6 === peg$FAILED) { | |
| 11499 | s6 = null; | |
| 11500 | } | |
| 11501 | s7 = peg$parseSEMICOLON(); | |
| 11502 | if (s7 !== peg$FAILED) { | |
| 11503 | peg$savedPos = s0; | |
| 11504 | s0 = peg$f28(s1, s2, s3, s4, s5, s6, s7); | |
| 11505 | } else { | |
| 11506 | peg$currPos = s0; | |
| 11507 | s0 = peg$FAILED; | |
| 11508 | } | |
| 11509 | } else { | |
| 11510 | peg$currPos = s0; | |
| 11511 | s0 = peg$FAILED; | |
| 11512 | } | |
| 11513 | } else { | |
| 11514 | peg$currPos = s0; | |
| 11515 | s0 = peg$FAILED; | |
| 11516 | } | |
| 11517 | } else { | |
| 11518 | peg$currPos = s0; | |
| 11519 | s0 = peg$FAILED; | |
| 11520 | } | |
| 11521 | } else { | |
| 11522 | peg$currPos = s0; | |
| 11523 | s0 = peg$FAILED; | |
| 11524 | } | |
| 11525 | } else { | |
| 11526 | peg$currPos = s0; | |
| 11527 | s0 = peg$FAILED; | |
| 11528 | } | |
| 11529 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11530 | return s0; | |
| 11531 | } | |
| 11532 | function peg$parseprecision_declarator_statement() { | |
| 11533 | var s0, s1, s2, s3, s4; | |
| 11534 | var key = peg$currPos * 306 + 254; | |
| 11535 | var cached = peg$resultsCache[key]; | |
| 11536 | if (cached) { | |
| 11537 | peg$currPos = cached.nextPos; | |
| 11538 | return cached.result; | |
| 11539 | } | |
| 11540 | peg$silentFails++; | |
| 11541 | s0 = peg$currPos; | |
| 11542 | s1 = peg$parsePRECISION(); | |
| 11543 | if (s1 !== peg$FAILED) { | |
| 11544 | s2 = peg$parseprecision_qualifier(); | |
| 11545 | if (s2 !== peg$FAILED) { | |
| 11546 | s3 = peg$parsetype_specifier(); | |
| 11547 | if (s3 !== peg$FAILED) { | |
| 11548 | s4 = peg$parseSEMICOLON(); | |
| 11549 | if (s4 !== peg$FAILED) { | |
| 11550 | peg$savedPos = s0; | |
| 11551 | s0 = peg$f29(s1, s2, s3, s4); | |
| 11552 | } else { | |
| 11553 | peg$currPos = s0; | |
| 11554 | s0 = peg$FAILED; | |
| 11555 | } | |
| 11556 | } else { | |
| 11557 | peg$currPos = s0; | |
| 11558 | s0 = peg$FAILED; | |
| 11559 | } | |
| 11560 | } else { | |
| 11561 | peg$currPos = s0; | |
| 11562 | s0 = peg$FAILED; | |
| 11563 | } | |
| 11564 | } else { | |
| 11565 | peg$currPos = s0; | |
| 11566 | s0 = peg$FAILED; | |
| 11567 | } | |
| 11568 | peg$silentFails--; | |
| 11569 | if (s0 === peg$FAILED) { | |
| 11570 | s1 = peg$FAILED; | |
| 11571 | if (peg$silentFails === 0) { | |
| 11572 | peg$fail(peg$e229); | |
| 11573 | } | |
| 11574 | } | |
| 11575 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11576 | return s0; | |
| 11577 | } | |
| 11578 | function peg$parsefunction_prototype_new_scope() { | |
| 11579 | var s0, s1, s2, s3; | |
| 11580 | var key = peg$currPos * 306 + 255; | |
| 11581 | var cached = peg$resultsCache[key]; | |
| 11582 | if (cached) { | |
| 11583 | peg$currPos = cached.nextPos; | |
| 11584 | return cached.result; | |
| 11585 | } | |
| 11586 | peg$silentFails++; | |
| 11587 | s0 = peg$currPos; | |
| 11588 | s1 = peg$parsefunction_header_new_scope(); | |
| 11589 | if (s1 !== peg$FAILED) { | |
| 11590 | s2 = peg$parsefunction_parameters(); | |
| 11591 | if (s2 === peg$FAILED) { | |
| 11592 | s2 = null; | |
| 11593 | } | |
| 11594 | s3 = peg$parseRIGHT_PAREN(); | |
| 11595 | if (s3 !== peg$FAILED) { | |
| 11596 | peg$savedPos = s0; | |
| 11597 | s0 = peg$f30(s1, s2, s3); | |
| 11598 | } else { | |
| 11599 | peg$currPos = s0; | |
| 11600 | s0 = peg$FAILED; | |
| 11601 | } | |
| 11602 | } else { | |
| 11603 | peg$currPos = s0; | |
| 11604 | s0 = peg$FAILED; | |
| 11605 | } | |
| 11606 | peg$silentFails--; | |
| 11607 | if (s0 === peg$FAILED) { | |
| 11608 | s1 = peg$FAILED; | |
| 11609 | if (peg$silentFails === 0) { | |
| 11610 | peg$fail(peg$e230); | |
| 11611 | } | |
| 11612 | } | |
| 11613 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11614 | return s0; | |
| 11615 | } | |
| 11616 | function peg$parsefunction_header_new_scope() { | |
| 11617 | var s0, s1, s2, s3; | |
| 11618 | var key = peg$currPos * 306 + 256; | |
| 11619 | var cached = peg$resultsCache[key]; | |
| 11620 | if (cached) { | |
| 11621 | peg$currPos = cached.nextPos; | |
| 11622 | return cached.result; | |
| 11623 | } | |
| 11624 | peg$silentFails++; | |
| 11625 | s0 = peg$currPos; | |
| 11626 | s1 = peg$parsefully_specified_type(); | |
| 11627 | if (s1 !== peg$FAILED) { | |
| 11628 | s2 = peg$parseIDENTIFIER(); | |
| 11629 | if (s2 !== peg$FAILED) { | |
| 11630 | s3 = peg$parseLEFT_PAREN(); | |
| 11631 | if (s3 !== peg$FAILED) { | |
| 11632 | peg$savedPos = s0; | |
| 11633 | s0 = peg$f31(s1, s2, s3); | |
| 11634 | } else { | |
| 11635 | peg$currPos = s0; | |
| 11636 | s0 = peg$FAILED; | |
| 11637 | } | |
| 11638 | } else { | |
| 11639 | peg$currPos = s0; | |
| 11640 | s0 = peg$FAILED; | |
| 11641 | } | |
| 11642 | } else { | |
| 11643 | peg$currPos = s0; | |
| 11644 | s0 = peg$FAILED; | |
| 11645 | } | |
| 11646 | peg$silentFails--; | |
| 11647 | if (s0 === peg$FAILED) { | |
| 11648 | s1 = peg$FAILED; | |
| 11649 | if (peg$silentFails === 0) { | |
| 11650 | peg$fail(peg$e231); | |
| 11651 | } | |
| 11652 | } | |
| 11653 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11654 | return s0; | |
| 11655 | } | |
| 11656 | function peg$parsefunction_prototype_no_new_scope() { | |
| 11657 | var s0, s1, s2, s3; | |
| 11658 | var key = peg$currPos * 306 + 257; | |
| 11659 | var cached = peg$resultsCache[key]; | |
| 11660 | if (cached) { | |
| 11661 | peg$currPos = cached.nextPos; | |
| 11662 | return cached.result; | |
| 11663 | } | |
| 11664 | peg$silentFails++; | |
| 11665 | s0 = peg$currPos; | |
| 11666 | s1 = peg$parsefunction_header_no_new_scope(); | |
| 11667 | if (s1 !== peg$FAILED) { | |
| 11668 | s2 = peg$parsefunction_parameters(); | |
| 11669 | if (s2 === peg$FAILED) { | |
| 11670 | s2 = null; | |
| 11671 | } | |
| 11672 | s3 = peg$parseRIGHT_PAREN(); | |
| 11673 | if (s3 !== peg$FAILED) { | |
| 11674 | peg$savedPos = s0; | |
| 11675 | s0 = peg$f32(s1, s2, s3); | |
| 11676 | } else { | |
| 11677 | peg$currPos = s0; | |
| 11678 | s0 = peg$FAILED; | |
| 11679 | } | |
| 11680 | } else { | |
| 11681 | peg$currPos = s0; | |
| 11682 | s0 = peg$FAILED; | |
| 11683 | } | |
| 11684 | peg$silentFails--; | |
| 11685 | if (s0 === peg$FAILED) { | |
| 11686 | s1 = peg$FAILED; | |
| 11687 | if (peg$silentFails === 0) { | |
| 11688 | peg$fail(peg$e232); | |
| 11689 | } | |
| 11690 | } | |
| 11691 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11692 | return s0; | |
| 11693 | } | |
| 11694 | function peg$parsefunction_header_no_new_scope() { | |
| 11695 | var s0, s1, s2, s3; | |
| 11696 | var key = peg$currPos * 306 + 258; | |
| 11697 | var cached = peg$resultsCache[key]; | |
| 11698 | if (cached) { | |
| 11699 | peg$currPos = cached.nextPos; | |
| 11700 | return cached.result; | |
| 11701 | } | |
| 11702 | peg$silentFails++; | |
| 11703 | s0 = peg$currPos; | |
| 11704 | s1 = peg$parsefully_specified_type(); | |
| 11705 | if (s1 !== peg$FAILED) { | |
| 11706 | s2 = peg$parseIDENTIFIER(); | |
| 11707 | if (s2 !== peg$FAILED) { | |
| 11708 | s3 = peg$parseLEFT_PAREN(); | |
| 11709 | if (s3 !== peg$FAILED) { | |
| 11710 | peg$savedPos = s0; | |
| 11711 | s0 = peg$f33(s1, s2, s3); | |
| 11712 | } else { | |
| 11713 | peg$currPos = s0; | |
| 11714 | s0 = peg$FAILED; | |
| 11715 | } | |
| 11716 | } else { | |
| 11717 | peg$currPos = s0; | |
| 11718 | s0 = peg$FAILED; | |
| 11719 | } | |
| 11720 | } else { | |
| 11721 | peg$currPos = s0; | |
| 11722 | s0 = peg$FAILED; | |
| 11723 | } | |
| 11724 | peg$silentFails--; | |
| 11725 | if (s0 === peg$FAILED) { | |
| 11726 | s1 = peg$FAILED; | |
| 11727 | if (peg$silentFails === 0) { | |
| 11728 | peg$fail(peg$e233); | |
| 11729 | } | |
| 11730 | } | |
| 11731 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11732 | return s0; | |
| 11733 | } | |
| 11734 | function peg$parsefunction_parameters() { | |
| 11735 | var s0, s1, s2, s3, s4, s5; | |
| 11736 | var key = peg$currPos * 306 + 259; | |
| 11737 | var cached = peg$resultsCache[key]; | |
| 11738 | if (cached) { | |
| 11739 | peg$currPos = cached.nextPos; | |
| 11740 | return cached.result; | |
| 11741 | } | |
| 11742 | peg$silentFails++; | |
| 11743 | s0 = peg$currPos; | |
| 11744 | s1 = peg$parseparameter_declaration(); | |
| 11745 | if (s1 !== peg$FAILED) { | |
| 11746 | s2 = []; | |
| 11747 | s3 = peg$currPos; | |
| 11748 | s4 = peg$parseCOMMA(); | |
| 11749 | if (s4 !== peg$FAILED) { | |
| 11750 | s5 = peg$parseparameter_declaration(); | |
| 11751 | if (s5 !== peg$FAILED) { | |
| 11752 | s4 = [s4, s5]; | |
| 11753 | s3 = s4; | |
| 11754 | } else { | |
| 11755 | peg$currPos = s3; | |
| 11756 | s3 = peg$FAILED; | |
| 11757 | } | |
| 11758 | } else { | |
| 11759 | peg$currPos = s3; | |
| 11760 | s3 = peg$FAILED; | |
| 11761 | } | |
| 11762 | while (s3 !== peg$FAILED) { | |
| 11763 | s2.push(s3); | |
| 11764 | s3 = peg$currPos; | |
| 11765 | s4 = peg$parseCOMMA(); | |
| 11766 | if (s4 !== peg$FAILED) { | |
| 11767 | s5 = peg$parseparameter_declaration(); | |
| 11768 | if (s5 !== peg$FAILED) { | |
| 11769 | s4 = [s4, s5]; | |
| 11770 | s3 = s4; | |
| 11771 | } else { | |
| 11772 | peg$currPos = s3; | |
| 11773 | s3 = peg$FAILED; | |
| 11774 | } | |
| 11775 | } else { | |
| 11776 | peg$currPos = s3; | |
| 11777 | s3 = peg$FAILED; | |
| 11778 | } | |
| 11779 | } | |
| 11780 | peg$savedPos = s0; | |
| 11781 | s0 = peg$f34(s1, s2); | |
| 11782 | } else { | |
| 11783 | peg$currPos = s0; | |
| 11784 | s0 = peg$FAILED; | |
| 11785 | } | |
| 11786 | peg$silentFails--; | |
| 11787 | if (s0 === peg$FAILED) { | |
| 11788 | s1 = peg$FAILED; | |
| 11789 | if (peg$silentFails === 0) { | |
| 11790 | peg$fail(peg$e234); | |
| 11791 | } | |
| 11792 | } | |
| 11793 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11794 | return s0; | |
| 11795 | } | |
| 11796 | function peg$parseparameter_declaration() { | |
| 11797 | var s0, s1, s2, s3, s4, s5; | |
| 11798 | var key = peg$currPos * 306 + 260; | |
| 11799 | var cached = peg$resultsCache[key]; | |
| 11800 | if (cached) { | |
| 11801 | peg$currPos = cached.nextPos; | |
| 11802 | return cached.result; | |
| 11803 | } | |
| 11804 | peg$silentFails++; | |
| 11805 | s0 = peg$currPos; | |
| 11806 | s1 = []; | |
| 11807 | s2 = peg$parseparameter_qualifier(); | |
| 11808 | while (s2 !== peg$FAILED) { | |
| 11809 | s1.push(s2); | |
| 11810 | s2 = peg$parseparameter_qualifier(); | |
| 11811 | } | |
| 11812 | s2 = peg$parsetype_specifier(); | |
| 11813 | if (s2 !== peg$FAILED) { | |
| 11814 | s3 = peg$currPos; | |
| 11815 | s4 = peg$parseIDENTIFIER(); | |
| 11816 | if (s4 !== peg$FAILED) { | |
| 11817 | s5 = peg$parsearray_specifiers(); | |
| 11818 | if (s5 === peg$FAILED) { | |
| 11819 | s5 = null; | |
| 11820 | } | |
| 11821 | s4 = [s4, s5]; | |
| 11822 | s3 = s4; | |
| 11823 | } else { | |
| 11824 | peg$currPos = s3; | |
| 11825 | s3 = peg$FAILED; | |
| 11826 | } | |
| 11827 | if (s3 === peg$FAILED) { | |
| 11828 | s3 = null; | |
| 11829 | } | |
| 11830 | peg$savedPos = s0; | |
| 11831 | s0 = peg$f35(s1, s2, s3); | |
| 11832 | } else { | |
| 11833 | peg$currPos = s0; | |
| 11834 | s0 = peg$FAILED; | |
| 11835 | } | |
| 11836 | peg$silentFails--; | |
| 11837 | if (s0 === peg$FAILED) { | |
| 11838 | s1 = peg$FAILED; | |
| 11839 | if (peg$silentFails === 0) { | |
| 11840 | peg$fail(peg$e235); | |
| 11841 | } | |
| 11842 | } | |
| 11843 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11844 | return s0; | |
| 11845 | } | |
| 11846 | function peg$parseparameter_qualifier() { | |
| 11847 | var s0; | |
| 11848 | var key = peg$currPos * 306 + 261; | |
| 11849 | var cached = peg$resultsCache[key]; | |
| 11850 | if (cached) { | |
| 11851 | peg$currPos = cached.nextPos; | |
| 11852 | return cached.result; | |
| 11853 | } | |
| 11854 | s0 = peg$parseCONST(); | |
| 11855 | if (s0 === peg$FAILED) { | |
| 11856 | s0 = peg$parseIN(); | |
| 11857 | if (s0 === peg$FAILED) { | |
| 11858 | s0 = peg$parseOUT(); | |
| 11859 | if (s0 === peg$FAILED) { | |
| 11860 | s0 = peg$parseINOUT(); | |
| 11861 | if (s0 === peg$FAILED) { | |
| 11862 | s0 = peg$parsememory_qualifier(); | |
| 11863 | if (s0 === peg$FAILED) { | |
| 11864 | s0 = peg$parseprecision_qualifier(); | |
| 11865 | } | |
| 11866 | } | |
| 11867 | } | |
| 11868 | } | |
| 11869 | } | |
| 11870 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11871 | return s0; | |
| 11872 | } | |
| 11873 | function peg$parsememory_qualifier() { | |
| 11874 | var s0; | |
| 11875 | var key = peg$currPos * 306 + 262; | |
| 11876 | var cached = peg$resultsCache[key]; | |
| 11877 | if (cached) { | |
| 11878 | peg$currPos = cached.nextPos; | |
| 11879 | return cached.result; | |
| 11880 | } | |
| 11881 | s0 = peg$parseCOHERENT(); | |
| 11882 | if (s0 === peg$FAILED) { | |
| 11883 | s0 = peg$parseVOLATILE(); | |
| 11884 | if (s0 === peg$FAILED) { | |
| 11885 | s0 = peg$parseRESTRICT(); | |
| 11886 | if (s0 === peg$FAILED) { | |
| 11887 | s0 = peg$parseREADONLY(); | |
| 11888 | if (s0 === peg$FAILED) { | |
| 11889 | s0 = peg$parseWRITEONLY(); | |
| 11890 | } | |
| 11891 | } | |
| 11892 | } | |
| 11893 | } | |
| 11894 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11895 | return s0; | |
| 11896 | } | |
| 11897 | function peg$parseinit_declarator_list_statement() { | |
| 11898 | var s0, s1, s2, s3, s4, s5; | |
| 11899 | var key = peg$currPos * 306 + 263; | |
| 11900 | var cached = peg$resultsCache[key]; | |
| 11901 | if (cached) { | |
| 11902 | peg$currPos = cached.nextPos; | |
| 11903 | return cached.result; | |
| 11904 | } | |
| 11905 | s0 = peg$currPos; | |
| 11906 | s1 = peg$parseinitial_declaration(); | |
| 11907 | if (s1 !== peg$FAILED) { | |
| 11908 | s2 = []; | |
| 11909 | s3 = peg$currPos; | |
| 11910 | s4 = peg$parseCOMMA(); | |
| 11911 | if (s4 !== peg$FAILED) { | |
| 11912 | s5 = peg$parsesubsequent_declaration(); | |
| 11913 | if (s5 !== peg$FAILED) { | |
| 11914 | s4 = [s4, s5]; | |
| 11915 | s3 = s4; | |
| 11916 | } else { | |
| 11917 | peg$currPos = s3; | |
| 11918 | s3 = peg$FAILED; | |
| 11919 | } | |
| 11920 | } else { | |
| 11921 | peg$currPos = s3; | |
| 11922 | s3 = peg$FAILED; | |
| 11923 | } | |
| 11924 | while (s3 !== peg$FAILED) { | |
| 11925 | s2.push(s3); | |
| 11926 | s3 = peg$currPos; | |
| 11927 | s4 = peg$parseCOMMA(); | |
| 11928 | if (s4 !== peg$FAILED) { | |
| 11929 | s5 = peg$parsesubsequent_declaration(); | |
| 11930 | if (s5 !== peg$FAILED) { | |
| 11931 | s4 = [s4, s5]; | |
| 11932 | s3 = s4; | |
| 11933 | } else { | |
| 11934 | peg$currPos = s3; | |
| 11935 | s3 = peg$FAILED; | |
| 11936 | } | |
| 11937 | } else { | |
| 11938 | peg$currPos = s3; | |
| 11939 | s3 = peg$FAILED; | |
| 11940 | } | |
| 11941 | } | |
| 11942 | s3 = peg$parseSEMICOLON(); | |
| 11943 | if (s3 !== peg$FAILED) { | |
| 11944 | peg$savedPos = s0; | |
| 11945 | s0 = peg$f36(s1, s2, s3); | |
| 11946 | } else { | |
| 11947 | peg$currPos = s0; | |
| 11948 | s0 = peg$FAILED; | |
| 11949 | } | |
| 11950 | } else { | |
| 11951 | peg$currPos = s0; | |
| 11952 | s0 = peg$FAILED; | |
| 11953 | } | |
| 11954 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11955 | return s0; | |
| 11956 | } | |
| 11957 | function peg$parsesubsequent_declaration() { | |
| 11958 | var s0, s1, s2, s3, s4, s5; | |
| 11959 | var key = peg$currPos * 306 + 264; | |
| 11960 | var cached = peg$resultsCache[key]; | |
| 11961 | if (cached) { | |
| 11962 | peg$currPos = cached.nextPos; | |
| 11963 | return cached.result; | |
| 11964 | } | |
| 11965 | s0 = peg$currPos; | |
| 11966 | s1 = peg$parseIDENTIFIER(); | |
| 11967 | if (s1 !== peg$FAILED) { | |
| 11968 | s2 = peg$parsearray_specifiers(); | |
| 11969 | if (s2 === peg$FAILED) { | |
| 11970 | s2 = null; | |
| 11971 | } | |
| 11972 | s3 = peg$currPos; | |
| 11973 | s4 = peg$parseEQUAL(); | |
| 11974 | if (s4 !== peg$FAILED) { | |
| 11975 | s5 = peg$parseinitializer(); | |
| 11976 | if (s5 !== peg$FAILED) { | |
| 11977 | s4 = [s4, s5]; | |
| 11978 | s3 = s4; | |
| 11979 | } else { | |
| 11980 | peg$currPos = s3; | |
| 11981 | s3 = peg$FAILED; | |
| 11982 | } | |
| 11983 | } else { | |
| 11984 | peg$currPos = s3; | |
| 11985 | s3 = peg$FAILED; | |
| 11986 | } | |
| 11987 | if (s3 === peg$FAILED) { | |
| 11988 | s3 = null; | |
| 11989 | } | |
| 11990 | peg$savedPos = s0; | |
| 11991 | s0 = peg$f37(s1, s2, s3); | |
| 11992 | } else { | |
| 11993 | peg$currPos = s0; | |
| 11994 | s0 = peg$FAILED; | |
| 11995 | } | |
| 11996 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 11997 | return s0; | |
| 11998 | } | |
| 11999 | function peg$parseinitial_declaration() { | |
| 12000 | var s0, s1, s2, s3, s4, s5, s6, s7; | |
| 12001 | var key = peg$currPos * 306 + 265; | |
| 12002 | var cached = peg$resultsCache[key]; | |
| 12003 | if (cached) { | |
| 12004 | peg$currPos = cached.nextPos; | |
| 12005 | return cached.result; | |
| 12006 | } | |
| 12007 | s0 = peg$currPos; | |
| 12008 | s1 = peg$parsefully_specified_type(); | |
| 12009 | if (s1 !== peg$FAILED) { | |
| 12010 | s2 = peg$currPos; | |
| 12011 | s3 = peg$parseIDENTIFIER(); | |
| 12012 | if (s3 !== peg$FAILED) { | |
| 12013 | s4 = peg$parsearray_specifiers(); | |
| 12014 | if (s4 === peg$FAILED) { | |
| 12015 | s4 = null; | |
| 12016 | } | |
| 12017 | s5 = peg$currPos; | |
| 12018 | s6 = peg$parseEQUAL(); | |
| 12019 | if (s6 !== peg$FAILED) { | |
| 12020 | s7 = peg$parseinitializer(); | |
| 12021 | if (s7 !== peg$FAILED) { | |
| 12022 | s6 = [s6, s7]; | |
| 12023 | s5 = s6; | |
| 12024 | } else { | |
| 12025 | peg$currPos = s5; | |
| 12026 | s5 = peg$FAILED; | |
| 12027 | } | |
| 12028 | } else { | |
| 12029 | peg$currPos = s5; | |
| 12030 | s5 = peg$FAILED; | |
| 12031 | } | |
| 12032 | if (s5 === peg$FAILED) { | |
| 12033 | s5 = null; | |
| 12034 | } | |
| 12035 | s3 = [s3, s4, s5]; | |
| 12036 | s2 = s3; | |
| 12037 | } else { | |
| 12038 | peg$currPos = s2; | |
| 12039 | s2 = peg$FAILED; | |
| 12040 | } | |
| 12041 | if (s2 === peg$FAILED) { | |
| 12042 | s2 = null; | |
| 12043 | } | |
| 12044 | peg$savedPos = s0; | |
| 12045 | s0 = peg$f38(s1, s2); | |
| 12046 | } else { | |
| 12047 | peg$currPos = s0; | |
| 12048 | s0 = peg$FAILED; | |
| 12049 | } | |
| 12050 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12051 | return s0; | |
| 12052 | } | |
| 12053 | function peg$parsefully_specified_type() { | |
| 12054 | var s0, s1, s2; | |
| 12055 | var key = peg$currPos * 306 + 266; | |
| 12056 | var cached = peg$resultsCache[key]; | |
| 12057 | if (cached) { | |
| 12058 | peg$currPos = cached.nextPos; | |
| 12059 | return cached.result; | |
| 12060 | } | |
| 12061 | s0 = peg$currPos; | |
| 12062 | s1 = peg$parsetype_qualifiers(); | |
| 12063 | if (s1 === peg$FAILED) { | |
| 12064 | s1 = null; | |
| 12065 | } | |
| 12066 | s2 = peg$parsetype_specifier(); | |
| 12067 | if (s2 !== peg$FAILED) { | |
| 12068 | peg$savedPos = s0; | |
| 12069 | s0 = peg$f39(s1, s2); | |
| 12070 | } else { | |
| 12071 | peg$currPos = s0; | |
| 12072 | s0 = peg$FAILED; | |
| 12073 | } | |
| 12074 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12075 | return s0; | |
| 12076 | } | |
| 12077 | function peg$parselayout_qualifier() { | |
| 12078 | var s0, s1, s2, s3, s4, s5, s6, s7, s8; | |
| 12079 | var key = peg$currPos * 306 + 267; | |
| 12080 | var cached = peg$resultsCache[key]; | |
| 12081 | if (cached) { | |
| 12082 | peg$currPos = cached.nextPos; | |
| 12083 | return cached.result; | |
| 12084 | } | |
| 12085 | s0 = peg$currPos; | |
| 12086 | s1 = peg$parseLAYOUT(); | |
| 12087 | if (s1 !== peg$FAILED) { | |
| 12088 | s2 = peg$parseLEFT_PAREN(); | |
| 12089 | if (s2 !== peg$FAILED) { | |
| 12090 | s3 = peg$currPos; | |
| 12091 | s4 = peg$parselayout_qualifier_id(); | |
| 12092 | if (s4 !== peg$FAILED) { | |
| 12093 | s5 = []; | |
| 12094 | s6 = peg$currPos; | |
| 12095 | s7 = peg$parseCOMMA(); | |
| 12096 | if (s7 !== peg$FAILED) { | |
| 12097 | s8 = peg$parselayout_qualifier_id(); | |
| 12098 | if (s8 !== peg$FAILED) { | |
| 12099 | s7 = [s7, s8]; | |
| 12100 | s6 = s7; | |
| 12101 | } else { | |
| 12102 | peg$currPos = s6; | |
| 12103 | s6 = peg$FAILED; | |
| 12104 | } | |
| 12105 | } else { | |
| 12106 | peg$currPos = s6; | |
| 12107 | s6 = peg$FAILED; | |
| 12108 | } | |
| 12109 | while (s6 !== peg$FAILED) { | |
| 12110 | s5.push(s6); | |
| 12111 | s6 = peg$currPos; | |
| 12112 | s7 = peg$parseCOMMA(); | |
| 12113 | if (s7 !== peg$FAILED) { | |
| 12114 | s8 = peg$parselayout_qualifier_id(); | |
| 12115 | if (s8 !== peg$FAILED) { | |
| 12116 | s7 = [s7, s8]; | |
| 12117 | s6 = s7; | |
| 12118 | } else { | |
| 12119 | peg$currPos = s6; | |
| 12120 | s6 = peg$FAILED; | |
| 12121 | } | |
| 12122 | } else { | |
| 12123 | peg$currPos = s6; | |
| 12124 | s6 = peg$FAILED; | |
| 12125 | } | |
| 12126 | } | |
| 12127 | peg$savedPos = s3; | |
| 12128 | s3 = peg$f40(s1, s2, s4, s5); | |
| 12129 | } else { | |
| 12130 | peg$currPos = s3; | |
| 12131 | s3 = peg$FAILED; | |
| 12132 | } | |
| 12133 | if (s3 !== peg$FAILED) { | |
| 12134 | s4 = peg$parseRIGHT_PAREN(); | |
| 12135 | if (s4 !== peg$FAILED) { | |
| 12136 | peg$savedPos = s0; | |
| 12137 | s0 = peg$f41(s1, s2, s3, s4); | |
| 12138 | } else { | |
| 12139 | peg$currPos = s0; | |
| 12140 | s0 = peg$FAILED; | |
| 12141 | } | |
| 12142 | } else { | |
| 12143 | peg$currPos = s0; | |
| 12144 | s0 = peg$FAILED; | |
| 12145 | } | |
| 12146 | } else { | |
| 12147 | peg$currPos = s0; | |
| 12148 | s0 = peg$FAILED; | |
| 12149 | } | |
| 12150 | } else { | |
| 12151 | peg$currPos = s0; | |
| 12152 | s0 = peg$FAILED; | |
| 12153 | } | |
| 12154 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12155 | return s0; | |
| 12156 | } | |
| 12157 | function peg$parselayout_qualifier_id() { | |
| 12158 | var s0, s1, s2, s3, s4; | |
| 12159 | var key = peg$currPos * 306 + 268; | |
| 12160 | var cached = peg$resultsCache[key]; | |
| 12161 | if (cached) { | |
| 12162 | peg$currPos = cached.nextPos; | |
| 12163 | return cached.result; | |
| 12164 | } | |
| 12165 | s0 = peg$currPos; | |
| 12166 | s1 = peg$parseIDENTIFIER(); | |
| 12167 | if (s1 !== peg$FAILED) { | |
| 12168 | s2 = peg$currPos; | |
| 12169 | s3 = peg$parseEQUAL(); | |
| 12170 | if (s3 !== peg$FAILED) { | |
| 12171 | s4 = peg$parseternary_expression(); | |
| 12172 | if (s4 !== peg$FAILED) { | |
| 12173 | s3 = [s3, s4]; | |
| 12174 | s2 = s3; | |
| 12175 | } else { | |
| 12176 | peg$currPos = s2; | |
| 12177 | s2 = peg$FAILED; | |
| 12178 | } | |
| 12179 | } else { | |
| 12180 | peg$currPos = s2; | |
| 12181 | s2 = peg$FAILED; | |
| 12182 | } | |
| 12183 | if (s2 === peg$FAILED) { | |
| 12184 | s2 = null; | |
| 12185 | } | |
| 12186 | peg$savedPos = s0; | |
| 12187 | s0 = peg$f42(s1, s2); | |
| 12188 | } else { | |
| 12189 | peg$currPos = s0; | |
| 12190 | s0 = peg$FAILED; | |
| 12191 | } | |
| 12192 | if (s0 === peg$FAILED) { | |
| 12193 | s0 = peg$parseSHARED(); | |
| 12194 | } | |
| 12195 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12196 | return s0; | |
| 12197 | } | |
| 12198 | function peg$parsetype_qualifiers() { | |
| 12199 | var s0, s1; | |
| 12200 | var key = peg$currPos * 306 + 269; | |
| 12201 | var cached = peg$resultsCache[key]; | |
| 12202 | if (cached) { | |
| 12203 | peg$currPos = cached.nextPos; | |
| 12204 | return cached.result; | |
| 12205 | } | |
| 12206 | s0 = []; | |
| 12207 | s1 = peg$parsesingle_type_qualifier(); | |
| 12208 | if (s1 !== peg$FAILED) { | |
| 12209 | while (s1 !== peg$FAILED) { | |
| 12210 | s0.push(s1); | |
| 12211 | s1 = peg$parsesingle_type_qualifier(); | |
| 12212 | } | |
| 12213 | } else { | |
| 12214 | s0 = peg$FAILED; | |
| 12215 | } | |
| 12216 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12217 | return s0; | |
| 12218 | } | |
| 12219 | function peg$parsesingle_type_qualifier() { | |
| 12220 | var s0, s1; | |
| 12221 | var key = peg$currPos * 306 + 270; | |
| 12222 | var cached = peg$resultsCache[key]; | |
| 12223 | if (cached) { | |
| 12224 | peg$currPos = cached.nextPos; | |
| 12225 | return cached.result; | |
| 12226 | } | |
| 12227 | peg$silentFails++; | |
| 12228 | s0 = peg$parsestorage_qualifier(); | |
| 12229 | if (s0 === peg$FAILED) { | |
| 12230 | s0 = peg$parselayout_qualifier(); | |
| 12231 | if (s0 === peg$FAILED) { | |
| 12232 | s0 = peg$parseprecision_qualifier(); | |
| 12233 | if (s0 === peg$FAILED) { | |
| 12234 | s0 = peg$parseinterpolation_qualifier(); | |
| 12235 | if (s0 === peg$FAILED) { | |
| 12236 | s0 = peg$parseINVARIANT(); | |
| 12237 | if (s0 === peg$FAILED) { | |
| 12238 | s0 = peg$parsePRECISE(); | |
| 12239 | } | |
| 12240 | } | |
| 12241 | } | |
| 12242 | } | |
| 12243 | } | |
| 12244 | peg$silentFails--; | |
| 12245 | if (s0 === peg$FAILED) { | |
| 12246 | s1 = peg$FAILED; | |
| 12247 | if (peg$silentFails === 0) { | |
| 12248 | peg$fail(peg$e236); | |
| 12249 | } | |
| 12250 | } | |
| 12251 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12252 | return s0; | |
| 12253 | } | |
| 12254 | function peg$parseinterpolation_qualifier() { | |
| 12255 | var s0, s1; | |
| 12256 | var key = peg$currPos * 306 + 271; | |
| 12257 | var cached = peg$resultsCache[key]; | |
| 12258 | if (cached) { | |
| 12259 | peg$currPos = cached.nextPos; | |
| 12260 | return cached.result; | |
| 12261 | } | |
| 12262 | peg$silentFails++; | |
| 12263 | s0 = peg$parseSMOOTH(); | |
| 12264 | if (s0 === peg$FAILED) { | |
| 12265 | s0 = peg$parseFLAT(); | |
| 12266 | if (s0 === peg$FAILED) { | |
| 12267 | s0 = peg$parseNOPERSPECTIVE(); | |
| 12268 | } | |
| 12269 | } | |
| 12270 | peg$silentFails--; | |
| 12271 | if (s0 === peg$FAILED) { | |
| 12272 | s1 = peg$FAILED; | |
| 12273 | if (peg$silentFails === 0) { | |
| 12274 | peg$fail(peg$e237); | |
| 12275 | } | |
| 12276 | } | |
| 12277 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12278 | return s0; | |
| 12279 | } | |
| 12280 | function peg$parsestorage_qualifier() { | |
| 12281 | var s0, s1, s2, s3, s4, s5, s6, s7, s8; | |
| 12282 | var key = peg$currPos * 306 + 272; | |
| 12283 | var cached = peg$resultsCache[key]; | |
| 12284 | if (cached) { | |
| 12285 | peg$currPos = cached.nextPos; | |
| 12286 | return cached.result; | |
| 12287 | } | |
| 12288 | peg$silentFails++; | |
| 12289 | s0 = peg$parseCONST(); | |
| 12290 | if (s0 === peg$FAILED) { | |
| 12291 | s0 = peg$parseINOUT(); | |
| 12292 | if (s0 === peg$FAILED) { | |
| 12293 | s0 = peg$parseIN(); | |
| 12294 | if (s0 === peg$FAILED) { | |
| 12295 | s0 = peg$parseOUT(); | |
| 12296 | if (s0 === peg$FAILED) { | |
| 12297 | s0 = peg$parseCENTROID(); | |
| 12298 | if (s0 === peg$FAILED) { | |
| 12299 | s0 = peg$parsePATCH(); | |
| 12300 | if (s0 === peg$FAILED) { | |
| 12301 | s0 = peg$parseSAMPLE(); | |
| 12302 | if (s0 === peg$FAILED) { | |
| 12303 | s0 = peg$parseUNIFORM(); | |
| 12304 | if (s0 === peg$FAILED) { | |
| 12305 | s0 = peg$parseBUFFER(); | |
| 12306 | if (s0 === peg$FAILED) { | |
| 12307 | s0 = peg$parseSHARED(); | |
| 12308 | if (s0 === peg$FAILED) { | |
| 12309 | s0 = peg$parseCOHERENT(); | |
| 12310 | if (s0 === peg$FAILED) { | |
| 12311 | s0 = peg$parseVOLATILE(); | |
| 12312 | if (s0 === peg$FAILED) { | |
| 12313 | s0 = peg$parseRESTRICT(); | |
| 12314 | if (s0 === peg$FAILED) { | |
| 12315 | s0 = peg$parseREADONLY(); | |
| 12316 | if (s0 === peg$FAILED) { | |
| 12317 | s0 = peg$parseWRITEONLY(); | |
| 12318 | if (s0 === peg$FAILED) { | |
| 12319 | s0 = peg$parseVARYING(); | |
| 12320 | if (s0 === peg$FAILED) { | |
| 12321 | s0 = peg$parseATTRIBUTE(); | |
| 12322 | if (s0 === peg$FAILED) { | |
| 12323 | s0 = peg$currPos; | |
| 12324 | s1 = peg$parseSUBROUTINE(); | |
| 12325 | if (s1 !== peg$FAILED) { | |
| 12326 | s2 = peg$currPos; | |
| 12327 | s3 = peg$parseLEFT_PAREN(); | |
| 12328 | if (s3 !== peg$FAILED) { | |
| 12329 | s4 = peg$parseTYPE_NAME(); | |
| 12330 | if (s4 !== peg$FAILED) { | |
| 12331 | s5 = []; | |
| 12332 | s6 = peg$currPos; | |
| 12333 | s7 = peg$parseCOMMA(); | |
| 12334 | if (s7 !== peg$FAILED) { | |
| 12335 | s8 = peg$parseTYPE_NAME(); | |
| 12336 | if (s8 !== peg$FAILED) { | |
| 12337 | s7 = [s7, s8]; | |
| 12338 | s6 = s7; | |
| 12339 | } else { | |
| 12340 | peg$currPos = s6; | |
| 12341 | s6 = peg$FAILED; | |
| 12342 | } | |
| 12343 | } else { | |
| 12344 | peg$currPos = s6; | |
| 12345 | s6 = peg$FAILED; | |
| 12346 | } | |
| 12347 | while (s6 !== peg$FAILED) { | |
| 12348 | s5.push(s6); | |
| 12349 | s6 = peg$currPos; | |
| 12350 | s7 = peg$parseCOMMA(); | |
| 12351 | if (s7 !== peg$FAILED) { | |
| 12352 | s8 = peg$parseTYPE_NAME(); | |
| 12353 | if (s8 !== peg$FAILED) { | |
| 12354 | s7 = [s7, s8]; | |
| 12355 | s6 = s7; | |
| 12356 | } else { | |
| 12357 | peg$currPos = s6; | |
| 12358 | s6 = peg$FAILED; | |
| 12359 | } | |
| 12360 | } else { | |
| 12361 | peg$currPos = s6; | |
| 12362 | s6 = peg$FAILED; | |
| 12363 | } | |
| 12364 | } | |
| 12365 | s6 = peg$parseRIGHT_PAREN(); | |
| 12366 | if (s6 !== peg$FAILED) { | |
| 12367 | peg$savedPos = s2; | |
| 12368 | s2 = peg$f43(s1, s3, s4, s5, s6); | |
| 12369 | } else { | |
| 12370 | peg$currPos = s2; | |
| 12371 | s2 = peg$FAILED; | |
| 12372 | } | |
| 12373 | } else { | |
| 12374 | peg$currPos = s2; | |
| 12375 | s2 = peg$FAILED; | |
| 12376 | } | |
| 12377 | } else { | |
| 12378 | peg$currPos = s2; | |
| 12379 | s2 = peg$FAILED; | |
| 12380 | } | |
| 12381 | if (s2 === peg$FAILED) { | |
| 12382 | s2 = null; | |
| 12383 | } | |
| 12384 | peg$savedPos = s0; | |
| 12385 | s0 = peg$f44(s1, s2); | |
| 12386 | } else { | |
| 12387 | peg$currPos = s0; | |
| 12388 | s0 = peg$FAILED; | |
| 12389 | } | |
| 12390 | } | |
| 12391 | } | |
| 12392 | } | |
| 12393 | } | |
| 12394 | } | |
| 12395 | } | |
| 12396 | } | |
| 12397 | } | |
| 12398 | } | |
| 12399 | } | |
| 12400 | } | |
| 12401 | } | |
| 12402 | } | |
| 12403 | } | |
| 12404 | } | |
| 12405 | } | |
| 12406 | } | |
| 12407 | peg$silentFails--; | |
| 12408 | if (s0 === peg$FAILED) { | |
| 12409 | s1 = peg$FAILED; | |
| 12410 | if (peg$silentFails === 0) { | |
| 12411 | peg$fail(peg$e238); | |
| 12412 | } | |
| 12413 | } | |
| 12414 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12415 | return s0; | |
| 12416 | } | |
| 12417 | function peg$parsetype_specifier() { | |
| 12418 | var s0, s1, s2; | |
| 12419 | var key = peg$currPos * 306 + 273; | |
| 12420 | var cached = peg$resultsCache[key]; | |
| 12421 | if (cached) { | |
| 12422 | peg$currPos = cached.nextPos; | |
| 12423 | return cached.result; | |
| 12424 | } | |
| 12425 | peg$silentFails++; | |
| 12426 | s0 = peg$currPos; | |
| 12427 | s1 = peg$parsetype_specifier_nonarray(); | |
| 12428 | if (s1 !== peg$FAILED) { | |
| 12429 | s2 = peg$parsearray_specifiers(); | |
| 12430 | if (s2 === peg$FAILED) { | |
| 12431 | s2 = null; | |
| 12432 | } | |
| 12433 | peg$savedPos = s0; | |
| 12434 | s0 = peg$f45(s1, s2); | |
| 12435 | } else { | |
| 12436 | peg$currPos = s0; | |
| 12437 | s0 = peg$FAILED; | |
| 12438 | } | |
| 12439 | peg$silentFails--; | |
| 12440 | if (s0 === peg$FAILED) { | |
| 12441 | s1 = peg$FAILED; | |
| 12442 | if (peg$silentFails === 0) { | |
| 12443 | peg$fail(peg$e239); | |
| 12444 | } | |
| 12445 | } | |
| 12446 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12447 | return s0; | |
| 12448 | } | |
| 12449 | function peg$parsetype_specifier_nonarray() { | |
| 12450 | var s0, s1; | |
| 12451 | var key = peg$currPos * 306 + 274; | |
| 12452 | var cached = peg$resultsCache[key]; | |
| 12453 | if (cached) { | |
| 12454 | peg$currPos = cached.nextPos; | |
| 12455 | return cached.result; | |
| 12456 | } | |
| 12457 | peg$silentFails++; | |
| 12458 | s0 = peg$parseVOID(); | |
| 12459 | if (s0 === peg$FAILED) { | |
| 12460 | s0 = peg$parseFLOAT(); | |
| 12461 | if (s0 === peg$FAILED) { | |
| 12462 | s0 = peg$parseDOUBLE(); | |
| 12463 | if (s0 === peg$FAILED) { | |
| 12464 | s0 = peg$parseINT(); | |
| 12465 | if (s0 === peg$FAILED) { | |
| 12466 | s0 = peg$parseUINT(); | |
| 12467 | if (s0 === peg$FAILED) { | |
| 12468 | s0 = peg$parseBOOL(); | |
| 12469 | if (s0 === peg$FAILED) { | |
| 12470 | s0 = peg$parseVEC2(); | |
| 12471 | if (s0 === peg$FAILED) { | |
| 12472 | s0 = peg$parseVEC3(); | |
| 12473 | if (s0 === peg$FAILED) { | |
| 12474 | s0 = peg$parseVEC4(); | |
| 12475 | if (s0 === peg$FAILED) { | |
| 12476 | s0 = peg$parseDVEC2(); | |
| 12477 | if (s0 === peg$FAILED) { | |
| 12478 | s0 = peg$parseDVEC3(); | |
| 12479 | if (s0 === peg$FAILED) { | |
| 12480 | s0 = peg$parseDVEC4(); | |
| 12481 | if (s0 === peg$FAILED) { | |
| 12482 | s0 = peg$parseBVEC2(); | |
| 12483 | if (s0 === peg$FAILED) { | |
| 12484 | s0 = peg$parseBVEC3(); | |
| 12485 | if (s0 === peg$FAILED) { | |
| 12486 | s0 = peg$parseBVEC4(); | |
| 12487 | if (s0 === peg$FAILED) { | |
| 12488 | s0 = peg$parseIVEC2(); | |
| 12489 | if (s0 === peg$FAILED) { | |
| 12490 | s0 = peg$parseIVEC3(); | |
| 12491 | if (s0 === peg$FAILED) { | |
| 12492 | s0 = peg$parseIVEC4(); | |
| 12493 | if (s0 === peg$FAILED) { | |
| 12494 | s0 = peg$parseUVEC2(); | |
| 12495 | if (s0 === peg$FAILED) { | |
| 12496 | s0 = peg$parseUVEC3(); | |
| 12497 | if (s0 === peg$FAILED) { | |
| 12498 | s0 = peg$parseUVEC4(); | |
| 12499 | if (s0 === peg$FAILED) { | |
| 12500 | s0 = peg$parseMAT2(); | |
| 12501 | if (s0 === peg$FAILED) { | |
| 12502 | s0 = peg$parseMAT3(); | |
| 12503 | if (s0 === peg$FAILED) { | |
| 12504 | s0 = peg$parseMAT4(); | |
| 12505 | if (s0 === peg$FAILED) { | |
| 12506 | s0 = peg$parseMAT2X2(); | |
| 12507 | if (s0 === peg$FAILED) { | |
| 12508 | s0 = peg$parseMAT2X3(); | |
| 12509 | if (s0 === peg$FAILED) { | |
| 12510 | s0 = peg$parseMAT2X4(); | |
| 12511 | if (s0 === peg$FAILED) { | |
| 12512 | s0 = peg$parseMAT3X2(); | |
| 12513 | if (s0 === peg$FAILED) { | |
| 12514 | s0 = peg$parseMAT3X3(); | |
| 12515 | if (s0 === peg$FAILED) { | |
| 12516 | s0 = peg$parseMAT3X4(); | |
| 12517 | if (s0 === peg$FAILED) { | |
| 12518 | s0 = peg$parseMAT4X2(); | |
| 12519 | if (s0 === peg$FAILED) { | |
| 12520 | s0 = peg$parseMAT4X3(); | |
| 12521 | if (s0 === peg$FAILED) { | |
| 12522 | s0 = peg$parseMAT4X4(); | |
| 12523 | if (s0 === peg$FAILED) { | |
| 12524 | s0 = peg$parseDMAT2(); | |
| 12525 | if (s0 === peg$FAILED) { | |
| 12526 | s0 = peg$parseDMAT3(); | |
| 12527 | if (s0 === peg$FAILED) { | |
| 12528 | s0 = peg$parseDMAT4(); | |
| 12529 | if (s0 === peg$FAILED) { | |
| 12530 | s0 = peg$parseDMAT2X2(); | |
| 12531 | if (s0 === peg$FAILED) { | |
| 12532 | s0 = peg$parseDMAT2X3(); | |
| 12533 | if (s0 === peg$FAILED) { | |
| 12534 | s0 = peg$parseDMAT2X4(); | |
| 12535 | if (s0 === peg$FAILED) { | |
| 12536 | s0 = peg$parseDMAT3X2(); | |
| 12537 | if (s0 === peg$FAILED) { | |
| 12538 | s0 = peg$parseDMAT3X3(); | |
| 12539 | if (s0 === peg$FAILED) { | |
| 12540 | s0 = peg$parseDMAT3X4(); | |
| 12541 | if (s0 === peg$FAILED) { | |
| 12542 | s0 = peg$parseDMAT4X2(); | |
| 12543 | if (s0 === peg$FAILED) { | |
| 12544 | s0 = peg$parseDMAT4X3(); | |
| 12545 | if (s0 === peg$FAILED) { | |
| 12546 | s0 = peg$parseDMAT4X4(); | |
| 12547 | if (s0 === peg$FAILED) { | |
| 12548 | s0 = peg$parseATOMIC_UINT(); | |
| 12549 | if (s0 === peg$FAILED) { | |
| 12550 | s0 = peg$parseSAMPLER1D(); | |
| 12551 | if (s0 === peg$FAILED) { | |
| 12552 | s0 = peg$parseSAMPLER2D(); | |
| 12553 | if (s0 === peg$FAILED) { | |
| 12554 | s0 = peg$parseSAMPLER3D(); | |
| 12555 | if (s0 === peg$FAILED) { | |
| 12556 | s0 = peg$parseSAMPLERCUBE(); | |
| 12557 | if (s0 === peg$FAILED) { | |
| 12558 | s0 = peg$parseSAMPLER1DSHADOW(); | |
| 12559 | if (s0 === peg$FAILED) { | |
| 12560 | s0 = peg$parseSAMPLER2DSHADOW(); | |
| 12561 | if (s0 === peg$FAILED) { | |
| 12562 | s0 = peg$parseSAMPLERCUBESHADOW(); | |
| 12563 | if (s0 === peg$FAILED) { | |
| 12564 | s0 = peg$parseSAMPLER1DARRAY(); | |
| 12565 | if (s0 === peg$FAILED) { | |
| 12566 | s0 = peg$parseSAMPLER2DARRAY(); | |
| 12567 | if (s0 === peg$FAILED) { | |
| 12568 | s0 = peg$parseSAMPLER1DARRAYSHADOW(); | |
| 12569 | if (s0 === peg$FAILED) { | |
| 12570 | s0 = peg$parseSAMPLER2DARRAYSHADOW(); | |
| 12571 | if (s0 === peg$FAILED) { | |
| 12572 | s0 = peg$parseSAMPLERCUBEARRAY(); | |
| 12573 | if (s0 === peg$FAILED) { | |
| 12574 | s0 = peg$parseSAMPLERCUBEARRAYSHADOW(); | |
| 12575 | if (s0 === peg$FAILED) { | |
| 12576 | s0 = peg$parseISAMPLER1D(); | |
| 12577 | if (s0 === peg$FAILED) { | |
| 12578 | s0 = peg$parseISAMPLER2D(); | |
| 12579 | if (s0 === peg$FAILED) { | |
| 12580 | s0 = peg$parseISAMPLER3D(); | |
| 12581 | if (s0 === peg$FAILED) { | |
| 12582 | s0 = peg$parseISAMPLERCUBE(); | |
| 12583 | if (s0 === peg$FAILED) { | |
| 12584 | s0 = peg$parseISAMPLER1DARRAY(); | |
| 12585 | if (s0 === peg$FAILED) { | |
| 12586 | s0 = peg$parseISAMPLER2DARRAY(); | |
| 12587 | if (s0 === peg$FAILED) { | |
| 12588 | s0 = peg$parseISAMPLERCUBEARRAY(); | |
| 12589 | if (s0 === peg$FAILED) { | |
| 12590 | s0 = peg$parseUSAMPLER1D(); | |
| 12591 | if (s0 === peg$FAILED) { | |
| 12592 | s0 = peg$parseUSAMPLER2D(); | |
| 12593 | if (s0 === peg$FAILED) { | |
| 12594 | s0 = peg$parseUSAMPLER3D(); | |
| 12595 | if (s0 === peg$FAILED) { | |
| 12596 | s0 = peg$parseUSAMPLERCUBE(); | |
| 12597 | if (s0 === peg$FAILED) { | |
| 12598 | s0 = peg$parseUSAMPLER1DARRAY(); | |
| 12599 | if (s0 === peg$FAILED) { | |
| 12600 | s0 = peg$parseUSAMPLER2DARRAY(); | |
| 12601 | if (s0 === peg$FAILED) { | |
| 12602 | s0 = peg$parseUSAMPLERCUBEARRAY(); | |
| 12603 | if (s0 === peg$FAILED) { | |
| 12604 | s0 = peg$parseSAMPLER2DRECT(); | |
| 12605 | if (s0 === peg$FAILED) { | |
| 12606 | s0 = peg$parseSAMPLER2DRECTSHADOW(); | |
| 12607 | if (s0 === peg$FAILED) { | |
| 12608 | s0 = peg$parseISAMPLER2DRECT(); | |
| 12609 | if (s0 === peg$FAILED) { | |
| 12610 | s0 = peg$parseUSAMPLER2DRECT(); | |
| 12611 | if (s0 === peg$FAILED) { | |
| 12612 | s0 = peg$parseSAMPLERBUFFER(); | |
| 12613 | if (s0 === peg$FAILED) { | |
| 12614 | s0 = peg$parseISAMPLERBUFFER(); | |
| 12615 | if (s0 === peg$FAILED) { | |
| 12616 | s0 = peg$parseUSAMPLERBUFFER(); | |
| 12617 | if (s0 === peg$FAILED) { | |
| 12618 | s0 = peg$parseSAMPLER2DMS(); | |
| 12619 | if (s0 === peg$FAILED) { | |
| 12620 | s0 = peg$parseISAMPLER2DMS(); | |
| 12621 | if (s0 === peg$FAILED) { | |
| 12622 | s0 = peg$parseUSAMPLER2DMS(); | |
| 12623 | if (s0 === peg$FAILED) { | |
| 12624 | s0 = peg$parseSAMPLER2DMSARRAY(); | |
| 12625 | if (s0 === peg$FAILED) { | |
| 12626 | s0 = peg$parseISAMPLER2DMSARRAY(); | |
| 12627 | if (s0 === peg$FAILED) { | |
| 12628 | s0 = peg$parseUSAMPLER2DMSARRAY(); | |
| 12629 | if (s0 === peg$FAILED) { | |
| 12630 | s0 = peg$parseIMAGE1D(); | |
| 12631 | if (s0 === peg$FAILED) { | |
| 12632 | s0 = peg$parseIIMAGE1D(); | |
| 12633 | if (s0 === peg$FAILED) { | |
| 12634 | s0 = peg$parseUIMAGE1D(); | |
| 12635 | if (s0 === peg$FAILED) { | |
| 12636 | s0 = peg$parseIMAGE2D(); | |
| 12637 | if (s0 === peg$FAILED) { | |
| 12638 | s0 = peg$parseIIMAGE2D(); | |
| 12639 | if (s0 === peg$FAILED) { | |
| 12640 | s0 = peg$parseUIMAGE2D(); | |
| 12641 | if (s0 === peg$FAILED) { | |
| 12642 | s0 = peg$parseIMAGE3D(); | |
| 12643 | if (s0 === peg$FAILED) { | |
| 12644 | s0 = peg$parseIIMAGE3D(); | |
| 12645 | if (s0 === peg$FAILED) { | |
| 12646 | s0 = peg$parseUIMAGE3D(); | |
| 12647 | if (s0 === peg$FAILED) { | |
| 12648 | s0 = peg$parseIMAGE2DRECT(); | |
| 12649 | if (s0 === peg$FAILED) { | |
| 12650 | s0 = peg$parseIIMAGE2DRECT(); | |
| 12651 | if (s0 === peg$FAILED) { | |
| 12652 | s0 = peg$parseUIMAGE2DRECT(); | |
| 12653 | if (s0 === peg$FAILED) { | |
| 12654 | s0 = peg$parseIMAGECUBE(); | |
| 12655 | if (s0 === peg$FAILED) { | |
| 12656 | s0 = peg$parseIIMAGECUBE(); | |
| 12657 | if (s0 === peg$FAILED) { | |
| 12658 | s0 = peg$parseUIMAGECUBE(); | |
| 12659 | if (s0 === peg$FAILED) { | |
| 12660 | s0 = peg$parseIMAGEBUFFER(); | |
| 12661 | if (s0 === peg$FAILED) { | |
| 12662 | s0 = peg$parseIIMAGEBUFFER(); | |
| 12663 | if (s0 === peg$FAILED) { | |
| 12664 | s0 = peg$parseUIMAGEBUFFER(); | |
| 12665 | if (s0 === peg$FAILED) { | |
| 12666 | s0 = peg$parseIMAGE1DARRAY(); | |
| 12667 | if (s0 === peg$FAILED) { | |
| 12668 | s0 = peg$parseIIMAGE1DARRAY(); | |
| 12669 | if (s0 === peg$FAILED) { | |
| 12670 | s0 = peg$parseUIMAGE1DARRAY(); | |
| 12671 | if (s0 === peg$FAILED) { | |
| 12672 | s0 = peg$parseIMAGE2DARRAY(); | |
| 12673 | if (s0 === peg$FAILED) { | |
| 12674 | s0 = peg$parseIIMAGE2DARRAY(); | |
| 12675 | if (s0 === peg$FAILED) { | |
| 12676 | s0 = peg$parseUIMAGE2DARRAY(); | |
| 12677 | if (s0 === peg$FAILED) { | |
| 12678 | s0 = peg$parseIMAGECUBEARRAY(); | |
| 12679 | if (s0 === peg$FAILED) { | |
| 12680 | s0 = peg$parseIIMAGECUBEARRAY(); | |
| 12681 | if (s0 === peg$FAILED) { | |
| 12682 | s0 = peg$parseUIMAGECUBEARRAY(); | |
| 12683 | if (s0 === peg$FAILED) { | |
| 12684 | s0 = peg$parseIMAGE2DMS(); | |
| 12685 | if (s0 === peg$FAILED) { | |
| 12686 | s0 = peg$parseIIMAGE2DMS(); | |
| 12687 | if (s0 === peg$FAILED) { | |
| 12688 | s0 = peg$parseUIMAGE2DMS(); | |
| 12689 | if (s0 === peg$FAILED) { | |
| 12690 | s0 = peg$parseIMAGE2DMSARRAY(); | |
| 12691 | if (s0 === peg$FAILED) { | |
| 12692 | s0 = peg$parseIIMAGE2DMSARRAY(); | |
| 12693 | if (s0 === peg$FAILED) { | |
| 12694 | s0 = peg$parseUIMAGE2DMSARRAY(); | |
| 12695 | if (s0 === peg$FAILED) { | |
| 12696 | s0 = peg$parsestruct_specifier(); | |
| 12697 | if (s0 === peg$FAILED) { | |
| 12698 | s0 = peg$parseTYPE_NAME(); | |
| 12699 | } | |
| 12700 | } | |
| 12701 | } | |
| 12702 | } | |
| 12703 | } | |
| 12704 | } | |
| 12705 | } | |
| 12706 | } | |
| 12707 | } | |
| 12708 | } | |
| 12709 | } | |
| 12710 | } | |
| 12711 | } | |
| 12712 | } | |
| 12713 | } | |
| 12714 | } | |
| 12715 | } | |
| 12716 | } | |
| 12717 | } | |
| 12718 | } | |
| 12719 | } | |
| 12720 | } | |
| 12721 | } | |
| 12722 | } | |
| 12723 | } | |
| 12724 | } | |
| 12725 | } | |
| 12726 | } | |
| 12727 | } | |
| 12728 | } | |
| 12729 | } | |
| 12730 | } | |
| 12731 | } | |
| 12732 | } | |
| 12733 | } | |
| 12734 | } | |
| 12735 | } | |
| 12736 | } | |
| 12737 | } | |
| 12738 | } | |
| 12739 | } | |
| 12740 | } | |
| 12741 | } | |
| 12742 | } | |
| 12743 | } | |
| 12744 | } | |
| 12745 | } | |
| 12746 | } | |
| 12747 | } | |
| 12748 | } | |
| 12749 | } | |
| 12750 | } | |
| 12751 | } | |
| 12752 | } | |
| 12753 | } | |
| 12754 | } | |
| 12755 | } | |
| 12756 | } | |
| 12757 | } | |
| 12758 | } | |
| 12759 | } | |
| 12760 | } | |
| 12761 | } | |
| 12762 | } | |
| 12763 | } | |
| 12764 | } | |
| 12765 | } | |
| 12766 | } | |
| 12767 | } | |
| 12768 | } | |
| 12769 | } | |
| 12770 | } | |
| 12771 | } | |
| 12772 | } | |
| 12773 | } | |
| 12774 | } | |
| 12775 | } | |
| 12776 | } | |
| 12777 | } | |
| 12778 | } | |
| 12779 | } | |
| 12780 | } | |
| 12781 | } | |
| 12782 | } | |
| 12783 | } | |
| 12784 | } | |
| 12785 | } | |
| 12786 | } | |
| 12787 | } | |
| 12788 | } | |
| 12789 | } | |
| 12790 | } | |
| 12791 | } | |
| 12792 | } | |
| 12793 | } | |
| 12794 | } | |
| 12795 | } | |
| 12796 | } | |
| 12797 | } | |
| 12798 | } | |
| 12799 | } | |
| 12800 | } | |
| 12801 | } | |
| 12802 | } | |
| 12803 | } | |
| 12804 | } | |
| 12805 | } | |
| 12806 | } | |
| 12807 | } | |
| 12808 | } | |
| 12809 | } | |
| 12810 | } | |
| 12811 | } | |
| 12812 | } | |
| 12813 | } | |
| 12814 | } | |
| 12815 | } | |
| 12816 | } | |
| 12817 | } | |
| 12818 | } | |
| 12819 | peg$silentFails--; | |
| 12820 | if (s0 === peg$FAILED) { | |
| 12821 | s1 = peg$FAILED; | |
| 12822 | if (peg$silentFails === 0) { | |
| 12823 | peg$fail(peg$e239); | |
| 12824 | } | |
| 12825 | } | |
| 12826 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12827 | return s0; | |
| 12828 | } | |
| 12829 | function peg$parsearray_specifiers() { | |
| 12830 | var s0, s1, s2, s3, s4, s5; | |
| 12831 | var key = peg$currPos * 306 + 275; | |
| 12832 | var cached = peg$resultsCache[key]; | |
| 12833 | if (cached) { | |
| 12834 | peg$currPos = cached.nextPos; | |
| 12835 | return cached.result; | |
| 12836 | } | |
| 12837 | peg$silentFails++; | |
| 12838 | s0 = peg$currPos; | |
| 12839 | s1 = []; | |
| 12840 | s2 = peg$currPos; | |
| 12841 | s3 = peg$parseLEFT_BRACKET(); | |
| 12842 | if (s3 !== peg$FAILED) { | |
| 12843 | s4 = peg$parseternary_expression(); | |
| 12844 | if (s4 === peg$FAILED) { | |
| 12845 | s4 = null; | |
| 12846 | } | |
| 12847 | s5 = peg$parseRIGHT_BRACKET(); | |
| 12848 | if (s5 !== peg$FAILED) { | |
| 12849 | peg$savedPos = s2; | |
| 12850 | s2 = peg$f46(s3, s4, s5); | |
| 12851 | } else { | |
| 12852 | peg$currPos = s2; | |
| 12853 | s2 = peg$FAILED; | |
| 12854 | } | |
| 12855 | } else { | |
| 12856 | peg$currPos = s2; | |
| 12857 | s2 = peg$FAILED; | |
| 12858 | } | |
| 12859 | if (s2 !== peg$FAILED) { | |
| 12860 | while (s2 !== peg$FAILED) { | |
| 12861 | s1.push(s2); | |
| 12862 | s2 = peg$currPos; | |
| 12863 | s3 = peg$parseLEFT_BRACKET(); | |
| 12864 | if (s3 !== peg$FAILED) { | |
| 12865 | s4 = peg$parseternary_expression(); | |
| 12866 | if (s4 === peg$FAILED) { | |
| 12867 | s4 = null; | |
| 12868 | } | |
| 12869 | s5 = peg$parseRIGHT_BRACKET(); | |
| 12870 | if (s5 !== peg$FAILED) { | |
| 12871 | peg$savedPos = s2; | |
| 12872 | s2 = peg$f46(s3, s4, s5); | |
| 12873 | } else { | |
| 12874 | peg$currPos = s2; | |
| 12875 | s2 = peg$FAILED; | |
| 12876 | } | |
| 12877 | } else { | |
| 12878 | peg$currPos = s2; | |
| 12879 | s2 = peg$FAILED; | |
| 12880 | } | |
| 12881 | } | |
| 12882 | } else { | |
| 12883 | s1 = peg$FAILED; | |
| 12884 | } | |
| 12885 | if (s1 !== peg$FAILED) { | |
| 12886 | peg$savedPos = s0; | |
| 12887 | s1 = peg$f47(s1); | |
| 12888 | } | |
| 12889 | s0 = s1; | |
| 12890 | peg$silentFails--; | |
| 12891 | if (s0 === peg$FAILED) { | |
| 12892 | s1 = peg$FAILED; | |
| 12893 | if (peg$silentFails === 0) { | |
| 12894 | peg$fail(peg$e240); | |
| 12895 | } | |
| 12896 | } | |
| 12897 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12898 | return s0; | |
| 12899 | } | |
| 12900 | function peg$parseprecision_qualifier() { | |
| 12901 | var s0, s1; | |
| 12902 | var key = peg$currPos * 306 + 276; | |
| 12903 | var cached = peg$resultsCache[key]; | |
| 12904 | if (cached) { | |
| 12905 | peg$currPos = cached.nextPos; | |
| 12906 | return cached.result; | |
| 12907 | } | |
| 12908 | peg$silentFails++; | |
| 12909 | s0 = peg$parseHIGH_PRECISION(); | |
| 12910 | if (s0 === peg$FAILED) { | |
| 12911 | s0 = peg$parseMEDIUM_PRECISION(); | |
| 12912 | if (s0 === peg$FAILED) { | |
| 12913 | s0 = peg$parseLOW_PRECISION(); | |
| 12914 | } | |
| 12915 | } | |
| 12916 | peg$silentFails--; | |
| 12917 | if (s0 === peg$FAILED) { | |
| 12918 | s1 = peg$FAILED; | |
| 12919 | if (peg$silentFails === 0) { | |
| 12920 | peg$fail(peg$e241); | |
| 12921 | } | |
| 12922 | } | |
| 12923 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12924 | return s0; | |
| 12925 | } | |
| 12926 | function peg$parsestruct_specifier() { | |
| 12927 | var s0, s1, s2, s3, s4, s5; | |
| 12928 | var key = peg$currPos * 306 + 277; | |
| 12929 | var cached = peg$resultsCache[key]; | |
| 12930 | if (cached) { | |
| 12931 | peg$currPos = cached.nextPos; | |
| 12932 | return cached.result; | |
| 12933 | } | |
| 12934 | peg$silentFails++; | |
| 12935 | s0 = peg$currPos; | |
| 12936 | s1 = peg$parseSTRUCT(); | |
| 12937 | if (s1 !== peg$FAILED) { | |
| 12938 | s2 = peg$parseTYPE_NAME(); | |
| 12939 | if (s2 === peg$FAILED) { | |
| 12940 | s2 = null; | |
| 12941 | } | |
| 12942 | s3 = peg$parseLEFT_BRACE(); | |
| 12943 | if (s3 !== peg$FAILED) { | |
| 12944 | s4 = peg$parsestruct_declaration_list(); | |
| 12945 | if (s4 !== peg$FAILED) { | |
| 12946 | s5 = peg$parseRIGHT_BRACE(); | |
| 12947 | if (s5 !== peg$FAILED) { | |
| 12948 | peg$savedPos = s0; | |
| 12949 | s0 = peg$f48(s1, s2, s3, s4, s5); | |
| 12950 | } else { | |
| 12951 | peg$currPos = s0; | |
| 12952 | s0 = peg$FAILED; | |
| 12953 | } | |
| 12954 | } else { | |
| 12955 | peg$currPos = s0; | |
| 12956 | s0 = peg$FAILED; | |
| 12957 | } | |
| 12958 | } else { | |
| 12959 | peg$currPos = s0; | |
| 12960 | s0 = peg$FAILED; | |
| 12961 | } | |
| 12962 | } else { | |
| 12963 | peg$currPos = s0; | |
| 12964 | s0 = peg$FAILED; | |
| 12965 | } | |
| 12966 | peg$silentFails--; | |
| 12967 | if (s0 === peg$FAILED) { | |
| 12968 | s1 = peg$FAILED; | |
| 12969 | if (peg$silentFails === 0) { | |
| 12970 | peg$fail(peg$e242); | |
| 12971 | } | |
| 12972 | } | |
| 12973 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 12974 | return s0; | |
| 12975 | } | |
| 12976 | function peg$parsestruct_declaration_list() { | |
| 12977 | var s0, s1, s2, s3; | |
| 12978 | var key = peg$currPos * 306 + 278; | |
| 12979 | var cached = peg$resultsCache[key]; | |
| 12980 | if (cached) { | |
| 12981 | peg$currPos = cached.nextPos; | |
| 12982 | return cached.result; | |
| 12983 | } | |
| 12984 | s0 = []; | |
| 12985 | s1 = peg$currPos; | |
| 12986 | s2 = peg$parsestruct_declaration(); | |
| 12987 | if (s2 !== peg$FAILED) { | |
| 12988 | s3 = peg$parseSEMICOLON(); | |
| 12989 | if (s3 !== peg$FAILED) { | |
| 12990 | peg$savedPos = s1; | |
| 12991 | s1 = peg$f49(s2, s3); | |
| 12992 | } else { | |
| 12993 | peg$currPos = s1; | |
| 12994 | s1 = peg$FAILED; | |
| 12995 | } | |
| 12996 | } else { | |
| 12997 | peg$currPos = s1; | |
| 12998 | s1 = peg$FAILED; | |
| 12999 | } | |
| 13000 | if (s1 !== peg$FAILED) { | |
| 13001 | while (s1 !== peg$FAILED) { | |
| 13002 | s0.push(s1); | |
| 13003 | s1 = peg$currPos; | |
| 13004 | s2 = peg$parsestruct_declaration(); | |
| 13005 | if (s2 !== peg$FAILED) { | |
| 13006 | s3 = peg$parseSEMICOLON(); | |
| 13007 | if (s3 !== peg$FAILED) { | |
| 13008 | peg$savedPos = s1; | |
| 13009 | s1 = peg$f49(s2, s3); | |
| 13010 | } else { | |
| 13011 | peg$currPos = s1; | |
| 13012 | s1 = peg$FAILED; | |
| 13013 | } | |
| 13014 | } else { | |
| 13015 | peg$currPos = s1; | |
| 13016 | s1 = peg$FAILED; | |
| 13017 | } | |
| 13018 | } | |
| 13019 | } else { | |
| 13020 | s0 = peg$FAILED; | |
| 13021 | } | |
| 13022 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13023 | return s0; | |
| 13024 | } | |
| 13025 | function peg$parsestruct_declaration() { | |
| 13026 | var s0, s1, s2, s3, s4, s5, s6; | |
| 13027 | var key = peg$currPos * 306 + 279; | |
| 13028 | var cached = peg$resultsCache[key]; | |
| 13029 | if (cached) { | |
| 13030 | peg$currPos = cached.nextPos; | |
| 13031 | return cached.result; | |
| 13032 | } | |
| 13033 | s0 = peg$currPos; | |
| 13034 | s1 = peg$parsefully_specified_type(); | |
| 13035 | if (s1 !== peg$FAILED) { | |
| 13036 | s2 = peg$parsequantified_identifier(); | |
| 13037 | if (s2 !== peg$FAILED) { | |
| 13038 | s3 = []; | |
| 13039 | s4 = peg$currPos; | |
| 13040 | s5 = peg$parseCOMMA(); | |
| 13041 | if (s5 !== peg$FAILED) { | |
| 13042 | s6 = peg$parsequantified_identifier(); | |
| 13043 | if (s6 !== peg$FAILED) { | |
| 13044 | s5 = [s5, s6]; | |
| 13045 | s4 = s5; | |
| 13046 | } else { | |
| 13047 | peg$currPos = s4; | |
| 13048 | s4 = peg$FAILED; | |
| 13049 | } | |
| 13050 | } else { | |
| 13051 | peg$currPos = s4; | |
| 13052 | s4 = peg$FAILED; | |
| 13053 | } | |
| 13054 | while (s4 !== peg$FAILED) { | |
| 13055 | s3.push(s4); | |
| 13056 | s4 = peg$currPos; | |
| 13057 | s5 = peg$parseCOMMA(); | |
| 13058 | if (s5 !== peg$FAILED) { | |
| 13059 | s6 = peg$parsequantified_identifier(); | |
| 13060 | if (s6 !== peg$FAILED) { | |
| 13061 | s5 = [s5, s6]; | |
| 13062 | s4 = s5; | |
| 13063 | } else { | |
| 13064 | peg$currPos = s4; | |
| 13065 | s4 = peg$FAILED; | |
| 13066 | } | |
| 13067 | } else { | |
| 13068 | peg$currPos = s4; | |
| 13069 | s4 = peg$FAILED; | |
| 13070 | } | |
| 13071 | } | |
| 13072 | peg$savedPos = s0; | |
| 13073 | s0 = peg$f50(s1, s2, s3); | |
| 13074 | } else { | |
| 13075 | peg$currPos = s0; | |
| 13076 | s0 = peg$FAILED; | |
| 13077 | } | |
| 13078 | } else { | |
| 13079 | peg$currPos = s0; | |
| 13080 | s0 = peg$FAILED; | |
| 13081 | } | |
| 13082 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13083 | return s0; | |
| 13084 | } | |
| 13085 | function peg$parsequantified_identifier() { | |
| 13086 | var s0, s1, s2; | |
| 13087 | var key = peg$currPos * 306 + 280; | |
| 13088 | var cached = peg$resultsCache[key]; | |
| 13089 | if (cached) { | |
| 13090 | peg$currPos = cached.nextPos; | |
| 13091 | return cached.result; | |
| 13092 | } | |
| 13093 | s0 = peg$currPos; | |
| 13094 | s1 = peg$parseIDENTIFIER(); | |
| 13095 | if (s1 !== peg$FAILED) { | |
| 13096 | s2 = peg$parsearray_specifiers(); | |
| 13097 | if (s2 === peg$FAILED) { | |
| 13098 | s2 = null; | |
| 13099 | } | |
| 13100 | peg$savedPos = s0; | |
| 13101 | s0 = peg$f51(s1, s2); | |
| 13102 | } else { | |
| 13103 | peg$currPos = s0; | |
| 13104 | s0 = peg$FAILED; | |
| 13105 | } | |
| 13106 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13107 | return s0; | |
| 13108 | } | |
| 13109 | function peg$parseinitializer() { | |
| 13110 | var s0, s1, s2, s3, s4, s5, s6; | |
| 13111 | var key = peg$currPos * 306 + 281; | |
| 13112 | var cached = peg$resultsCache[key]; | |
| 13113 | if (cached) { | |
| 13114 | peg$currPos = cached.nextPos; | |
| 13115 | return cached.result; | |
| 13116 | } | |
| 13117 | s0 = peg$parseassignment_expression(); | |
| 13118 | if (s0 === peg$FAILED) { | |
| 13119 | s0 = peg$currPos; | |
| 13120 | s1 = peg$parseLEFT_BRACE(); | |
| 13121 | if (s1 !== peg$FAILED) { | |
| 13122 | s2 = peg$parseinitializer(); | |
| 13123 | if (s2 !== peg$FAILED) { | |
| 13124 | s3 = []; | |
| 13125 | s4 = peg$currPos; | |
| 13126 | s5 = peg$parseCOMMA(); | |
| 13127 | if (s5 !== peg$FAILED) { | |
| 13128 | s6 = peg$parseinitializer(); | |
| 13129 | if (s6 !== peg$FAILED) { | |
| 13130 | s5 = [s5, s6]; | |
| 13131 | s4 = s5; | |
| 13132 | } else { | |
| 13133 | peg$currPos = s4; | |
| 13134 | s4 = peg$FAILED; | |
| 13135 | } | |
| 13136 | } else { | |
| 13137 | peg$currPos = s4; | |
| 13138 | s4 = peg$FAILED; | |
| 13139 | } | |
| 13140 | while (s4 !== peg$FAILED) { | |
| 13141 | s3.push(s4); | |
| 13142 | s4 = peg$currPos; | |
| 13143 | s5 = peg$parseCOMMA(); | |
| 13144 | if (s5 !== peg$FAILED) { | |
| 13145 | s6 = peg$parseinitializer(); | |
| 13146 | if (s6 !== peg$FAILED) { | |
| 13147 | s5 = [s5, s6]; | |
| 13148 | s4 = s5; | |
| 13149 | } else { | |
| 13150 | peg$currPos = s4; | |
| 13151 | s4 = peg$FAILED; | |
| 13152 | } | |
| 13153 | } else { | |
| 13154 | peg$currPos = s4; | |
| 13155 | s4 = peg$FAILED; | |
| 13156 | } | |
| 13157 | } | |
| 13158 | s4 = peg$parseCOMMA(); | |
| 13159 | if (s4 === peg$FAILED) { | |
| 13160 | s4 = null; | |
| 13161 | } | |
| 13162 | s5 = peg$parseRIGHT_BRACE(); | |
| 13163 | if (s5 !== peg$FAILED) { | |
| 13164 | peg$savedPos = s0; | |
| 13165 | s0 = peg$f52(s1, s2, s3, s4, s5); | |
| 13166 | } else { | |
| 13167 | peg$currPos = s0; | |
| 13168 | s0 = peg$FAILED; | |
| 13169 | } | |
| 13170 | } else { | |
| 13171 | peg$currPos = s0; | |
| 13172 | s0 = peg$FAILED; | |
| 13173 | } | |
| 13174 | } else { | |
| 13175 | peg$currPos = s0; | |
| 13176 | s0 = peg$FAILED; | |
| 13177 | } | |
| 13178 | } | |
| 13179 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13180 | return s0; | |
| 13181 | } | |
| 13182 | function peg$parsestatement() { | |
| 13183 | var s0; | |
| 13184 | var key = peg$currPos * 306 + 282; | |
| 13185 | var cached = peg$resultsCache[key]; | |
| 13186 | if (cached) { | |
| 13187 | peg$currPos = cached.nextPos; | |
| 13188 | return cached.result; | |
| 13189 | } | |
| 13190 | s0 = peg$parsecompound_statement(); | |
| 13191 | if (s0 === peg$FAILED) { | |
| 13192 | s0 = peg$parsesimple_statement(); | |
| 13193 | } | |
| 13194 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13195 | return s0; | |
| 13196 | } | |
| 13197 | function peg$parsesimple_statement() { | |
| 13198 | var s0; | |
| 13199 | var key = peg$currPos * 306 + 283; | |
| 13200 | var cached = peg$resultsCache[key]; | |
| 13201 | if (cached) { | |
| 13202 | peg$currPos = cached.nextPos; | |
| 13203 | return cached.result; | |
| 13204 | } | |
| 13205 | s0 = peg$parsejump_statement(); | |
| 13206 | if (s0 === peg$FAILED) { | |
| 13207 | s0 = peg$parsedeclaration_statement(); | |
| 13208 | if (s0 === peg$FAILED) { | |
| 13209 | s0 = peg$parseexpression_statement(); | |
| 13210 | if (s0 === peg$FAILED) { | |
| 13211 | s0 = peg$parseif_statement(); | |
| 13212 | if (s0 === peg$FAILED) { | |
| 13213 | s0 = peg$parseswitch_statement(); | |
| 13214 | if (s0 === peg$FAILED) { | |
| 13215 | s0 = peg$parsecase_label(); | |
| 13216 | if (s0 === peg$FAILED) { | |
| 13217 | s0 = peg$parseiteration_statement(); | |
| 13218 | } | |
| 13219 | } | |
| 13220 | } | |
| 13221 | } | |
| 13222 | } | |
| 13223 | } | |
| 13224 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13225 | return s0; | |
| 13226 | } | |
| 13227 | function peg$parsecompound_statement() { | |
| 13228 | var s0, s1, s2, s3; | |
| 13229 | var key = peg$currPos * 306 + 284; | |
| 13230 | var cached = peg$resultsCache[key]; | |
| 13231 | if (cached) { | |
| 13232 | peg$currPos = cached.nextPos; | |
| 13233 | return cached.result; | |
| 13234 | } | |
| 13235 | s0 = peg$currPos; | |
| 13236 | s1 = peg$currPos; | |
| 13237 | s2 = peg$parseLEFT_BRACE(); | |
| 13238 | if (s2 !== peg$FAILED) { | |
| 13239 | peg$savedPos = s1; | |
| 13240 | s2 = peg$f53(s2); | |
| 13241 | } | |
| 13242 | s1 = s2; | |
| 13243 | if (s1 !== peg$FAILED) { | |
| 13244 | s2 = peg$parsestatement_list(); | |
| 13245 | if (s2 === peg$FAILED) { | |
| 13246 | s2 = null; | |
| 13247 | } | |
| 13248 | s3 = peg$parseRIGHT_BRACE(); | |
| 13249 | if (s3 !== peg$FAILED) { | |
| 13250 | peg$savedPos = s0; | |
| 13251 | s0 = peg$f54(s1, s2, s3); | |
| 13252 | } else { | |
| 13253 | peg$currPos = s0; | |
| 13254 | s0 = peg$FAILED; | |
| 13255 | } | |
| 13256 | } else { | |
| 13257 | peg$currPos = s0; | |
| 13258 | s0 = peg$FAILED; | |
| 13259 | } | |
| 13260 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13261 | return s0; | |
| 13262 | } | |
| 13263 | function peg$parsecompound_statement_no_new_scope() { | |
| 13264 | var s0, s1, s2, s3; | |
| 13265 | var key = peg$currPos * 306 + 285; | |
| 13266 | var cached = peg$resultsCache[key]; | |
| 13267 | if (cached) { | |
| 13268 | peg$currPos = cached.nextPos; | |
| 13269 | return cached.result; | |
| 13270 | } | |
| 13271 | s0 = peg$currPos; | |
| 13272 | s1 = peg$parseLEFT_BRACE(); | |
| 13273 | if (s1 !== peg$FAILED) { | |
| 13274 | s2 = peg$parsestatement_list(); | |
| 13275 | if (s2 === peg$FAILED) { | |
| 13276 | s2 = null; | |
| 13277 | } | |
| 13278 | s3 = peg$parseRIGHT_BRACE(); | |
| 13279 | if (s3 !== peg$FAILED) { | |
| 13280 | peg$savedPos = s0; | |
| 13281 | s0 = peg$f55(s1, s2, s3); | |
| 13282 | } else { | |
| 13283 | peg$currPos = s0; | |
| 13284 | s0 = peg$FAILED; | |
| 13285 | } | |
| 13286 | } else { | |
| 13287 | peg$currPos = s0; | |
| 13288 | s0 = peg$FAILED; | |
| 13289 | } | |
| 13290 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13291 | return s0; | |
| 13292 | } | |
| 13293 | function peg$parsestatement_no_new_scope() { | |
| 13294 | var s0; | |
| 13295 | var key = peg$currPos * 306 + 286; | |
| 13296 | var cached = peg$resultsCache[key]; | |
| 13297 | if (cached) { | |
| 13298 | peg$currPos = cached.nextPos; | |
| 13299 | return cached.result; | |
| 13300 | } | |
| 13301 | s0 = peg$parsecompound_statement_no_new_scope(); | |
| 13302 | if (s0 === peg$FAILED) { | |
| 13303 | s0 = peg$parsesimple_statement(); | |
| 13304 | } | |
| 13305 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13306 | return s0; | |
| 13307 | } | |
| 13308 | function peg$parsestatement_list() { | |
| 13309 | var s0, s1; | |
| 13310 | var key = peg$currPos * 306 + 287; | |
| 13311 | var cached = peg$resultsCache[key]; | |
| 13312 | if (cached) { | |
| 13313 | peg$currPos = cached.nextPos; | |
| 13314 | return cached.result; | |
| 13315 | } | |
| 13316 | s0 = []; | |
| 13317 | s1 = peg$parsestatement(); | |
| 13318 | if (s1 === peg$FAILED) { | |
| 13319 | s1 = peg$parsepreprocessor(); | |
| 13320 | } | |
| 13321 | if (s1 !== peg$FAILED) { | |
| 13322 | while (s1 !== peg$FAILED) { | |
| 13323 | s0.push(s1); | |
| 13324 | s1 = peg$parsestatement(); | |
| 13325 | if (s1 === peg$FAILED) { | |
| 13326 | s1 = peg$parsepreprocessor(); | |
| 13327 | } | |
| 13328 | } | |
| 13329 | } else { | |
| 13330 | s0 = peg$FAILED; | |
| 13331 | } | |
| 13332 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13333 | return s0; | |
| 13334 | } | |
| 13335 | function peg$parseexpression_statement() { | |
| 13336 | var s0, s1, s2; | |
| 13337 | var key = peg$currPos * 306 + 288; | |
| 13338 | var cached = peg$resultsCache[key]; | |
| 13339 | if (cached) { | |
| 13340 | peg$currPos = cached.nextPos; | |
| 13341 | return cached.result; | |
| 13342 | } | |
| 13343 | s0 = peg$currPos; | |
| 13344 | s1 = peg$parseexpression(); | |
| 13345 | if (s1 === peg$FAILED) { | |
| 13346 | s1 = null; | |
| 13347 | } | |
| 13348 | s2 = peg$parseSEMICOLON(); | |
| 13349 | if (s2 !== peg$FAILED) { | |
| 13350 | peg$savedPos = s0; | |
| 13351 | s0 = peg$f56(s1, s2); | |
| 13352 | } else { | |
| 13353 | peg$currPos = s0; | |
| 13354 | s0 = peg$FAILED; | |
| 13355 | } | |
| 13356 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13357 | return s0; | |
| 13358 | } | |
| 13359 | function peg$parseif_statement() { | |
| 13360 | var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; | |
| 13361 | var key = peg$currPos * 306 + 289; | |
| 13362 | var cached = peg$resultsCache[key]; | |
| 13363 | if (cached) { | |
| 13364 | peg$currPos = cached.nextPos; | |
| 13365 | return cached.result; | |
| 13366 | } | |
| 13367 | s0 = peg$currPos; | |
| 13368 | s1 = peg$parseIF(); | |
| 13369 | if (s1 !== peg$FAILED) { | |
| 13370 | s2 = peg$parseLEFT_PAREN(); | |
| 13371 | if (s2 !== peg$FAILED) { | |
| 13372 | s3 = peg$parseexpression(); | |
| 13373 | if (s3 !== peg$FAILED) { | |
| 13374 | s4 = peg$parseRIGHT_PAREN(); | |
| 13375 | if (s4 !== peg$FAILED) { | |
| 13376 | s5 = peg$currPos; | |
| 13377 | s6 = peg$parsestatement(); | |
| 13378 | if (s6 !== peg$FAILED) { | |
| 13379 | s7 = peg$currPos; | |
| 13380 | s8 = peg$parseELSE(); | |
| 13381 | if (s8 !== peg$FAILED) { | |
| 13382 | s9 = peg$parsestatement(); | |
| 13383 | if (s9 !== peg$FAILED) { | |
| 13384 | s8 = [s8, s9]; | |
| 13385 | s7 = s8; | |
| 13386 | } else { | |
| 13387 | peg$currPos = s7; | |
| 13388 | s7 = peg$FAILED; | |
| 13389 | } | |
| 13390 | } else { | |
| 13391 | peg$currPos = s7; | |
| 13392 | s7 = peg$FAILED; | |
| 13393 | } | |
| 13394 | if (s7 === peg$FAILED) { | |
| 13395 | s7 = null; | |
| 13396 | } | |
| 13397 | s6 = [s6, s7]; | |
| 13398 | s5 = s6; | |
| 13399 | } else { | |
| 13400 | peg$currPos = s5; | |
| 13401 | s5 = peg$FAILED; | |
| 13402 | } | |
| 13403 | if (s5 !== peg$FAILED) { | |
| 13404 | peg$savedPos = s0; | |
| 13405 | s0 = peg$f57(s1, s2, s3, s4, s5); | |
| 13406 | } else { | |
| 13407 | peg$currPos = s0; | |
| 13408 | s0 = peg$FAILED; | |
| 13409 | } | |
| 13410 | } else { | |
| 13411 | peg$currPos = s0; | |
| 13412 | s0 = peg$FAILED; | |
| 13413 | } | |
| 13414 | } else { | |
| 13415 | peg$currPos = s0; | |
| 13416 | s0 = peg$FAILED; | |
| 13417 | } | |
| 13418 | } else { | |
| 13419 | peg$currPos = s0; | |
| 13420 | s0 = peg$FAILED; | |
| 13421 | } | |
| 13422 | } else { | |
| 13423 | peg$currPos = s0; | |
| 13424 | s0 = peg$FAILED; | |
| 13425 | } | |
| 13426 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13427 | return s0; | |
| 13428 | } | |
| 13429 | function peg$parseswitch_statement() { | |
| 13430 | var s0, s1, s2, s3, s4, s5, s6, s7; | |
| 13431 | var key = peg$currPos * 306 + 290; | |
| 13432 | var cached = peg$resultsCache[key]; | |
| 13433 | if (cached) { | |
| 13434 | peg$currPos = cached.nextPos; | |
| 13435 | return cached.result; | |
| 13436 | } | |
| 13437 | s0 = peg$currPos; | |
| 13438 | s1 = peg$parseSWITCH(); | |
| 13439 | if (s1 !== peg$FAILED) { | |
| 13440 | s2 = peg$parseLEFT_PAREN(); | |
| 13441 | if (s2 !== peg$FAILED) { | |
| 13442 | s3 = peg$parseexpression(); | |
| 13443 | if (s3 !== peg$FAILED) { | |
| 13444 | s4 = peg$parseRIGHT_PAREN(); | |
| 13445 | if (s4 !== peg$FAILED) { | |
| 13446 | s5 = peg$parseLEFT_BRACE(); | |
| 13447 | if (s5 !== peg$FAILED) { | |
| 13448 | s6 = peg$parsestatement_list(); | |
| 13449 | if (s6 !== peg$FAILED) { | |
| 13450 | s7 = peg$parseRIGHT_BRACE(); | |
| 13451 | if (s7 !== peg$FAILED) { | |
| 13452 | peg$savedPos = s0; | |
| 13453 | s0 = peg$f58(s1, s2, s3, s4, s5, s6, s7); | |
| 13454 | } else { | |
| 13455 | peg$currPos = s0; | |
| 13456 | s0 = peg$FAILED; | |
| 13457 | } | |
| 13458 | } else { | |
| 13459 | peg$currPos = s0; | |
| 13460 | s0 = peg$FAILED; | |
| 13461 | } | |
| 13462 | } else { | |
| 13463 | peg$currPos = s0; | |
| 13464 | s0 = peg$FAILED; | |
| 13465 | } | |
| 13466 | } else { | |
| 13467 | peg$currPos = s0; | |
| 13468 | s0 = peg$FAILED; | |
| 13469 | } | |
| 13470 | } else { | |
| 13471 | peg$currPos = s0; | |
| 13472 | s0 = peg$FAILED; | |
| 13473 | } | |
| 13474 | } else { | |
| 13475 | peg$currPos = s0; | |
| 13476 | s0 = peg$FAILED; | |
| 13477 | } | |
| 13478 | } else { | |
| 13479 | peg$currPos = s0; | |
| 13480 | s0 = peg$FAILED; | |
| 13481 | } | |
| 13482 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13483 | return s0; | |
| 13484 | } | |
| 13485 | function peg$parsecase_label() { | |
| 13486 | var s0, s1, s2, s3; | |
| 13487 | var key = peg$currPos * 306 + 291; | |
| 13488 | var cached = peg$resultsCache[key]; | |
| 13489 | if (cached) { | |
| 13490 | peg$currPos = cached.nextPos; | |
| 13491 | return cached.result; | |
| 13492 | } | |
| 13493 | s0 = peg$currPos; | |
| 13494 | s1 = peg$parseCASE(); | |
| 13495 | if (s1 !== peg$FAILED) { | |
| 13496 | s2 = peg$parseexpression(); | |
| 13497 | if (s2 !== peg$FAILED) { | |
| 13498 | s3 = peg$parseCOLON(); | |
| 13499 | if (s3 !== peg$FAILED) { | |
| 13500 | peg$savedPos = s0; | |
| 13501 | s0 = peg$f59(s1, s2, s3); | |
| 13502 | } else { | |
| 13503 | peg$currPos = s0; | |
| 13504 | s0 = peg$FAILED; | |
| 13505 | } | |
| 13506 | } else { | |
| 13507 | peg$currPos = s0; | |
| 13508 | s0 = peg$FAILED; | |
| 13509 | } | |
| 13510 | } else { | |
| 13511 | peg$currPos = s0; | |
| 13512 | s0 = peg$FAILED; | |
| 13513 | } | |
| 13514 | if (s0 === peg$FAILED) { | |
| 13515 | s0 = peg$currPos; | |
| 13516 | s1 = peg$parseDEFAULT(); | |
| 13517 | if (s1 !== peg$FAILED) { | |
| 13518 | s2 = peg$parseCOLON(); | |
| 13519 | if (s2 !== peg$FAILED) { | |
| 13520 | peg$savedPos = s0; | |
| 13521 | s0 = peg$f60(s1, s2); | |
| 13522 | } else { | |
| 13523 | peg$currPos = s0; | |
| 13524 | s0 = peg$FAILED; | |
| 13525 | } | |
| 13526 | } else { | |
| 13527 | peg$currPos = s0; | |
| 13528 | s0 = peg$FAILED; | |
| 13529 | } | |
| 13530 | } | |
| 13531 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13532 | return s0; | |
| 13533 | } | |
| 13534 | function peg$parseiteration_statement() { | |
| 13535 | var s0, s1, s2, s3, s4, s5, s6, s7, s8; | |
| 13536 | var key = peg$currPos * 306 + 292; | |
| 13537 | var cached = peg$resultsCache[key]; | |
| 13538 | if (cached) { | |
| 13539 | peg$currPos = cached.nextPos; | |
| 13540 | return cached.result; | |
| 13541 | } | |
| 13542 | peg$silentFails++; | |
| 13543 | s0 = peg$currPos; | |
| 13544 | s1 = peg$currPos; | |
| 13545 | s2 = peg$parseWHILE(); | |
| 13546 | if (s2 !== peg$FAILED) { | |
| 13547 | peg$savedPos = s1; | |
| 13548 | s2 = peg$f61(s2); | |
| 13549 | } | |
| 13550 | s1 = s2; | |
| 13551 | if (s1 !== peg$FAILED) { | |
| 13552 | s2 = peg$parseLEFT_PAREN(); | |
| 13553 | if (s2 !== peg$FAILED) { | |
| 13554 | s3 = peg$parsecondition(); | |
| 13555 | if (s3 !== peg$FAILED) { | |
| 13556 | s4 = peg$parseRIGHT_PAREN(); | |
| 13557 | if (s4 !== peg$FAILED) { | |
| 13558 | s5 = peg$parsestatement_no_new_scope(); | |
| 13559 | if (s5 !== peg$FAILED) { | |
| 13560 | peg$savedPos = s0; | |
| 13561 | s0 = peg$f62(s1, s2, s3, s4, s5); | |
| 13562 | } else { | |
| 13563 | peg$currPos = s0; | |
| 13564 | s0 = peg$FAILED; | |
| 13565 | } | |
| 13566 | } else { | |
| 13567 | peg$currPos = s0; | |
| 13568 | s0 = peg$FAILED; | |
| 13569 | } | |
| 13570 | } else { | |
| 13571 | peg$currPos = s0; | |
| 13572 | s0 = peg$FAILED; | |
| 13573 | } | |
| 13574 | } else { | |
| 13575 | peg$currPos = s0; | |
| 13576 | s0 = peg$FAILED; | |
| 13577 | } | |
| 13578 | } else { | |
| 13579 | peg$currPos = s0; | |
| 13580 | s0 = peg$FAILED; | |
| 13581 | } | |
| 13582 | if (s0 === peg$FAILED) { | |
| 13583 | s0 = peg$currPos; | |
| 13584 | s1 = peg$parseDO(); | |
| 13585 | if (s1 !== peg$FAILED) { | |
| 13586 | s2 = peg$parsestatement(); | |
| 13587 | if (s2 !== peg$FAILED) { | |
| 13588 | s3 = peg$parseWHILE(); | |
| 13589 | if (s3 !== peg$FAILED) { | |
| 13590 | s4 = peg$parseLEFT_PAREN(); | |
| 13591 | if (s4 !== peg$FAILED) { | |
| 13592 | s5 = peg$parseexpression(); | |
| 13593 | if (s5 !== peg$FAILED) { | |
| 13594 | s6 = peg$parseRIGHT_PAREN(); | |
| 13595 | if (s6 !== peg$FAILED) { | |
| 13596 | s7 = peg$parseSEMICOLON(); | |
| 13597 | if (s7 !== peg$FAILED) { | |
| 13598 | peg$savedPos = s0; | |
| 13599 | s0 = peg$f63(s1, s2, s3, s4, s5, s6, s7); | |
| 13600 | } else { | |
| 13601 | peg$currPos = s0; | |
| 13602 | s0 = peg$FAILED; | |
| 13603 | } | |
| 13604 | } else { | |
| 13605 | peg$currPos = s0; | |
| 13606 | s0 = peg$FAILED; | |
| 13607 | } | |
| 13608 | } else { | |
| 13609 | peg$currPos = s0; | |
| 13610 | s0 = peg$FAILED; | |
| 13611 | } | |
| 13612 | } else { | |
| 13613 | peg$currPos = s0; | |
| 13614 | s0 = peg$FAILED; | |
| 13615 | } | |
| 13616 | } else { | |
| 13617 | peg$currPos = s0; | |
| 13618 | s0 = peg$FAILED; | |
| 13619 | } | |
| 13620 | } else { | |
| 13621 | peg$currPos = s0; | |
| 13622 | s0 = peg$FAILED; | |
| 13623 | } | |
| 13624 | } else { | |
| 13625 | peg$currPos = s0; | |
| 13626 | s0 = peg$FAILED; | |
| 13627 | } | |
| 13628 | if (s0 === peg$FAILED) { | |
| 13629 | s0 = peg$currPos; | |
| 13630 | s1 = peg$currPos; | |
| 13631 | s2 = peg$parseFOR(); | |
| 13632 | if (s2 !== peg$FAILED) { | |
| 13633 | peg$savedPos = s1; | |
| 13634 | s2 = peg$f64(s2); | |
| 13635 | } | |
| 13636 | s1 = s2; | |
| 13637 | if (s1 !== peg$FAILED) { | |
| 13638 | s2 = peg$parseLEFT_PAREN(); | |
| 13639 | if (s2 !== peg$FAILED) { | |
| 13640 | s3 = peg$parseexpression_statement(); | |
| 13641 | if (s3 === peg$FAILED) { | |
| 13642 | s3 = peg$parsedeclaration_statement(); | |
| 13643 | } | |
| 13644 | if (s3 === peg$FAILED) { | |
| 13645 | s3 = null; | |
| 13646 | } | |
| 13647 | s4 = peg$parsecondition(); | |
| 13648 | if (s4 === peg$FAILED) { | |
| 13649 | s4 = null; | |
| 13650 | } | |
| 13651 | s5 = peg$parseSEMICOLON(); | |
| 13652 | if (s5 !== peg$FAILED) { | |
| 13653 | s6 = peg$parseexpression(); | |
| 13654 | if (s6 === peg$FAILED) { | |
| 13655 | s6 = null; | |
| 13656 | } | |
| 13657 | s7 = peg$parseRIGHT_PAREN(); | |
| 13658 | if (s7 !== peg$FAILED) { | |
| 13659 | s8 = peg$parsestatement_no_new_scope(); | |
| 13660 | if (s8 !== peg$FAILED) { | |
| 13661 | peg$savedPos = s0; | |
| 13662 | s0 = peg$f65(s1, s2, s3, s4, s5, s6, s7, s8); | |
| 13663 | } else { | |
| 13664 | peg$currPos = s0; | |
| 13665 | s0 = peg$FAILED; | |
| 13666 | } | |
| 13667 | } else { | |
| 13668 | peg$currPos = s0; | |
| 13669 | s0 = peg$FAILED; | |
| 13670 | } | |
| 13671 | } else { | |
| 13672 | peg$currPos = s0; | |
| 13673 | s0 = peg$FAILED; | |
| 13674 | } | |
| 13675 | } else { | |
| 13676 | peg$currPos = s0; | |
| 13677 | s0 = peg$FAILED; | |
| 13678 | } | |
| 13679 | } else { | |
| 13680 | peg$currPos = s0; | |
| 13681 | s0 = peg$FAILED; | |
| 13682 | } | |
| 13683 | } | |
| 13684 | } | |
| 13685 | peg$silentFails--; | |
| 13686 | if (s0 === peg$FAILED) { | |
| 13687 | s1 = peg$FAILED; | |
| 13688 | if (peg$silentFails === 0) { | |
| 13689 | peg$fail(peg$e243); | |
| 13690 | } | |
| 13691 | } | |
| 13692 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13693 | return s0; | |
| 13694 | } | |
| 13695 | function peg$parsecondition() { | |
| 13696 | var s0, s1, s2, s3, s4; | |
| 13697 | var key = peg$currPos * 306 + 293; | |
| 13698 | var cached = peg$resultsCache[key]; | |
| 13699 | if (cached) { | |
| 13700 | peg$currPos = cached.nextPos; | |
| 13701 | return cached.result; | |
| 13702 | } | |
| 13703 | s0 = peg$currPos; | |
| 13704 | s1 = peg$parsefully_specified_type(); | |
| 13705 | if (s1 !== peg$FAILED) { | |
| 13706 | s2 = peg$parseIDENTIFIER(); | |
| 13707 | if (s2 !== peg$FAILED) { | |
| 13708 | s3 = peg$parseEQUAL(); | |
| 13709 | if (s3 !== peg$FAILED) { | |
| 13710 | s4 = peg$parseinitializer(); | |
| 13711 | if (s4 !== peg$FAILED) { | |
| 13712 | peg$savedPos = s0; | |
| 13713 | s0 = peg$f66(s1, s2, s3, s4); | |
| 13714 | } else { | |
| 13715 | peg$currPos = s0; | |
| 13716 | s0 = peg$FAILED; | |
| 13717 | } | |
| 13718 | } else { | |
| 13719 | peg$currPos = s0; | |
| 13720 | s0 = peg$FAILED; | |
| 13721 | } | |
| 13722 | } else { | |
| 13723 | peg$currPos = s0; | |
| 13724 | s0 = peg$FAILED; | |
| 13725 | } | |
| 13726 | } else { | |
| 13727 | peg$currPos = s0; | |
| 13728 | s0 = peg$FAILED; | |
| 13729 | } | |
| 13730 | if (s0 === peg$FAILED) { | |
| 13731 | s0 = peg$parseexpression(); | |
| 13732 | } | |
| 13733 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13734 | return s0; | |
| 13735 | } | |
| 13736 | function peg$parsejump_statement() { | |
| 13737 | var s0, s1, s2, s3; | |
| 13738 | var key = peg$currPos * 306 + 294; | |
| 13739 | var cached = peg$resultsCache[key]; | |
| 13740 | if (cached) { | |
| 13741 | peg$currPos = cached.nextPos; | |
| 13742 | return cached.result; | |
| 13743 | } | |
| 13744 | peg$silentFails++; | |
| 13745 | s0 = peg$currPos; | |
| 13746 | s1 = peg$parseCONTINUE(); | |
| 13747 | if (s1 !== peg$FAILED) { | |
| 13748 | s2 = peg$parseSEMICOLON(); | |
| 13749 | if (s2 !== peg$FAILED) { | |
| 13750 | peg$savedPos = s0; | |
| 13751 | s0 = peg$f67(s1, s2); | |
| 13752 | } else { | |
| 13753 | peg$currPos = s0; | |
| 13754 | s0 = peg$FAILED; | |
| 13755 | } | |
| 13756 | } else { | |
| 13757 | peg$currPos = s0; | |
| 13758 | s0 = peg$FAILED; | |
| 13759 | } | |
| 13760 | if (s0 === peg$FAILED) { | |
| 13761 | s0 = peg$currPos; | |
| 13762 | s1 = peg$parseBREAK(); | |
| 13763 | if (s1 !== peg$FAILED) { | |
| 13764 | s2 = peg$parseSEMICOLON(); | |
| 13765 | if (s2 !== peg$FAILED) { | |
| 13766 | peg$savedPos = s0; | |
| 13767 | s0 = peg$f68(s1, s2); | |
| 13768 | } else { | |
| 13769 | peg$currPos = s0; | |
| 13770 | s0 = peg$FAILED; | |
| 13771 | } | |
| 13772 | } else { | |
| 13773 | peg$currPos = s0; | |
| 13774 | s0 = peg$FAILED; | |
| 13775 | } | |
| 13776 | if (s0 === peg$FAILED) { | |
| 13777 | s0 = peg$currPos; | |
| 13778 | s1 = peg$parseRETURN(); | |
| 13779 | if (s1 !== peg$FAILED) { | |
| 13780 | s2 = peg$parseexpression(); | |
| 13781 | if (s2 === peg$FAILED) { | |
| 13782 | s2 = null; | |
| 13783 | } | |
| 13784 | s3 = peg$parseSEMICOLON(); | |
| 13785 | if (s3 !== peg$FAILED) { | |
| 13786 | peg$savedPos = s0; | |
| 13787 | s0 = peg$f69(s1, s2, s3); | |
| 13788 | } else { | |
| 13789 | peg$currPos = s0; | |
| 13790 | s0 = peg$FAILED; | |
| 13791 | } | |
| 13792 | } else { | |
| 13793 | peg$currPos = s0; | |
| 13794 | s0 = peg$FAILED; | |
| 13795 | } | |
| 13796 | if (s0 === peg$FAILED) { | |
| 13797 | s0 = peg$currPos; | |
| 13798 | s1 = peg$parseDISCARD(); | |
| 13799 | if (s1 !== peg$FAILED) { | |
| 13800 | s2 = peg$parseSEMICOLON(); | |
| 13801 | if (s2 !== peg$FAILED) { | |
| 13802 | peg$savedPos = s0; | |
| 13803 | s0 = peg$f70(s1, s2); | |
| 13804 | } else { | |
| 13805 | peg$currPos = s0; | |
| 13806 | s0 = peg$FAILED; | |
| 13807 | } | |
| 13808 | } else { | |
| 13809 | peg$currPos = s0; | |
| 13810 | s0 = peg$FAILED; | |
| 13811 | } | |
| 13812 | } | |
| 13813 | } | |
| 13814 | } | |
| 13815 | peg$silentFails--; | |
| 13816 | if (s0 === peg$FAILED) { | |
| 13817 | s1 = peg$FAILED; | |
| 13818 | if (peg$silentFails === 0) { | |
| 13819 | peg$fail(peg$e244); | |
| 13820 | } | |
| 13821 | } | |
| 13822 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13823 | return s0; | |
| 13824 | } | |
| 13825 | function peg$parsepreprocessor() { | |
| 13826 | var s0, s1, s2, s3, s4, s5; | |
| 13827 | var key = peg$currPos * 306 + 295; | |
| 13828 | var cached = peg$resultsCache[key]; | |
| 13829 | if (cached) { | |
| 13830 | peg$currPos = cached.nextPos; | |
| 13831 | return cached.result; | |
| 13832 | } | |
| 13833 | peg$silentFails++; | |
| 13834 | s0 = peg$currPos; | |
| 13835 | s1 = peg$currPos; | |
| 13836 | s2 = peg$currPos; | |
| 13837 | if (input.charCodeAt(peg$currPos) === 35) { | |
| 13838 | s3 = peg$c210; | |
| 13839 | peg$currPos++; | |
| 13840 | } else { | |
| 13841 | s3 = peg$FAILED; | |
| 13842 | if (peg$silentFails === 0) { | |
| 13843 | peg$fail(peg$e246); | |
| 13844 | } | |
| 13845 | } | |
| 13846 | if (s3 !== peg$FAILED) { | |
| 13847 | s4 = []; | |
| 13848 | if (peg$r11.test(input.charAt(peg$currPos))) { | |
| 13849 | s5 = input.charAt(peg$currPos); | |
| 13850 | peg$currPos++; | |
| 13851 | } else { | |
| 13852 | s5 = peg$FAILED; | |
| 13853 | if (peg$silentFails === 0) { | |
| 13854 | peg$fail(peg$e247); | |
| 13855 | } | |
| 13856 | } | |
| 13857 | while (s5 !== peg$FAILED) { | |
| 13858 | s4.push(s5); | |
| 13859 | if (peg$r11.test(input.charAt(peg$currPos))) { | |
| 13860 | s5 = input.charAt(peg$currPos); | |
| 13861 | peg$currPos++; | |
| 13862 | } else { | |
| 13863 | s5 = peg$FAILED; | |
| 13864 | if (peg$silentFails === 0) { | |
| 13865 | peg$fail(peg$e247); | |
| 13866 | } | |
| 13867 | } | |
| 13868 | } | |
| 13869 | s3 = [s3, s4]; | |
| 13870 | s2 = s3; | |
| 13871 | } else { | |
| 13872 | peg$currPos = s2; | |
| 13873 | s2 = peg$FAILED; | |
| 13874 | } | |
| 13875 | if (s2 !== peg$FAILED) { | |
| 13876 | s1 = input.substring(s1, peg$currPos); | |
| 13877 | } else { | |
| 13878 | s1 = s2; | |
| 13879 | } | |
| 13880 | if (s1 !== peg$FAILED) { | |
| 13881 | s2 = peg$parse_(); | |
| 13882 | peg$savedPos = s0; | |
| 13883 | s0 = peg$f71(s1, s2); | |
| 13884 | } else { | |
| 13885 | peg$currPos = s0; | |
| 13886 | s0 = peg$FAILED; | |
| 13887 | } | |
| 13888 | peg$silentFails--; | |
| 13889 | if (s0 === peg$FAILED) { | |
| 13890 | s1 = peg$FAILED; | |
| 13891 | if (peg$silentFails === 0) { | |
| 13892 | peg$fail(peg$e245); | |
| 13893 | } | |
| 13894 | } | |
| 13895 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13896 | return s0; | |
| 13897 | } | |
| 13898 | function peg$parsetranslation_unit() { | |
| 13899 | var s0, s1; | |
| 13900 | var key = peg$currPos * 306 + 296; | |
| 13901 | var cached = peg$resultsCache[key]; | |
| 13902 | if (cached) { | |
| 13903 | peg$currPos = cached.nextPos; | |
| 13904 | return cached.result; | |
| 13905 | } | |
| 13906 | s0 = []; | |
| 13907 | s1 = peg$parseexternal_declaration(); | |
| 13908 | if (s1 === peg$FAILED) { | |
| 13909 | s1 = peg$parsepreprocessor(); | |
| 13910 | } | |
| 13911 | if (s1 !== peg$FAILED) { | |
| 13912 | while (s1 !== peg$FAILED) { | |
| 13913 | s0.push(s1); | |
| 13914 | s1 = peg$parseexternal_declaration(); | |
| 13915 | if (s1 === peg$FAILED) { | |
| 13916 | s1 = peg$parsepreprocessor(); | |
| 13917 | } | |
| 13918 | } | |
| 13919 | } else { | |
| 13920 | s0 = peg$FAILED; | |
| 13921 | } | |
| 13922 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13923 | return s0; | |
| 13924 | } | |
| 13925 | function peg$parsefunction_prototype_statement() { | |
| 13926 | var s0, s1, s2; | |
| 13927 | var key = peg$currPos * 306 + 297; | |
| 13928 | var cached = peg$resultsCache[key]; | |
| 13929 | if (cached) { | |
| 13930 | peg$currPos = cached.nextPos; | |
| 13931 | return cached.result; | |
| 13932 | } | |
| 13933 | s0 = peg$currPos; | |
| 13934 | s1 = peg$parsefunction_prototype_no_new_scope(); | |
| 13935 | if (s1 !== peg$FAILED) { | |
| 13936 | s2 = peg$parseSEMICOLON(); | |
| 13937 | if (s2 !== peg$FAILED) { | |
| 13938 | peg$savedPos = s0; | |
| 13939 | s0 = peg$f72(s1, s2); | |
| 13940 | } else { | |
| 13941 | peg$currPos = s0; | |
| 13942 | s0 = peg$FAILED; | |
| 13943 | } | |
| 13944 | } else { | |
| 13945 | peg$currPos = s0; | |
| 13946 | s0 = peg$FAILED; | |
| 13947 | } | |
| 13948 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13949 | return s0; | |
| 13950 | } | |
| 13951 | function peg$parseexternal_declaration() { | |
| 13952 | var s0; | |
| 13953 | var key = peg$currPos * 306 + 298; | |
| 13954 | var cached = peg$resultsCache[key]; | |
| 13955 | if (cached) { | |
| 13956 | peg$currPos = cached.nextPos; | |
| 13957 | return cached.result; | |
| 13958 | } | |
| 13959 | s0 = peg$parsefunction_prototype_statement(); | |
| 13960 | if (s0 === peg$FAILED) { | |
| 13961 | s0 = peg$parsefunction_definition(); | |
| 13962 | if (s0 === peg$FAILED) { | |
| 13963 | s0 = peg$parsedeclaration_statement(); | |
| 13964 | } | |
| 13965 | } | |
| 13966 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13967 | return s0; | |
| 13968 | } | |
| 13969 | function peg$parsefunction_definition() { | |
| 13970 | var s0, s1, s2; | |
| 13971 | var key = peg$currPos * 306 + 299; | |
| 13972 | var cached = peg$resultsCache[key]; | |
| 13973 | if (cached) { | |
| 13974 | peg$currPos = cached.nextPos; | |
| 13975 | return cached.result; | |
| 13976 | } | |
| 13977 | s0 = peg$currPos; | |
| 13978 | s1 = peg$parsefunction_prototype_new_scope(); | |
| 13979 | if (s1 !== peg$FAILED) { | |
| 13980 | s2 = peg$parsecompound_statement_no_new_scope(); | |
| 13981 | if (s2 !== peg$FAILED) { | |
| 13982 | peg$savedPos = s0; | |
| 13983 | s0 = peg$f73(s1, s2); | |
| 13984 | } else { | |
| 13985 | peg$currPos = s0; | |
| 13986 | s0 = peg$FAILED; | |
| 13987 | } | |
| 13988 | } else { | |
| 13989 | peg$currPos = s0; | |
| 13990 | s0 = peg$FAILED; | |
| 13991 | } | |
| 13992 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 13993 | return s0; | |
| 13994 | } | |
| 13995 | function peg$parse_() { | |
| 13996 | var s0, s1, s2, s3, s4, s5; | |
| 13997 | var key = peg$currPos * 306 + 300; | |
| 13998 | var cached = peg$resultsCache[key]; | |
| 13999 | if (cached) { | |
| 14000 | peg$currPos = cached.nextPos; | |
| 14001 | return cached.result; | |
| 14002 | } | |
| 14003 | peg$silentFails++; | |
| 14004 | s0 = peg$currPos; | |
| 14005 | s1 = peg$parsewhitespace(); | |
| 14006 | if (s1 === peg$FAILED) { | |
| 14007 | s1 = null; | |
| 14008 | } | |
| 14009 | s2 = []; | |
| 14010 | s3 = peg$currPos; | |
| 14011 | s4 = peg$parsecomment(); | |
| 14012 | if (s4 !== peg$FAILED) { | |
| 14013 | s5 = peg$parsewhitespace(); | |
| 14014 | if (s5 === peg$FAILED) { | |
| 14015 | s5 = null; | |
| 14016 | } | |
| 14017 | s4 = [s4, s5]; | |
| 14018 | s3 = s4; | |
| 14019 | } else { | |
| 14020 | peg$currPos = s3; | |
| 14021 | s3 = peg$FAILED; | |
| 14022 | } | |
| 14023 | while (s3 !== peg$FAILED) { | |
| 14024 | s2.push(s3); | |
| 14025 | s3 = peg$currPos; | |
| 14026 | s4 = peg$parsecomment(); | |
| 14027 | if (s4 !== peg$FAILED) { | |
| 14028 | s5 = peg$parsewhitespace(); | |
| 14029 | if (s5 === peg$FAILED) { | |
| 14030 | s5 = null; | |
| 14031 | } | |
| 14032 | s4 = [s4, s5]; | |
| 14033 | s3 = s4; | |
| 14034 | } else { | |
| 14035 | peg$currPos = s3; | |
| 14036 | s3 = peg$FAILED; | |
| 14037 | } | |
| 14038 | } | |
| 14039 | peg$savedPos = s0; | |
| 14040 | s0 = peg$f74(s1, s2); | |
| 14041 | peg$silentFails--; | |
| 14042 | s1 = peg$FAILED; | |
| 14043 | if (peg$silentFails === 0) { | |
| 14044 | peg$fail(peg$e248); | |
| 14045 | } | |
| 14046 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 14047 | return s0; | |
| 14048 | } | |
| 14049 | function peg$parsecomment() { | |
| 14050 | var s0, s1, s2, s3, s4, s5; | |
| 14051 | var key = peg$currPos * 306 + 301; | |
| 14052 | var cached = peg$resultsCache[key]; | |
| 14053 | if (cached) { | |
| 14054 | peg$currPos = cached.nextPos; | |
| 14055 | return cached.result; | |
| 14056 | } | |
| 14057 | s0 = peg$parsesingle_comment(); | |
| 14058 | if (s0 === peg$FAILED) { | |
| 14059 | s0 = peg$currPos; | |
| 14060 | s1 = peg$parsemultiline_comment(); | |
| 14061 | if (s1 !== peg$FAILED) { | |
| 14062 | s2 = []; | |
| 14063 | s3 = peg$currPos; | |
| 14064 | s4 = peg$parsewhitespace(); | |
| 14065 | if (s4 !== peg$FAILED) { | |
| 14066 | s5 = peg$parsecomment(); | |
| 14067 | if (s5 !== peg$FAILED) { | |
| 14068 | peg$savedPos = s3; | |
| 14069 | s3 = peg$f75(s1, s4, s5); | |
| 14070 | } else { | |
| 14071 | peg$currPos = s3; | |
| 14072 | s3 = peg$FAILED; | |
| 14073 | } | |
| 14074 | } else { | |
| 14075 | peg$currPos = s3; | |
| 14076 | s3 = peg$FAILED; | |
| 14077 | } | |
| 14078 | while (s3 !== peg$FAILED) { | |
| 14079 | s2.push(s3); | |
| 14080 | s3 = peg$currPos; | |
| 14081 | s4 = peg$parsewhitespace(); | |
| 14082 | if (s4 !== peg$FAILED) { | |
| 14083 | s5 = peg$parsecomment(); | |
| 14084 | if (s5 !== peg$FAILED) { | |
| 14085 | peg$savedPos = s3; | |
| 14086 | s3 = peg$f75(s1, s4, s5); | |
| 14087 | } else { | |
| 14088 | peg$currPos = s3; | |
| 14089 | s3 = peg$FAILED; | |
| 14090 | } | |
| 14091 | } else { | |
| 14092 | peg$currPos = s3; | |
| 14093 | s3 = peg$FAILED; | |
| 14094 | } | |
| 14095 | } | |
| 14096 | peg$savedPos = s0; | |
| 14097 | s0 = peg$f76(s1, s2); | |
| 14098 | } else { | |
| 14099 | peg$currPos = s0; | |
| 14100 | s0 = peg$FAILED; | |
| 14101 | } | |
| 14102 | } | |
| 14103 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 14104 | return s0; | |
| 14105 | } | |
| 14106 | function peg$parsesingle_comment() { | |
| 14107 | var s0, s1, s2, s3, s4; | |
| 14108 | var key = peg$currPos * 306 + 302; | |
| 14109 | var cached = peg$resultsCache[key]; | |
| 14110 | if (cached) { | |
| 14111 | peg$currPos = cached.nextPos; | |
| 14112 | return cached.result; | |
| 14113 | } | |
| 14114 | s0 = peg$currPos; | |
| 14115 | s1 = peg$currPos; | |
| 14116 | if (input.substr(peg$currPos, 2) === peg$c211) { | |
| 14117 | s2 = peg$c211; | |
| 14118 | peg$currPos += 2; | |
| 14119 | } else { | |
| 14120 | s2 = peg$FAILED; | |
| 14121 | if (peg$silentFails === 0) { | |
| 14122 | peg$fail(peg$e249); | |
| 14123 | } | |
| 14124 | } | |
| 14125 | if (s2 !== peg$FAILED) { | |
| 14126 | s3 = []; | |
| 14127 | if (peg$r11.test(input.charAt(peg$currPos))) { | |
| 14128 | s4 = input.charAt(peg$currPos); | |
| 14129 | peg$currPos++; | |
| 14130 | } else { | |
| 14131 | s4 = peg$FAILED; | |
| 14132 | if (peg$silentFails === 0) { | |
| 14133 | peg$fail(peg$e247); | |
| 14134 | } | |
| 14135 | } | |
| 14136 | while (s4 !== peg$FAILED) { | |
| 14137 | s3.push(s4); | |
| 14138 | if (peg$r11.test(input.charAt(peg$currPos))) { | |
| 14139 | s4 = input.charAt(peg$currPos); | |
| 14140 | peg$currPos++; | |
| 14141 | } else { | |
| 14142 | s4 = peg$FAILED; | |
| 14143 | if (peg$silentFails === 0) { | |
| 14144 | peg$fail(peg$e247); | |
| 14145 | } | |
| 14146 | } | |
| 14147 | } | |
| 14148 | s2 = [s2, s3]; | |
| 14149 | s1 = s2; | |
| 14150 | } else { | |
| 14151 | peg$currPos = s1; | |
| 14152 | s1 = peg$FAILED; | |
| 14153 | } | |
| 14154 | if (s1 !== peg$FAILED) { | |
| 14155 | s0 = input.substring(s0, peg$currPos); | |
| 14156 | } else { | |
| 14157 | s0 = s1; | |
| 14158 | } | |
| 14159 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 14160 | return s0; | |
| 14161 | } | |
| 14162 | function peg$parsemultiline_comment() { | |
| 14163 | var s0, s1, s2, s3, s4, s5, s6; | |
| 14164 | var key = peg$currPos * 306 + 303; | |
| 14165 | var cached = peg$resultsCache[key]; | |
| 14166 | if (cached) { | |
| 14167 | peg$currPos = cached.nextPos; | |
| 14168 | return cached.result; | |
| 14169 | } | |
| 14170 | s0 = peg$currPos; | |
| 14171 | s1 = peg$currPos; | |
| 14172 | if (input.substr(peg$currPos, 2) === peg$c212) { | |
| 14173 | s2 = peg$c212; | |
| 14174 | peg$currPos += 2; | |
| 14175 | } else { | |
| 14176 | s2 = peg$FAILED; | |
| 14177 | if (peg$silentFails === 0) { | |
| 14178 | peg$fail(peg$e250); | |
| 14179 | } | |
| 14180 | } | |
| 14181 | if (s2 !== peg$FAILED) { | |
| 14182 | s3 = []; | |
| 14183 | s4 = peg$currPos; | |
| 14184 | s5 = peg$currPos; | |
| 14185 | peg$silentFails++; | |
| 14186 | if (input.substr(peg$currPos, 2) === peg$c213) { | |
| 14187 | s6 = peg$c213; | |
| 14188 | peg$currPos += 2; | |
| 14189 | } else { | |
| 14190 | s6 = peg$FAILED; | |
| 14191 | if (peg$silentFails === 0) { | |
| 14192 | peg$fail(peg$e251); | |
| 14193 | } | |
| 14194 | } | |
| 14195 | peg$silentFails--; | |
| 14196 | if (s6 === peg$FAILED) { | |
| 14197 | s5 = void 0; | |
| 14198 | } else { | |
| 14199 | peg$currPos = s5; | |
| 14200 | s5 = peg$FAILED; | |
| 14201 | } | |
| 14202 | if (s5 !== peg$FAILED) { | |
| 14203 | if (input.length > peg$currPos) { | |
| 14204 | s6 = input.charAt(peg$currPos); | |
| 14205 | peg$currPos++; | |
| 14206 | } else { | |
| 14207 | s6 = peg$FAILED; | |
| 14208 | if (peg$silentFails === 0) { | |
| 14209 | peg$fail(peg$e252); | |
| 14210 | } | |
| 14211 | } | |
| 14212 | if (s6 !== peg$FAILED) { | |
| 14213 | peg$savedPos = s4; | |
| 14214 | s4 = peg$f77(s6); | |
| 14215 | } else { | |
| 14216 | peg$currPos = s4; | |
| 14217 | s4 = peg$FAILED; | |
| 14218 | } | |
| 14219 | } else { | |
| 14220 | peg$currPos = s4; | |
| 14221 | s4 = peg$FAILED; | |
| 14222 | } | |
| 14223 | while (s4 !== peg$FAILED) { | |
| 14224 | s3.push(s4); | |
| 14225 | s4 = peg$currPos; | |
| 14226 | s5 = peg$currPos; | |
| 14227 | peg$silentFails++; | |
| 14228 | if (input.substr(peg$currPos, 2) === peg$c213) { | |
| 14229 | s6 = peg$c213; | |
| 14230 | peg$currPos += 2; | |
| 14231 | } else { | |
| 14232 | s6 = peg$FAILED; | |
| 14233 | if (peg$silentFails === 0) { | |
| 14234 | peg$fail(peg$e251); | |
| 14235 | } | |
| 14236 | } | |
| 14237 | peg$silentFails--; | |
| 14238 | if (s6 === peg$FAILED) { | |
| 14239 | s5 = void 0; | |
| 14240 | } else { | |
| 14241 | peg$currPos = s5; | |
| 14242 | s5 = peg$FAILED; | |
| 14243 | } | |
| 14244 | if (s5 !== peg$FAILED) { | |
| 14245 | if (input.length > peg$currPos) { | |
| 14246 | s6 = input.charAt(peg$currPos); | |
| 14247 | peg$currPos++; | |
| 14248 | } else { | |
| 14249 | s6 = peg$FAILED; | |
| 14250 | if (peg$silentFails === 0) { | |
| 14251 | peg$fail(peg$e252); | |
| 14252 | } | |
| 14253 | } | |
| 14254 | if (s6 !== peg$FAILED) { | |
| 14255 | peg$savedPos = s4; | |
| 14256 | s4 = peg$f77(s6); | |
| 14257 | } else { | |
| 14258 | peg$currPos = s4; | |
| 14259 | s4 = peg$FAILED; | |
| 14260 | } | |
| 14261 | } else { | |
| 14262 | peg$currPos = s4; | |
| 14263 | s4 = peg$FAILED; | |
| 14264 | } | |
| 14265 | } | |
| 14266 | if (input.substr(peg$currPos, 2) === peg$c213) { | |
| 14267 | s4 = peg$c213; | |
| 14268 | peg$currPos += 2; | |
| 14269 | } else { | |
| 14270 | s4 = peg$FAILED; | |
| 14271 | if (peg$silentFails === 0) { | |
| 14272 | peg$fail(peg$e251); | |
| 14273 | } | |
| 14274 | } | |
| 14275 | if (s4 !== peg$FAILED) { | |
| 14276 | s2 = [s2, s3, s4]; | |
| 14277 | s1 = s2; | |
| 14278 | } else { | |
| 14279 | peg$currPos = s1; | |
| 14280 | s1 = peg$FAILED; | |
| 14281 | } | |
| 14282 | } else { | |
| 14283 | peg$currPos = s1; | |
| 14284 | s1 = peg$FAILED; | |
| 14285 | } | |
| 14286 | if (s1 !== peg$FAILED) { | |
| 14287 | s0 = input.substring(s0, peg$currPos); | |
| 14288 | } else { | |
| 14289 | s0 = s1; | |
| 14290 | } | |
| 14291 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 14292 | return s0; | |
| 14293 | } | |
| 14294 | function peg$parsewhitespace() { | |
| 14295 | var s0, s1, s2; | |
| 14296 | var key = peg$currPos * 306 + 304; | |
| 14297 | var cached = peg$resultsCache[key]; | |
| 14298 | if (cached) { | |
| 14299 | peg$currPos = cached.nextPos; | |
| 14300 | return cached.result; | |
| 14301 | } | |
| 14302 | s0 = peg$currPos; | |
| 14303 | s1 = []; | |
| 14304 | if (peg$r12.test(input.charAt(peg$currPos))) { | |
| 14305 | s2 = input.charAt(peg$currPos); | |
| 14306 | peg$currPos++; | |
| 14307 | } else { | |
| 14308 | s2 = peg$FAILED; | |
| 14309 | if (peg$silentFails === 0) { | |
| 14310 | peg$fail(peg$e253); | |
| 14311 | } | |
| 14312 | } | |
| 14313 | if (s2 !== peg$FAILED) { | |
| 14314 | while (s2 !== peg$FAILED) { | |
| 14315 | s1.push(s2); | |
| 14316 | if (peg$r12.test(input.charAt(peg$currPos))) { | |
| 14317 | s2 = input.charAt(peg$currPos); | |
| 14318 | peg$currPos++; | |
| 14319 | } else { | |
| 14320 | s2 = peg$FAILED; | |
| 14321 | if (peg$silentFails === 0) { | |
| 14322 | peg$fail(peg$e253); | |
| 14323 | } | |
| 14324 | } | |
| 14325 | } | |
| 14326 | } else { | |
| 14327 | s1 = peg$FAILED; | |
| 14328 | } | |
| 14329 | if (s1 !== peg$FAILED) { | |
| 14330 | s0 = input.substring(s0, peg$currPos); | |
| 14331 | } else { | |
| 14332 | s0 = s1; | |
| 14333 | } | |
| 14334 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 14335 | return s0; | |
| 14336 | } | |
| 14337 | function peg$parseterminal() { | |
| 14338 | var s0, s1, s2; | |
| 14339 | var key = peg$currPos * 306 + 305; | |
| 14340 | var cached = peg$resultsCache[key]; | |
| 14341 | if (cached) { | |
| 14342 | peg$currPos = cached.nextPos; | |
| 14343 | return cached.result; | |
| 14344 | } | |
| 14345 | s0 = peg$currPos; | |
| 14346 | s1 = peg$currPos; | |
| 14347 | peg$silentFails++; | |
| 14348 | if (peg$r1.test(input.charAt(peg$currPos))) { | |
| 14349 | s2 = input.charAt(peg$currPos); | |
| 14350 | peg$currPos++; | |
| 14351 | } else { | |
| 14352 | s2 = peg$FAILED; | |
| 14353 | if (peg$silentFails === 0) { | |
| 14354 | peg$fail(peg$e209); | |
| 14355 | } | |
| 14356 | } | |
| 14357 | peg$silentFails--; | |
| 14358 | if (s2 === peg$FAILED) { | |
| 14359 | s1 = void 0; | |
| 14360 | } else { | |
| 14361 | peg$currPos = s1; | |
| 14362 | s1 = peg$FAILED; | |
| 14363 | } | |
| 14364 | if (s1 !== peg$FAILED) { | |
| 14365 | s2 = peg$parse_(); | |
| 14366 | peg$savedPos = s0; | |
| 14367 | s0 = peg$f78(s2); | |
| 14368 | } else { | |
| 14369 | peg$currPos = s0; | |
| 14370 | s0 = peg$FAILED; | |
| 14371 | } | |
| 14372 | peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; | |
| 14373 | return s0; | |
| 14374 | } | |
| 14375 | const context = { | |
| 14376 | options, | |
| 14377 | location, | |
| 14378 | text | |
| 14379 | }; | |
| 14380 | const { | |
| 14381 | getLocation, | |
| 14382 | node, | |
| 14383 | makeScope, | |
| 14384 | warn, | |
| 14385 | pushScope, | |
| 14386 | popScope, | |
| 14387 | setScopeEnd, | |
| 14388 | createFunctionPrototype, | |
| 14389 | addFunctionCallReference, | |
| 14390 | createFunctionDefinition, | |
| 14391 | addTypeReference, | |
| 14392 | addTypeIfFound, | |
| 14393 | createType, | |
| 14394 | addOrCreateBindingReference, | |
| 14395 | createBindings, | |
| 14396 | groupCases | |
| 14397 | } = makeLocals(context); | |
| 14398 | peg$result = peg$startRuleFunction(); | |
| 14399 | if (peg$result !== peg$FAILED && peg$currPos === input.length) { | |
| 14400 | return peg$result; | |
| 14401 | } else { | |
| 14402 | if (peg$result !== peg$FAILED && peg$currPos < input.length) { | |
| 14403 | peg$fail(peg$endExpectation()); | |
| 14404 | } | |
| 14405 | throw peg$buildStructuredError( | |
| 14406 | peg$maxFailExpected, | |
| 14407 | peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, | |
| 14408 | peg$maxFailPos < input.length ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) | |
| 14409 | ); | |
| 14410 | } | |
| 14411 | } | |
| 14412 | ||
| 14413 | // node_modules/@shaderfrog/glsl-parser/error.js | |
| 14414 | var __extends = /* @__PURE__ */ (function() { | |
| 14415 | var extendStatics = function(d, b) { | |
| 14416 | extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) { | |
| 14417 | d2.__proto__ = b2; | |
| 14418 | } || function(d2, b2) { | |
| 14419 | for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p]; | |
| 14420 | }; | |
| 14421 | return extendStatics(d, b); | |
| 14422 | }; | |
| 14423 | return function(d, b) { | |
| 14424 | if (typeof b !== "function" && b !== null) | |
| 14425 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | |
| 14426 | extendStatics(d, b); | |
| 14427 | function __() { | |
| 14428 | this.constructor = d; | |
| 14429 | } | |
| 14430 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | |
| 14431 | }; | |
| 14432 | })(); | |
| 14433 | var __assign2 = function() { | |
| 14434 | __assign2 = Object.assign || function(t) { | |
| 14435 | for (var s, i = 1, n = arguments.length; i < n; i++) { | |
| 14436 | s = arguments[i]; | |
| 14437 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | |
| 14438 | t[p] = s[p]; | |
| 14439 | } | |
| 14440 | return t; | |
| 14441 | }; | |
| 14442 | return __assign2.apply(this, arguments); | |
| 14443 | }; | |
| 14444 | var GlslSyntaxError = ( | |
| 14445 | /** @class */ | |
| 14446 | (function(_super) { | |
| 14447 | __extends(GlslSyntaxError2, _super); | |
| 14448 | function GlslSyntaxError2(source, grammarSource, error) { | |
| 14449 | var _this = _super.call(this, error.format([{ source: grammarSource, text: source }])) || this; | |
| 14450 | _this.location = error.location; | |
| 14451 | _this.expected = error.expected; | |
| 14452 | _this.found = error.found; | |
| 14453 | return _this; | |
| 14454 | } | |
| 14455 | return GlslSyntaxError2; | |
| 14456 | })(Error) | |
| 14457 | ); | |
| 14458 | var DEFAULT_GRAMMAR_SOURCE = "location"; | |
| 14459 | var formatError = function(parser, grammarSource) { | |
| 14460 | if (grammarSource === void 0) { | |
| 14461 | grammarSource = DEFAULT_GRAMMAR_SOURCE; | |
| 14462 | } | |
| 14463 | return function() { | |
| 14464 | var args = []; | |
| 14465 | for (var _i = 0; _i < arguments.length; _i++) { | |
| 14466 | args[_i] = arguments[_i]; | |
| 14467 | } | |
| 14468 | var src = args[0], options = args[1]; | |
| 14469 | try { | |
| 14470 | return parser.parse(src, __assign2({ grammarSource }, options)); | |
| 14471 | } catch (e) { | |
| 14472 | if (e instanceof parser.SyntaxError) { | |
| 14473 | throw new GlslSyntaxError(src, grammarSource, e); | |
| 14474 | } | |
| 14475 | throw e; | |
| 14476 | } | |
| 14477 | }; | |
| 14478 | }; | |
| 14479 | ||
| 14480 | // node_modules/@shaderfrog/glsl-parser/parser/index.js | |
| 14481 | var parse = formatError(parser_exports); | |
| 14482 | var parser_default = parse; | |
| 14483 | export { | |
| 14484 | GlslSyntaxError, | |
| 14485 | generator_default as generate, | |
| 14486 | parser_default as parse, | |
| 14487 | parser_exports as parser | |
| 14488 | }; |
| … | … | @@ -0,0 +1,21 @@ |
| 1 | MIT License | |
| 2 | ||
| 3 | Copyright (C) 2020 by Marijn Haverbeke <marijn@haverbeke.berlin> and others | |
| 4 | ||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 | of this software and associated documentation files (the "Software"), to deal | |
| 7 | in the Software without restriction, including without limitation the rights | |
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 9 | copies of the Software, and to permit persons to whom the Software is | |
| 10 | furnished to do so, subject to the following conditions: | |
| 11 | ||
| 12 | The above copyright notice and this permission notice shall be included in | |
| 13 | all copies or substantial portions of the Software. | |
| 14 | ||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| 21 | THE SOFTWARE. |
| … | … | @@ -0,0 +1,25 @@ |
| 1 | # Vendored: @lezer/cpp | |
| 2 | ||
| 3 | - **Source**: https://www.npmjs.com/package/@lezer/cpp | |
| 4 | - **Version**: 1.1.5 | |
| 5 | - **License**: MIT (see LICENSE) | |
| 6 | - **Author**: Marijn Haverbeke | |
| 7 | - **Bundled**: Grammar + Lezer runtime (@lezer/lr + @lezer/common + @lezer/highlight) | |
| 8 | - **Bundle size**: 215 KB | |
| 9 | ||
| 10 | ## Usage | |
| 11 | ||
| 12 | ```js | |
| 13 | import { parser } from '../vendor/lezer-cpp/lezer-cpp.mjs' | |
| 14 | const tree = parser.parse(source) | |
| 15 | ``` | |
| 16 | ||
| 17 | ## Regeneration | |
| 18 | ||
| 19 | ```sh | |
| 20 | cd /tmp && mkdir -p codetree-vendor && cd codetree-vendor | |
| 21 | npm init -y && echo '{"type":"module"}' > package.json | |
| 22 | npm install @lezer/cpp @lezer/lr @lezer/common @lezer/highlight esbuild | |
| 23 | echo "export { parser } from '@lezer/cpp'" > bundle.js | |
| 24 | ./node_modules/.bin/esbuild bundle.js --bundle --format=esm --platform=neutral --outfile=lezer-cpp.mjs | |
| 25 | ``` |
| … | … | @@ -0,0 +1,4055 @@ |
| 1 | // node_modules/@lezer/common/dist/index.js | |
| 2 | var DefaultBufferLength = 1024; | |
| 3 | var nextPropID = 0; | |
| 4 | var Range = class { | |
| 5 | constructor(from, to) { | |
| 6 | this.from = from; | |
| 7 | this.to = to; | |
| 8 | } | |
| 9 | }; | |
| 10 | var NodeProp = class { | |
| 11 | /** | |
| 12 | Create a new node prop type. | |
| 13 | */ | |
| 14 | constructor(config = {}) { | |
| 15 | this.id = nextPropID++; | |
| 16 | this.perNode = !!config.perNode; | |
| 17 | this.deserialize = config.deserialize || (() => { | |
| 18 | throw new Error("This node type doesn't define a deserialize function"); | |
| 19 | }); | |
| 20 | this.combine = config.combine || null; | |
| 21 | } | |
| 22 | /** | |
| 23 | This is meant to be used with | |
| 24 | [`NodeSet.extend`](#common.NodeSet.extend) or | |
| 25 | [`LRParser.configure`](#lr.ParserConfig.props) to compute | |
| 26 | prop values for each node type in the set. Takes a [match | |
| 27 | object](#common.NodeType^match) or function that returns undefined | |
| 28 | if the node type doesn't get this prop, and the prop's value if | |
| 29 | it does. | |
| 30 | */ | |
| 31 | add(match) { | |
| 32 | if (this.perNode) | |
| 33 | throw new RangeError("Can't add per-node props to node types"); | |
| 34 | if (typeof match != "function") | |
| 35 | match = NodeType.match(match); | |
| 36 | return (type) => { | |
| 37 | let result = match(type); | |
| 38 | return result === void 0 ? null : [this, result]; | |
| 39 | }; | |
| 40 | } | |
| 41 | }; | |
| 42 | NodeProp.closedBy = new NodeProp({ deserialize: (str) => str.split(" ") }); | |
| 43 | NodeProp.openedBy = new NodeProp({ deserialize: (str) => str.split(" ") }); | |
| 44 | NodeProp.group = new NodeProp({ deserialize: (str) => str.split(" ") }); | |
| 45 | NodeProp.isolate = new NodeProp({ deserialize: (value) => { | |
| 46 | if (value && value != "rtl" && value != "ltr" && value != "auto") | |
| 47 | throw new RangeError("Invalid value for isolate: " + value); | |
| 48 | return value || "auto"; | |
| 49 | } }); | |
| 50 | NodeProp.contextHash = new NodeProp({ perNode: true }); | |
| 51 | NodeProp.lookAhead = new NodeProp({ perNode: true }); | |
| 52 | NodeProp.mounted = new NodeProp({ perNode: true }); | |
| 53 | var MountedTree = class { | |
| 54 | constructor(tree, overlay, parser2, bracketed = false) { | |
| 55 | this.tree = tree; | |
| 56 | this.overlay = overlay; | |
| 57 | this.parser = parser2; | |
| 58 | this.bracketed = bracketed; | |
| 59 | } | |
| 60 | /** | |
| 61 | @internal | |
| 62 | */ | |
| 63 | static get(tree) { | |
| 64 | return tree && tree.props && tree.props[NodeProp.mounted.id]; | |
| 65 | } | |
| 66 | }; | |
| 67 | var noProps = /* @__PURE__ */ Object.create(null); | |
| 68 | var NodeType = class _NodeType { | |
| 69 | /** | |
| 70 | @internal | |
| 71 | */ | |
| 72 | constructor(name2, props, id, flags = 0) { | |
| 73 | this.name = name2; | |
| 74 | this.props = props; | |
| 75 | this.id = id; | |
| 76 | this.flags = flags; | |
| 77 | } | |
| 78 | /** | |
| 79 | Define a node type. | |
| 80 | */ | |
| 81 | static define(spec) { | |
| 82 | let props = spec.props && spec.props.length ? /* @__PURE__ */ Object.create(null) : noProps; | |
| 83 | let flags = (spec.top ? 1 : 0) | (spec.skipped ? 2 : 0) | (spec.error ? 4 : 0) | (spec.name == null ? 8 : 0); | |
| 84 | let type = new _NodeType(spec.name || "", props, spec.id, flags); | |
| 85 | if (spec.props) | |
| 86 | for (let src of spec.props) { | |
| 87 | if (!Array.isArray(src)) | |
| 88 | src = src(type); | |
| 89 | if (src) { | |
| 90 | if (src[0].perNode) | |
| 91 | throw new RangeError("Can't store a per-node prop on a node type"); | |
| 92 | props[src[0].id] = src[1]; | |
| 93 | } | |
| 94 | } | |
| 95 | return type; | |
| 96 | } | |
| 97 | /** | |
| 98 | Retrieves a node prop for this type. Will return `undefined` if | |
| 99 | the prop isn't present on this node. | |
| 100 | */ | |
| 101 | prop(prop) { | |
| 102 | return this.props[prop.id]; | |
| 103 | } | |
| 104 | /** | |
| 105 | True when this is the top node of a grammar. | |
| 106 | */ | |
| 107 | get isTop() { | |
| 108 | return (this.flags & 1) > 0; | |
| 109 | } | |
| 110 | /** | |
| 111 | True when this node is produced by a skip rule. | |
| 112 | */ | |
| 113 | get isSkipped() { | |
| 114 | return (this.flags & 2) > 0; | |
| 115 | } | |
| 116 | /** | |
| 117 | Indicates whether this is an error node. | |
| 118 | */ | |
| 119 | get isError() { | |
| 120 | return (this.flags & 4) > 0; | |
| 121 | } | |
| 122 | /** | |
| 123 | When true, this node type doesn't correspond to a user-declared | |
| 124 | named node, for example because it is used to cache repetition. | |
| 125 | */ | |
| 126 | get isAnonymous() { | |
| 127 | return (this.flags & 8) > 0; | |
| 128 | } | |
| 129 | /** | |
| 130 | Returns true when this node's name or one of its | |
| 131 | [groups](#common.NodeProp^group) matches the given string. | |
| 132 | */ | |
| 133 | is(name2) { | |
| 134 | if (typeof name2 == "string") { | |
| 135 | if (this.name == name2) | |
| 136 | return true; | |
| 137 | let group = this.prop(NodeProp.group); | |
| 138 | return group ? group.indexOf(name2) > -1 : false; | |
| 139 | } | |
| 140 | return this.id == name2; | |
| 141 | } | |
| 142 | /** | |
| 143 | Create a function from node types to arbitrary values by | |
| 144 | specifying an object whose property names are node or | |
| 145 | [group](#common.NodeProp^group) names. Often useful with | |
| 146 | [`NodeProp.add`](#common.NodeProp.add). You can put multiple | |
| 147 | names, separated by spaces, in a single property name to map | |
| 148 | multiple node names to a single value. | |
| 149 | */ | |
| 150 | static match(map) { | |
| 151 | let direct = /* @__PURE__ */ Object.create(null); | |
| 152 | for (let prop in map) | |
| 153 | for (let name2 of prop.split(" ")) | |
| 154 | direct[name2] = map[prop]; | |
| 155 | return (node) => { | |
| 156 | for (let groups = node.prop(NodeProp.group), i = -1; i < (groups ? groups.length : 0); i++) { | |
| 157 | let found = direct[i < 0 ? node.name : groups[i]]; | |
| 158 | if (found) | |
| 159 | return found; | |
| 160 | } | |
| 161 | }; | |
| 162 | } | |
| 163 | }; | |
| 164 | NodeType.none = new NodeType( | |
| 165 | "", | |
| 166 | /* @__PURE__ */ Object.create(null), | |
| 167 | 0, | |
| 168 | 8 | |
| 169 | /* NodeFlag.Anonymous */ | |
| 170 | ); | |
| 171 | var NodeSet = class _NodeSet { | |
| 172 | /** | |
| 173 | Create a set with the given types. The `id` property of each | |
| 174 | type should correspond to its position within the array. | |
| 175 | */ | |
| 176 | constructor(types) { | |
| 177 | this.types = types; | |
| 178 | for (let i = 0; i < types.length; i++) | |
| 179 | if (types[i].id != i) | |
| 180 | throw new RangeError("Node type ids should correspond to array positions when creating a node set"); | |
| 181 | } | |
| 182 | /** | |
| 183 | Create a copy of this set with some node properties added. The | |
| 184 | arguments to this method can be created with | |
| 185 | [`NodeProp.add`](#common.NodeProp.add). | |
| 186 | */ | |
| 187 | extend(...props) { | |
| 188 | let newTypes = []; | |
| 189 | for (let type of this.types) { | |
| 190 | let newProps = null; | |
| 191 | for (let source of props) { | |
| 192 | let add = source(type); | |
| 193 | if (add) { | |
| 194 | if (!newProps) | |
| 195 | newProps = Object.assign({}, type.props); | |
| 196 | let value = add[1], prop = add[0]; | |
| 197 | if (prop.combine && prop.id in newProps) | |
| 198 | value = prop.combine(newProps[prop.id], value); | |
| 199 | newProps[prop.id] = value; | |
| 200 | } | |
| 201 | } | |
| 202 | newTypes.push(newProps ? new NodeType(type.name, newProps, type.id, type.flags) : type); | |
| 203 | } | |
| 204 | return new _NodeSet(newTypes); | |
| 205 | } | |
| 206 | }; | |
| 207 | var CachedNode = /* @__PURE__ */ new WeakMap(); | |
| 208 | var CachedInnerNode = /* @__PURE__ */ new WeakMap(); | |
| 209 | var IterMode; | |
| 210 | (function(IterMode2) { | |
| 211 | IterMode2[IterMode2["ExcludeBuffers"] = 1] = "ExcludeBuffers"; | |
| 212 | IterMode2[IterMode2["IncludeAnonymous"] = 2] = "IncludeAnonymous"; | |
| 213 | IterMode2[IterMode2["IgnoreMounts"] = 4] = "IgnoreMounts"; | |
| 214 | IterMode2[IterMode2["IgnoreOverlays"] = 8] = "IgnoreOverlays"; | |
| 215 | IterMode2[IterMode2["EnterBracketed"] = 16] = "EnterBracketed"; | |
| 216 | })(IterMode || (IterMode = {})); | |
| 217 | var Tree = class _Tree { | |
| 218 | /** | |
| 219 | Construct a new tree. See also [`Tree.build`](#common.Tree^build). | |
| 220 | */ | |
| 221 | constructor(type, children, positions, length, props) { | |
| 222 | this.type = type; | |
| 223 | this.children = children; | |
| 224 | this.positions = positions; | |
| 225 | this.length = length; | |
| 226 | this.props = null; | |
| 227 | if (props && props.length) { | |
| 228 | this.props = /* @__PURE__ */ Object.create(null); | |
| 229 | for (let [prop, value] of props) | |
| 230 | this.props[typeof prop == "number" ? prop : prop.id] = value; | |
| 231 | } | |
| 232 | } | |
| 233 | /** | |
| 234 | @internal | |
| 235 | */ | |
| 236 | toString() { | |
| 237 | let mounted = MountedTree.get(this); | |
| 238 | if (mounted && !mounted.overlay) | |
| 239 | return mounted.tree.toString(); | |
| 240 | let children = ""; | |
| 241 | for (let ch of this.children) { | |
| 242 | let str = ch.toString(); | |
| 243 | if (str) { | |
| 244 | if (children) | |
| 245 | children += ","; | |
| 246 | children += str; | |
| 247 | } | |
| 248 | } | |
| 249 | return !this.type.name ? children : (/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) + (children.length ? "(" + children + ")" : ""); | |
| 250 | } | |
| 251 | /** | |
| 252 | Get a [tree cursor](#common.TreeCursor) positioned at the top of | |
| 253 | the tree. Mode can be used to [control](#common.IterMode) which | |
| 254 | nodes the cursor visits. | |
| 255 | */ | |
| 256 | cursor(mode = 0) { | |
| 257 | return new TreeCursor(this.topNode, mode); | |
| 258 | } | |
| 259 | /** | |
| 260 | Get a [tree cursor](#common.TreeCursor) pointing into this tree | |
| 261 | at the given position and side (see | |
| 262 | [`moveTo`](#common.TreeCursor.moveTo). | |
| 263 | */ | |
| 264 | cursorAt(pos, side = 0, mode = 0) { | |
| 265 | let scope = CachedNode.get(this) || this.topNode; | |
| 266 | let cursor = new TreeCursor(scope); | |
| 267 | cursor.moveTo(pos, side); | |
| 268 | CachedNode.set(this, cursor._tree); | |
| 269 | return cursor; | |
| 270 | } | |
| 271 | /** | |
| 272 | Get a [syntax node](#common.SyntaxNode) object for the top of the | |
| 273 | tree. | |
| 274 | */ | |
| 275 | get topNode() { | |
| 276 | return new TreeNode(this, 0, 0, null); | |
| 277 | } | |
| 278 | /** | |
| 279 | Get the [syntax node](#common.SyntaxNode) at the given position. | |
| 280 | If `side` is -1, this will move into nodes that end at the | |
| 281 | position. If 1, it'll move into nodes that start at the | |
| 282 | position. With 0, it'll only enter nodes that cover the position | |
| 283 | from both sides. | |
| 284 | ||
| 285 | Note that this will not enter | |
| 286 | [overlays](#common.MountedTree.overlay), and you often want | |
| 287 | [`resolveInner`](#common.Tree.resolveInner) instead. | |
| 288 | */ | |
| 289 | resolve(pos, side = 0) { | |
| 290 | let node = resolveNode(CachedNode.get(this) || this.topNode, pos, side, false); | |
| 291 | CachedNode.set(this, node); | |
| 292 | return node; | |
| 293 | } | |
| 294 | /** | |
| 295 | Like [`resolve`](#common.Tree.resolve), but will enter | |
| 296 | [overlaid](#common.MountedTree.overlay) nodes, producing a syntax node | |
| 297 | pointing into the innermost overlaid tree at the given position | |
| 298 | (with parent links going through all parent structure, including | |
| 299 | the host trees). | |
| 300 | */ | |
| 301 | resolveInner(pos, side = 0) { | |
| 302 | let node = resolveNode(CachedInnerNode.get(this) || this.topNode, pos, side, true); | |
| 303 | CachedInnerNode.set(this, node); | |
| 304 | return node; | |
| 305 | } | |
| 306 | /** | |
| 307 | In some situations, it can be useful to iterate through all | |
| 308 | nodes around a position, including those in overlays that don't | |
| 309 | directly cover the position. This method gives you an iterator | |
| 310 | that will produce all nodes, from small to big, around the given | |
| 311 | position. | |
| 312 | */ | |
| 313 | resolveStack(pos, side = 0) { | |
| 314 | return stackIterator(this, pos, side); | |
| 315 | } | |
| 316 | /** | |
| 317 | Iterate over the tree and its children, calling `enter` for any | |
| 318 | node that touches the `from`/`to` region (if given) before | |
| 319 | running over such a node's children, and `leave` (if given) when | |
| 320 | leaving the node. When `enter` returns `false`, that node will | |
| 321 | not have its children iterated over (or `leave` called). | |
| 322 | */ | |
| 323 | iterate(spec) { | |
| 324 | let { enter, leave, from = 0, to = this.length } = spec; | |
| 325 | let mode = spec.mode || 0, anon = (mode & IterMode.IncludeAnonymous) > 0; | |
| 326 | for (let c = this.cursor(mode | IterMode.IncludeAnonymous); ; ) { | |
| 327 | let entered = false; | |
| 328 | if (c.from <= to && c.to >= from && (!anon && c.type.isAnonymous || enter(c) !== false)) { | |
| 329 | if (c.firstChild()) | |
| 330 | continue; | |
| 331 | entered = true; | |
| 332 | } | |
| 333 | for (; ; ) { | |
| 334 | if (entered && leave && (anon || !c.type.isAnonymous)) | |
| 335 | leave(c); | |
| 336 | if (c.nextSibling()) | |
| 337 | break; | |
| 338 | if (!c.parent()) | |
| 339 | return; | |
| 340 | entered = true; | |
| 341 | } | |
| 342 | } | |
| 343 | } | |
| 344 | /** | |
| 345 | Get the value of the given [node prop](#common.NodeProp) for this | |
| 346 | node. Works with both per-node and per-type props. | |
| 347 | */ | |
| 348 | prop(prop) { | |
| 349 | return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : void 0; | |
| 350 | } | |
| 351 | /** | |
| 352 | Returns the node's [per-node props](#common.NodeProp.perNode) in a | |
| 353 | format that can be passed to the [`Tree`](#common.Tree) | |
| 354 | constructor. | |
| 355 | */ | |
| 356 | get propValues() { | |
| 357 | let result = []; | |
| 358 | if (this.props) | |
| 359 | for (let id in this.props) | |
| 360 | result.push([+id, this.props[id]]); | |
| 361 | return result; | |
| 362 | } | |
| 363 | /** | |
| 364 | Balance the direct children of this tree, producing a copy of | |
| 365 | which may have children grouped into subtrees with type | |
| 366 | [`NodeType.none`](#common.NodeType^none). | |
| 367 | */ | |
| 368 | balance(config = {}) { | |
| 369 | return this.children.length <= 8 ? this : balanceRange(NodeType.none, this.children, this.positions, 0, this.children.length, 0, this.length, (children, positions, length) => new _Tree(this.type, children, positions, length, this.propValues), config.makeTree || ((children, positions, length) => new _Tree(NodeType.none, children, positions, length))); | |
| 370 | } | |
| 371 | /** | |
| 372 | Build a tree from a postfix-ordered buffer of node information, | |
| 373 | or a cursor over such a buffer. | |
| 374 | */ | |
| 375 | static build(data) { | |
| 376 | return buildTree(data); | |
| 377 | } | |
| 378 | }; | |
| 379 | Tree.empty = new Tree(NodeType.none, [], [], 0); | |
| 380 | var FlatBufferCursor = class _FlatBufferCursor { | |
| 381 | constructor(buffer, index) { | |
| 382 | this.buffer = buffer; | |
| 383 | this.index = index; | |
| 384 | } | |
| 385 | get id() { | |
| 386 | return this.buffer[this.index - 4]; | |
| 387 | } | |
| 388 | get start() { | |
| 389 | return this.buffer[this.index - 3]; | |
| 390 | } | |
| 391 | get end() { | |
| 392 | return this.buffer[this.index - 2]; | |
| 393 | } | |
| 394 | get size() { | |
| 395 | return this.buffer[this.index - 1]; | |
| 396 | } | |
| 397 | get pos() { | |
| 398 | return this.index; | |
| 399 | } | |
| 400 | next() { | |
| 401 | this.index -= 4; | |
| 402 | } | |
| 403 | fork() { | |
| 404 | return new _FlatBufferCursor(this.buffer, this.index); | |
| 405 | } | |
| 406 | }; | |
| 407 | var TreeBuffer = class _TreeBuffer { | |
| 408 | /** | |
| 409 | Create a tree buffer. | |
| 410 | */ | |
| 411 | constructor(buffer, length, set) { | |
| 412 | this.buffer = buffer; | |
| 413 | this.length = length; | |
| 414 | this.set = set; | |
| 415 | } | |
| 416 | /** | |
| 417 | @internal | |
| 418 | */ | |
| 419 | get type() { | |
| 420 | return NodeType.none; | |
| 421 | } | |
| 422 | /** | |
| 423 | @internal | |
| 424 | */ | |
| 425 | toString() { | |
| 426 | let result = []; | |
| 427 | for (let index = 0; index < this.buffer.length; ) { | |
| 428 | result.push(this.childString(index)); | |
| 429 | index = this.buffer[index + 3]; | |
| 430 | } | |
| 431 | return result.join(","); | |
| 432 | } | |
| 433 | /** | |
| 434 | @internal | |
| 435 | */ | |
| 436 | childString(index) { | |
| 437 | let id = this.buffer[index], endIndex = this.buffer[index + 3]; | |
| 438 | let type = this.set.types[id], result = type.name; | |
| 439 | if (/\W/.test(result) && !type.isError) | |
| 440 | result = JSON.stringify(result); | |
| 441 | index += 4; | |
| 442 | if (endIndex == index) | |
| 443 | return result; | |
| 444 | let children = []; | |
| 445 | while (index < endIndex) { | |
| 446 | children.push(this.childString(index)); | |
| 447 | index = this.buffer[index + 3]; | |
| 448 | } | |
| 449 | return result + "(" + children.join(",") + ")"; | |
| 450 | } | |
| 451 | /** | |
| 452 | @internal | |
| 453 | */ | |
| 454 | findChild(startIndex, endIndex, dir, pos, side) { | |
| 455 | let { buffer } = this, pick = -1; | |
| 456 | for (let i = startIndex; i != endIndex; i = buffer[i + 3]) { | |
| 457 | if (checkSide(side, pos, buffer[i + 1], buffer[i + 2])) { | |
| 458 | pick = i; | |
| 459 | if (dir > 0) | |
| 460 | break; | |
| 461 | } | |
| 462 | } | |
| 463 | return pick; | |
| 464 | } | |
| 465 | /** | |
| 466 | @internal | |
| 467 | */ | |
| 468 | slice(startI, endI, from) { | |
| 469 | let b = this.buffer; | |
| 470 | let copy = new Uint16Array(endI - startI), len = 0; | |
| 471 | for (let i = startI, j = 0; i < endI; ) { | |
| 472 | copy[j++] = b[i++]; | |
| 473 | copy[j++] = b[i++] - from; | |
| 474 | let to = copy[j++] = b[i++] - from; | |
| 475 | copy[j++] = b[i++] - startI; | |
| 476 | len = Math.max(len, to); | |
| 477 | } | |
| 478 | return new _TreeBuffer(copy, len, this.set); | |
| 479 | } | |
| 480 | }; | |
| 481 | function checkSide(side, pos, from, to) { | |
| 482 | switch (side) { | |
| 483 | case -2: | |
| 484 | return from < pos; | |
| 485 | case -1: | |
| 486 | return to >= pos && from < pos; | |
| 487 | case 0: | |
| 488 | return from < pos && to > pos; | |
| 489 | case 1: | |
| 490 | return from <= pos && to > pos; | |
| 491 | case 2: | |
| 492 | return to > pos; | |
| 493 | case 4: | |
| 494 | return true; | |
| 495 | } | |
| 496 | } | |
| 497 | function resolveNode(node, pos, side, overlays) { | |
| 498 | var _a; | |
| 499 | while (node.from == node.to || (side < 1 ? node.from >= pos : node.from > pos) || (side > -1 ? node.to <= pos : node.to < pos)) { | |
| 500 | let parent = !overlays && node instanceof TreeNode && node.index < 0 ? null : node.parent; | |
| 501 | if (!parent) | |
| 502 | return node; | |
| 503 | node = parent; | |
| 504 | } | |
| 505 | let mode = overlays ? 0 : IterMode.IgnoreOverlays; | |
| 506 | if (overlays) | |
| 507 | for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) { | |
| 508 | if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from) | |
| 509 | node = parent; | |
| 510 | } | |
| 511 | for (; ; ) { | |
| 512 | let inner = node.enter(pos, side, mode); | |
| 513 | if (!inner) | |
| 514 | return node; | |
| 515 | node = inner; | |
| 516 | } | |
| 517 | } | |
| 518 | var BaseNode = class { | |
| 519 | cursor(mode = 0) { | |
| 520 | return new TreeCursor(this, mode); | |
| 521 | } | |
| 522 | getChild(type, before = null, after = null) { | |
| 523 | let r = getChildren(this, type, before, after); | |
| 524 | return r.length ? r[0] : null; | |
| 525 | } | |
| 526 | getChildren(type, before = null, after = null) { | |
| 527 | return getChildren(this, type, before, after); | |
| 528 | } | |
| 529 | resolve(pos, side = 0) { | |
| 530 | return resolveNode(this, pos, side, false); | |
| 531 | } | |
| 532 | resolveInner(pos, side = 0) { | |
| 533 | return resolveNode(this, pos, side, true); | |
| 534 | } | |
| 535 | matchContext(context) { | |
| 536 | return matchNodeContext(this.parent, context); | |
| 537 | } | |
| 538 | enterUnfinishedNodesBefore(pos) { | |
| 539 | let scan = this.childBefore(pos), node = this; | |
| 540 | while (scan) { | |
| 541 | let last = scan.lastChild; | |
| 542 | if (!last || last.to != scan.to) | |
| 543 | break; | |
| 544 | if (last.type.isError && last.from == last.to) { | |
| 545 | node = scan; | |
| 546 | scan = last.prevSibling; | |
| 547 | } else { | |
| 548 | scan = last; | |
| 549 | } | |
| 550 | } | |
| 551 | return node; | |
| 552 | } | |
| 553 | get node() { | |
| 554 | return this; | |
| 555 | } | |
| 556 | get next() { | |
| 557 | return this.parent; | |
| 558 | } | |
| 559 | }; | |
| 560 | var TreeNode = class _TreeNode extends BaseNode { | |
| 561 | constructor(_tree, from, index, _parent) { | |
| 562 | super(); | |
| 563 | this._tree = _tree; | |
| 564 | this.from = from; | |
| 565 | this.index = index; | |
| 566 | this._parent = _parent; | |
| 567 | } | |
| 568 | get type() { | |
| 569 | return this._tree.type; | |
| 570 | } | |
| 571 | get name() { | |
| 572 | return this._tree.type.name; | |
| 573 | } | |
| 574 | get to() { | |
| 575 | return this.from + this._tree.length; | |
| 576 | } | |
| 577 | nextChild(i, dir, pos, side, mode = 0) { | |
| 578 | for (let parent = this; ; ) { | |
| 579 | for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) { | |
| 580 | let next = children[i], start = positions[i] + parent.from, mounted; | |
| 581 | if (!(mode & IterMode.EnterBracketed && next instanceof Tree && (mounted = MountedTree.get(next)) && !mounted.overlay && mounted.bracketed && pos >= start && pos <= start + next.length) && !checkSide(side, pos, start, start + next.length)) | |
| 582 | continue; | |
| 583 | if (next instanceof TreeBuffer) { | |
| 584 | if (mode & IterMode.ExcludeBuffers) | |
| 585 | continue; | |
| 586 | let index = next.findChild(0, next.buffer.length, dir, pos - start, side); | |
| 587 | if (index > -1) | |
| 588 | return new BufferNode(new BufferContext(parent, next, i, start), null, index); | |
| 589 | } else if (mode & IterMode.IncludeAnonymous || (!next.type.isAnonymous || hasChild(next))) { | |
| 590 | let mounted2; | |
| 591 | if (!(mode & IterMode.IgnoreMounts) && (mounted2 = MountedTree.get(next)) && !mounted2.overlay) | |
| 592 | return new _TreeNode(mounted2.tree, start, i, parent); | |
| 593 | let inner = new _TreeNode(next, start, i, parent); | |
| 594 | return mode & IterMode.IncludeAnonymous || !inner.type.isAnonymous ? inner : inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side, mode); | |
| 595 | } | |
| 596 | } | |
| 597 | if (mode & IterMode.IncludeAnonymous || !parent.type.isAnonymous) | |
| 598 | return null; | |
| 599 | if (parent.index >= 0) | |
| 600 | i = parent.index + dir; | |
| 601 | else | |
| 602 | i = dir < 0 ? -1 : parent._parent._tree.children.length; | |
| 603 | parent = parent._parent; | |
| 604 | if (!parent) | |
| 605 | return null; | |
| 606 | } | |
| 607 | } | |
| 608 | get firstChild() { | |
| 609 | return this.nextChild( | |
| 610 | 0, | |
| 611 | 1, | |
| 612 | 0, | |
| 613 | 4 | |
| 614 | /* Side.DontCare */ | |
| 615 | ); | |
| 616 | } | |
| 617 | get lastChild() { | |
| 618 | return this.nextChild( | |
| 619 | this._tree.children.length - 1, | |
| 620 | -1, | |
| 621 | 0, | |
| 622 | 4 | |
| 623 | /* Side.DontCare */ | |
| 624 | ); | |
| 625 | } | |
| 626 | childAfter(pos) { | |
| 627 | return this.nextChild( | |
| 628 | 0, | |
| 629 | 1, | |
| 630 | pos, | |
| 631 | 2 | |
| 632 | /* Side.After */ | |
| 633 | ); | |
| 634 | } | |
| 635 | childBefore(pos) { | |
| 636 | return this.nextChild( | |
| 637 | this._tree.children.length - 1, | |
| 638 | -1, | |
| 639 | pos, | |
| 640 | -2 | |
| 641 | /* Side.Before */ | |
| 642 | ); | |
| 643 | } | |
| 644 | prop(prop) { | |
| 645 | return this._tree.prop(prop); | |
| 646 | } | |
| 647 | enter(pos, side, mode = 0) { | |
| 648 | let mounted; | |
| 649 | if (!(mode & IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) { | |
| 650 | let rPos = pos - this.from, enterBracketed = mode & IterMode.EnterBracketed && mounted.bracketed; | |
| 651 | for (let { from, to } of mounted.overlay) { | |
| 652 | if ((side > 0 || enterBracketed ? from <= rPos : from < rPos) && (side < 0 || enterBracketed ? to >= rPos : to > rPos)) | |
| 653 | return new _TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this); | |
| 654 | } | |
| 655 | } | |
| 656 | return this.nextChild(0, 1, pos, side, mode); | |
| 657 | } | |
| 658 | nextSignificantParent() { | |
| 659 | let val = this; | |
| 660 | while (val.type.isAnonymous && val._parent) | |
| 661 | val = val._parent; | |
| 662 | return val; | |
| 663 | } | |
| 664 | get parent() { | |
| 665 | return this._parent ? this._parent.nextSignificantParent() : null; | |
| 666 | } | |
| 667 | get nextSibling() { | |
| 668 | return this._parent && this.index >= 0 ? this._parent.nextChild( | |
| 669 | this.index + 1, | |
| 670 | 1, | |
| 671 | 0, | |
| 672 | 4 | |
| 673 | /* Side.DontCare */ | |
| 674 | ) : null; | |
| 675 | } | |
| 676 | get prevSibling() { | |
| 677 | return this._parent && this.index >= 0 ? this._parent.nextChild( | |
| 678 | this.index - 1, | |
| 679 | -1, | |
| 680 | 0, | |
| 681 | 4 | |
| 682 | /* Side.DontCare */ | |
| 683 | ) : null; | |
| 684 | } | |
| 685 | get tree() { | |
| 686 | return this._tree; | |
| 687 | } | |
| 688 | toTree() { | |
| 689 | return this._tree; | |
| 690 | } | |
| 691 | /** | |
| 692 | @internal | |
| 693 | */ | |
| 694 | toString() { | |
| 695 | return this._tree.toString(); | |
| 696 | } | |
| 697 | }; | |
| 698 | function getChildren(node, type, before, after) { | |
| 699 | let cur = node.cursor(), result = []; | |
| 700 | if (!cur.firstChild()) | |
| 701 | return result; | |
| 702 | if (before != null) | |
| 703 | for (let found = false; !found; ) { | |
| 704 | found = cur.type.is(before); | |
| 705 | if (!cur.nextSibling()) | |
| 706 | return result; | |
| 707 | } | |
| 708 | for (; ; ) { | |
| 709 | if (after != null && cur.type.is(after)) | |
| 710 | return result; | |
| 711 | if (cur.type.is(type)) | |
| 712 | result.push(cur.node); | |
| 713 | if (!cur.nextSibling()) | |
| 714 | return after == null ? result : []; | |
| 715 | } | |
| 716 | } | |
| 717 | function matchNodeContext(node, context, i = context.length - 1) { | |
| 718 | for (let p = node; i >= 0; p = p.parent) { | |
| 719 | if (!p) | |
| 720 | return false; | |
| 721 | if (!p.type.isAnonymous) { | |
| 722 | if (context[i] && context[i] != p.name) | |
| 723 | return false; | |
| 724 | i--; | |
| 725 | } | |
| 726 | } | |
| 727 | return true; | |
| 728 | } | |
| 729 | var BufferContext = class { | |
| 730 | constructor(parent, buffer, index, start) { | |
| 731 | this.parent = parent; | |
| 732 | this.buffer = buffer; | |
| 733 | this.index = index; | |
| 734 | this.start = start; | |
| 735 | } | |
| 736 | }; | |
| 737 | var BufferNode = class _BufferNode extends BaseNode { | |
| 738 | get name() { | |
| 739 | return this.type.name; | |
| 740 | } | |
| 741 | get from() { | |
| 742 | return this.context.start + this.context.buffer.buffer[this.index + 1]; | |
| 743 | } | |
| 744 | get to() { | |
| 745 | return this.context.start + this.context.buffer.buffer[this.index + 2]; | |
| 746 | } | |
| 747 | constructor(context, _parent, index) { | |
| 748 | super(); | |
| 749 | this.context = context; | |
| 750 | this._parent = _parent; | |
| 751 | this.index = index; | |
| 752 | this.type = context.buffer.set.types[context.buffer.buffer[index]]; | |
| 753 | } | |
| 754 | child(dir, pos, side) { | |
| 755 | let { buffer } = this.context; | |
| 756 | let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.context.start, side); | |
| 757 | return index < 0 ? null : new _BufferNode(this.context, this, index); | |
| 758 | } | |
| 759 | get firstChild() { | |
| 760 | return this.child( | |
| 761 | 1, | |
| 762 | 0, | |
| 763 | 4 | |
| 764 | /* Side.DontCare */ | |
| 765 | ); | |
| 766 | } | |
| 767 | get lastChild() { | |
| 768 | return this.child( | |
| 769 | -1, | |
| 770 | 0, | |
| 771 | 4 | |
| 772 | /* Side.DontCare */ | |
| 773 | ); | |
| 774 | } | |
| 775 | childAfter(pos) { | |
| 776 | return this.child( | |
| 777 | 1, | |
| 778 | pos, | |
| 779 | 2 | |
| 780 | /* Side.After */ | |
| 781 | ); | |
| 782 | } | |
| 783 | childBefore(pos) { | |
| 784 | return this.child( | |
| 785 | -1, | |
| 786 | pos, | |
| 787 | -2 | |
| 788 | /* Side.Before */ | |
| 789 | ); | |
| 790 | } | |
| 791 | prop(prop) { | |
| 792 | return this.type.prop(prop); | |
| 793 | } | |
| 794 | enter(pos, side, mode = 0) { | |
| 795 | if (mode & IterMode.ExcludeBuffers) | |
| 796 | return null; | |
| 797 | let { buffer } = this.context; | |
| 798 | let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side); | |
| 799 | return index < 0 ? null : new _BufferNode(this.context, this, index); | |
| 800 | } | |
| 801 | get parent() { | |
| 802 | return this._parent || this.context.parent.nextSignificantParent(); | |
| 803 | } | |
| 804 | externalSibling(dir) { | |
| 805 | return this._parent ? null : this.context.parent.nextChild( | |
| 806 | this.context.index + dir, | |
| 807 | dir, | |
| 808 | 0, | |
| 809 | 4 | |
| 810 | /* Side.DontCare */ | |
| 811 | ); | |
| 812 | } | |
| 813 | get nextSibling() { | |
| 814 | let { buffer } = this.context; | |
| 815 | let after = buffer.buffer[this.index + 3]; | |
| 816 | if (after < (this._parent ? buffer.buffer[this._parent.index + 3] : buffer.buffer.length)) | |
| 817 | return new _BufferNode(this.context, this._parent, after); | |
| 818 | return this.externalSibling(1); | |
| 819 | } | |
| 820 | get prevSibling() { | |
| 821 | let { buffer } = this.context; | |
| 822 | let parentStart = this._parent ? this._parent.index + 4 : 0; | |
| 823 | if (this.index == parentStart) | |
| 824 | return this.externalSibling(-1); | |
| 825 | return new _BufferNode(this.context, this._parent, buffer.findChild( | |
| 826 | parentStart, | |
| 827 | this.index, | |
| 828 | -1, | |
| 829 | 0, | |
| 830 | 4 | |
| 831 | /* Side.DontCare */ | |
| 832 | )); | |
| 833 | } | |
| 834 | get tree() { | |
| 835 | return null; | |
| 836 | } | |
| 837 | toTree() { | |
| 838 | let children = [], positions = []; | |
| 839 | let { buffer } = this.context; | |
| 840 | let startI = this.index + 4, endI = buffer.buffer[this.index + 3]; | |
| 841 | if (endI > startI) { | |
| 842 | let from = buffer.buffer[this.index + 1]; | |
| 843 | children.push(buffer.slice(startI, endI, from)); | |
| 844 | positions.push(0); | |
| 845 | } | |
| 846 | return new Tree(this.type, children, positions, this.to - this.from); | |
| 847 | } | |
| 848 | /** | |
| 849 | @internal | |
| 850 | */ | |
| 851 | toString() { | |
| 852 | return this.context.buffer.childString(this.index); | |
| 853 | } | |
| 854 | }; | |
| 855 | function iterStack(heads) { | |
| 856 | if (!heads.length) | |
| 857 | return null; | |
| 858 | let pick = 0, picked = heads[0]; | |
| 859 | for (let i = 1; i < heads.length; i++) { | |
| 860 | let node = heads[i]; | |
| 861 | if (node.from > picked.from || node.to < picked.to) { | |
| 862 | picked = node; | |
| 863 | pick = i; | |
| 864 | } | |
| 865 | } | |
| 866 | let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent; | |
| 867 | let newHeads = heads.slice(); | |
| 868 | if (next) | |
| 869 | newHeads[pick] = next; | |
| 870 | else | |
| 871 | newHeads.splice(pick, 1); | |
| 872 | return new StackIterator(newHeads, picked); | |
| 873 | } | |
| 874 | var StackIterator = class { | |
| 875 | constructor(heads, node) { | |
| 876 | this.heads = heads; | |
| 877 | this.node = node; | |
| 878 | } | |
| 879 | get next() { | |
| 880 | return iterStack(this.heads); | |
| 881 | } | |
| 882 | }; | |
| 883 | function stackIterator(tree, pos, side) { | |
| 884 | let inner = tree.resolveInner(pos, side), layers = null; | |
| 885 | for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) { | |
| 886 | if (scan.index < 0) { | |
| 887 | let parent = scan.parent; | |
| 888 | (layers || (layers = [inner])).push(parent.resolve(pos, side)); | |
| 889 | scan = parent; | |
| 890 | } else { | |
| 891 | let mount = MountedTree.get(scan.tree); | |
| 892 | if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) { | |
| 893 | let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, -1, scan); | |
| 894 | (layers || (layers = [inner])).push(resolveNode(root, pos, side, false)); | |
| 895 | } | |
| 896 | } | |
| 897 | } | |
| 898 | return layers ? iterStack(layers) : inner; | |
| 899 | } | |
| 900 | var TreeCursor = class { | |
| 901 | /** | |
| 902 | Shorthand for `.type.name`. | |
| 903 | */ | |
| 904 | get name() { | |
| 905 | return this.type.name; | |
| 906 | } | |
| 907 | /** | |
| 908 | @internal | |
| 909 | */ | |
| 910 | constructor(node, mode = 0) { | |
| 911 | this.buffer = null; | |
| 912 | this.stack = []; | |
| 913 | this.index = 0; | |
| 914 | this.bufferNode = null; | |
| 915 | this.mode = mode & ~IterMode.EnterBracketed; | |
| 916 | if (node instanceof TreeNode) { | |
| 917 | this.yieldNode(node); | |
| 918 | } else { | |
| 919 | this._tree = node.context.parent; | |
| 920 | this.buffer = node.context; | |
| 921 | for (let n = node._parent; n; n = n._parent) | |
| 922 | this.stack.unshift(n.index); | |
| 923 | this.bufferNode = node; | |
| 924 | this.yieldBuf(node.index); | |
| 925 | } | |
| 926 | } | |
| 927 | yieldNode(node) { | |
| 928 | if (!node) | |
| 929 | return false; | |
| 930 | this._tree = node; | |
| 931 | this.type = node.type; | |
| 932 | this.from = node.from; | |
| 933 | this.to = node.to; | |
| 934 | return true; | |
| 935 | } | |
| 936 | yieldBuf(index, type) { | |
| 937 | this.index = index; | |
| 938 | let { start, buffer } = this.buffer; | |
| 939 | this.type = type || buffer.set.types[buffer.buffer[index]]; | |
| 940 | this.from = start + buffer.buffer[index + 1]; | |
| 941 | this.to = start + buffer.buffer[index + 2]; | |
| 942 | return true; | |
| 943 | } | |
| 944 | /** | |
| 945 | @internal | |
| 946 | */ | |
| 947 | yield(node) { | |
| 948 | if (!node) | |
| 949 | return false; | |
| 950 | if (node instanceof TreeNode) { | |
| 951 | this.buffer = null; | |
| 952 | return this.yieldNode(node); | |
| 953 | } | |
| 954 | this.buffer = node.context; | |
| 955 | return this.yieldBuf(node.index, node.type); | |
| 956 | } | |
| 957 | /** | |
| 958 | @internal | |
| 959 | */ | |
| 960 | toString() { | |
| 961 | return this.buffer ? this.buffer.buffer.childString(this.index) : this._tree.toString(); | |
| 962 | } | |
| 963 | /** | |
| 964 | @internal | |
| 965 | */ | |
| 966 | enterChild(dir, pos, side) { | |
| 967 | if (!this.buffer) | |
| 968 | return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode)); | |
| 969 | let { buffer } = this.buffer; | |
| 970 | let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side); | |
| 971 | if (index < 0) | |
| 972 | return false; | |
| 973 | this.stack.push(this.index); | |
| 974 | return this.yieldBuf(index); | |
| 975 | } | |
| 976 | /** | |
| 977 | Move the cursor to this node's first child. When this returns | |
| 978 | false, the node has no child, and the cursor has not been moved. | |
| 979 | */ | |
| 980 | firstChild() { | |
| 981 | return this.enterChild( | |
| 982 | 1, | |
| 983 | 0, | |
| 984 | 4 | |
| 985 | /* Side.DontCare */ | |
| 986 | ); | |
| 987 | } | |
| 988 | /** | |
| 989 | Move the cursor to this node's last child. | |
| 990 | */ | |
| 991 | lastChild() { | |
| 992 | return this.enterChild( | |
| 993 | -1, | |
| 994 | 0, | |
| 995 | 4 | |
| 996 | /* Side.DontCare */ | |
| 997 | ); | |
| 998 | } | |
| 999 | /** | |
| 1000 | Move the cursor to the first child that ends after `pos`. | |
| 1001 | */ | |
| 1002 | childAfter(pos) { | |
| 1003 | return this.enterChild( | |
| 1004 | 1, | |
| 1005 | pos, | |
| 1006 | 2 | |
| 1007 | /* Side.After */ | |
| 1008 | ); | |
| 1009 | } | |
| 1010 | /** | |
| 1011 | Move to the last child that starts before `pos`. | |
| 1012 | */ | |
| 1013 | childBefore(pos) { | |
| 1014 | return this.enterChild( | |
| 1015 | -1, | |
| 1016 | pos, | |
| 1017 | -2 | |
| 1018 | /* Side.Before */ | |
| 1019 | ); | |
| 1020 | } | |
| 1021 | /** | |
| 1022 | Move the cursor to the child around `pos`. If side is -1 the | |
| 1023 | child may end at that position, when 1 it may start there. This | |
| 1024 | will also enter [overlaid](#common.MountedTree.overlay) | |
| 1025 | [mounted](#common.NodeProp^mounted) trees unless `overlays` is | |
| 1026 | set to false. | |
| 1027 | */ | |
| 1028 | enter(pos, side, mode = this.mode) { | |
| 1029 | if (!this.buffer) | |
| 1030 | return this.yield(this._tree.enter(pos, side, mode)); | |
| 1031 | return mode & IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side); | |
| 1032 | } | |
| 1033 | /** | |
| 1034 | Move to the node's parent node, if this isn't the top node. | |
| 1035 | */ | |
| 1036 | parent() { | |
| 1037 | if (!this.buffer) | |
| 1038 | return this.yieldNode(this.mode & IterMode.IncludeAnonymous ? this._tree._parent : this._tree.parent); | |
| 1039 | if (this.stack.length) | |
| 1040 | return this.yieldBuf(this.stack.pop()); | |
| 1041 | let parent = this.mode & IterMode.IncludeAnonymous ? this.buffer.parent : this.buffer.parent.nextSignificantParent(); | |
| 1042 | this.buffer = null; | |
| 1043 | return this.yieldNode(parent); | |
| 1044 | } | |
| 1045 | /** | |
| 1046 | @internal | |
| 1047 | */ | |
| 1048 | sibling(dir) { | |
| 1049 | if (!this.buffer) | |
| 1050 | return !this._tree._parent ? false : this.yield(this._tree.index < 0 ? null : this._tree._parent.nextChild(this._tree.index + dir, dir, 0, 4, this.mode)); | |
| 1051 | let { buffer } = this.buffer, d = this.stack.length - 1; | |
| 1052 | if (dir < 0) { | |
| 1053 | let parentStart = d < 0 ? 0 : this.stack[d] + 4; | |
| 1054 | if (this.index != parentStart) | |
| 1055 | return this.yieldBuf(buffer.findChild( | |
| 1056 | parentStart, | |
| 1057 | this.index, | |
| 1058 | -1, | |
| 1059 | 0, | |
| 1060 | 4 | |
| 1061 | /* Side.DontCare */ | |
| 1062 | )); | |
| 1063 | } else { | |
| 1064 | let after = buffer.buffer[this.index + 3]; | |
| 1065 | if (after < (d < 0 ? buffer.buffer.length : buffer.buffer[this.stack[d] + 3])) | |
| 1066 | return this.yieldBuf(after); | |
| 1067 | } | |
| 1068 | return d < 0 ? this.yield(this.buffer.parent.nextChild(this.buffer.index + dir, dir, 0, 4, this.mode)) : false; | |
| 1069 | } | |
| 1070 | /** | |
| 1071 | Move to this node's next sibling, if any. | |
| 1072 | */ | |
| 1073 | nextSibling() { | |
| 1074 | return this.sibling(1); | |
| 1075 | } | |
| 1076 | /** | |
| 1077 | Move to this node's previous sibling, if any. | |
| 1078 | */ | |
| 1079 | prevSibling() { | |
| 1080 | return this.sibling(-1); | |
| 1081 | } | |
| 1082 | atLastNode(dir) { | |
| 1083 | let index, parent, { buffer } = this; | |
| 1084 | if (buffer) { | |
| 1085 | if (dir > 0) { | |
| 1086 | if (this.index < buffer.buffer.buffer.length) | |
| 1087 | return false; | |
| 1088 | } else { | |
| 1089 | for (let i = 0; i < this.index; i++) | |
| 1090 | if (buffer.buffer.buffer[i + 3] < this.index) | |
| 1091 | return false; | |
| 1092 | } | |
| 1093 | ({ index, parent } = buffer); | |
| 1094 | } else { | |
| 1095 | ({ index, _parent: parent } = this._tree); | |
| 1096 | } | |
| 1097 | for (; parent; { index, _parent: parent } = parent) { | |
| 1098 | if (index > -1) | |
| 1099 | for (let i = index + dir, e = dir < 0 ? -1 : parent._tree.children.length; i != e; i += dir) { | |
| 1100 | let child = parent._tree.children[i]; | |
| 1101 | if (this.mode & IterMode.IncludeAnonymous || child instanceof TreeBuffer || !child.type.isAnonymous || hasChild(child)) | |
| 1102 | return false; | |
| 1103 | } | |
| 1104 | } | |
| 1105 | return true; | |
| 1106 | } | |
| 1107 | move(dir, enter) { | |
| 1108 | if (enter && this.enterChild( | |
| 1109 | dir, | |
| 1110 | 0, | |
| 1111 | 4 | |
| 1112 | /* Side.DontCare */ | |
| 1113 | )) | |
| 1114 | return true; | |
| 1115 | for (; ; ) { | |
| 1116 | if (this.sibling(dir)) | |
| 1117 | return true; | |
| 1118 | if (this.atLastNode(dir) || !this.parent()) | |
| 1119 | return false; | |
| 1120 | } | |
| 1121 | } | |
| 1122 | /** | |
| 1123 | Move to the next node in a | |
| 1124 | [pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR) | |
| 1125 | traversal, going from a node to its first child or, if the | |
| 1126 | current node is empty or `enter` is false, its next sibling or | |
| 1127 | the next sibling of the first parent node that has one. | |
| 1128 | */ | |
| 1129 | next(enter = true) { | |
| 1130 | return this.move(1, enter); | |
| 1131 | } | |
| 1132 | /** | |
| 1133 | Move to the next node in a last-to-first pre-order traversal. A | |
| 1134 | node is followed by its last child or, if it has none, its | |
| 1135 | previous sibling or the previous sibling of the first parent | |
| 1136 | node that has one. | |
| 1137 | */ | |
| 1138 | prev(enter = true) { | |
| 1139 | return this.move(-1, enter); | |
| 1140 | } | |
| 1141 | /** | |
| 1142 | Move the cursor to the innermost node that covers `pos`. If | |
| 1143 | `side` is -1, it will enter nodes that end at `pos`. If it is 1, | |
| 1144 | it will enter nodes that start at `pos`. | |
| 1145 | */ | |
| 1146 | moveTo(pos, side = 0) { | |
| 1147 | while (this.from == this.to || (side < 1 ? this.from >= pos : this.from > pos) || (side > -1 ? this.to <= pos : this.to < pos)) | |
| 1148 | if (!this.parent()) | |
| 1149 | break; | |
| 1150 | while (this.enterChild(1, pos, side)) { | |
| 1151 | } | |
| 1152 | return this; | |
| 1153 | } | |
| 1154 | /** | |
| 1155 | Get a [syntax node](#common.SyntaxNode) at the cursor's current | |
| 1156 | position. | |
| 1157 | */ | |
| 1158 | get node() { | |
| 1159 | if (!this.buffer) | |
| 1160 | return this._tree; | |
| 1161 | let cache = this.bufferNode, result = null, depth = 0; | |
| 1162 | if (cache && cache.context == this.buffer) { | |
| 1163 | scan: for (let index = this.index, d = this.stack.length; d >= 0; ) { | |
| 1164 | for (let c = cache; c; c = c._parent) | |
| 1165 | if (c.index == index) { | |
| 1166 | if (index == this.index) | |
| 1167 | return c; | |
| 1168 | result = c; | |
| 1169 | depth = d + 1; | |
| 1170 | break scan; | |
| 1171 | } | |
| 1172 | index = this.stack[--d]; | |
| 1173 | } | |
| 1174 | } | |
| 1175 | for (let i = depth; i < this.stack.length; i++) | |
| 1176 | result = new BufferNode(this.buffer, result, this.stack[i]); | |
| 1177 | return this.bufferNode = new BufferNode(this.buffer, result, this.index); | |
| 1178 | } | |
| 1179 | /** | |
| 1180 | Get the [tree](#common.Tree) that represents the current node, if | |
| 1181 | any. Will return null when the node is in a [tree | |
| 1182 | buffer](#common.TreeBuffer). | |
| 1183 | */ | |
| 1184 | get tree() { | |
| 1185 | return this.buffer ? null : this._tree._tree; | |
| 1186 | } | |
| 1187 | /** | |
| 1188 | Iterate over the current node and all its descendants, calling | |
| 1189 | `enter` when entering a node and `leave`, if given, when leaving | |
| 1190 | one. When `enter` returns `false`, any children of that node are | |
| 1191 | skipped, and `leave` isn't called for it. | |
| 1192 | */ | |
| 1193 | iterate(enter, leave) { | |
| 1194 | for (let depth = 0; ; ) { | |
| 1195 | let mustLeave = false; | |
| 1196 | if (this.type.isAnonymous || enter(this) !== false) { | |
| 1197 | if (this.firstChild()) { | |
| 1198 | depth++; | |
| 1199 | continue; | |
| 1200 | } | |
| 1201 | if (!this.type.isAnonymous) | |
| 1202 | mustLeave = true; | |
| 1203 | } | |
| 1204 | for (; ; ) { | |
| 1205 | if (mustLeave && leave) | |
| 1206 | leave(this); | |
| 1207 | mustLeave = this.type.isAnonymous; | |
| 1208 | if (!depth) | |
| 1209 | return; | |
| 1210 | if (this.nextSibling()) | |
| 1211 | break; | |
| 1212 | this.parent(); | |
| 1213 | depth--; | |
| 1214 | mustLeave = true; | |
| 1215 | } | |
| 1216 | } | |
| 1217 | } | |
| 1218 | /** | |
| 1219 | Test whether the current node matches a given context—a sequence | |
| 1220 | of direct parent node names. Empty strings in the context array | |
| 1221 | are treated as wildcards. | |
| 1222 | */ | |
| 1223 | matchContext(context) { | |
| 1224 | if (!this.buffer) | |
| 1225 | return matchNodeContext(this.node.parent, context); | |
| 1226 | let { buffer } = this.buffer, { types } = buffer.set; | |
| 1227 | for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) { | |
| 1228 | if (d < 0) | |
| 1229 | return matchNodeContext(this._tree, context, i); | |
| 1230 | let type = types[buffer.buffer[this.stack[d]]]; | |
| 1231 | if (!type.isAnonymous) { | |
| 1232 | if (context[i] && context[i] != type.name) | |
| 1233 | return false; | |
| 1234 | i--; | |
| 1235 | } | |
| 1236 | } | |
| 1237 | return true; | |
| 1238 | } | |
| 1239 | }; | |
| 1240 | function hasChild(tree) { | |
| 1241 | return tree.children.some((ch) => ch instanceof TreeBuffer || !ch.type.isAnonymous || hasChild(ch)); | |
| 1242 | } | |
| 1243 | function buildTree(data) { | |
| 1244 | var _a; | |
| 1245 | let { buffer, nodeSet, maxBufferLength = DefaultBufferLength, reused = [], minRepeatType = nodeSet.types.length } = data; | |
| 1246 | let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer; | |
| 1247 | let types = nodeSet.types; | |
| 1248 | let contextHash = 0, lookAhead = 0; | |
| 1249 | function takeNode(parentStart, minPos, children2, positions2, inRepeat, depth) { | |
| 1250 | let { id, start, end, size } = cursor; | |
| 1251 | let lookAheadAtStart = lookAhead, contextAtStart = contextHash; | |
| 1252 | if (size < 0) { | |
| 1253 | cursor.next(); | |
| 1254 | if (size == -1) { | |
| 1255 | let node2 = reused[id]; | |
| 1256 | children2.push(node2); | |
| 1257 | positions2.push(start - parentStart); | |
| 1258 | return; | |
| 1259 | } else if (size == -3) { | |
| 1260 | contextHash = id; | |
| 1261 | return; | |
| 1262 | } else if (size == -4) { | |
| 1263 | lookAhead = id; | |
| 1264 | return; | |
| 1265 | } else { | |
| 1266 | throw new RangeError(`Unrecognized record size: ${size}`); | |
| 1267 | } | |
| 1268 | } | |
| 1269 | let type = types[id], node, buffer2; | |
| 1270 | let startPos = start - parentStart; | |
| 1271 | if (end - start <= maxBufferLength && (buffer2 = findBufferSize(cursor.pos - minPos, inRepeat))) { | |
| 1272 | let data2 = new Uint16Array(buffer2.size - buffer2.skip); | |
| 1273 | let endPos = cursor.pos - buffer2.size, index = data2.length; | |
| 1274 | while (cursor.pos > endPos) | |
| 1275 | index = copyToBuffer(buffer2.start, data2, index); | |
| 1276 | node = new TreeBuffer(data2, end - buffer2.start, nodeSet); | |
| 1277 | startPos = buffer2.start - parentStart; | |
| 1278 | } else { | |
| 1279 | let endPos = cursor.pos - size; | |
| 1280 | cursor.next(); | |
| 1281 | let localChildren = [], localPositions = []; | |
| 1282 | let localInRepeat = id >= minRepeatType ? id : -1; | |
| 1283 | let lastGroup = 0, lastEnd = end; | |
| 1284 | while (cursor.pos > endPos) { | |
| 1285 | if (localInRepeat >= 0 && cursor.id == localInRepeat && cursor.size >= 0) { | |
| 1286 | if (cursor.end <= lastEnd - maxBufferLength) { | |
| 1287 | makeRepeatLeaf(localChildren, localPositions, start, lastGroup, cursor.end, lastEnd, localInRepeat, lookAheadAtStart, contextAtStart); | |
| 1288 | lastGroup = localChildren.length; | |
| 1289 | lastEnd = cursor.end; | |
| 1290 | } | |
| 1291 | cursor.next(); | |
| 1292 | } else if (depth > 2500) { | |
| 1293 | takeFlatNode(start, endPos, localChildren, localPositions); | |
| 1294 | } else { | |
| 1295 | takeNode(start, endPos, localChildren, localPositions, localInRepeat, depth + 1); | |
| 1296 | } | |
| 1297 | } | |
| 1298 | if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length) | |
| 1299 | makeRepeatLeaf(localChildren, localPositions, start, lastGroup, start, lastEnd, localInRepeat, lookAheadAtStart, contextAtStart); | |
| 1300 | localChildren.reverse(); | |
| 1301 | localPositions.reverse(); | |
| 1302 | if (localInRepeat > -1 && lastGroup > 0) { | |
| 1303 | let make = makeBalanced(type, contextAtStart); | |
| 1304 | node = balanceRange(type, localChildren, localPositions, 0, localChildren.length, 0, end - start, make, make); | |
| 1305 | } else { | |
| 1306 | node = makeTree(type, localChildren, localPositions, end - start, lookAheadAtStart - end, contextAtStart); | |
| 1307 | } | |
| 1308 | } | |
| 1309 | children2.push(node); | |
| 1310 | positions2.push(startPos); | |
| 1311 | } | |
| 1312 | function takeFlatNode(parentStart, minPos, children2, positions2) { | |
| 1313 | let nodes = []; | |
| 1314 | let nodeCount = 0, stopAt = -1; | |
| 1315 | while (cursor.pos > minPos) { | |
| 1316 | let { id, start, end, size } = cursor; | |
| 1317 | if (size > 4) { | |
| 1318 | cursor.next(); | |
| 1319 | } else if (stopAt > -1 && start < stopAt) { | |
| 1320 | break; | |
| 1321 | } else { | |
| 1322 | if (stopAt < 0) | |
| 1323 | stopAt = end - maxBufferLength; | |
| 1324 | nodes.push(id, start, end); | |
| 1325 | nodeCount++; | |
| 1326 | cursor.next(); | |
| 1327 | } | |
| 1328 | } | |
| 1329 | if (nodeCount) { | |
| 1330 | let buffer2 = new Uint16Array(nodeCount * 4); | |
| 1331 | let start = nodes[nodes.length - 2]; | |
| 1332 | for (let i = nodes.length - 3, j = 0; i >= 0; i -= 3) { | |
| 1333 | buffer2[j++] = nodes[i]; | |
| 1334 | buffer2[j++] = nodes[i + 1] - start; | |
| 1335 | buffer2[j++] = nodes[i + 2] - start; | |
| 1336 | buffer2[j++] = j; | |
| 1337 | } | |
| 1338 | children2.push(new TreeBuffer(buffer2, nodes[2] - start, nodeSet)); | |
| 1339 | positions2.push(start - parentStart); | |
| 1340 | } | |
| 1341 | } | |
| 1342 | function makeBalanced(type, contextHash2) { | |
| 1343 | return (children2, positions2, length2) => { | |
| 1344 | let lookAhead2 = 0, lastI = children2.length - 1, last, lookAheadProp; | |
| 1345 | if (lastI >= 0 && (last = children2[lastI]) instanceof Tree) { | |
| 1346 | if (!lastI && last.type == type && last.length == length2) | |
| 1347 | return last; | |
| 1348 | if (lookAheadProp = last.prop(NodeProp.lookAhead)) | |
| 1349 | lookAhead2 = positions2[lastI] + last.length + lookAheadProp; | |
| 1350 | } | |
| 1351 | return makeTree(type, children2, positions2, length2, lookAhead2, contextHash2); | |
| 1352 | }; | |
| 1353 | } | |
| 1354 | function makeRepeatLeaf(children2, positions2, base, i, from, to, type, lookAhead2, contextHash2) { | |
| 1355 | let localChildren = [], localPositions = []; | |
| 1356 | while (children2.length > i) { | |
| 1357 | localChildren.push(children2.pop()); | |
| 1358 | localPositions.push(positions2.pop() + base - from); | |
| 1359 | } | |
| 1360 | children2.push(makeTree(nodeSet.types[type], localChildren, localPositions, to - from, lookAhead2 - to, contextHash2)); | |
| 1361 | positions2.push(from - base); | |
| 1362 | } | |
| 1363 | function makeTree(type, children2, positions2, length2, lookAhead2, contextHash2, props) { | |
| 1364 | if (contextHash2) { | |
| 1365 | let pair2 = [NodeProp.contextHash, contextHash2]; | |
| 1366 | props = props ? [pair2].concat(props) : [pair2]; | |
| 1367 | } | |
| 1368 | if (lookAhead2 > 25) { | |
| 1369 | let pair2 = [NodeProp.lookAhead, lookAhead2]; | |
| 1370 | props = props ? [pair2].concat(props) : [pair2]; | |
| 1371 | } | |
| 1372 | return new Tree(type, children2, positions2, length2, props); | |
| 1373 | } | |
| 1374 | function findBufferSize(maxSize, inRepeat) { | |
| 1375 | let fork = cursor.fork(); | |
| 1376 | let size = 0, start = 0, skip = 0, minStart = fork.end - maxBufferLength; | |
| 1377 | let result = { size: 0, start: 0, skip: 0 }; | |
| 1378 | scan: for (let minPos = fork.pos - maxSize; fork.pos > minPos; ) { | |
| 1379 | let nodeSize2 = fork.size; | |
| 1380 | if (fork.id == inRepeat && nodeSize2 >= 0) { | |
| 1381 | result.size = size; | |
| 1382 | result.start = start; | |
| 1383 | result.skip = skip; | |
| 1384 | skip += 4; | |
| 1385 | size += 4; | |
| 1386 | fork.next(); | |
| 1387 | continue; | |
| 1388 | } | |
| 1389 | let startPos = fork.pos - nodeSize2; | |
| 1390 | if (nodeSize2 < 0 || startPos < minPos || fork.start < minStart) | |
| 1391 | break; | |
| 1392 | let localSkipped = fork.id >= minRepeatType ? 4 : 0; | |
| 1393 | let nodeStart = fork.start; | |
| 1394 | fork.next(); | |
| 1395 | while (fork.pos > startPos) { | |
| 1396 | if (fork.size < 0) { | |
| 1397 | if (fork.size == -3 || fork.size == -4) | |
| 1398 | localSkipped += 4; | |
| 1399 | else | |
| 1400 | break scan; | |
| 1401 | } else if (fork.id >= minRepeatType) { | |
| 1402 | localSkipped += 4; | |
| 1403 | } | |
| 1404 | fork.next(); | |
| 1405 | } | |
| 1406 | start = nodeStart; | |
| 1407 | size += nodeSize2; | |
| 1408 | skip += localSkipped; | |
| 1409 | } | |
| 1410 | if (inRepeat < 0 || size == maxSize) { | |
| 1411 | result.size = size; | |
| 1412 | result.start = start; | |
| 1413 | result.skip = skip; | |
| 1414 | } | |
| 1415 | return result.size > 4 ? result : void 0; | |
| 1416 | } | |
| 1417 | function copyToBuffer(bufferStart, buffer2, index) { | |
| 1418 | let { id, start, end, size } = cursor; | |
| 1419 | cursor.next(); | |
| 1420 | if (size >= 0 && id < minRepeatType) { | |
| 1421 | let startIndex = index; | |
| 1422 | if (size > 4) { | |
| 1423 | let endPos = cursor.pos - (size - 4); | |
| 1424 | while (cursor.pos > endPos) | |
| 1425 | index = copyToBuffer(bufferStart, buffer2, index); | |
| 1426 | } | |
| 1427 | buffer2[--index] = startIndex; | |
| 1428 | buffer2[--index] = end - bufferStart; | |
| 1429 | buffer2[--index] = start - bufferStart; | |
| 1430 | buffer2[--index] = id; | |
| 1431 | } else if (size == -3) { | |
| 1432 | contextHash = id; | |
| 1433 | } else if (size == -4) { | |
| 1434 | lookAhead = id; | |
| 1435 | } | |
| 1436 | return index; | |
| 1437 | } | |
| 1438 | let children = [], positions = []; | |
| 1439 | while (cursor.pos > 0) | |
| 1440 | takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1, 0); | |
| 1441 | let length = (_a = data.length) !== null && _a !== void 0 ? _a : children.length ? positions[0] + children[0].length : 0; | |
| 1442 | return new Tree(types[data.topID], children.reverse(), positions.reverse(), length); | |
| 1443 | } | |
| 1444 | var nodeSizeCache = /* @__PURE__ */ new WeakMap(); | |
| 1445 | function nodeSize(balanceType, node) { | |
| 1446 | if (!balanceType.isAnonymous || node instanceof TreeBuffer || node.type != balanceType) | |
| 1447 | return 1; | |
| 1448 | let size = nodeSizeCache.get(node); | |
| 1449 | if (size == null) { | |
| 1450 | size = 1; | |
| 1451 | for (let child of node.children) { | |
| 1452 | if (child.type != balanceType || !(child instanceof Tree)) { | |
| 1453 | size = 1; | |
| 1454 | break; | |
| 1455 | } | |
| 1456 | size += nodeSize(balanceType, child); | |
| 1457 | } | |
| 1458 | nodeSizeCache.set(node, size); | |
| 1459 | } | |
| 1460 | return size; | |
| 1461 | } | |
| 1462 | function balanceRange(balanceType, children, positions, from, to, start, length, mkTop, mkTree) { | |
| 1463 | let total = 0; | |
| 1464 | for (let i = from; i < to; i++) | |
| 1465 | total += nodeSize(balanceType, children[i]); | |
| 1466 | let maxChild = Math.ceil( | |
| 1467 | total * 1.5 / 8 | |
| 1468 | /* Balance.BranchFactor */ | |
| 1469 | ); | |
| 1470 | let localChildren = [], localPositions = []; | |
| 1471 | function divide(children2, positions2, from2, to2, offset) { | |
| 1472 | for (let i = from2; i < to2; ) { | |
| 1473 | let groupFrom = i, groupStart = positions2[i], groupSize = nodeSize(balanceType, children2[i]); | |
| 1474 | i++; | |
| 1475 | for (; i < to2; i++) { | |
| 1476 | let nextSize = nodeSize(balanceType, children2[i]); | |
| 1477 | if (groupSize + nextSize >= maxChild) | |
| 1478 | break; | |
| 1479 | groupSize += nextSize; | |
| 1480 | } | |
| 1481 | if (i == groupFrom + 1) { | |
| 1482 | if (groupSize > maxChild) { | |
| 1483 | let only = children2[groupFrom]; | |
| 1484 | divide(only.children, only.positions, 0, only.children.length, positions2[groupFrom] + offset); | |
| 1485 | continue; | |
| 1486 | } | |
| 1487 | localChildren.push(children2[groupFrom]); | |
| 1488 | } else { | |
| 1489 | let length2 = positions2[i - 1] + children2[i - 1].length - groupStart; | |
| 1490 | localChildren.push(balanceRange(balanceType, children2, positions2, groupFrom, i, groupStart, length2, null, mkTree)); | |
| 1491 | } | |
| 1492 | localPositions.push(groupStart + offset - start); | |
| 1493 | } | |
| 1494 | } | |
| 1495 | divide(children, positions, from, to, 0); | |
| 1496 | return (mkTop || mkTree)(localChildren, localPositions, length); | |
| 1497 | } | |
| 1498 | var Parser = class { | |
| 1499 | /** | |
| 1500 | Start a parse, returning a [partial parse](#common.PartialParse) | |
| 1501 | object. [`fragments`](#common.TreeFragment) can be passed in to | |
| 1502 | make the parse incremental. | |
| 1503 | ||
| 1504 | By default, the entire input is parsed. You can pass `ranges`, | |
| 1505 | which should be a sorted array of non-empty, non-overlapping | |
| 1506 | ranges, to parse only those ranges. The tree returned in that | |
| 1507 | case will start at `ranges[0].from`. | |
| 1508 | */ | |
| 1509 | startParse(input, fragments, ranges) { | |
| 1510 | if (typeof input == "string") | |
| 1511 | input = new StringInput(input); | |
| 1512 | ranges = !ranges ? [new Range(0, input.length)] : ranges.length ? ranges.map((r) => new Range(r.from, r.to)) : [new Range(0, 0)]; | |
| 1513 | return this.createParse(input, fragments || [], ranges); | |
| 1514 | } | |
| 1515 | /** | |
| 1516 | Run a full parse, returning the resulting tree. | |
| 1517 | */ | |
| 1518 | parse(input, fragments, ranges) { | |
| 1519 | let parse = this.startParse(input, fragments, ranges); | |
| 1520 | for (; ; ) { | |
| 1521 | let done = parse.advance(); | |
| 1522 | if (done) | |
| 1523 | return done; | |
| 1524 | } | |
| 1525 | } | |
| 1526 | }; | |
| 1527 | var StringInput = class { | |
| 1528 | constructor(string2) { | |
| 1529 | this.string = string2; | |
| 1530 | } | |
| 1531 | get length() { | |
| 1532 | return this.string.length; | |
| 1533 | } | |
| 1534 | chunk(from) { | |
| 1535 | return this.string.slice(from); | |
| 1536 | } | |
| 1537 | get lineChunks() { | |
| 1538 | return false; | |
| 1539 | } | |
| 1540 | read(from, to) { | |
| 1541 | return this.string.slice(from, to); | |
| 1542 | } | |
| 1543 | }; | |
| 1544 | var stoppedInner = new NodeProp({ perNode: true }); | |
| 1545 | ||
| 1546 | // node_modules/@lezer/lr/dist/index.js | |
| 1547 | var Stack = class _Stack { | |
| 1548 | /** | |
| 1549 | @internal | |
| 1550 | */ | |
| 1551 | constructor(p, stack, state, reducePos, pos, score, buffer, bufferBase, curContext, lookAhead = 0, parent) { | |
| 1552 | this.p = p; | |
| 1553 | this.stack = stack; | |
| 1554 | this.state = state; | |
| 1555 | this.reducePos = reducePos; | |
| 1556 | this.pos = pos; | |
| 1557 | this.score = score; | |
| 1558 | this.buffer = buffer; | |
| 1559 | this.bufferBase = bufferBase; | |
| 1560 | this.curContext = curContext; | |
| 1561 | this.lookAhead = lookAhead; | |
| 1562 | this.parent = parent; | |
| 1563 | } | |
| 1564 | /** | |
| 1565 | @internal | |
| 1566 | */ | |
| 1567 | toString() { | |
| 1568 | return `[${this.stack.filter((_, i) => i % 3 == 0).concat(this.state)}]@${this.pos}${this.score ? "!" + this.score : ""}`; | |
| 1569 | } | |
| 1570 | // Start an empty stack | |
| 1571 | /** | |
| 1572 | @internal | |
| 1573 | */ | |
| 1574 | static start(p, state, pos = 0) { | |
| 1575 | let cx = p.parser.context; | |
| 1576 | return new _Stack(p, [], state, pos, pos, 0, [], 0, cx ? new StackContext(cx, cx.start) : null, 0, null); | |
| 1577 | } | |
| 1578 | /** | |
| 1579 | The stack's current [context](#lr.ContextTracker) value, if | |
| 1580 | any. Its type will depend on the context tracker's type | |
| 1581 | parameter, or it will be `null` if there is no context | |
| 1582 | tracker. | |
| 1583 | */ | |
| 1584 | get context() { | |
| 1585 | return this.curContext ? this.curContext.context : null; | |
| 1586 | } | |
| 1587 | // Push a state onto the stack, tracking its start position as well | |
| 1588 | // as the buffer base at that point. | |
| 1589 | /** | |
| 1590 | @internal | |
| 1591 | */ | |
| 1592 | pushState(state, start) { | |
| 1593 | this.stack.push(this.state, start, this.bufferBase + this.buffer.length); | |
| 1594 | this.state = state; | |
| 1595 | } | |
| 1596 | // Apply a reduce action | |
| 1597 | /** | |
| 1598 | @internal | |
| 1599 | */ | |
| 1600 | reduce(action) { | |
| 1601 | var _a; | |
| 1602 | let depth = action >> 19, type = action & 65535; | |
| 1603 | let { parser: parser2 } = this.p; | |
| 1604 | let lookaheadRecord = this.reducePos < this.pos - 25 && this.setLookAhead(this.pos); | |
| 1605 | let dPrec = parser2.dynamicPrecedence(type); | |
| 1606 | if (dPrec) | |
| 1607 | this.score += dPrec; | |
| 1608 | if (depth == 0) { | |
| 1609 | this.pushState(parser2.getGoto(this.state, type, true), this.reducePos); | |
| 1610 | if (type < parser2.minRepeatTerm) | |
| 1611 | this.storeNode(type, this.reducePos, this.reducePos, lookaheadRecord ? 8 : 4, true); | |
| 1612 | this.reduceContext(type, this.reducePos); | |
| 1613 | return; | |
| 1614 | } | |
| 1615 | let base = this.stack.length - (depth - 1) * 3 - (action & 262144 ? 6 : 0); | |
| 1616 | let start = base ? this.stack[base - 2] : this.p.ranges[0].from, size = this.reducePos - start; | |
| 1617 | if (size >= 2e3 && !((_a = this.p.parser.nodeSet.types[type]) === null || _a === void 0 ? void 0 : _a.isAnonymous)) { | |
| 1618 | if (start == this.p.lastBigReductionStart) { | |
| 1619 | this.p.bigReductionCount++; | |
| 1620 | this.p.lastBigReductionSize = size; | |
| 1621 | } else if (this.p.lastBigReductionSize < size) { | |
| 1622 | this.p.bigReductionCount = 1; | |
| 1623 | this.p.lastBigReductionStart = start; | |
| 1624 | this.p.lastBigReductionSize = size; | |
| 1625 | } | |
| 1626 | } | |
| 1627 | let bufferBase = base ? this.stack[base - 1] : 0, count = this.bufferBase + this.buffer.length - bufferBase; | |
| 1628 | if (type < parser2.minRepeatTerm || action & 131072) { | |
| 1629 | let pos = parser2.stateFlag( | |
| 1630 | this.state, | |
| 1631 | 1 | |
| 1632 | /* StateFlag.Skipped */ | |
| 1633 | ) ? this.pos : this.reducePos; | |
| 1634 | this.storeNode(type, start, pos, count + 4, true); | |
| 1635 | } | |
| 1636 | if (action & 262144) { | |
| 1637 | this.state = this.stack[base]; | |
| 1638 | } else { | |
| 1639 | let baseStateID = this.stack[base - 3]; | |
| 1640 | this.state = parser2.getGoto(baseStateID, type, true); | |
| 1641 | } | |
| 1642 | while (this.stack.length > base) | |
| 1643 | this.stack.pop(); | |
| 1644 | this.reduceContext(type, start); | |
| 1645 | } | |
| 1646 | // Shift a value into the buffer | |
| 1647 | /** | |
| 1648 | @internal | |
| 1649 | */ | |
| 1650 | storeNode(term, start, end, size = 4, mustSink = false) { | |
| 1651 | if (term == 0 && (!this.stack.length || this.stack[this.stack.length - 1] < this.buffer.length + this.bufferBase)) { | |
| 1652 | let cur = this, top = this.buffer.length; | |
| 1653 | if (top == 0 && cur.parent) { | |
| 1654 | top = cur.bufferBase - cur.parent.bufferBase; | |
| 1655 | cur = cur.parent; | |
| 1656 | } | |
| 1657 | if (top > 0 && cur.buffer[top - 4] == 0 && cur.buffer[top - 1] > -1) { | |
| 1658 | if (start == end) | |
| 1659 | return; | |
| 1660 | if (cur.buffer[top - 2] >= start) { | |
| 1661 | cur.buffer[top - 2] = end; | |
| 1662 | return; | |
| 1663 | } | |
| 1664 | } | |
| 1665 | } | |
| 1666 | if (!mustSink || this.pos == end) { | |
| 1667 | this.buffer.push(term, start, end, size); | |
| 1668 | } else { | |
| 1669 | let index = this.buffer.length; | |
| 1670 | if (index > 0 && (this.buffer[index - 4] != 0 || this.buffer[index - 1] < 0)) { | |
| 1671 | let mustMove = false; | |
| 1672 | for (let scan = index; scan > 0 && this.buffer[scan - 2] > end; scan -= 4) { | |
| 1673 | if (this.buffer[scan - 1] >= 0) { | |
| 1674 | mustMove = true; | |
| 1675 | break; | |
| 1676 | } | |
| 1677 | } | |
| 1678 | if (mustMove) | |
| 1679 | while (index > 0 && this.buffer[index - 2] > end) { | |
| 1680 | this.buffer[index] = this.buffer[index - 4]; | |
| 1681 | this.buffer[index + 1] = this.buffer[index - 3]; | |
| 1682 | this.buffer[index + 2] = this.buffer[index - 2]; | |
| 1683 | this.buffer[index + 3] = this.buffer[index - 1]; | |
| 1684 | index -= 4; | |
| 1685 | if (size > 4) | |
| 1686 | size -= 4; | |
| 1687 | } | |
| 1688 | } | |
| 1689 | this.buffer[index] = term; | |
| 1690 | this.buffer[index + 1] = start; | |
| 1691 | this.buffer[index + 2] = end; | |
| 1692 | this.buffer[index + 3] = size; | |
| 1693 | } | |
| 1694 | } | |
| 1695 | // Apply a shift action | |
| 1696 | /** | |
| 1697 | @internal | |
| 1698 | */ | |
| 1699 | shift(action, type, start, end) { | |
| 1700 | if (action & 131072) { | |
| 1701 | this.pushState(action & 65535, this.pos); | |
| 1702 | } else if ((action & 262144) == 0) { | |
| 1703 | let nextState = action, { parser: parser2 } = this.p; | |
| 1704 | this.pos = end; | |
| 1705 | let skipped = parser2.stateFlag( | |
| 1706 | nextState, | |
| 1707 | 1 | |
| 1708 | /* StateFlag.Skipped */ | |
| 1709 | ); | |
| 1710 | if (!skipped && (end > start || type <= parser2.maxNode)) | |
| 1711 | this.reducePos = end; | |
| 1712 | this.pushState(nextState, skipped ? start : Math.min(start, this.reducePos)); | |
| 1713 | this.shiftContext(type, start); | |
| 1714 | if (type <= parser2.maxNode) | |
| 1715 | this.buffer.push(type, start, end, 4); | |
| 1716 | } else { | |
| 1717 | this.pos = end; | |
| 1718 | this.shiftContext(type, start); | |
| 1719 | if (type <= this.p.parser.maxNode) | |
| 1720 | this.buffer.push(type, start, end, 4); | |
| 1721 | } | |
| 1722 | } | |
| 1723 | // Apply an action | |
| 1724 | /** | |
| 1725 | @internal | |
| 1726 | */ | |
| 1727 | apply(action, next, nextStart, nextEnd) { | |
| 1728 | if (action & 65536) | |
| 1729 | this.reduce(action); | |
| 1730 | else | |
| 1731 | this.shift(action, next, nextStart, nextEnd); | |
| 1732 | } | |
| 1733 | // Add a prebuilt (reused) node into the buffer. | |
| 1734 | /** | |
| 1735 | @internal | |
| 1736 | */ | |
| 1737 | useNode(value, next) { | |
| 1738 | let index = this.p.reused.length - 1; | |
| 1739 | if (index < 0 || this.p.reused[index] != value) { | |
| 1740 | this.p.reused.push(value); | |
| 1741 | index++; | |
| 1742 | } | |
| 1743 | let start = this.pos; | |
| 1744 | this.reducePos = this.pos = start + value.length; | |
| 1745 | this.pushState(next, start); | |
| 1746 | this.buffer.push( | |
| 1747 | index, | |
| 1748 | start, | |
| 1749 | this.reducePos, | |
| 1750 | -1 | |
| 1751 | /* size == -1 means this is a reused value */ | |
| 1752 | ); | |
| 1753 | if (this.curContext) | |
| 1754 | this.updateContext(this.curContext.tracker.reuse(this.curContext.context, value, this, this.p.stream.reset(this.pos - value.length))); | |
| 1755 | } | |
| 1756 | // Split the stack. Due to the buffer sharing and the fact | |
| 1757 | // that `this.stack` tends to stay quite shallow, this isn't very | |
| 1758 | // expensive. | |
| 1759 | /** | |
| 1760 | @internal | |
| 1761 | */ | |
| 1762 | split() { | |
| 1763 | let parent = this; | |
| 1764 | let off = parent.buffer.length; | |
| 1765 | while (off > 0 && parent.buffer[off - 2] > parent.reducePos) | |
| 1766 | off -= 4; | |
| 1767 | let buffer = parent.buffer.slice(off), base = parent.bufferBase + off; | |
| 1768 | while (parent && base == parent.bufferBase) | |
| 1769 | parent = parent.parent; | |
| 1770 | return new _Stack(this.p, this.stack.slice(), this.state, this.reducePos, this.pos, this.score, buffer, base, this.curContext, this.lookAhead, parent); | |
| 1771 | } | |
| 1772 | // Try to recover from an error by 'deleting' (ignoring) one token. | |
| 1773 | /** | |
| 1774 | @internal | |
| 1775 | */ | |
| 1776 | recoverByDelete(next, nextEnd) { | |
| 1777 | let isNode = next <= this.p.parser.maxNode; | |
| 1778 | if (isNode) | |
| 1779 | this.storeNode(next, this.pos, nextEnd, 4); | |
| 1780 | this.storeNode(0, this.pos, nextEnd, isNode ? 8 : 4); | |
| 1781 | this.pos = this.reducePos = nextEnd; | |
| 1782 | this.score -= 190; | |
| 1783 | } | |
| 1784 | /** | |
| 1785 | Check if the given term would be able to be shifted (optionally | |
| 1786 | after some reductions) on this stack. This can be useful for | |
| 1787 | external tokenizers that want to make sure they only provide a | |
| 1788 | given token when it applies. | |
| 1789 | */ | |
| 1790 | canShift(term) { | |
| 1791 | for (let sim = new SimulatedStack(this); ; ) { | |
| 1792 | let action = this.p.parser.stateSlot( | |
| 1793 | sim.state, | |
| 1794 | 4 | |
| 1795 | /* ParseState.DefaultReduce */ | |
| 1796 | ) || this.p.parser.hasAction(sim.state, term); | |
| 1797 | if (action == 0) | |
| 1798 | return false; | |
| 1799 | if ((action & 65536) == 0) | |
| 1800 | return true; | |
| 1801 | sim.reduce(action); | |
| 1802 | } | |
| 1803 | } | |
| 1804 | // Apply up to Recover.MaxNext recovery actions that conceptually | |
| 1805 | // inserts some missing token or rule. | |
| 1806 | /** | |
| 1807 | @internal | |
| 1808 | */ | |
| 1809 | recoverByInsert(next) { | |
| 1810 | if (this.stack.length >= 300) | |
| 1811 | return []; | |
| 1812 | let nextStates = this.p.parser.nextStates(this.state); | |
| 1813 | if (nextStates.length > 4 << 1 || this.stack.length >= 120) { | |
| 1814 | let best = []; | |
| 1815 | for (let i = 0, s; i < nextStates.length; i += 2) { | |
| 1816 | if ((s = nextStates[i + 1]) != this.state && this.p.parser.hasAction(s, next)) | |
| 1817 | best.push(nextStates[i], s); | |
| 1818 | } | |
| 1819 | if (this.stack.length < 120) | |
| 1820 | for (let i = 0; best.length < 4 << 1 && i < nextStates.length; i += 2) { | |
| 1821 | let s = nextStates[i + 1]; | |
| 1822 | if (!best.some((v, i2) => i2 & 1 && v == s)) | |
| 1823 | best.push(nextStates[i], s); | |
| 1824 | } | |
| 1825 | nextStates = best; | |
| 1826 | } | |
| 1827 | let result = []; | |
| 1828 | for (let i = 0; i < nextStates.length && result.length < 4; i += 2) { | |
| 1829 | let s = nextStates[i + 1]; | |
| 1830 | if (s == this.state) | |
| 1831 | continue; | |
| 1832 | let stack = this.split(); | |
| 1833 | stack.pushState(s, this.pos); | |
| 1834 | stack.storeNode(0, stack.pos, stack.pos, 4, true); | |
| 1835 | stack.shiftContext(nextStates[i], this.pos); | |
| 1836 | stack.reducePos = this.pos; | |
| 1837 | stack.score -= 200; | |
| 1838 | result.push(stack); | |
| 1839 | } | |
| 1840 | return result; | |
| 1841 | } | |
| 1842 | // Force a reduce, if possible. Return false if that can't | |
| 1843 | // be done. | |
| 1844 | /** | |
| 1845 | @internal | |
| 1846 | */ | |
| 1847 | forceReduce() { | |
| 1848 | let { parser: parser2 } = this.p; | |
| 1849 | let reduce = parser2.stateSlot( | |
| 1850 | this.state, | |
| 1851 | 5 | |
| 1852 | /* ParseState.ForcedReduce */ | |
| 1853 | ); | |
| 1854 | if ((reduce & 65536) == 0) | |
| 1855 | return false; | |
| 1856 | if (!parser2.validAction(this.state, reduce)) { | |
| 1857 | let depth = reduce >> 19, term = reduce & 65535; | |
| 1858 | let target = this.stack.length - depth * 3; | |
| 1859 | if (target < 0 || parser2.getGoto(this.stack[target], term, false) < 0) { | |
| 1860 | let backup = this.findForcedReduction(); | |
| 1861 | if (backup == null) | |
| 1862 | return false; | |
| 1863 | reduce = backup; | |
| 1864 | } | |
| 1865 | this.storeNode(0, this.pos, this.pos, 4, true); | |
| 1866 | this.score -= 100; | |
| 1867 | } | |
| 1868 | this.reducePos = this.pos; | |
| 1869 | this.reduce(reduce); | |
| 1870 | return true; | |
| 1871 | } | |
| 1872 | /** | |
| 1873 | Try to scan through the automaton to find some kind of reduction | |
| 1874 | that can be applied. Used when the regular ForcedReduce field | |
| 1875 | isn't a valid action. @internal | |
| 1876 | */ | |
| 1877 | findForcedReduction() { | |
| 1878 | let { parser: parser2 } = this.p, seen = []; | |
| 1879 | let explore = (state, depth) => { | |
| 1880 | if (seen.includes(state)) | |
| 1881 | return; | |
| 1882 | seen.push(state); | |
| 1883 | return parser2.allActions(state, (action) => { | |
| 1884 | if (action & (262144 | 131072)) ; | |
| 1885 | else if (action & 65536) { | |
| 1886 | let rDepth = (action >> 19) - depth; | |
| 1887 | if (rDepth > 1) { | |
| 1888 | let term = action & 65535, target = this.stack.length - rDepth * 3; | |
| 1889 | if (target >= 0 && parser2.getGoto(this.stack[target], term, false) >= 0) | |
| 1890 | return rDepth << 19 | 65536 | term; | |
| 1891 | } | |
| 1892 | } else { | |
| 1893 | let found = explore(action, depth + 1); | |
| 1894 | if (found != null) | |
| 1895 | return found; | |
| 1896 | } | |
| 1897 | }); | |
| 1898 | }; | |
| 1899 | return explore(this.state, 0); | |
| 1900 | } | |
| 1901 | /** | |
| 1902 | @internal | |
| 1903 | */ | |
| 1904 | forceAll() { | |
| 1905 | while (!this.p.parser.stateFlag( | |
| 1906 | this.state, | |
| 1907 | 2 | |
| 1908 | /* StateFlag.Accepting */ | |
| 1909 | )) { | |
| 1910 | if (!this.forceReduce()) { | |
| 1911 | this.storeNode(0, this.pos, this.pos, 4, true); | |
| 1912 | break; | |
| 1913 | } | |
| 1914 | } | |
| 1915 | return this; | |
| 1916 | } | |
| 1917 | /** | |
| 1918 | Check whether this state has no further actions (assumed to be a direct descendant of the | |
| 1919 | top state, since any other states must be able to continue | |
| 1920 | somehow). @internal | |
| 1921 | */ | |
| 1922 | get deadEnd() { | |
| 1923 | if (this.stack.length != 3) | |
| 1924 | return false; | |
| 1925 | let { parser: parser2 } = this.p; | |
| 1926 | return parser2.data[parser2.stateSlot( | |
| 1927 | this.state, | |
| 1928 | 1 | |
| 1929 | /* ParseState.Actions */ | |
| 1930 | )] == 65535 && !parser2.stateSlot( | |
| 1931 | this.state, | |
| 1932 | 4 | |
| 1933 | /* ParseState.DefaultReduce */ | |
| 1934 | ); | |
| 1935 | } | |
| 1936 | /** | |
| 1937 | Restart the stack (put it back in its start state). Only safe | |
| 1938 | when this.stack.length == 3 (state is directly below the top | |
| 1939 | state). @internal | |
| 1940 | */ | |
| 1941 | restart() { | |
| 1942 | this.storeNode(0, this.pos, this.pos, 4, true); | |
| 1943 | this.state = this.stack[0]; | |
| 1944 | this.stack.length = 0; | |
| 1945 | } | |
| 1946 | /** | |
| 1947 | @internal | |
| 1948 | */ | |
| 1949 | sameState(other) { | |
| 1950 | if (this.state != other.state || this.stack.length != other.stack.length) | |
| 1951 | return false; | |
| 1952 | for (let i = 0; i < this.stack.length; i += 3) | |
| 1953 | if (this.stack[i] != other.stack[i]) | |
| 1954 | return false; | |
| 1955 | return true; | |
| 1956 | } | |
| 1957 | /** | |
| 1958 | Get the parser used by this stack. | |
| 1959 | */ | |
| 1960 | get parser() { | |
| 1961 | return this.p.parser; | |
| 1962 | } | |
| 1963 | /** | |
| 1964 | Test whether a given dialect (by numeric ID, as exported from | |
| 1965 | the terms file) is enabled. | |
| 1966 | */ | |
| 1967 | dialectEnabled(dialectID) { | |
| 1968 | return this.p.parser.dialect.flags[dialectID]; | |
| 1969 | } | |
| 1970 | shiftContext(term, start) { | |
| 1971 | if (this.curContext) | |
| 1972 | this.updateContext(this.curContext.tracker.shift(this.curContext.context, term, this, this.p.stream.reset(start))); | |
| 1973 | } | |
| 1974 | reduceContext(term, start) { | |
| 1975 | if (this.curContext) | |
| 1976 | this.updateContext(this.curContext.tracker.reduce(this.curContext.context, term, this, this.p.stream.reset(start))); | |
| 1977 | } | |
| 1978 | /** | |
| 1979 | @internal | |
| 1980 | */ | |
| 1981 | emitContext() { | |
| 1982 | let last = this.buffer.length - 1; | |
| 1983 | if (last < 0 || this.buffer[last] != -3) | |
| 1984 | this.buffer.push(this.curContext.hash, this.pos, this.pos, -3); | |
| 1985 | } | |
| 1986 | /** | |
| 1987 | @internal | |
| 1988 | */ | |
| 1989 | emitLookAhead() { | |
| 1990 | let last = this.buffer.length - 1; | |
| 1991 | if (last < 0 || this.buffer[last] != -4) | |
| 1992 | this.buffer.push(this.lookAhead, this.pos, this.pos, -4); | |
| 1993 | } | |
| 1994 | updateContext(context) { | |
| 1995 | if (context != this.curContext.context) { | |
| 1996 | let newCx = new StackContext(this.curContext.tracker, context); | |
| 1997 | if (newCx.hash != this.curContext.hash) | |
| 1998 | this.emitContext(); | |
| 1999 | this.curContext = newCx; | |
| 2000 | } | |
| 2001 | } | |
| 2002 | /** | |
| 2003 | @internal | |
| 2004 | */ | |
| 2005 | setLookAhead(lookAhead) { | |
| 2006 | if (lookAhead <= this.lookAhead) | |
| 2007 | return false; | |
| 2008 | this.emitLookAhead(); | |
| 2009 | this.lookAhead = lookAhead; | |
| 2010 | return true; | |
| 2011 | } | |
| 2012 | /** | |
| 2013 | @internal | |
| 2014 | */ | |
| 2015 | close() { | |
| 2016 | if (this.curContext && this.curContext.tracker.strict) | |
| 2017 | this.emitContext(); | |
| 2018 | if (this.lookAhead > 0) | |
| 2019 | this.emitLookAhead(); | |
| 2020 | } | |
| 2021 | }; | |
| 2022 | var StackContext = class { | |
| 2023 | constructor(tracker, context) { | |
| 2024 | this.tracker = tracker; | |
| 2025 | this.context = context; | |
| 2026 | this.hash = tracker.strict ? tracker.hash(context) : 0; | |
| 2027 | } | |
| 2028 | }; | |
| 2029 | var SimulatedStack = class { | |
| 2030 | constructor(start) { | |
| 2031 | this.start = start; | |
| 2032 | this.state = start.state; | |
| 2033 | this.stack = start.stack; | |
| 2034 | this.base = this.stack.length; | |
| 2035 | } | |
| 2036 | reduce(action) { | |
| 2037 | let term = action & 65535, depth = action >> 19; | |
| 2038 | if (depth == 0) { | |
| 2039 | if (this.stack == this.start.stack) | |
| 2040 | this.stack = this.stack.slice(); | |
| 2041 | this.stack.push(this.state, 0, 0); | |
| 2042 | this.base += 3; | |
| 2043 | } else { | |
| 2044 | this.base -= (depth - 1) * 3; | |
| 2045 | } | |
| 2046 | let goto = this.start.p.parser.getGoto(this.stack[this.base - 3], term, true); | |
| 2047 | this.state = goto; | |
| 2048 | } | |
| 2049 | }; | |
| 2050 | var StackBufferCursor = class _StackBufferCursor { | |
| 2051 | constructor(stack, pos, index) { | |
| 2052 | this.stack = stack; | |
| 2053 | this.pos = pos; | |
| 2054 | this.index = index; | |
| 2055 | this.buffer = stack.buffer; | |
| 2056 | if (this.index == 0) | |
| 2057 | this.maybeNext(); | |
| 2058 | } | |
| 2059 | static create(stack, pos = stack.bufferBase + stack.buffer.length) { | |
| 2060 | return new _StackBufferCursor(stack, pos, pos - stack.bufferBase); | |
| 2061 | } | |
| 2062 | maybeNext() { | |
| 2063 | let next = this.stack.parent; | |
| 2064 | if (next != null) { | |
| 2065 | this.index = this.stack.bufferBase - next.bufferBase; | |
| 2066 | this.stack = next; | |
| 2067 | this.buffer = next.buffer; | |
| 2068 | } | |
| 2069 | } | |
| 2070 | get id() { | |
| 2071 | return this.buffer[this.index - 4]; | |
| 2072 | } | |
| 2073 | get start() { | |
| 2074 | return this.buffer[this.index - 3]; | |
| 2075 | } | |
| 2076 | get end() { | |
| 2077 | return this.buffer[this.index - 2]; | |
| 2078 | } | |
| 2079 | get size() { | |
| 2080 | return this.buffer[this.index - 1]; | |
| 2081 | } | |
| 2082 | next() { | |
| 2083 | this.index -= 4; | |
| 2084 | this.pos -= 4; | |
| 2085 | if (this.index == 0) | |
| 2086 | this.maybeNext(); | |
| 2087 | } | |
| 2088 | fork() { | |
| 2089 | return new _StackBufferCursor(this.stack, this.pos, this.index); | |
| 2090 | } | |
| 2091 | }; | |
| 2092 | function decodeArray(input, Type = Uint16Array) { | |
| 2093 | if (typeof input != "string") | |
| 2094 | return input; | |
| 2095 | let array = null; | |
| 2096 | for (let pos = 0, out = 0; pos < input.length; ) { | |
| 2097 | let value = 0; | |
| 2098 | for (; ; ) { | |
| 2099 | let next = input.charCodeAt(pos++), stop = false; | |
| 2100 | if (next == 126) { | |
| 2101 | value = 65535; | |
| 2102 | break; | |
| 2103 | } | |
| 2104 | if (next >= 92) | |
| 2105 | next--; | |
| 2106 | if (next >= 34) | |
| 2107 | next--; | |
| 2108 | let digit = next - 32; | |
| 2109 | if (digit >= 46) { | |
| 2110 | digit -= 46; | |
| 2111 | stop = true; | |
| 2112 | } | |
| 2113 | value += digit; | |
| 2114 | if (stop) | |
| 2115 | break; | |
| 2116 | value *= 46; | |
| 2117 | } | |
| 2118 | if (array) | |
| 2119 | array[out++] = value; | |
| 2120 | else | |
| 2121 | array = new Type(value); | |
| 2122 | } | |
| 2123 | return array; | |
| 2124 | } | |
| 2125 | var CachedToken = class { | |
| 2126 | constructor() { | |
| 2127 | this.start = -1; | |
| 2128 | this.value = -1; | |
| 2129 | this.end = -1; | |
| 2130 | this.extended = -1; | |
| 2131 | this.lookAhead = 0; | |
| 2132 | this.mask = 0; | |
| 2133 | this.context = 0; | |
| 2134 | } | |
| 2135 | }; | |
| 2136 | var nullToken = new CachedToken(); | |
| 2137 | var InputStream = class { | |
| 2138 | /** | |
| 2139 | @internal | |
| 2140 | */ | |
| 2141 | constructor(input, ranges) { | |
| 2142 | this.input = input; | |
| 2143 | this.ranges = ranges; | |
| 2144 | this.chunk = ""; | |
| 2145 | this.chunkOff = 0; | |
| 2146 | this.chunk2 = ""; | |
| 2147 | this.chunk2Pos = 0; | |
| 2148 | this.next = -1; | |
| 2149 | this.token = nullToken; | |
| 2150 | this.rangeIndex = 0; | |
| 2151 | this.pos = this.chunkPos = ranges[0].from; | |
| 2152 | this.range = ranges[0]; | |
| 2153 | this.end = ranges[ranges.length - 1].to; | |
| 2154 | this.readNext(); | |
| 2155 | } | |
| 2156 | /** | |
| 2157 | @internal | |
| 2158 | */ | |
| 2159 | resolveOffset(offset, assoc) { | |
| 2160 | let range = this.range, index = this.rangeIndex; | |
| 2161 | let pos = this.pos + offset; | |
| 2162 | while (pos < range.from) { | |
| 2163 | if (!index) | |
| 2164 | return null; | |
| 2165 | let next = this.ranges[--index]; | |
| 2166 | pos -= range.from - next.to; | |
| 2167 | range = next; | |
| 2168 | } | |
| 2169 | while (assoc < 0 ? pos > range.to : pos >= range.to) { | |
| 2170 | if (index == this.ranges.length - 1) | |
| 2171 | return null; | |
| 2172 | let next = this.ranges[++index]; | |
| 2173 | pos += next.from - range.to; | |
| 2174 | range = next; | |
| 2175 | } | |
| 2176 | return pos; | |
| 2177 | } | |
| 2178 | /** | |
| 2179 | @internal | |
| 2180 | */ | |
| 2181 | clipPos(pos) { | |
| 2182 | if (pos >= this.range.from && pos < this.range.to) | |
| 2183 | return pos; | |
| 2184 | for (let range of this.ranges) | |
| 2185 | if (range.to > pos) | |
| 2186 | return Math.max(pos, range.from); | |
| 2187 | return this.end; | |
| 2188 | } | |
| 2189 | /** | |
| 2190 | Look at a code unit near the stream position. `.peek(0)` equals | |
| 2191 | `.next`, `.peek(-1)` gives you the previous character, and so | |
| 2192 | on. | |
| 2193 | ||
| 2194 | Note that looking around during tokenizing creates dependencies | |
| 2195 | on potentially far-away content, which may reduce the | |
| 2196 | effectiveness incremental parsing—when looking forward—or even | |
| 2197 | cause invalid reparses when looking backward more than 25 code | |
| 2198 | units, since the library does not track lookbehind. | |
| 2199 | */ | |
| 2200 | peek(offset) { | |
| 2201 | let idx = this.chunkOff + offset, pos, result; | |
| 2202 | if (idx >= 0 && idx < this.chunk.length) { | |
| 2203 | pos = this.pos + offset; | |
| 2204 | result = this.chunk.charCodeAt(idx); | |
| 2205 | } else { | |
| 2206 | let resolved = this.resolveOffset(offset, 1); | |
| 2207 | if (resolved == null) | |
| 2208 | return -1; | |
| 2209 | pos = resolved; | |
| 2210 | if (pos >= this.chunk2Pos && pos < this.chunk2Pos + this.chunk2.length) { | |
| 2211 | result = this.chunk2.charCodeAt(pos - this.chunk2Pos); | |
| 2212 | } else { | |
| 2213 | let i = this.rangeIndex, range = this.range; | |
| 2214 | while (range.to <= pos) | |
| 2215 | range = this.ranges[++i]; | |
| 2216 | this.chunk2 = this.input.chunk(this.chunk2Pos = pos); | |
| 2217 | if (pos + this.chunk2.length > range.to) | |
| 2218 | this.chunk2 = this.chunk2.slice(0, range.to - pos); | |
| 2219 | result = this.chunk2.charCodeAt(0); | |
| 2220 | } | |
| 2221 | } | |
| 2222 | if (pos >= this.token.lookAhead) | |
| 2223 | this.token.lookAhead = pos + 1; | |
| 2224 | return result; | |
| 2225 | } | |
| 2226 | /** | |
| 2227 | Accept a token. By default, the end of the token is set to the | |
| 2228 | current stream position, but you can pass an offset (relative to | |
| 2229 | the stream position) to change that. | |
| 2230 | */ | |
| 2231 | acceptToken(token, endOffset = 0) { | |
| 2232 | let end = endOffset ? this.resolveOffset(endOffset, -1) : this.pos; | |
| 2233 | if (end == null || end < this.token.start) | |
| 2234 | throw new RangeError("Token end out of bounds"); | |
| 2235 | this.token.value = token; | |
| 2236 | this.token.end = end; | |
| 2237 | } | |
| 2238 | /** | |
| 2239 | Accept a token ending at a specific given position. | |
| 2240 | */ | |
| 2241 | acceptTokenTo(token, endPos) { | |
| 2242 | this.token.value = token; | |
| 2243 | this.token.end = endPos; | |
| 2244 | } | |
| 2245 | getChunk() { | |
| 2246 | if (this.pos >= this.chunk2Pos && this.pos < this.chunk2Pos + this.chunk2.length) { | |
| 2247 | let { chunk, chunkPos } = this; | |
| 2248 | this.chunk = this.chunk2; | |
| 2249 | this.chunkPos = this.chunk2Pos; | |
| 2250 | this.chunk2 = chunk; | |
| 2251 | this.chunk2Pos = chunkPos; | |
| 2252 | this.chunkOff = this.pos - this.chunkPos; | |
| 2253 | } else { | |
| 2254 | this.chunk2 = this.chunk; | |
| 2255 | this.chunk2Pos = this.chunkPos; | |
| 2256 | let nextChunk = this.input.chunk(this.pos); | |
| 2257 | let end = this.pos + nextChunk.length; | |
| 2258 | this.chunk = end > this.range.to ? nextChunk.slice(0, this.range.to - this.pos) : nextChunk; | |
| 2259 | this.chunkPos = this.pos; | |
| 2260 | this.chunkOff = 0; | |
| 2261 | } | |
| 2262 | } | |
| 2263 | readNext() { | |
| 2264 | if (this.chunkOff >= this.chunk.length) { | |
| 2265 | this.getChunk(); | |
| 2266 | if (this.chunkOff == this.chunk.length) | |
| 2267 | return this.next = -1; | |
| 2268 | } | |
| 2269 | return this.next = this.chunk.charCodeAt(this.chunkOff); | |
| 2270 | } | |
| 2271 | /** | |
| 2272 | Move the stream forward N (defaults to 1) code units. Returns | |
| 2273 | the new value of [`next`](#lr.InputStream.next). | |
| 2274 | */ | |
| 2275 | advance(n = 1) { | |
| 2276 | this.chunkOff += n; | |
| 2277 | while (this.pos + n >= this.range.to) { | |
| 2278 | if (this.rangeIndex == this.ranges.length - 1) | |
| 2279 | return this.setDone(); | |
| 2280 | n -= this.range.to - this.pos; | |
| 2281 | this.range = this.ranges[++this.rangeIndex]; | |
| 2282 | this.pos = this.range.from; | |
| 2283 | } | |
| 2284 | this.pos += n; | |
| 2285 | if (this.pos >= this.token.lookAhead) | |
| 2286 | this.token.lookAhead = this.pos + 1; | |
| 2287 | return this.readNext(); | |
| 2288 | } | |
| 2289 | setDone() { | |
| 2290 | this.pos = this.chunkPos = this.end; | |
| 2291 | this.range = this.ranges[this.rangeIndex = this.ranges.length - 1]; | |
| 2292 | this.chunk = ""; | |
| 2293 | return this.next = -1; | |
| 2294 | } | |
| 2295 | /** | |
| 2296 | @internal | |
| 2297 | */ | |
| 2298 | reset(pos, token) { | |
| 2299 | if (token) { | |
| 2300 | this.token = token; | |
| 2301 | token.start = pos; | |
| 2302 | token.lookAhead = pos + 1; | |
| 2303 | token.value = token.extended = -1; | |
| 2304 | } else { | |
| 2305 | this.token = nullToken; | |
| 2306 | } | |
| 2307 | if (this.pos != pos) { | |
| 2308 | this.pos = pos; | |
| 2309 | if (pos == this.end) { | |
| 2310 | this.setDone(); | |
| 2311 | return this; | |
| 2312 | } | |
| 2313 | while (pos < this.range.from) | |
| 2314 | this.range = this.ranges[--this.rangeIndex]; | |
| 2315 | while (pos >= this.range.to) | |
| 2316 | this.range = this.ranges[++this.rangeIndex]; | |
| 2317 | if (pos >= this.chunkPos && pos < this.chunkPos + this.chunk.length) { | |
| 2318 | this.chunkOff = pos - this.chunkPos; | |
| 2319 | } else { | |
| 2320 | this.chunk = ""; | |
| 2321 | this.chunkOff = 0; | |
| 2322 | } | |
| 2323 | this.readNext(); | |
| 2324 | } | |
| 2325 | return this; | |
| 2326 | } | |
| 2327 | /** | |
| 2328 | @internal | |
| 2329 | */ | |
| 2330 | read(from, to) { | |
| 2331 | if (from >= this.chunkPos && to <= this.chunkPos + this.chunk.length) | |
| 2332 | return this.chunk.slice(from - this.chunkPos, to - this.chunkPos); | |
| 2333 | if (from >= this.chunk2Pos && to <= this.chunk2Pos + this.chunk2.length) | |
| 2334 | return this.chunk2.slice(from - this.chunk2Pos, to - this.chunk2Pos); | |
| 2335 | if (from >= this.range.from && to <= this.range.to) | |
| 2336 | return this.input.read(from, to); | |
| 2337 | let result = ""; | |
| 2338 | for (let r of this.ranges) { | |
| 2339 | if (r.from >= to) | |
| 2340 | break; | |
| 2341 | if (r.to > from) | |
| 2342 | result += this.input.read(Math.max(r.from, from), Math.min(r.to, to)); | |
| 2343 | } | |
| 2344 | return result; | |
| 2345 | } | |
| 2346 | }; | |
| 2347 | var TokenGroup = class { | |
| 2348 | constructor(data, id) { | |
| 2349 | this.data = data; | |
| 2350 | this.id = id; | |
| 2351 | } | |
| 2352 | token(input, stack) { | |
| 2353 | let { parser: parser2 } = stack.p; | |
| 2354 | readToken(this.data, input, stack, this.id, parser2.data, parser2.tokenPrecTable); | |
| 2355 | } | |
| 2356 | }; | |
| 2357 | TokenGroup.prototype.contextual = TokenGroup.prototype.fallback = TokenGroup.prototype.extend = false; | |
| 2358 | var LocalTokenGroup = class { | |
| 2359 | constructor(data, precTable, elseToken) { | |
| 2360 | this.precTable = precTable; | |
| 2361 | this.elseToken = elseToken; | |
| 2362 | this.data = typeof data == "string" ? decodeArray(data) : data; | |
| 2363 | } | |
| 2364 | token(input, stack) { | |
| 2365 | let start = input.pos, skipped = 0; | |
| 2366 | for (; ; ) { | |
| 2367 | let atEof = input.next < 0, nextPos = input.resolveOffset(1, 1); | |
| 2368 | readToken(this.data, input, stack, 0, this.data, this.precTable); | |
| 2369 | if (input.token.value > -1) | |
| 2370 | break; | |
| 2371 | if (this.elseToken == null) | |
| 2372 | return; | |
| 2373 | if (!atEof) | |
| 2374 | skipped++; | |
| 2375 | if (nextPos == null) | |
| 2376 | break; | |
| 2377 | input.reset(nextPos, input.token); | |
| 2378 | } | |
| 2379 | if (skipped) { | |
| 2380 | input.reset(start, input.token); | |
| 2381 | input.acceptToken(this.elseToken, skipped); | |
| 2382 | } | |
| 2383 | } | |
| 2384 | }; | |
| 2385 | LocalTokenGroup.prototype.contextual = TokenGroup.prototype.fallback = TokenGroup.prototype.extend = false; | |
| 2386 | var ExternalTokenizer = class { | |
| 2387 | /** | |
| 2388 | Create a tokenizer. The first argument is the function that, | |
| 2389 | given an input stream, scans for the types of tokens it | |
| 2390 | recognizes at the stream's position, and calls | |
| 2391 | [`acceptToken`](#lr.InputStream.acceptToken) when it finds | |
| 2392 | one. | |
| 2393 | */ | |
| 2394 | constructor(token, options = {}) { | |
| 2395 | this.token = token; | |
| 2396 | this.contextual = !!options.contextual; | |
| 2397 | this.fallback = !!options.fallback; | |
| 2398 | this.extend = !!options.extend; | |
| 2399 | } | |
| 2400 | }; | |
| 2401 | function readToken(data, input, stack, group, precTable, precOffset) { | |
| 2402 | let state = 0, groupMask = 1 << group, { dialect } = stack.p.parser; | |
| 2403 | scan: for (; ; ) { | |
| 2404 | if ((groupMask & data[state]) == 0) | |
| 2405 | break; | |
| 2406 | let accEnd = data[state + 1]; | |
| 2407 | for (let i = state + 3; i < accEnd; i += 2) | |
| 2408 | if ((data[i + 1] & groupMask) > 0) { | |
| 2409 | let term = data[i]; | |
| 2410 | if (dialect.allows(term) && (input.token.value == -1 || input.token.value == term || overrides(term, input.token.value, precTable, precOffset))) { | |
| 2411 | input.acceptToken(term); | |
| 2412 | break; | |
| 2413 | } | |
| 2414 | } | |
| 2415 | let next = input.next, low = 0, high = data[state + 2]; | |
| 2416 | if (input.next < 0 && high > low && data[accEnd + high * 3 - 3] == 65535) { | |
| 2417 | state = data[accEnd + high * 3 - 1]; | |
| 2418 | continue scan; | |
| 2419 | } | |
| 2420 | for (; low < high; ) { | |
| 2421 | let mid = low + high >> 1; | |
| 2422 | let index = accEnd + mid + (mid << 1); | |
| 2423 | let from = data[index], to = data[index + 1] || 65536; | |
| 2424 | if (next < from) | |
| 2425 | high = mid; | |
| 2426 | else if (next >= to) | |
| 2427 | low = mid + 1; | |
| 2428 | else { | |
| 2429 | state = data[index + 2]; | |
| 2430 | input.advance(); | |
| 2431 | continue scan; | |
| 2432 | } | |
| 2433 | } | |
| 2434 | break; | |
| 2435 | } | |
| 2436 | } | |
| 2437 | function findOffset(data, start, term) { | |
| 2438 | for (let i = start, next; (next = data[i]) != 65535; i++) | |
| 2439 | if (next == term) | |
| 2440 | return i - start; | |
| 2441 | return -1; | |
| 2442 | } | |
| 2443 | function overrides(token, prev, tableData, tableOffset) { | |
| 2444 | let iPrev = findOffset(tableData, tableOffset, prev); | |
| 2445 | return iPrev < 0 || findOffset(tableData, tableOffset, token) < iPrev; | |
| 2446 | } | |
| 2447 | var verbose = typeof process != "undefined" && process.env && /\bparse\b/.test(process.env.LOG); | |
| 2448 | var stackIDs = null; | |
| 2449 | function cutAt(tree, pos, side) { | |
| 2450 | let cursor = tree.cursor(IterMode.IncludeAnonymous); | |
| 2451 | cursor.moveTo(pos); | |
| 2452 | for (; ; ) { | |
| 2453 | if (!(side < 0 ? cursor.childBefore(pos) : cursor.childAfter(pos))) | |
| 2454 | for (; ; ) { | |
| 2455 | if ((side < 0 ? cursor.to < pos : cursor.from > pos) && !cursor.type.isError) | |
| 2456 | return side < 0 ? Math.max(0, Math.min( | |
| 2457 | cursor.to - 1, | |
| 2458 | pos - 25 | |
| 2459 | /* Lookahead.Margin */ | |
| 2460 | )) : Math.min(tree.length, Math.max( | |
| 2461 | cursor.from + 1, | |
| 2462 | pos + 25 | |
| 2463 | /* Lookahead.Margin */ | |
| 2464 | )); | |
| 2465 | if (side < 0 ? cursor.prevSibling() : cursor.nextSibling()) | |
| 2466 | break; | |
| 2467 | if (!cursor.parent()) | |
| 2468 | return side < 0 ? 0 : tree.length; | |
| 2469 | } | |
| 2470 | } | |
| 2471 | } | |
| 2472 | var FragmentCursor = class { | |
| 2473 | constructor(fragments, nodeSet) { | |
| 2474 | this.fragments = fragments; | |
| 2475 | this.nodeSet = nodeSet; | |
| 2476 | this.i = 0; | |
| 2477 | this.fragment = null; | |
| 2478 | this.safeFrom = -1; | |
| 2479 | this.safeTo = -1; | |
| 2480 | this.trees = []; | |
| 2481 | this.start = []; | |
| 2482 | this.index = []; | |
| 2483 | this.nextFragment(); | |
| 2484 | } | |
| 2485 | nextFragment() { | |
| 2486 | let fr = this.fragment = this.i == this.fragments.length ? null : this.fragments[this.i++]; | |
| 2487 | if (fr) { | |
| 2488 | this.safeFrom = fr.openStart ? cutAt(fr.tree, fr.from + fr.offset, 1) - fr.offset : fr.from; | |
| 2489 | this.safeTo = fr.openEnd ? cutAt(fr.tree, fr.to + fr.offset, -1) - fr.offset : fr.to; | |
| 2490 | while (this.trees.length) { | |
| 2491 | this.trees.pop(); | |
| 2492 | this.start.pop(); | |
| 2493 | this.index.pop(); | |
| 2494 | } | |
| 2495 | this.trees.push(fr.tree); | |
| 2496 | this.start.push(-fr.offset); | |
| 2497 | this.index.push(0); | |
| 2498 | this.nextStart = this.safeFrom; | |
| 2499 | } else { | |
| 2500 | this.nextStart = 1e9; | |
| 2501 | } | |
| 2502 | } | |
| 2503 | // `pos` must be >= any previously given `pos` for this cursor | |
| 2504 | nodeAt(pos) { | |
| 2505 | if (pos < this.nextStart) | |
| 2506 | return null; | |
| 2507 | while (this.fragment && this.safeTo <= pos) | |
| 2508 | this.nextFragment(); | |
| 2509 | if (!this.fragment) | |
| 2510 | return null; | |
| 2511 | for (; ; ) { | |
| 2512 | let last = this.trees.length - 1; | |
| 2513 | if (last < 0) { | |
| 2514 | this.nextFragment(); | |
| 2515 | return null; | |
| 2516 | } | |
| 2517 | let top = this.trees[last], index = this.index[last]; | |
| 2518 | if (index == top.children.length) { | |
| 2519 | this.trees.pop(); | |
| 2520 | this.start.pop(); | |
| 2521 | this.index.pop(); | |
| 2522 | continue; | |
| 2523 | } | |
| 2524 | let next = top.children[index]; | |
| 2525 | let start = this.start[last] + top.positions[index]; | |
| 2526 | if (start > pos) { | |
| 2527 | this.nextStart = start; | |
| 2528 | return null; | |
| 2529 | } | |
| 2530 | if (next instanceof Tree) { | |
| 2531 | if (start == pos) { | |
| 2532 | if (start < this.safeFrom) | |
| 2533 | return null; | |
| 2534 | let end = start + next.length; | |
| 2535 | if (end <= this.safeTo) { | |
| 2536 | let lookAhead = next.prop(NodeProp.lookAhead); | |
| 2537 | if (!lookAhead || end + lookAhead < this.fragment.to) | |
| 2538 | return next; | |
| 2539 | } | |
| 2540 | } | |
| 2541 | this.index[last]++; | |
| 2542 | if (start + next.length >= Math.max(this.safeFrom, pos)) { | |
| 2543 | this.trees.push(next); | |
| 2544 | this.start.push(start); | |
| 2545 | this.index.push(0); | |
| 2546 | } | |
| 2547 | } else { | |
| 2548 | this.index[last]++; | |
| 2549 | this.nextStart = start + next.length; | |
| 2550 | } | |
| 2551 | } | |
| 2552 | } | |
| 2553 | }; | |
| 2554 | var TokenCache = class { | |
| 2555 | constructor(parser2, stream) { | |
| 2556 | this.stream = stream; | |
| 2557 | this.tokens = []; | |
| 2558 | this.mainToken = null; | |
| 2559 | this.actions = []; | |
| 2560 | this.tokens = parser2.tokenizers.map((_) => new CachedToken()); | |
| 2561 | } | |
| 2562 | getActions(stack) { | |
| 2563 | let actionIndex = 0; | |
| 2564 | let main = null; | |
| 2565 | let { parser: parser2 } = stack.p, { tokenizers } = parser2; | |
| 2566 | let mask = parser2.stateSlot( | |
| 2567 | stack.state, | |
| 2568 | 3 | |
| 2569 | /* ParseState.TokenizerMask */ | |
| 2570 | ); | |
| 2571 | let context = stack.curContext ? stack.curContext.hash : 0; | |
| 2572 | let lookAhead = 0; | |
| 2573 | for (let i = 0; i < tokenizers.length; i++) { | |
| 2574 | if ((1 << i & mask) == 0) | |
| 2575 | continue; | |
| 2576 | let tokenizer = tokenizers[i], token = this.tokens[i]; | |
| 2577 | if (main && !tokenizer.fallback) | |
| 2578 | continue; | |
| 2579 | if (tokenizer.contextual || token.start != stack.pos || token.mask != mask || token.context != context) { | |
| 2580 | this.updateCachedToken(token, tokenizer, stack); | |
| 2581 | token.mask = mask; | |
| 2582 | token.context = context; | |
| 2583 | } | |
| 2584 | if (token.lookAhead > token.end + 25) | |
| 2585 | lookAhead = Math.max(token.lookAhead, lookAhead); | |
| 2586 | if (token.value != 0) { | |
| 2587 | let startIndex = actionIndex; | |
| 2588 | if (token.extended > -1) | |
| 2589 | actionIndex = this.addActions(stack, token.extended, token.end, actionIndex); | |
| 2590 | actionIndex = this.addActions(stack, token.value, token.end, actionIndex); | |
| 2591 | if (!tokenizer.extend) { | |
| 2592 | main = token; | |
| 2593 | if (actionIndex > startIndex) | |
| 2594 | break; | |
| 2595 | } | |
| 2596 | } | |
| 2597 | } | |
| 2598 | while (this.actions.length > actionIndex) | |
| 2599 | this.actions.pop(); | |
| 2600 | if (lookAhead) | |
| 2601 | stack.setLookAhead(lookAhead); | |
| 2602 | if (!main && stack.pos == this.stream.end) { | |
| 2603 | main = new CachedToken(); | |
| 2604 | main.value = stack.p.parser.eofTerm; | |
| 2605 | main.start = main.end = stack.pos; | |
| 2606 | actionIndex = this.addActions(stack, main.value, main.end, actionIndex); | |
| 2607 | } | |
| 2608 | this.mainToken = main; | |
| 2609 | return this.actions; | |
| 2610 | } | |
| 2611 | getMainToken(stack) { | |
| 2612 | if (this.mainToken) | |
| 2613 | return this.mainToken; | |
| 2614 | let main = new CachedToken(), { pos, p } = stack; | |
| 2615 | main.start = pos; | |
| 2616 | main.end = Math.min(pos + 1, p.stream.end); | |
| 2617 | main.value = pos == p.stream.end ? p.parser.eofTerm : 0; | |
| 2618 | return main; | |
| 2619 | } | |
| 2620 | updateCachedToken(token, tokenizer, stack) { | |
| 2621 | let start = this.stream.clipPos(stack.pos); | |
| 2622 | tokenizer.token(this.stream.reset(start, token), stack); | |
| 2623 | if (token.value > -1) { | |
| 2624 | let { parser: parser2 } = stack.p; | |
| 2625 | for (let i = 0; i < parser2.specialized.length; i++) | |
| 2626 | if (parser2.specialized[i] == token.value) { | |
| 2627 | let result = parser2.specializers[i](this.stream.read(token.start, token.end), stack); | |
| 2628 | if (result >= 0 && stack.p.parser.dialect.allows(result >> 1)) { | |
| 2629 | if ((result & 1) == 0) | |
| 2630 | token.value = result >> 1; | |
| 2631 | else | |
| 2632 | token.extended = result >> 1; | |
| 2633 | break; | |
| 2634 | } | |
| 2635 | } | |
| 2636 | } else { | |
| 2637 | token.value = 0; | |
| 2638 | token.end = this.stream.clipPos(start + 1); | |
| 2639 | } | |
| 2640 | } | |
| 2641 | putAction(action, token, end, index) { | |
| 2642 | for (let i = 0; i < index; i += 3) | |
| 2643 | if (this.actions[i] == action) | |
| 2644 | return index; | |
| 2645 | this.actions[index++] = action; | |
| 2646 | this.actions[index++] = token; | |
| 2647 | this.actions[index++] = end; | |
| 2648 | return index; | |
| 2649 | } | |
| 2650 | addActions(stack, token, end, index) { | |
| 2651 | let { state } = stack, { parser: parser2 } = stack.p, { data } = parser2; | |
| 2652 | for (let set = 0; set < 2; set++) { | |
| 2653 | for (let i = parser2.stateSlot( | |
| 2654 | state, | |
| 2655 | set ? 2 : 1 | |
| 2656 | /* ParseState.Actions */ | |
| 2657 | ); ; i += 3) { | |
| 2658 | if (data[i] == 65535) { | |
| 2659 | if (data[i + 1] == 1) { | |
| 2660 | i = pair(data, i + 2); | |
| 2661 | } else { | |
| 2662 | if (index == 0 && data[i + 1] == 2) | |
| 2663 | index = this.putAction(pair(data, i + 2), token, end, index); | |
| 2664 | break; | |
| 2665 | } | |
| 2666 | } | |
| 2667 | if (data[i] == token) | |
| 2668 | index = this.putAction(pair(data, i + 1), token, end, index); | |
| 2669 | } | |
| 2670 | } | |
| 2671 | return index; | |
| 2672 | } | |
| 2673 | }; | |
| 2674 | var Parse = class { | |
| 2675 | constructor(parser2, input, fragments, ranges) { | |
| 2676 | this.parser = parser2; | |
| 2677 | this.input = input; | |
| 2678 | this.ranges = ranges; | |
| 2679 | this.recovering = 0; | |
| 2680 | this.nextStackID = 9812; | |
| 2681 | this.minStackPos = 0; | |
| 2682 | this.reused = []; | |
| 2683 | this.stoppedAt = null; | |
| 2684 | this.lastBigReductionStart = -1; | |
| 2685 | this.lastBigReductionSize = 0; | |
| 2686 | this.bigReductionCount = 0; | |
| 2687 | this.stream = new InputStream(input, ranges); | |
| 2688 | this.tokens = new TokenCache(parser2, this.stream); | |
| 2689 | this.topTerm = parser2.top[1]; | |
| 2690 | let { from } = ranges[0]; | |
| 2691 | this.stacks = [Stack.start(this, parser2.top[0], from)]; | |
| 2692 | this.fragments = fragments.length && this.stream.end - from > parser2.bufferLength * 4 ? new FragmentCursor(fragments, parser2.nodeSet) : null; | |
| 2693 | } | |
| 2694 | get parsedPos() { | |
| 2695 | return this.minStackPos; | |
| 2696 | } | |
| 2697 | // Move the parser forward. This will process all parse stacks at | |
| 2698 | // `this.pos` and try to advance them to a further position. If no | |
| 2699 | // stack for such a position is found, it'll start error-recovery. | |
| 2700 | // | |
| 2701 | // When the parse is finished, this will return a syntax tree. When | |
| 2702 | // not, it returns `null`. | |
| 2703 | advance() { | |
| 2704 | let stacks = this.stacks, pos = this.minStackPos; | |
| 2705 | let newStacks = this.stacks = []; | |
| 2706 | let stopped, stoppedTokens; | |
| 2707 | if (this.bigReductionCount > 300 && stacks.length == 1) { | |
| 2708 | let [s] = stacks; | |
| 2709 | while (s.forceReduce() && s.stack.length && s.stack[s.stack.length - 2] >= this.lastBigReductionStart) { | |
| 2710 | } | |
| 2711 | this.bigReductionCount = this.lastBigReductionSize = 0; | |
| 2712 | } | |
| 2713 | for (let i = 0; i < stacks.length; i++) { | |
| 2714 | let stack = stacks[i]; | |
| 2715 | for (; ; ) { | |
| 2716 | this.tokens.mainToken = null; | |
| 2717 | if (stack.pos > pos) { | |
| 2718 | newStacks.push(stack); | |
| 2719 | } else if (this.advanceStack(stack, newStacks, stacks)) { | |
| 2720 | continue; | |
| 2721 | } else { | |
| 2722 | if (!stopped) { | |
| 2723 | stopped = []; | |
| 2724 | stoppedTokens = []; | |
| 2725 | } | |
| 2726 | stopped.push(stack); | |
| 2727 | let tok = this.tokens.getMainToken(stack); | |
| 2728 | stoppedTokens.push(tok.value, tok.end); | |
| 2729 | } | |
| 2730 | break; | |
| 2731 | } | |
| 2732 | } | |
| 2733 | if (!newStacks.length) { | |
| 2734 | let finished = stopped && findFinished(stopped); | |
| 2735 | if (finished) { | |
| 2736 | if (verbose) | |
| 2737 | console.log("Finish with " + this.stackID(finished)); | |
| 2738 | return this.stackToTree(finished); | |
| 2739 | } | |
| 2740 | if (this.parser.strict) { | |
| 2741 | if (verbose && stopped) | |
| 2742 | console.log("Stuck with token " + (this.tokens.mainToken ? this.parser.getName(this.tokens.mainToken.value) : "none")); | |
| 2743 | throw new SyntaxError("No parse at " + pos); | |
| 2744 | } | |
| 2745 | if (!this.recovering) | |
| 2746 | this.recovering = 5; | |
| 2747 | } | |
| 2748 | if (this.recovering && stopped) { | |
| 2749 | let finished = this.stoppedAt != null && stopped[0].pos > this.stoppedAt ? stopped[0] : this.runRecovery(stopped, stoppedTokens, newStacks); | |
| 2750 | if (finished) { | |
| 2751 | if (verbose) | |
| 2752 | console.log("Force-finish " + this.stackID(finished)); | |
| 2753 | return this.stackToTree(finished.forceAll()); | |
| 2754 | } | |
| 2755 | } | |
| 2756 | if (this.recovering) { | |
| 2757 | let maxRemaining = this.recovering == 1 ? 1 : this.recovering * 3; | |
| 2758 | if (newStacks.length > maxRemaining) { | |
| 2759 | newStacks.sort((a2, b) => b.score - a2.score); | |
| 2760 | while (newStacks.length > maxRemaining) | |
| 2761 | newStacks.pop(); | |
| 2762 | } | |
| 2763 | if (newStacks.some((s) => s.reducePos > pos)) | |
| 2764 | this.recovering--; | |
| 2765 | } else if (newStacks.length > 1) { | |
| 2766 | outer: for (let i = 0; i < newStacks.length - 1; i++) { | |
| 2767 | let stack = newStacks[i]; | |
| 2768 | for (let j = i + 1; j < newStacks.length; j++) { | |
| 2769 | let other = newStacks[j]; | |
| 2770 | if (stack.sameState(other) || stack.buffer.length > 500 && other.buffer.length > 500) { | |
| 2771 | if ((stack.score - other.score || stack.buffer.length - other.buffer.length) > 0) { | |
| 2772 | newStacks.splice(j--, 1); | |
| 2773 | } else { | |
| 2774 | newStacks.splice(i--, 1); | |
| 2775 | continue outer; | |
| 2776 | } | |
| 2777 | } | |
| 2778 | } | |
| 2779 | } | |
| 2780 | if (newStacks.length > 12) { | |
| 2781 | newStacks.sort((a2, b) => b.score - a2.score); | |
| 2782 | newStacks.splice( | |
| 2783 | 12, | |
| 2784 | newStacks.length - 12 | |
| 2785 | /* Rec.MaxStackCount */ | |
| 2786 | ); | |
| 2787 | } | |
| 2788 | } | |
| 2789 | this.minStackPos = newStacks[0].pos; | |
| 2790 | for (let i = 1; i < newStacks.length; i++) | |
| 2791 | if (newStacks[i].pos < this.minStackPos) | |
| 2792 | this.minStackPos = newStacks[i].pos; | |
| 2793 | return null; | |
| 2794 | } | |
| 2795 | stopAt(pos) { | |
| 2796 | if (this.stoppedAt != null && this.stoppedAt < pos) | |
| 2797 | throw new RangeError("Can't move stoppedAt forward"); | |
| 2798 | this.stoppedAt = pos; | |
| 2799 | } | |
| 2800 | // Returns an updated version of the given stack, or null if the | |
| 2801 | // stack can't advance normally. When `split` and `stacks` are | |
| 2802 | // given, stacks split off by ambiguous operations will be pushed to | |
| 2803 | // `split`, or added to `stacks` if they move `pos` forward. | |
| 2804 | advanceStack(stack, stacks, split) { | |
| 2805 | let start = stack.pos, { parser: parser2 } = this; | |
| 2806 | let base = verbose ? this.stackID(stack) + " -> " : ""; | |
| 2807 | if (this.stoppedAt != null && start > this.stoppedAt) | |
| 2808 | return stack.forceReduce() ? stack : null; | |
| 2809 | if (this.fragments) { | |
| 2810 | let strictCx = stack.curContext && stack.curContext.tracker.strict, cxHash = strictCx ? stack.curContext.hash : 0; | |
| 2811 | for (let cached = this.fragments.nodeAt(start); cached; ) { | |
| 2812 | let match = this.parser.nodeSet.types[cached.type.id] == cached.type ? parser2.getGoto(stack.state, cached.type.id) : -1; | |
| 2813 | if (match > -1 && cached.length && (!strictCx || (cached.prop(NodeProp.contextHash) || 0) == cxHash)) { | |
| 2814 | stack.useNode(cached, match); | |
| 2815 | if (verbose) | |
| 2816 | console.log(base + this.stackID(stack) + ` (via reuse of ${parser2.getName(cached.type.id)})`); | |
| 2817 | return true; | |
| 2818 | } | |
| 2819 | if (!(cached instanceof Tree) || cached.children.length == 0 || cached.positions[0] > 0) | |
| 2820 | break; | |
| 2821 | let inner = cached.children[0]; | |
| 2822 | if (inner instanceof Tree && cached.positions[0] == 0) | |
| 2823 | cached = inner; | |
| 2824 | else | |
| 2825 | break; | |
| 2826 | } | |
| 2827 | } | |
| 2828 | let defaultReduce = parser2.stateSlot( | |
| 2829 | stack.state, | |
| 2830 | 4 | |
| 2831 | /* ParseState.DefaultReduce */ | |
| 2832 | ); | |
| 2833 | if (defaultReduce > 0) { | |
| 2834 | stack.reduce(defaultReduce); | |
| 2835 | if (verbose) | |
| 2836 | console.log(base + this.stackID(stack) + ` (via always-reduce ${parser2.getName( | |
| 2837 | defaultReduce & 65535 | |
| 2838 | /* Action.ValueMask */ | |
| 2839 | )})`); | |
| 2840 | return true; | |
| 2841 | } | |
| 2842 | if (stack.stack.length >= 8400) { | |
| 2843 | while (stack.stack.length > 6e3 && stack.forceReduce()) { | |
| 2844 | } | |
| 2845 | } | |
| 2846 | let actions = this.tokens.getActions(stack); | |
| 2847 | for (let i = 0; i < actions.length; ) { | |
| 2848 | let action = actions[i++], term = actions[i++], end = actions[i++]; | |
| 2849 | let last = i == actions.length || !split; | |
| 2850 | let localStack = last ? stack : stack.split(); | |
| 2851 | let main = this.tokens.mainToken; | |
| 2852 | localStack.apply(action, term, main ? main.start : localStack.pos, end); | |
| 2853 | if (verbose) | |
| 2854 | console.log(base + this.stackID(localStack) + ` (via ${(action & 65536) == 0 ? "shift" : `reduce of ${parser2.getName( | |
| 2855 | action & 65535 | |
| 2856 | /* Action.ValueMask */ | |
| 2857 | )}`} for ${parser2.getName(term)} @ ${start}${localStack == stack ? "" : ", split"})`); | |
| 2858 | if (last) | |
| 2859 | return true; | |
| 2860 | else if (localStack.pos > start) | |
| 2861 | stacks.push(localStack); | |
| 2862 | else | |
| 2863 | split.push(localStack); | |
| 2864 | } | |
| 2865 | return false; | |
| 2866 | } | |
| 2867 | // Advance a given stack forward as far as it will go. Returns the | |
| 2868 | // (possibly updated) stack if it got stuck, or null if it moved | |
| 2869 | // forward and was given to `pushStackDedup`. | |
| 2870 | advanceFully(stack, newStacks) { | |
| 2871 | let pos = stack.pos; | |
| 2872 | for (; ; ) { | |
| 2873 | if (!this.advanceStack(stack, null, null)) | |
| 2874 | return false; | |
| 2875 | if (stack.pos > pos) { | |
| 2876 | pushStackDedup(stack, newStacks); | |
| 2877 | return true; | |
| 2878 | } | |
| 2879 | } | |
| 2880 | } | |
| 2881 | runRecovery(stacks, tokens, newStacks) { | |
| 2882 | let finished = null, restarted = false; | |
| 2883 | for (let i = 0; i < stacks.length; i++) { | |
| 2884 | let stack = stacks[i], token = tokens[i << 1], tokenEnd = tokens[(i << 1) + 1]; | |
| 2885 | let base = verbose ? this.stackID(stack) + " -> " : ""; | |
| 2886 | if (stack.deadEnd) { | |
| 2887 | if (restarted) | |
| 2888 | continue; | |
| 2889 | restarted = true; | |
| 2890 | stack.restart(); | |
| 2891 | if (verbose) | |
| 2892 | console.log(base + this.stackID(stack) + " (restarted)"); | |
| 2893 | let done = this.advanceFully(stack, newStacks); | |
| 2894 | if (done) | |
| 2895 | continue; | |
| 2896 | } | |
| 2897 | let force = stack.split(), forceBase = base; | |
| 2898 | for (let j = 0; j < 10 && force.forceReduce(); j++) { | |
| 2899 | if (verbose) | |
| 2900 | console.log(forceBase + this.stackID(force) + " (via force-reduce)"); | |
| 2901 | let done = this.advanceFully(force, newStacks); | |
| 2902 | if (done) | |
| 2903 | break; | |
| 2904 | if (verbose) | |
| 2905 | forceBase = this.stackID(force) + " -> "; | |
| 2906 | } | |
| 2907 | for (let insert of stack.recoverByInsert(token)) { | |
| 2908 | if (verbose) | |
| 2909 | console.log(base + this.stackID(insert) + " (via recover-insert)"); | |
| 2910 | this.advanceFully(insert, newStacks); | |
| 2911 | } | |
| 2912 | if (this.stream.end > stack.pos) { | |
| 2913 | if (tokenEnd == stack.pos) { | |
| 2914 | tokenEnd++; | |
| 2915 | token = 0; | |
| 2916 | } | |
| 2917 | stack.recoverByDelete(token, tokenEnd); | |
| 2918 | if (verbose) | |
| 2919 | console.log(base + this.stackID(stack) + ` (via recover-delete ${this.parser.getName(token)})`); | |
| 2920 | pushStackDedup(stack, newStacks); | |
| 2921 | } else if (!finished || finished.score < force.score) { | |
| 2922 | finished = force; | |
| 2923 | } | |
| 2924 | } | |
| 2925 | return finished; | |
| 2926 | } | |
| 2927 | // Convert the stack's buffer to a syntax tree. | |
| 2928 | stackToTree(stack) { | |
| 2929 | stack.close(); | |
| 2930 | return Tree.build({ | |
| 2931 | buffer: StackBufferCursor.create(stack), | |
| 2932 | nodeSet: this.parser.nodeSet, | |
| 2933 | topID: this.topTerm, | |
| 2934 | maxBufferLength: this.parser.bufferLength, | |
| 2935 | reused: this.reused, | |
| 2936 | start: this.ranges[0].from, | |
| 2937 | length: stack.pos - this.ranges[0].from, | |
| 2938 | minRepeatType: this.parser.minRepeatTerm | |
| 2939 | }); | |
| 2940 | } | |
| 2941 | stackID(stack) { | |
| 2942 | let id = (stackIDs || (stackIDs = /* @__PURE__ */ new WeakMap())).get(stack); | |
| 2943 | if (!id) | |
| 2944 | stackIDs.set(stack, id = String.fromCodePoint(this.nextStackID++)); | |
| 2945 | return id + stack; | |
| 2946 | } | |
| 2947 | }; | |
| 2948 | function pushStackDedup(stack, newStacks) { | |
| 2949 | for (let i = 0; i < newStacks.length; i++) { | |
| 2950 | let other = newStacks[i]; | |
| 2951 | if (other.pos == stack.pos && other.sameState(stack)) { | |
| 2952 | if (newStacks[i].score < stack.score) | |
| 2953 | newStacks[i] = stack; | |
| 2954 | return; | |
| 2955 | } | |
| 2956 | } | |
| 2957 | newStacks.push(stack); | |
| 2958 | } | |
| 2959 | var Dialect = class { | |
| 2960 | constructor(source, flags, disabled) { | |
| 2961 | this.source = source; | |
| 2962 | this.flags = flags; | |
| 2963 | this.disabled = disabled; | |
| 2964 | } | |
| 2965 | allows(term) { | |
| 2966 | return !this.disabled || this.disabled[term] == 0; | |
| 2967 | } | |
| 2968 | }; | |
| 2969 | var LRParser = class _LRParser extends Parser { | |
| 2970 | /** | |
| 2971 | @internal | |
| 2972 | */ | |
| 2973 | constructor(spec) { | |
| 2974 | super(); | |
| 2975 | this.wrappers = []; | |
| 2976 | if (spec.version != 14) | |
| 2977 | throw new RangeError(`Parser version (${spec.version}) doesn't match runtime version (${14})`); | |
| 2978 | let nodeNames = spec.nodeNames.split(" "); | |
| 2979 | this.minRepeatTerm = nodeNames.length; | |
| 2980 | for (let i = 0; i < spec.repeatNodeCount; i++) | |
| 2981 | nodeNames.push(""); | |
| 2982 | let topTerms = Object.keys(spec.topRules).map((r) => spec.topRules[r][1]); | |
| 2983 | let nodeProps = []; | |
| 2984 | for (let i = 0; i < nodeNames.length; i++) | |
| 2985 | nodeProps.push([]); | |
| 2986 | function setProp(nodeID, prop, value) { | |
| 2987 | nodeProps[nodeID].push([prop, prop.deserialize(String(value))]); | |
| 2988 | } | |
| 2989 | if (spec.nodeProps) | |
| 2990 | for (let propSpec of spec.nodeProps) { | |
| 2991 | let prop = propSpec[0]; | |
| 2992 | if (typeof prop == "string") | |
| 2993 | prop = NodeProp[prop]; | |
| 2994 | for (let i = 1; i < propSpec.length; ) { | |
| 2995 | let next = propSpec[i++]; | |
| 2996 | if (next >= 0) { | |
| 2997 | setProp(next, prop, propSpec[i++]); | |
| 2998 | } else { | |
| 2999 | let value = propSpec[i + -next]; | |
| 3000 | for (let j = -next; j > 0; j--) | |
| 3001 | setProp(propSpec[i++], prop, value); | |
| 3002 | i++; | |
| 3003 | } | |
| 3004 | } | |
| 3005 | } | |
| 3006 | this.nodeSet = new NodeSet(nodeNames.map((name2, i) => NodeType.define({ | |
| 3007 | name: i >= this.minRepeatTerm ? void 0 : name2, | |
| 3008 | id: i, | |
| 3009 | props: nodeProps[i], | |
| 3010 | top: topTerms.indexOf(i) > -1, | |
| 3011 | error: i == 0, | |
| 3012 | skipped: spec.skippedNodes && spec.skippedNodes.indexOf(i) > -1 | |
| 3013 | }))); | |
| 3014 | if (spec.propSources) | |
| 3015 | this.nodeSet = this.nodeSet.extend(...spec.propSources); | |
| 3016 | this.strict = false; | |
| 3017 | this.bufferLength = DefaultBufferLength; | |
| 3018 | let tokenArray = decodeArray(spec.tokenData); | |
| 3019 | this.context = spec.context; | |
| 3020 | this.specializerSpecs = spec.specialized || []; | |
| 3021 | this.specialized = new Uint16Array(this.specializerSpecs.length); | |
| 3022 | for (let i = 0; i < this.specializerSpecs.length; i++) | |
| 3023 | this.specialized[i] = this.specializerSpecs[i].term; | |
| 3024 | this.specializers = this.specializerSpecs.map(getSpecializer); | |
| 3025 | this.states = decodeArray(spec.states, Uint32Array); | |
| 3026 | this.data = decodeArray(spec.stateData); | |
| 3027 | this.goto = decodeArray(spec.goto); | |
| 3028 | this.maxTerm = spec.maxTerm; | |
| 3029 | this.tokenizers = spec.tokenizers.map((value) => typeof value == "number" ? new TokenGroup(tokenArray, value) : value); | |
| 3030 | this.topRules = spec.topRules; | |
| 3031 | this.dialects = spec.dialects || {}; | |
| 3032 | this.dynamicPrecedences = spec.dynamicPrecedences || null; | |
| 3033 | this.tokenPrecTable = spec.tokenPrec; | |
| 3034 | this.termNames = spec.termNames || null; | |
| 3035 | this.maxNode = this.nodeSet.types.length - 1; | |
| 3036 | this.dialect = this.parseDialect(); | |
| 3037 | this.top = this.topRules[Object.keys(this.topRules)[0]]; | |
| 3038 | } | |
| 3039 | createParse(input, fragments, ranges) { | |
| 3040 | let parse = new Parse(this, input, fragments, ranges); | |
| 3041 | for (let w of this.wrappers) | |
| 3042 | parse = w(parse, input, fragments, ranges); | |
| 3043 | return parse; | |
| 3044 | } | |
| 3045 | /** | |
| 3046 | Get a goto table entry @internal | |
| 3047 | */ | |
| 3048 | getGoto(state, term, loose = false) { | |
| 3049 | let table = this.goto; | |
| 3050 | if (term >= table[0]) | |
| 3051 | return -1; | |
| 3052 | for (let pos = table[term + 1]; ; ) { | |
| 3053 | let groupTag = table[pos++], last = groupTag & 1; | |
| 3054 | let target = table[pos++]; | |
| 3055 | if (last && loose) | |
| 3056 | return target; | |
| 3057 | for (let end = pos + (groupTag >> 1); pos < end; pos++) | |
| 3058 | if (table[pos] == state) | |
| 3059 | return target; | |
| 3060 | if (last) | |
| 3061 | return -1; | |
| 3062 | } | |
| 3063 | } | |
| 3064 | /** | |
| 3065 | Check if this state has an action for a given terminal @internal | |
| 3066 | */ | |
| 3067 | hasAction(state, terminal) { | |
| 3068 | let data = this.data; | |
| 3069 | for (let set = 0; set < 2; set++) { | |
| 3070 | for (let i = this.stateSlot( | |
| 3071 | state, | |
| 3072 | set ? 2 : 1 | |
| 3073 | /* ParseState.Actions */ | |
| 3074 | ), next; ; i += 3) { | |
| 3075 | if ((next = data[i]) == 65535) { | |
| 3076 | if (data[i + 1] == 1) | |
| 3077 | next = data[i = pair(data, i + 2)]; | |
| 3078 | else if (data[i + 1] == 2) | |
| 3079 | return pair(data, i + 2); | |
| 3080 | else | |
| 3081 | break; | |
| 3082 | } | |
| 3083 | if (next == terminal || next == 0) | |
| 3084 | return pair(data, i + 1); | |
| 3085 | } | |
| 3086 | } | |
| 3087 | return 0; | |
| 3088 | } | |
| 3089 | /** | |
| 3090 | @internal | |
| 3091 | */ | |
| 3092 | stateSlot(state, slot) { | |
| 3093 | return this.states[state * 6 + slot]; | |
| 3094 | } | |
| 3095 | /** | |
| 3096 | @internal | |
| 3097 | */ | |
| 3098 | stateFlag(state, flag) { | |
| 3099 | return (this.stateSlot( | |
| 3100 | state, | |
| 3101 | 0 | |
| 3102 | /* ParseState.Flags */ | |
| 3103 | ) & flag) > 0; | |
| 3104 | } | |
| 3105 | /** | |
| 3106 | @internal | |
| 3107 | */ | |
| 3108 | validAction(state, action) { | |
| 3109 | return !!this.allActions(state, (a2) => a2 == action ? true : null); | |
| 3110 | } | |
| 3111 | /** | |
| 3112 | @internal | |
| 3113 | */ | |
| 3114 | allActions(state, action) { | |
| 3115 | let deflt = this.stateSlot( | |
| 3116 | state, | |
| 3117 | 4 | |
| 3118 | /* ParseState.DefaultReduce */ | |
| 3119 | ); | |
| 3120 | let result = deflt ? action(deflt) : void 0; | |
| 3121 | for (let i = this.stateSlot( | |
| 3122 | state, | |
| 3123 | 1 | |
| 3124 | /* ParseState.Actions */ | |
| 3125 | ); result == null; i += 3) { | |
| 3126 | if (this.data[i] == 65535) { | |
| 3127 | if (this.data[i + 1] == 1) | |
| 3128 | i = pair(this.data, i + 2); | |
| 3129 | else | |
| 3130 | break; | |
| 3131 | } | |
| 3132 | result = action(pair(this.data, i + 1)); | |
| 3133 | } | |
| 3134 | return result; | |
| 3135 | } | |
| 3136 | /** | |
| 3137 | Get the states that can follow this one through shift actions or | |
| 3138 | goto jumps. @internal | |
| 3139 | */ | |
| 3140 | nextStates(state) { | |
| 3141 | let result = []; | |
| 3142 | for (let i = this.stateSlot( | |
| 3143 | state, | |
| 3144 | 1 | |
| 3145 | /* ParseState.Actions */ | |
| 3146 | ); ; i += 3) { | |
| 3147 | if (this.data[i] == 65535) { | |
| 3148 | if (this.data[i + 1] == 1) | |
| 3149 | i = pair(this.data, i + 2); | |
| 3150 | else | |
| 3151 | break; | |
| 3152 | } | |
| 3153 | if ((this.data[i + 2] & 65536 >> 16) == 0) { | |
| 3154 | let value = this.data[i + 1]; | |
| 3155 | if (!result.some((v, i2) => i2 & 1 && v == value)) | |
| 3156 | result.push(this.data[i], value); | |
| 3157 | } | |
| 3158 | } | |
| 3159 | return result; | |
| 3160 | } | |
| 3161 | /** | |
| 3162 | Configure the parser. Returns a new parser instance that has the | |
| 3163 | given settings modified. Settings not provided in `config` are | |
| 3164 | kept from the original parser. | |
| 3165 | */ | |
| 3166 | configure(config) { | |
| 3167 | let copy = Object.assign(Object.create(_LRParser.prototype), this); | |
| 3168 | if (config.props) | |
| 3169 | copy.nodeSet = this.nodeSet.extend(...config.props); | |
| 3170 | if (config.top) { | |
| 3171 | let info = this.topRules[config.top]; | |
| 3172 | if (!info) | |
| 3173 | throw new RangeError(`Invalid top rule name ${config.top}`); | |
| 3174 | copy.top = info; | |
| 3175 | } | |
| 3176 | if (config.tokenizers) | |
| 3177 | copy.tokenizers = this.tokenizers.map((t2) => { | |
| 3178 | let found = config.tokenizers.find((r) => r.from == t2); | |
| 3179 | return found ? found.to : t2; | |
| 3180 | }); | |
| 3181 | if (config.specializers) { | |
| 3182 | copy.specializers = this.specializers.slice(); | |
| 3183 | copy.specializerSpecs = this.specializerSpecs.map((s, i) => { | |
| 3184 | let found = config.specializers.find((r) => r.from == s.external); | |
| 3185 | if (!found) | |
| 3186 | return s; | |
| 3187 | let spec = Object.assign(Object.assign({}, s), { external: found.to }); | |
| 3188 | copy.specializers[i] = getSpecializer(spec); | |
| 3189 | return spec; | |
| 3190 | }); | |
| 3191 | } | |
| 3192 | if (config.contextTracker) | |
| 3193 | copy.context = config.contextTracker; | |
| 3194 | if (config.dialect) | |
| 3195 | copy.dialect = this.parseDialect(config.dialect); | |
| 3196 | if (config.strict != null) | |
| 3197 | copy.strict = config.strict; | |
| 3198 | if (config.wrap) | |
| 3199 | copy.wrappers = copy.wrappers.concat(config.wrap); | |
| 3200 | if (config.bufferLength != null) | |
| 3201 | copy.bufferLength = config.bufferLength; | |
| 3202 | return copy; | |
| 3203 | } | |
| 3204 | /** | |
| 3205 | Tells you whether any [parse wrappers](#lr.ParserConfig.wrap) | |
| 3206 | are registered for this parser. | |
| 3207 | */ | |
| 3208 | hasWrappers() { | |
| 3209 | return this.wrappers.length > 0; | |
| 3210 | } | |
| 3211 | /** | |
| 3212 | Returns the name associated with a given term. This will only | |
| 3213 | work for all terms when the parser was generated with the | |
| 3214 | `--names` option. By default, only the names of tagged terms are | |
| 3215 | stored. | |
| 3216 | */ | |
| 3217 | getName(term) { | |
| 3218 | return this.termNames ? this.termNames[term] : String(term <= this.maxNode && this.nodeSet.types[term].name || term); | |
| 3219 | } | |
| 3220 | /** | |
| 3221 | The eof term id is always allocated directly after the node | |
| 3222 | types. @internal | |
| 3223 | */ | |
| 3224 | get eofTerm() { | |
| 3225 | return this.maxNode + 1; | |
| 3226 | } | |
| 3227 | /** | |
| 3228 | The type of top node produced by the parser. | |
| 3229 | */ | |
| 3230 | get topNode() { | |
| 3231 | return this.nodeSet.types[this.top[1]]; | |
| 3232 | } | |
| 3233 | /** | |
| 3234 | @internal | |
| 3235 | */ | |
| 3236 | dynamicPrecedence(term) { | |
| 3237 | let prec = this.dynamicPrecedences; | |
| 3238 | return prec == null ? 0 : prec[term] || 0; | |
| 3239 | } | |
| 3240 | /** | |
| 3241 | @internal | |
| 3242 | */ | |
| 3243 | parseDialect(dialect) { | |
| 3244 | let values = Object.keys(this.dialects), flags = values.map(() => false); | |
| 3245 | if (dialect) | |
| 3246 | for (let part of dialect.split(" ")) { | |
| 3247 | let id = values.indexOf(part); | |
| 3248 | if (id >= 0) | |
| 3249 | flags[id] = true; | |
| 3250 | } | |
| 3251 | let disabled = null; | |
| 3252 | for (let i = 0; i < values.length; i++) | |
| 3253 | if (!flags[i]) { | |
| 3254 | for (let j = this.dialects[values[i]], id; (id = this.data[j++]) != 65535; ) | |
| 3255 | (disabled || (disabled = new Uint8Array(this.maxTerm + 1)))[id] = 1; | |
| 3256 | } | |
| 3257 | return new Dialect(dialect, flags, disabled); | |
| 3258 | } | |
| 3259 | /** | |
| 3260 | Used by the output of the parser generator. Not available to | |
| 3261 | user code. @hide | |
| 3262 | */ | |
| 3263 | static deserialize(spec) { | |
| 3264 | return new _LRParser(spec); | |
| 3265 | } | |
| 3266 | }; | |
| 3267 | function pair(data, off) { | |
| 3268 | return data[off] | data[off + 1] << 16; | |
| 3269 | } | |
| 3270 | function findFinished(stacks) { | |
| 3271 | let best = null; | |
| 3272 | for (let stack of stacks) { | |
| 3273 | let stopped = stack.p.stoppedAt; | |
| 3274 | if ((stack.pos == stack.p.stream.end || stopped != null && stack.pos > stopped) && stack.p.parser.stateFlag( | |
| 3275 | stack.state, | |
| 3276 | 2 | |
| 3277 | /* StateFlag.Accepting */ | |
| 3278 | ) && (!best || best.score < stack.score)) | |
| 3279 | best = stack; | |
| 3280 | } | |
| 3281 | return best; | |
| 3282 | } | |
| 3283 | function getSpecializer(spec) { | |
| 3284 | if (spec.external) { | |
| 3285 | let mask = spec.extend ? 1 : 0; | |
| 3286 | return (value, stack) => spec.external(value, stack) << 1 | mask; | |
| 3287 | } | |
| 3288 | return spec.get; | |
| 3289 | } | |
| 3290 | ||
| 3291 | // node_modules/@lezer/highlight/dist/index.js | |
| 3292 | var nextTagID = 0; | |
| 3293 | var Tag = class _Tag { | |
| 3294 | /** | |
| 3295 | @internal | |
| 3296 | */ | |
| 3297 | constructor(name2, set, base, modified) { | |
| 3298 | this.name = name2; | |
| 3299 | this.set = set; | |
| 3300 | this.base = base; | |
| 3301 | this.modified = modified; | |
| 3302 | this.id = nextTagID++; | |
| 3303 | } | |
| 3304 | toString() { | |
| 3305 | let { name: name2 } = this; | |
| 3306 | for (let mod of this.modified) | |
| 3307 | if (mod.name) | |
| 3308 | name2 = `${mod.name}(${name2})`; | |
| 3309 | return name2; | |
| 3310 | } | |
| 3311 | static define(nameOrParent, parent) { | |
| 3312 | let name2 = typeof nameOrParent == "string" ? nameOrParent : "?"; | |
| 3313 | if (nameOrParent instanceof _Tag) | |
| 3314 | parent = nameOrParent; | |
| 3315 | if (parent === null || parent === void 0 ? void 0 : parent.base) | |
| 3316 | throw new Error("Can not derive from a modified tag"); | |
| 3317 | let tag = new _Tag(name2, [], null, []); | |
| 3318 | tag.set.push(tag); | |
| 3319 | if (parent) | |
| 3320 | for (let t2 of parent.set) | |
| 3321 | tag.set.push(t2); | |
| 3322 | return tag; | |
| 3323 | } | |
| 3324 | /** | |
| 3325 | Define a tag _modifier_, which is a function that, given a tag, | |
| 3326 | will return a tag that is a subtag of the original. Applying the | |
| 3327 | same modifier to a twice tag will return the same value (`m1(t1) | |
| 3328 | == m1(t1)`) and applying multiple modifiers will, regardless or | |
| 3329 | order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`). | |
| 3330 | ||
| 3331 | When multiple modifiers are applied to a given base tag, each | |
| 3332 | smaller set of modifiers is registered as a parent, so that for | |
| 3333 | example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`, | |
| 3334 | `m1(m3(t1)`, and so on. | |
| 3335 | */ | |
| 3336 | static defineModifier(name2) { | |
| 3337 | let mod = new Modifier(name2); | |
| 3338 | return (tag) => { | |
| 3339 | if (tag.modified.indexOf(mod) > -1) | |
| 3340 | return tag; | |
| 3341 | return Modifier.get(tag.base || tag, tag.modified.concat(mod).sort((a2, b) => a2.id - b.id)); | |
| 3342 | }; | |
| 3343 | } | |
| 3344 | }; | |
| 3345 | var nextModifierID = 0; | |
| 3346 | var Modifier = class _Modifier { | |
| 3347 | constructor(name2) { | |
| 3348 | this.name = name2; | |
| 3349 | this.instances = []; | |
| 3350 | this.id = nextModifierID++; | |
| 3351 | } | |
| 3352 | static get(base, mods) { | |
| 3353 | if (!mods.length) | |
| 3354 | return base; | |
| 3355 | let exists = mods[0].instances.find((t2) => t2.base == base && sameArray(mods, t2.modified)); | |
| 3356 | if (exists) | |
| 3357 | return exists; | |
| 3358 | let set = [], tag = new Tag(base.name, set, base, mods); | |
| 3359 | for (let m of mods) | |
| 3360 | m.instances.push(tag); | |
| 3361 | let configs = powerSet(mods); | |
| 3362 | for (let parent of base.set) | |
| 3363 | if (!parent.modified.length) | |
| 3364 | for (let config of configs) | |
| 3365 | set.push(_Modifier.get(parent, config)); | |
| 3366 | return tag; | |
| 3367 | } | |
| 3368 | }; | |
| 3369 | function sameArray(a2, b) { | |
| 3370 | return a2.length == b.length && a2.every((x, i) => x == b[i]); | |
| 3371 | } | |
| 3372 | function powerSet(array) { | |
| 3373 | let sets = [[]]; | |
| 3374 | for (let i = 0; i < array.length; i++) { | |
| 3375 | for (let j = 0, e = sets.length; j < e; j++) { | |
| 3376 | sets.push(sets[j].concat(array[i])); | |
| 3377 | } | |
| 3378 | } | |
| 3379 | return sets.sort((a2, b) => b.length - a2.length); | |
| 3380 | } | |
| 3381 | function styleTags(spec) { | |
| 3382 | let byName = /* @__PURE__ */ Object.create(null); | |
| 3383 | for (let prop in spec) { | |
| 3384 | let tags2 = spec[prop]; | |
| 3385 | if (!Array.isArray(tags2)) | |
| 3386 | tags2 = [tags2]; | |
| 3387 | for (let part of prop.split(" ")) | |
| 3388 | if (part) { | |
| 3389 | let pieces = [], mode = 2, rest = part; | |
| 3390 | for (let pos = 0; ; ) { | |
| 3391 | if (rest == "..." && pos > 0 && pos + 3 == part.length) { | |
| 3392 | mode = 1; | |
| 3393 | break; | |
| 3394 | } | |
| 3395 | let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest); | |
| 3396 | if (!m) | |
| 3397 | throw new RangeError("Invalid path: " + part); | |
| 3398 | pieces.push(m[0] == "*" ? "" : m[0][0] == '"' ? JSON.parse(m[0]) : m[0]); | |
| 3399 | pos += m[0].length; | |
| 3400 | if (pos == part.length) | |
| 3401 | break; | |
| 3402 | let next = part[pos++]; | |
| 3403 | if (pos == part.length && next == "!") { | |
| 3404 | mode = 0; | |
| 3405 | break; | |
| 3406 | } | |
| 3407 | if (next != "/") | |
| 3408 | throw new RangeError("Invalid path: " + part); | |
| 3409 | rest = part.slice(pos); | |
| 3410 | } | |
| 3411 | let last = pieces.length - 1, inner = pieces[last]; | |
| 3412 | if (!inner) | |
| 3413 | throw new RangeError("Invalid path: " + part); | |
| 3414 | let rule = new Rule(tags2, mode, last > 0 ? pieces.slice(0, last) : null); | |
| 3415 | byName[inner] = rule.sort(byName[inner]); | |
| 3416 | } | |
| 3417 | } | |
| 3418 | return ruleNodeProp.add(byName); | |
| 3419 | } | |
| 3420 | var ruleNodeProp = new NodeProp({ | |
| 3421 | combine(a2, b) { | |
| 3422 | let cur, root, take; | |
| 3423 | while (a2 || b) { | |
| 3424 | if (!a2 || b && a2.depth >= b.depth) { | |
| 3425 | take = b; | |
| 3426 | b = b.next; | |
| 3427 | } else { | |
| 3428 | take = a2; | |
| 3429 | a2 = a2.next; | |
| 3430 | } | |
| 3431 | if (cur && cur.mode == take.mode && !take.context && !cur.context) | |
| 3432 | continue; | |
| 3433 | let copy = new Rule(take.tags, take.mode, take.context); | |
| 3434 | if (cur) | |
| 3435 | cur.next = copy; | |
| 3436 | else | |
| 3437 | root = copy; | |
| 3438 | cur = copy; | |
| 3439 | } | |
| 3440 | return root; | |
| 3441 | } | |
| 3442 | }); | |
| 3443 | var Rule = class { | |
| 3444 | constructor(tags2, mode, context, next) { | |
| 3445 | this.tags = tags2; | |
| 3446 | this.mode = mode; | |
| 3447 | this.context = context; | |
| 3448 | this.next = next; | |
| 3449 | } | |
| 3450 | get opaque() { | |
| 3451 | return this.mode == 0; | |
| 3452 | } | |
| 3453 | get inherit() { | |
| 3454 | return this.mode == 1; | |
| 3455 | } | |
| 3456 | sort(other) { | |
| 3457 | if (!other || other.depth < this.depth) { | |
| 3458 | this.next = other; | |
| 3459 | return this; | |
| 3460 | } | |
| 3461 | other.next = this.sort(other.next); | |
| 3462 | return other; | |
| 3463 | } | |
| 3464 | get depth() { | |
| 3465 | return this.context ? this.context.length : 0; | |
| 3466 | } | |
| 3467 | }; | |
| 3468 | Rule.empty = new Rule([], 2, null); | |
| 3469 | function tagHighlighter(tags2, options) { | |
| 3470 | let map = /* @__PURE__ */ Object.create(null); | |
| 3471 | for (let style of tags2) { | |
| 3472 | if (!Array.isArray(style.tag)) | |
| 3473 | map[style.tag.id] = style.class; | |
| 3474 | else | |
| 3475 | for (let tag of style.tag) | |
| 3476 | map[tag.id] = style.class; | |
| 3477 | } | |
| 3478 | let { scope, all = null } = options || {}; | |
| 3479 | return { | |
| 3480 | style: (tags3) => { | |
| 3481 | let cls = all; | |
| 3482 | for (let tag of tags3) { | |
| 3483 | for (let sub of tag.set) { | |
| 3484 | let tagClass = map[sub.id]; | |
| 3485 | if (tagClass) { | |
| 3486 | cls = cls ? cls + " " + tagClass : tagClass; | |
| 3487 | break; | |
| 3488 | } | |
| 3489 | } | |
| 3490 | } | |
| 3491 | return cls; | |
| 3492 | }, | |
| 3493 | scope | |
| 3494 | }; | |
| 3495 | } | |
| 3496 | var t = Tag.define; | |
| 3497 | var comment = t(); | |
| 3498 | var name = t(); | |
| 3499 | var typeName = t(name); | |
| 3500 | var propertyName = t(name); | |
| 3501 | var literal = t(); | |
| 3502 | var string = t(literal); | |
| 3503 | var number = t(literal); | |
| 3504 | var content = t(); | |
| 3505 | var heading = t(content); | |
| 3506 | var keyword = t(); | |
| 3507 | var operator = t(); | |
| 3508 | var punctuation = t(); | |
| 3509 | var bracket = t(punctuation); | |
| 3510 | var meta = t(); | |
| 3511 | var tags = { | |
| 3512 | /** | |
| 3513 | A comment. | |
| 3514 | */ | |
| 3515 | comment, | |
| 3516 | /** | |
| 3517 | A line [comment](#highlight.tags.comment). | |
| 3518 | */ | |
| 3519 | lineComment: t(comment), | |
| 3520 | /** | |
| 3521 | A block [comment](#highlight.tags.comment). | |
| 3522 | */ | |
| 3523 | blockComment: t(comment), | |
| 3524 | /** | |
| 3525 | A documentation [comment](#highlight.tags.comment). | |
| 3526 | */ | |
| 3527 | docComment: t(comment), | |
| 3528 | /** | |
| 3529 | Any kind of identifier. | |
| 3530 | */ | |
| 3531 | name, | |
| 3532 | /** | |
| 3533 | The [name](#highlight.tags.name) of a variable. | |
| 3534 | */ | |
| 3535 | variableName: t(name), | |
| 3536 | /** | |
| 3537 | A type [name](#highlight.tags.name). | |
| 3538 | */ | |
| 3539 | typeName, | |
| 3540 | /** | |
| 3541 | A tag name (subtag of [`typeName`](#highlight.tags.typeName)). | |
| 3542 | */ | |
| 3543 | tagName: t(typeName), | |
| 3544 | /** | |
| 3545 | A property or field [name](#highlight.tags.name). | |
| 3546 | */ | |
| 3547 | propertyName, | |
| 3548 | /** | |
| 3549 | An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)). | |
| 3550 | */ | |
| 3551 | attributeName: t(propertyName), | |
| 3552 | /** | |
| 3553 | The [name](#highlight.tags.name) of a class. | |
| 3554 | */ | |
| 3555 | className: t(name), | |
| 3556 | /** | |
| 3557 | A label [name](#highlight.tags.name). | |
| 3558 | */ | |
| 3559 | labelName: t(name), | |
| 3560 | /** | |
| 3561 | A namespace [name](#highlight.tags.name). | |
| 3562 | */ | |
| 3563 | namespace: t(name), | |
| 3564 | /** | |
| 3565 | The [name](#highlight.tags.name) of a macro. | |
| 3566 | */ | |
| 3567 | macroName: t(name), | |
| 3568 | /** | |
| 3569 | A literal value. | |
| 3570 | */ | |
| 3571 | literal, | |
| 3572 | /** | |
| 3573 | A string [literal](#highlight.tags.literal). | |
| 3574 | */ | |
| 3575 | string, | |
| 3576 | /** | |
| 3577 | A documentation [string](#highlight.tags.string). | |
| 3578 | */ | |
| 3579 | docString: t(string), | |
| 3580 | /** | |
| 3581 | A character literal (subtag of [string](#highlight.tags.string)). | |
| 3582 | */ | |
| 3583 | character: t(string), | |
| 3584 | /** | |
| 3585 | An attribute value (subtag of [string](#highlight.tags.string)). | |
| 3586 | */ | |
| 3587 | attributeValue: t(string), | |
| 3588 | /** | |
| 3589 | A number [literal](#highlight.tags.literal). | |
| 3590 | */ | |
| 3591 | number, | |
| 3592 | /** | |
| 3593 | An integer [number](#highlight.tags.number) literal. | |
| 3594 | */ | |
| 3595 | integer: t(number), | |
| 3596 | /** | |
| 3597 | A floating-point [number](#highlight.tags.number) literal. | |
| 3598 | */ | |
| 3599 | float: t(number), | |
| 3600 | /** | |
| 3601 | A boolean [literal](#highlight.tags.literal). | |
| 3602 | */ | |
| 3603 | bool: t(literal), | |
| 3604 | /** | |
| 3605 | Regular expression [literal](#highlight.tags.literal). | |
| 3606 | */ | |
| 3607 | regexp: t(literal), | |
| 3608 | /** | |
| 3609 | An escape [literal](#highlight.tags.literal), for example a | |
| 3610 | backslash escape in a string. | |
| 3611 | */ | |
| 3612 | escape: t(literal), | |
| 3613 | /** | |
| 3614 | A color [literal](#highlight.tags.literal). | |
| 3615 | */ | |
| 3616 | color: t(literal), | |
| 3617 | /** | |
| 3618 | A URL [literal](#highlight.tags.literal). | |
| 3619 | */ | |
| 3620 | url: t(literal), | |
| 3621 | /** | |
| 3622 | A language keyword. | |
| 3623 | */ | |
| 3624 | keyword, | |
| 3625 | /** | |
| 3626 | The [keyword](#highlight.tags.keyword) for the self or this | |
| 3627 | object. | |
| 3628 | */ | |
| 3629 | self: t(keyword), | |
| 3630 | /** | |
| 3631 | The [keyword](#highlight.tags.keyword) for null. | |
| 3632 | */ | |
| 3633 | null: t(keyword), | |
| 3634 | /** | |
| 3635 | A [keyword](#highlight.tags.keyword) denoting some atomic value. | |
| 3636 | */ | |
| 3637 | atom: t(keyword), | |
| 3638 | /** | |
| 3639 | A [keyword](#highlight.tags.keyword) that represents a unit. | |
| 3640 | */ | |
| 3641 | unit: t(keyword), | |
| 3642 | /** | |
| 3643 | A modifier [keyword](#highlight.tags.keyword). | |
| 3644 | */ | |
| 3645 | modifier: t(keyword), | |
| 3646 | /** | |
| 3647 | A [keyword](#highlight.tags.keyword) that acts as an operator. | |
| 3648 | */ | |
| 3649 | operatorKeyword: t(keyword), | |
| 3650 | /** | |
| 3651 | A control-flow related [keyword](#highlight.tags.keyword). | |
| 3652 | */ | |
| 3653 | controlKeyword: t(keyword), | |
| 3654 | /** | |
| 3655 | A [keyword](#highlight.tags.keyword) that defines something. | |
| 3656 | */ | |
| 3657 | definitionKeyword: t(keyword), | |
| 3658 | /** | |
| 3659 | A [keyword](#highlight.tags.keyword) related to defining or | |
| 3660 | interfacing with modules. | |
| 3661 | */ | |
| 3662 | moduleKeyword: t(keyword), | |
| 3663 | /** | |
| 3664 | An operator. | |
| 3665 | */ | |
| 3666 | operator, | |
| 3667 | /** | |
| 3668 | An [operator](#highlight.tags.operator) that dereferences something. | |
| 3669 | */ | |
| 3670 | derefOperator: t(operator), | |
| 3671 | /** | |
| 3672 | Arithmetic-related [operator](#highlight.tags.operator). | |
| 3673 | */ | |
| 3674 | arithmeticOperator: t(operator), | |
| 3675 | /** | |
| 3676 | Logical [operator](#highlight.tags.operator). | |
| 3677 | */ | |
| 3678 | logicOperator: t(operator), | |
| 3679 | /** | |
| 3680 | Bit [operator](#highlight.tags.operator). | |
| 3681 | */ | |
| 3682 | bitwiseOperator: t(operator), | |
| 3683 | /** | |
| 3684 | Comparison [operator](#highlight.tags.operator). | |
| 3685 | */ | |
| 3686 | compareOperator: t(operator), | |
| 3687 | /** | |
| 3688 | [Operator](#highlight.tags.operator) that updates its operand. | |
| 3689 | */ | |
| 3690 | updateOperator: t(operator), | |
| 3691 | /** | |
| 3692 | [Operator](#highlight.tags.operator) that defines something. | |
| 3693 | */ | |
| 3694 | definitionOperator: t(operator), | |
| 3695 | /** | |
| 3696 | Type-related [operator](#highlight.tags.operator). | |
| 3697 | */ | |
| 3698 | typeOperator: t(operator), | |
| 3699 | /** | |
| 3700 | Control-flow [operator](#highlight.tags.operator). | |
| 3701 | */ | |
| 3702 | controlOperator: t(operator), | |
| 3703 | /** | |
| 3704 | Program or markup punctuation. | |
| 3705 | */ | |
| 3706 | punctuation, | |
| 3707 | /** | |
| 3708 | [Punctuation](#highlight.tags.punctuation) that separates | |
| 3709 | things. | |
| 3710 | */ | |
| 3711 | separator: t(punctuation), | |
| 3712 | /** | |
| 3713 | Bracket-style [punctuation](#highlight.tags.punctuation). | |
| 3714 | */ | |
| 3715 | bracket, | |
| 3716 | /** | |
| 3717 | Angle [brackets](#highlight.tags.bracket) (usually `<` and `>` | |
| 3718 | tokens). | |
| 3719 | */ | |
| 3720 | angleBracket: t(bracket), | |
| 3721 | /** | |
| 3722 | Square [brackets](#highlight.tags.bracket) (usually `[` and `]` | |
| 3723 | tokens). | |
| 3724 | */ | |
| 3725 | squareBracket: t(bracket), | |
| 3726 | /** | |
| 3727 | Parentheses (usually `(` and `)` tokens). Subtag of | |
| 3728 | [bracket](#highlight.tags.bracket). | |
| 3729 | */ | |
| 3730 | paren: t(bracket), | |
| 3731 | /** | |
| 3732 | Braces (usually `{` and `}` tokens). Subtag of | |
| 3733 | [bracket](#highlight.tags.bracket). | |
| 3734 | */ | |
| 3735 | brace: t(bracket), | |
| 3736 | /** | |
| 3737 | Content, for example plain text in XML or markup documents. | |
| 3738 | */ | |
| 3739 | content, | |
| 3740 | /** | |
| 3741 | [Content](#highlight.tags.content) that represents a heading. | |
| 3742 | */ | |
| 3743 | heading, | |
| 3744 | /** | |
| 3745 | A level 1 [heading](#highlight.tags.heading). | |
| 3746 | */ | |
| 3747 | heading1: t(heading), | |
| 3748 | /** | |
| 3749 | A level 2 [heading](#highlight.tags.heading). | |
| 3750 | */ | |
| 3751 | heading2: t(heading), | |
| 3752 | /** | |
| 3753 | A level 3 [heading](#highlight.tags.heading). | |
| 3754 | */ | |
| 3755 | heading3: t(heading), | |
| 3756 | /** | |
| 3757 | A level 4 [heading](#highlight.tags.heading). | |
| 3758 | */ | |
| 3759 | heading4: t(heading), | |
| 3760 | /** | |
| 3761 | A level 5 [heading](#highlight.tags.heading). | |
| 3762 | */ | |
| 3763 | heading5: t(heading), | |
| 3764 | /** | |
| 3765 | A level 6 [heading](#highlight.tags.heading). | |
| 3766 | */ | |
| 3767 | heading6: t(heading), | |
| 3768 | /** | |
| 3769 | A prose [content](#highlight.tags.content) separator (such as a horizontal rule). | |
| 3770 | */ | |
| 3771 | contentSeparator: t(content), | |
| 3772 | /** | |
| 3773 | [Content](#highlight.tags.content) that represents a list. | |
| 3774 | */ | |
| 3775 | list: t(content), | |
| 3776 | /** | |
| 3777 | [Content](#highlight.tags.content) that represents a quote. | |
| 3778 | */ | |
| 3779 | quote: t(content), | |
| 3780 | /** | |
| 3781 | [Content](#highlight.tags.content) that is emphasized. | |
| 3782 | */ | |
| 3783 | emphasis: t(content), | |
| 3784 | /** | |
| 3785 | [Content](#highlight.tags.content) that is styled strong. | |
| 3786 | */ | |
| 3787 | strong: t(content), | |
| 3788 | /** | |
| 3789 | [Content](#highlight.tags.content) that is part of a link. | |
| 3790 | */ | |
| 3791 | link: t(content), | |
| 3792 | /** | |
| 3793 | [Content](#highlight.tags.content) that is styled as code or | |
| 3794 | monospace. | |
| 3795 | */ | |
| 3796 | monospace: t(content), | |
| 3797 | /** | |
| 3798 | [Content](#highlight.tags.content) that has a strike-through | |
| 3799 | style. | |
| 3800 | */ | |
| 3801 | strikethrough: t(content), | |
| 3802 | /** | |
| 3803 | Inserted text in a change-tracking format. | |
| 3804 | */ | |
| 3805 | inserted: t(), | |
| 3806 | /** | |
| 3807 | Deleted text. | |
| 3808 | */ | |
| 3809 | deleted: t(), | |
| 3810 | /** | |
| 3811 | Changed text. | |
| 3812 | */ | |
| 3813 | changed: t(), | |
| 3814 | /** | |
| 3815 | An invalid or unsyntactic element. | |
| 3816 | */ | |
| 3817 | invalid: t(), | |
| 3818 | /** | |
| 3819 | Metadata or meta-instruction. | |
| 3820 | */ | |
| 3821 | meta, | |
| 3822 | /** | |
| 3823 | [Metadata](#highlight.tags.meta) that applies to the entire | |
| 3824 | document. | |
| 3825 | */ | |
| 3826 | documentMeta: t(meta), | |
| 3827 | /** | |
| 3828 | [Metadata](#highlight.tags.meta) that annotates or adds | |
| 3829 | attributes to a given syntactic element. | |
| 3830 | */ | |
| 3831 | annotation: t(meta), | |
| 3832 | /** | |
| 3833 | Processing instruction or preprocessor directive. Subtag of | |
| 3834 | [meta](#highlight.tags.meta). | |
| 3835 | */ | |
| 3836 | processingInstruction: t(meta), | |
| 3837 | /** | |
| 3838 | [Modifier](#highlight.Tag^defineModifier) that indicates that a | |
| 3839 | given element is being defined. Expected to be used with the | |
| 3840 | various [name](#highlight.tags.name) tags. | |
| 3841 | */ | |
| 3842 | definition: Tag.defineModifier("definition"), | |
| 3843 | /** | |
| 3844 | [Modifier](#highlight.Tag^defineModifier) that indicates that | |
| 3845 | something is constant. Mostly expected to be used with | |
| 3846 | [variable names](#highlight.tags.variableName). | |
| 3847 | */ | |
| 3848 | constant: Tag.defineModifier("constant"), | |
| 3849 | /** | |
| 3850 | [Modifier](#highlight.Tag^defineModifier) used to indicate that | |
| 3851 | a [variable](#highlight.tags.variableName) or [property | |
| 3852 | name](#highlight.tags.propertyName) is being called or defined | |
| 3853 | as a function. | |
| 3854 | */ | |
| 3855 | function: Tag.defineModifier("function"), | |
| 3856 | /** | |
| 3857 | [Modifier](#highlight.Tag^defineModifier) that can be applied to | |
| 3858 | [names](#highlight.tags.name) to indicate that they belong to | |
| 3859 | the language's standard environment. | |
| 3860 | */ | |
| 3861 | standard: Tag.defineModifier("standard"), | |
| 3862 | /** | |
| 3863 | [Modifier](#highlight.Tag^defineModifier) that indicates a given | |
| 3864 | [names](#highlight.tags.name) is local to some scope. | |
| 3865 | */ | |
| 3866 | local: Tag.defineModifier("local"), | |
| 3867 | /** | |
| 3868 | A generic variant [modifier](#highlight.Tag^defineModifier) that | |
| 3869 | can be used to tag language-specific alternative variants of | |
| 3870 | some common tag. It is recommended for themes to define special | |
| 3871 | forms of at least the [string](#highlight.tags.string) and | |
| 3872 | [variable name](#highlight.tags.variableName) tags, since those | |
| 3873 | come up a lot. | |
| 3874 | */ | |
| 3875 | special: Tag.defineModifier("special") | |
| 3876 | }; | |
| 3877 | for (let name2 in tags) { | |
| 3878 | let val = tags[name2]; | |
| 3879 | if (val instanceof Tag) | |
| 3880 | val.name = name2; | |
| 3881 | } | |
| 3882 | var classHighlighter = tagHighlighter([ | |
| 3883 | { tag: tags.link, class: "tok-link" }, | |
| 3884 | { tag: tags.heading, class: "tok-heading" }, | |
| 3885 | { tag: tags.emphasis, class: "tok-emphasis" }, | |
| 3886 | { tag: tags.strong, class: "tok-strong" }, | |
| 3887 | { tag: tags.keyword, class: "tok-keyword" }, | |
| 3888 | { tag: tags.atom, class: "tok-atom" }, | |
| 3889 | { tag: tags.bool, class: "tok-bool" }, | |
| 3890 | { tag: tags.url, class: "tok-url" }, | |
| 3891 | { tag: tags.labelName, class: "tok-labelName" }, | |
| 3892 | { tag: tags.inserted, class: "tok-inserted" }, | |
| 3893 | { tag: tags.deleted, class: "tok-deleted" }, | |
| 3894 | { tag: tags.literal, class: "tok-literal" }, | |
| 3895 | { tag: tags.string, class: "tok-string" }, | |
| 3896 | { tag: tags.number, class: "tok-number" }, | |
| 3897 | { tag: [tags.regexp, tags.escape, tags.special(tags.string)], class: "tok-string2" }, | |
| 3898 | { tag: tags.variableName, class: "tok-variableName" }, | |
| 3899 | { tag: tags.local(tags.variableName), class: "tok-variableName tok-local" }, | |
| 3900 | { tag: tags.definition(tags.variableName), class: "tok-variableName tok-definition" }, | |
| 3901 | { tag: tags.special(tags.variableName), class: "tok-variableName2" }, | |
| 3902 | { tag: tags.definition(tags.propertyName), class: "tok-propertyName tok-definition" }, | |
| 3903 | { tag: tags.typeName, class: "tok-typeName" }, | |
| 3904 | { tag: tags.namespace, class: "tok-namespace" }, | |
| 3905 | { tag: tags.className, class: "tok-className" }, | |
| 3906 | { tag: tags.macroName, class: "tok-macroName" }, | |
| 3907 | { tag: tags.propertyName, class: "tok-propertyName" }, | |
| 3908 | { tag: tags.operator, class: "tok-operator" }, | |
| 3909 | { tag: tags.comment, class: "tok-comment" }, | |
| 3910 | { tag: tags.meta, class: "tok-meta" }, | |
| 3911 | { tag: tags.invalid, class: "tok-invalid" }, | |
| 3912 | { tag: tags.punctuation, class: "tok-punctuation" } | |
| 3913 | ]); | |
| 3914 | ||
| 3915 | // node_modules/@lezer/cpp/dist/index.js | |
| 3916 | var RawString = 1; | |
| 3917 | var templateArgsEndFallback = 2; | |
| 3918 | var MacroName = 3; | |
| 3919 | var R = 82; | |
| 3920 | var L = 76; | |
| 3921 | var u = 117; | |
| 3922 | var U = 85; | |
| 3923 | var a = 97; | |
| 3924 | var z = 122; | |
| 3925 | var A = 65; | |
| 3926 | var Z = 90; | |
| 3927 | var Underscore = 95; | |
| 3928 | var Zero = 48; | |
| 3929 | var Quote = 34; | |
| 3930 | var ParenL = 40; | |
| 3931 | var ParenR = 41; | |
| 3932 | var Space = 32; | |
| 3933 | var GreaterThan = 62; | |
| 3934 | var rawString = new ExternalTokenizer((input) => { | |
| 3935 | if (input.next == L || input.next == U) { | |
| 3936 | input.advance(); | |
| 3937 | } else if (input.next == u) { | |
| 3938 | input.advance(); | |
| 3939 | if (input.next == Zero + 8) input.advance(); | |
| 3940 | } | |
| 3941 | if (input.next != R) return; | |
| 3942 | input.advance(); | |
| 3943 | if (input.next != Quote) return; | |
| 3944 | input.advance(); | |
| 3945 | let marker = ""; | |
| 3946 | while (input.next != ParenL) { | |
| 3947 | if (input.next == Space || input.next <= 13 || input.next == ParenR) return; | |
| 3948 | marker += String.fromCharCode(input.next); | |
| 3949 | input.advance(); | |
| 3950 | } | |
| 3951 | input.advance(); | |
| 3952 | for (; ; ) { | |
| 3953 | if (input.next < 0) | |
| 3954 | return input.acceptToken(RawString); | |
| 3955 | if (input.next == ParenR) { | |
| 3956 | let match = true; | |
| 3957 | for (let i = 0; match && i < marker.length; i++) | |
| 3958 | if (input.peek(i + 1) != marker.charCodeAt(i)) match = false; | |
| 3959 | if (match && input.peek(marker.length + 1) == Quote) | |
| 3960 | return input.acceptToken(RawString, 2 + marker.length); | |
| 3961 | } | |
| 3962 | input.advance(); | |
| 3963 | } | |
| 3964 | }); | |
| 3965 | var fallback = new ExternalTokenizer((input) => { | |
| 3966 | if (input.next == GreaterThan) { | |
| 3967 | if (input.peek(1) == GreaterThan) | |
| 3968 | input.acceptToken(templateArgsEndFallback, 1); | |
| 3969 | } else { | |
| 3970 | let sawLetter = false, i = 0; | |
| 3971 | for (; ; i++) { | |
| 3972 | if (input.next >= A && input.next <= Z) sawLetter = true; | |
| 3973 | else if (input.next >= a && input.next <= z) return; | |
| 3974 | else if (input.next != Underscore && !(input.next >= Zero && input.next <= Zero + 9)) break; | |
| 3975 | input.advance(); | |
| 3976 | } | |
| 3977 | if (sawLetter && i > 1) input.acceptToken(MacroName); | |
| 3978 | } | |
| 3979 | }, { extend: true }); | |
| 3980 | var cppHighlighting = styleTags({ | |
| 3981 | "typedef struct union enum class typename decltype auto template operator friend noexcept namespace using requires concept import export module __attribute__ __declspec __based": tags.definitionKeyword, | |
| 3982 | "extern MsCallModifier MsPointerModifier extern static register thread_local inline const volatile restrict _Atomic mutable constexpr constinit consteval virtual explicit VirtualSpecifier Access": tags.modifier, | |
| 3983 | "if else switch for while do case default return break continue goto throw try catch": tags.controlKeyword, | |
| 3984 | "co_return co_yield co_await": tags.controlKeyword, | |
| 3985 | "new sizeof delete static_assert": tags.operatorKeyword, | |
| 3986 | "NULL nullptr": tags.null, | |
| 3987 | this: tags.self, | |
| 3988 | "True False": tags.bool, | |
| 3989 | "TypeSize PrimitiveType": tags.standard(tags.typeName), | |
| 3990 | TypeIdentifier: tags.typeName, | |
| 3991 | FieldIdentifier: tags.propertyName, | |
| 3992 | "CallExpression/FieldExpression/FieldIdentifier": tags.function(tags.propertyName), | |
| 3993 | "ModuleName/Identifier": tags.namespace, | |
| 3994 | "PartitionName": tags.labelName, | |
| 3995 | StatementIdentifier: tags.labelName, | |
| 3996 | "Identifier DestructorName": tags.variableName, | |
| 3997 | "CallExpression/Identifier": tags.function(tags.variableName), | |
| 3998 | "CallExpression/ScopedIdentifier/Identifier": tags.function(tags.variableName), | |
| 3999 | "FunctionDeclarator/Identifier FunctionDeclarator/DestructorName": tags.function(tags.definition(tags.variableName)), | |
| 4000 | NamespaceIdentifier: tags.namespace, | |
| 4001 | OperatorName: tags.operator, | |
| 4002 | ArithOp: tags.arithmeticOperator, | |
| 4003 | LogicOp: tags.logicOperator, | |
| 4004 | BitOp: tags.bitwiseOperator, | |
| 4005 | CompareOp: tags.compareOperator, | |
| 4006 | AssignOp: tags.definitionOperator, | |
| 4007 | UpdateOp: tags.updateOperator, | |
| 4008 | LineComment: tags.lineComment, | |
| 4009 | BlockComment: tags.blockComment, | |
| 4010 | Number: tags.number, | |
| 4011 | String: tags.string, | |
| 4012 | "RawString SystemLibString": tags.special(tags.string), | |
| 4013 | CharLiteral: tags.character, | |
| 4014 | EscapeSequence: tags.escape, | |
| 4015 | "UserDefinedLiteral/Identifier": tags.literal, | |
| 4016 | PreProcArg: tags.meta, | |
| 4017 | "PreprocDirectiveName #include #ifdef #ifndef #if #define #else #endif #elif": tags.processingInstruction, | |
| 4018 | MacroName: tags.special(tags.name), | |
| 4019 | "( )": tags.paren, | |
| 4020 | "[ ]": tags.squareBracket, | |
| 4021 | "{ }": tags.brace, | |
| 4022 | "< >": tags.angleBracket, | |
| 4023 | ". ->": tags.derefOperator, | |
| 4024 | ", ;": tags.separator | |
| 4025 | }); | |
| 4026 | var spec_identifier = { __proto__: null, bool: 36, char: 36, int: 36, float: 36, double: 36, void: 36, size_t: 36, ssize_t: 36, intptr_t: 36, uintptr_t: 36, charptr_t: 36, int8_t: 36, int16_t: 36, int32_t: 36, int64_t: 36, uint8_t: 36, uint16_t: 36, uint32_t: 36, uint64_t: 36, char8_t: 36, char16_t: 36, char32_t: 36, char64_t: 36, const: 70, volatile: 72, restrict: 74, _Atomic: 76, mutable: 78, constexpr: 80, constinit: 82, consteval: 84, struct: 88, __declspec: 92, final: 148, override: 148, public: 152, private: 152, protected: 152, virtual: 154, extern: 160, static: 162, register: 164, inline: 166, thread_local: 168, __attribute__: 172, __based: 178, __restrict: 180, __uptr: 180, __sptr: 180, _unaligned: 180, __unaligned: 180, noexcept: 194, requires: 198, TRUE: 796, true: 796, FALSE: 798, false: 798, typename: 218, class: 220, template: 234, throw: 248, __cdecl: 256, __clrcall: 256, __stdcall: 256, __fastcall: 256, __thiscall: 256, __vectorcall: 256, try: 260, catch: 264, export: 282, import: 286, case: 296, default: 298, if: 308, else: 314, switch: 318, do: 322, while: 324, for: 330, return: 334, break: 338, continue: 342, goto: 346, co_return: 350, co_yield: 354, using: 362, typedef: 366, namespace: 380, new: 398, delete: 400, co_await: 402, concept: 406, enum: 410, static_assert: 414, friend: 422, union: 424, explicit: 430, operator: 444, module: 456, signed: 518, unsigned: 518, long: 518, short: 518, decltype: 528, auto: 530, sizeof: 566, NULL: 572, nullptr: 586, this: 588 }; | |
| 4027 | var spec_ = { __proto__: null, "<": 765 }; | |
| 4028 | var spec_templateArgsEnd = { __proto__: null, ">": 135 }; | |
| 4029 | var spec_scopedIdentifier = { __proto__: null, operator: 388, new: 576, delete: 582 }; | |
| 4030 | var parser = LRParser.deserialize({ | |
| 4031 | version: 14, | |
| 4032 | states: "$;xQ!QQVOOP'gOUOOO([OWO'#CdO,UQUO'#CgO,`QUO'#FjO-vQbO'#CxO.XQUO'#CxO0WQUO'#K`O0_QUO'#CwO0jOpO'#DvO0rQ!dO'#D]OOQR'#JP'#JPO5[QVO'#GUO5iQUO'#JWOOQQ'#JW'#JWO8}QUO'#KsO<hQUO'#KsO?OQVO'#E^O?`QUO'#E^OOQQ'#Ed'#EdOOQQ'#Ee'#EeO?eQVO'#EfO@[QVO'#EiOBXQUO'#FPOByQUO'#FhOOQR'#Fj'#FjOCOQUO'#FjOOQR'#LW'#LWOOQR'#LV'#LVOEWQVO'#KVOF{QUO'#L]OGYQUO'#KwOGnQUO'#L]OH`QUO'#L_OOQR'#HU'#HUOOQR'#HV'#HVOOQR'#HW'#HWOOQR'#LS'#LSOOQR'#J`'#J`Q!QQVOOOHnQVO'#FOOIZQUO'#EhOIbQUOOOK^QVO'#HgOKnQUO'#HgONYQUO'#KwONdQUO'#KwOOQQ'#Kw'#KwO!!bQUO'#KwOOQQ'#Jr'#JrO!!oQUO'#HxOOQQ'#K`'#K`O!&aQUO'#K`O!&}QUO'#KVO!(}QVO'#I]O!(}QVO'#I`OCTQUO'#KVOOQQ'#Ip'#IpOOQQ'#KV'#KVO!-QQUO'#K`OOQR'#K_'#K_O!-XQUO'#DZO!/pQUO'#KtOOQQ'#Kt'#KtO!/wQUO'#KtO!0OQUO'#ETO!0TQUO'#EWO!0YQUO'#FRO8}QUO'#FPO!QQVO'#F^O!0_Q#vO'#F`O!0jQUO'#FkO!0rQUO'#FpO!0wQVO'#FrO!0rQUO'#FuO!3vQUO'#FvO!3{QVO'#FxO!4VQUO'#FzO!4[QUO'#F|O!4aQUO'#GOO!4fQVO'#GQO!(}QVO'#GSO!4mQUO'#GpO!4{QUO'#GYO!(}QVO'#FeO!6YQUO'#FeO!6_QVO'#G`O!6fQUO'#GaO!6qQUO'#GnO!6vQUO'#GrO!6{QUO'#GzO!7mQ&lO'#HiO!:pQUO'#GuO!;QQUO'#HXO!;]QUO'#HZO!;eQUO'#DXO!;eQUO'#HuO!;eQUO'#HvO!;|QUO'#HwO!<_QUO'#H|O!=SQUO'#H}O!>xQVO'#IbO!(}QVO'#IdO!?SQUO'#IgO!?ZQVO'#IjP!AQO!LQO'#CaP!A]{,UO'#CbP!6q{,UO'#CbP!Ah{7[O'#CbP!6q{,UO'#CbP!Am{,UO'#CbP!AxOSO'#IzPOOO)CEo)CEoOOOO'#I}'#I}O!BSOWO,59OOOQR,59O,59OO!(}QVO,59VOOQQ,59X,59XOOQR'#Do'#DoO!(}QVO,5;ROOQR,5<U,5<UO!B_QUO,59ZO!(}QVO,5>qOOQR'#IX'#IXOOQR'#IY'#IYOOQR'#IZ'#IZOOQR'#I['#I[O!(}QVO,5>rO!(}QVO,5>rO!(}QVO,5>rO!(}QVO,5>rO!(}QVO,5>rO!(}QVO,5>rO!(}QVO,5>rO!(}QVO,5>rO!(}QVO,5>rO!(}QVO,5>rO!D^QVO,5>zOOQQ,5?W,5?WO!FPQVO'#CjO!IxQUO'#CzOOQQ,59d,59dOOQQ,59c,59cOOQQ,5<},5<}O!JVQ&lO,5=mO!?SQUO,5?RO!LyQVO,5?UO!MQQbO,59dO!M]QVO'#FYOOQQ,5?P,5?PO!MmQVO,59WO!MtO`O,5:bO!MyQbO'#D^O!N[QbO'#KdO!NjQbO,59wO!NrQbO'#CxO# TQUO'#CxO# YQUO'#K`O# dQUO'#CwOOQR-E<}-E<}O# oQUO,5AuO# vQVO'#EfO@[QVO'#EiOBXQUO,5;kOOQR,5<p,5<pO#$oQUO'#KVO#$vQUO'#KVO!(}QVO'#IUO8}QUO,5;kO#%ZQ&lO'#HiO#(bQUO'#CtO#+VQbO'#CxO#+[QUO'#CwO#.xQUO'#K`OOQQ-E=U-E=UO#1]QUO,5A_O#1gQUO'#K`O#1qQUO,5A_OOQR,5Au,5AuOOQQ,5>l,5>lO#3uQUO'#CgO#4kQUO,5>pO#6^QUO'#IeOOQR'#JO'#JOO#6fQUO,5:xO#7SQUO,5:xO#7sQUO,5:xO#8hQUO'#CuO!0TQUO'#CmOOQQ'#JX'#JXO#7SQUO,5:xO#8pQUO,5;QO!4{QUO'#DOO#9yQUO,5;QO#:OQUO,5>QO#;[QUO'#DOO#;rQUO,5>{O#;wQUO'#K}O#=QQUO,5;TO#=YQVO,5;TO#=dQUO,5;TOOQQ,5;T,5;TO#?]QUO'#LbO#?dQUO,5>UO#?iQbO'#CxO#?tQUO'#GcO#?yQUO'#E^O#@jQUO,5;kO#ARQUO'#LTO#AZQUO,5;rOKnQUO'#HfOBXQUO'#HgO#A`QUO'#KwO!6qQUO'#HjO#BWQUO'#CuO!0wQVO,5<SOOQQ'#Cg'#CgOOQR'#Ji'#JiO#B]QVO,5=`OOQQ,5?Z,5?ZO#DfQbO'#CxO#DqQUO'#GcOOQQ'#Jj'#JjOOQQ-E=h-E=hOGYQUO,5AwOGnQUO,5AwO#DvQUO,5AyO#ERQUO'#G|OOQR,5Aw,5AwO#DvQUO,5AwO#E^QUO'#HOO#EfQUO,5AyOOQR,5Ay,5AyOOQR,5Az,5AzO#EtQVO,5AzOOQR-E=^-E=^O#GnQVO,5;jOOQR,5;j,5;jO#IoQUO'#EjO#JtQUO'#EwO#KkQVO'#ExO#M}QUO'#EvO#NVQUO'#EyO$ UQUO'#EzOOQQ'#LQ'#LQO$ {QUO,5;SO$#RQUO'#EvOOQQ,5;S,5;SO$$OQUO,5;SO$%qQUO,5:yO$([QVO,5>PO$(fQUO'#E[O$(sQUO,5>ROOQQ,5>S,5>SO$,aQVO'#C|OOQQ-E=p-E=pOOQQ,5>d,5>dOOQQ,59a,59aO$,kQUO,5>wO$.kQUO,5>zO!6qQUO,59uO$/OQUO,5;qO$/]QUO,5<{O!0TQUO,5:oOOQQ,5:r,5:rO$/hQUO,5;mO$/mQUO'#KsOBXQUO,5;kOOQR,5;x,5;xO$0^QUO'#FbO$0lQUO'#FbO$0qQUO,5;zO$4[QVO'#FmO!0wQVO,5<VO!0rQUO,5<VO!0YQUO,5<[O$4cQVO'#GUO$7_QUO,5<^O!0wQVO,5<aO$:uQVO,5<bO$;SQUO,5<dOOQR,5<d,5<dO$<]QUO,5<dOOQR,5<f,5<fOOQR,5<h,5<hOOQQ'#Fi'#FiO$<bQUO,5<jO$<gQUO,5<lOOQR,5<l,5<lO$=mQUO,5<nO$>sQUO,5<rO$?OQUO,5=[O$?TQUO,5=[O!4{QUO,5<tO$?]QUO,5<tO$?qQUO,5<PO$@wQVO,5<PO$CYQUO,5<zOOQR,5<z,5<zOOQR,5<{,5<{O$?TQUO,5<{O$D`QUO,5<{O$DkQUO,5=YO!(}QVO,5=^O!(}QVO,5=fO#NsQUO,5=mOOQQ,5>T,5>TO$FpQUO,5>TO$FzQUO,5>TO$GPQUO,5>TO$GUQUO,5>TO!6qQUO,5>TO$ISQUO'#K`O$IZQUO,5=oO$IfQUO,5=aOKnQUO,5=oO$J`QUO,5=sOOQR,5=s,5=sO$JhQUO,5=sO$LsQVO'#H[OOQQ,5=u,5=uO!;`QUO,5=uO%#nQUO'#KpO%#uQUO'#KaO%$ZQUO'#KpO%$eQUO'#DyO%$vQUO'#D|O%'sQUO'#KaOOQQ'#Ka'#KaO%)fQUO'#KaO%#uQUO'#KaO%)kQUO'#KaOOQQ,59s,59sOOQQ,5>a,5>aOOQQ,5>b,5>bO%)sQUO'#HzO%){QUO,5>cOOQQ,5>c,5>cO%-gQUO,5>cO%-rQUO,5>hO%1^QVO,5>iO%1eQUO,5>|O# vQVO'#EfO%4kQUO,5>|OOQQ,5>|,5>|O%5[QUO,5?OO%7`QUO,5?RO!<_QUO,5?RO%9[QUO,5?UO%<wQVO,5?UPOOO'#I|'#I|P%=OO!LQO,58{POOO,58{,58{P!Am{,UO,58|P%=Z{,UO,58|P%=i{7[O,58|P%=o{,UO,58|PO{O'#Jv'#JvP%=t{,UO'#LiPOOO'#Li'#LiP%=z{,UO'#LiPOOO,58|,58|POOO,5?f,5?fP%>POSO,5?fOOOO-E<{-E<{OOQR1G.j1G.jO%>WQUO1G.qO%?^QUO1G0mOOQQ1G0m1G0mO%@jQUO'#CpO%ByQbO'#CxO%CUQUO'#CsO%CZQUO'#CsO%C`QUO1G.uO#BWQUO'#CrOOQQ1G.u1G.uO%EcQUO1G4]O%FiQUO1G4^O%H[QUO1G4^O%I}QUO1G4^O%KpQUO1G4^O%McQUO1G4^O& UQUO1G4^O&!wQUO1G4^O&$jQUO1G4^O&&]QUO1G4^O&(OQUO1G4^O&)qQUO1G4^O&+dQUO'#KUO&,mQUO'#KUO&,uQUO,59UOOQQ,5=P,5=PO&.}QUO,5=PO&/XQUO,5=PO&/^QUO,5=PO&/cQUO,5=PO!6qQUO,5=PO#NsQUO1G3XO&/mQUO1G4mO!<_QUO1G4mO&1iQUO1G4pO&3[QVO1G4pOOQQ1G/O1G/OOOQQ1G.}1G.}OOQQ1G2i1G2iO!JVQ&lO1G3XO&3cQUO'#LUO@[QVO'#EiO&4lQUO'#F]OOQQ'#Jb'#JbO&4qQUO'#FZO&4|QUO'#LUO&5UQUO,5;tO&5ZQUO1G.rOOQQ1G.r1G.rOOQR1G/|1G/|O&6|Q!dO'#JQO&7RQbO,59xO&9dQ!eO'#D`O&9kQ!dO'#JSO&9pQbO,5AOO&9pQbO,5AOOOQR1G/c1G/cO&9{QbO1G/cO&:QQ&lO'#GeO&;OQbO,59dOOQR1G7a1G7aO#@jQUO1G1VO&;ZQUO1G1^OBXQUO1G1VO&=lQUO'#CzO#+VQbO,59dO&A_QUO1G6yOOQR-E<|-E<|O&BqQUO1G0dO#6fQUO1G0dOOQQ-E=V-E=VO#7SQUO1G0dOOQQ1G0l1G0lO&CfQUO,59jOOQQ1G3l1G3lO&C|QUO,59jO&DdQUO,59jO!MmQVO1G4gO!(}QVO'#JZO&EOQUO,5AiOOQQ1G0o1G0oO!(}QVO1G0oO!6qQUO'#JoO&EWQUO,5A|OOQQ1G3p1G3pOOQR1G1V1G1VO&ITQVO'#FOO!MmQVO,5;sOOQQ,5;s,5;sOBXQUO'#JdO&KPQUO,5AoO&KXQVO'#E[OOQR1G1^1G1^O&MvQUO'#LbOOQR1G1n1G1nOOQR-E=g-E=gOOQR1G7c1G7cO#DvQUO1G7cOGYQUO1G7cO#DvQUO1G7eOOQR1G7e1G7eO&NOQUO'#G}O&NWQUO'#L^OOQQ,5=h,5=hO&NfQUO,5=jO&NkQUO,5=kOOQR1G7f1G7fO#EtQVO1G7fO&NpQUO1G7fO' vQVO,5=kOOQR1G1U1G1UO$/UQUO'#E]O'!lQUO'#E]OOQQ'#LP'#LPO'#VQUO'#LOO'#bQUO,5;UO'#jQUO'#ElO'#}QUO'#ElO'$bQUO'#EtOOQQ'#J]'#J]O'$gQUO,5;cO'%^QUO,5;cO'&XQUO,5;dO''_QVO,5;dOOQQ,5;d,5;dO''iQVO,5;dO''_QVO,5;dO''pQUO,5;bO'(mQUO,5;eO'(xQUO'#KvO')QQUO,5:vO')VQUO,5;fOOQQ1G0n1G0nOOQQ'#J^'#J^O''pQUO,5;bO!4{QUO'#E}OOQQ,5;b,5;bO'*QQUO'#E`O'+zQUO'#E{OHuQUO1G0nO',PQUO'#EbOOQQ'#JY'#JYO'-iQUO'#KxOOQQ'#Kx'#KxO'.cQUO1G0eO'/ZQUO1G3kO'0aQVO1G3kOOQQ1G3k1G3kO'0kQVO1G3kO'0rQUO'#LeO'2OQUO'#K^O'2^QUO'#K]O'2iQUO,59hO'2qQUO1G/aO'2vQUO'#FPOOQR1G1]1G1]OOQR1G2g1G2gO$?TQUO1G2gO'3QQUO1G2gO'3]QUO1G0ZOOQR'#Ja'#JaO'3bQVO1G1XO'9ZQUO'#FTO'9`QUO1G1VO!6qQUO'#JeO'9nQUO,5;|O$0lQUO,5;|OOQQ'#Fc'#FcOOQQ,5;|,5;|O'9|QUO1G1fOOQR1G1f1G1fO':UQUO,5<XO$/UQUO'#FWOBXQUO'#FWO':]QUO,5<XO!(}QVO,5<XO':eQUO,5<XO':jQVO1G1qO!0wQVO1G1qOOQR1G1v1G1vO'@YQUO1G1xOOQR1G1{1G1{O'@_QUO1G1|OBXQUO1G2]O'AhQVO1G1|O'C|QUO1G1|O'DRQUO'#GWO8}QUO1G2]OOQR1G2O1G2OOOQR1G2U1G2UOOQR1G2W1G2WOOQR1G2Y1G2YO'DWQUO1G2^O!4{QUO1G2^OOQR1G2v1G2vO'D`QUO1G2vO$?]QUO1G2`OOQQ'#Cv'#CvO'DeQUO'#G[O'E`QUO'#G[O'EeQUO'#LXO'EsQUO'#G_OOQQ'#LY'#LYO'FRQUO1G2`O'FWQVO1G1kO'HiQVO'#GUOBXQUO'#FWOOQR'#Jf'#JfO'FWQVO1G1kO'HsQUO'#FvOOQR1G2f1G2fO'HxQUO1G2gO'H}QUO'#JhO'3QQUO1G2gO!(}QVO1G2tO'IVQUO1G2xO'J`QUO1G3QO'KfQUO1G3XOOQQ1G3o1G3oO'KzQUO1G3oOOQR1G3Z1G3ZO'LPQUO'#K`O'2vQUO'#LZOGnQUO'#L]OOQR'#Gy'#GyO#DvQUO'#L_OOQR'#HQ'#HQO'LZQUO'#GvO'$bQUO'#GuOOQR1G2{1G2{O'MWQUO1G2{O'M}QUO1G3ZO'NYQUO1G3_O'N_QUO1G3_OOQR1G3_1G3_O'NgQUO'#H]OOQR'#H]'#H]O( pQUO'#H]O!(}QVO'#H`O!(}QVO'#H_OOQR'#La'#LaO( uQUO'#LaOOQR'#Jl'#JlO( zQVO,5=vOOQQ,5=v,5=vO(!RQUO'#H^O(!ZQUO'#HZOOQQ1G3a1G3aO(!eQUO,5@{OOQQ,5@{,5@{O%)fQUO,5@{O%)kQUO,5@{O%$eQUO,5:eO(&SQUO'#KqO(&bQUO'#KqOOQQ,5:e,5:eOOQQ'#JT'#JTO(&mQUO'#D}O(&wQUO'#KwOGnQUO'#L]O('sQUO'#D}OOQQ'#Hp'#HpOOQQ'#Hr'#HrOOQQ'#Hs'#HsOOQQ'#Kr'#KrOOQQ'#JV'#JVO('}QUO,5:hOOQQ,5:h,5:hO((zQUO'#L]O()XQUO'#HtO()oQUO,5@{O()vQUO'#H{O(*RQUO'#LdO(*ZQUO,5>fO(*`QUO'#LcOOQQ1G3}1G3}O(.VQUO1G3}O(.^QUO1G3}O(.eQUO1G4TO(/kQUO1G4TO(/pQUO,5BSO!6qQUO1G4hO!(}QVO'#IiOOQQ1G4m1G4mO(/uQUO1G4mO(1xQVO1G4pPOOO-E<z-E<zPOOO1G.g1G.gPOOO1G.h1G.hP!Am{,UO1G.hP(3xQUO'#LkP(4T{,UO1G.hP(4Y{7[O1G.hPO{O-E=t-E=tPOOO,5BT,5BTP(4b{,UO,5BTPOOO1G5Q1G5QO!(}QVO7+$]O(4gQUO'#CzOOQQ,59_,59_O(4rQbO,59dO(4}QbO,59_OOQQ,59^,59^OOQQ7+)w7+)wO!MmQVO'#JuO(5YQUO,5@pOOQQ1G.p1G.pOOQQ1G2k1G2kO(5bQUO1G2kO(5gQUO7+(sOOQQ7+*X7+*XO(7{QUO7+*XO(8SQUO7+*XO(1xQVO7+*[O#NsQUO7+(sO(8aQVO'#JcO(8tQUO,5ApO(8|QUO,5;vOOQQ'#Cp'#CpOOQQ,5;w,5;wO!(}QVO'#F[OOQQ-E=`-E=`O!MmQVO,5;uOOQQ1G1`1G1`OOQQ,5?l,5?lOOQQ-E=O-E=OOOQR'#Dg'#DgOOQR'#Di'#DiOOQR'#Dl'#DlO(:VQ!eO'#KeO(:^QMkO'#KeO(:eQ!eO'#KeOOQR'#Ke'#KeOOQR'#JR'#JRO(:lQ!eO,59zOOQQ,59z,59zO(:sQbO,5?nOOQQ-E=Q-E=QO(;RQbO1G6jOOQR7+$}7+$}OOQR7+&q7+&qOOQR7+&x7+&xO'9`QUO7+&qO(;^QUO7+&OO#6fQUO7+&OO(<RQUO1G/UO(<iQUO1G/UO(=TQUO7+*ROOQQ7+*V7+*VO(>vQUO,5?uOOQQ-E=X-E=XO(@PQUO7+&ZOOQQ,5@Z,5@ZOOQQ-E=m-E=mO(@UQUO'#LUO@[QVO'#EiO(AbQUO1G1_OOQQ1G1_1G1_O(BkQUO,5@OOOQQ,5@O,5@OOOQQ-E=b-E=bO(CPQUO'#KvOOQR7+,}7+,}O#DvQUO7+,}OOQR7+-P7+-PO(C^QUO,5=iO#ERQUO'#JkO(CoQUO,5AxOOQR1G3U1G3UOOQR1G3V1G3VO(C}QUO7+-QOOQR7+-Q7+-QO(EuQUO,5:wO(GdQUO'#EwO!(}QVO,5;VO(HVQUO,5:wO(HaQUO'#EpO(HrQUO'#EzOOQQ,5;Z,5;ZO#KkQVO'#ExO(IYQUO,5:wO(IaQUO'#EyO#GuQUO'#J[O(JyQUO,5AjOOQQ1G0p1G0pO(KUQUO,5;WO!<_QUO,5;^O(KoQUO,5;_O(K}QUO,5;WO(NaQUO,5;`OOQQ-E=Z-E=ZO(NiQUO1G0}OOQQ1G1O1G1OO) dQUO1G1OO)!jQVO1G1OO)!qQVO1G1OO)!{QUO1G0|OOQQ1G0|1G0|OOQQ1G1P1G1PO)#xQUO'#JpO)$SQUO,5AbOOQQ1G0b1G0bOOQQ-E=[-E=[O)$[QUO,5;iO!<_QUO,5;iO)%XQVO,5:zO)%`QUO,5;gO$ {QUO7+&YOOQQ7+&Y7+&YO!(}QVO'#EfO)%gQUO,5:|OOQQ'#Ky'#KyOOQQ-E=W-E=WOOQQ,5Ad,5AdOOQQ'#Jm'#JmO))[QUO7+&PPOQQ7+&P7+&POOQQ7+)V7+)VO)*SQUO7+)VO)+YQVO7+)VOOQQ,5>m,5>mO$)hQVO'#JtO)+aQUO,5@wOOQQ1G/S1G/SOOQQ7+${7+${O)+lQUO7+(RO)+qQUO7+(ROOQR7+(R7+(RO$?TQUO7+(ROOQQ7+%u7+%uOOQR-E=_-E=_O!0YQUO,5;oOOQQ,5@P,5@POOQQ-E=c-E=cO$0lQUO1G1hOOQQ1G1h1G1hOOQR7+'Q7+'QOOQR1G1s1G1sOBXQUO,5;rO),_QUO,5<YO),fQUO1G1sO)-oQUO1G1sO!0wQVO7+']O)-tQVO7+']O)3dQUO7+'dO)3iQVO7+'hO)5}QUO7+'wO)6XQUO7+'hO)7_QVO7+'hOKnQUO7+'wO$>vQUO,5<rO!4{QUO7+'xO)7fQUO7+'xOOQR7+(b7+(bO)7kQUO7+'zO)7pQUO,5<vO'DeQUO,5<vO)8hQUO,5<vO'DeQUO,5<vOOQQ,5<w,5<wO)8yQVO,5<xO'EsQUO'#JgO)9TQUO,5AsO)9]QUO,5<yOOQR7+'z7+'zO)9hQVO7+'VO)6QQUO'#LTOOQR-E=d-E=dO);yQVO,5<bOOQQ,5@S,5@SO!6qQUO,5@SOOQQ-E=f-E=fO)>bQUO7+(`O)?hQUO7+(dO)?mQVO7+(dOOQQ7+(l7+(lOOQQ7+)Z7+)ZO)?uQUO'#KpO)@PQUO'#KpOOQR,5=b,5=bO)@^QUO,5=bO!;eQUO,5=bO!;eQUO,5=bO!;eQUO,5=bOOQR7+(g7+(gOOQR7+(u7+(uOOQR7+(y7+(yOOQR,5=w,5=wO)@cQUO,5=zO)AiQUO,5=yOOQR,5A{,5A{OOQR-E=j-E=jOOQQ1G3b1G3bO)BoQUO,5=xO)BtQVO'#EfOOQQ1G6g1G6gO%)fQUO1G6gO%)kQUO1G6gOOQQ1G0P1G0POOQQ-E=R-E=RO)E]QUO,5A]O(&SQUO'#JUO)EhQUO,5A]O)EhQUO,5A]O)EpQUO,5:iO8}QUO,5:iOOQQ,5>],5>]O)EzQUO,5AwO)FRQUO'#EVO)G]QUO'#EVO)GvQUO,5:iO)HQQUO'#HlO)HQQUO'#HmOOQQ'#Ku'#KuO)HoQUO'#KuO!(}QVO'#HnOOQQ,5:i,5:iO)IaQUO,5:iO!MmQVO,5:iOOQQ-E=T-E=TOOQQ1G0S1G0SOOQQ,5>`,5>`O)IfQUO1G6gO!(}QVO,5>gO)MTQUO'#JsO)M`QUO,5BOOOQQ1G4Q1G4QO)MhQUO,5A}OOQQ,5A},5A}OOQQ7+)i7+)iO*#VQUO7+)iOOQQ7+)o7+)oO*(UQVO1G7nO**WQUO7+*SO**]QUO,5?TO*+cQUO7+*[POOO7+$S7+$SP*-UQUO'#LlP*-^QUO,5BVP*-c{,UO7+$SPOOO1G7o1G7oO*-hQUO<<GwOOQQ1G.y1G.yOOQQ'#IT'#ITO*/ZQUO,5@aOOQQ,5@a,5@aOOQQ-E=s-E=sOOQQ7+(V7+(VOOQQ<<Ms<<MsO*0dQUO<<MsO*2gQUO<<MvO*4YQUO<<L_O*4nQUO,5?}OOQQ,5?},5?}OOQQ-E=a-E=aOOQQ1G1b1G1bO*5wQUO,5;vO*6}QUO1G1aOOQQ1G1a1G1aOOQR,5AP,5APO*8WQ!eO,5APO*8_QMkO,5APO*8fQ!eO,5APOOQR-E=P-E=POOQQ1G/f1G/fO*8mQ!eO'#DwOOQQ1G5Y1G5YOOQR<<J]<<J]O*8tQUO<<IjO*9iQUO7+$pOOQQ<<Iu<<IuO(8aQVO,5;ROOQR<=!i<=!iOOQQ1G3T1G3TOOQQ,5@V,5@VOOQQ-E=i-E=iOOQR<=!l<=!lO*:fQUO1G0cO*:mQUO'#EzO*:}QUO1G0cO*;UQUO'#JOO*<lQUO1G0qO!(}QVO1G0qOOQQ,5;[,5;[OOQQ,5;],5;]OOQQ,5?v,5?vOOQQ-E=Y-E=YO!<_QUO1G0xO*={QUO1G0xOOQQ1G0y1G0yO*>^QUO'#ElOOQQ1G0z1G0zOOQQ7+&j7+&jO*>rQUO7+&jO*?xQVO7+&jOOQQ7+&h7+&hOOQQ,5@[,5@[OOQQ-E=n-E=nO*@tQUO1G1TO*AOQUO1G1TO*AiQUO1G0fOOQQ1G0f1G0fO*BoQUO'#LRO*BwQUO1G1ROOQQ<<It<<ItOOQQ'#Hb'#HbO',PQUO,5={OOQQ'#Hd'#HdO',PQUO,5=}OOQQ-E=k-E=kPOQQ<<Ik<<IkPOQQ-E=l-E=lOOQQ<<Lq<<LqO*B|QUO'#LgO*DYQUO'#LfOOQQ,5@`,5@`OOQQ-E=r-E=rOOQR<<Km<<KmO$?TQUO<<KmO*DhQUO<<KmOOQR1G1Z1G1ZOOQQ7+'S7+'SO!MmQVO1G1tO*DmQUO1G1tOOQR7+'_7+'_OOQR<<Jw<<JwO!0wQVO<<JwOOQR<<KO<<KOO*DxQUO<<KSO*FOQVO<<KSOKnQUO<<KcO!MmQVO<<KcO*FVQUO<<KSO!0wQVO<<KSO*G`QUO<<KSO*GeQUO<<KcO*GpQUO<<KdOOQR<<Kd<<KdOOQR<<Kf<<KfO*GuQUO1G2bO)7pQUO1G2bO'DeQUO1G2bO*HWQUO1G2dO*I^QVO1G2dOOQQ1G2d1G2dO*IhQVO1G2dO*IoQUO,5@ROOQQ-E=e-E=eOOQQ1G2e1G2eO*I}QUO1G1|O*KWQVO1G1|O*K_QUO1G1|OOQQ1G5n1G5nOOQR<<Kz<<KzOOQR<<LO<<LOO*KdQVO<<LOO*KoQUO<<LOOOQR1G2|1G2|O*KtQUO1G2|O*K{QUO1G3eOOQR1G3d1G3dOOQQ7+,R7+,RO%)fQUO7+,RO*LWQUO1G6wO*LWQUO1G6wO(&SQUO,5?pO*L`QUO,5?pOOQQ-E=S-E=SO*LkQUO1G0TOOQQ1G0T1G0TO*LuQUO1G0TO!MmQVO1G0TO*LzQUO1G0TOOQQ1G3w1G3wO*MUQUO,5:qO)FRQUO,5:qO*MrQUO,5:qO)FRQUO,5:qO$$TQUO,5:uO*NaQVO,5>VO)HQQUO'#JqO*NkQUO1G0TO*N|QVO1G0TOOQQ1G3u1G3uO+ TQUO,5>WO+ `QUO,5>XO+ }QUO,5>YO+#TQUO1G0TO%)kQUO7+,RO+$ZQUO1G4ROOQQ,5@_,5@_OOQQ-E=q-E=qOOQQ<<MT<<MTOOQQ<<Mn<<MnO+%dQUO1G4oP+'gQUO'#JwP+'oQUO,5BWPO{O1G7q1G7qPOOO<<Gn<<GnOOQQANC_ANC_OOQR1G6k1G6kO+'wQ!eO,5:cOOQQ,5:c,5:cO+(OQUO1G0mO+)[QUO7+&]O+*kQUO7+&dO+*|QUO,5;WOOQQ<<JU<<JUO++[QUO7+&oOOQQ7+&Q7+&QO!4{QUO'#J_O+,VQUO,5AmOOQQ7+&m7+&mOOQQ1G3g1G3gO+,_QUO1G3iOOQQ,5>n,5>nO+0SQUOANAXOOQRANAXANAXO+0XQUO7+'`OOQRAN@cAN@cO+1eQVOAN@nO+1lQUOAN@nO!0wQVOAN@nO+2uQUOAN@nO+2zQUOAN@}O+3VQUOAN@}O+4]QUOAN@}OOQRAN@nAN@nO!MmQVOAN@}OOQRANAOANAOO+4bQUO7+'|O)7pQUO7+'|OOQQ7+(O7+(OO+4sQUO7+(OO+5yQVO7+(OO+6QQVO7+'hO+6XQUOANAjOOQR7+(h7+(hOOQR7+)P7+)PO+6^QUO7+)PO+6cQUO7+)POOQQ<= m<= mO+6kQUO7+,cO+6sQUO1G5[OOQQ1G5[1G5[O+7OQUO7+%oOOQQ7+%o7+%oO+7aQUO7+%oO*N|QVO7+%oOOQQ7+)a7+)aO+7fQUO7+%oO+8lQUO7+%oO!MmQVO7+%oO+8vQUO1G0]O*MUQUO1G0]O)FRQUO1G0]OOQQ1G0a1G0aO+9eQUO1G3qO+:kQVO1G3qOOQQ1G3q1G3qO+:uQVO1G3qO+:|QUO,5@]OOQQ-E=o-E=oOOQQ1G3r1G3rO%)fQUO<= mOOQQ7+*Z7+*ZPOQQ,5@c,5@cPOQQ-E=u-E=uOOQQ1G/}1G/}OOQQ,5?y,5?yOOQQ-E=]-E=]OOQRG26sG26sO+;eQUOG26YO!0wQVOG26YO+<nQUOG26YOOQRG26YG26YO!MmQVOG26iO!0wQVOG26iO+<sQUOG26iO+=yQUOG26iO+>OQUO<<KhOOQQ<<Kj<<KjOOQRG27UG27UOOQR<<Lk<<LkO+>aQUO<<LkOOQQ7+*v7+*vOOQQ<<IZ<<IZO+>fQUO<<IZO!MmQVO<<IZO+>kQUO<<IZO+?qQUO<<IZO*N|QVO<<IZOOQQ<<L{<<L{O+@SQUO7+%wO*MUQUO7+%wOOQQ7+)]7+)]O+@qQUO7+)]O+AwQVO7+)]OOQQANEXANEXO!0wQVOLD+tOOQRLD+tLD+tO+BOQUOLD,TO+CUQUOLD,TOOQRLD,TLD,TO!0wQVOLD,TOOQRANBVANBVOOQQAN>uAN>uO+CZQUOAN>uO+DaQUOAN>uO!MmQVOAN>uO+DfQUO<<IcOOQQ<<Lw<<LwOOQR!$( `!$( `O!0wQVO!$( oOOQR!$( o!$( oOOQQG24aG24aO+ETQUOG24aO+FZQUOG24aOOQR!)9EZ!)9EZOOQQLD){LD){O+F`QUO'#CgO(gQUO'#CgO+J]QUO'#CzO+L|QUO'#CzO!FZQUO'#CzO+MuQUO'#CzO+NYQUO'#CzO,#{QUO'#CzO,$]QUO'#CzO,$jQUO'#CzO,$uQbO,59dO,%QQbO,59dO,%]QbO,59dO,%hQbO'#CxO,%yQbO'#CxO,&[QbO'#CxO,&mQUO'#CgO,)QQUO'#CgO,)_QUO'#CgO,,SQUO'#CgO,/VQUO'#CgO,/gQUO'#CgO,3`QUO'#CgO,3gQUO'#CgO,4gQUO'#CgO,6pQUO,5:xO#?yQUO,5:xO#?yQUO,5:xO#=iQUO'#LbO,7^QbO'#CxO,7iQbO'#CxO,7tQbO'#CxO,8PQbO'#CxO#7SQUO'#E^O,8[QUO'#E^O,9iQUO'#HgO,:ZQbO'#CxO,:fQbO'#CxO,:qQUO'#CwO,:vQUO'#CwO,:{QUO'#CpO,;ZQbO,59dO,;fQbO,59dO,;qQbO,59dO,;|QbO,59dO,<XQbO,59dO,<dQbO,59dO,<oQbO,59dO,6pQUO1G0dO,<zQUO1G0dO#?yQUO1G0dO,8[QUO1G0dO,?XQUO'#K`O,?iQUO'#CzO,?wQbO,59dO,6pQUO7+&OO,<zQUO7+&OO,@SQUO'#EwO,@uQUO'#EzO,AfQUO'#E^O,AkQUO'#GcO,ApQUO'#CwO,AuQUO'#CxO,AzQUO'#CxO,BPQUO'#CwO,BUQUO'#GcO,BZQUO'#K`O,BwQUO'#K`O,CRQUO'#CwO,C^QUO'#CwO,CiQUO'#CwO,<zQUO,5:xO,8[QUO,5:xO,8[QUO,5:xO,CtQUO'#K`O,DXQbO'#CxO,DdQUO'#CsO,DiQUO'#E^", | |
| 4033 | stateData: ",E_~O(oOSSOSRPQVPQ'ePQ'gPQ'hPQ'iPQ'jPQ'kPQ'lPQ'mPQ(pPQ~O*aOS~OPmO]eOb!]Oe!POmTOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!O!_O!TxO!VfO!X!XO!Y!WO!i!YO!opO!r!`O!s!aO!t!aO!u!bO!v!aO!x!cO!{!dO#V#QO#a#VO#b#TO#i#OO#p!xO#t!fO#v!eO$R!gO$T!hO$Y!vO$Z!wO$`!iO$e!jO$g!kO$h!lO$k!mO$m!nO$o!oO$q!pO$s!qO$u!rO$w!sO${!tO$}!uO%U!yO%_#ZO%`#[O%a#YO%c!zO%e#UO%g!{O%l#SO%o!|O%v!}O%|#PO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(wRO)VYO)YaO)[|O)]{O)_iO)`!ZO)bXO)ncO)odO~OR#cOV#^O'e#_O'g#`O'h#aO'i#aO'j#bO'k#bO'l#`O'm#`O(p#]O~OX#eO(t#gO(v#eO~O]ZX]jXejXmhXqZXqjXsjXtjXujXvjXwjXxjXyjXzjX!OjX!TjX!VZX!VjX!XZX!YZX![ZX!^ZX!_ZX!aZX!bZX!eZX!fZX!gZX!hZX!rjX!sjX!tjX!ujX!vjX!xjX!{jX%vjX&rjX&sjX(wjX(zZX({$]X(|ZX(}ZX)YZX)YjX)ZZX)[ZX)[jX)]ZX)]jX)^ZX)_ZX)`ZX)pZX~O)_jX!UZX~P(gO]$PO!V#nO!X#}O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO(|#mO(}#mO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_#lO)`$OO~Oe$TO%Y$UO'[$VO'_$WO)O$QO~Om$XO~O!T$YO])SXe)SXs)SXt)SXu)SXv)SXw)SXx)SXy)SXz)SX!O)SX!V)SX!r)SX!s)SX!t)SX!u)SX!v)SX!x)SX!{)SX%v)SX&r)SX&s)SX(w)SX)Y)SX)[)SX)])SX)_)SX~Om$XO~P.^Om$XO!g$[O)p$[O~OX$]O)c$]O~O!R$^O)U)WP)`)WP~OPmO]$gOb!]Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!O!_O!TxO!V$hO!X!XO!Y!WO!i!YO!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO#V#QO#a#VO#b#TO#v!eO$Y!vO$Z!wO$`!iO$e!jO$g!kO$h!lO$k!mO$m!nO$o!oO$q!pO$s!qO$u!rO$w!sO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO)VYO)Y$mO)]$mO)_iO)`!ZO)bXO)ncO)odO~Om$aO#t$nO(wRO~P0}O](^Xb'zXe(^Xm'zXm(^Xs'zXs(^Xt'zXt(^Xu'zXu(^Xv'zXv(^Xw'zXw(^Xx'zXx(^Xy'zXy(^Xz'zXz(^X|'zX!O'zX!V(^X!o(^X!r'zX!r(^X!s'zX!s(^X!t'zX!t(^X!u'zX!u(^X!v'zX!v(^X!x'zX!x(^X!{(^X#a'zX#b'zX%e'zX%l'zX%o(^X%v(^X&m'zX&r'zX&s'zX(w'zX(w(^X)Y(^X)[(^X)](^X~Ob!TOm$qOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!O!_O!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO#a#VO#b#TO%e#UO%l#SO&m!RO&r#WO&s!TO(w$pO~Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!O!_O!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO&r#WO&s$yO])gXe)gXm)gX!V)gX!{)gX%v)gX(w)gX)Y)gX)[)gX)])gX~O)_$xO~P:qOPmO]eOe!POs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!VfO!X!XO!Y!WO!i!YO!{!dO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO)YaO)[|O)]{O)`!ZO)bXO)ncO)odO~Ob%SOm;RO!|%TO(w$zO~P<oO)Y%UO~Ob!]Om$aO|#RO#a#VO#b#TO%e#UO%l#SO&m!RO&r#WO&s!TO(w;UO~P<oOPmO]$gOb%SOm;RO!V$hO!W%aO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)Y$mO)]%_O)`!ZO)bXO)ncO)odO)p%^O~O]%jOe!POm%dO!V%mO!{!dO%v$oO(w;VO)Y%fO)[%kO)]%kO~O({%oO~O)_#lO~O(w%pO](yX!V(yX!X(yX!Y(yX^(yX)_(yX)`(yX!g(yX)p(yX[(yX!W(yX({(yX!U(yXQ(yX!d(yX~OP%qO(uQO~PCTO]%jOe!POs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!V%mO!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO!{!dO%o!|O%v!}O)Y;gO)[|O)]|O~Om%tO!o%yO(w$zO~PEbO!TxO#v!eO({%{O)p&OO])kX!V)kX~O]%jOe!POm%tO!V%mO!{!dO%v!}O(w$zO)Y;gO)[|O)]|O~O!TxO#v!eO)_&RO)p&SO~O!U&VO~P!QO]&[O!TxO!V&YO)Y&XO)[&]O)]&]O~Oq&WO~PHuO]&eO!V&dO~OPmO]eOe!PO!VfO!X!XO!Y!WO!i!YO!{!dO#V#QO%_#ZO%`#[O%a#YO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO)YaO)[|O)]{O)`!ZO)bXO)ncO)odO~Ob%SOm;RO%v$oO(w$zO~PIjO]%jOe!POm;cO!V%mO!{!dO%v$oO(w$zO)Y;gO)[|O)]|O~Oq&hO](yX])kX!V(yX!V)kX!X(yX!Y(yX^(yX)_(yX)`(yX[(yX[)kX!U(yX~O!g$[O)p$[O~PL`O!g(yX)p(yX~PL`O](yX!V(yX!X(yX!Y(yX^(yX)_(yX)`(yX!g(yX)p(yX[(yX!U(yX~O])kX!V)kX[)kX~PNnOb&jO&m!RO]&lXe&lXm&lXs&lXt&lXu&lXv&lXw&lXx&lXy&lXz&lX!O&lX!V&lX!r&lX!s&lX!t&lX!u&lX!v&lX!x&lX!{&lX%v&lX&r&lX&s&lX(w&lX)Y&lX)[&lX)]&lX)_&lX[&lX!T&lX!X&lX!Y&lXY(yX)Z(yX)[(yX)](yX)^(yX)_(yX)`(yX[(yX!W(yX({(yX!U(yXQ(yX!d(yX~OPmO]$gOb%SOm;RO!V$hO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)Y$mO)]$mO)`!ZO)bXO)ncO)odO~O])SXe)SXm)SXs)SXt)SXu)SXv)SXw)SXx)SXy)SXz)SX!O)SX!V)SX!r)SX!s)SX!t)SX!u)SX!v)SX!x)SX!{)SX%v)SX&r)SX&s)SX(w)SX)Y)SX)[)SX)])SX)_)SX[)SXQ)SX!d)SX!h)SX)`)SX)p)SX~O]$PO~P!*tO]&nO~O])hXb)hXe)hXm)hXs)hXt)hXu)hXv)hXw)hXx)hXy)hXz)hX|)hX!O)hX!V)hX!o)hX!r)hX!s)hX!t)hX!u)hX!v)hX!x)hX!{)hX#a)hX#b)hX%e)hX%l)hX%o)hX%v)hX&m)hX&r)hX&s)hX(w)hX)Y)hX)[)hX)])hX~O(uQO~P!-^O%U&pO~P!-^O]&qO~O]$PO~O!TxO~O$W&yO(w%pO({&xO~O]&zOx&|O~O]&zO~OPmO]$gOb%SOm;RO!TxO!V$hO!X!XO!Y!WO!i!YO#V#QO#p!xO#v!eO$Y!vO$Z!wO$`!iO$e!jO$g!kO$h!lO$k!mO$m!nO$o!oO$q!pO$s!qO$u!rO$w!sO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w:tO)VYO)Y$mO)]$mO)_iO)`!ZO)bXO)ncO)odO~O]'RO~O!T$YO)_'TO~P!(}O)_'VO~O)_'WO~O(w'XO~O)_'[O~P!(}Om;eO%U'`O%e'`O(w;WO~Ob!TOm$qOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO#a#VO#b#TO%e#UO%l#SO&m!RO&r#WO&s!TO(w$pO~O({'dO~O)_'fO~P!(}O!TxO(w%pO)p'hO~O(w%pO~O]'kO~O]'lOe%nXm%nX!V%nX!{%nX%v%nX(w%nX)Y%nX)[%nX)]%nX~O]'pO!V'qO!X'nO!g'nO%Z'nO%['nO%]'nO%^'nO%_'rO%`'rO%a'nO(}'oO)p'nO*O'sO~P8}O]%jOb!TOe!POs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!O!_O!V%mO!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO!{!dO#a#VO#b#TO%e#UO%l#SO&m!RO&r#WO&s!TO)Y;gO)[|O)]|O~Om;fOq&WO%v$oO(w;XO~P!8mO(w%pO({'xO)_'yO~O]&eO!T'{O~Om$qO!O!_O!T(SO!l(XO(w$pO({(RO)VYO~Om$qO|(`O!T(]O#b(`O(w$pO~Ob!TOm$qO|#RO#a#VO#b#TO%e#UO%l#SO&m!RO&r#WO&s!TO(w$pO~O](bO~OPmOb%SOm;RO!V$hO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)Y$mO)]$mO)bXO)ncO)odO~O](dO)`(eO~P!=XO]$PO~P!<_OPmO]$gOb%SOm;RO!V(kO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)Y$mO)]$mO)`!ZO)bXO)ncO)odO~O(q(lO(r(lO(s(nO~OY(oO(uQO(w%pO~O'f(rO~OS(vO(p#]O*^(uO~O]$PO(o(yO~Q'nXX#eO(t({O(v#eO~Oe)VOm)QO&r#WO(w)PO~O!Y'Sa!['Sa!^'Sa!_'Sa!a'Sa!b'Sa!e'Sa!f'Sa!h'Sa(z'Sa)Y'Sa)Z'Sa)['Sa)]'Sa)^'Sa)_'Sa)`'Sa!g'Sa)p'Sa['Sa!W'Sa({'Sa!U'SaQ'Sa!d'Sa~OPmOb%SOm;RO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)bXO)ncO)odO]'Sa!V'Sa!X'Sa(|'Sa(}'Sa~P!BmO!T$YO[(xP~P!(}O]oX]%WXeoXmnXqoXq%WXsoXtoXuoXvoXwoXxoXyoXzoX!OoX!ToX!VoX!V%WX!X%WX!Y%WX![%WX!^%WX!_%WX!a%WX!b%WX!e%WX!f%WX!gnX!h%WX!roX!soX!toX!uoX!voX!xoX!{oX%voX&roX&soX(woX(z%WX(|%WX(}%WX)YoX)Y%WX)Z%WX)[oX)[%WX)]oX)]%WX)^%WX)_%WX)`%WX)pnX[%WX~O)_oX[oX!U%WX~P!FZO])iO!V)jO!X)gO!g)gO%Z)gO%[)gO%])gO%^)gO%_)kO%`)kO%a)gO(})hO)p)gO*O)lO~P8}OPmO]$gOb%SOm;RO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)Y$mO)]$mO)`!ZO)bXO)ncO)odO~O!V)qO~P!KVOe)tO%Y)uO)O$QO~O!T$YO!V)wO(|)xO!U)xP~P!KVO!T$YO~P!(}O)a*PO~Om*QO]!QX!h!QX)U!QX)`!QX~O]*SO!h*TO)U)WX)`)WX~O)U*WO)`*XO~Oe$TO%Y*YO'[$VO'_$WO)O$QO~Om*ZO~Om*ZO[)SX~P.^Om*ZO!g$[O)p$[O~O)_*[O~P:qOPmO]$gOb!]Om$aOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!V$hO!X!XO!Y!WO!i!YO#V#QO#a#VO#b#TO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w;UO)Y$mO)]$mO)`!ZO)bXO)ncO)odO~Oq&hO~P!&}Oq&hO!W(yX({(yXQ(yX!d(yX~PNnO]'pO!V'qO!X'nO!g'nO%Z'nO%['nO%]'nO%^'nO%_'rO%`'rO%a'nO(}'oO)p'nO*O'sO~O]jXejXmhXqjXsjXtjXujXvjXwjXxjXyjXzjX!OjX!VjX!rjX!sjX!tjX!ujX!vjX!xjX!{jX%vjX&rjX&sjX(wjX)YjX)[jX)]jX!TjX!hjX)`jX)pjX[jX~O!ljX({jX)_jX!XjX!YjX![jX!^jX!_jX!ajX!bjX!ejX!fjX(zjX(|jX(}jX)ZjX)^jX!gjX!WjXQjX!djX!UjX#vjX#TjX#VjX#pjXbjX|jX!ojX#ajX#bjX#ijX#tjX${jX%cjX%ejX%kjX%ljX%ojX&mjX)VjX~P#&XO)O*`O~Om*aO~O])SXe)SXs)SXt)SXu)SXv)SXw)SXx)SXy)SXz)SX!O)SX!V)SX!r)SX!s)SX!t)SX!u)SX!v)SX!x)SX!{)SX%v)SX&r)SX&s)SX(w)SX)Y)SX)[)SX)])SX)_)SX!T)SX!X)SX!Y)SX![)SX!^)SX!_)SX!a)SX!b)SX!e)SX!f)SX!h)SX(z)SX(|)SX(})SX)Z)SX)^)SX)`)SX!g)SX)p)SX[)SX!W)SXQ)SX!d)SX({)SX!U)SX#v)SX~Om*aO~P#+aOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!O!_O!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO])gae)gam)ga!V)ga!{)ga%v)ga(w)ga)Y)ga)[)ga)])gaQ)ga!d)ga!h)ga)`)ga)p)ga[)ga!T)ga({)ga)_)ga~O&r#WO&s$yO~P#/POq&hOm)SX~P#+aO&r)ga~P#/PO]ZXmhXqZXqjX!TjX!VZX!XZX!YZX![ZX!^ZX!_ZX!aZX!bZX!eZX!fZX!gZX!hZX(zZX(|ZX(}ZX)YZX)ZZX)[ZX)]ZX)^ZX)_ZX)`ZX)pZX[ZX~O!WZX({ZX!UZXQZX!dZX~P#1xO]$PO!V#nO!X#}O(|#mO(}#mO~O!Y&xa![&xa!^&xa!_&xa!a&xa!b&xa!e&xa!f&xa!g&xa!h&xa(z&xa)Y&xa)Z&xa)[&xa)]&xa)^&xa)_&xa)`&xa)p&xa[&xa!W&xa({&xa!U&xaQ&xa!d&xa~P#4YOm;oO!T$YO~Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O~PKnOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!|%TO~PKnO]&eO!V&dO[#Qa!T#Qa!h#Qa#v#Qa)_#Qa)p#QaQ#Qa!d#Qa({#Qa~Oq&hO!T$YO~O[*hO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[*hO~O[*jO]&eO!V&dO~O]&[Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!V&YO&r#WO&s$yO)Y&XO)[&]O)]&]O~O[rXQrX!drX!hrX)`rX)_rX~P#:ZO[*mO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h*nO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!W)qX~P#4YO!W*pO!h*qO~O!W*pO!h*qO~P!(}O!W*pO~Oq&hO!g$[O!h*rO)p$[O](yX!V(yX!W(yX!W*UX!X(yX!Y(yX^(yX)`(yX~O!h(yX~P#=iO!W*tO~Oe$TO%Y*YO)O:yO~Om;rO~Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!|%TO~PBXO]*{O!T*vO!V&dO!h*yO#v!eO)p*wO)_)wX~O!h*yO)_)wX~O)_*|O~Oq&hO])kX!T)kX!V)kX!h)kX#v)kX)_)kX)p)kX[)kXQ)kX!d)kX({)kX~Oq&hO~OP%qO(uQO]%ha!V%ha!X%ha!Y%ha![%ha!^%ha!_%ha!a%ha!b%ha!e%ha!f%ha!h%ha(w%ha(z%ha(|%ha(}%ha)Y%ha)Z%ha)[%ha)]%ha)^%ha)_%ha)`%ha!g%ha)p%ha[%ha!W%ha({%ha!U%haQ%ha!d%ha~Oe$TO%Y$UO)O:vO~Om;OO~O!TxO#v!eO)p&OO~Om<cO&r#WO(w;nO~O$Z+YO%`+ZO~O!TxO#v!eO)_+[O)p+]O~OPmO]$gOb%SOm;RO!V$hO!X!XO!Y!WO!i!YO#V#QO$Z+YO%_#ZO%`+_O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)Y$mO)]$mO)`!ZO)bXO)ncO)odO~O!U+`O~P!QOb!TOm$qOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!O!_O!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO#a+fO#b+gO#i+hO%e#UO%l#SO&m!RO&r#WO&s!TO(w$pO)VYO~OQ)rP!d)rP~P#GuO]&[Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!V&YO)Y&XO)[&]O)]&]O~O[#kX!T#kX#v#kX)_#kX)p#kXQ#kX!d#kX!h#kX)`#kX!x#kX({#kX~P#IyOPmO]$gOb%SOm;ROs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!V$hO!W+nO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)Y+oO)]$mO)`!ZO)bXO)ncO)odO~O]&eO!V+pO~O]&[O!V&YO)VYO)Y&XO)[&]O)]&]O)`+sO[)jP~P8}O]&[O!V&YO)Y&XO)[&]O)]&]O~O[#nX!T#nX#v#nX)_#nX)p#nXQ#nX!d#nX!h#nX)`#nX!x#nX({#nX~P#NsO!TxO])tX!V)tX~Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O#T+{O#p+|O(}+yO)[+wO)]+wO~O]#jX!T#jX!V#jX[#jX#v#jX)_#jX)p#jXQ#jX!d#jX!h#jX)`#jX!x#jX({#jX~P$!WO#V,OO~Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!l,PO#T+{O#V,OO#p+|O(}+yO)[,PO)],PO])lP!T)lP!V)lP#v)lP({)lP)p)lP[)lP!h)lP)_)lP~O!x)lPQ)lP!d)lP~P$$TOPmO]$gOb%SOm;ROs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!V$hO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)]$mO)`!ZO)bXO)ncO)odO~O!W,VO)Y,WO~P$&OO)VYO)`+sO[)jP~P8}O]&eO!V&dO[&Za!T&Za!h&Za#v&Za)_&Za)p&ZaQ&Za!d&Za({&Za~OPmO]$gOb!]Om;TOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!V$hO!X!XO!Y!WO!i!YO#V#QO#a#VO#b#TO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w;YO)Y$mO)]$mO)`!ZO)bXO)ncO)odO~OQ)PP!d)PP~P$)hO]$PO!V#nO(|#mO(}#mO!X'Pa!Y'Pa!['Pa!^'Pa!_'Pa!a'Pa!b'Pa!e'Pa!f'Pa!h'Pa(z'Pa)Y'Pa)Z'Pa)['Pa)]'Pa)^'Pa)_'Pa)`'Pa!g'Pa)p'Pa['Pa!W'Pa({'Pa!U'PaQ'Pa!d'Pa~O]$PO!V#nO!X#}O(|#mO(}#mO~P!BmO!TxO#t!fO)VYO~P8}O!TxO(w%pO)p,aO~O#x,fO~OQ)gX!d)gX!h)gX)`)gX)p)gX[)gX!T)gX({)gX)_)gX~P:qO({,jO(|,hO)V$UX)_$UX~O(w,kO~O)VYO)_,nO~OPmO]$gOb!]Om;SOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!O!_O!V$hO!X!XO!Y!WO!i!YO!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO#V#QO#a#VO#b#TO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO)VYO)Y$mO)]$mO)_iO)`!ZO)bXO)ncO)odO~O(w;ZO~P$0yOPmO]$gOb%SOm;RO!TxO!V$hO!X!XO!Y!WO!i!YO#V#QO#v!eO$Y!vO$Z!wO$`!iO$e!jO$g!kO$h!lO$k!mO$m!nO$o!oO$q!pO$s!qO$u!rO$w!sO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w:tO)VYO)Y$mO)]$mO)_iO)`!ZO)bXO)ncO)odO~O$h,xO~OPmO]$gOb!]Om;SOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!O!_O!V$hO!X!XO!Y!WO!i!YO!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO#V#QO#a#VO#b#TO$}!uO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO)VYO)Y$mO)]$mO)`!ZO)bXO)ncO)odO~O${-OO(w;UO)_,|O~P$7dO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_-QO)`$OO~P#4YO)_-QO~O)_-RO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_-SO)`$OO~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_-TO)`$OO~P#4YOq&hO)VYO)p-VO~O)_-WO~Om;eO(w;WO~O]-_O!{!dO&r#WO&s$yO(w-ZO)Y-[O~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO({-bO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!TxO$`!iO$e!jO$g!kO$h!lO$k-gO$m!nO$o!oO$q!pO$s!qO$u!rO$w!sO$}!uO(w:uOe$Xa!o$Xa!{$Xa#i$Xa#p$Xa#t$Xa#v$Xa$R$Xa$T$Xa$Y$Xa$Z$Xa${$Xa%U$Xa%c$Xa%g$Xa%o$Xa%|$Xa(l$Xa)[$Xa!U$Xa$c$Xa~P$0yO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_-hO)`$OO~P#4YOm-jO!TxO)p,aO~O)p-lO~O]&]a!X&]a!Y&]a![&]a!^&]a!_&]a!a&]a!b&]a!e&]a!f&]a!h&]a(z&]a(|&]a(}&]a)Z&]a)[&]a)]&]a)^&]a)_&]a)`&]a!g&]a)p&]a[&]a!W&]a!T&]a#v&]a({&]a!U&]aQ&]a!d&]a~O)Y-pO!V&]a~P$DpO[-pO~O!W-pO~O!V-qO)Y&]a~P$DpO])SXe)SXs)SXt)SXu)SXv)SXw)SXx)SXy)SXz)SX!O)SX!V)SX!r)SX!s)SX!t)SX!u)SX!v)SX!x)SX!{)SX%v)SX&r)SX&s)SX(w)SX)Y)SX)[)SX)])SX~Om;tO~P$G`O]&eO!V&dO)_-rO~Om;jO!o-uO#V,OO#i-zO#t!fO${-OO%c!zO%k-yO%o!|O%v!}O(w;[O)VYO~P!8mO!n.OO(w,kO~O)VYO)_.QO~OPmO]$gOb%SOm;RO!T.VO!V$hO!X!XO!Y!WO!i!YO#V.^O#a.]O%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO(}.UO)Y$mO)]$mO)_.SO)`!ZO)bXO)ncO)odO~O!U.[O~P$JpO])dXe)dXs)dXt)dXu)dXv)dXw)dXx)dXy)dXz)dX!O)dX!T)dX!V)dX!l)dX!r)dX!s)dX!t)dX!u)dX!v)dX!x)dX!{)dX%v)dX&r)dX&s)dX(w)dX({)dX)Y)dX)[)dX)])dX)_)dX[)dX!h)dX)`)dX!X)dX!Y)dX![)dX!^)dX!_)dX!a)dX!b)dX!e)dX!f)dX(z)dX(|)dX(})dX)Z)dX)^)dX!g)dX)p)dX!W)dXQ)dX!d)dX#T)dX#V)dX#p)dX#v)dXb)dX|)dX!o)dX#a)dX#b)dX#i)dX#t)dX${)dX%c)dX%e)dX%k)dX%l)dX%o)dX&m)dX)V)dX!U)dX~Om*aO~P$LzOm$qO!T(SO!l.cO(w$pO({(RO)VYO~Oq&hOm)dX~P$LzOm$qO!n.hO!o.hO(w$pO)VYO~Om;kO!U.sO!n.uO!o.tO#i-zO${!tO$}!uO%g!{O%k-yO%o!|O%v!}O(w;^O)VYO~P!8mO!T(SO!l.cO({(RO])TXe)TXm)TXs)TXt)TXu)TXv)TXw)TXx)TXy)TXz)TX!O)TX!V)TX!r)TX!s)TX!t)TX!u)TX!v)TX!x)TX!{)TX%v)TX&r)TX&s)TX(w)TX)Y)TX)[)TX)])TX~O)_)TX[)TX!X)TX!Y)TX![)TX!^)TX!_)TX!a)TX!b)TX!e)TX!f)TX!h)TX(z)TX(|)TX(})TX)Z)TX)^)TX)`)TX!g)TX)p)TX!W)TXQ)TX!d)TX!U)TX#v)TX~P%%sO!T(SO~O!T(SO({(RO~O(w%pO!U*WP~O!T(]O({.zO]&kae&kam&kas&kat&kau&kav&kaw&kax&kay&kaz&ka!O&ka!V&ka!r&ka!s&ka!t&ka!u&ka!v&ka!x&ka!{&ka%v&ka&r&ka&s&ka(w&ka)Y&ka)[&ka)]&ka)_&ka[&ka!X&ka!Y&ka![&ka!^&ka!_&ka!a&ka!b&ka!e&ka!f&ka!h&ka(z&ka(|&ka(}&ka)Z&ka)^&ka)`&ka!g&ka)p&ka!W&kaQ&ka!d&ka!U&ka#v&ka~Om$qO!T(]O(w$pO~O&r#WO&s$yO]&pae&pam&pas&pat&pau&pav&paw&pax&pay&paz&pa!O&pa!V&pa!r&pa!s&pa!t&pa!u&pa!v&pa!x&pa!{&pa%v&pa(w&pa)Y&pa)[&pa)]&pa)_&pa[&pa!T&pa!X&pa!Y&pa![&pa!^&pa!_&pa!a&pa!b&pa!e&pa!f&pa!h&pa(z&pa(|&pa(}&pa)Z&pa)^&pa)`&pa!g&pa)p&pa!W&paQ&pa!d&pa({&pa!U&pa#v&pa~O&s/PO~P!(}O!Y#sO![#tO!f#|O)Y#oO!^'Ua!_'Ua!a'Ua!b'Ua!e'Ua!h'Ua(z'Ua)Z'Ua)['Ua)]'Ua)^'Ua)_'Ua)`'Ua!g'Ua)p'Ua['Ua!W'Ua({'Ua!U'UaQ'Ua!d'Ua~P#4YO!V'dX!X'dX!Y'dX!['dX!^'dX!_'dX!a'dX!b'dX!e'dX!f'dX!h'dX(z'dX(|'dX(}'dX)Y'dX)Z'dX)['dX)]'dX)^'dX)`'dX['dX~O]/RO)_'dX!g'dX)p'dX!W'dX({'dX!U'dXQ'dX!d'dX~P%3WO!Y#sO![#tO!f#|O)Y#oO!^'Wa!_'Wa!a'Wa!b'Wa!e'Wa!h'Wa(z'Wa)Z'Wa)['Wa)]'Wa)^'Wa)_'Wa)`'Wa!g'Wa)p'Wa['Wa!W'Wa({'Wa!U'WaQ'Wa!d'Wa~P#4YO]$PO!T$YO!V/SO&r#WO&s$yO~O!X'Za!Y'Za!['Za!^'Za!_'Za!a'Za!b'Za!e'Za!f'Za!h'Za(z'Za(|'Za(}'Za)Y'Za)Z'Za)['Za)]'Za)^'Za)_'Za)`'Za!g'Za)p'Za['Za!W'Za({'Za!U'ZaQ'Za!d'Za~P%6}O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!h'^a)_'^a!g'^a)p'^a['^a!W'^a({'^a!U'^aQ'^a!d'^a~P#4YOPmO]$gOb%SOm;RO!V$hO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)Y$mO)]%_O)`!ZO)bXO)ncO)odO)p%^O~O!W/VO~P%:}O(q(lO(r(lO(s/XO~OS(vO]$PO(p#]O*^(uO~O]/[O'f/]O*^/YO~OS/aO(p#]O*^/`O~O]$PO~Q'na!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO({/cO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO)_#Zi[#Zi~P#4YO]dXmhXqdXqjX!VdX!XdX!YdX![dX!^dX!_dX!adX!bdX!edX!fdX!gdX!hdX(zdX(|dX(}dX)YdX)ZdX)[dX)]dX)^dX)_dX)`dX)pdX[dX!WdX({dX!TdX#vdX!UdXQdX!ddX~Oe/eO%Y*YO)O/dO~Om/fO~Om/gO~Oq&hO]ci!Vci!Xci!Yci![ci!^ci!_ci!aci!bci!eci!fci!gci!hci(zci(|ci(}ci)Yci)Zci)[ci)]ci)^ci)_ci)`ci)pci[ci!Wci({ci!UciQci!dci~O!W/iO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO![#tO)Y#oO!Y&zi!^&zi!_&zi!a&zi!b&zi!e&zi!f&zi!h&zi(z&zi)Z&zi)[&zi)]&zi)^&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y&zi![&zi!^&zi!_&zi!a&zi!b&zi!e&zi!f&zi!h&zi(z&zi)Y&zi)Z&zi)[&zi)]&zi)^&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O)Y#oO)]#rO)^#jO!h&zi(z&zi)Z&zi)[&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O)Y#oO)[#pO)]#rO)^#jO!h&zi(z&zi)Z&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!_#xO!a#zO!b#{O!e#{O!f#|O)Y#oO)]#rO)^#jO!^&zi!h&zi(z&zi)Z&zi)[&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!a#zO!b#{O!e#{O!f#|O)Y#oO)]#rO)^#jO!^&zi!_&zi!h&zi(z&zi)Z&zi)[&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!a#zO!b#{O!e#{O!f#|O)Y#oO)^#jO!^&zi!_&zi!h&zi(z&zi)Z&zi)[&zi)]&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!b#{O!e#{O!f#|O)Y#oO)^#jO!^&zi!_&zi!a&zi!h&zi(z&zi)Z&zi)[&zi)]&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!f#|O)Y#oO!^&zi!_&zi!a&zi!b&zi!e&zi!h&zi(z&zi)Z&zi)[&zi)]&zi)^&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO)Y#oO!^&zi!_&zi!a&zi!b&zi!e&zi!f&zi!h&zi(z&zi)Z&zi)[&zi)]&zi)^&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O)Y#oO)Z#qO)[#pO)]#rO)^#jO!h&zi(z&zi)_&zi)`&zi!g&zi)p&zi[&zi!W&zi({&zi!U&ziQ&zi!d&zi~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h/jO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO[(xX~P#4YO!h/jO[(xX~O[/lO~O]%Xaq%Xa!X%Xa!Y%Xa![%Xa!^%Xa!_%Xa!a%Xa!b%Xa!e%Xa!f%Xa!h%Xa(z%Xa(|%Xa(}%Xa)Z%Xa)[%Xa)]%Xa)^%Xa)_%Xa)`%Xa!g%Xa)p%Xa[%Xa!W%Xa!T%Xa#v%Xa({%Xa!U%XaQ%Xa!d%Xa~O)Y/mO!V%Xa~P&,zO[/mO~O!W/mO~O!V/nO)Y%Xa~P&,zO!X'Zi!Y'Zi!['Zi!^'Zi!_'Zi!a'Zi!b'Zi!e'Zi!f'Zi!h'Zi(z'Zi(|'Zi(}'Zi)Y'Zi)Z'Zi)['Zi)]'Zi)^'Zi)_'Zi)`'Zi!g'Zi)p'Zi['Zi!W'Zi({'Zi!U'ZiQ'Zi!d'Zi~P%6}O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!h'^i)_'^i!g'^i)p'^i['^i!W'^i({'^i!U'^iQ'^i!d'^i~P#4YO!W/sO~P%:}O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h/uO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!U)xX~P#4YO(w/xO~O!V/zO(|)xO)p/|O~O!h/uO!U)xX~O!U/}O~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!h`i(z`i)_`i!g`i)p`i[`i!W`i({`i!U`iQ`i!d`i~P#4YO!R0OO~Om*QO]!Qa!h!Qa)U!Qa)`!Qa~OP0WO]0VOm0WO!R0WO!T0TO!V0UO!X0WO!Y0WO![0WO!^0WO!_0WO!a0WO!b0WO!e0WO!f0WO!g0WO!h0WO!i0WO(uQO({0WO(|0WO(}0WO)Y0QO)Z0RO)[0RO)]0SO)^#jO)_0WO)`0WO)bXO~O[0ZO~P&7dO!R$^O~O!h*TO)U)Wa)`)Wa~O)U0_O~O])iO!V)jO!X)gO!g)gO%Z)gO%[)gO%])gO%^)gO%_)kO%`)kO%a)gO(})hO)p)gO*O)lO~Oe)tO%Y*YO)O$QO~O)_0aO~O]oXeoXmnXqoXsoXtoXuoXvoXwoXxoXyoXzoX!OoX!VoX!roX!soX!toX!uoX!voX!xoX!{oX%voX&roX&soX(woX)YoX)[oX)]oX!ToX!hoX)`oX[oXQoX!doX~O!loX({oX)_oX!XoX!YoX![oX!^oX!_oX!aoX!boX!eoX!foX(zoX(|oX(}oX)ZoX)^oX!goX)poX!WoX!UoX#voX#ToX#VoX#poXboX|oX!ooX#aoX#boX#ioX#toX${oX%coX%eoX%koX%loX%ooX&moX)VoX~P&;`Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!O!_O!r!aO!s!aO!t!aO!u!aO!v!aO!x!cO~O])gie)gim)gi!V)gi!{)gi%v)gi(w)gi)Y)gi)[)gi)])giQ)gi!d)gi!h)gi)`)gi)p)gi[)gi!T)gi&r)gi({)gi)_)gi~P&@^O]&eO!V&dO[#Qi!T#Qi!h#Qi#v#Qi)_#Qi)p#QiQ#Qi!d#Qi({#Qi~O[raQra!dra!hra)`ra)_ra~P#:ZO[raQra!dra!hra)`ra)_ra~P#IyO]&eO!V+pO[raQra!dra!hra)`ra)_ra~O!h*nO!W)qa~O!h*rO!W*Ua~OPmOb!]Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O|#RO!O!_O!X!XO!Y!WO!i!YO!s!aO!t!aO!v!aO!x!cO#V#QO#a#VO#b#TO#v!eO$Y!vO$Z!wO$`!iO$e!jO$g!kO$h!lO$k!mO$m!nO$o!oO$q!pO$s!qO$u!rO$w!sO%_#ZO%`#[O%a#YO%e#UO%l#SO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO)VYO)_iO)`!ZO)bXO)ncO)odO~O]eOe!POmTO!T*vO!U&VO!V0oO!opO!r!`O!u!bO!{!dO#i#OO#p!xO#t!fO$R!gO$T!hO${!tO$}!uO%U!yO%c!zO%g!{O%o!|O%v!}O%|#PO(wRO(|)xO)YaO)[|O)]{O~P&E`O!h*yO)_)wa~OPmO]$gOb!]Om;TO|#RO!T$YO!V$hO!X!XO!Y!WO!i!YO#V#QO#a#VO#b#TO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w;]O)VYO)Y$mO)]$mO)`0uO)bXO)ncO)odO[(xP[)jP~P&@^O!h*rO!W*UX~O]$PO!T$YO~O!h0zO!T*QX#v*QX)p*QX~O)_0|O~O)_0}O~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_1PO)`$OO~P#4YO)_0}O~P!?ZO]1ZOe!POm%dO!V1XO!{!dO%v$oO(w$zO)Y1RO)`1UO~O)[1VO)]1VO)p1SOQ#PX!d#PX!h#PX[#PX~P' }O!h1[OQ)rX!d)rX~OQ1^O!d1^O~O)`1aO)p1`OQ#`X!d#`X!h#`X~P!<_O)`1aO)p1`OQ#`X!d#`X!h#`X~P!;eOq&WO~O[#ka!T#ka#v#ka)_#ka)p#kaQ#ka!d#ka!h#ka)`#ka!x#ka({#ka~P#IyO]&eO!V+pO[#ka!T#ka#v#ka)_#ka)p#kaQ#ka!d#ka!h#ka)`#ka!x#ka({#ka~O!W1fO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W1fO)Y1hO~P$&OO!W1fO~P!(}O]#ja!T#ja!V#ja[#ja#v#ja)_#ja)p#jaQ#ja!d#ja!h#ja)`#ja!x#ja({#ja~P$!WO[1lO]&eO!V+pO~O!h1mO[)jX~O[1oO~O]&eO!V+pO[#na!T#na#v#na)_#na)p#naQ#na!d#na!h#na)`#na!x#na({#na~O]1sOs#SXt#SXu#SXv#SXw#SXx#SXy#SXz#SX!T#SX!V#SX#T#SX#p#SX(}#SX)[#SX)]#SX!l#SX!x#SX#V#SX#v#SX({#SX)p#SX[#SX!h#SX)_#SXQ#SX!d#SX)`#SX~O]1tO~O]1wOm$qO!V$hO#V#QO(w$pO)ncO)odO~Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!l,PO#T+{O#V,OO#p+|O(}+yO)[,PO)],PO~O])lX!T)lX!V)lX!x)lX#v)lX({)lX)p)lX[)lX!h)lX)_)lXQ)lX!d)lX~P',hO!x!cO]#Ri!T#Ri!V#Ri#v#Ri({#Ri)p#Ri[#Ri!h#Ri)_#RiQ#Ri!d#Ri~O!W2PO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W2PO)Y2RO~P$&OO!W2PO~P!(}O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OOQ*XX!d*XX!h*XX~P#4YO)`2SOQ)QX!d)QX!h)QX~O!h2TOQ)PX!d)PX~OQ2VO!d2VO~O[2WO~O#t$nO)VYO~P8}Om-jO!TxO)p2[O~O[2]O~O#x,fOP#ui]#uib#uie#uim#uis#uit#uiu#uiv#uiw#uix#uiy#uiz#ui|#ui!O#ui!T#ui!V#ui!X#ui!Y#ui!i#ui!o#ui!r#ui!s#ui!t#ui!u#ui!v#ui!x#ui!{#ui#V#ui#a#ui#b#ui#i#ui#p#ui#t#ui#v#ui$R#ui$T#ui$Y#ui$Z#ui$`#ui$e#ui$g#ui$h#ui$k#ui$m#ui$o#ui$q#ui$s#ui$u#ui$w#ui${#ui$}#ui%U#ui%_#ui%`#ui%a#ui%c#ui%e#ui%g#ui%l#ui%o#ui%v#ui%|#ui&m#ui&r#ui&s#ui'Q#ui'R#ui'V#ui'Y#ui'a#ui'b#ui(l#ui(u#ui(w#ui)V#ui)Y#ui)[#ui)]#ui)_#ui)`#ui)b#ui)n#ui)o#ui!U#ui$c#ui!n#ui%k#ui~O]&eO~O]&eO!TxO!V&dO#v!eO~O({2bO(|,hO)V$Ua)_$Ua~O)VYO)_2dO~O[2eO~P,`O[2eO)_#lO~O[2eO~O$c2jOP$_i]$_ib$_ie$_im$_is$_it$_iu$_iv$_iw$_ix$_iy$_iz$_i|$_i!O$_i!T$_i!V$_i!X$_i!Y$_i!i$_i!o$_i!r$_i!s$_i!t$_i!u$_i!v$_i!x$_i!{$_i#V$_i#a$_i#b$_i#i$_i#p$_i#t$_i#v$_i$R$_i$T$_i$Y$_i$Z$_i$`$_i$e$_i$g$_i$h$_i$k$_i$m$_i$o$_i$q$_i$s$_i$u$_i$w$_i${$_i$}$_i%U$_i%_$_i%`$_i%a$_i%c$_i%e$_i%g$_i%l$_i%o$_i%v$_i%|$_i&m$_i&r$_i&s$_i'Q$_i'R$_i'V$_i'Y$_i'a$_i'b$_i(l$_i(u$_i(w$_i)V$_i)Y$_i)[$_i)]$_i)_$_i)`$_i)b$_i)n$_i)o$_i!U$_i~O]1wO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_2mO)`$OO~P#4YOPmO]$gOb!]Om;SO|#RO!V$hO!X!XO!Y!WO!i!YO#V#QO#a#VO#b#TO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w;UO)Y$mO)]$mO)_2pO)`!ZO)bXO)ncO)odO~P&@^O)_2mO~O(w-ZO~O)VYO)p2sO~O)_2uO~O]-_Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!{!dO!|%TO(w-ZO)Y-[O~O)Y2zO~O]&eO!V2|O!h2}O)_){X~O]-_O!{!dO(w-ZO)Y-[O~O)_3QO~O!TxO$`!iO$e!jO$g!kO$h!lO$k-gO$m!nO$o!oO$q!pO$s!qO$u!rO$w!sO$}!uO(w:uOe$Xi!o$Xi!{$Xi#i$Xi#p$Xi#t$Xi#v$Xi$R$Xi$T$Xi$Y$Xi$Z$Xi${$Xi%U$Xi%c$Xi%g$Xi%o$Xi%|$Xi(l$Xi)[$Xi!U$Xi$c$Xi~P$0yOm;SO(w:uO~P0}O]3UO~O)_2ZO~O!u3WO(w%pO~O[3ZO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h3[O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[3]O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO]&eO!V+pO!T%ui#v%ui)_%ui)p%ui~O!W3^O~Om;QO)_)SX~P$G`Ob!TOm$qO|3dO#a#VO#b3cO#t!fO%e#UO%l3eO&m!RO&r#WO&s!TO(w$pO)VYO~P&@^Om;jO!o-uO#i-zO#t!fO${-OO%c!zO%k-yO%o!|O%v!}O(w;[O)VYO~P!8mO]&eO!V&dO)_3gO~O)_3hO~O)VYO)_3hO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_3iO)`$OO~P#4YO)_3iO~O)_3lO~O!U3nO~P$JpOm$qO(w$pO~O]3pO!T'{O~P',SO!T(SO!l3sO({(RO])Tae)Tam)Tas)Tat)Tau)Tav)Taw)Tax)Tay)Taz)Ta!O)Ta!V)Ta!r)Ta!s)Ta!t)Ta!u)Ta!v)Ta!x)Ta!{)Ta%v)Ta&r)Ta&s)Ta(w)Ta)Y)Ta)[)Ta)])Ta)_)Ta[)Ta!X)Ta!Y)Ta![)Ta!^)Ta!_)Ta!a)Ta!b)Ta!e)Ta!f)Ta!h)Ta(z)Ta(|)Ta(})Ta)Z)Ta)^)Ta)`)Ta!g)Ta)p)Ta!W)TaQ)Ta!d)Ta!U)Ta#v)Ta~Om$qO!n.hO!o.hO(w$pO~O!h3wO)`3yO!T)eX~O!o3{O)VYO~P8}O)_3|O~PGYO]4ROm)QO!T$YO!{!dO%v$oO&r#WO(w)PO({4VO)Y4OO)[4SO)]4SO~O)_4WO)p4YO~P('OOm;kO!U4[O!n.uO!o.tO#i-zO${!tO$}!uO%g!{O%k-yO%o!|O%v!}O(w;^O)VYO~P!8mOm;kO%v!}O(w;^O~P!8mO({4]O~Om$qO!T(SO(w$pO({(RO)VYO~O!l3sO~P()^O)p4_O!U&oX!h&oX~O!h4`O!U*WX~O!U4bO~Ob4dOm$qO&m!RO(w$pO~O!T(]O]&kie&kim&kis&kit&kiu&kiv&kiw&kix&kiy&kiz&ki!O&ki!V&ki!r&ki!s&ki!t&ki!u&ki!v&ki!x&ki!{&ki%v&ki&r&ki&s&ki(w&ki)Y&ki)[&ki)]&ki)_&ki[&ki!X&ki!Y&ki![&ki!^&ki!_&ki!a&ki!b&ki!e&ki!f&ki!h&ki(z&ki(|&ki(}&ki)Z&ki)^&ki)`&ki!g&ki)p&ki!W&kiQ&ki!d&ki!U&ki#v&ki~O({&ki~P(*nO({.zO~P(*nO[4gO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[4gO~O[4hO~O]$PO!T$YO!V'Zi!X'Zi!Y'Zi!['Zi!^'Zi!_'Zi!a'Zi!b'Zi!e'Zi!f'Zi!h'Zi(z'Zi(|'Zi(}'Zi)Y'Zi)Z'Zi)['Zi)]'Zi)^'Zi)_'Zi)`'Zi!g'Zi)p'Zi['Zi!W'Zi({'Zi!U'ZiQ'Zi!d'Zi~OPmOb%SOm;RO!X!XO!Y!WO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)`!ZO)bXO)ncO)odO]#]aq#]a!T#]a!V#]a)Y#]a)[#]a)]#]a~O(w%pO)`4mO[*`P~O*^4lO~O'f4oO*^4lO~O*^4pO~OmnXqoXq&wX~Oe4rO%Y*YO)O/dO~Oe4rO%Y*YO)O4sO~O!h/jO[(xa~O!W4wO~O]&eO!V+pO!T%uq#v%uq)_%uq)p%uq~O]$PO!T$YO!X'Zq!Y'Zq!['Zq!^'Zq!_'Zq!a'Zq!b'Zq!e'Zq!f'Zq!h'Zq(z'Zq(|'Zq(}'Zq)Y'Zq)Z'Zq)['Zq)]'Zq)^'Zq)_'Zq)`'Zq!g'Zq)p'Zq['Zq!W'Zq({'Zq!U'ZqQ'Zq!d'Zq~O!V'Zq~P(5{O!V/SO&r#WO&s$yO~P(5{O!T$YO!V)wO(|)xO!U(VX!h(VX~P!KVO!h/uO!U)xa~O!W5PO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h*nO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!U5TO~P&7dO!W5TO~P&7dO[5TO~P&7dO[5YO~P&7dO]5ZO!h'va)U'va)`'va~O!h*TO)U)Wi)`)Wi~O]&eO!V&dO[#Qq!T#Qq!h#Qq#v#Qq)_#Qq)p#QqQ#Qq!d#Qq({#Qq~O[riQri!dri!hri)`ri)_ri~P#IyO]&eO!V+pO[riQri!dri!hri)`ri)_ri~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!h'Tq)_'Tq!g'Tq)p'Tq['Tq!W'Tq({'Tq!U'TqQ'Tq!d'Tq~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!W'}a!h'}a~P#4YO!W5`O~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h5aO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_#lO)`$OO!U)xX~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!h#{i)_#{i~P#4YO]*{O!T$YO!V&dO)p*wO!h(Wa)_(Wa~O!h1mO[)jX]'dX~P%3WO)`5cO!T%qa!h%qa#v%qa)p%qa~O!h0zO!T*Qa#v*Qa)p*Qa~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_5fO)`$OO~P#4YO]1ZOe!POm;cO!V1XO!{!dO%v$oO(w$zO)Y<PO)[5hO)]5hO~OQ#Pa!d#Pa!h#Pa[#Pa~P(ETO]1ZOe!POs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!V1XO!{!dO!|%TO%v$oO(w$zOQ#kX!d#kX!h#kX[#kX~Om%dO)Y1RO)[<QO)]<QO~P(FVO]&eOQ#Pa!d#Pa!h#Pa[#Pa~O!V&dO)p5lO~P(GtO(w%pOQ#dX!d#dX!h#dX[#dX~O)[<QO)]<QOQ#nX!d#nX!h#nX[#nX~P' }O!V+pO~P(GtO]1ZOb!TOe!POm;dO|#RO!V1XO!{!dO#a#VO#b#TO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO(w;XO)VYO)Y<PO)[5hO)]5hO)`+sO[)jP~P&@^O!h1[OQ)ra!d)ra~Oq&hO)p5qOQ#`am)SX!d#`a!h#`a)`)SX~P$G`O(w-ZOQ#ga!d#ga!h#ga~Oq&hO)p5qOQ#`a])dXe)dXm)dXs)dXt)dXu)dXv)dXw)dXx)dXy)dXz)dX!O)dX!T)dX!V)dX!d#`a!h#`a!l)dX!r)dX!s)dX!t)dX!u)dX!v)dX!x)dX!{)dX%v)dX&r)dX&s)dX(w)dX({)dX)Y)dX)[)dX)])dX)`)dX~O#a5tO#b5tO~O]&eO!V+pO[#ki!T#ki#v#ki)_#ki)p#kiQ#ki!d#ki!h#ki)`#ki!x#ki({#ki~O!W5vO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W5vO~P!(}O!W5vO)Y5xO~P$&OO]#ji!T#ji!V#ji[#ji#v#ji)_#ji)p#jiQ#ji!d#ji!h#ji)`#ji!x#ji({#ji~P$!WO)VYO)`5zO~P8}O!h1mO[)ja~O&r#WO&s$yO!T#qa!x#qa#v#qa({#qa)p#qa[#qa!h#qa)_#qaQ#qa!d#qa)`#qa~P#NsO[6PO~P!(}O[)uP~P!4{O)Z6VO)[6TO]#Ua!T#Ua!V#Ua)Y#Ua)]#Uas#Uat#Uau#Uav#Uaw#Uax#Uay#Uaz#Ua!l#Ua!x#Ua#T#Ua#V#Ua#p#Ua#v#Ua({#Ua(}#Ua)p#Uab#Uae#Uam#Ua|#Ua!O#Ua!o#Ua!r#Ua!s#Ua!t#Ua!u#Ua!v#Ua!{#Ua#a#Ua#b#Ua#i#Ua#t#Ua${#Ua%c#Ua%e#Ua%k#Ua%l#Ua%o#Ua%v#Ua&m#Ua&r#Ua&s#Ua(w#Ua)V#Ua)_#Ua[#Ua!h#UaQ#Ua!d#Ua~O!x!cO]#Rq!T#Rq!V#Rq#v#Rq({#Rq)p#Rq[#Rq!h#Rq)_#RqQ#Rq!d#Rq~O!W6[O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W6[O~P!(}O!h2TOQ)Pa!d)Pa~O)_6aO~Om-jO!TxO)p6bO~O]*{O!T$YO!V&dO!h*yO)_)wX~O)p6fO~P)+|O[6hO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[6hO~O$c6jOP$_q]$_qb$_qe$_qm$_qs$_qt$_qu$_qv$_qw$_qx$_qy$_qz$_q|$_q!O$_q!T$_q!V$_q!X$_q!Y$_q!i$_q!o$_q!r$_q!s$_q!t$_q!u$_q!v$_q!x$_q!{$_q#V$_q#a$_q#b$_q#i$_q#p$_q#t$_q#v$_q$R$_q$T$_q$Y$_q$Z$_q$`$_q$e$_q$g$_q$h$_q$k$_q$m$_q$o$_q$q$_q$s$_q$u$_q$w$_q${$_q$}$_q%U$_q%_$_q%`$_q%a$_q%c$_q%e$_q%g$_q%l$_q%o$_q%v$_q%|$_q&m$_q&r$_q&s$_q'Q$_q'R$_q'V$_q'Y$_q'a$_q'b$_q(l$_q(u$_q(w$_q)V$_q)Y$_q)[$_q)]$_q)_$_q)`$_q)b$_q)n$_q)o$_q!U$_q~O)_6kO~OPmO]$gOb!]Om;SO|#RO!V$hO!X!XO!Y!WO!i!YO#V#QO#a#VO#b#TO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w;UO)Y$mO)]$mO)_6mO)`!ZO)bXO)ncO)odO~P&@^O({6oO)p*wO~P)+|O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_6mO)`$OO~P#4YO[6qO~P!(}O)_6uO~O)_6vO~O]-_Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!{!dO(w-ZO)Y-[O~O]&eO!V2|O!h%Oa)_%Oa[%Oa~O!W6|O)Y6}O~P$&OO!h2}O)_){a~O[7QO]&eO!V2|O~O!TxO$`!iO$e!jO$g!kO$h!lO$k-gO$m!nO$o!oO$q!pO$s!qO$u!rO$w!sO$}!uO(w:uOe$Xq!o$Xq!{$Xq#i$Xq#p$Xq#t$Xq#v$Xq$R$Xq$T$Xq$Y$Xq$Z$Xq${$Xq%U$Xq%c$Xq%g$Xq%o$Xq%|$Xq(l$Xq)[$Xq!U$Xq$c$Xq~P$0yOPmO]$gOb!]Om;SO|#RO!V$hO!X!XO!Y!WO!i!YO#V#QO#a#VO#b#TO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w;UO)VYO)Y$mO)]$mO)_7SO)`!ZO)bXO)ncO)odO~P&@^O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_7VO)`$OO~P#4YO)_7WO~OP7XO(uQO~Om*aO)_)dX~P$G`Oq&hOm)SX)_)dX~P$G`O)_7ZO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO)_&Sa~P#4YO!U7]O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO)_7^O~OPmO]$gOb!]Om;TO|#RO!V$hO!X!XO!Y!WO!i!YO#V#QO#a#VO#b#TO%_#ZO%`#[O%a#YO%e#UO%l#SO%v$oO&m!RO&r#WO&s!TO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w;]O)VYO)Y$mO)]$mO)`0uO)bXO)ncO)odO[)jP~P&@^O!h3wO)`7bO!T)ea~O!h3wO!T)ea~O)_7gO)p7iO~P('OO)_7kO~PGYO]4ROm)QOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!{!dO!|%TO%v$oO&r#WO(w)PO)Y4OO)[4SO)]4SO~O)Y7oO~O]&eO!T*vO!V7qO!h7rO#v!eO({4VO~O)_7gO)p7tO~P)GbO]4ROm)QO!{!dO%v$oO&r#WO(w)PO)Y4OO)[4SO)]4SO~Oq&hO])iX!T)iX!V)iX!h)iX#v)iX({)iX)_)iX)p)iX[)iX~O)_7gO~O!T(SO!l7zO({(RO])Tie)Tim)Tis)Tit)Tiu)Tiv)Tiw)Tix)Tiy)Tiz)Ti!O)Ti!V)Ti!r)Ti!s)Ti!t)Ti!u)Ti!v)Ti!x)Ti!{)Ti%v)Ti&r)Ti&s)Ti(w)Ti)Y)Ti)[)Ti)])Ti)_)Ti[)Ti!X)Ti!Y)Ti![)Ti!^)Ti!_)Ti!a)Ti!b)Ti!e)Ti!f)Ti!h)Ti(z)Ti(|)Ti(})Ti)Z)Ti)^)Ti)`)Ti!g)Ti)p)Ti!W)TiQ)Ti!d)Ti!U)Ti#v)Ti~O(w%pO!U(gX!h(gX~O!h4`O!U*Wa~Oq&hO]*Vae*Vam*Vas*Vat*Vau*Vav*Vaw*Vax*Vay*Vaz*Va!O*Va!T*Va!V*Va!r*Va!s*Va!t*Va!u*Va!v*Va!x*Va!{*Va%v*Va&r*Va&s*Va(w*Va)Y*Va)[*Va)]*Va)_*Va[*Va!X*Va!Y*Va![*Va!^*Va!_*Va!a*Va!b*Va!e*Va!f*Va!h*Va(z*Va(|*Va(}*Va)Z*Va)^*Va)`*Va!g*Va)p*Va!W*VaQ*Va!d*Va({*Va!U*Va#v*Va~O!T(]O]&kqe&kqm&kqs&kqt&kqu&kqv&kqw&kqx&kqy&kqz&kq!O&kq!V&kq!r&kq!s&kq!t&kq!u&kq!v&kq!x&kq!{&kq%v&kq&r&kq&s&kq(w&kq)Y&kq)[&kq)]&kq)_&kq[&kq!X&kq!Y&kq![&kq!^&kq!_&kq!a&kq!b&kq!e&kq!f&kq!h&kq(z&kq(|&kq(}&kq)Z&kq)^&kq)`&kq!g&kq)p&kq!W&kqQ&kq!d&kq({&kq!U&kq#v&kq~OPmOb%SOm;RO!T$YO!i!YO#V#QO%_#ZO%`#[O%a#YO%v$oO'Q!WO'R!WO'V#XO'Y![O'a![O'b![O(uQO(w$zO)bXO)ncO)odO~O]*[i!V*[i!X*[i!Y*[i![*[i!^*[i!_*[i!a*[i!b*[i!e*[i!f*[i!h*[i(z*[i(|*[i(}*[i)Y*[i)Z*[i)[*[i)]*[i)^*[i)_*[i)`*[i!g*[i)p*[i[*[i!W*[i({*[i!U*[iQ*[i!d*[i~P*&qO[8PO~O!W8QO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!h'^q)_'^q!g'^q)p'^q['^q!W'^q({'^q!U'^qQ'^q!d'^q~P#4YO!h8RO[*`X~O[8TO~O*^8UO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!h_y)__y!g_y)p_y[_y!W_y({_y!U_yQ_y!d_y~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO[(ia!h(ia~P#4YO]$PO!T$YO!V'Zy!X'Zy!Y'Zy!['Zy!^'Zy!_'Zy!a'Zy!b'Zy!e'Zy!f'Zy!h'Zy(z'Zy(|'Zy(}'Zy)Y'Zy)Z'Zy)['Zy)]'Zy)^'Zy)_'Zy)`'Zy!g'Zy)p'Zy['Zy!W'Zy({'Zy!U'ZyQ'Zy!d'Zy~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!h'^y)_'^y!g'^y)p'^y['^y!W'^y({'^y!U'^yQ'^y!d'^y~P#4YO]&eO!V+pO!T%uy#v%uy)_%uy)p%uy~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!U(Va!h(Va~P#4YO!W5PO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!U#}i!h#}i~P#4YO!U8WO~P&7dO!W8WO~P&7dO[8WO~P&7dO[8YO~P&7dO]&eO!V&dO[#Qy!T#Qy!h#Qy#v#Qy)_#Qy)p#QyQ#Qy!d#Qy({#Qy~O]&eO!V+pO[rqQrq!drq!hrq)`rq)_rq~O]&eOQ#Pi!d#Pi!h#Pi[#Pi~O!V+pO~P*:TOQ#nX!d#nX!h#nX[#nX~P(ETO!V&dO~P*:TOQ(PX](PXe'rXm'rXs(PXt(PXu(PXv(PXw(PXx(PXy(PXz(PX!V(PX!d(PX!h(PX!{'rX%v'rX(w'rX)Y(PX)[(PX)](PX[(PX~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OOQ#_i!d#_i!h#_i[#_i~P#4YO&r#WO&s$yOQ#fi!d#fi!h#fi~O(w-ZO)`1aO)p1`OQ#`X!d#`X!h#`X~O!W8_O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W8_O~P!(}O!T#qi!x#qi#v#qi({#qi)p#qi[#qi!h#qi)_#qiQ#qi!d#qi)`#qi~O]&eO!V+pO~P*@PO]&[O!V&YO&r#WO&s$yO)Y&XO)[&]O)]&]O~P*@PO[8aO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!h8bO[)uX~O[8dO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OOQ*ZX!d*ZX!h*ZX~P#4YO)`8gOQ*YX!d*YX!h*YX~O)_8iO~O[$bi!h#{a)_#{a~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_8lO)`$OO~P#4YO[8nO~P!(}O[8nO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[8nO~O]&eO!V&dO({8tO~O)_8uO~O]&eO!V2|O!h%Oi)_%Oi[%Oi~O!W8xO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W8xO)Y8zO~P$&OO!W8xO~P!(}O]&eO!V2|O!h(Za)_(Za~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_8{O)`$OO~P#4YO)_2pO~P!(}O)_8{O~OP%qO[8|O(uQO~O[8|O~O)_8}O~P%%sO#T9QO(}.UO)_9OO~O!h3wO!T)ei~O)`9UO!T'xa!h'xa~O)_9WO)p9YO~P)GbO)_9WO~O)_9WO)p9^O~P('OOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O~P)HQO]&eO!V7qO!T!ya!h!ya#v!ya({!ya)_!ya)p!ya[!ya~O!W9eO)Y9fO~P$&OO!T$YO!h7rO({4VO)_9WO)p9^O~O!T$YO~P#EtO[9iO]&eO!V7qO~O]&eO!V7qO!T&aa!h&aa#v&aa({&aa)_&aa)p&aa[&aa~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO)_&ba~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_9WO)`$OO~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!U&oi!h&oi~P#4YO!V/SO]']i!T']i!X']i!Y']i![']i!^']i!_']i!a']i!b']i!e']i!f']i!h']i(z']i(|']i(}']i)Y']i)Z']i)[']i)]']i)^']i)_']i)`']i!g']i)p']i[']i!W']i({']i!U']iQ']i!d']i~O(w%pO)`9lO~O!h8RO[*`a~O[9nO~P&7dO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO!U(Va)_#Zi~P#4YO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OOQ#_q!d#_q!h#_q[#_q~P#4YO&r#WO&s$yOQ#fq!d#fq!h#fq~O)p5qOQ#`a!d#`a!h#`a~O]&eO!V+pO!T#qq!x#qq#v#qq({#qq)p#qq[#qq!h#qq)_#qqQ#qq!d#qq)`#qq~O!h8bO[)ua~O)[6TO]&Vi!T&Vi!V&Vi)Y&Vi)Z&Vi)]&Vis&Vit&Viu&Viv&Viw&Vix&Viy&Viz&Vi!l&Vi!x&Vi#T&Vi#V&Vi#p&Vi#v&Vi({&Vi(}&Vi)p&Vib&Vie&Vim&Vi|&Vi!O&Vi!o&Vi!r&Vi!s&Vi!t&Vi!u&Vi!v&Vi!{&Vi#a&Vi#b&Vi#i&Vi#t&Vi${&Vi%c&Vi%e&Vi%k&Vi%l&Vi%o&Vi%v&Vi&m&Vi&r&Vi&s&Vi(w&Vi)V&Vi)_&Vi[&Vi!h&ViQ&Vi!d&Vi~O)_9qO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO[$bq!h#{i)_#{i~P#4YO[9sO~P!(}O[9sO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[9sO~O]&eO!V&dO({9vO~O[9wO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[9wO~O]&eO!V2|O!h%Oq)_%Oq[%Oq~O!W9{O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W9{O~P!(}O)_6mO~P!(}O)_9|O~O)_9}O~O(}.UO)_9}O~O!h3wO!T)eq~O)`:PO!T'xi!h'xi~O!T$YO!h7rO({4VO)_:QO)p:SO~O)_:QO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_:QO)`$OO~P#4YO)_:QO)p:VO~P)GbO]&eO!V7qO!T!yi!h!yi#v!yi({!yi)_!yi)p!yi[!yi~O!W:ZO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W:ZO)Y:]O~P$&OO!W:ZO~P!(}O]&eO!V7qO!T(ea!h(ea({(ea)_(ea)p(ea~O[:_O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O!h#kO(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[:_O~O[:dO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[:dO~O]&eO!V2|O!h%Oy)_%Oy[%Oy~O)_:eO~O)_:fO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_:fO)`$OO~P#4YO!T$YO!h7rO({4VO)_:fO)p:iO~O]&eO!V7qO!T!yq!h!yq#v!yq({!yq)_!yq)p!yq[!yq~O!W:kO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO!W:kO~P!(}O[:mO!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)`$OO~P#4YO[:mO~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_:oO)`$OO~P#4YO)_:oO~O]&eO!V7qO!T!yy!h!yy#v!yy({!yy)_!yy)p!yy[!yy~O!Y#sO![#tO!^#wO!_#xO!a#zO!b#{O!e#{O!f#|O(z#hO)Y#oO)Z#qO)[#pO)]#rO)^#jO)_:sO)`$OO~P#4YO)_:sO~O]ZXmhXqZXqjX!TjX!VZX!XZX!YZX![ZX!^ZX!_ZX!aZX!bZX!eZX!fZX!gZX!hZX(zZX({$]X(|ZX(}ZX)YZX)ZZX)[ZX)]ZX)^ZX)_ZX)`ZX)pZX~O]%WXmnXqoXq%WX!ToX!V%WX!X%WX!Y%WX![%WX!^%WX!_%WX!a%WX!b%WX!e%WX!f%WX!gnX!h%WX(z%WX(|%WX(}%WX)Y%WX)Z%WX)[%WX)]%WX)^%WX)`%WX)pnX[%WXQ%WX!d%WX~O)_%WX!W%WX({%WX!U%WX~P+H]O]oX]%WXeoXmnXqoXq%WXsoXtoXuoXvoXwoXxoXyoXzoX!OoX!VoX!V%WX!roX!soX!toX!uoX!voX!xoX!{oX%voX&roX&soX(woX)YoX)[oX)]oX[oX[%WX!hoX)`oX~O)_oX)poX~P+JmO]%WXmnXqoXq%WX!V%WX!h%WXQ%WX!d%WX[%WX~O!T%WX#v%WX)_%WX)p%WX({%WX~P+MWOQoXQ%WX!ToX!X%WX!Y%WX![%WX!^%WX!_%WX!a%WX!b%WX!doX!d%WX!e%WX!f%WX!gnX!h%WX(z%WX(|%WX(}%WX)Y%WX)Z%WX)[%WX)]%WX)^%WX)`%WX)pnX~P+JmO]oX]%WXmnXqoXq%WXsoXtoXuoXvoXwoXxoXyoXzoX!OoX!V%WX!roX!soX!toX!uoX!voX!xoX!{oX%voX&roX&soX(woX)YoX)[oX)]oX~O!ToX({oX)_oX)poX~P,!OOeoX!VoX)_%WX~P,!OOmnXqoX)_%WX~Oe)tO%Y)uO)O:vO~Oe)tO%Y)uO)O:{O~Oe)tO%Y)uO)O:wO~Oe$TO%Y*YO'[$VO'_$WO)O:vO~Oe$TO%Y*YO'[$VO'_$WO)O:xO~Oe$TO%Y*YO'[$VO'_$WO)O:zO~O[jX]jXsjXtjXujXvjXwjXxjXyjXzjX!VjX&rjX&sjX)YjX)[jX)]jXejX!OjX!rjX!sjX!tjX!ujX!vjX!xjX!{jX%vjX(wjX~P#1xO]ZXmhXqZXqjX!VZX!hZX)_ZX)pZX~O!TZX#vZX({ZX~P,(fOmhXqjX)VjX)_ZX)pjX~O]ZX]jXejXmhXqZXqjXsjXtjXujXvjXwjXxjXyjXzjX!OjX!VZX!VjX!rjX!sjX!tjX!ujX!vjX!xjX!{jX%vjX&rjX&sjX(wjX)YjX)[jX)]jX[ZX[jX!hjX)`jX)pjX~O)_ZX~P,)pO]ZX]jXmhXqZXqjXsjXtjXujXvjXwjXxjXyjXzjX!TjX!VZX!VjX!XZX!YZX![ZX!^ZX!_ZX!aZX!bZX!eZX!fZX!gZX!hZX!hjX&rjX&sjX(zZX(|ZX(}ZX)YZX)YjX)ZZX)[ZX)[jX)]ZX)]jX)^ZX)`ZX)`jX)pZX~OQZXQjX!dZX!djX~P,,ZO]jXejXsjXtjXujXvjXwjXxjXyjXzjX!OjX!VjX!rjX!sjX!tjX!ujX!vjX!xjX!{jX%vjX&rjX&sjX(wjX)YjX)[jX)]jX~P#1xO]ZX]jXejXmhXqZXqjXsjXtjXujXvjXwjXxjXyjXzjX!OjX!VZX!VjX!rjX!sjX!tjX!ujX!vjX!xjX!{jX%vjX&rjX&sjX(wjX)YjX)[jX)]jX~O)_jX~P,1]O[ZX[jXejX!OjX!rjX!sjX!tjX!ujX!vjX!xjX!{jX%vjX(wjX)pjX~P,,ZO]ZX]jXmhXqZXqjXsjXtjXujXvjXwjXxjXyjXzjX!OjX!TjX!VZX!rjX!sjX!tjX!ujX!vjX!xjX!{jX%vjX&rjX&sjX(wjX({jX)YjX)[jX)]jX)_jX)pjX~Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O~PBXOe$TO%Y*YO)O:vO~Oe$TO%Y*YO)O:wO~Oe$TO%Y*YO)O:}O~Oe$TO%Y*YO)O:|O~O]%jOe!POm%dOs!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O!V%mO!{!dO!|%TO%v$oO(w$zO)Y;hO)[;iO)];iO~O]%jOe!POm%dO!V%mO!{!dO%v$oO(w$zO)Y;hO)[;iO)];iO~Oe$TO%Y$UO)O:wO~Oe$TO%Y$UO)O:{O~Om;QO~Om;PO~O]dXmhXqjX!TdX~Oe)tO%Y*YO)O:vO~Oe)tO%Y*YO)O:wO~Oe)tO%Y*YO)O:xO~Oe)tO%Y*YO)O:yO~Oe)tO%Y*YO)O:zO~Oe)tO%Y*YO)O:|O~Oe)tO%Y*YO)O:}O~Os!^Ot!^Ou!^Ov!^Ow!^Ox!^Oy!^Oz!^O~P,9iO])SXs)SXt)SXu)SXv)SXw)SXx)SXy)SXz)SX!O)SX!r)SX!s)SX!t)SX!u)SX!v)SX!x)SX!{)SX%v)SX&r)SX&s)SX(w)SX)Y)SX)[)SX)])SX)p)SX~Om;PO!T)SX({)SX)_)SX~P,=hO]&wXmnXqoX!T&wX~Oe4rO%Y*YO)O;{O~Om;cO)Y<PO)[5hO)]5hO~P(FVOe!POm%dO!{!dO%v$oO(w$zO~O]1ZO!V1XO)Y1RO)[<QO)]<QOQ#nX!d#nX!h#nX[#nX~P,@dO)Y;aO~Om;oO~Om;pO~Om;qO~Om;sO~Om;tO~Om;uO~Om;sO!T$YOQ)SX!d)SX!h)SX)`)SX[)SX)p)SX~P$G`Om;qO!T$YO~P$G`Om;oO!g$[O)p$[O~Om;qO!g$[O)p$[O~Om;sO!g$[O)p$[O~Om;pO[)SX!h)SX)`)SX)p)SX~P$G`Oe/eO%Y*YO)O;{O~Om;|O~O)Y<aO~OV'e'h'i'g(u)b!R(wS(p%Z!Y!['je%[!i'R!f]'f*a'k(|!^!_'l'm'l~", | |
| 4034 | goto: "%7u*aPPPPP*b*lP*oPP.ePP4y7z7z;UP;U>`P>y?]?qFiMi!&m!-TP!3}!4r!5gP!6RPPPPPPPP!6lP!8UP!9g!;PP!;VPPPPPP!;YP!;YPP!;YPP!;fPPPPPP!=h!AOP!ARPP!Ao!BdPPPPP!BhP>|!CyPP>|!FQ!HR!Ha!Iv!KgP!KrP!LR!LR# c#$r#&Y#)f#,p!HR#,zPP!HR#-R#-X#,z#,z#-[P#-`#-}#-}#-}#-}!KgP#.h#.y#1`P#1tP#3aP#3e#3m#4b#4m#6{#7T#7T#3eP#3eP#7[#7bP#7lPP#8X#8v#9h#8XP#:Y#:fP#8XP#8XPP#8X#8XP#8XP#8XP#8XP#8XP#8XP#8XP#:i#7l#;VP#;lP#<R#<R#<R#<R#<`#3eP#<v#Ar#BaPPPPPPPP#CXP#CgP#CgP#Cs#GQ#;bPP#Ca#GdP#Gw#HS#HY#HY#Ca#IOP#3e#3e#3e#3e#3eP!LR#Ij#Iq#Iq#Iq#Iu# ]#JP# ]#JT!Ha!Ha!Ha#JW#Np!Ha>|>|>|$%i!Bd!Bd!Bd!Bd!Bd!Bd!6l!6l!6l$%|P$'i$'w!6l$'}PP!6l$*]$*`#CO$*c;U7z$-i$/d$1T$2s7zPP7z$4g7zP7z7zP7zP$7m7zP7zPP7z$7yPPPPPPPPP*lP$;R$;X$;_$=v$?|$@S$@j$@t$AP$A`$Af$Bt$Cs$Cz$DR$DX$Da$Dk$Dq$D|$ES$E]$Ee$Ep$Ev$FQ$FW$Fb$Fi$Fx$GO$GUP$G[$Gd$Gk$Gy$Ig$Im$Is$Iz$JTPPPPPPPPPPPP$JZ$J_PPPPP%#a$*]%#d%&l%(tPP%)R%)UPPPPPPPPPP%)b%*e%*k%*o%,f%-s%.f%.m%0|%1SPPP%1^%1i%1l%1r%2y%2|%3W%3b%3f%4j%5]%5c#CXP%5|%6^%6a%6q%6}%7R%7X%7_$*]$*`$*`%7b%7eP%7o%7rQ#dPZ(s#b(o(p(t/ZR#dP'`mO[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mU%qm%r7XQ&o!`Q(o#^d0W*S0T0U0V0Y5U5V5W5Z8XR7X3[b}Oaewx{!g&U*v&v$k[!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|1S1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mS%bf0o#d%lgnp|#O$i%O%P%U%f%j%k%y&u'v'w(S*_*e*g*y+b,q,{-d-u-|.k.r.t0d1Q1R1V1Z2f2q5h6n;_;`;a;g;h;i;v;w;x;y;}<O<P<Q<_<`<aS%sm!YS&w!h#PQ'_!tQ'i!yQ'j!zQ(o#aQ(p#^Q(q#_Q*}%mQ,]&nQ,b&pQ-X'`Q-i'hQ-p'sS.w(]4`Q/m)lQ0l*rQ2X,aQ2`,hQ3V-jQ4i/RQ4m/[Q5m1UQ6c2[Q7U3WQ8h6bQ9l8RR;b1X$|#iS!]${%S%V%]&l&m'S'Z']'c'e(c(g(j(|(})W)X)Y)Z)[)])^)_)`)a)b)c)d)p)v)}+^+l,T,X,o,z-m-n.R/O/w0g0i0n0p1O1g2Q2h2o3Y3j3k4j4k4q4t4z4|5Q5R5k5w6O6]6l6p6z7R7x7y7{8Z8[8j8m8q8y9[9c9r9x:T:[:a:g:pQ&r!dQ(i#ZQ(x#cQ)o$V[*x%g*]0r2g2n3SQ,c&qQ/T(hQ/Z(pQ/b(yS/p)n/UQ0y+VS4x/q/rR8V4y'a![O[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:m'a!VO[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mQ)T#mS+V%{0zQ/y)xk4U.l3z4O4R4S7j7l7m7o7r9`9a:YQ)V#mk4T.l3z4O4R4S7j7l7m7o7r9`9a:Yl)U#m.l3z4O4R4S7j7l7m7o7r9`9a:YT+V%{0z[UOwx!g&U*vW$b[e$g(d#l$r_!f!u!}#R#S#T#U#V#Z$U$V$n%W&W&[&e&o'a(P(R(W(`(i)o)u+a+f+g+y,O,^,p-P-V-t-y.].^.d.e.i.v.z1[1`1m1r1t2s3c3d3e3w3{5q6U6W7c8b![%eg$i%f%k&u*_*y+b,q,{-d1R1V2f;_;`;a;h;i;v;w;x;y;}<O<Q<_<`<aY%unp%y-u.kl)R#m.l3z4O4R4S7j7l7m7o7r9`9a:YS;l'v-|U;m(S.r.t&|<Saf{|!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$h$m%O%P%U%_%j%o&S&Y&d&{'O'Q'k'l'w'{(b(k)q)w*e*g*m*n*q*w+]+_+m+o+p,U,W,s,v-l.U.V.Z/S/V/c/j/s/u/z/|0d0o1Q1S1X1h1i1s1w2R2j2p2q2|4V4Y4_4h5a5h5l5x6f6j6m6n6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:m;g<PQ<T1Zd<U&z'R'd,|-b-c-f2m3R3UW<V&h*{2T3pQ<W#O[<X!t'`'h,a2[6bT<d%{0z[VOwx!g&U*vW$c[e$g(dQ$r.z!j$s_!f!u!}#V#Z$U$V$n%W&W&[&e&o'a(i)o)u+a+f+y,^,p-P-V-t.i1[1`1m1r1t2s3{5q8b&^$|af{!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$h$m%_%o&S&Y&d&{'O'Q'k'l'{(b(k)q)w*m*n*q*w+]+_+m+o+p,U,W,s,v-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2j2p2|4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:m![%eg$i%f%k&u*_*y+b,q,{-d1R1V2f;_;`;a;h;i;v;w;x;y;}<O<Q<_<`<aY%unp%y-u.kQ't#O|(O#R#S#T#U(P(R(W(`+g,O.].^.d.e.v3c3d3e3w6U6W7cl)R#m.l3z4O4R4S7j7l7m7o7r9`9a:YS-s'v-|Q3_-yU;z(S.r.tn<S|%O%P%U%j'w*e*g0d1Q2q5h6n;g<P[<X!t'`'h,a2[6bW<Y&h*{2T3pd<Z&z'R'd,|-b-c-f2m3R3UQ<b1ZT<d%{0z!Q!UO[ewx!g$g&U&h&z'R'd(d*v*{,|-b-c-f2T2m3R3U3p!v$v_!f!u!}#O#V#Z$U$V$n%W&W&[&e&o'a'v(S(i)o)u+a+y,^,p-P-V-t-|.i.r.t1Z1[1`1m1r1t2s3{5q8b&^%Raf{!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$h$m%_%o&S&Y&d&{'O'Q'k'l'{(b(k)q)w*m*n*q*w+]+_+m+o+p,U,W,s,v-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2j2p2|4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:m$Q%ngnp|#m$i%O%P%U%f%j%k%y%{&u'`'h'w*_*e*g*y+b,a,q,{-d-u.k.l0d0z1Q1R1V2[2f2q3z4O4R4S5h6b6n7j7l7m7o7r9`9a:Y;_;`;a;g;h;i;v;w;x;y;}<O<P<Q<_<`<aQ'^!tz(Q#R#S#T#U(P(R(W(`,O.].^.d.e.v3c3d3e3w6U6W7cf-`'b-Y-[-_2w2x2z2}6x6y8wQ1_+fQ1b+gQ2r-OQ3`-yQ4c.zQ5s1aR8^5t!Q!UO[ewx!g$g&U&h&z'R'd(d*v*{,|-b-c-f2T2m3R3U3p!x$v_!f!u!}#O#V#Z$U$V$n%W&W&[&e&o'a'v(S(i)o)u+a+f+y,^,p-P-V-t-|.i.r.t1Z1[1`1m1r1t2s3{5q8b&^%Raf{!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$h$m%_%o&S&Y&d&{'O'Q'k'l'{(b(k)q)w*m*n*q*w+]+_+m+o+p,U,W,s,v-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2j2p2|4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:m$S%ngnp|!t#m$i%O%P%U%f%j%k%y%{&u'`'h'w*_*e*g*y+b,a,q,{-d-u.k.l0d0z1Q1R1V2[2f2q3z4O4R4S5h6b6n7j7l7m7o7r9`9a:Y;_;`;a;g;h;i;v;w;x;y;}<O<P<Q<_<`<a|(Q#R#S#T#U(P(R(W(`+g,O.].^.d.e.v3c3d3e3w6U6W7cQ3`-yR4c.z[WOwx!g&U*vW$d[e$g(d#l$r_!f!u!}#R#S#T#U#V#Z$U$V$n%W&W&[&e&o'a(P(R(W(`(i)o)u+a+f+g+y,O,^,p-P-V-t-y.].^.d.e.i.v.z1[1`1m1r1t2s3c3d3e3w3{5q6U6W7c8b![%eg$i%f%k&u*_*y+b,q,{-d1R1V2f;_;`;a;h;i;v;w;x;y;}<O<Q<_<`<aY%unp%y-u.kl)R#m.l3z4O4R4S7j7l7m7o7r9`9a:YS;l'v-|U;m(S.r.tn<S|%O%P%U%j'w*e*g0d1Q2q5h6n;g<PQ<T1ZQ<W#O[<X!t'`'h,a2[6b&^<[af{!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$h$m%_%o&S&Y&d&{'O'Q'k'l'{(b(k)q)w*m*n*q*w+]+_+m+o+p,U,W,s,v-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2j2p2|4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:md<]&z'R'd,|-b-c-f2m3R3UW<^&h*{2T3pT<d%{0zp$RT$a$q%d%t)Q;R;S;T;c;d;e;f;j;k<co)r$X*Z*a/f;O;P;Q;o;p;q;r;s;t;u;|p$ST$a$q%d%t)Q;R;S;T;c;d;e;f;j;k<co)s$X*Z*a/f;O;P;Q;o;p;q;r;s;t;u;|^&g}!O$k$l%b%l;bd&k!U$v%R%n'^(Q1_1b3`4cV/h)T)U4US%[e$gQ,Y&hQ/Q(dQ2t-VQ6Q1tQ6^2TQ6t2sR9o8b#}!TO[_ewx!f!g!u!}#O#V#Z$U$V$g$n%W&U&W&[&e&h&o&z'R'a'd'v(S(d(i)o)u*v*{+a+f+y,^,p,|-P-V-b-c-f-t-y-|.i.r.t1Z1[1`1m1r1t2T2m2s3R3U3p3{5q8b#[^O[_`wx!f!g!}#O$U$f$n$u$w&U&W&[&e&o&t&z'R'd'v(S)u*b*v*{+a,^,p,|-P-b-c-f-t-y-|.i.r.t1Z1[1m2m3R3U3p3{_(W#R#S#T+g3c3d3e#}ZO[wx!g!k#R#S#T%o&U&W&[&e&o&y&z&{'O'Q'R'^'d'v'z(P(R(S(W*v*{+a+g,^,m,p,v-U-b-c-f-t-y-|.P.d.i.r.v1Z1[1m2j2r3R3U3c3d3e3p6j6q8n9s9w:_:d:mQ$_YR0[*TR*V$_e0W*S0T0U0V0Y5U5V5W5Z8X$f#{S%V%]'S'Z']'c'e(j(|(})W)Z)[)])^)_)`)c)d)p)v)}+^+l,T,X,o,z-m-n.R/O/w0g0i0n0p1O1g2Q2h2o3Y3j3k4j4k4q4t4z4|5Q5R5k5w6O6]6l6p6z7R7x7y7{8Z8[8j8m8q8y9[9c9r9x:T:[:a:g:pe0W*S0T0U0V0Y5U5V5W5Z8X'`!YO[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:me0W*S0T0U0V0Y5U5V5W5Z8XR5[0[^(V#R#S#T+g3c3d3eY.b(P(T(W(X7[U3r.`.c.vS7`3s4^R9j7z^(U#R#S#T+g3c3d3e[.a(P(T(V(W(X7[W3q.`.b.c.vU7_3r3s4^S9R7`7zR:^9jT.p(S.rd]Owx!g&U'v(S*v-|.r!v^[_`!f!}#O$U$f$n$u$w&W&[&e&o&t&z'R'd)u*b*{+a,^,p,|-P-b-c-f-t-y.i.t1Z1[1m2m3R3U3p3{Q%vnT1|,S1}!jbOaenpwx{|!g#O%O%P%U%j%y&U'v'w(S*e*g*v-u-|.k.r.t0d1Q1Z2q5h6n;g<Pf-]'b-Y-[-_2w2x2z2}6x6y8wj4P.l3z4O4R4S7j7l7m7o7r9`9a:Yr<Rg$i%f%k&u*_*y,q,{-d2f;_;`;a;v;x;}i<e+b1R1V;h;i;w;y<O<Q<_<`<a!O&`y%Z&X&[&]'m)m*i*k+b+j+}/t0e1Q1R1V1Z1q5h5}<P<Qz&cz%Q%Y%g&f'u*]*d,g-}0b0c0r1T2g2n3S5^5i6s8pS'}#Q.^n+q&Z*l+k+r+u-o/o0f1Y1e4{5_5g5|8`Q2_,f^2{-^2y3P6w7O8v9ze7p4Q7f7n7v7w9]9_9g:X:jS+c&W1[Y+s&[&e*{1Z3pR5z1m#w!POaegnpwx{|!g#O$i%O%P%U%f%j%k%y&U&u'v'w(S*_*e*g*v*y+b,q,{-d-u-|.k.r.t0d1Q1R1V1Z2f2q5h6n;_;`;a;g;h;i;v;w;x;y;}<O<P<Q<_<`<a`oOwx!g&U'v*v-|#U!Paeg{|#O$i%O%P%U%f%j%k&u'w*_*e*g*y+b,q,{-d0d1Q1R1V1Z2f2q5h6n;_;`;a;g;h;i;v;w;x;y;}<O<P<Q<_<`<aU%xnp-uQ+S%yS.j(S.rT3}.k.tW+w&`+q+x1jV,P&c,Q7pQ+}&bU,P&c,Q7pQ-|'vT.X'{.Z'`![O[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mX1y,O.^6U6W'W!VO[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/c/j/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mW1y,O.^6U6WR2l,x!WjO[wx!g!k%o&U&{'O'Q'd*v,v-b-c-f2j3R6j6q8n9s9w:_:d:mY%Xe$g(d1w3pQ'U!nS)O#k5aQ,r&zQ,}'RS.T'{.ZQ2i,sQ6r2pQ7T3UQ8o6mR9t8l'W![O[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/c/j/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mX1y,O.^6U6W'ayO[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,O,U,W,s,v,|-b-c-f-l.U.V.Z.^/S/c/j/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_5a5l5x6U6W6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mQ&byS'v#O-zR1c+hS+c&W1[R5u1cQ1W+bR5n1VR1W+bT+c&W1[z&^%Z&X&[&]'m)m*i*k+b+j/t0e1Q1R1V1Z1q5h5}<P<QQ&_yR1u+}!P&^y%Z&X&[&]'m)m*i*k+b+j+}/t0e1Q1R1V1Z1q5h5}<P<QQ+z&`S,R&c7pS1k+q+xQ1{,QR5y1j!WkO[wx!g!k%o&U&{'O'Q'd*v,v-b-c-f2j3R6j6q8n9s9w:_:d:mS%|o.jS&Qq-wQ&ayQ&s!eQ'g!yQ*u%gU+Q%x%}3}S+U%z&PQ+v&_Q,_&oS,`&p'iQ,w&}S0`*],gS0v+R+SQ0x+TQ1v+}S2Z,b-kQ5]0bQ5b0wQ6S1uQ6a2YQ6d2_Q7u4QQ9Z7fR:W9][uOwx!g&U*vQ,_&oQ-{'vQ3a-yR3f-|xlOwx!g!k%o&U&{'Q*v,v2j6j6q8n9s9w:_:d:mU$j['O-cS%|o.jS&Qq-wQ*u%gU+Q%x%}3}S+U%z&PS0`*],gS0v+R+SQ0x+TQ5]0bQ5b0wQ7u4QQ9Z7fR:W9]T,d&s,e]uOwx!g&U*v[uOwx!g&U*vQ,_&oQ,s&zQ,|'RW-e'd-b-f3RQ-{'vQ3a-yQ3f-|R7S3U[%hg$i,q,{-d2fR0s*y^$ZV!U$c$|%R<Y<ZQ'U!nS)e$P*{S){$Y*vQ*O$[Y*x%g*]0r2n3SQ/T(hS/p)n/US0h*m4hS0q*w6fQ0y+VQ4X.lQ4u/jS4x/q/rS4}/u5aQ5S/|Q6g2gU7h3z4Q4YQ8V4yQ8r6oY9X7f7i7j7s7tQ9y8tW:R9V9Y9]9^Q:b9vU:h:S:U:VR:q:iS){$Y*vT4}/u5aZ)y$Y)z*v/u5aQ&y!hR'z#PS,l&x'xQ2c,jR6e2bxlOwx!g!k%o&U&{'Q*v,v2j6j6q8n9s9w:_:d:mV$j['O-c!XkO[wx!g!k%o&U&{'O'Q'd*v,v-b-c-f2j3R6j6q8n9s9w:_:d:m!WhO[wx!g!k%o&U&{'O'Q'd*v,v-b-c-f2j3R6j6q8n9s9w:_:d:mR'Y!q!WkO[wx!g!k%o&U&{'O'Q'd*v,v-b-c-f2j3R6j6q8n9s9w:_:d:mR,s&zQ&{!iQ&}!jQ'Q!lR,v&|R,t&zxlOwx!g!k%o&U&{'Q*v,v2j6j6q8n9s9w:_:d:mX-e'd-b-f3R[uOwx!g&U*vQ-P'RQ-{'vS.p(S.rR3f-|[uOwx!g&U*vQ-P'RW-e'd-b-f3RT.p(S.rg-`'b-Y-[-_2w2x2z2}6x6y8wylOwx!g!k%o&U&{'Q*v,v2j6j6q8n9s9w:_:d:mb!OOaewx{!g&U*v&|$l[f!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:m#d%lgnp|#O$i%O%P%U%f%j%k%y&u'v'w(S*_*e*g*y+b,q,{-d-u-|.k.r.t0d1Q1R1V1Z2f2q5h6n;_;`;a;g;h;i;v;w;x;y;}<O<P<Q<_<`<aQ'_!tQ-X'`Q-i'hQ2X,aQ6c2[R8h6bj$TT$a%d%t;R;S;T;c;d;e;f;j;ki)t$X*Z;O;P;Q;o;p;q;r;s;t;uj$TT$a%d%t;R;S;T;c;d;e;f;j;kh)t$X*Z;O;P;Q;o;p;q;r;s;t;uS/e)Q<cV4r/f/g;|[uOwx!g&U*vQ-{'vR3f-|[uOwx!g&U*vT.p(S.r'`!YO[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mR7Y3[[uOwx!g&U*vQ-{'vS.p(S.rR3f-|[pOwx!g&U*vQ%ynS-u'v-|T.k(S.rS%}o.jS+R%x3}R0w+SQ+W%{R5d0zS%|o.jS&Qq-wU+Q%x%}3}S+U%z&PS0v+R+SQ0x+TQ5b0wQ7u4QQ9Z7fR:W9]`qOwx!g&U(S*v.rS%zn-uU&Pp.k.tQ+T%yT-w'v-|S'|#Q.^R._'}T.W'{.ZS.X'{.ZQ9P7]R:O9QT6U1x8fR6W1x#d!Pgnp|#O$i%O%P%U%f%j%k%y&u'v'w(S*_*e*g*y+b,q,{-d-u-|.k.r.t0d1Q1R1V1Z2f2q5h6n;_;`;a;g;h;i;v;w;x;y;}<O<P<Q<_<`<ab!QOaewx{!g&U*v&}![[f!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:m#d!Pgnp|#O$i%O%P%U%f%j%k%y&u'v'w(S*_*e*g*y+b,q,{-d-u-|.k.r.t0d1Q1R1V1Z2f2q5h6n;_;`;a;g;h;i;v;w;x;y;}<O<P<Q<_<`<ab!QOaewx{!g&U*v&|![[f!W!X!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|#}$P$W$Y$[$g$h$m%_%o&S&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_4h5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mk4T.l3z4O4R4S7j7l7m7o7r9`9a:YQ4X.lS7h3z4QU9X7f7j7sS:R9V9]R:h:U#|!TO[_ewx!f!g!u!}#O#V#Z$U$V$g$n%W&U&W&[&e&h&o&z'R'a'd'v(S(d(i)o)u*v*{+a+f+y,^,p,|-P-V-b-c-f-t-y-|.i.r.t1Z1[1`1m1r1t2T2m2s3R3U3p3{5q8bR4d.zQ(_#US.{(^(`S4e.|.}R8O4fQ.x(]R7|4`#|!TO[_ewx!f!g!u!}#O#V#Z$U$V$g$n%W&U&W&[&e&h&o&z'R'a'd'v(S(d(i)o)u*v*{+a+f+y,^,p,|-P-V-b-c-f-t-y-|.i.r.t1Z1[1`1m1r1t2T2m2s3R3U3p3{5q8bp$y`$f$u%Z&t'b(a(h)n*i-Y/r1q5r5}8]q)S#m%{.l0z3z4O4R4S7j7l7m7o7r9`9a:YR,Z&hR6_2T'X!VO[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/c/j/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:m$q#tS%V%]'S'Z']'c'e(c(g(j(|(})W)X)Z)[)])^)_)`)a)b)c)d)p)v)}+^+l,T,X,o,z-m-n.R/O/w0g0i0n0p1O1g2Q2h2o3Y3j3k4j4k4q4t4z4|5Q5R5k5w6O6]6l6p6z7R7x7y7{8Z8[8j8m8q8y9[9c9r9x:T:[:a:g:p$]#uS%V%]'S'Z']'c'e(j(|(})W)[)c)d)p)v)}+^+l,T,X,o,z-m-n.R/O/w0g0i0n0p1O1g2Q2h2o3Y3j3k4j4k4q4t4z4|5Q5R5k5w6O6]6l6p6z7R7x7y7{8Z8[8j8m8q8y9[9c9r9x:T:[:a:g:p$Z#vS%V%]'S'Z']'c'e(j(|(})W)c)d)p)v)}+^+l,T,X,o,z-m-n.R/O/w0g0i0n0p1O1g2Q2h2o3Y3j3k4j4k4q4t4z4|5Q5R5k5w6O6]6l6p6z7R7x7y7{8Z8[8j8m8q8y9[9c9r9x:T:[:a:g:p$c#yS%V%]'S'Z']'c'e(j(|(})W)Z)[)])^)c)d)p)v)}+^+l,T,X,o,z-m-n.R/O/w0g0i0n0p1O1g2Q2h2o3Y3j3k4j4k4q4t4z4|5Q5R5k5w6O6]6l6p6z7R7x7y7{8Z8[8j8m8q8y9[9c9r9x:T:[:a:g:p'X![O[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/c/j/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mQ/U(hQ/q)nQ4y/rR9k8Q']![O[aefwx{!W!X!g!k!n!r!s!v!x#X#Y#[#h#k#n#s#t#u#v#w#x#y#z#{#|$P$W$Y$[$g$h$m%_%o&S&U&Y&d&h&z&{'O'Q'R'd'k'l'{(b(d(k)q)w*m*n*q*v*w*{+]+_+m+o+p,U,W,s,v,|-b-c-f-l.U.V.Z/S/V/c/j/s/u/z/|0o1S1X1h1i1s1w2R2T2j2m2p2|3R3U3p4V4Y4_5a5l5x6f6j6m6o6q6{6}7S7i7q7t8l8n8t8z8{9Y9^9d9f9s9v9w:S:V:]:_:d:i:mQ(m#]R/W(mQ#fQR(z#fU%Oa;g<Pb%We$g&h(d-V1t2T2s8bQ'a!u!Q*c%O%W'a*e*k+m,U0d0e1i2w6x6{7l8w9`9d:Y;_;v;w;}<O<_S*e%P%UQ*k%ZS+m&Y1XQ,U&dQ0d*gQ0e*iQ1i+pQ2w-[S6x2x2zQ6{2|Q7l4OQ8w6yS9`7m7oQ9d7qQ:Y9aQ;_%fS;v;`;aS;w<`<aQ;};xQ<O;yT<_1R;h[[Owx!g&U*vl$e['O(P+a,^,m,p-U-c-t.P.d.i.vl'O!k%o&{'Q,v2j6j6q8n9s9w:_:d:m^(P#R#S#T+g3c3d3e`+a&W&[&e*{1Z1[1m3pS,^&o-yQ,m&yU,p&z'R3US-U'^2rW-c'd-b-f3RS-t'v-|Q.P'zQ.d(RS.i(S.rR.v(WQ*R$^R0P*RQ0Y*SQ5U0TQ5V0UQ5W0VY5X0Y5U5V5W8XR8X5ZQ*U$_S0]*U0^R0^*VS.e(R.dS3u.e7cR7c3wQ3x.fS7a3v3yU7e3x7a9SR9S7bQ.r(SR4Z.r!|_O[wx!f!g!}#O$U$n&U&W&[&e&o&z'R'd'v(S)u*v*{+a,^,p,|-P-b-c-f-t-y-|.i.r.t1Z1[1m2m3R3U3p3{U$t_$w*bU$w`$f&tR*b$uU%Pa;g<Pd*f%P*g2x6y7m9a;`;x;y<`Q*g%UQ2x-[Q6y2zQ7m4OQ9a7oQ;`%fQ;x;aQ;y<aT<`1R;hS,Q&c7pR1z,QS*o%]/wR0j*oQ1]+dR5p1]U+j&X1R<PR1d+jQ+x&`Q1j+qT1p+x1jQ8c6QR9p8cQwOS&Tw&UT&Ux*vQ,e&sR2^,eW)z$Y*v/u5aR/{)zU/v)v){0nR5O/v[*z%g%h*]2g2n3SR0t*zQ,i&wR2a,iQ-f'dQ3R-bT3T-f3RQ3O-^R7P3OQ-k'iQ2Y,bT3X-k2YS%rm7XR+P%rdnOwx!g&U'v(S*v-|.rR%wnQ0{+WR5e0{Q.Z'{R3m.ZQ1},SR6X1}U*s%b*};bR0m*sS1n+s0uR5{1nQ7s4QQ9V7fU9h7s9V:UR:U9]$O!SO[_ewx!f!g!u!}#O#V#Z$U$V$g$n%W&U&W&[&e&h&o&z'R'a'd'v(S(d(i)o)u*v*{+a+f+y,^,p,|-P-V-b-c-f-t-y-|.i.r.t.z1Z1[1`1m1r1t2T2m2s3R3U3p3{5q8bR&i!SQ4a.xR7}4aQ2U,ZR6`2US/k)d)eR4v/kW(t#b(o(p/ZR/_(tQ8S4mR9m8ST)f$P*{!USO[wx!g!k%o&U&{'O'Q'd,v-b-c-f2j3R6j6q8n9s9w:_:d:mj${a{$m%_+o,W1h2R5x6}8z9f:]Y%Ve$g(d1w3pY%]f$h(k)q*qQ&l!WQ&m!XQ'S!nQ'Z!rQ']!sQ'c!vQ'e!xQ(c#XQ(g#YS(j#[+_Q(|#hQ(}#kQ)W#nQ)X#sQ)Y#tQ)Z#uQ)[#vQ)]#wQ)^#xQ)_#yQ)`#zQ)a#{Q)b#|Q)c#}S)d$P*{Q)p$WQ)v$YQ)}$[Q+^&SS+l&Y1XQ,T&dQ,X&hQ,o&zQ,z'RQ-m'kQ-n'lS.R'{.ZQ/O(bS/w)w0oS0g*m4hQ0i*nQ0n*vQ0p*wQ1O+]S1g+m+pQ2Q,UQ2h,sS2o,|7SQ3Y-lQ3j.UQ3k.VQ4j/SQ4k/VQ4q/cQ4t/jQ4z/sQ4|/uQ5Q/zQ5R/|Q5k1SQ5w1iQ6O1sQ6]2TS6l2m8{Q6p2pQ6z2|Q7R3UQ7x4VQ7y4YQ7{4_Q8Z5aQ8[5lQ8j6fQ8m6mQ8q6oQ8y6{S9[7i7tQ9c7qQ9r8lQ9x8tS:T9Y9^Q:[9dQ:a9vS:g:S:VR:p:iR,[&hd]Owx!g&U'v(S*v-|.r!v^[_`!f!}#O$U$f$n$u$w&W&[&e&o&t&z'R'd)u*b*{+a,^,p,|-P-b-c-f-t-y.i.t1Z1[1m2m3R3U3p3{#r$}ae!u$g%O%P%U%W%Z%f&Y&d&h'a(d*e*g*i*k+m+p,U-V-[0d0e1X1i1t2T2s2w2x2z2|4O6x6y6{7l7m7o7q8b8w9`9a9d:Y;_;`;a;g;h;v;w;x;y;}<O<_<`<aQ%vnS+i&X+jW+w&`+q+x1jU,P&c,Q7pQ1r+yT5j1R<P``Owx!g&U'v*v-|S$f[-tQ$u_b%Ze$g&h(d-V1t2T2s8b!h&t!f!}#O$U$n&W&[&e&o&z'R'd(S)u*{+a,^,p,|-P-b-c-f-y.i.r.t1Z1[1m2m3R3U3p3{Q'b!uS(a#V+fQ(h#ZS)n$V(iQ*i%WQ-Y'aQ/r)oQ1q+yQ5r1`Q5}1rR8]5qS(Y#R3dS(Z#S3eV([#T+g3cR$`Ye0X*S0T0U0V0Y5U5V5W5Z8XW(T#R#S#T+gQ(^#US.`(P(WS.f(R.dQ.}(`W1y,O.^6U6WQ3b-yQ3o.]Q3v.eQ4^.vU7[3c3d3eQ7d3wR9T7cQ.g(RR3t.dT.q(S.rdgOwx!g&U&o'v*v-y-|U$i[,^-tQ&u!fQ'm!}Q'w#OQ)m$UQ*_$n`+b&W&[&e*{1Z1[1m3pQ,q&zQ,{'RY-d'd-b-f3R3US.l(S.rQ/t)uQ1Q+aS2f,p-cS2q,|-PS3z.i.tQ6n2mR7j3{d]Owx!g&U'v(S*v-|.r!v^[_`!f!}#O$U$f$n$u$w&W&[&e&o&t&z'R'd)u*b*{+a,^,p,|-P-b-c-f-t-y.i.t1Z1[1m2m3R3U3p3{R%vnQ4Q.lQ7f3zQ7n4OQ7v4RQ7w4SQ9]7jU9_7l7m7oQ9g7rS:X9`9aR:j:YZ+t&[&e*{1Z3ppzOnpwx!g%y&U'v(S*v-u-|.k.r.t[%Qa%f1R;g;h<PU%Ye%j1ZQ%gg^&f{|%k1V5h;i<QQ'u#OQ*]$ib*d%O%P%U;_;`;a<_<`<aQ,g&uQ-}'wQ0b*_[0c*e*g;v;w;x;yQ0r*yQ1T+bQ2g,qQ2n,{S3S-d2fU5^0d;}<OQ5i1QQ6s2qR8p6nQ,S&cR9b7pS1x,O.^Q8e6UR8f6W[%`f$h(k)q)w0oR0k*qR+e&WQ+d&WR5o1[S&Zy+}Q*l%ZU+k&X1R<PS+r&[1ZW+u&]1V5h<QQ-o'mQ/o)mS0f*i*kQ1Y+bQ1e+jQ4{/tQ5_0eQ5g1QQ5|1qR8`5}R6R1tYvOwx&U*vR&v!gW%ig,q,{-dT*^$i2fT)|$Y*v[uOwx!g&U*vQ'P!kQ+O%oQ,u&{Q,y'QQ2k,vQ6i2jQ8k6jQ8s6qQ9u8nQ:`9sQ:c9wQ:l:_Q:n:dR:r:mxlOwx!g!k%o&U&{'Q*v,v2j6j6q8n9s9w:_:d:mU$j['O-cX-e'd-b-f3RQ-a'bR2v-YS-^'b-YQ2y-[Q3P-_U6w2w2x2zQ7O2}S8v6x6yR9z8w[rOwx!g&U*vS-v'v-|T.m(S.rR+X%{[sOwx!g&U*vS-x'v-|T.n(S.r[tOwx!g&U*vT.o(S.rT.Y'{.ZX%cf%m0o1XQ.|(^R4f.}R.y(]R(f#XQ(w#bS/Y(o(pR4l/ZR/^(qR4n/[", | |
| 4035 | nodeNames: "\u26A0 RawString > MacroName LineComment BlockComment PreprocDirective #include String EscapeSequence SystemLibString Identifier ) ( ArgumentList ConditionalExpression AssignmentExpression CallExpression PrimitiveType FieldExpression FieldIdentifier DestructorName TemplateMethod ScopedFieldIdentifier NamespaceIdentifier TemplateType TypeIdentifier ScopedTypeIdentifier ScopedNamespaceIdentifier :: NamespaceIdentifier TypeIdentifier TemplateArgumentList < TypeDescriptor const volatile restrict _Atomic mutable constexpr constinit consteval StructSpecifier struct MsDeclspecModifier __declspec Attribute AttributeName Identifier AttributeArgs { } [ ] UpdateOp ArithOp ArithOp ArithOp LogicOp BitOp BitOp BitOp CompareOp CompareOp CompareOp > CompareOp BitOp UpdateOp , Number CharLiteral AttributeArgs VirtualSpecifier BaseClassClause Access virtual FieldDeclarationList FieldDeclaration extern static register inline thread_local AttributeSpecifier __attribute__ PointerDeclarator MsBasedModifier __based MsPointerModifier FunctionDeclarator ParameterList ParameterDeclaration PointerDeclarator FunctionDeclarator Noexcept noexcept RequiresClause requires True False ParenthesizedExpression CommaExpression LambdaExpression LambdaCaptureSpecifier TemplateParameterList OptionalParameterDeclaration TypeParameterDeclaration typename class VariadicParameterDeclaration VariadicDeclarator ReferenceDeclarator OptionalTypeParameterDeclaration VariadicTypeParameterDeclaration TemplateTemplateParameterDeclaration template AbstractFunctionDeclarator AbstractPointerDeclarator AbstractArrayDeclarator AbstractParenthesizedDeclarator AbstractReferenceDeclarator ThrowSpecifier throw TrailingReturnType CompoundStatement FunctionDefinition MsCallModifier TryStatement try CatchClause catch LinkageSpecification Declaration InitDeclarator InitializerList InitializerPair SubscriptDesignator FieldDesignator ExportDeclaration export ImportDeclaration import ModuleName PartitionName HeaderName CaseStatement case default LabeledStatement StatementIdentifier ExpressionStatement IfStatement if ConditionClause Declaration else SwitchStatement switch DoStatement do while WhileStatement ForStatement for ReturnStatement return BreakStatement break ContinueStatement continue GotoStatement goto CoReturnStatement co_return CoYieldStatement co_yield AttributeStatement ForRangeLoop AliasDeclaration using TypeDefinition typedef PointerDeclarator FunctionDeclarator ArrayDeclarator ParenthesizedDeclarator ThrowStatement NamespaceDefinition namespace ScopedIdentifier Identifier OperatorName operator ArithOp BitOp CompareOp LogicOp new delete co_await ConceptDefinition concept UsingDeclaration enum StaticAssertDeclaration static_assert ConcatenatedString TemplateDeclaration FriendDeclaration friend union FunctionDefinition ExplicitFunctionSpecifier explicit FieldInitializerList FieldInitializer DefaultMethodClause DeleteMethodClause FunctionDefinition OperatorCast operator TemplateInstantiation FunctionDefinition FunctionDefinition Declaration ModuleDeclaration module RequiresExpression RequirementList SimpleRequirement TypeRequirement CompoundRequirement ReturnTypeRequirement ConstraintConjuction LogicOp ConstraintDisjunction LogicOp ArrayDeclarator ParenthesizedDeclarator ReferenceDeclarator TemplateFunction OperatorName StructuredBindingDeclarator ArrayDeclarator ParenthesizedDeclarator ReferenceDeclarator BitfieldClause FunctionDefinition FunctionDefinition Declaration FunctionDefinition Declaration AccessSpecifier UnionSpecifier ClassSpecifier EnumSpecifier SizedTypeSpecifier TypeSize EnumeratorList Enumerator DependentType Decltype decltype auto PlaceholderTypeSpecifier ParameterPackExpansion ParameterPackExpansion FieldIdentifier PointerExpression SubscriptExpression BinaryExpression ArithOp LogicOp LogicOp BitOp UnaryExpression LogicOp BitOp UpdateExpression CastExpression SizeofExpression sizeof CoAwaitExpression CompoundLiteralExpression NULL NewExpression new NewDeclarator DeleteExpression delete ParameterPackExpansion nullptr this UserDefinedLiteral ParamPack #define PreprocArg #if #ifdef #ifndef #else #endif #elif PreprocDirectiveName Macro Program", | |
| 4036 | maxTerm: 431, | |
| 4037 | nodeProps: [ | |
| 4038 | ["group", -35, 1, 8, 11, 15, 16, 17, 19, 71, 72, 100, 101, 102, 104, 191, 208, 229, 242, 243, 270, 271, 272, 277, 280, 281, 282, 284, 285, 286, 287, 290, 292, 293, 294, 295, 296, "Expression", -13, 18, 25, 26, 27, 43, 255, 256, 257, 258, 262, 263, 265, 266, "Type", -19, 126, 129, 147, 150, 152, 153, 158, 160, 163, 164, 166, 168, 170, 172, 174, 176, 178, 179, 188, "Statement"], | |
| 4039 | ["isolate", -3, 4, 8, 10, ""], | |
| 4040 | ["openedBy", 12, "(", 52, "{", 54, "["], | |
| 4041 | ["closedBy", 13, ")", 51, "}", 53, "]"] | |
| 4042 | ], | |
| 4043 | propSources: [cppHighlighting], | |
| 4044 | skippedNodes: [0, 3, 4, 5, 6, 7, 10, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 308, 348, 349], | |
| 4045 | repeatNodeCount: 42, | |
| 4046 | tokenData: "%LSMfR!UOX$eXY({YZ.gZ]$e]^+P^p$epq({qr.}rs0}st2ktu$euv!7dvw!9bwx!;exy!<Yyz!=Tz{!>O{|!?R|}!AV}!O!BQ!O!P!DX!P!Q#+y!Q!R#5[!R![#JY![!]$4w!]!^$6s!^!_$7n!_!`%$h!`!a%%i!a!b%(o!b!c$e!c!n%)j!n!o%+R!o!w%)j!w!x%+R!x!}%)j!}#O%.O#O#P%/w#P#Q%?[#Q#R%AT#R#S%)j#S#T$e#T#i%)j#i#j%BW#j#o%)j#o#p%Cu#p#q%Dp#q#r%Fv#r#s%Gq#s;'S$e;'S;=`(u<%lO$e,j$nY)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$e,f%eW)c`'f,UOY%^Zw%^wx%}x#O%^#O#P&f#P;'S%^;'S;=`'x<%lO%^,U&SU'f,UOY%}Z#O%}#O#P&f#P;'S%};'S;=`'r<%lO%},U&kX'f,UOY%}YZ%}Z]%}]^'W^#O%}#O#P&f#P;'S%};'S;=`'r<%lO%},U']V'f,UOY%}YZ%}Z#O%}#O#P&f#P;'S%};'S;=`'r<%lO%},U'uP;=`<%l%},f'{P;=`<%l%^,Y(VW(vS'f,UOY(OZr(Ors%}s#O(O#O#P&f#P;'S(O;'S;=`(o<%lO(O,Y(rP;=`<%l(O,j(xP;=`<%l$eMf)Y`)c`(vS(o<`'f,U*a1pOX$eXY({YZ*[Z]$e]^+P^p$epq({qr$ers%^sw$ewx(Ox#O$e#O#P,^#P;'S$e;'S;=`(u<%lO$e<`*aT(o<`XY*[YZ*[]^*[pq*[#O#P*p<`*sQYZ*[]^*y<`*|PYZ*[Gz+[`)c`(vS(o<`'f,UOX$eXY+PYZ*[Z]$e]^+P^p$epq+Pqr$ers%^sw$ewx(Ox#O$e#O#P,^#P;'S$e;'S;=`(u<%lO$eGf,cX'f,UOY%}YZ-OZ]%}]^-{^#O%}#O#P&f#P;'S%};'S;=`'r<%lO%}Gf-V[(o<`'f,UOX%}XY-OYZ*[Z]%}]^-O^p%}pq-Oq#O%}#O#P,^#P;'S%};'S;=`'r<%lO%}Gf.QV'f,UOY%}YZ-OZ#O%}#O#P&f#P;'S%};'S;=`'r<%lO%}MQ.nT*^1p(o<`XY*[YZ*[]^*[pq*[#O#P*pF`/[[%^#t'QQ)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!_$e!_!`0Q!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`0_Y%]#t!a8O)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eKz1YY)c`(tS(u=j'f,UOY%^Zr%^rs1xsw%^wx%}x#O%^#O#P&f#P;'S%^;'S;=`'x<%lO%^/[2RW*O#t)c`'f,UOY%^Zw%^wx%}x#O%^#O#P&f#P;'S%^;'S;=`'x<%lO%^Gz2tf)c`(vS'f,UOX$eXY2kZp$epq2kqr$ers%^sw$ewx(Ox!c$e!c!}4Y!}#O$e#O#P&f#P#T$e#T#W4Y#W#X5m#X#Y>u#Y#]4Y#]#^NZ#^#o4Y#o;'S$e;'S;=`(u<%lO$eGz4eb)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#o4Y#o;'S$e;'S;=`(u<%lO$eGz5xd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#X4Y#X#Y7W#Y#o4Y#o;'S$e;'S;=`(u<%lO$eGz7cd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#Y4Y#Y#Z8q#Z#o4Y#o;'S$e;'S;=`(u<%lO$eGz8|d)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#]4Y#]#^:[#^#o4Y#o;'S$e;'S;=`(u<%lO$eGz:gd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#b4Y#b#c;u#c#o4Y#o;'S$e;'S;=`(u<%lO$eGz<Qd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#X4Y#X#Y=`#Y#o4Y#o;'S$e;'S;=`(u<%lO$eGz=mb)c`(vS'e<`'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#o4Y#o;'S$e;'S;=`(u<%lO$eGz?Qf)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#`4Y#`#a@f#a#b4Y#b#cHV#c#o4Y#o;'S$e;'S;=`(u<%lO$eGz@qf)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#]4Y#]#^BV#^#g4Y#g#hEV#h#o4Y#o;'S$e;'S;=`(u<%lO$eGzBbd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#Y4Y#Y#ZCp#Z#o4Y#o;'S$e;'S;=`(u<%lO$eGzC}b)c`(vS'f,U'l<`'m<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#o4Y#o;'S$e;'S;=`(u<%lO$eGzEbd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#X4Y#X#YFp#Y#o4Y#o;'S$e;'S;=`(u<%lO$eGzF}b)c`(vS'j<`'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#o4Y#o;'S$e;'S;=`(u<%lO$eGzHbd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#W4Y#W#XIp#X#o4Y#o;'S$e;'S;=`(u<%lO$eGzI{d)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#]4Y#]#^KZ#^#o4Y#o;'S$e;'S;=`(u<%lO$eGzKfd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#Y4Y#Y#ZLt#Z#o4Y#o;'S$e;'S;=`(u<%lO$eGzMRb)c`(vS'f,U'k<`'m<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#o4Y#o;'S$e;'S;=`(u<%lO$eGzNff)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#Y4Y#Y#Z! z#Z#b4Y#b#c!.[#c#o4Y#o;'S$e;'S;=`(u<%lO$eGz!!Xf)c`(vS'g<`'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#W4Y#W#X!#m#X#b4Y#b#c!(W#c#o4Y#o;'S$e;'S;=`(u<%lO$eGz!#xd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#X4Y#X#Y!%W#Y#o4Y#o;'S$e;'S;=`(u<%lO$eGz!%cd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#Y4Y#Y#Z!&q#Z#o4Y#o;'S$e;'S;=`(u<%lO$eGz!'Ob)c`(vS'h<`'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#o4Y#o;'S$e;'S;=`(u<%lO$eGz!(cd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#W4Y#W#X!)q#X#o4Y#o;'S$e;'S;=`(u<%lO$eGz!)|d)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#X4Y#X#Y!+[#Y#o4Y#o;'S$e;'S;=`(u<%lO$eGz!+gd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#Y4Y#Y#Z!,u#Z#o4Y#o;'S$e;'S;=`(u<%lO$eGz!-Sb)c`(vS'i<`'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#o4Y#o;'S$e;'S;=`(u<%lO$eGz!.gd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#V4Y#V#W!/u#W#o4Y#o;'S$e;'S;=`(u<%lO$eGz!0Qd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#`4Y#`#a!1`#a#o4Y#o;'S$e;'S;=`(u<%lO$eGz!1kd)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#i4Y#i#j!2y#j#o4Y#o;'S$e;'S;=`(u<%lO$eGz!3Ud)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#W4Y#W#X!4d#X#o4Y#o;'S$e;'S;=`(u<%lO$eGz!4od)c`(vS'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#X4Y#X#Y!5}#Y#o4Y#o;'S$e;'S;=`(u<%lO$eGz!6[b)c`(vSV<`'f,U'm<`OY$eZr$ers%^sw$ewx(Ox!Q$e!Q![4Y![!c$e!c!}4Y!}#O$e#O#P&f#P#R$e#R#S4Y#S#T$e#T#o4Y#o;'S$e;'S;=`(u<%lO$eF`!7q[)c`(vS%Z#t![8O'f,UOY$eZr$ers%^sw$ewx(Ox!_$e!_!`!8g!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`!8rY!g:t)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`!9o])]8O)c`(vS%[#t'f,UOY$eZr$ers%^sv$evw!:hwx(Ox!_$e!_!`!8g!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`!:uY)[8O%^#t)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCb!;pW)aW(vS)b8O'f,UOY(OZr(Ors%}s#O(O#O#P&f#P;'S(O;'S;=`(o<%lO(OLS!<eY)c`(vS]Kn'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$e-^!=`Y[r)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`!>][)Y8O)c`(vS%Z#t'f,UOY$eZr$ers%^sw$ewx(Ox!_$e!_!`!8g!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`!?`^)c`(vS%Z#t!Y8O'f,UOY$eZr$ers%^sw$ewx(Ox{$e{|!@[|!_$e!_!`!8g!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`!@gY)c`!X:t(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCr!AbY!h8W)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`!B__)c`(vS%Z#t!Y8O'f,UOY$eZr$ers%^sw$ewx(Ox}$e}!O!@[!O!_$e!_!`!8g!`!a!C^!a#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`!CiY(}:t)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCr!Dd^)c`(vS'f,U(|8OOY$eZr$ers%^sw$ewx(Ox!O$e!O!P!E`!P!Q$e!Q![!GY![#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCr!Ei[)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!O$e!O!P!F_!P#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCr!FjY)`8W)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCj!Gen)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx!Icx!Q$e!Q![!GY![!g$e!g!h#$w!h!i#*Y!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#X$e#X#Y#$w#Y#Z#*Y#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCY!IjY(vS'f,UOY(OZr(Ors%}s!Q(O!Q![!JY![#O(O#O#P&f#P;'S(O;'S;=`(o<%lO(OCY!Jcn(vS!i8O'f,UOY(OZr(Ors%}sw(Owx!Icx!Q(O!Q![!JY![!g(O!g!h!La!h!i##`!i!n(O!n!o##`!o!r(O!r!s!La!s!w(O!w!x##`!x#O(O#O#P&f#P#X(O#X#Y!La#Y#Z##`#Z#`(O#`#a##`#a#d(O#d#e!La#e#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCY!Ljl(vS!i8O'f,UOY(OZr(Ors%}s{(O{|!Nb|}(O}!O!Nb!O!Q(O!Q![# e![!c(O!c!h# e!h!i# e!i!n(O!n!o##`!o!w(O!w!x##`!x#O(O#O#P&f#P#T(O#T#Y# e#Y#Z# e#Z#`(O#`#a##`#a#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCY!Ni^(vS'f,UOY(OZr(Ors%}s!Q(O!Q![# e![!c(O!c!i# e!i#O(O#O#P&f#P#T(O#T#Z# e#Z;'S(O;'S;=`(o<%lO(OCY# nj(vS!i8O'f,UOY(OZr(Ors%}sw(Owx!Nbx!Q(O!Q![# e![!c(O!c!h# e!h!i# e!i!n(O!n!o##`!o!w(O!w!x##`!x#O(O#O#P&f#P#T(O#T#Y# e#Y#Z# e#Z#`(O#`#a##`#a#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCY##id(vS!i8O'f,UOY(OZr(Ors%}s!h(O!h!i##`!i!n(O!n!o##`!o!w(O!w!x##`!x#O(O#O#P&f#P#Y(O#Y#Z##`#Z#`(O#`#a##`#a#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCj#%Sn)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx(Ox{$e{|#'Q|}$e}!O#'Q!O!Q$e!Q![#(]![!c$e!c!h#(]!h!i#(]!i!n$e!n!o#*Y!o!w$e!w!x#*Y!x#O$e#O#P&f#P#T$e#T#Y#(]#Y#Z#(]#Z#`$e#`#a#*Y#a#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCj#'Z`)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!Q$e!Q![#(]![!c$e!c!i#(]!i#O$e#O#P&f#P#T$e#T#Z#(]#Z;'S$e;'S;=`(u<%lO$eCj#(hj)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx!Nbx!Q$e!Q![#(]![!c$e!c!h#(]!h!i#(]!i!n$e!n!o#*Y!o!w$e!w!x#*Y!x#O$e#O#P&f#P#T$e#T#Y#(]#Y#Z#(]#Z#`$e#`#a#*Y#a#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCj#*ef)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx(Ox!h$e!h!i#*Y!i!n$e!n!o#*Y!o!w$e!w!x#*Y!x#O$e#O#P&f#P#Y$e#Y#Z#*Y#Z#`$e#`#a#*Y#a#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eMf#,W`)c`(vS%Z#t![8O'f,UOY$eZr$ers%^sw$ewx(Oxz$ez{#-Y{!P$e!P!Q#.T!Q!_$e!_!`!8g!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eMf#-eY)c`(vS(pAz'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eMf#.`Y)c`(vSSAz'f,UOY#.TZr#.Trs#/Osw#.Twx#4]x#O#.T#O#P#0[#P;'S#.T;'S;=`#5U<%lO#.TMb#/XW)c`SAz'f,UOY#/OZw#/Owx#/qx#O#/O#O#P#0[#P;'S#/O;'S;=`#4V<%lO#/OMQ#/xUSAz'f,UOY#/qZ#O#/q#O#P#0[#P;'S#/q;'S;=`#1l<%lO#/qMQ#0cXSAz'f,UOY#/qYZ%}Z]#/q]^#1O^#O#/q#O#P#1r#P;'S#/q;'S;=`#1l<%lO#/qMQ#1VVSAz'f,UOY#/qYZ%}Z#O#/q#O#P#0[#P;'S#/q;'S;=`#1l<%lO#/qMQ#1oP;=`<%l#/qMQ#1y]SAz'f,UOY#/qYZ%}Z]#/q]^#1O^#O#/q#O#P#1r#P#b#/q#b#c#/q#c#f#/q#f#g#2r#g;'S#/q;'S;=`#1l<%lO#/qMQ#2yUSAz'f,UOY#/qZ#O#/q#O#P#3]#P;'S#/q;'S;=`#1l<%lO#/qMQ#3dZSAz'f,UOY#/qYZ%}Z]#/q]^#1O^#O#/q#O#P#1r#P#b#/q#b#c#/q#c;'S#/q;'S;=`#1l<%lO#/qMb#4YP;=`<%l#/OMU#4fW(vSSAz'f,UOY#4]Zr#4]rs#/qs#O#4]#O#P#0[#P;'S#4];'S;=`#5O<%lO#4]MU#5RP;=`<%l#4]Mf#5XP;=`<%l#.TCj#5gt)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx#7wx!O$e!O!P#B}!P!Q$e!Q![#JY![!g$e!g!h#$w!h!i#*Y!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#U$e#U#V#Li#V#X$e#X#Y#$w#Y#Z#*Y#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j#l$e#l#m$0p#m;'S$e;'S;=`(u<%lO$eCY#8OY(vS'f,UOY(OZr(Ors%}s!Q(O!Q![#8n![#O(O#O#P&f#P;'S(O;'S;=`(o<%lO(OCY#8wp(vS!i8O'f,UOY(OZr(Ors%}sw(Owx#7wx!O(O!O!P#:{!P!Q(O!Q![#8n![!g(O!g!h!La!h!i##`!i!n(O!n!o##`!o!r(O!r!s!La!s!w(O!w!x##`!x#O(O#O#P&f#P#X(O#X#Y!La#Y#Z##`#Z#`(O#`#a##`#a#d(O#d#e!La#e#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCY#;Un(vS!i8O'f,UOY(OZr(Ors%}s!Q(O!Q![#=S![!c(O!c!g#=S!g!h#@d!h!i#=S!i!n(O!n!o##`!o!r(O!r!s!La!s!w(O!w!x##`!x#O(O#O#P&f#P#T(O#T#X#=S#X#Y#@d#Y#Z#=S#Z#`(O#`#a##`#a#d(O#d#e!La#e#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCY#=]p(vS!i8O'f,UOY(OZr(Ors%}sw(Owx#?ax!Q(O!Q![#=S![!c(O!c!g#=S!g!h#@d!h!i#=S!i!n(O!n!o##`!o!r(O!r!s!La!s!w(O!w!x##`!x#O(O#O#P&f#P#T(O#T#X#=S#X#Y#@d#Y#Z#=S#Z#`(O#`#a##`#a#d(O#d#e!La#e#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCY#?h^(vS'f,UOY(OZr(Ors%}s!Q(O!Q![#=S![!c(O!c!i#=S!i#O(O#O#P&f#P#T(O#T#Z#=S#Z;'S(O;'S;=`(o<%lO(OCY#@mt(vS!i8O'f,UOY(OZr(Ors%}sw(Owx#?ax{(O{|!Nb|}(O}!O!Nb!O!Q(O!Q![#=S![!c(O!c!g#=S!g!h#@d!h!i#=S!i!n(O!n!o##`!o!r(O!r!s!La!s!w(O!w!x##`!x#O(O#O#P&f#P#T(O#T#X#=S#X#Y#@d#Y#Z#=S#Z#`(O#`#a##`#a#d(O#d#e!La#e#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCj#CYp)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx(Ox!Q$e!Q![#E^![!c$e!c!g#E^!g!h#Gm!h!i#E^!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#T$e#T#X#E^#X#Y#Gm#Y#Z#E^#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCj#Eip)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx#?ax!Q$e!Q![#E^![!c$e!c!g#E^!g!h#Gm!h!i#E^!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#T$e#T#X#E^#X#Y#Gm#Y#Z#E^#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCj#Gxt)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx#?ax{$e{|#'Q|}$e}!O#'Q!O!Q$e!Q![#E^![!c$e!c!g#E^!g!h#Gm!h!i#E^!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#T$e#T#X#E^#X#Y#Gm#Y#Z#E^#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCj#Jep)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx#7wx!O$e!O!P#B}!P!Q$e!Q![#JY![!g$e!g!h#$w!h!i#*Y!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#X$e#X#Y#$w#Y#Z#*Y#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCj#Lr_)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!O$e!O!P#Mq!P!Q$e!Q!R#Np!R![#JY![#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCj#Mz[)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!Q$e!Q![!GY![#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCj#N{t)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx#7wx!O$e!O!P#B}!P!Q$e!Q![#JY![!g$e!g!h#$w!h!i#*Y!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#U$e#U#V$#]#V#X$e#X#Y#$w#Y#Z#*Y#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j#l$e#l#m$$[#m;'S$e;'S;=`(u<%lO$eCj$#f[)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!Q$e!Q![#JY![#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCj$$e`)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!Q$e!Q![$%g![!c$e!c!i$%g!i#O$e#O#P&f#P#T$e#T#Z$%g#Z;'S$e;'S;=`(u<%lO$eCj$%rr)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx$'|x!O$e!O!P#B}!P!Q$e!Q![$%g![!c$e!c!g$%g!g!h$.Q!h!i$%g!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#T$e#T#X$%g#X#Y$.Q#Y#Z$%g#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCY$(T^(vS'f,UOY(OZr(Ors%}s!Q(O!Q![$)P![!c(O!c!i$)P!i#O(O#O#P&f#P#T(O#T#Z$)P#Z;'S(O;'S;=`(o<%lO(OCY$)Yr(vS!i8O'f,UOY(OZr(Ors%}sw(Owx$'|x!O(O!O!P#:{!P!Q(O!Q![$)P![!c(O!c!g$)P!g!h$+d!h!i$)P!i!n(O!n!o##`!o!r(O!r!s!La!s!w(O!w!x##`!x#O(O#O#P&f#P#T(O#T#X$)P#X#Y$+d#Y#Z$)P#Z#`(O#`#a##`#a#d(O#d#e!La#e#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCY$+mu(vS!i8O'f,UOY(OZr(Ors%}sw(Owx$'|x{(O{|!Nb|}(O}!O!Nb!O!P#:{!P!Q(O!Q![$)P![!c(O!c!g$)P!g!h$+d!h!i$)P!i!n(O!n!o##`!o!r(O!r!s!La!s!w(O!w!x##`!x#O(O#O#P&f#P#T(O#T#X$)P#X#Y$+d#Y#Z$)P#Z#`(O#`#a##`#a#d(O#d#e!La#e#i(O#i#j##`#j;'S(O;'S;=`(o<%lO(OCj$.]u)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx$'|x{$e{|#'Q|}$e}!O#'Q!O!P#B}!P!Q$e!Q![$%g![!c$e!c!g$%g!g!h$.Q!h!i$%g!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#T$e#T#X$%g#X#Y$.Q#Y#Z$%g#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j;'S$e;'S;=`(u<%lO$eCj$0yc)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!O$e!O!P#Mq!P!Q$e!Q!R$2U!R![$%g![!c$e!c!i$%g!i#O$e#O#P&f#P#T$e#T#Z$%g#Z;'S$e;'S;=`(u<%lO$eCj$2av)c`(vS!i8O'f,UOY$eZr$ers%^sw$ewx$'|x!O$e!O!P#B}!P!Q$e!Q![$%g![!c$e!c!g$%g!g!h$.Q!h!i$%g!i!n$e!n!o#*Y!o!r$e!r!s#$w!s!w$e!w!x#*Y!x#O$e#O#P&f#P#T$e#T#U$%g#U#V$%g#V#X$%g#X#Y$.Q#Y#Z$%g#Z#`$e#`#a#*Y#a#d$e#d#e#$w#e#i$e#i#j#*Y#j#l$e#l#m$$[#m;'S$e;'S;=`(u<%lO$eGz$5S[({9b)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox![$e![!]$5x!]#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eFh$6TYm:|)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eCj$7OY)_8O)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eM^$7{_q8O%]#t)c`(vS'f,UOY$8zYZ$9|Zr$8zrs$:ksw$8zwx$Jax!^$8z!^!_$MX!_!`% f!`!a%#m!a#O$8z#O#P$<r#P;'S$8z;'S;=`$MR<%lO$8z3h$9T])c`(vS'f,UOY$8zYZ$9|Zr$8zrs$:ksw$8zwx$Jax!`$8z!`!a$LU!a#O$8z#O#P$<r#P;'S$8z;'S;=`$MR<%lO$8z!b$:PTO!`$9|!`!a$:`!a;'S$9|;'S;=`$:e<%lO$9|!b$:eO$W!b!b$:hP;=`<%l$9|3d$:rZ)c`'f,UOY$:kYZ$9|Zw$:kwx$;ex!`$:k!`!a$If!a#O$:k#O#P$<r#P;'S$:k;'S;=`$JZ<%lO$:k3S$;jX'f,UOY$;eYZ$9|Z!`$;e!`!a$<V!a#O$;e#O#P$<r#P;'S$;e;'S;=`$AY<%lO$;e3S$<`U$W!bY&j'f,UOY%}Z#O%}#O#P&f#P;'S%};'S;=`'r<%lO%}3S$<w['f,UOY$;eYZ$;eZ]$;e]^$=m^!`$;e!`!a$A`!a#O$;e#O#P$HO#P;'S$;e;'S;=`$Hv;=`<%l$F[<%lO$;e3S$=rX'f,UOY$;eYZ$>_Z!`$;e!`!a$<V!a#O$;e#O#P$<r#P;'S$;e;'S;=`$AY<%lO$;e-h$>dX'f,UOY$>_YZ$9|Z!`$>_!`!a$?P!a#O$>_#O#P$?j#P;'S$>_;'S;=`$AS<%lO$>_-h$?WU$W!b'f,UOY%}Z#O%}#O#P&f#P;'S%};'S;=`'r<%lO%}-h$?oZ'f,UOY$>_YZ$>_Z]$>_]^$@b^!`$>_!`!a$?P!a#O$>_#O#P$?j#P;'S$>_;'S;=`$AS<%lO$>_-h$@gX'f,UOY$>_YZ$>_Z!`$>_!`!a$?P!a#O$>_#O#P$?j#P;'S$>_;'S;=`$AS<%lO$>_-h$AVP;=`<%l$>_3S$A]P;=`<%l$;e3S$AgW$W!b'f,UOY$BPZ!`$BP!`!a$Bn!a#O$BP#O#P$CX#P;'S$BP;'S;=`$Dn<%lO$BP1p$BUW'f,UOY$BPZ!`$BP!`!a$Bn!a#O$BP#O#P$CX#P;'S$BP;'S;=`$Dn<%lO$BP1p$BuUY&j'f,UOY%}Z#O%}#O#P&f#P;'S%};'S;=`'r<%lO%}1p$C^Y'f,UOY$BPYZ$BPZ]$BP]^$C|^#O$BP#O#P$Dt#P;'S$BP;'S;=`$El;=`<%l$F[<%lO$BP1p$DRX'f,UOY$BPYZ%}Z!`$BP!`!a$Bn!a#O$BP#O#P$CX#P;'S$BP;'S;=`$Dn<%lO$BP1p$DqP;=`<%l$BP1p$DyZ'f,UOY$BPYZ%}Z]$BP]^$C|^!`$BP!`!a$Bn!a#O$BP#O#P$CX#P;'S$BP;'S;=`$Dn<%lO$BP1p$EoXOY$F[Z!`$F[!`!a$Fw!a#O$F[#O#P$F|#P;'S$F[;'S;=`$Gx;=`<%l$BP<%lO$F[&j$F_WOY$F[Z!`$F[!`!a$Fw!a#O$F[#O#P$F|#P;'S$F[;'S;=`$Gx<%lO$F[&j$F|OY&j&j$GPRO;'S$F[;'S;=`$GY;=`O$F[&j$G]XOY$F[Z!`$F[!`!a$Fw!a#O$F[#O#P$F|#P;'S$F[;'S;=`$Gx;=`<%l$F[<%lO$F[&j$G{P;=`<%l$F[3S$HTZ'f,UOY$;eYZ$>_Z]$;e]^$=m^!`$;e!`!a$<V!a#O$;e#O#P$<r#P;'S$;e;'S;=`$AY<%lO$;e3S$HyXOY$F[Z!`$F[!`!a$Fw!a#O$F[#O#P$F|#P;'S$F[;'S;=`$Gx;=`<%l$;e<%lO$F[3d$IqW$W!bY&j)c`'f,UOY%^Zw%^wx%}x#O%^#O#P&f#P;'S%^;'S;=`'x<%lO%^3d$J^P;=`<%l$:k3W$JhZ(vS'f,UOY$JaYZ$9|Zr$Jars$;es!`$Ja!`!a$KZ!a#O$Ja#O#P$<r#P;'S$Ja;'S;=`$LO<%lO$Ja3W$KfW$W!bY&j(vS'f,UOY(OZr(Ors%}s#O(O#O#P&f#P;'S(O;'S;=`(o<%lO(O3W$LRP;=`<%l$Ja3h$LcY$W!bY&j)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$e3h$MUP;=`<%l$8zM^$Mf^)c`(vS%[#t!f8O'f,UOY$8zYZ$9|Zr$8zrs$:ksw$8zwx$Jax!_$8z!_!`$Nb!`!a$LU!a#O$8z#O#P$<r#P;'S$8z;'S;=`$MR<%lO$8zM^$Nm]!g:t)c`(vS'f,UOY$8zYZ$9|Zr$8zrs$:ksw$8zwx$Jax!`$8z!`!a$LU!a#O$8z#O#P$<r#P;'S$8z;'S;=`$MR<%lO$8zM^% s]%]#t!b8O)c`(vS'f,UOY$8zYZ$9|Zr$8zrs$:ksw$8zwx$Jax!`$8z!`!a%!l!a#O$8z#O#P$<r#P;'S$8z;'S;=`$MR<%lO$8zM^%!}Y%]#t!b8O$W!bY&j)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$e2U%#xYY&j)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`%$s[)p#v)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!_$e!_!`0Q!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`%%v]%]#t)c`(vS!d8O'f,UOY$eZr$ers%^sw$ewx(Ox!_$e!_!`%&o!`!a%'l!a#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`%&|Y%]#t!b8O)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`%'y[)c`(vS%[#t!f8O'f,UOY$eZr$ers%^sw$ewx(Ox!_$e!_!`!8g!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$e,l%(zY(zQ)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eMf%)yb)c`)OW(vS!R7|(w*t'f,UOY$eZr$ers%^sw$ewx(Ox!Q$e!Q![%)j![!c$e!c!}%)j!}#O$e#O#P&f#P#R$e#R#S%)j#S#T$e#T#o%)j#o;'S$e;'S;=`(u<%lO$eMf%+bb)c`)OW(vS!R7|(w*t'f,UOY$eZr$ers%,jsw$ewx%-]x!Q$e!Q![%)j![!c$e!c!}%)j!}#O$e#O#P&f#P#R$e#R#S%)j#S#T$e#T#o%)j#o;'S$e;'S;=`(u<%lO$eIQ%,sW)c`(u=j'f,UOY%^Zw%^wx%}x#O%^#O#P&f#P;'S%^;'S;=`'x<%lO%^CY%-fW(vS)b8O'f,UOY(OZr(Ors%}s#O(O#O#P&f#P;'S(O;'S;=`(o<%lO(OF`%.ZZ!V:t)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox!}$e!}#O%.|#O#P&f#P;'S$e;'S;=`(u<%lO$e,l%/XY)VQ)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eGz%/|a'f,UOY%1RYZ%1lZ]%1R]^%2k^!Q%1R!Q![%3X![!w%1R!w!x%4i!x#O%1R#O#P%;o#P#i%1R#i#j%8T#j#l%1R#l#m%<c#m;'S%1R;'S;=`%?U<%lO%1R,j%1YUXd'f,UOY%}Z#O%}#O#P&f#P;'S%};'S;=`'r<%lO%}Gz%1u[Xd(o<`'f,UOX%}XY-OYZ*[Z]%}]^-O^p%}pq-Oq#O%}#O#P,^#P;'S%};'S;=`'r<%lO%}Gz%2rVXd'f,UOY%}YZ-OZ#O%}#O#P&f#P;'S%};'S;=`'r<%lO%},j%3`WXd'f,UOY%}Z!Q%}!Q![%3x![#O%}#O#P&f#P;'S%};'S;=`'r<%lO%},j%4PWXd'f,UOY%}Z!Q%}!Q![%1R![#O%}#O#P&f#P;'S%};'S;=`'r<%lO%},j%4n['f,UOY%}Z!Q%}!Q![%5d![!c%}!c!i%5d!i#O%}#O#P&f#P#T%}#T#Z%5d#Z;'S%};'S;=`'r<%lO%},j%5i['f,UOY%}Z!Q%}!Q![%6_![!c%}!c!i%6_!i#O%}#O#P&f#P#T%}#T#Z%6_#Z;'S%};'S;=`'r<%lO%},j%6d['f,UOY%}Z!Q%}!Q![%7Y![!c%}!c!i%7Y!i#O%}#O#P&f#P#T%}#T#Z%7Y#Z;'S%};'S;=`'r<%lO%},j%7_['f,UOY%}Z!Q%}!Q![%8T![!c%}!c!i%8T!i#O%}#O#P&f#P#T%}#T#Z%8T#Z;'S%};'S;=`'r<%lO%},j%8Y['f,UOY%}Z!Q%}!Q![%9O![!c%}!c!i%9O!i#O%}#O#P&f#P#T%}#T#Z%9O#Z;'S%};'S;=`'r<%lO%},j%9T['f,UOY%}Z!Q%}!Q![%9y![!c%}!c!i%9y!i#O%}#O#P&f#P#T%}#T#Z%9y#Z;'S%};'S;=`'r<%lO%},j%:O['f,UOY%}Z!Q%}!Q![%:t![!c%}!c!i%:t!i#O%}#O#P&f#P#T%}#T#Z%:t#Z;'S%};'S;=`'r<%lO%},j%:y['f,UOY%}Z!Q%}!Q![%1R![!c%}!c!i%1R!i#O%}#O#P&f#P#T%}#T#Z%1R#Z;'S%};'S;=`'r<%lO%},j%;vXXd'f,UOY%}YZ%}Z]%}]^'W^#O%}#O#P&f#P;'S%};'S;=`'r<%lO%},j%<h['f,UOY%}Z!Q%}!Q![%=^![!c%}!c!i%=^!i#O%}#O#P&f#P#T%}#T#Z%=^#Z;'S%};'S;=`'r<%lO%},j%=c['f,UOY%}Z!Q%}!Q![%>X![!c%}!c!i%>X!i#O%}#O#P&f#P#T%}#T#Z%>X#Z;'S%};'S;=`'r<%lO%},j%>`[Xd'f,UOY%}Z!Q%}!Q![%>X![!c%}!c!i%>X!i#O%}#O#P&f#P#T%}#T#Z%>X#Z;'S%};'S;=`'r<%lO%},j%?XP;=`<%l%1RCr%?gZ!W7^)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P#Q%@Y#Q;'S$e;'S;=`(u<%lO$e-d%@eY)Ux)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`%Ab[)c`(vS%[#t'f,U!_8OOY$eZr$ers%^sw$ewx(Ox!_$e!_!`!8g!`#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eMf%Bgd)c`)OW(vS!R7|(w*t'f,UOY$eZr$ers%,jsw$ewx%-]x!Q$e!Q!Y%)j!Y!Z%+R!Z![%)j![!c$e!c!}%)j!}#O$e#O#P&f#P#R$e#R#S%)j#S#T$e#T#o%)j#o;'S$e;'S;=`(u<%lO$eCj%DQY!T8O)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$eF`%D}^)c`(vS%[#t'f,U!^8OOY$eZr$ers%^sw$ewx(Ox!_$e!_!`!8g!`#O$e#O#P&f#P#p$e#p#q%Ey#q;'S$e;'S;=`(u<%lO$eF`%FWY)Z8O%^#t)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$e-^%GRY!Ur)c`(vS'f,UOY$eZr$ers%^sw$ewx(Ox#O$e#O#P&f#P;'S$e;'S;=`(u<%lO$e/j%HOc)c`(vS%[#t'RQ'f,UOX$eXY%IZZp$epq%IZqr$ers%^sw$ewx(Ox!c$e!c!}%Jo!}#O$e#O#P&f#P#R$e#R#S%Jo#S#T$e#T#o%Jo#o;'S$e;'S;=`(u<%lO$e,t%Idc)c`(vS'f,UOX$eXY%IZZp$epq%IZqr$ers%^sw$ewx(Ox!c$e!c!}%Jo!}#O$e#O#P&f#P#R$e#R#S%Jo#S#T$e#T#o%Jo#o;'S$e;'S;=`(u<%lO$e,t%Jzb)c`(vSeY'f,UOY$eZr$ers%^sw$ewx(Ox!Q$e!Q![%Jo![!c$e!c!}%Jo!}#O$e#O#P&f#P#R$e#R#S%Jo#S#T$e#T#o%Jo#o;'S$e;'S;=`(u<%lO$e", | |
| 4047 | tokenizers: [rawString, fallback, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, new LocalTokenGroup("j~RQYZXz{^~^O(r~~aP!P!Qd~iO(s~~", 25, 355)], | |
| 4048 | topRules: { "Program": [0, 307] }, | |
| 4049 | dynamicPrecedences: { "17": 1, "65": 1, "87": 1, "94": 1, "119": 1, "184": 1, "187": -10, "240": -10, "241": 1, "244": -1, "246": -10, "247": 1, "262": -1, "267": 2, "268": 2, "306": -10, "370": 3, "423": 1, "424": 3, "425": 1, "426": 1 }, | |
| 4050 | specialized: [{ term: 361, get: (value) => spec_identifier[value] || -1 }, { term: 33, get: (value) => spec_[value] || -1 }, { term: 66, get: (value) => spec_templateArgsEnd[value] || -1 }, { term: 368, get: (value) => spec_scopedIdentifier[value] || -1 }], | |
| 4051 | tokenPrec: 24916 | |
| 4052 | }); | |
| 4053 | export { | |
| 4054 | parser | |
| 4055 | }; |
| … | … | @@ -0,0 +1,21 @@ |
| 1 | MIT License | |
| 2 | ||
| 3 | Copyright (c) 2023 GDQuest | |
| 4 | ||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 | of this software and associated documentation files (the "Software"), to deal | |
| 7 | in the Software without restriction, including without limitation the rights | |
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 9 | copies of the Software, and to permit persons to whom the Software is | |
| 10 | furnished to do so, subject to the following conditions: | |
| 11 | ||
| 12 | The above copyright notice and this permission notice shall be included in all | |
| 13 | copies or substantial portions of the Software. | |
| 14 | ||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 21 | SOFTWARE. |
| … | … | @@ -0,0 +1,31 @@ |
| 1 | # Vendored: @gdquest/lezer-gdscript | |
| 2 | ||
| 3 | - **Source**: https://www.npmjs.com/package/@gdquest/lezer-gdscript | |
| 4 | - **Version**: 0.1.2 | |
| 5 | - **License**: MIT (see LICENSE) | |
| 6 | - **Author**: GDQuest / Adam Scott | |
| 7 | - **Bundled**: Grammar + Lezer runtime (@lezer/lr + @lezer/common + @lezer/highlight) | |
| 8 | - **Bundle size**: 136 KB | |
| 9 | ||
| 10 | ## Usage | |
| 11 | ||
| 12 | ```js | |
| 13 | import { parser } from '../vendor/lezer-gdscript/lezer-gdscript.mjs' | |
| 14 | const tree = parser.parse(source) | |
| 15 | ``` | |
| 16 | ||
| 17 | ## Bundled With | |
| 18 | ||
| 19 | - @lezer/lr (LR parser runtime, by Marijn Haverbeke, MIT) | |
| 20 | - @lezer/common (tree types, by Marijn Haverbeke, MIT) | |
| 21 | - @lezer/highlight (style tags, by Marijn Haverbeke, MIT) | |
| 22 | ||
| 23 | ## Regeneration | |
| 24 | ||
| 25 | ```sh | |
| 26 | cd /tmp && mkdir -p codetree-vendor && cd codetree-vendor | |
| 27 | npm init -y && echo '{"type":"module"}' > package.json | |
| 28 | npm install @gdquest/lezer-gdscript @lezer/lr @lezer/common @lezer/highlight esbuild | |
| 29 | echo "export { parser } from '@gdquest/lezer-gdscript'" > bundle.js | |
| 30 | ./node_modules/.bin/esbuild bundle.js --bundle --format=esm --platform=neutral --outfile=lezer-gdscript.mjs | |
| 31 | ``` |
| … | … | @@ -0,0 +1,4105 @@ |
| 1 | // node_modules/@lezer/common/dist/index.js | |
| 2 | var DefaultBufferLength = 1024; | |
| 3 | var nextPropID = 0; | |
| 4 | var Range = class { | |
| 5 | constructor(from, to) { | |
| 6 | this.from = from; | |
| 7 | this.to = to; | |
| 8 | } | |
| 9 | }; | |
| 10 | var NodeProp = class { | |
| 11 | /** | |
| 12 | Create a new node prop type. | |
| 13 | */ | |
| 14 | constructor(config = {}) { | |
| 15 | this.id = nextPropID++; | |
| 16 | this.perNode = !!config.perNode; | |
| 17 | this.deserialize = config.deserialize || (() => { | |
| 18 | throw new Error("This node type doesn't define a deserialize function"); | |
| 19 | }); | |
| 20 | this.combine = config.combine || null; | |
| 21 | } | |
| 22 | /** | |
| 23 | This is meant to be used with | |
| 24 | [`NodeSet.extend`](#common.NodeSet.extend) or | |
| 25 | [`LRParser.configure`](#lr.ParserConfig.props) to compute | |
| 26 | prop values for each node type in the set. Takes a [match | |
| 27 | object](#common.NodeType^match) or function that returns undefined | |
| 28 | if the node type doesn't get this prop, and the prop's value if | |
| 29 | it does. | |
| 30 | */ | |
| 31 | add(match) { | |
| 32 | if (this.perNode) | |
| 33 | throw new RangeError("Can't add per-node props to node types"); | |
| 34 | if (typeof match != "function") | |
| 35 | match = NodeType.match(match); | |
| 36 | return (type) => { | |
| 37 | let result = match(type); | |
| 38 | return result === void 0 ? null : [this, result]; | |
| 39 | }; | |
| 40 | } | |
| 41 | }; | |
| 42 | NodeProp.closedBy = new NodeProp({ deserialize: (str) => str.split(" ") }); | |
| 43 | NodeProp.openedBy = new NodeProp({ deserialize: (str) => str.split(" ") }); | |
| 44 | NodeProp.group = new NodeProp({ deserialize: (str) => str.split(" ") }); | |
| 45 | NodeProp.isolate = new NodeProp({ deserialize: (value) => { | |
| 46 | if (value && value != "rtl" && value != "ltr" && value != "auto") | |
| 47 | throw new RangeError("Invalid value for isolate: " + value); | |
| 48 | return value || "auto"; | |
| 49 | } }); | |
| 50 | NodeProp.contextHash = new NodeProp({ perNode: true }); | |
| 51 | NodeProp.lookAhead = new NodeProp({ perNode: true }); | |
| 52 | NodeProp.mounted = new NodeProp({ perNode: true }); | |
| 53 | var MountedTree = class { | |
| 54 | constructor(tree, overlay, parser2, bracketed2 = false) { | |
| 55 | this.tree = tree; | |
| 56 | this.overlay = overlay; | |
| 57 | this.parser = parser2; | |
| 58 | this.bracketed = bracketed2; | |
| 59 | } | |
| 60 | /** | |
| 61 | @internal | |
| 62 | */ | |
| 63 | static get(tree) { | |
| 64 | return tree && tree.props && tree.props[NodeProp.mounted.id]; | |
| 65 | } | |
| 66 | }; | |
| 67 | var noProps = /* @__PURE__ */ Object.create(null); | |
| 68 | var NodeType = class _NodeType { | |
| 69 | /** | |
| 70 | @internal | |
| 71 | */ | |
| 72 | constructor(name2, props, id2, flags = 0) { | |
| 73 | this.name = name2; | |
| 74 | this.props = props; | |
| 75 | this.id = id2; | |
| 76 | this.flags = flags; | |
| 77 | } | |
| 78 | /** | |
| 79 | Define a node type. | |
| 80 | */ | |
| 81 | static define(spec) { | |
| 82 | let props = spec.props && spec.props.length ? /* @__PURE__ */ Object.create(null) : noProps; | |
| 83 | let flags = (spec.top ? 1 : 0) | (spec.skipped ? 2 : 0) | (spec.error ? 4 : 0) | (spec.name == null ? 8 : 0); | |
| 84 | let type = new _NodeType(spec.name || "", props, spec.id, flags); | |
| 85 | if (spec.props) | |
| 86 | for (let src of spec.props) { | |
| 87 | if (!Array.isArray(src)) | |
| 88 | src = src(type); | |
| 89 | if (src) { | |
| 90 | if (src[0].perNode) | |
| 91 | throw new RangeError("Can't store a per-node prop on a node type"); | |
| 92 | props[src[0].id] = src[1]; | |
| 93 | } | |
| 94 | } | |
| 95 | return type; | |
| 96 | } | |
| 97 | /** | |
| 98 | Retrieves a node prop for this type. Will return `undefined` if | |
| 99 | the prop isn't present on this node. | |
| 100 | */ | |
| 101 | prop(prop) { | |
| 102 | return this.props[prop.id]; | |
| 103 | } | |
| 104 | /** | |
| 105 | True when this is the top node of a grammar. | |
| 106 | */ | |
| 107 | get isTop() { | |
| 108 | return (this.flags & 1) > 0; | |
| 109 | } | |
| 110 | /** | |
| 111 | True when this node is produced by a skip rule. | |
| 112 | */ | |
| 113 | get isSkipped() { | |
| 114 | return (this.flags & 2) > 0; | |
| 115 | } | |
| 116 | /** | |
| 117 | Indicates whether this is an error node. | |
| 118 | */ | |
| 119 | get isError() { | |
| 120 | return (this.flags & 4) > 0; | |
| 121 | } | |
| 122 | /** | |
| 123 | When true, this node type doesn't correspond to a user-declared | |
| 124 | named node, for example because it is used to cache repetition. | |
| 125 | */ | |
| 126 | get isAnonymous() { | |
| 127 | return (this.flags & 8) > 0; | |
| 128 | } | |
| 129 | /** | |
| 130 | Returns true when this node's name or one of its | |
| 131 | [groups](#common.NodeProp^group) matches the given string. | |
| 132 | */ | |
| 133 | is(name2) { | |
| 134 | if (typeof name2 == "string") { | |
| 135 | if (this.name == name2) | |
| 136 | return true; | |
| 137 | let group = this.prop(NodeProp.group); | |
| 138 | return group ? group.indexOf(name2) > -1 : false; | |
| 139 | } | |
| 140 | return this.id == name2; | |
| 141 | } | |
| 142 | /** | |
| 143 | Create a function from node types to arbitrary values by | |
| 144 | specifying an object whose property names are node or | |
| 145 | [group](#common.NodeProp^group) names. Often useful with | |
| 146 | [`NodeProp.add`](#common.NodeProp.add). You can put multiple | |
| 147 | names, separated by spaces, in a single property name to map | |
| 148 | multiple node names to a single value. | |
| 149 | */ | |
| 150 | static match(map) { | |
| 151 | let direct = /* @__PURE__ */ Object.create(null); | |
| 152 | for (let prop in map) | |
| 153 | for (let name2 of prop.split(" ")) | |
| 154 | direct[name2] = map[prop]; | |
| 155 | return (node) => { | |
| 156 | for (let groups = node.prop(NodeProp.group), i = -1; i < (groups ? groups.length : 0); i++) { | |
| 157 | let found = direct[i < 0 ? node.name : groups[i]]; | |
| 158 | if (found) | |
| 159 | return found; | |
| 160 | } | |
| 161 | }; | |
| 162 | } | |
| 163 | }; | |
| 164 | NodeType.none = new NodeType( | |
| 165 | "", | |
| 166 | /* @__PURE__ */ Object.create(null), | |
| 167 | 0, | |
| 168 | 8 | |
| 169 | /* NodeFlag.Anonymous */ | |
| 170 | ); | |
| 171 | var NodeSet = class _NodeSet { | |
| 172 | /** | |
| 173 | Create a set with the given types. The `id` property of each | |
| 174 | type should correspond to its position within the array. | |
| 175 | */ | |
| 176 | constructor(types) { | |
| 177 | this.types = types; | |
| 178 | for (let i = 0; i < types.length; i++) | |
| 179 | if (types[i].id != i) | |
| 180 | throw new RangeError("Node type ids should correspond to array positions when creating a node set"); | |
| 181 | } | |
| 182 | /** | |
| 183 | Create a copy of this set with some node properties added. The | |
| 184 | arguments to this method can be created with | |
| 185 | [`NodeProp.add`](#common.NodeProp.add). | |
| 186 | */ | |
| 187 | extend(...props) { | |
| 188 | let newTypes = []; | |
| 189 | for (let type of this.types) { | |
| 190 | let newProps = null; | |
| 191 | for (let source of props) { | |
| 192 | let add = source(type); | |
| 193 | if (add) { | |
| 194 | if (!newProps) | |
| 195 | newProps = Object.assign({}, type.props); | |
| 196 | let value = add[1], prop = add[0]; | |
| 197 | if (prop.combine && prop.id in newProps) | |
| 198 | value = prop.combine(newProps[prop.id], value); | |
| 199 | newProps[prop.id] = value; | |
| 200 | } | |
| 201 | } | |
| 202 | newTypes.push(newProps ? new NodeType(type.name, newProps, type.id, type.flags) : type); | |
| 203 | } | |
| 204 | return new _NodeSet(newTypes); | |
| 205 | } | |
| 206 | }; | |
| 207 | var CachedNode = /* @__PURE__ */ new WeakMap(); | |
| 208 | var CachedInnerNode = /* @__PURE__ */ new WeakMap(); | |
| 209 | var IterMode; | |
| 210 | (function(IterMode2) { | |
| 211 | IterMode2[IterMode2["ExcludeBuffers"] = 1] = "ExcludeBuffers"; | |
| 212 | IterMode2[IterMode2["IncludeAnonymous"] = 2] = "IncludeAnonymous"; | |
| 213 | IterMode2[IterMode2["IgnoreMounts"] = 4] = "IgnoreMounts"; | |
| 214 | IterMode2[IterMode2["IgnoreOverlays"] = 8] = "IgnoreOverlays"; | |
| 215 | IterMode2[IterMode2["EnterBracketed"] = 16] = "EnterBracketed"; | |
| 216 | })(IterMode || (IterMode = {})); | |
| 217 | var Tree = class _Tree { | |
| 218 | /** | |
| 219 | Construct a new tree. See also [`Tree.build`](#common.Tree^build). | |
| 220 | */ | |
| 221 | constructor(type, children, positions, length, props) { | |
| 222 | this.type = type; | |
| 223 | this.children = children; | |
| 224 | this.positions = positions; | |
| 225 | this.length = length; | |
| 226 | this.props = null; | |
| 227 | if (props && props.length) { | |
| 228 | this.props = /* @__PURE__ */ Object.create(null); | |
| 229 | for (let [prop, value] of props) | |
| 230 | this.props[typeof prop == "number" ? prop : prop.id] = value; | |
| 231 | } | |
| 232 | } | |
| 233 | /** | |
| 234 | @internal | |
| 235 | */ | |
| 236 | toString() { | |
| 237 | let mounted = MountedTree.get(this); | |
| 238 | if (mounted && !mounted.overlay) | |
| 239 | return mounted.tree.toString(); | |
| 240 | let children = ""; | |
| 241 | for (let ch of this.children) { | |
| 242 | let str = ch.toString(); | |
| 243 | if (str) { | |
| 244 | if (children) | |
| 245 | children += ","; | |
| 246 | children += str; | |
| 247 | } | |
| 248 | } | |
| 249 | return !this.type.name ? children : (/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) + (children.length ? "(" + children + ")" : ""); | |
| 250 | } | |
| 251 | /** | |
| 252 | Get a [tree cursor](#common.TreeCursor) positioned at the top of | |
| 253 | the tree. Mode can be used to [control](#common.IterMode) which | |
| 254 | nodes the cursor visits. | |
| 255 | */ | |
| 256 | cursor(mode = 0) { | |
| 257 | return new TreeCursor(this.topNode, mode); | |
| 258 | } | |
| 259 | /** | |
| 260 | Get a [tree cursor](#common.TreeCursor) pointing into this tree | |
| 261 | at the given position and side (see | |
| 262 | [`moveTo`](#common.TreeCursor.moveTo). | |
| 263 | */ | |
| 264 | cursorAt(pos, side = 0, mode = 0) { | |
| 265 | let scope = CachedNode.get(this) || this.topNode; | |
| 266 | let cursor = new TreeCursor(scope); | |
| 267 | cursor.moveTo(pos, side); | |
| 268 | CachedNode.set(this, cursor._tree); | |
| 269 | return cursor; | |
| 270 | } | |
| 271 | /** | |
| 272 | Get a [syntax node](#common.SyntaxNode) object for the top of the | |
| 273 | tree. | |
| 274 | */ | |
| 275 | get topNode() { | |
| 276 | return new TreeNode(this, 0, 0, null); | |
| 277 | } | |
| 278 | /** | |
| 279 | Get the [syntax node](#common.SyntaxNode) at the given position. | |
| 280 | If `side` is -1, this will move into nodes that end at the | |
| 281 | position. If 1, it'll move into nodes that start at the | |
| 282 | position. With 0, it'll only enter nodes that cover the position | |
| 283 | from both sides. | |
| 284 | ||
| 285 | Note that this will not enter | |
| 286 | [overlays](#common.MountedTree.overlay), and you often want | |
| 287 | [`resolveInner`](#common.Tree.resolveInner) instead. | |
| 288 | */ | |
| 289 | resolve(pos, side = 0) { | |
| 290 | let node = resolveNode(CachedNode.get(this) || this.topNode, pos, side, false); | |
| 291 | CachedNode.set(this, node); | |
| 292 | return node; | |
| 293 | } | |
| 294 | /** | |
| 295 | Like [`resolve`](#common.Tree.resolve), but will enter | |
| 296 | [overlaid](#common.MountedTree.overlay) nodes, producing a syntax node | |
| 297 | pointing into the innermost overlaid tree at the given position | |
| 298 | (with parent links going through all parent structure, including | |
| 299 | the host trees). | |
| 300 | */ | |
| 301 | resolveInner(pos, side = 0) { | |
| 302 | let node = resolveNode(CachedInnerNode.get(this) || this.topNode, pos, side, true); | |
| 303 | CachedInnerNode.set(this, node); | |
| 304 | return node; | |
| 305 | } | |
| 306 | /** | |
| 307 | In some situations, it can be useful to iterate through all | |
| 308 | nodes around a position, including those in overlays that don't | |
| 309 | directly cover the position. This method gives you an iterator | |
| 310 | that will produce all nodes, from small to big, around the given | |
| 311 | position. | |
| 312 | */ | |
| 313 | resolveStack(pos, side = 0) { | |
| 314 | return stackIterator(this, pos, side); | |
| 315 | } | |
| 316 | /** | |
| 317 | Iterate over the tree and its children, calling `enter` for any | |
| 318 | node that touches the `from`/`to` region (if given) before | |
| 319 | running over such a node's children, and `leave` (if given) when | |
| 320 | leaving the node. When `enter` returns `false`, that node will | |
| 321 | not have its children iterated over (or `leave` called). | |
| 322 | */ | |
| 323 | iterate(spec) { | |
| 324 | let { enter, leave, from = 0, to = this.length } = spec; | |
| 325 | let mode = spec.mode || 0, anon = (mode & IterMode.IncludeAnonymous) > 0; | |
| 326 | for (let c = this.cursor(mode | IterMode.IncludeAnonymous); ; ) { | |
| 327 | let entered = false; | |
| 328 | if (c.from <= to && c.to >= from && (!anon && c.type.isAnonymous || enter(c) !== false)) { | |
| 329 | if (c.firstChild()) | |
| 330 | continue; | |
| 331 | entered = true; | |
| 332 | } | |
| 333 | for (; ; ) { | |
| 334 | if (entered && leave && (anon || !c.type.isAnonymous)) | |
| 335 | leave(c); | |
| 336 | if (c.nextSibling()) | |
| 337 | break; | |
| 338 | if (!c.parent()) | |
| 339 | return; | |
| 340 | entered = true; | |
| 341 | } | |
| 342 | } | |
| 343 | } | |
| 344 | /** | |
| 345 | Get the value of the given [node prop](#common.NodeProp) for this | |
| 346 | node. Works with both per-node and per-type props. | |
| 347 | */ | |
| 348 | prop(prop) { | |
| 349 | return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : void 0; | |
| 350 | } | |
| 351 | /** | |
| 352 | Returns the node's [per-node props](#common.NodeProp.perNode) in a | |
| 353 | format that can be passed to the [`Tree`](#common.Tree) | |
| 354 | constructor. | |
| 355 | */ | |
| 356 | get propValues() { | |
| 357 | let result = []; | |
| 358 | if (this.props) | |
| 359 | for (let id2 in this.props) | |
| 360 | result.push([+id2, this.props[id2]]); | |
| 361 | return result; | |
| 362 | } | |
| 363 | /** | |
| 364 | Balance the direct children of this tree, producing a copy of | |
| 365 | which may have children grouped into subtrees with type | |
| 366 | [`NodeType.none`](#common.NodeType^none). | |
| 367 | */ | |
| 368 | balance(config = {}) { | |
| 369 | return this.children.length <= 8 ? this : balanceRange(NodeType.none, this.children, this.positions, 0, this.children.length, 0, this.length, (children, positions, length) => new _Tree(this.type, children, positions, length, this.propValues), config.makeTree || ((children, positions, length) => new _Tree(NodeType.none, children, positions, length))); | |
| 370 | } | |
| 371 | /** | |
| 372 | Build a tree from a postfix-ordered buffer of node information, | |
| 373 | or a cursor over such a buffer. | |
| 374 | */ | |
| 375 | static build(data) { | |
| 376 | return buildTree(data); | |
| 377 | } | |
| 378 | }; | |
| 379 | Tree.empty = new Tree(NodeType.none, [], [], 0); | |
| 380 | var FlatBufferCursor = class _FlatBufferCursor { | |
| 381 | constructor(buffer, index) { | |
| 382 | this.buffer = buffer; | |
| 383 | this.index = index; | |
| 384 | } | |
| 385 | get id() { | |
| 386 | return this.buffer[this.index - 4]; | |
| 387 | } | |
| 388 | get start() { | |
| 389 | return this.buffer[this.index - 3]; | |
| 390 | } | |
| 391 | get end() { | |
| 392 | return this.buffer[this.index - 2]; | |
| 393 | } | |
| 394 | get size() { | |
| 395 | return this.buffer[this.index - 1]; | |
| 396 | } | |
| 397 | get pos() { | |
| 398 | return this.index; | |
| 399 | } | |
| 400 | next() { | |
| 401 | this.index -= 4; | |
| 402 | } | |
| 403 | fork() { | |
| 404 | return new _FlatBufferCursor(this.buffer, this.index); | |
| 405 | } | |
| 406 | }; | |
| 407 | var TreeBuffer = class _TreeBuffer { | |
| 408 | /** | |
| 409 | Create a tree buffer. | |
| 410 | */ | |
| 411 | constructor(buffer, length, set) { | |
| 412 | this.buffer = buffer; | |
| 413 | this.length = length; | |
| 414 | this.set = set; | |
| 415 | } | |
| 416 | /** | |
| 417 | @internal | |
| 418 | */ | |
| 419 | get type() { | |
| 420 | return NodeType.none; | |
| 421 | } | |
| 422 | /** | |
| 423 | @internal | |
| 424 | */ | |
| 425 | toString() { | |
| 426 | let result = []; | |
| 427 | for (let index = 0; index < this.buffer.length; ) { | |
| 428 | result.push(this.childString(index)); | |
| 429 | index = this.buffer[index + 3]; | |
| 430 | } | |
| 431 | return result.join(","); | |
| 432 | } | |
| 433 | /** | |
| 434 | @internal | |
| 435 | */ | |
| 436 | childString(index) { | |
| 437 | let id2 = this.buffer[index], endIndex = this.buffer[index + 3]; | |
| 438 | let type = this.set.types[id2], result = type.name; | |
| 439 | if (/\W/.test(result) && !type.isError) | |
| 440 | result = JSON.stringify(result); | |
| 441 | index += 4; | |
| 442 | if (endIndex == index) | |
| 443 | return result; | |
| 444 | let children = []; | |
| 445 | while (index < endIndex) { | |
| 446 | children.push(this.childString(index)); | |
| 447 | index = this.buffer[index + 3]; | |
| 448 | } | |
| 449 | return result + "(" + children.join(",") + ")"; | |
| 450 | } | |
| 451 | /** | |
| 452 | @internal | |
| 453 | */ | |
| 454 | findChild(startIndex, endIndex, dir, pos, side) { | |
| 455 | let { buffer } = this, pick = -1; | |
| 456 | for (let i = startIndex; i != endIndex; i = buffer[i + 3]) { | |
| 457 | if (checkSide(side, pos, buffer[i + 1], buffer[i + 2])) { | |
| 458 | pick = i; | |
| 459 | if (dir > 0) | |
| 460 | break; | |
| 461 | } | |
| 462 | } | |
| 463 | return pick; | |
| 464 | } | |
| 465 | /** | |
| 466 | @internal | |
| 467 | */ | |
| 468 | slice(startI, endI, from) { | |
| 469 | let b = this.buffer; | |
| 470 | let copy = new Uint16Array(endI - startI), len = 0; | |
| 471 | for (let i = startI, j = 0; i < endI; ) { | |
| 472 | copy[j++] = b[i++]; | |
| 473 | copy[j++] = b[i++] - from; | |
| 474 | let to = copy[j++] = b[i++] - from; | |
| 475 | copy[j++] = b[i++] - startI; | |
| 476 | len = Math.max(len, to); | |
| 477 | } | |
| 478 | return new _TreeBuffer(copy, len, this.set); | |
| 479 | } | |
| 480 | }; | |
| 481 | function checkSide(side, pos, from, to) { | |
| 482 | switch (side) { | |
| 483 | case -2: | |
| 484 | return from < pos; | |
| 485 | case -1: | |
| 486 | return to >= pos && from < pos; | |
| 487 | case 0: | |
| 488 | return from < pos && to > pos; | |
| 489 | case 1: | |
| 490 | return from <= pos && to > pos; | |
| 491 | case 2: | |
| 492 | return to > pos; | |
| 493 | case 4: | |
| 494 | return true; | |
| 495 | } | |
| 496 | } | |
| 497 | function resolveNode(node, pos, side, overlays) { | |
| 498 | var _a; | |
| 499 | while (node.from == node.to || (side < 1 ? node.from >= pos : node.from > pos) || (side > -1 ? node.to <= pos : node.to < pos)) { | |
| 500 | let parent = !overlays && node instanceof TreeNode && node.index < 0 ? null : node.parent; | |
| 501 | if (!parent) | |
| 502 | return node; | |
| 503 | node = parent; | |
| 504 | } | |
| 505 | let mode = overlays ? 0 : IterMode.IgnoreOverlays; | |
| 506 | if (overlays) | |
| 507 | for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) { | |
| 508 | if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from) | |
| 509 | node = parent; | |
| 510 | } | |
| 511 | for (; ; ) { | |
| 512 | let inner = node.enter(pos, side, mode); | |
| 513 | if (!inner) | |
| 514 | return node; | |
| 515 | node = inner; | |
| 516 | } | |
| 517 | } | |
| 518 | var BaseNode = class { | |
| 519 | cursor(mode = 0) { | |
| 520 | return new TreeCursor(this, mode); | |
| 521 | } | |
| 522 | getChild(type, before = null, after = null) { | |
| 523 | let r = getChildren(this, type, before, after); | |
| 524 | return r.length ? r[0] : null; | |
| 525 | } | |
| 526 | getChildren(type, before = null, after = null) { | |
| 527 | return getChildren(this, type, before, after); | |
| 528 | } | |
| 529 | resolve(pos, side = 0) { | |
| 530 | return resolveNode(this, pos, side, false); | |
| 531 | } | |
| 532 | resolveInner(pos, side = 0) { | |
| 533 | return resolveNode(this, pos, side, true); | |
| 534 | } | |
| 535 | matchContext(context) { | |
| 536 | return matchNodeContext(this.parent, context); | |
| 537 | } | |
| 538 | enterUnfinishedNodesBefore(pos) { | |
| 539 | let scan = this.childBefore(pos), node = this; | |
| 540 | while (scan) { | |
| 541 | let last = scan.lastChild; | |
| 542 | if (!last || last.to != scan.to) | |
| 543 | break; | |
| 544 | if (last.type.isError && last.from == last.to) { | |
| 545 | node = scan; | |
| 546 | scan = last.prevSibling; | |
| 547 | } else { | |
| 548 | scan = last; | |
| 549 | } | |
| 550 | } | |
| 551 | return node; | |
| 552 | } | |
| 553 | get node() { | |
| 554 | return this; | |
| 555 | } | |
| 556 | get next() { | |
| 557 | return this.parent; | |
| 558 | } | |
| 559 | }; | |
| 560 | var TreeNode = class _TreeNode extends BaseNode { | |
| 561 | constructor(_tree, from, index, _parent) { | |
| 562 | super(); | |
| 563 | this._tree = _tree; | |
| 564 | this.from = from; | |
| 565 | this.index = index; | |
| 566 | this._parent = _parent; | |
| 567 | } | |
| 568 | get type() { | |
| 569 | return this._tree.type; | |
| 570 | } | |
| 571 | get name() { | |
| 572 | return this._tree.type.name; | |
| 573 | } | |
| 574 | get to() { | |
| 575 | return this.from + this._tree.length; | |
| 576 | } | |
| 577 | nextChild(i, dir, pos, side, mode = 0) { | |
| 578 | for (let parent = this; ; ) { | |
| 579 | for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) { | |
| 580 | let next = children[i], start = positions[i] + parent.from, mounted; | |
| 581 | if (!(mode & IterMode.EnterBracketed && next instanceof Tree && (mounted = MountedTree.get(next)) && !mounted.overlay && mounted.bracketed && pos >= start && pos <= start + next.length) && !checkSide(side, pos, start, start + next.length)) | |
| 582 | continue; | |
| 583 | if (next instanceof TreeBuffer) { | |
| 584 | if (mode & IterMode.ExcludeBuffers) | |
| 585 | continue; | |
| 586 | let index = next.findChild(0, next.buffer.length, dir, pos - start, side); | |
| 587 | if (index > -1) | |
| 588 | return new BufferNode(new BufferContext(parent, next, i, start), null, index); | |
| 589 | } else if (mode & IterMode.IncludeAnonymous || (!next.type.isAnonymous || hasChild(next))) { | |
| 590 | let mounted2; | |
| 591 | if (!(mode & IterMode.IgnoreMounts) && (mounted2 = MountedTree.get(next)) && !mounted2.overlay) | |
| 592 | return new _TreeNode(mounted2.tree, start, i, parent); | |
| 593 | let inner = new _TreeNode(next, start, i, parent); | |
| 594 | return mode & IterMode.IncludeAnonymous || !inner.type.isAnonymous ? inner : inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side, mode); | |
| 595 | } | |
| 596 | } | |
| 597 | if (mode & IterMode.IncludeAnonymous || !parent.type.isAnonymous) | |
| 598 | return null; | |
| 599 | if (parent.index >= 0) | |
| 600 | i = parent.index + dir; | |
| 601 | else | |
| 602 | i = dir < 0 ? -1 : parent._parent._tree.children.length; | |
| 603 | parent = parent._parent; | |
| 604 | if (!parent) | |
| 605 | return null; | |
| 606 | } | |
| 607 | } | |
| 608 | get firstChild() { | |
| 609 | return this.nextChild( | |
| 610 | 0, | |
| 611 | 1, | |
| 612 | 0, | |
| 613 | 4 | |
| 614 | /* Side.DontCare */ | |
| 615 | ); | |
| 616 | } | |
| 617 | get lastChild() { | |
| 618 | return this.nextChild( | |
| 619 | this._tree.children.length - 1, | |
| 620 | -1, | |
| 621 | 0, | |
| 622 | 4 | |
| 623 | /* Side.DontCare */ | |
| 624 | ); | |
| 625 | } | |
| 626 | childAfter(pos) { | |
| 627 | return this.nextChild( | |
| 628 | 0, | |
| 629 | 1, | |
| 630 | pos, | |
| 631 | 2 | |
| 632 | /* Side.After */ | |
| 633 | ); | |
| 634 | } | |
| 635 | childBefore(pos) { | |
| 636 | return this.nextChild( | |
| 637 | this._tree.children.length - 1, | |
| 638 | -1, | |
| 639 | pos, | |
| 640 | -2 | |
| 641 | /* Side.Before */ | |
| 642 | ); | |
| 643 | } | |
| 644 | prop(prop) { | |
| 645 | return this._tree.prop(prop); | |
| 646 | } | |
| 647 | enter(pos, side, mode = 0) { | |
| 648 | let mounted; | |
| 649 | if (!(mode & IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) { | |
| 650 | let rPos = pos - this.from, enterBracketed = mode & IterMode.EnterBracketed && mounted.bracketed; | |
| 651 | for (let { from, to } of mounted.overlay) { | |
| 652 | if ((side > 0 || enterBracketed ? from <= rPos : from < rPos) && (side < 0 || enterBracketed ? to >= rPos : to > rPos)) | |
| 653 | return new _TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this); | |
| 654 | } | |
| 655 | } | |
| 656 | return this.nextChild(0, 1, pos, side, mode); | |
| 657 | } | |
| 658 | nextSignificantParent() { | |
| 659 | let val = this; | |
| 660 | while (val.type.isAnonymous && val._parent) | |
| 661 | val = val._parent; | |
| 662 | return val; | |
| 663 | } | |
| 664 | get parent() { | |
| 665 | return this._parent ? this._parent.nextSignificantParent() : null; | |
| 666 | } | |
| 667 | get nextSibling() { | |
| 668 | return this._parent && this.index >= 0 ? this._parent.nextChild( | |
| 669 | this.index + 1, | |
| 670 | 1, | |
| 671 | 0, | |
| 672 | 4 | |
| 673 | /* Side.DontCare */ | |
| 674 | ) : null; | |
| 675 | } | |
| 676 | get prevSibling() { | |
| 677 | return this._parent && this.index >= 0 ? this._parent.nextChild( | |
| 678 | this.index - 1, | |
| 679 | -1, | |
| 680 | 0, | |
| 681 | 4 | |
| 682 | /* Side.DontCare */ | |
| 683 | ) : null; | |
| 684 | } | |
| 685 | get tree() { | |
| 686 | return this._tree; | |
| 687 | } | |
| 688 | toTree() { | |
| 689 | return this._tree; | |
| 690 | } | |
| 691 | /** | |
| 692 | @internal | |
| 693 | */ | |
| 694 | toString() { | |
| 695 | return this._tree.toString(); | |
| 696 | } | |
| 697 | }; | |
| 698 | function getChildren(node, type, before, after) { | |
| 699 | let cur = node.cursor(), result = []; | |
| 700 | if (!cur.firstChild()) | |
| 701 | return result; | |
| 702 | if (before != null) | |
| 703 | for (let found = false; !found; ) { | |
| 704 | found = cur.type.is(before); | |
| 705 | if (!cur.nextSibling()) | |
| 706 | return result; | |
| 707 | } | |
| 708 | for (; ; ) { | |
| 709 | if (after != null && cur.type.is(after)) | |
| 710 | return result; | |
| 711 | if (cur.type.is(type)) | |
| 712 | result.push(cur.node); | |
| 713 | if (!cur.nextSibling()) | |
| 714 | return after == null ? result : []; | |
| 715 | } | |
| 716 | } | |
| 717 | function matchNodeContext(node, context, i = context.length - 1) { | |
| 718 | for (let p = node; i >= 0; p = p.parent) { | |
| 719 | if (!p) | |
| 720 | return false; | |
| 721 | if (!p.type.isAnonymous) { | |
| 722 | if (context[i] && context[i] != p.name) | |
| 723 | return false; | |
| 724 | i--; | |
| 725 | } | |
| 726 | } | |
| 727 | return true; | |
| 728 | } | |
| 729 | var BufferContext = class { | |
| 730 | constructor(parent, buffer, index, start) { | |
| 731 | this.parent = parent; | |
| 732 | this.buffer = buffer; | |
| 733 | this.index = index; | |
| 734 | this.start = start; | |
| 735 | } | |
| 736 | }; | |
| 737 | var BufferNode = class _BufferNode extends BaseNode { | |
| 738 | get name() { | |
| 739 | return this.type.name; | |
| 740 | } | |
| 741 | get from() { | |
| 742 | return this.context.start + this.context.buffer.buffer[this.index + 1]; | |
| 743 | } | |
| 744 | get to() { | |
| 745 | return this.context.start + this.context.buffer.buffer[this.index + 2]; | |
| 746 | } | |
| 747 | constructor(context, _parent, index) { | |
| 748 | super(); | |
| 749 | this.context = context; | |
| 750 | this._parent = _parent; | |
| 751 | this.index = index; | |
| 752 | this.type = context.buffer.set.types[context.buffer.buffer[index]]; | |
| 753 | } | |
| 754 | child(dir, pos, side) { | |
| 755 | let { buffer } = this.context; | |
| 756 | let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.context.start, side); | |
| 757 | return index < 0 ? null : new _BufferNode(this.context, this, index); | |
| 758 | } | |
| 759 | get firstChild() { | |
| 760 | return this.child( | |
| 761 | 1, | |
| 762 | 0, | |
| 763 | 4 | |
| 764 | /* Side.DontCare */ | |
| 765 | ); | |
| 766 | } | |
| 767 | get lastChild() { | |
| 768 | return this.child( | |
| 769 | -1, | |
| 770 | 0, | |
| 771 | 4 | |
| 772 | /* Side.DontCare */ | |
| 773 | ); | |
| 774 | } | |
| 775 | childAfter(pos) { | |
| 776 | return this.child( | |
| 777 | 1, | |
| 778 | pos, | |
| 779 | 2 | |
| 780 | /* Side.After */ | |
| 781 | ); | |
| 782 | } | |
| 783 | childBefore(pos) { | |
| 784 | return this.child( | |
| 785 | -1, | |
| 786 | pos, | |
| 787 | -2 | |
| 788 | /* Side.Before */ | |
| 789 | ); | |
| 790 | } | |
| 791 | prop(prop) { | |
| 792 | return this.type.prop(prop); | |
| 793 | } | |
| 794 | enter(pos, side, mode = 0) { | |
| 795 | if (mode & IterMode.ExcludeBuffers) | |
| 796 | return null; | |
| 797 | let { buffer } = this.context; | |
| 798 | let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side); | |
| 799 | return index < 0 ? null : new _BufferNode(this.context, this, index); | |
| 800 | } | |
| 801 | get parent() { | |
| 802 | return this._parent || this.context.parent.nextSignificantParent(); | |
| 803 | } | |
| 804 | externalSibling(dir) { | |
| 805 | return this._parent ? null : this.context.parent.nextChild( | |
| 806 | this.context.index + dir, | |
| 807 | dir, | |
| 808 | 0, | |
| 809 | 4 | |
| 810 | /* Side.DontCare */ | |
| 811 | ); | |
| 812 | } | |
| 813 | get nextSibling() { | |
| 814 | let { buffer } = this.context; | |
| 815 | let after = buffer.buffer[this.index + 3]; | |
| 816 | if (after < (this._parent ? buffer.buffer[this._parent.index + 3] : buffer.buffer.length)) | |
| 817 | return new _BufferNode(this.context, this._parent, after); | |
| 818 | return this.externalSibling(1); | |
| 819 | } | |
| 820 | get prevSibling() { | |
| 821 | let { buffer } = this.context; | |
| 822 | let parentStart = this._parent ? this._parent.index + 4 : 0; | |
| 823 | if (this.index == parentStart) | |
| 824 | return this.externalSibling(-1); | |
| 825 | return new _BufferNode(this.context, this._parent, buffer.findChild( | |
| 826 | parentStart, | |
| 827 | this.index, | |
| 828 | -1, | |
| 829 | 0, | |
| 830 | 4 | |
| 831 | /* Side.DontCare */ | |
| 832 | )); | |
| 833 | } | |
| 834 | get tree() { | |
| 835 | return null; | |
| 836 | } | |
| 837 | toTree() { | |
| 838 | let children = [], positions = []; | |
| 839 | let { buffer } = this.context; | |
| 840 | let startI = this.index + 4, endI = buffer.buffer[this.index + 3]; | |
| 841 | if (endI > startI) { | |
| 842 | let from = buffer.buffer[this.index + 1]; | |
| 843 | children.push(buffer.slice(startI, endI, from)); | |
| 844 | positions.push(0); | |
| 845 | } | |
| 846 | return new Tree(this.type, children, positions, this.to - this.from); | |
| 847 | } | |
| 848 | /** | |
| 849 | @internal | |
| 850 | */ | |
| 851 | toString() { | |
| 852 | return this.context.buffer.childString(this.index); | |
| 853 | } | |
| 854 | }; | |
| 855 | function iterStack(heads) { | |
| 856 | if (!heads.length) | |
| 857 | return null; | |
| 858 | let pick = 0, picked = heads[0]; | |
| 859 | for (let i = 1; i < heads.length; i++) { | |
| 860 | let node = heads[i]; | |
| 861 | if (node.from > picked.from || node.to < picked.to) { | |
| 862 | picked = node; | |
| 863 | pick = i; | |
| 864 | } | |
| 865 | } | |
| 866 | let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent; | |
| 867 | let newHeads = heads.slice(); | |
| 868 | if (next) | |
| 869 | newHeads[pick] = next; | |
| 870 | else | |
| 871 | newHeads.splice(pick, 1); | |
| 872 | return new StackIterator(newHeads, picked); | |
| 873 | } | |
| 874 | var StackIterator = class { | |
| 875 | constructor(heads, node) { | |
| 876 | this.heads = heads; | |
| 877 | this.node = node; | |
| 878 | } | |
| 879 | get next() { | |
| 880 | return iterStack(this.heads); | |
| 881 | } | |
| 882 | }; | |
| 883 | function stackIterator(tree, pos, side) { | |
| 884 | let inner = tree.resolveInner(pos, side), layers = null; | |
| 885 | for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) { | |
| 886 | if (scan.index < 0) { | |
| 887 | let parent = scan.parent; | |
| 888 | (layers || (layers = [inner])).push(parent.resolve(pos, side)); | |
| 889 | scan = parent; | |
| 890 | } else { | |
| 891 | let mount = MountedTree.get(scan.tree); | |
| 892 | if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) { | |
| 893 | let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, -1, scan); | |
| 894 | (layers || (layers = [inner])).push(resolveNode(root, pos, side, false)); | |
| 895 | } | |
| 896 | } | |
| 897 | } | |
| 898 | return layers ? iterStack(layers) : inner; | |
| 899 | } | |
| 900 | var TreeCursor = class { | |
| 901 | /** | |
| 902 | Shorthand for `.type.name`. | |
| 903 | */ | |
| 904 | get name() { | |
| 905 | return this.type.name; | |
| 906 | } | |
| 907 | /** | |
| 908 | @internal | |
| 909 | */ | |
| 910 | constructor(node, mode = 0) { | |
| 911 | this.buffer = null; | |
| 912 | this.stack = []; | |
| 913 | this.index = 0; | |
| 914 | this.bufferNode = null; | |
| 915 | this.mode = mode & ~IterMode.EnterBracketed; | |
| 916 | if (node instanceof TreeNode) { | |
| 917 | this.yieldNode(node); | |
| 918 | } else { | |
| 919 | this._tree = node.context.parent; | |
| 920 | this.buffer = node.context; | |
| 921 | for (let n = node._parent; n; n = n._parent) | |
| 922 | this.stack.unshift(n.index); | |
| 923 | this.bufferNode = node; | |
| 924 | this.yieldBuf(node.index); | |
| 925 | } | |
| 926 | } | |
| 927 | yieldNode(node) { | |
| 928 | if (!node) | |
| 929 | return false; | |
| 930 | this._tree = node; | |
| 931 | this.type = node.type; | |
| 932 | this.from = node.from; | |
| 933 | this.to = node.to; | |
| 934 | return true; | |
| 935 | } | |
| 936 | yieldBuf(index, type) { | |
| 937 | this.index = index; | |
| 938 | let { start, buffer } = this.buffer; | |
| 939 | this.type = type || buffer.set.types[buffer.buffer[index]]; | |
| 940 | this.from = start + buffer.buffer[index + 1]; | |
| 941 | this.to = start + buffer.buffer[index + 2]; | |
| 942 | return true; | |
| 943 | } | |
| 944 | /** | |
| 945 | @internal | |
| 946 | */ | |
| 947 | yield(node) { | |
| 948 | if (!node) | |
| 949 | return false; | |
| 950 | if (node instanceof TreeNode) { | |
| 951 | this.buffer = null; | |
| 952 | return this.yieldNode(node); | |
| 953 | } | |
| 954 | this.buffer = node.context; | |
| 955 | return this.yieldBuf(node.index, node.type); | |
| 956 | } | |
| 957 | /** | |
| 958 | @internal | |
| 959 | */ | |
| 960 | toString() { | |
| 961 | return this.buffer ? this.buffer.buffer.childString(this.index) : this._tree.toString(); | |
| 962 | } | |
| 963 | /** | |
| 964 | @internal | |
| 965 | */ | |
| 966 | enterChild(dir, pos, side) { | |
| 967 | if (!this.buffer) | |
| 968 | return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode)); | |
| 969 | let { buffer } = this.buffer; | |
| 970 | let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side); | |
| 971 | if (index < 0) | |
| 972 | return false; | |
| 973 | this.stack.push(this.index); | |
| 974 | return this.yieldBuf(index); | |
| 975 | } | |
| 976 | /** | |
| 977 | Move the cursor to this node's first child. When this returns | |
| 978 | false, the node has no child, and the cursor has not been moved. | |
| 979 | */ | |
| 980 | firstChild() { | |
| 981 | return this.enterChild( | |
| 982 | 1, | |
| 983 | 0, | |
| 984 | 4 | |
| 985 | /* Side.DontCare */ | |
| 986 | ); | |
| 987 | } | |
| 988 | /** | |
| 989 | Move the cursor to this node's last child. | |
| 990 | */ | |
| 991 | lastChild() { | |
| 992 | return this.enterChild( | |
| 993 | -1, | |
| 994 | 0, | |
| 995 | 4 | |
| 996 | /* Side.DontCare */ | |
| 997 | ); | |
| 998 | } | |
| 999 | /** | |
| 1000 | Move the cursor to the first child that ends after `pos`. | |
| 1001 | */ | |
| 1002 | childAfter(pos) { | |
| 1003 | return this.enterChild( | |
| 1004 | 1, | |
| 1005 | pos, | |
| 1006 | 2 | |
| 1007 | /* Side.After */ | |
| 1008 | ); | |
| 1009 | } | |
| 1010 | /** | |
| 1011 | Move to the last child that starts before `pos`. | |
| 1012 | */ | |
| 1013 | childBefore(pos) { | |
| 1014 | return this.enterChild( | |
| 1015 | -1, | |
| 1016 | pos, | |
| 1017 | -2 | |
| 1018 | /* Side.Before */ | |
| 1019 | ); | |
| 1020 | } | |
| 1021 | /** | |
| 1022 | Move the cursor to the child around `pos`. If side is -1 the | |
| 1023 | child may end at that position, when 1 it may start there. This | |
| 1024 | will also enter [overlaid](#common.MountedTree.overlay) | |
| 1025 | [mounted](#common.NodeProp^mounted) trees unless `overlays` is | |
| 1026 | set to false. | |
| 1027 | */ | |
| 1028 | enter(pos, side, mode = this.mode) { | |
| 1029 | if (!this.buffer) | |
| 1030 | return this.yield(this._tree.enter(pos, side, mode)); | |
| 1031 | return mode & IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side); | |
| 1032 | } | |
| 1033 | /** | |
| 1034 | Move to the node's parent node, if this isn't the top node. | |
| 1035 | */ | |
| 1036 | parent() { | |
| 1037 | if (!this.buffer) | |
| 1038 | return this.yieldNode(this.mode & IterMode.IncludeAnonymous ? this._tree._parent : this._tree.parent); | |
| 1039 | if (this.stack.length) | |
| 1040 | return this.yieldBuf(this.stack.pop()); | |
| 1041 | let parent = this.mode & IterMode.IncludeAnonymous ? this.buffer.parent : this.buffer.parent.nextSignificantParent(); | |
| 1042 | this.buffer = null; | |
| 1043 | return this.yieldNode(parent); | |
| 1044 | } | |
| 1045 | /** | |
| 1046 | @internal | |
| 1047 | */ | |
| 1048 | sibling(dir) { | |
| 1049 | if (!this.buffer) | |
| 1050 | return !this._tree._parent ? false : this.yield(this._tree.index < 0 ? null : this._tree._parent.nextChild(this._tree.index + dir, dir, 0, 4, this.mode)); | |
| 1051 | let { buffer } = this.buffer, d = this.stack.length - 1; | |
| 1052 | if (dir < 0) { | |
| 1053 | let parentStart = d < 0 ? 0 : this.stack[d] + 4; | |
| 1054 | if (this.index != parentStart) | |
| 1055 | return this.yieldBuf(buffer.findChild( | |
| 1056 | parentStart, | |
| 1057 | this.index, | |
| 1058 | -1, | |
| 1059 | 0, | |
| 1060 | 4 | |
| 1061 | /* Side.DontCare */ | |
| 1062 | )); | |
| 1063 | } else { | |
| 1064 | let after = buffer.buffer[this.index + 3]; | |
| 1065 | if (after < (d < 0 ? buffer.buffer.length : buffer.buffer[this.stack[d] + 3])) | |
| 1066 | return this.yieldBuf(after); | |
| 1067 | } | |
| 1068 | return d < 0 ? this.yield(this.buffer.parent.nextChild(this.buffer.index + dir, dir, 0, 4, this.mode)) : false; | |
| 1069 | } | |
| 1070 | /** | |
| 1071 | Move to this node's next sibling, if any. | |
| 1072 | */ | |
| 1073 | nextSibling() { | |
| 1074 | return this.sibling(1); | |
| 1075 | } | |
| 1076 | /** | |
| 1077 | Move to this node's previous sibling, if any. | |
| 1078 | */ | |
| 1079 | prevSibling() { | |
| 1080 | return this.sibling(-1); | |
| 1081 | } | |
| 1082 | atLastNode(dir) { | |
| 1083 | let index, parent, { buffer } = this; | |
| 1084 | if (buffer) { | |
| 1085 | if (dir > 0) { | |
| 1086 | if (this.index < buffer.buffer.buffer.length) | |
| 1087 | return false; | |
| 1088 | } else { | |
| 1089 | for (let i = 0; i < this.index; i++) | |
| 1090 | if (buffer.buffer.buffer[i + 3] < this.index) | |
| 1091 | return false; | |
| 1092 | } | |
| 1093 | ({ index, parent } = buffer); | |
| 1094 | } else { | |
| 1095 | ({ index, _parent: parent } = this._tree); | |
| 1096 | } | |
| 1097 | for (; parent; { index, _parent: parent } = parent) { | |
| 1098 | if (index > -1) | |
| 1099 | for (let i = index + dir, e = dir < 0 ? -1 : parent._tree.children.length; i != e; i += dir) { | |
| 1100 | let child = parent._tree.children[i]; | |
| 1101 | if (this.mode & IterMode.IncludeAnonymous || child instanceof TreeBuffer || !child.type.isAnonymous || hasChild(child)) | |
| 1102 | return false; | |
| 1103 | } | |
| 1104 | } | |
| 1105 | return true; | |
| 1106 | } | |
| 1107 | move(dir, enter) { | |
| 1108 | if (enter && this.enterChild( | |
| 1109 | dir, | |
| 1110 | 0, | |
| 1111 | 4 | |
| 1112 | /* Side.DontCare */ | |
| 1113 | )) | |
| 1114 | return true; | |
| 1115 | for (; ; ) { | |
| 1116 | if (this.sibling(dir)) | |
| 1117 | return true; | |
| 1118 | if (this.atLastNode(dir) || !this.parent()) | |
| 1119 | return false; | |
| 1120 | } | |
| 1121 | } | |
| 1122 | /** | |
| 1123 | Move to the next node in a | |
| 1124 | [pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR) | |
| 1125 | traversal, going from a node to its first child or, if the | |
| 1126 | current node is empty or `enter` is false, its next sibling or | |
| 1127 | the next sibling of the first parent node that has one. | |
| 1128 | */ | |
| 1129 | next(enter = true) { | |
| 1130 | return this.move(1, enter); | |
| 1131 | } | |
| 1132 | /** | |
| 1133 | Move to the next node in a last-to-first pre-order traversal. A | |
| 1134 | node is followed by its last child or, if it has none, its | |
| 1135 | previous sibling or the previous sibling of the first parent | |
| 1136 | node that has one. | |
| 1137 | */ | |
| 1138 | prev(enter = true) { | |
| 1139 | return this.move(-1, enter); | |
| 1140 | } | |
| 1141 | /** | |
| 1142 | Move the cursor to the innermost node that covers `pos`. If | |
| 1143 | `side` is -1, it will enter nodes that end at `pos`. If it is 1, | |
| 1144 | it will enter nodes that start at `pos`. | |
| 1145 | */ | |
| 1146 | moveTo(pos, side = 0) { | |
| 1147 | while (this.from == this.to || (side < 1 ? this.from >= pos : this.from > pos) || (side > -1 ? this.to <= pos : this.to < pos)) | |
| 1148 | if (!this.parent()) | |
| 1149 | break; | |
| 1150 | while (this.enterChild(1, pos, side)) { | |
| 1151 | } | |
| 1152 | return this; | |
| 1153 | } | |
| 1154 | /** | |
| 1155 | Get a [syntax node](#common.SyntaxNode) at the cursor's current | |
| 1156 | position. | |
| 1157 | */ | |
| 1158 | get node() { | |
| 1159 | if (!this.buffer) | |
| 1160 | return this._tree; | |
| 1161 | let cache = this.bufferNode, result = null, depth = 0; | |
| 1162 | if (cache && cache.context == this.buffer) { | |
| 1163 | scan: for (let index = this.index, d = this.stack.length; d >= 0; ) { | |
| 1164 | for (let c = cache; c; c = c._parent) | |
| 1165 | if (c.index == index) { | |
| 1166 | if (index == this.index) | |
| 1167 | return c; | |
| 1168 | result = c; | |
| 1169 | depth = d + 1; | |
| 1170 | break scan; | |
| 1171 | } | |
| 1172 | index = this.stack[--d]; | |
| 1173 | } | |
| 1174 | } | |
| 1175 | for (let i = depth; i < this.stack.length; i++) | |
| 1176 | result = new BufferNode(this.buffer, result, this.stack[i]); | |
| 1177 | return this.bufferNode = new BufferNode(this.buffer, result, this.index); | |
| 1178 | } | |
| 1179 | /** | |
| 1180 | Get the [tree](#common.Tree) that represents the current node, if | |
| 1181 | any. Will return null when the node is in a [tree | |
| 1182 | buffer](#common.TreeBuffer). | |
| 1183 | */ | |
| 1184 | get tree() { | |
| 1185 | return this.buffer ? null : this._tree._tree; | |
| 1186 | } | |
| 1187 | /** | |
| 1188 | Iterate over the current node and all its descendants, calling | |
| 1189 | `enter` when entering a node and `leave`, if given, when leaving | |
| 1190 | one. When `enter` returns `false`, any children of that node are | |
| 1191 | skipped, and `leave` isn't called for it. | |
| 1192 | */ | |
| 1193 | iterate(enter, leave) { | |
| 1194 | for (let depth = 0; ; ) { | |
| 1195 | let mustLeave = false; | |
| 1196 | if (this.type.isAnonymous || enter(this) !== false) { | |
| 1197 | if (this.firstChild()) { | |
| 1198 | depth++; | |
| 1199 | continue; | |
| 1200 | } | |
| 1201 | if (!this.type.isAnonymous) | |
| 1202 | mustLeave = true; | |
| 1203 | } | |
| 1204 | for (; ; ) { | |
| 1205 | if (mustLeave && leave) | |
| 1206 | leave(this); | |
| 1207 | mustLeave = this.type.isAnonymous; | |
| 1208 | if (!depth) | |
| 1209 | return; | |
| 1210 | if (this.nextSibling()) | |
| 1211 | break; | |
| 1212 | this.parent(); | |
| 1213 | depth--; | |
| 1214 | mustLeave = true; | |
| 1215 | } | |
| 1216 | } | |
| 1217 | } | |
| 1218 | /** | |
| 1219 | Test whether the current node matches a given context—a sequence | |
| 1220 | of direct parent node names. Empty strings in the context array | |
| 1221 | are treated as wildcards. | |
| 1222 | */ | |
| 1223 | matchContext(context) { | |
| 1224 | if (!this.buffer) | |
| 1225 | return matchNodeContext(this.node.parent, context); | |
| 1226 | let { buffer } = this.buffer, { types } = buffer.set; | |
| 1227 | for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) { | |
| 1228 | if (d < 0) | |
| 1229 | return matchNodeContext(this._tree, context, i); | |
| 1230 | let type = types[buffer.buffer[this.stack[d]]]; | |
| 1231 | if (!type.isAnonymous) { | |
| 1232 | if (context[i] && context[i] != type.name) | |
| 1233 | return false; | |
| 1234 | i--; | |
| 1235 | } | |
| 1236 | } | |
| 1237 | return true; | |
| 1238 | } | |
| 1239 | }; | |
| 1240 | function hasChild(tree) { | |
| 1241 | return tree.children.some((ch) => ch instanceof TreeBuffer || !ch.type.isAnonymous || hasChild(ch)); | |
| 1242 | } | |
| 1243 | function buildTree(data) { | |
| 1244 | var _a; | |
| 1245 | let { buffer, nodeSet, maxBufferLength = DefaultBufferLength, reused = [], minRepeatType = nodeSet.types.length } = data; | |
| 1246 | let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer; | |
| 1247 | let types = nodeSet.types; | |
| 1248 | let contextHash = 0, lookAhead = 0; | |
| 1249 | function takeNode(parentStart, minPos, children2, positions2, inRepeat, depth) { | |
| 1250 | let { id: id2, start, end, size } = cursor; | |
| 1251 | let lookAheadAtStart = lookAhead, contextAtStart = contextHash; | |
| 1252 | if (size < 0) { | |
| 1253 | cursor.next(); | |
| 1254 | if (size == -1) { | |
| 1255 | let node2 = reused[id2]; | |
| 1256 | children2.push(node2); | |
| 1257 | positions2.push(start - parentStart); | |
| 1258 | return; | |
| 1259 | } else if (size == -3) { | |
| 1260 | contextHash = id2; | |
| 1261 | return; | |
| 1262 | } else if (size == -4) { | |
| 1263 | lookAhead = id2; | |
| 1264 | return; | |
| 1265 | } else { | |
| 1266 | throw new RangeError(`Unrecognized record size: ${size}`); | |
| 1267 | } | |
| 1268 | } | |
| 1269 | let type = types[id2], node, buffer2; | |
| 1270 | let startPos = start - parentStart; | |
| 1271 | if (end - start <= maxBufferLength && (buffer2 = findBufferSize(cursor.pos - minPos, inRepeat))) { | |
| 1272 | let data2 = new Uint16Array(buffer2.size - buffer2.skip); | |
| 1273 | let endPos = cursor.pos - buffer2.size, index = data2.length; | |
| 1274 | while (cursor.pos > endPos) | |
| 1275 | index = copyToBuffer(buffer2.start, data2, index); | |
| 1276 | node = new TreeBuffer(data2, end - buffer2.start, nodeSet); | |
| 1277 | startPos = buffer2.start - parentStart; | |
| 1278 | } else { | |
| 1279 | let endPos = cursor.pos - size; | |
| 1280 | cursor.next(); | |
| 1281 | let localChildren = [], localPositions = []; | |
| 1282 | let localInRepeat = id2 >= minRepeatType ? id2 : -1; | |
| 1283 | let lastGroup = 0, lastEnd = end; | |
| 1284 | while (cursor.pos > endPos) { | |
| 1285 | if (localInRepeat >= 0 && cursor.id == localInRepeat && cursor.size >= 0) { | |
| 1286 | if (cursor.end <= lastEnd - maxBufferLength) { | |
| 1287 | makeRepeatLeaf(localChildren, localPositions, start, lastGroup, cursor.end, lastEnd, localInRepeat, lookAheadAtStart, contextAtStart); | |
| 1288 | lastGroup = localChildren.length; | |
| 1289 | lastEnd = cursor.end; | |
| 1290 | } | |
| 1291 | cursor.next(); | |
| 1292 | } else if (depth > 2500) { | |
| 1293 | takeFlatNode(start, endPos, localChildren, localPositions); | |
| 1294 | } else { | |
| 1295 | takeNode(start, endPos, localChildren, localPositions, localInRepeat, depth + 1); | |
| 1296 | } | |
| 1297 | } | |
| 1298 | if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length) | |
| 1299 | makeRepeatLeaf(localChildren, localPositions, start, lastGroup, start, lastEnd, localInRepeat, lookAheadAtStart, contextAtStart); | |
| 1300 | localChildren.reverse(); | |
| 1301 | localPositions.reverse(); | |
| 1302 | if (localInRepeat > -1 && lastGroup > 0) { | |
| 1303 | let make = makeBalanced(type, contextAtStart); | |
| 1304 | node = balanceRange(type, localChildren, localPositions, 0, localChildren.length, 0, end - start, make, make); | |
| 1305 | } else { | |
| 1306 | node = makeTree(type, localChildren, localPositions, end - start, lookAheadAtStart - end, contextAtStart); | |
| 1307 | } | |
| 1308 | } | |
| 1309 | children2.push(node); | |
| 1310 | positions2.push(startPos); | |
| 1311 | } | |
| 1312 | function takeFlatNode(parentStart, minPos, children2, positions2) { | |
| 1313 | let nodes = []; | |
| 1314 | let nodeCount = 0, stopAt = -1; | |
| 1315 | while (cursor.pos > minPos) { | |
| 1316 | let { id: id2, start, end, size } = cursor; | |
| 1317 | if (size > 4) { | |
| 1318 | cursor.next(); | |
| 1319 | } else if (stopAt > -1 && start < stopAt) { | |
| 1320 | break; | |
| 1321 | } else { | |
| 1322 | if (stopAt < 0) | |
| 1323 | stopAt = end - maxBufferLength; | |
| 1324 | nodes.push(id2, start, end); | |
| 1325 | nodeCount++; | |
| 1326 | cursor.next(); | |
| 1327 | } | |
| 1328 | } | |
| 1329 | if (nodeCount) { | |
| 1330 | let buffer2 = new Uint16Array(nodeCount * 4); | |
| 1331 | let start = nodes[nodes.length - 2]; | |
| 1332 | for (let i = nodes.length - 3, j = 0; i >= 0; i -= 3) { | |
| 1333 | buffer2[j++] = nodes[i]; | |
| 1334 | buffer2[j++] = nodes[i + 1] - start; | |
| 1335 | buffer2[j++] = nodes[i + 2] - start; | |
| 1336 | buffer2[j++] = j; | |
| 1337 | } | |
| 1338 | children2.push(new TreeBuffer(buffer2, nodes[2] - start, nodeSet)); | |
| 1339 | positions2.push(start - parentStart); | |
| 1340 | } | |
| 1341 | } | |
| 1342 | function makeBalanced(type, contextHash2) { | |
| 1343 | return (children2, positions2, length2) => { | |
| 1344 | let lookAhead2 = 0, lastI = children2.length - 1, last, lookAheadProp; | |
| 1345 | if (lastI >= 0 && (last = children2[lastI]) instanceof Tree) { | |
| 1346 | if (!lastI && last.type == type && last.length == length2) | |
| 1347 | return last; | |
| 1348 | if (lookAheadProp = last.prop(NodeProp.lookAhead)) | |
| 1349 | lookAhead2 = positions2[lastI] + last.length + lookAheadProp; | |
| 1350 | } | |
| 1351 | return makeTree(type, children2, positions2, length2, lookAhead2, contextHash2); | |
| 1352 | }; | |
| 1353 | } | |
| 1354 | function makeRepeatLeaf(children2, positions2, base, i, from, to, type, lookAhead2, contextHash2) { | |
| 1355 | let localChildren = [], localPositions = []; | |
| 1356 | while (children2.length > i) { | |
| 1357 | localChildren.push(children2.pop()); | |
| 1358 | localPositions.push(positions2.pop() + base - from); | |
| 1359 | } | |
| 1360 | children2.push(makeTree(nodeSet.types[type], localChildren, localPositions, to - from, lookAhead2 - to, contextHash2)); | |
| 1361 | positions2.push(from - base); | |
| 1362 | } | |
| 1363 | function makeTree(type, children2, positions2, length2, lookAhead2, contextHash2, props) { | |
| 1364 | if (contextHash2) { | |
| 1365 | let pair2 = [NodeProp.contextHash, contextHash2]; | |
| 1366 | props = props ? [pair2].concat(props) : [pair2]; | |
| 1367 | } | |
| 1368 | if (lookAhead2 > 25) { | |
| 1369 | let pair2 = [NodeProp.lookAhead, lookAhead2]; | |
| 1370 | props = props ? [pair2].concat(props) : [pair2]; | |
| 1371 | } | |
| 1372 | return new Tree(type, children2, positions2, length2, props); | |
| 1373 | } | |
| 1374 | function findBufferSize(maxSize, inRepeat) { | |
| 1375 | let fork = cursor.fork(); | |
| 1376 | let size = 0, start = 0, skip = 0, minStart = fork.end - maxBufferLength; | |
| 1377 | let result = { size: 0, start: 0, skip: 0 }; | |
| 1378 | scan: for (let minPos = fork.pos - maxSize; fork.pos > minPos; ) { | |
| 1379 | let nodeSize2 = fork.size; | |
| 1380 | if (fork.id == inRepeat && nodeSize2 >= 0) { | |
| 1381 | result.size = size; | |
| 1382 | result.start = start; | |
| 1383 | result.skip = skip; | |
| 1384 | skip += 4; | |
| 1385 | size += 4; | |
| 1386 | fork.next(); | |
| 1387 | continue; | |
| 1388 | } | |
| 1389 | let startPos = fork.pos - nodeSize2; | |
| 1390 | if (nodeSize2 < 0 || startPos < minPos || fork.start < minStart) | |
| 1391 | break; | |
| 1392 | let localSkipped = fork.id >= minRepeatType ? 4 : 0; | |
| 1393 | let nodeStart = fork.start; | |
| 1394 | fork.next(); | |
| 1395 | while (fork.pos > startPos) { | |
| 1396 | if (fork.size < 0) { | |
| 1397 | if (fork.size == -3 || fork.size == -4) | |
| 1398 | localSkipped += 4; | |
| 1399 | else | |
| 1400 | break scan; | |
| 1401 | } else if (fork.id >= minRepeatType) { | |
| 1402 | localSkipped += 4; | |
| 1403 | } | |
| 1404 | fork.next(); | |
| 1405 | } | |
| 1406 | start = nodeStart; | |
| 1407 | size += nodeSize2; | |
| 1408 | skip += localSkipped; | |
| 1409 | } | |
| 1410 | if (inRepeat < 0 || size == maxSize) { | |
| 1411 | result.size = size; | |
| 1412 | result.start = start; | |
| 1413 | result.skip = skip; | |
| 1414 | } | |
| 1415 | return result.size > 4 ? result : void 0; | |
| 1416 | } | |
| 1417 | function copyToBuffer(bufferStart, buffer2, index) { | |
| 1418 | let { id: id2, start, end, size } = cursor; | |
| 1419 | cursor.next(); | |
| 1420 | if (size >= 0 && id2 < minRepeatType) { | |
| 1421 | let startIndex = index; | |
| 1422 | if (size > 4) { | |
| 1423 | let endPos = cursor.pos - (size - 4); | |
| 1424 | while (cursor.pos > endPos) | |
| 1425 | index = copyToBuffer(bufferStart, buffer2, index); | |
| 1426 | } | |
| 1427 | buffer2[--index] = startIndex; | |
| 1428 | buffer2[--index] = end - bufferStart; | |
| 1429 | buffer2[--index] = start - bufferStart; | |
| 1430 | buffer2[--index] = id2; | |
| 1431 | } else if (size == -3) { | |
| 1432 | contextHash = id2; | |
| 1433 | } else if (size == -4) { | |
| 1434 | lookAhead = id2; | |
| 1435 | } | |
| 1436 | return index; | |
| 1437 | } | |
| 1438 | let children = [], positions = []; | |
| 1439 | while (cursor.pos > 0) | |
| 1440 | takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1, 0); | |
| 1441 | let length = (_a = data.length) !== null && _a !== void 0 ? _a : children.length ? positions[0] + children[0].length : 0; | |
| 1442 | return new Tree(types[data.topID], children.reverse(), positions.reverse(), length); | |
| 1443 | } | |
| 1444 | var nodeSizeCache = /* @__PURE__ */ new WeakMap(); | |
| 1445 | function nodeSize(balanceType, node) { | |
| 1446 | if (!balanceType.isAnonymous || node instanceof TreeBuffer || node.type != balanceType) | |
| 1447 | return 1; | |
| 1448 | let size = nodeSizeCache.get(node); | |
| 1449 | if (size == null) { | |
| 1450 | size = 1; | |
| 1451 | for (let child of node.children) { | |
| 1452 | if (child.type != balanceType || !(child instanceof Tree)) { | |
| 1453 | size = 1; | |
| 1454 | break; | |
| 1455 | } | |
| 1456 | size += nodeSize(balanceType, child); | |
| 1457 | } | |
| 1458 | nodeSizeCache.set(node, size); | |
| 1459 | } | |
| 1460 | return size; | |
| 1461 | } | |
| 1462 | function balanceRange(balanceType, children, positions, from, to, start, length, mkTop, mkTree) { | |
| 1463 | let total = 0; | |
| 1464 | for (let i = from; i < to; i++) | |
| 1465 | total += nodeSize(balanceType, children[i]); | |
| 1466 | let maxChild = Math.ceil( | |
| 1467 | total * 1.5 / 8 | |
| 1468 | /* Balance.BranchFactor */ | |
| 1469 | ); | |
| 1470 | let localChildren = [], localPositions = []; | |
| 1471 | function divide(children2, positions2, from2, to2, offset) { | |
| 1472 | for (let i = from2; i < to2; ) { | |
| 1473 | let groupFrom = i, groupStart = positions2[i], groupSize = nodeSize(balanceType, children2[i]); | |
| 1474 | i++; | |
| 1475 | for (; i < to2; i++) { | |
| 1476 | let nextSize = nodeSize(balanceType, children2[i]); | |
| 1477 | if (groupSize + nextSize >= maxChild) | |
| 1478 | break; | |
| 1479 | groupSize += nextSize; | |
| 1480 | } | |
| 1481 | if (i == groupFrom + 1) { | |
| 1482 | if (groupSize > maxChild) { | |
| 1483 | let only = children2[groupFrom]; | |
| 1484 | divide(only.children, only.positions, 0, only.children.length, positions2[groupFrom] + offset); | |
| 1485 | continue; | |
| 1486 | } | |
| 1487 | localChildren.push(children2[groupFrom]); | |
| 1488 | } else { | |
| 1489 | let length2 = positions2[i - 1] + children2[i - 1].length - groupStart; | |
| 1490 | localChildren.push(balanceRange(balanceType, children2, positions2, groupFrom, i, groupStart, length2, null, mkTree)); | |
| 1491 | } | |
| 1492 | localPositions.push(groupStart + offset - start); | |
| 1493 | } | |
| 1494 | } | |
| 1495 | divide(children, positions, from, to, 0); | |
| 1496 | return (mkTop || mkTree)(localChildren, localPositions, length); | |
| 1497 | } | |
| 1498 | var Parser = class { | |
| 1499 | /** | |
| 1500 | Start a parse, returning a [partial parse](#common.PartialParse) | |
| 1501 | object. [`fragments`](#common.TreeFragment) can be passed in to | |
| 1502 | make the parse incremental. | |
| 1503 | ||
| 1504 | By default, the entire input is parsed. You can pass `ranges`, | |
| 1505 | which should be a sorted array of non-empty, non-overlapping | |
| 1506 | ranges, to parse only those ranges. The tree returned in that | |
| 1507 | case will start at `ranges[0].from`. | |
| 1508 | */ | |
| 1509 | startParse(input, fragments, ranges) { | |
| 1510 | if (typeof input == "string") | |
| 1511 | input = new StringInput(input); | |
| 1512 | ranges = !ranges ? [new Range(0, input.length)] : ranges.length ? ranges.map((r) => new Range(r.from, r.to)) : [new Range(0, 0)]; | |
| 1513 | return this.createParse(input, fragments || [], ranges); | |
| 1514 | } | |
| 1515 | /** | |
| 1516 | Run a full parse, returning the resulting tree. | |
| 1517 | */ | |
| 1518 | parse(input, fragments, ranges) { | |
| 1519 | let parse = this.startParse(input, fragments, ranges); | |
| 1520 | for (; ; ) { | |
| 1521 | let done = parse.advance(); | |
| 1522 | if (done) | |
| 1523 | return done; | |
| 1524 | } | |
| 1525 | } | |
| 1526 | }; | |
| 1527 | var StringInput = class { | |
| 1528 | constructor(string2) { | |
| 1529 | this.string = string2; | |
| 1530 | } | |
| 1531 | get length() { | |
| 1532 | return this.string.length; | |
| 1533 | } | |
| 1534 | chunk(from) { | |
| 1535 | return this.string.slice(from); | |
| 1536 | } | |
| 1537 | get lineChunks() { | |
| 1538 | return false; | |
| 1539 | } | |
| 1540 | read(from, to) { | |
| 1541 | return this.string.slice(from, to); | |
| 1542 | } | |
| 1543 | }; | |
| 1544 | var stoppedInner = new NodeProp({ perNode: true }); | |
| 1545 | ||
| 1546 | // node_modules/@lezer/lr/dist/index.js | |
| 1547 | var Stack = class _Stack { | |
| 1548 | /** | |
| 1549 | @internal | |
| 1550 | */ | |
| 1551 | constructor(p, stack, state, reducePos, pos, score, buffer, bufferBase, curContext, lookAhead = 0, parent) { | |
| 1552 | this.p = p; | |
| 1553 | this.stack = stack; | |
| 1554 | this.state = state; | |
| 1555 | this.reducePos = reducePos; | |
| 1556 | this.pos = pos; | |
| 1557 | this.score = score; | |
| 1558 | this.buffer = buffer; | |
| 1559 | this.bufferBase = bufferBase; | |
| 1560 | this.curContext = curContext; | |
| 1561 | this.lookAhead = lookAhead; | |
| 1562 | this.parent = parent; | |
| 1563 | } | |
| 1564 | /** | |
| 1565 | @internal | |
| 1566 | */ | |
| 1567 | toString() { | |
| 1568 | return `[${this.stack.filter((_, i) => i % 3 == 0).concat(this.state)}]@${this.pos}${this.score ? "!" + this.score : ""}`; | |
| 1569 | } | |
| 1570 | // Start an empty stack | |
| 1571 | /** | |
| 1572 | @internal | |
| 1573 | */ | |
| 1574 | static start(p, state, pos = 0) { | |
| 1575 | let cx = p.parser.context; | |
| 1576 | return new _Stack(p, [], state, pos, pos, 0, [], 0, cx ? new StackContext(cx, cx.start) : null, 0, null); | |
| 1577 | } | |
| 1578 | /** | |
| 1579 | The stack's current [context](#lr.ContextTracker) value, if | |
| 1580 | any. Its type will depend on the context tracker's type | |
| 1581 | parameter, or it will be `null` if there is no context | |
| 1582 | tracker. | |
| 1583 | */ | |
| 1584 | get context() { | |
| 1585 | return this.curContext ? this.curContext.context : null; | |
| 1586 | } | |
| 1587 | // Push a state onto the stack, tracking its start position as well | |
| 1588 | // as the buffer base at that point. | |
| 1589 | /** | |
| 1590 | @internal | |
| 1591 | */ | |
| 1592 | pushState(state, start) { | |
| 1593 | this.stack.push(this.state, start, this.bufferBase + this.buffer.length); | |
| 1594 | this.state = state; | |
| 1595 | } | |
| 1596 | // Apply a reduce action | |
| 1597 | /** | |
| 1598 | @internal | |
| 1599 | */ | |
| 1600 | reduce(action) { | |
| 1601 | var _a; | |
| 1602 | let depth = action >> 19, type = action & 65535; | |
| 1603 | let { parser: parser2 } = this.p; | |
| 1604 | let lookaheadRecord = this.reducePos < this.pos - 25 && this.setLookAhead(this.pos); | |
| 1605 | let dPrec = parser2.dynamicPrecedence(type); | |
| 1606 | if (dPrec) | |
| 1607 | this.score += dPrec; | |
| 1608 | if (depth == 0) { | |
| 1609 | this.pushState(parser2.getGoto(this.state, type, true), this.reducePos); | |
| 1610 | if (type < parser2.minRepeatTerm) | |
| 1611 | this.storeNode(type, this.reducePos, this.reducePos, lookaheadRecord ? 8 : 4, true); | |
| 1612 | this.reduceContext(type, this.reducePos); | |
| 1613 | return; | |
| 1614 | } | |
| 1615 | let base = this.stack.length - (depth - 1) * 3 - (action & 262144 ? 6 : 0); | |
| 1616 | let start = base ? this.stack[base - 2] : this.p.ranges[0].from, size = this.reducePos - start; | |
| 1617 | if (size >= 2e3 && !((_a = this.p.parser.nodeSet.types[type]) === null || _a === void 0 ? void 0 : _a.isAnonymous)) { | |
| 1618 | if (start == this.p.lastBigReductionStart) { | |
| 1619 | this.p.bigReductionCount++; | |
| 1620 | this.p.lastBigReductionSize = size; | |
| 1621 | } else if (this.p.lastBigReductionSize < size) { | |
| 1622 | this.p.bigReductionCount = 1; | |
| 1623 | this.p.lastBigReductionStart = start; | |
| 1624 | this.p.lastBigReductionSize = size; | |
| 1625 | } | |
| 1626 | } | |
| 1627 | let bufferBase = base ? this.stack[base - 1] : 0, count = this.bufferBase + this.buffer.length - bufferBase; | |
| 1628 | if (type < parser2.minRepeatTerm || action & 131072) { | |
| 1629 | let pos = parser2.stateFlag( | |
| 1630 | this.state, | |
| 1631 | 1 | |
| 1632 | /* StateFlag.Skipped */ | |
| 1633 | ) ? this.pos : this.reducePos; | |
| 1634 | this.storeNode(type, start, pos, count + 4, true); | |
| 1635 | } | |
| 1636 | if (action & 262144) { | |
| 1637 | this.state = this.stack[base]; | |
| 1638 | } else { | |
| 1639 | let baseStateID = this.stack[base - 3]; | |
| 1640 | this.state = parser2.getGoto(baseStateID, type, true); | |
| 1641 | } | |
| 1642 | while (this.stack.length > base) | |
| 1643 | this.stack.pop(); | |
| 1644 | this.reduceContext(type, start); | |
| 1645 | } | |
| 1646 | // Shift a value into the buffer | |
| 1647 | /** | |
| 1648 | @internal | |
| 1649 | */ | |
| 1650 | storeNode(term, start, end, size = 4, mustSink = false) { | |
| 1651 | if (term == 0 && (!this.stack.length || this.stack[this.stack.length - 1] < this.buffer.length + this.bufferBase)) { | |
| 1652 | let cur = this, top = this.buffer.length; | |
| 1653 | if (top == 0 && cur.parent) { | |
| 1654 | top = cur.bufferBase - cur.parent.bufferBase; | |
| 1655 | cur = cur.parent; | |
| 1656 | } | |
| 1657 | if (top > 0 && cur.buffer[top - 4] == 0 && cur.buffer[top - 1] > -1) { | |
| 1658 | if (start == end) | |
| 1659 | return; | |
| 1660 | if (cur.buffer[top - 2] >= start) { | |
| 1661 | cur.buffer[top - 2] = end; | |
| 1662 | return; | |
| 1663 | } | |
| 1664 | } | |
| 1665 | } | |
| 1666 | if (!mustSink || this.pos == end) { | |
| 1667 | this.buffer.push(term, start, end, size); | |
| 1668 | } else { | |
| 1669 | let index = this.buffer.length; | |
| 1670 | if (index > 0 && (this.buffer[index - 4] != 0 || this.buffer[index - 1] < 0)) { | |
| 1671 | let mustMove = false; | |
| 1672 | for (let scan = index; scan > 0 && this.buffer[scan - 2] > end; scan -= 4) { | |
| 1673 | if (this.buffer[scan - 1] >= 0) { | |
| 1674 | mustMove = true; | |
| 1675 | break; | |
| 1676 | } | |
| 1677 | } | |
| 1678 | if (mustMove) | |
| 1679 | while (index > 0 && this.buffer[index - 2] > end) { | |
| 1680 | this.buffer[index] = this.buffer[index - 4]; | |
| 1681 | this.buffer[index + 1] = this.buffer[index - 3]; | |
| 1682 | this.buffer[index + 2] = this.buffer[index - 2]; | |
| 1683 | this.buffer[index + 3] = this.buffer[index - 1]; | |
| 1684 | index -= 4; | |
| 1685 | if (size > 4) | |
| 1686 | size -= 4; | |
| 1687 | } | |
| 1688 | } | |
| 1689 | this.buffer[index] = term; | |
| 1690 | this.buffer[index + 1] = start; | |
| 1691 | this.buffer[index + 2] = end; | |
| 1692 | this.buffer[index + 3] = size; | |
| 1693 | } | |
| 1694 | } | |
| 1695 | // Apply a shift action | |
| 1696 | /** | |
| 1697 | @internal | |
| 1698 | */ | |
| 1699 | shift(action, type, start, end) { | |
| 1700 | if (action & 131072) { | |
| 1701 | this.pushState(action & 65535, this.pos); | |
| 1702 | } else if ((action & 262144) == 0) { | |
| 1703 | let nextState = action, { parser: parser2 } = this.p; | |
| 1704 | this.pos = end; | |
| 1705 | let skipped = parser2.stateFlag( | |
| 1706 | nextState, | |
| 1707 | 1 | |
| 1708 | /* StateFlag.Skipped */ | |
| 1709 | ); | |
| 1710 | if (!skipped && (end > start || type <= parser2.maxNode)) | |
| 1711 | this.reducePos = end; | |
| 1712 | this.pushState(nextState, skipped ? start : Math.min(start, this.reducePos)); | |
| 1713 | this.shiftContext(type, start); | |
| 1714 | if (type <= parser2.maxNode) | |
| 1715 | this.buffer.push(type, start, end, 4); | |
| 1716 | } else { | |
| 1717 | this.pos = end; | |
| 1718 | this.shiftContext(type, start); | |
| 1719 | if (type <= this.p.parser.maxNode) | |
| 1720 | this.buffer.push(type, start, end, 4); | |
| 1721 | } | |
| 1722 | } | |
| 1723 | // Apply an action | |
| 1724 | /** | |
| 1725 | @internal | |
| 1726 | */ | |
| 1727 | apply(action, next, nextStart, nextEnd) { | |
| 1728 | if (action & 65536) | |
| 1729 | this.reduce(action); | |
| 1730 | else | |
| 1731 | this.shift(action, next, nextStart, nextEnd); | |
| 1732 | } | |
| 1733 | // Add a prebuilt (reused) node into the buffer. | |
| 1734 | /** | |
| 1735 | @internal | |
| 1736 | */ | |
| 1737 | useNode(value, next) { | |
| 1738 | let index = this.p.reused.length - 1; | |
| 1739 | if (index < 0 || this.p.reused[index] != value) { | |
| 1740 | this.p.reused.push(value); | |
| 1741 | index++; | |
| 1742 | } | |
| 1743 | let start = this.pos; | |
| 1744 | this.reducePos = this.pos = start + value.length; | |
| 1745 | this.pushState(next, start); | |
| 1746 | this.buffer.push( | |
| 1747 | index, | |
| 1748 | start, | |
| 1749 | this.reducePos, | |
| 1750 | -1 | |
| 1751 | /* size == -1 means this is a reused value */ | |
| 1752 | ); | |
| 1753 | if (this.curContext) | |
| 1754 | this.updateContext(this.curContext.tracker.reuse(this.curContext.context, value, this, this.p.stream.reset(this.pos - value.length))); | |
| 1755 | } | |
| 1756 | // Split the stack. Due to the buffer sharing and the fact | |
| 1757 | // that `this.stack` tends to stay quite shallow, this isn't very | |
| 1758 | // expensive. | |
| 1759 | /** | |
| 1760 | @internal | |
| 1761 | */ | |
| 1762 | split() { | |
| 1763 | let parent = this; | |
| 1764 | let off = parent.buffer.length; | |
| 1765 | while (off > 0 && parent.buffer[off - 2] > parent.reducePos) | |
| 1766 | off -= 4; | |
| 1767 | let buffer = parent.buffer.slice(off), base = parent.bufferBase + off; | |
| 1768 | while (parent && base == parent.bufferBase) | |
| 1769 | parent = parent.parent; | |
| 1770 | return new _Stack(this.p, this.stack.slice(), this.state, this.reducePos, this.pos, this.score, buffer, base, this.curContext, this.lookAhead, parent); | |
| 1771 | } | |
| 1772 | // Try to recover from an error by 'deleting' (ignoring) one token. | |
| 1773 | /** | |
| 1774 | @internal | |
| 1775 | */ | |
| 1776 | recoverByDelete(next, nextEnd) { | |
| 1777 | let isNode = next <= this.p.parser.maxNode; | |
| 1778 | if (isNode) | |
| 1779 | this.storeNode(next, this.pos, nextEnd, 4); | |
| 1780 | this.storeNode(0, this.pos, nextEnd, isNode ? 8 : 4); | |
| 1781 | this.pos = this.reducePos = nextEnd; | |
| 1782 | this.score -= 190; | |
| 1783 | } | |
| 1784 | /** | |
| 1785 | Check if the given term would be able to be shifted (optionally | |
| 1786 | after some reductions) on this stack. This can be useful for | |
| 1787 | external tokenizers that want to make sure they only provide a | |
| 1788 | given token when it applies. | |
| 1789 | */ | |
| 1790 | canShift(term) { | |
| 1791 | for (let sim = new SimulatedStack(this); ; ) { | |
| 1792 | let action = this.p.parser.stateSlot( | |
| 1793 | sim.state, | |
| 1794 | 4 | |
| 1795 | /* ParseState.DefaultReduce */ | |
| 1796 | ) || this.p.parser.hasAction(sim.state, term); | |
| 1797 | if (action == 0) | |
| 1798 | return false; | |
| 1799 | if ((action & 65536) == 0) | |
| 1800 | return true; | |
| 1801 | sim.reduce(action); | |
| 1802 | } | |
| 1803 | } | |
| 1804 | // Apply up to Recover.MaxNext recovery actions that conceptually | |
| 1805 | // inserts some missing token or rule. | |
| 1806 | /** | |
| 1807 | @internal | |
| 1808 | */ | |
| 1809 | recoverByInsert(next) { | |
| 1810 | if (this.stack.length >= 300) | |
| 1811 | return []; | |
| 1812 | let nextStates = this.p.parser.nextStates(this.state); | |
| 1813 | if (nextStates.length > 4 << 1 || this.stack.length >= 120) { | |
| 1814 | let best = []; | |
| 1815 | for (let i = 0, s; i < nextStates.length; i += 2) { | |
| 1816 | if ((s = nextStates[i + 1]) != this.state && this.p.parser.hasAction(s, next)) | |
| 1817 | best.push(nextStates[i], s); | |
| 1818 | } | |
| 1819 | if (this.stack.length < 120) | |
| 1820 | for (let i = 0; best.length < 4 << 1 && i < nextStates.length; i += 2) { | |
| 1821 | let s = nextStates[i + 1]; | |
| 1822 | if (!best.some((v, i2) => i2 & 1 && v == s)) | |
| 1823 | best.push(nextStates[i], s); | |
| 1824 | } | |
| 1825 | nextStates = best; | |
| 1826 | } | |
| 1827 | let result = []; | |
| 1828 | for (let i = 0; i < nextStates.length && result.length < 4; i += 2) { | |
| 1829 | let s = nextStates[i + 1]; | |
| 1830 | if (s == this.state) | |
| 1831 | continue; | |
| 1832 | let stack = this.split(); | |
| 1833 | stack.pushState(s, this.pos); | |
| 1834 | stack.storeNode(0, stack.pos, stack.pos, 4, true); | |
| 1835 | stack.shiftContext(nextStates[i], this.pos); | |
| 1836 | stack.reducePos = this.pos; | |
| 1837 | stack.score -= 200; | |
| 1838 | result.push(stack); | |
| 1839 | } | |
| 1840 | return result; | |
| 1841 | } | |
| 1842 | // Force a reduce, if possible. Return false if that can't | |
| 1843 | // be done. | |
| 1844 | /** | |
| 1845 | @internal | |
| 1846 | */ | |
| 1847 | forceReduce() { | |
| 1848 | let { parser: parser2 } = this.p; | |
| 1849 | let reduce = parser2.stateSlot( | |
| 1850 | this.state, | |
| 1851 | 5 | |
| 1852 | /* ParseState.ForcedReduce */ | |
| 1853 | ); | |
| 1854 | if ((reduce & 65536) == 0) | |
| 1855 | return false; | |
| 1856 | if (!parser2.validAction(this.state, reduce)) { | |
| 1857 | let depth = reduce >> 19, term = reduce & 65535; | |
| 1858 | let target = this.stack.length - depth * 3; | |
| 1859 | if (target < 0 || parser2.getGoto(this.stack[target], term, false) < 0) { | |
| 1860 | let backup = this.findForcedReduction(); | |
| 1861 | if (backup == null) | |
| 1862 | return false; | |
| 1863 | reduce = backup; | |
| 1864 | } | |
| 1865 | this.storeNode(0, this.pos, this.pos, 4, true); | |
| 1866 | this.score -= 100; | |
| 1867 | } | |
| 1868 | this.reducePos = this.pos; | |
| 1869 | this.reduce(reduce); | |
| 1870 | return true; | |
| 1871 | } | |
| 1872 | /** | |
| 1873 | Try to scan through the automaton to find some kind of reduction | |
| 1874 | that can be applied. Used when the regular ForcedReduce field | |
| 1875 | isn't a valid action. @internal | |
| 1876 | */ | |
| 1877 | findForcedReduction() { | |
| 1878 | let { parser: parser2 } = this.p, seen = []; | |
| 1879 | let explore = (state, depth) => { | |
| 1880 | if (seen.includes(state)) | |
| 1881 | return; | |
| 1882 | seen.push(state); | |
| 1883 | return parser2.allActions(state, (action) => { | |
| 1884 | if (action & (262144 | 131072)) ; | |
| 1885 | else if (action & 65536) { | |
| 1886 | let rDepth = (action >> 19) - depth; | |
| 1887 | if (rDepth > 1) { | |
| 1888 | let term = action & 65535, target = this.stack.length - rDepth * 3; | |
| 1889 | if (target >= 0 && parser2.getGoto(this.stack[target], term, false) >= 0) | |
| 1890 | return rDepth << 19 | 65536 | term; | |
| 1891 | } | |
| 1892 | } else { | |
| 1893 | let found = explore(action, depth + 1); | |
| 1894 | if (found != null) | |
| 1895 | return found; | |
| 1896 | } | |
| 1897 | }); | |
| 1898 | }; | |
| 1899 | return explore(this.state, 0); | |
| 1900 | } | |
| 1901 | /** | |
| 1902 | @internal | |
| 1903 | */ | |
| 1904 | forceAll() { | |
| 1905 | while (!this.p.parser.stateFlag( | |
| 1906 | this.state, | |
| 1907 | 2 | |
| 1908 | /* StateFlag.Accepting */ | |
| 1909 | )) { | |
| 1910 | if (!this.forceReduce()) { | |
| 1911 | this.storeNode(0, this.pos, this.pos, 4, true); | |
| 1912 | break; | |
| 1913 | } | |
| 1914 | } | |
| 1915 | return this; | |
| 1916 | } | |
| 1917 | /** | |
| 1918 | Check whether this state has no further actions (assumed to be a direct descendant of the | |
| 1919 | top state, since any other states must be able to continue | |
| 1920 | somehow). @internal | |
| 1921 | */ | |
| 1922 | get deadEnd() { | |
| 1923 | if (this.stack.length != 3) | |
| 1924 | return false; | |
| 1925 | let { parser: parser2 } = this.p; | |
| 1926 | return parser2.data[parser2.stateSlot( | |
| 1927 | this.state, | |
| 1928 | 1 | |
| 1929 | /* ParseState.Actions */ | |
| 1930 | )] == 65535 && !parser2.stateSlot( | |
| 1931 | this.state, | |
| 1932 | 4 | |
| 1933 | /* ParseState.DefaultReduce */ | |
| 1934 | ); | |
| 1935 | } | |
| 1936 | /** | |
| 1937 | Restart the stack (put it back in its start state). Only safe | |
| 1938 | when this.stack.length == 3 (state is directly below the top | |
| 1939 | state). @internal | |
| 1940 | */ | |
| 1941 | restart() { | |
| 1942 | this.storeNode(0, this.pos, this.pos, 4, true); | |
| 1943 | this.state = this.stack[0]; | |
| 1944 | this.stack.length = 0; | |
| 1945 | } | |
| 1946 | /** | |
| 1947 | @internal | |
| 1948 | */ | |
| 1949 | sameState(other) { | |
| 1950 | if (this.state != other.state || this.stack.length != other.stack.length) | |
| 1951 | return false; | |
| 1952 | for (let i = 0; i < this.stack.length; i += 3) | |
| 1953 | if (this.stack[i] != other.stack[i]) | |
| 1954 | return false; | |
| 1955 | return true; | |
| 1956 | } | |
| 1957 | /** | |
| 1958 | Get the parser used by this stack. | |
| 1959 | */ | |
| 1960 | get parser() { | |
| 1961 | return this.p.parser; | |
| 1962 | } | |
| 1963 | /** | |
| 1964 | Test whether a given dialect (by numeric ID, as exported from | |
| 1965 | the terms file) is enabled. | |
| 1966 | */ | |
| 1967 | dialectEnabled(dialectID) { | |
| 1968 | return this.p.parser.dialect.flags[dialectID]; | |
| 1969 | } | |
| 1970 | shiftContext(term, start) { | |
| 1971 | if (this.curContext) | |
| 1972 | this.updateContext(this.curContext.tracker.shift(this.curContext.context, term, this, this.p.stream.reset(start))); | |
| 1973 | } | |
| 1974 | reduceContext(term, start) { | |
| 1975 | if (this.curContext) | |
| 1976 | this.updateContext(this.curContext.tracker.reduce(this.curContext.context, term, this, this.p.stream.reset(start))); | |
| 1977 | } | |
| 1978 | /** | |
| 1979 | @internal | |
| 1980 | */ | |
| 1981 | emitContext() { | |
| 1982 | let last = this.buffer.length - 1; | |
| 1983 | if (last < 0 || this.buffer[last] != -3) | |
| 1984 | this.buffer.push(this.curContext.hash, this.pos, this.pos, -3); | |
| 1985 | } | |
| 1986 | /** | |
| 1987 | @internal | |
| 1988 | */ | |
| 1989 | emitLookAhead() { | |
| 1990 | let last = this.buffer.length - 1; | |
| 1991 | if (last < 0 || this.buffer[last] != -4) | |
| 1992 | this.buffer.push(this.lookAhead, this.pos, this.pos, -4); | |
| 1993 | } | |
| 1994 | updateContext(context) { | |
| 1995 | if (context != this.curContext.context) { | |
| 1996 | let newCx = new StackContext(this.curContext.tracker, context); | |
| 1997 | if (newCx.hash != this.curContext.hash) | |
| 1998 | this.emitContext(); | |
| 1999 | this.curContext = newCx; | |
| 2000 | } | |
| 2001 | } | |
| 2002 | /** | |
| 2003 | @internal | |
| 2004 | */ | |
| 2005 | setLookAhead(lookAhead) { | |
| 2006 | if (lookAhead <= this.lookAhead) | |
| 2007 | return false; | |
| 2008 | this.emitLookAhead(); | |
| 2009 | this.lookAhead = lookAhead; | |
| 2010 | return true; | |
| 2011 | } | |
| 2012 | /** | |
| 2013 | @internal | |
| 2014 | */ | |
| 2015 | close() { | |
| 2016 | if (this.curContext && this.curContext.tracker.strict) | |
| 2017 | this.emitContext(); | |
| 2018 | if (this.lookAhead > 0) | |
| 2019 | this.emitLookAhead(); | |
| 2020 | } | |
| 2021 | }; | |
| 2022 | var StackContext = class { | |
| 2023 | constructor(tracker, context) { | |
| 2024 | this.tracker = tracker; | |
| 2025 | this.context = context; | |
| 2026 | this.hash = tracker.strict ? tracker.hash(context) : 0; | |
| 2027 | } | |
| 2028 | }; | |
| 2029 | var SimulatedStack = class { | |
| 2030 | constructor(start) { | |
| 2031 | this.start = start; | |
| 2032 | this.state = start.state; | |
| 2033 | this.stack = start.stack; | |
| 2034 | this.base = this.stack.length; | |
| 2035 | } | |
| 2036 | reduce(action) { | |
| 2037 | let term = action & 65535, depth = action >> 19; | |
| 2038 | if (depth == 0) { | |
| 2039 | if (this.stack == this.start.stack) | |
| 2040 | this.stack = this.stack.slice(); | |
| 2041 | this.stack.push(this.state, 0, 0); | |
| 2042 | this.base += 3; | |
| 2043 | } else { | |
| 2044 | this.base -= (depth - 1) * 3; | |
| 2045 | } | |
| 2046 | let goto = this.start.p.parser.getGoto(this.stack[this.base - 3], term, true); | |
| 2047 | this.state = goto; | |
| 2048 | } | |
| 2049 | }; | |
| 2050 | var StackBufferCursor = class _StackBufferCursor { | |
| 2051 | constructor(stack, pos, index) { | |
| 2052 | this.stack = stack; | |
| 2053 | this.pos = pos; | |
| 2054 | this.index = index; | |
| 2055 | this.buffer = stack.buffer; | |
| 2056 | if (this.index == 0) | |
| 2057 | this.maybeNext(); | |
| 2058 | } | |
| 2059 | static create(stack, pos = stack.bufferBase + stack.buffer.length) { | |
| 2060 | return new _StackBufferCursor(stack, pos, pos - stack.bufferBase); | |
| 2061 | } | |
| 2062 | maybeNext() { | |
| 2063 | let next = this.stack.parent; | |
| 2064 | if (next != null) { | |
| 2065 | this.index = this.stack.bufferBase - next.bufferBase; | |
| 2066 | this.stack = next; | |
| 2067 | this.buffer = next.buffer; | |
| 2068 | } | |
| 2069 | } | |
| 2070 | get id() { | |
| 2071 | return this.buffer[this.index - 4]; | |
| 2072 | } | |
| 2073 | get start() { | |
| 2074 | return this.buffer[this.index - 3]; | |
| 2075 | } | |
| 2076 | get end() { | |
| 2077 | return this.buffer[this.index - 2]; | |
| 2078 | } | |
| 2079 | get size() { | |
| 2080 | return this.buffer[this.index - 1]; | |
| 2081 | } | |
| 2082 | next() { | |
| 2083 | this.index -= 4; | |
| 2084 | this.pos -= 4; | |
| 2085 | if (this.index == 0) | |
| 2086 | this.maybeNext(); | |
| 2087 | } | |
| 2088 | fork() { | |
| 2089 | return new _StackBufferCursor(this.stack, this.pos, this.index); | |
| 2090 | } | |
| 2091 | }; | |
| 2092 | function decodeArray(input, Type = Uint16Array) { | |
| 2093 | if (typeof input != "string") | |
| 2094 | return input; | |
| 2095 | let array = null; | |
| 2096 | for (let pos = 0, out = 0; pos < input.length; ) { | |
| 2097 | let value = 0; | |
| 2098 | for (; ; ) { | |
| 2099 | let next = input.charCodeAt(pos++), stop = false; | |
| 2100 | if (next == 126) { | |
| 2101 | value = 65535; | |
| 2102 | break; | |
| 2103 | } | |
| 2104 | if (next >= 92) | |
| 2105 | next--; | |
| 2106 | if (next >= 34) | |
| 2107 | next--; | |
| 2108 | let digit = next - 32; | |
| 2109 | if (digit >= 46) { | |
| 2110 | digit -= 46; | |
| 2111 | stop = true; | |
| 2112 | } | |
| 2113 | value += digit; | |
| 2114 | if (stop) | |
| 2115 | break; | |
| 2116 | value *= 46; | |
| 2117 | } | |
| 2118 | if (array) | |
| 2119 | array[out++] = value; | |
| 2120 | else | |
| 2121 | array = new Type(value); | |
| 2122 | } | |
| 2123 | return array; | |
| 2124 | } | |
| 2125 | var CachedToken = class { | |
| 2126 | constructor() { | |
| 2127 | this.start = -1; | |
| 2128 | this.value = -1; | |
| 2129 | this.end = -1; | |
| 2130 | this.extended = -1; | |
| 2131 | this.lookAhead = 0; | |
| 2132 | this.mask = 0; | |
| 2133 | this.context = 0; | |
| 2134 | } | |
| 2135 | }; | |
| 2136 | var nullToken = new CachedToken(); | |
| 2137 | var InputStream = class { | |
| 2138 | /** | |
| 2139 | @internal | |
| 2140 | */ | |
| 2141 | constructor(input, ranges) { | |
| 2142 | this.input = input; | |
| 2143 | this.ranges = ranges; | |
| 2144 | this.chunk = ""; | |
| 2145 | this.chunkOff = 0; | |
| 2146 | this.chunk2 = ""; | |
| 2147 | this.chunk2Pos = 0; | |
| 2148 | this.next = -1; | |
| 2149 | this.token = nullToken; | |
| 2150 | this.rangeIndex = 0; | |
| 2151 | this.pos = this.chunkPos = ranges[0].from; | |
| 2152 | this.range = ranges[0]; | |
| 2153 | this.end = ranges[ranges.length - 1].to; | |
| 2154 | this.readNext(); | |
| 2155 | } | |
| 2156 | /** | |
| 2157 | @internal | |
| 2158 | */ | |
| 2159 | resolveOffset(offset, assoc) { | |
| 2160 | let range = this.range, index = this.rangeIndex; | |
| 2161 | let pos = this.pos + offset; | |
| 2162 | while (pos < range.from) { | |
| 2163 | if (!index) | |
| 2164 | return null; | |
| 2165 | let next = this.ranges[--index]; | |
| 2166 | pos -= range.from - next.to; | |
| 2167 | range = next; | |
| 2168 | } | |
| 2169 | while (assoc < 0 ? pos > range.to : pos >= range.to) { | |
| 2170 | if (index == this.ranges.length - 1) | |
| 2171 | return null; | |
| 2172 | let next = this.ranges[++index]; | |
| 2173 | pos += next.from - range.to; | |
| 2174 | range = next; | |
| 2175 | } | |
| 2176 | return pos; | |
| 2177 | } | |
| 2178 | /** | |
| 2179 | @internal | |
| 2180 | */ | |
| 2181 | clipPos(pos) { | |
| 2182 | if (pos >= this.range.from && pos < this.range.to) | |
| 2183 | return pos; | |
| 2184 | for (let range of this.ranges) | |
| 2185 | if (range.to > pos) | |
| 2186 | return Math.max(pos, range.from); | |
| 2187 | return this.end; | |
| 2188 | } | |
| 2189 | /** | |
| 2190 | Look at a code unit near the stream position. `.peek(0)` equals | |
| 2191 | `.next`, `.peek(-1)` gives you the previous character, and so | |
| 2192 | on. | |
| 2193 | ||
| 2194 | Note that looking around during tokenizing creates dependencies | |
| 2195 | on potentially far-away content, which may reduce the | |
| 2196 | effectiveness incremental parsing—when looking forward—or even | |
| 2197 | cause invalid reparses when looking backward more than 25 code | |
| 2198 | units, since the library does not track lookbehind. | |
| 2199 | */ | |
| 2200 | peek(offset) { | |
| 2201 | let idx = this.chunkOff + offset, pos, result; | |
| 2202 | if (idx >= 0 && idx < this.chunk.length) { | |
| 2203 | pos = this.pos + offset; | |
| 2204 | result = this.chunk.charCodeAt(idx); | |
| 2205 | } else { | |
| 2206 | let resolved = this.resolveOffset(offset, 1); | |
| 2207 | if (resolved == null) | |
| 2208 | return -1; | |
| 2209 | pos = resolved; | |
| 2210 | if (pos >= this.chunk2Pos && pos < this.chunk2Pos + this.chunk2.length) { | |
| 2211 | result = this.chunk2.charCodeAt(pos - this.chunk2Pos); | |
| 2212 | } else { | |
| 2213 | let i = this.rangeIndex, range = this.range; | |
| 2214 | while (range.to <= pos) | |
| 2215 | range = this.ranges[++i]; | |
| 2216 | this.chunk2 = this.input.chunk(this.chunk2Pos = pos); | |
| 2217 | if (pos + this.chunk2.length > range.to) | |
| 2218 | this.chunk2 = this.chunk2.slice(0, range.to - pos); | |
| 2219 | result = this.chunk2.charCodeAt(0); | |
| 2220 | } | |
| 2221 | } | |
| 2222 | if (pos >= this.token.lookAhead) | |
| 2223 | this.token.lookAhead = pos + 1; | |
| 2224 | return result; | |
| 2225 | } | |
| 2226 | /** | |
| 2227 | Accept a token. By default, the end of the token is set to the | |
| 2228 | current stream position, but you can pass an offset (relative to | |
| 2229 | the stream position) to change that. | |
| 2230 | */ | |
| 2231 | acceptToken(token, endOffset = 0) { | |
| 2232 | let end = endOffset ? this.resolveOffset(endOffset, -1) : this.pos; | |
| 2233 | if (end == null || end < this.token.start) | |
| 2234 | throw new RangeError("Token end out of bounds"); | |
| 2235 | this.token.value = token; | |
| 2236 | this.token.end = end; | |
| 2237 | } | |
| 2238 | /** | |
| 2239 | Accept a token ending at a specific given position. | |
| 2240 | */ | |
| 2241 | acceptTokenTo(token, endPos) { | |
| 2242 | this.token.value = token; | |
| 2243 | this.token.end = endPos; | |
| 2244 | } | |
| 2245 | getChunk() { | |
| 2246 | if (this.pos >= this.chunk2Pos && this.pos < this.chunk2Pos + this.chunk2.length) { | |
| 2247 | let { chunk, chunkPos } = this; | |
| 2248 | this.chunk = this.chunk2; | |
| 2249 | this.chunkPos = this.chunk2Pos; | |
| 2250 | this.chunk2 = chunk; | |
| 2251 | this.chunk2Pos = chunkPos; | |
| 2252 | this.chunkOff = this.pos - this.chunkPos; | |
| 2253 | } else { | |
| 2254 | this.chunk2 = this.chunk; | |
| 2255 | this.chunk2Pos = this.chunkPos; | |
| 2256 | let nextChunk = this.input.chunk(this.pos); | |
| 2257 | let end = this.pos + nextChunk.length; | |
| 2258 | this.chunk = end > this.range.to ? nextChunk.slice(0, this.range.to - this.pos) : nextChunk; | |
| 2259 | this.chunkPos = this.pos; | |
| 2260 | this.chunkOff = 0; | |
| 2261 | } | |
| 2262 | } | |
| 2263 | readNext() { | |
| 2264 | if (this.chunkOff >= this.chunk.length) { | |
| 2265 | this.getChunk(); | |
| 2266 | if (this.chunkOff == this.chunk.length) | |
| 2267 | return this.next = -1; | |
| 2268 | } | |
| 2269 | return this.next = this.chunk.charCodeAt(this.chunkOff); | |
| 2270 | } | |
| 2271 | /** | |
| 2272 | Move the stream forward N (defaults to 1) code units. Returns | |
| 2273 | the new value of [`next`](#lr.InputStream.next). | |
| 2274 | */ | |
| 2275 | advance(n = 1) { | |
| 2276 | this.chunkOff += n; | |
| 2277 | while (this.pos + n >= this.range.to) { | |
| 2278 | if (this.rangeIndex == this.ranges.length - 1) | |
| 2279 | return this.setDone(); | |
| 2280 | n -= this.range.to - this.pos; | |
| 2281 | this.range = this.ranges[++this.rangeIndex]; | |
| 2282 | this.pos = this.range.from; | |
| 2283 | } | |
| 2284 | this.pos += n; | |
| 2285 | if (this.pos >= this.token.lookAhead) | |
| 2286 | this.token.lookAhead = this.pos + 1; | |
| 2287 | return this.readNext(); | |
| 2288 | } | |
| 2289 | setDone() { | |
| 2290 | this.pos = this.chunkPos = this.end; | |
| 2291 | this.range = this.ranges[this.rangeIndex = this.ranges.length - 1]; | |
| 2292 | this.chunk = ""; | |
| 2293 | return this.next = -1; | |
| 2294 | } | |
| 2295 | /** | |
| 2296 | @internal | |
| 2297 | */ | |
| 2298 | reset(pos, token) { | |
| 2299 | if (token) { | |
| 2300 | this.token = token; | |
| 2301 | token.start = pos; | |
| 2302 | token.lookAhead = pos + 1; | |
| 2303 | token.value = token.extended = -1; | |
| 2304 | } else { | |
| 2305 | this.token = nullToken; | |
| 2306 | } | |
| 2307 | if (this.pos != pos) { | |
| 2308 | this.pos = pos; | |
| 2309 | if (pos == this.end) { | |
| 2310 | this.setDone(); | |
| 2311 | return this; | |
| 2312 | } | |
| 2313 | while (pos < this.range.from) | |
| 2314 | this.range = this.ranges[--this.rangeIndex]; | |
| 2315 | while (pos >= this.range.to) | |
| 2316 | this.range = this.ranges[++this.rangeIndex]; | |
| 2317 | if (pos >= this.chunkPos && pos < this.chunkPos + this.chunk.length) { | |
| 2318 | this.chunkOff = pos - this.chunkPos; | |
| 2319 | } else { | |
| 2320 | this.chunk = ""; | |
| 2321 | this.chunkOff = 0; | |
| 2322 | } | |
| 2323 | this.readNext(); | |
| 2324 | } | |
| 2325 | return this; | |
| 2326 | } | |
| 2327 | /** | |
| 2328 | @internal | |
| 2329 | */ | |
| 2330 | read(from, to) { | |
| 2331 | if (from >= this.chunkPos && to <= this.chunkPos + this.chunk.length) | |
| 2332 | return this.chunk.slice(from - this.chunkPos, to - this.chunkPos); | |
| 2333 | if (from >= this.chunk2Pos && to <= this.chunk2Pos + this.chunk2.length) | |
| 2334 | return this.chunk2.slice(from - this.chunk2Pos, to - this.chunk2Pos); | |
| 2335 | if (from >= this.range.from && to <= this.range.to) | |
| 2336 | return this.input.read(from, to); | |
| 2337 | let result = ""; | |
| 2338 | for (let r of this.ranges) { | |
| 2339 | if (r.from >= to) | |
| 2340 | break; | |
| 2341 | if (r.to > from) | |
| 2342 | result += this.input.read(Math.max(r.from, from), Math.min(r.to, to)); | |
| 2343 | } | |
| 2344 | return result; | |
| 2345 | } | |
| 2346 | }; | |
| 2347 | var TokenGroup = class { | |
| 2348 | constructor(data, id2) { | |
| 2349 | this.data = data; | |
| 2350 | this.id = id2; | |
| 2351 | } | |
| 2352 | token(input, stack) { | |
| 2353 | let { parser: parser2 } = stack.p; | |
| 2354 | readToken(this.data, input, stack, this.id, parser2.data, parser2.tokenPrecTable); | |
| 2355 | } | |
| 2356 | }; | |
| 2357 | TokenGroup.prototype.contextual = TokenGroup.prototype.fallback = TokenGroup.prototype.extend = false; | |
| 2358 | var LocalTokenGroup = class { | |
| 2359 | constructor(data, precTable, elseToken) { | |
| 2360 | this.precTable = precTable; | |
| 2361 | this.elseToken = elseToken; | |
| 2362 | this.data = typeof data == "string" ? decodeArray(data) : data; | |
| 2363 | } | |
| 2364 | token(input, stack) { | |
| 2365 | let start = input.pos, skipped = 0; | |
| 2366 | for (; ; ) { | |
| 2367 | let atEof = input.next < 0, nextPos = input.resolveOffset(1, 1); | |
| 2368 | readToken(this.data, input, stack, 0, this.data, this.precTable); | |
| 2369 | if (input.token.value > -1) | |
| 2370 | break; | |
| 2371 | if (this.elseToken == null) | |
| 2372 | return; | |
| 2373 | if (!atEof) | |
| 2374 | skipped++; | |
| 2375 | if (nextPos == null) | |
| 2376 | break; | |
| 2377 | input.reset(nextPos, input.token); | |
| 2378 | } | |
| 2379 | if (skipped) { | |
| 2380 | input.reset(start, input.token); | |
| 2381 | input.acceptToken(this.elseToken, skipped); | |
| 2382 | } | |
| 2383 | } | |
| 2384 | }; | |
| 2385 | LocalTokenGroup.prototype.contextual = TokenGroup.prototype.fallback = TokenGroup.prototype.extend = false; | |
| 2386 | var ExternalTokenizer = class { | |
| 2387 | /** | |
| 2388 | Create a tokenizer. The first argument is the function that, | |
| 2389 | given an input stream, scans for the types of tokens it | |
| 2390 | recognizes at the stream's position, and calls | |
| 2391 | [`acceptToken`](#lr.InputStream.acceptToken) when it finds | |
| 2392 | one. | |
| 2393 | */ | |
| 2394 | constructor(token, options = {}) { | |
| 2395 | this.token = token; | |
| 2396 | this.contextual = !!options.contextual; | |
| 2397 | this.fallback = !!options.fallback; | |
| 2398 | this.extend = !!options.extend; | |
| 2399 | } | |
| 2400 | }; | |
| 2401 | function readToken(data, input, stack, group, precTable, precOffset) { | |
| 2402 | let state = 0, groupMask = 1 << group, { dialect } = stack.p.parser; | |
| 2403 | scan: for (; ; ) { | |
| 2404 | if ((groupMask & data[state]) == 0) | |
| 2405 | break; | |
| 2406 | let accEnd = data[state + 1]; | |
| 2407 | for (let i = state + 3; i < accEnd; i += 2) | |
| 2408 | if ((data[i + 1] & groupMask) > 0) { | |
| 2409 | let term = data[i]; | |
| 2410 | if (dialect.allows(term) && (input.token.value == -1 || input.token.value == term || overrides(term, input.token.value, precTable, precOffset))) { | |
| 2411 | input.acceptToken(term); | |
| 2412 | break; | |
| 2413 | } | |
| 2414 | } | |
| 2415 | let next = input.next, low = 0, high = data[state + 2]; | |
| 2416 | if (input.next < 0 && high > low && data[accEnd + high * 3 - 3] == 65535) { | |
| 2417 | state = data[accEnd + high * 3 - 1]; | |
| 2418 | continue scan; | |
| 2419 | } | |
| 2420 | for (; low < high; ) { | |
| 2421 | let mid = low + high >> 1; | |
| 2422 | let index = accEnd + mid + (mid << 1); | |
| 2423 | let from = data[index], to = data[index + 1] || 65536; | |
| 2424 | if (next < from) | |
| 2425 | high = mid; | |
| 2426 | else if (next >= to) | |
| 2427 | low = mid + 1; | |
| 2428 | else { | |
| 2429 | state = data[index + 2]; | |
| 2430 | input.advance(); | |
| 2431 | continue scan; | |
| 2432 | } | |
| 2433 | } | |
| 2434 | break; | |
| 2435 | } | |
| 2436 | } | |
| 2437 | function findOffset(data, start, term) { | |
| 2438 | for (let i = start, next; (next = data[i]) != 65535; i++) | |
| 2439 | if (next == term) | |
| 2440 | return i - start; | |
| 2441 | return -1; | |
| 2442 | } | |
| 2443 | function overrides(token, prev, tableData, tableOffset) { | |
| 2444 | let iPrev = findOffset(tableData, tableOffset, prev); | |
| 2445 | return iPrev < 0 || findOffset(tableData, tableOffset, token) < iPrev; | |
| 2446 | } | |
| 2447 | var verbose = typeof process != "undefined" && process.env && /\bparse\b/.test(process.env.LOG); | |
| 2448 | var stackIDs = null; | |
| 2449 | function cutAt(tree, pos, side) { | |
| 2450 | let cursor = tree.cursor(IterMode.IncludeAnonymous); | |
| 2451 | cursor.moveTo(pos); | |
| 2452 | for (; ; ) { | |
| 2453 | if (!(side < 0 ? cursor.childBefore(pos) : cursor.childAfter(pos))) | |
| 2454 | for (; ; ) { | |
| 2455 | if ((side < 0 ? cursor.to < pos : cursor.from > pos) && !cursor.type.isError) | |
| 2456 | return side < 0 ? Math.max(0, Math.min( | |
| 2457 | cursor.to - 1, | |
| 2458 | pos - 25 | |
| 2459 | /* Lookahead.Margin */ | |
| 2460 | )) : Math.min(tree.length, Math.max( | |
| 2461 | cursor.from + 1, | |
| 2462 | pos + 25 | |
| 2463 | /* Lookahead.Margin */ | |
| 2464 | )); | |
| 2465 | if (side < 0 ? cursor.prevSibling() : cursor.nextSibling()) | |
| 2466 | break; | |
| 2467 | if (!cursor.parent()) | |
| 2468 | return side < 0 ? 0 : tree.length; | |
| 2469 | } | |
| 2470 | } | |
| 2471 | } | |
| 2472 | var FragmentCursor = class { | |
| 2473 | constructor(fragments, nodeSet) { | |
| 2474 | this.fragments = fragments; | |
| 2475 | this.nodeSet = nodeSet; | |
| 2476 | this.i = 0; | |
| 2477 | this.fragment = null; | |
| 2478 | this.safeFrom = -1; | |
| 2479 | this.safeTo = -1; | |
| 2480 | this.trees = []; | |
| 2481 | this.start = []; | |
| 2482 | this.index = []; | |
| 2483 | this.nextFragment(); | |
| 2484 | } | |
| 2485 | nextFragment() { | |
| 2486 | let fr = this.fragment = this.i == this.fragments.length ? null : this.fragments[this.i++]; | |
| 2487 | if (fr) { | |
| 2488 | this.safeFrom = fr.openStart ? cutAt(fr.tree, fr.from + fr.offset, 1) - fr.offset : fr.from; | |
| 2489 | this.safeTo = fr.openEnd ? cutAt(fr.tree, fr.to + fr.offset, -1) - fr.offset : fr.to; | |
| 2490 | while (this.trees.length) { | |
| 2491 | this.trees.pop(); | |
| 2492 | this.start.pop(); | |
| 2493 | this.index.pop(); | |
| 2494 | } | |
| 2495 | this.trees.push(fr.tree); | |
| 2496 | this.start.push(-fr.offset); | |
| 2497 | this.index.push(0); | |
| 2498 | this.nextStart = this.safeFrom; | |
| 2499 | } else { | |
| 2500 | this.nextStart = 1e9; | |
| 2501 | } | |
| 2502 | } | |
| 2503 | // `pos` must be >= any previously given `pos` for this cursor | |
| 2504 | nodeAt(pos) { | |
| 2505 | if (pos < this.nextStart) | |
| 2506 | return null; | |
| 2507 | while (this.fragment && this.safeTo <= pos) | |
| 2508 | this.nextFragment(); | |
| 2509 | if (!this.fragment) | |
| 2510 | return null; | |
| 2511 | for (; ; ) { | |
| 2512 | let last = this.trees.length - 1; | |
| 2513 | if (last < 0) { | |
| 2514 | this.nextFragment(); | |
| 2515 | return null; | |
| 2516 | } | |
| 2517 | let top = this.trees[last], index = this.index[last]; | |
| 2518 | if (index == top.children.length) { | |
| 2519 | this.trees.pop(); | |
| 2520 | this.start.pop(); | |
| 2521 | this.index.pop(); | |
| 2522 | continue; | |
| 2523 | } | |
| 2524 | let next = top.children[index]; | |
| 2525 | let start = this.start[last] + top.positions[index]; | |
| 2526 | if (start > pos) { | |
| 2527 | this.nextStart = start; | |
| 2528 | return null; | |
| 2529 | } | |
| 2530 | if (next instanceof Tree) { | |
| 2531 | if (start == pos) { | |
| 2532 | if (start < this.safeFrom) | |
| 2533 | return null; | |
| 2534 | let end = start + next.length; | |
| 2535 | if (end <= this.safeTo) { | |
| 2536 | let lookAhead = next.prop(NodeProp.lookAhead); | |
| 2537 | if (!lookAhead || end + lookAhead < this.fragment.to) | |
| 2538 | return next; | |
| 2539 | } | |
| 2540 | } | |
| 2541 | this.index[last]++; | |
| 2542 | if (start + next.length >= Math.max(this.safeFrom, pos)) { | |
| 2543 | this.trees.push(next); | |
| 2544 | this.start.push(start); | |
| 2545 | this.index.push(0); | |
| 2546 | } | |
| 2547 | } else { | |
| 2548 | this.index[last]++; | |
| 2549 | this.nextStart = start + next.length; | |
| 2550 | } | |
| 2551 | } | |
| 2552 | } | |
| 2553 | }; | |
| 2554 | var TokenCache = class { | |
| 2555 | constructor(parser2, stream) { | |
| 2556 | this.stream = stream; | |
| 2557 | this.tokens = []; | |
| 2558 | this.mainToken = null; | |
| 2559 | this.actions = []; | |
| 2560 | this.tokens = parser2.tokenizers.map((_) => new CachedToken()); | |
| 2561 | } | |
| 2562 | getActions(stack) { | |
| 2563 | let actionIndex = 0; | |
| 2564 | let main = null; | |
| 2565 | let { parser: parser2 } = stack.p, { tokenizers } = parser2; | |
| 2566 | let mask = parser2.stateSlot( | |
| 2567 | stack.state, | |
| 2568 | 3 | |
| 2569 | /* ParseState.TokenizerMask */ | |
| 2570 | ); | |
| 2571 | let context = stack.curContext ? stack.curContext.hash : 0; | |
| 2572 | let lookAhead = 0; | |
| 2573 | for (let i = 0; i < tokenizers.length; i++) { | |
| 2574 | if ((1 << i & mask) == 0) | |
| 2575 | continue; | |
| 2576 | let tokenizer = tokenizers[i], token = this.tokens[i]; | |
| 2577 | if (main && !tokenizer.fallback) | |
| 2578 | continue; | |
| 2579 | if (tokenizer.contextual || token.start != stack.pos || token.mask != mask || token.context != context) { | |
| 2580 | this.updateCachedToken(token, tokenizer, stack); | |
| 2581 | token.mask = mask; | |
| 2582 | token.context = context; | |
| 2583 | } | |
| 2584 | if (token.lookAhead > token.end + 25) | |
| 2585 | lookAhead = Math.max(token.lookAhead, lookAhead); | |
| 2586 | if (token.value != 0) { | |
| 2587 | let startIndex = actionIndex; | |
| 2588 | if (token.extended > -1) | |
| 2589 | actionIndex = this.addActions(stack, token.extended, token.end, actionIndex); | |
| 2590 | actionIndex = this.addActions(stack, token.value, token.end, actionIndex); | |
| 2591 | if (!tokenizer.extend) { | |
| 2592 | main = token; | |
| 2593 | if (actionIndex > startIndex) | |
| 2594 | break; | |
| 2595 | } | |
| 2596 | } | |
| 2597 | } | |
| 2598 | while (this.actions.length > actionIndex) | |
| 2599 | this.actions.pop(); | |
| 2600 | if (lookAhead) | |
| 2601 | stack.setLookAhead(lookAhead); | |
| 2602 | if (!main && stack.pos == this.stream.end) { | |
| 2603 | main = new CachedToken(); | |
| 2604 | main.value = stack.p.parser.eofTerm; | |
| 2605 | main.start = main.end = stack.pos; | |
| 2606 | actionIndex = this.addActions(stack, main.value, main.end, actionIndex); | |
| 2607 | } | |
| 2608 | this.mainToken = main; | |
| 2609 | return this.actions; | |
| 2610 | } | |
| 2611 | getMainToken(stack) { | |
| 2612 | if (this.mainToken) | |
| 2613 | return this.mainToken; | |
| 2614 | let main = new CachedToken(), { pos, p } = stack; | |
| 2615 | main.start = pos; | |
| 2616 | main.end = Math.min(pos + 1, p.stream.end); | |
| 2617 | main.value = pos == p.stream.end ? p.parser.eofTerm : 0; | |
| 2618 | return main; | |
| 2619 | } | |
| 2620 | updateCachedToken(token, tokenizer, stack) { | |
| 2621 | let start = this.stream.clipPos(stack.pos); | |
| 2622 | tokenizer.token(this.stream.reset(start, token), stack); | |
| 2623 | if (token.value > -1) { | |
| 2624 | let { parser: parser2 } = stack.p; | |
| 2625 | for (let i = 0; i < parser2.specialized.length; i++) | |
| 2626 | if (parser2.specialized[i] == token.value) { | |
| 2627 | let result = parser2.specializers[i](this.stream.read(token.start, token.end), stack); | |
| 2628 | if (result >= 0 && stack.p.parser.dialect.allows(result >> 1)) { | |
| 2629 | if ((result & 1) == 0) | |
| 2630 | token.value = result >> 1; | |
| 2631 | else | |
| 2632 | token.extended = result >> 1; | |
| 2633 | break; | |
| 2634 | } | |
| 2635 | } | |
| 2636 | } else { | |
| 2637 | token.value = 0; | |
| 2638 | token.end = this.stream.clipPos(start + 1); | |
| 2639 | } | |
| 2640 | } | |
| 2641 | putAction(action, token, end, index) { | |
| 2642 | for (let i = 0; i < index; i += 3) | |
| 2643 | if (this.actions[i] == action) | |
| 2644 | return index; | |
| 2645 | this.actions[index++] = action; | |
| 2646 | this.actions[index++] = token; | |
| 2647 | this.actions[index++] = end; | |
| 2648 | return index; | |
| 2649 | } | |
| 2650 | addActions(stack, token, end, index) { | |
| 2651 | let { state } = stack, { parser: parser2 } = stack.p, { data } = parser2; | |
| 2652 | for (let set = 0; set < 2; set++) { | |
| 2653 | for (let i = parser2.stateSlot( | |
| 2654 | state, | |
| 2655 | set ? 2 : 1 | |
| 2656 | /* ParseState.Actions */ | |
| 2657 | ); ; i += 3) { | |
| 2658 | if (data[i] == 65535) { | |
| 2659 | if (data[i + 1] == 1) { | |
| 2660 | i = pair(data, i + 2); | |
| 2661 | } else { | |
| 2662 | if (index == 0 && data[i + 1] == 2) | |
| 2663 | index = this.putAction(pair(data, i + 2), token, end, index); | |
| 2664 | break; | |
| 2665 | } | |
| 2666 | } | |
| 2667 | if (data[i] == token) | |
| 2668 | index = this.putAction(pair(data, i + 1), token, end, index); | |
| 2669 | } | |
| 2670 | } | |
| 2671 | return index; | |
| 2672 | } | |
| 2673 | }; | |
| 2674 | var Parse = class { | |
| 2675 | constructor(parser2, input, fragments, ranges) { | |
| 2676 | this.parser = parser2; | |
| 2677 | this.input = input; | |
| 2678 | this.ranges = ranges; | |
| 2679 | this.recovering = 0; | |
| 2680 | this.nextStackID = 9812; | |
| 2681 | this.minStackPos = 0; | |
| 2682 | this.reused = []; | |
| 2683 | this.stoppedAt = null; | |
| 2684 | this.lastBigReductionStart = -1; | |
| 2685 | this.lastBigReductionSize = 0; | |
| 2686 | this.bigReductionCount = 0; | |
| 2687 | this.stream = new InputStream(input, ranges); | |
| 2688 | this.tokens = new TokenCache(parser2, this.stream); | |
| 2689 | this.topTerm = parser2.top[1]; | |
| 2690 | let { from } = ranges[0]; | |
| 2691 | this.stacks = [Stack.start(this, parser2.top[0], from)]; | |
| 2692 | this.fragments = fragments.length && this.stream.end - from > parser2.bufferLength * 4 ? new FragmentCursor(fragments, parser2.nodeSet) : null; | |
| 2693 | } | |
| 2694 | get parsedPos() { | |
| 2695 | return this.minStackPos; | |
| 2696 | } | |
| 2697 | // Move the parser forward. This will process all parse stacks at | |
| 2698 | // `this.pos` and try to advance them to a further position. If no | |
| 2699 | // stack for such a position is found, it'll start error-recovery. | |
| 2700 | // | |
| 2701 | // When the parse is finished, this will return a syntax tree. When | |
| 2702 | // not, it returns `null`. | |
| 2703 | advance() { | |
| 2704 | let stacks = this.stacks, pos = this.minStackPos; | |
| 2705 | let newStacks = this.stacks = []; | |
| 2706 | let stopped, stoppedTokens; | |
| 2707 | if (this.bigReductionCount > 300 && stacks.length == 1) { | |
| 2708 | let [s] = stacks; | |
| 2709 | while (s.forceReduce() && s.stack.length && s.stack[s.stack.length - 2] >= this.lastBigReductionStart) { | |
| 2710 | } | |
| 2711 | this.bigReductionCount = this.lastBigReductionSize = 0; | |
| 2712 | } | |
| 2713 | for (let i = 0; i < stacks.length; i++) { | |
| 2714 | let stack = stacks[i]; | |
| 2715 | for (; ; ) { | |
| 2716 | this.tokens.mainToken = null; | |
| 2717 | if (stack.pos > pos) { | |
| 2718 | newStacks.push(stack); | |
| 2719 | } else if (this.advanceStack(stack, newStacks, stacks)) { | |
| 2720 | continue; | |
| 2721 | } else { | |
| 2722 | if (!stopped) { | |
| 2723 | stopped = []; | |
| 2724 | stoppedTokens = []; | |
| 2725 | } | |
| 2726 | stopped.push(stack); | |
| 2727 | let tok = this.tokens.getMainToken(stack); | |
| 2728 | stoppedTokens.push(tok.value, tok.end); | |
| 2729 | } | |
| 2730 | break; | |
| 2731 | } | |
| 2732 | } | |
| 2733 | if (!newStacks.length) { | |
| 2734 | let finished = stopped && findFinished(stopped); | |
| 2735 | if (finished) { | |
| 2736 | if (verbose) | |
| 2737 | console.log("Finish with " + this.stackID(finished)); | |
| 2738 | return this.stackToTree(finished); | |
| 2739 | } | |
| 2740 | if (this.parser.strict) { | |
| 2741 | if (verbose && stopped) | |
| 2742 | console.log("Stuck with token " + (this.tokens.mainToken ? this.parser.getName(this.tokens.mainToken.value) : "none")); | |
| 2743 | throw new SyntaxError("No parse at " + pos); | |
| 2744 | } | |
| 2745 | if (!this.recovering) | |
| 2746 | this.recovering = 5; | |
| 2747 | } | |
| 2748 | if (this.recovering && stopped) { | |
| 2749 | let finished = this.stoppedAt != null && stopped[0].pos > this.stoppedAt ? stopped[0] : this.runRecovery(stopped, stoppedTokens, newStacks); | |
| 2750 | if (finished) { | |
| 2751 | if (verbose) | |
| 2752 | console.log("Force-finish " + this.stackID(finished)); | |
| 2753 | return this.stackToTree(finished.forceAll()); | |
| 2754 | } | |
| 2755 | } | |
| 2756 | if (this.recovering) { | |
| 2757 | let maxRemaining = this.recovering == 1 ? 1 : this.recovering * 3; | |
| 2758 | if (newStacks.length > maxRemaining) { | |
| 2759 | newStacks.sort((a, b) => b.score - a.score); | |
| 2760 | while (newStacks.length > maxRemaining) | |
| 2761 | newStacks.pop(); | |
| 2762 | } | |
| 2763 | if (newStacks.some((s) => s.reducePos > pos)) | |
| 2764 | this.recovering--; | |
| 2765 | } else if (newStacks.length > 1) { | |
| 2766 | outer: for (let i = 0; i < newStacks.length - 1; i++) { | |
| 2767 | let stack = newStacks[i]; | |
| 2768 | for (let j = i + 1; j < newStacks.length; j++) { | |
| 2769 | let other = newStacks[j]; | |
| 2770 | if (stack.sameState(other) || stack.buffer.length > 500 && other.buffer.length > 500) { | |
| 2771 | if ((stack.score - other.score || stack.buffer.length - other.buffer.length) > 0) { | |
| 2772 | newStacks.splice(j--, 1); | |
| 2773 | } else { | |
| 2774 | newStacks.splice(i--, 1); | |
| 2775 | continue outer; | |
| 2776 | } | |
| 2777 | } | |
| 2778 | } | |
| 2779 | } | |
| 2780 | if (newStacks.length > 12) { | |
| 2781 | newStacks.sort((a, b) => b.score - a.score); | |
| 2782 | newStacks.splice( | |
| 2783 | 12, | |
| 2784 | newStacks.length - 12 | |
| 2785 | /* Rec.MaxStackCount */ | |
| 2786 | ); | |
| 2787 | } | |
| 2788 | } | |
| 2789 | this.minStackPos = newStacks[0].pos; | |
| 2790 | for (let i = 1; i < newStacks.length; i++) | |
| 2791 | if (newStacks[i].pos < this.minStackPos) | |
| 2792 | this.minStackPos = newStacks[i].pos; | |
| 2793 | return null; | |
| 2794 | } | |
| 2795 | stopAt(pos) { | |
| 2796 | if (this.stoppedAt != null && this.stoppedAt < pos) | |
| 2797 | throw new RangeError("Can't move stoppedAt forward"); | |
| 2798 | this.stoppedAt = pos; | |
| 2799 | } | |
| 2800 | // Returns an updated version of the given stack, or null if the | |
| 2801 | // stack can't advance normally. When `split` and `stacks` are | |
| 2802 | // given, stacks split off by ambiguous operations will be pushed to | |
| 2803 | // `split`, or added to `stacks` if they move `pos` forward. | |
| 2804 | advanceStack(stack, stacks, split) { | |
| 2805 | let start = stack.pos, { parser: parser2 } = this; | |
| 2806 | let base = verbose ? this.stackID(stack) + " -> " : ""; | |
| 2807 | if (this.stoppedAt != null && start > this.stoppedAt) | |
| 2808 | return stack.forceReduce() ? stack : null; | |
| 2809 | if (this.fragments) { | |
| 2810 | let strictCx = stack.curContext && stack.curContext.tracker.strict, cxHash = strictCx ? stack.curContext.hash : 0; | |
| 2811 | for (let cached = this.fragments.nodeAt(start); cached; ) { | |
| 2812 | let match = this.parser.nodeSet.types[cached.type.id] == cached.type ? parser2.getGoto(stack.state, cached.type.id) : -1; | |
| 2813 | if (match > -1 && cached.length && (!strictCx || (cached.prop(NodeProp.contextHash) || 0) == cxHash)) { | |
| 2814 | stack.useNode(cached, match); | |
| 2815 | if (verbose) | |
| 2816 | console.log(base + this.stackID(stack) + ` (via reuse of ${parser2.getName(cached.type.id)})`); | |
| 2817 | return true; | |
| 2818 | } | |
| 2819 | if (!(cached instanceof Tree) || cached.children.length == 0 || cached.positions[0] > 0) | |
| 2820 | break; | |
| 2821 | let inner = cached.children[0]; | |
| 2822 | if (inner instanceof Tree && cached.positions[0] == 0) | |
| 2823 | cached = inner; | |
| 2824 | else | |
| 2825 | break; | |
| 2826 | } | |
| 2827 | } | |
| 2828 | let defaultReduce = parser2.stateSlot( | |
| 2829 | stack.state, | |
| 2830 | 4 | |
| 2831 | /* ParseState.DefaultReduce */ | |
| 2832 | ); | |
| 2833 | if (defaultReduce > 0) { | |
| 2834 | stack.reduce(defaultReduce); | |
| 2835 | if (verbose) | |
| 2836 | console.log(base + this.stackID(stack) + ` (via always-reduce ${parser2.getName( | |
| 2837 | defaultReduce & 65535 | |
| 2838 | /* Action.ValueMask */ | |
| 2839 | )})`); | |
| 2840 | return true; | |
| 2841 | } | |
| 2842 | if (stack.stack.length >= 8400) { | |
| 2843 | while (stack.stack.length > 6e3 && stack.forceReduce()) { | |
| 2844 | } | |
| 2845 | } | |
| 2846 | let actions = this.tokens.getActions(stack); | |
| 2847 | for (let i = 0; i < actions.length; ) { | |
| 2848 | let action = actions[i++], term = actions[i++], end = actions[i++]; | |
| 2849 | let last = i == actions.length || !split; | |
| 2850 | let localStack = last ? stack : stack.split(); | |
| 2851 | let main = this.tokens.mainToken; | |
| 2852 | localStack.apply(action, term, main ? main.start : localStack.pos, end); | |
| 2853 | if (verbose) | |
| 2854 | console.log(base + this.stackID(localStack) + ` (via ${(action & 65536) == 0 ? "shift" : `reduce of ${parser2.getName( | |
| 2855 | action & 65535 | |
| 2856 | /* Action.ValueMask */ | |
| 2857 | )}`} for ${parser2.getName(term)} @ ${start}${localStack == stack ? "" : ", split"})`); | |
| 2858 | if (last) | |
| 2859 | return true; | |
| 2860 | else if (localStack.pos > start) | |
| 2861 | stacks.push(localStack); | |
| 2862 | else | |
| 2863 | split.push(localStack); | |
| 2864 | } | |
| 2865 | return false; | |
| 2866 | } | |
| 2867 | // Advance a given stack forward as far as it will go. Returns the | |
| 2868 | // (possibly updated) stack if it got stuck, or null if it moved | |
| 2869 | // forward and was given to `pushStackDedup`. | |
| 2870 | advanceFully(stack, newStacks) { | |
| 2871 | let pos = stack.pos; | |
| 2872 | for (; ; ) { | |
| 2873 | if (!this.advanceStack(stack, null, null)) | |
| 2874 | return false; | |
| 2875 | if (stack.pos > pos) { | |
| 2876 | pushStackDedup(stack, newStacks); | |
| 2877 | return true; | |
| 2878 | } | |
| 2879 | } | |
| 2880 | } | |
| 2881 | runRecovery(stacks, tokens, newStacks) { | |
| 2882 | let finished = null, restarted = false; | |
| 2883 | for (let i = 0; i < stacks.length; i++) { | |
| 2884 | let stack = stacks[i], token = tokens[i << 1], tokenEnd = tokens[(i << 1) + 1]; | |
| 2885 | let base = verbose ? this.stackID(stack) + " -> " : ""; | |
| 2886 | if (stack.deadEnd) { | |
| 2887 | if (restarted) | |
| 2888 | continue; | |
| 2889 | restarted = true; | |
| 2890 | stack.restart(); | |
| 2891 | if (verbose) | |
| 2892 | console.log(base + this.stackID(stack) + " (restarted)"); | |
| 2893 | let done = this.advanceFully(stack, newStacks); | |
| 2894 | if (done) | |
| 2895 | continue; | |
| 2896 | } | |
| 2897 | let force = stack.split(), forceBase = base; | |
| 2898 | for (let j = 0; j < 10 && force.forceReduce(); j++) { | |
| 2899 | if (verbose) | |
| 2900 | console.log(forceBase + this.stackID(force) + " (via force-reduce)"); | |
| 2901 | let done = this.advanceFully(force, newStacks); | |
| 2902 | if (done) | |
| 2903 | break; | |
| 2904 | if (verbose) | |
| 2905 | forceBase = this.stackID(force) + " -> "; | |
| 2906 | } | |
| 2907 | for (let insert of stack.recoverByInsert(token)) { | |
| 2908 | if (verbose) | |
| 2909 | console.log(base + this.stackID(insert) + " (via recover-insert)"); | |
| 2910 | this.advanceFully(insert, newStacks); | |
| 2911 | } | |
| 2912 | if (this.stream.end > stack.pos) { | |
| 2913 | if (tokenEnd == stack.pos) { | |
| 2914 | tokenEnd++; | |
| 2915 | token = 0; | |
| 2916 | } | |
| 2917 | stack.recoverByDelete(token, tokenEnd); | |
| 2918 | if (verbose) | |
| 2919 | console.log(base + this.stackID(stack) + ` (via recover-delete ${this.parser.getName(token)})`); | |
| 2920 | pushStackDedup(stack, newStacks); | |
| 2921 | } else if (!finished || finished.score < force.score) { | |
| 2922 | finished = force; | |
| 2923 | } | |
| 2924 | } | |
| 2925 | return finished; | |
| 2926 | } | |
| 2927 | // Convert the stack's buffer to a syntax tree. | |
| 2928 | stackToTree(stack) { | |
| 2929 | stack.close(); | |
| 2930 | return Tree.build({ | |
| 2931 | buffer: StackBufferCursor.create(stack), | |
| 2932 | nodeSet: this.parser.nodeSet, | |
| 2933 | topID: this.topTerm, | |
| 2934 | maxBufferLength: this.parser.bufferLength, | |
| 2935 | reused: this.reused, | |
| 2936 | start: this.ranges[0].from, | |
| 2937 | length: stack.pos - this.ranges[0].from, | |
| 2938 | minRepeatType: this.parser.minRepeatTerm | |
| 2939 | }); | |
| 2940 | } | |
| 2941 | stackID(stack) { | |
| 2942 | let id2 = (stackIDs || (stackIDs = /* @__PURE__ */ new WeakMap())).get(stack); | |
| 2943 | if (!id2) | |
| 2944 | stackIDs.set(stack, id2 = String.fromCodePoint(this.nextStackID++)); | |
| 2945 | return id2 + stack; | |
| 2946 | } | |
| 2947 | }; | |
| 2948 | function pushStackDedup(stack, newStacks) { | |
| 2949 | for (let i = 0; i < newStacks.length; i++) { | |
| 2950 | let other = newStacks[i]; | |
| 2951 | if (other.pos == stack.pos && other.sameState(stack)) { | |
| 2952 | if (newStacks[i].score < stack.score) | |
| 2953 | newStacks[i] = stack; | |
| 2954 | return; | |
| 2955 | } | |
| 2956 | } | |
| 2957 | newStacks.push(stack); | |
| 2958 | } | |
| 2959 | var Dialect = class { | |
| 2960 | constructor(source, flags, disabled) { | |
| 2961 | this.source = source; | |
| 2962 | this.flags = flags; | |
| 2963 | this.disabled = disabled; | |
| 2964 | } | |
| 2965 | allows(term) { | |
| 2966 | return !this.disabled || this.disabled[term] == 0; | |
| 2967 | } | |
| 2968 | }; | |
| 2969 | var id = (x) => x; | |
| 2970 | var ContextTracker = class { | |
| 2971 | /** | |
| 2972 | Define a context tracker. | |
| 2973 | */ | |
| 2974 | constructor(spec) { | |
| 2975 | this.start = spec.start; | |
| 2976 | this.shift = spec.shift || id; | |
| 2977 | this.reduce = spec.reduce || id; | |
| 2978 | this.reuse = spec.reuse || id; | |
| 2979 | this.hash = spec.hash || (() => 0); | |
| 2980 | this.strict = spec.strict !== false; | |
| 2981 | } | |
| 2982 | }; | |
| 2983 | var LRParser = class _LRParser extends Parser { | |
| 2984 | /** | |
| 2985 | @internal | |
| 2986 | */ | |
| 2987 | constructor(spec) { | |
| 2988 | super(); | |
| 2989 | this.wrappers = []; | |
| 2990 | if (spec.version != 14) | |
| 2991 | throw new RangeError(`Parser version (${spec.version}) doesn't match runtime version (${14})`); | |
| 2992 | let nodeNames = spec.nodeNames.split(" "); | |
| 2993 | this.minRepeatTerm = nodeNames.length; | |
| 2994 | for (let i = 0; i < spec.repeatNodeCount; i++) | |
| 2995 | nodeNames.push(""); | |
| 2996 | let topTerms = Object.keys(spec.topRules).map((r) => spec.topRules[r][1]); | |
| 2997 | let nodeProps = []; | |
| 2998 | for (let i = 0; i < nodeNames.length; i++) | |
| 2999 | nodeProps.push([]); | |
| 3000 | function setProp(nodeID, prop, value) { | |
| 3001 | nodeProps[nodeID].push([prop, prop.deserialize(String(value))]); | |
| 3002 | } | |
| 3003 | if (spec.nodeProps) | |
| 3004 | for (let propSpec of spec.nodeProps) { | |
| 3005 | let prop = propSpec[0]; | |
| 3006 | if (typeof prop == "string") | |
| 3007 | prop = NodeProp[prop]; | |
| 3008 | for (let i = 1; i < propSpec.length; ) { | |
| 3009 | let next = propSpec[i++]; | |
| 3010 | if (next >= 0) { | |
| 3011 | setProp(next, prop, propSpec[i++]); | |
| 3012 | } else { | |
| 3013 | let value = propSpec[i + -next]; | |
| 3014 | for (let j = -next; j > 0; j--) | |
| 3015 | setProp(propSpec[i++], prop, value); | |
| 3016 | i++; | |
| 3017 | } | |
| 3018 | } | |
| 3019 | } | |
| 3020 | this.nodeSet = new NodeSet(nodeNames.map((name2, i) => NodeType.define({ | |
| 3021 | name: i >= this.minRepeatTerm ? void 0 : name2, | |
| 3022 | id: i, | |
| 3023 | props: nodeProps[i], | |
| 3024 | top: topTerms.indexOf(i) > -1, | |
| 3025 | error: i == 0, | |
| 3026 | skipped: spec.skippedNodes && spec.skippedNodes.indexOf(i) > -1 | |
| 3027 | }))); | |
| 3028 | if (spec.propSources) | |
| 3029 | this.nodeSet = this.nodeSet.extend(...spec.propSources); | |
| 3030 | this.strict = false; | |
| 3031 | this.bufferLength = DefaultBufferLength; | |
| 3032 | let tokenArray = decodeArray(spec.tokenData); | |
| 3033 | this.context = spec.context; | |
| 3034 | this.specializerSpecs = spec.specialized || []; | |
| 3035 | this.specialized = new Uint16Array(this.specializerSpecs.length); | |
| 3036 | for (let i = 0; i < this.specializerSpecs.length; i++) | |
| 3037 | this.specialized[i] = this.specializerSpecs[i].term; | |
| 3038 | this.specializers = this.specializerSpecs.map(getSpecializer); | |
| 3039 | this.states = decodeArray(spec.states, Uint32Array); | |
| 3040 | this.data = decodeArray(spec.stateData); | |
| 3041 | this.goto = decodeArray(spec.goto); | |
| 3042 | this.maxTerm = spec.maxTerm; | |
| 3043 | this.tokenizers = spec.tokenizers.map((value) => typeof value == "number" ? new TokenGroup(tokenArray, value) : value); | |
| 3044 | this.topRules = spec.topRules; | |
| 3045 | this.dialects = spec.dialects || {}; | |
| 3046 | this.dynamicPrecedences = spec.dynamicPrecedences || null; | |
| 3047 | this.tokenPrecTable = spec.tokenPrec; | |
| 3048 | this.termNames = spec.termNames || null; | |
| 3049 | this.maxNode = this.nodeSet.types.length - 1; | |
| 3050 | this.dialect = this.parseDialect(); | |
| 3051 | this.top = this.topRules[Object.keys(this.topRules)[0]]; | |
| 3052 | } | |
| 3053 | createParse(input, fragments, ranges) { | |
| 3054 | let parse = new Parse(this, input, fragments, ranges); | |
| 3055 | for (let w of this.wrappers) | |
| 3056 | parse = w(parse, input, fragments, ranges); | |
| 3057 | return parse; | |
| 3058 | } | |
| 3059 | /** | |
| 3060 | Get a goto table entry @internal | |
| 3061 | */ | |
| 3062 | getGoto(state, term, loose = false) { | |
| 3063 | let table = this.goto; | |
| 3064 | if (term >= table[0]) | |
| 3065 | return -1; | |
| 3066 | for (let pos = table[term + 1]; ; ) { | |
| 3067 | let groupTag = table[pos++], last = groupTag & 1; | |
| 3068 | let target = table[pos++]; | |
| 3069 | if (last && loose) | |
| 3070 | return target; | |
| 3071 | for (let end = pos + (groupTag >> 1); pos < end; pos++) | |
| 3072 | if (table[pos] == state) | |
| 3073 | return target; | |
| 3074 | if (last) | |
| 3075 | return -1; | |
| 3076 | } | |
| 3077 | } | |
| 3078 | /** | |
| 3079 | Check if this state has an action for a given terminal @internal | |
| 3080 | */ | |
| 3081 | hasAction(state, terminal) { | |
| 3082 | let data = this.data; | |
| 3083 | for (let set = 0; set < 2; set++) { | |
| 3084 | for (let i = this.stateSlot( | |
| 3085 | state, | |
| 3086 | set ? 2 : 1 | |
| 3087 | /* ParseState.Actions */ | |
| 3088 | ), next; ; i += 3) { | |
| 3089 | if ((next = data[i]) == 65535) { | |
| 3090 | if (data[i + 1] == 1) | |
| 3091 | next = data[i = pair(data, i + 2)]; | |
| 3092 | else if (data[i + 1] == 2) | |
| 3093 | return pair(data, i + 2); | |
| 3094 | else | |
| 3095 | break; | |
| 3096 | } | |
| 3097 | if (next == terminal || next == 0) | |
| 3098 | return pair(data, i + 1); | |
| 3099 | } | |
| 3100 | } | |
| 3101 | return 0; | |
| 3102 | } | |
| 3103 | /** | |
| 3104 | @internal | |
| 3105 | */ | |
| 3106 | stateSlot(state, slot) { | |
| 3107 | return this.states[state * 6 + slot]; | |
| 3108 | } | |
| 3109 | /** | |
| 3110 | @internal | |
| 3111 | */ | |
| 3112 | stateFlag(state, flag) { | |
| 3113 | return (this.stateSlot( | |
| 3114 | state, | |
| 3115 | 0 | |
| 3116 | /* ParseState.Flags */ | |
| 3117 | ) & flag) > 0; | |
| 3118 | } | |
| 3119 | /** | |
| 3120 | @internal | |
| 3121 | */ | |
| 3122 | validAction(state, action) { | |
| 3123 | return !!this.allActions(state, (a) => a == action ? true : null); | |
| 3124 | } | |
| 3125 | /** | |
| 3126 | @internal | |
| 3127 | */ | |
| 3128 | allActions(state, action) { | |
| 3129 | let deflt = this.stateSlot( | |
| 3130 | state, | |
| 3131 | 4 | |
| 3132 | /* ParseState.DefaultReduce */ | |
| 3133 | ); | |
| 3134 | let result = deflt ? action(deflt) : void 0; | |
| 3135 | for (let i = this.stateSlot( | |
| 3136 | state, | |
| 3137 | 1 | |
| 3138 | /* ParseState.Actions */ | |
| 3139 | ); result == null; i += 3) { | |
| 3140 | if (this.data[i] == 65535) { | |
| 3141 | if (this.data[i + 1] == 1) | |
| 3142 | i = pair(this.data, i + 2); | |
| 3143 | else | |
| 3144 | break; | |
| 3145 | } | |
| 3146 | result = action(pair(this.data, i + 1)); | |
| 3147 | } | |
| 3148 | return result; | |
| 3149 | } | |
| 3150 | /** | |
| 3151 | Get the states that can follow this one through shift actions or | |
| 3152 | goto jumps. @internal | |
| 3153 | */ | |
| 3154 | nextStates(state) { | |
| 3155 | let result = []; | |
| 3156 | for (let i = this.stateSlot( | |
| 3157 | state, | |
| 3158 | 1 | |
| 3159 | /* ParseState.Actions */ | |
| 3160 | ); ; i += 3) { | |
| 3161 | if (this.data[i] == 65535) { | |
| 3162 | if (this.data[i + 1] == 1) | |
| 3163 | i = pair(this.data, i + 2); | |
| 3164 | else | |
| 3165 | break; | |
| 3166 | } | |
| 3167 | if ((this.data[i + 2] & 65536 >> 16) == 0) { | |
| 3168 | let value = this.data[i + 1]; | |
| 3169 | if (!result.some((v, i2) => i2 & 1 && v == value)) | |
| 3170 | result.push(this.data[i], value); | |
| 3171 | } | |
| 3172 | } | |
| 3173 | return result; | |
| 3174 | } | |
| 3175 | /** | |
| 3176 | Configure the parser. Returns a new parser instance that has the | |
| 3177 | given settings modified. Settings not provided in `config` are | |
| 3178 | kept from the original parser. | |
| 3179 | */ | |
| 3180 | configure(config) { | |
| 3181 | let copy = Object.assign(Object.create(_LRParser.prototype), this); | |
| 3182 | if (config.props) | |
| 3183 | copy.nodeSet = this.nodeSet.extend(...config.props); | |
| 3184 | if (config.top) { | |
| 3185 | let info = this.topRules[config.top]; | |
| 3186 | if (!info) | |
| 3187 | throw new RangeError(`Invalid top rule name ${config.top}`); | |
| 3188 | copy.top = info; | |
| 3189 | } | |
| 3190 | if (config.tokenizers) | |
| 3191 | copy.tokenizers = this.tokenizers.map((t2) => { | |
| 3192 | let found = config.tokenizers.find((r) => r.from == t2); | |
| 3193 | return found ? found.to : t2; | |
| 3194 | }); | |
| 3195 | if (config.specializers) { | |
| 3196 | copy.specializers = this.specializers.slice(); | |
| 3197 | copy.specializerSpecs = this.specializerSpecs.map((s, i) => { | |
| 3198 | let found = config.specializers.find((r) => r.from == s.external); | |
| 3199 | if (!found) | |
| 3200 | return s; | |
| 3201 | let spec = Object.assign(Object.assign({}, s), { external: found.to }); | |
| 3202 | copy.specializers[i] = getSpecializer(spec); | |
| 3203 | return spec; | |
| 3204 | }); | |
| 3205 | } | |
| 3206 | if (config.contextTracker) | |
| 3207 | copy.context = config.contextTracker; | |
| 3208 | if (config.dialect) | |
| 3209 | copy.dialect = this.parseDialect(config.dialect); | |
| 3210 | if (config.strict != null) | |
| 3211 | copy.strict = config.strict; | |
| 3212 | if (config.wrap) | |
| 3213 | copy.wrappers = copy.wrappers.concat(config.wrap); | |
| 3214 | if (config.bufferLength != null) | |
| 3215 | copy.bufferLength = config.bufferLength; | |
| 3216 | return copy; | |
| 3217 | } | |
| 3218 | /** | |
| 3219 | Tells you whether any [parse wrappers](#lr.ParserConfig.wrap) | |
| 3220 | are registered for this parser. | |
| 3221 | */ | |
| 3222 | hasWrappers() { | |
| 3223 | return this.wrappers.length > 0; | |
| 3224 | } | |
| 3225 | /** | |
| 3226 | Returns the name associated with a given term. This will only | |
| 3227 | work for all terms when the parser was generated with the | |
| 3228 | `--names` option. By default, only the names of tagged terms are | |
| 3229 | stored. | |
| 3230 | */ | |
| 3231 | getName(term) { | |
| 3232 | return this.termNames ? this.termNames[term] : String(term <= this.maxNode && this.nodeSet.types[term].name || term); | |
| 3233 | } | |
| 3234 | /** | |
| 3235 | The eof term id is always allocated directly after the node | |
| 3236 | types. @internal | |
| 3237 | */ | |
| 3238 | get eofTerm() { | |
| 3239 | return this.maxNode + 1; | |
| 3240 | } | |
| 3241 | /** | |
| 3242 | The type of top node produced by the parser. | |
| 3243 | */ | |
| 3244 | get topNode() { | |
| 3245 | return this.nodeSet.types[this.top[1]]; | |
| 3246 | } | |
| 3247 | /** | |
| 3248 | @internal | |
| 3249 | */ | |
| 3250 | dynamicPrecedence(term) { | |
| 3251 | let prec = this.dynamicPrecedences; | |
| 3252 | return prec == null ? 0 : prec[term] || 0; | |
| 3253 | } | |
| 3254 | /** | |
| 3255 | @internal | |
| 3256 | */ | |
| 3257 | parseDialect(dialect) { | |
| 3258 | let values = Object.keys(this.dialects), flags = values.map(() => false); | |
| 3259 | if (dialect) | |
| 3260 | for (let part of dialect.split(" ")) { | |
| 3261 | let id2 = values.indexOf(part); | |
| 3262 | if (id2 >= 0) | |
| 3263 | flags[id2] = true; | |
| 3264 | } | |
| 3265 | let disabled = null; | |
| 3266 | for (let i = 0; i < values.length; i++) | |
| 3267 | if (!flags[i]) { | |
| 3268 | for (let j = this.dialects[values[i]], id2; (id2 = this.data[j++]) != 65535; ) | |
| 3269 | (disabled || (disabled = new Uint8Array(this.maxTerm + 1)))[id2] = 1; | |
| 3270 | } | |
| 3271 | return new Dialect(dialect, flags, disabled); | |
| 3272 | } | |
| 3273 | /** | |
| 3274 | Used by the output of the parser generator. Not available to | |
| 3275 | user code. @hide | |
| 3276 | */ | |
| 3277 | static deserialize(spec) { | |
| 3278 | return new _LRParser(spec); | |
| 3279 | } | |
| 3280 | }; | |
| 3281 | function pair(data, off) { | |
| 3282 | return data[off] | data[off + 1] << 16; | |
| 3283 | } | |
| 3284 | function findFinished(stacks) { | |
| 3285 | let best = null; | |
| 3286 | for (let stack of stacks) { | |
| 3287 | let stopped = stack.p.stoppedAt; | |
| 3288 | if ((stack.pos == stack.p.stream.end || stopped != null && stack.pos > stopped) && stack.p.parser.stateFlag( | |
| 3289 | stack.state, | |
| 3290 | 2 | |
| 3291 | /* StateFlag.Accepting */ | |
| 3292 | ) && (!best || best.score < stack.score)) | |
| 3293 | best = stack; | |
| 3294 | } | |
| 3295 | return best; | |
| 3296 | } | |
| 3297 | function getSpecializer(spec) { | |
| 3298 | if (spec.external) { | |
| 3299 | let mask = spec.extend ? 1 : 0; | |
| 3300 | return (value, stack) => spec.external(value, stack) << 1 | mask; | |
| 3301 | } | |
| 3302 | return spec.get; | |
| 3303 | } | |
| 3304 | ||
| 3305 | // node_modules/@lezer/highlight/dist/index.js | |
| 3306 | var nextTagID = 0; | |
| 3307 | var Tag = class _Tag { | |
| 3308 | /** | |
| 3309 | @internal | |
| 3310 | */ | |
| 3311 | constructor(name2, set, base, modified) { | |
| 3312 | this.name = name2; | |
| 3313 | this.set = set; | |
| 3314 | this.base = base; | |
| 3315 | this.modified = modified; | |
| 3316 | this.id = nextTagID++; | |
| 3317 | } | |
| 3318 | toString() { | |
| 3319 | let { name: name2 } = this; | |
| 3320 | for (let mod of this.modified) | |
| 3321 | if (mod.name) | |
| 3322 | name2 = `${mod.name}(${name2})`; | |
| 3323 | return name2; | |
| 3324 | } | |
| 3325 | static define(nameOrParent, parent) { | |
| 3326 | let name2 = typeof nameOrParent == "string" ? nameOrParent : "?"; | |
| 3327 | if (nameOrParent instanceof _Tag) | |
| 3328 | parent = nameOrParent; | |
| 3329 | if (parent === null || parent === void 0 ? void 0 : parent.base) | |
| 3330 | throw new Error("Can not derive from a modified tag"); | |
| 3331 | let tag = new _Tag(name2, [], null, []); | |
| 3332 | tag.set.push(tag); | |
| 3333 | if (parent) | |
| 3334 | for (let t2 of parent.set) | |
| 3335 | tag.set.push(t2); | |
| 3336 | return tag; | |
| 3337 | } | |
| 3338 | /** | |
| 3339 | Define a tag _modifier_, which is a function that, given a tag, | |
| 3340 | will return a tag that is a subtag of the original. Applying the | |
| 3341 | same modifier to a twice tag will return the same value (`m1(t1) | |
| 3342 | == m1(t1)`) and applying multiple modifiers will, regardless or | |
| 3343 | order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`). | |
| 3344 | ||
| 3345 | When multiple modifiers are applied to a given base tag, each | |
| 3346 | smaller set of modifiers is registered as a parent, so that for | |
| 3347 | example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`, | |
| 3348 | `m1(m3(t1)`, and so on. | |
| 3349 | */ | |
| 3350 | static defineModifier(name2) { | |
| 3351 | let mod = new Modifier(name2); | |
| 3352 | return (tag) => { | |
| 3353 | if (tag.modified.indexOf(mod) > -1) | |
| 3354 | return tag; | |
| 3355 | return Modifier.get(tag.base || tag, tag.modified.concat(mod).sort((a, b) => a.id - b.id)); | |
| 3356 | }; | |
| 3357 | } | |
| 3358 | }; | |
| 3359 | var nextModifierID = 0; | |
| 3360 | var Modifier = class _Modifier { | |
| 3361 | constructor(name2) { | |
| 3362 | this.name = name2; | |
| 3363 | this.instances = []; | |
| 3364 | this.id = nextModifierID++; | |
| 3365 | } | |
| 3366 | static get(base, mods) { | |
| 3367 | if (!mods.length) | |
| 3368 | return base; | |
| 3369 | let exists = mods[0].instances.find((t2) => t2.base == base && sameArray(mods, t2.modified)); | |
| 3370 | if (exists) | |
| 3371 | return exists; | |
| 3372 | let set = [], tag = new Tag(base.name, set, base, mods); | |
| 3373 | for (let m of mods) | |
| 3374 | m.instances.push(tag); | |
| 3375 | let configs = powerSet(mods); | |
| 3376 | for (let parent of base.set) | |
| 3377 | if (!parent.modified.length) | |
| 3378 | for (let config of configs) | |
| 3379 | set.push(_Modifier.get(parent, config)); | |
| 3380 | return tag; | |
| 3381 | } | |
| 3382 | }; | |
| 3383 | function sameArray(a, b) { | |
| 3384 | return a.length == b.length && a.every((x, i) => x == b[i]); | |
| 3385 | } | |
| 3386 | function powerSet(array) { | |
| 3387 | let sets = [[]]; | |
| 3388 | for (let i = 0; i < array.length; i++) { | |
| 3389 | for (let j = 0, e = sets.length; j < e; j++) { | |
| 3390 | sets.push(sets[j].concat(array[i])); | |
| 3391 | } | |
| 3392 | } | |
| 3393 | return sets.sort((a, b) => b.length - a.length); | |
| 3394 | } | |
| 3395 | function styleTags(spec) { | |
| 3396 | let byName = /* @__PURE__ */ Object.create(null); | |
| 3397 | for (let prop in spec) { | |
| 3398 | let tags2 = spec[prop]; | |
| 3399 | if (!Array.isArray(tags2)) | |
| 3400 | tags2 = [tags2]; | |
| 3401 | for (let part of prop.split(" ")) | |
| 3402 | if (part) { | |
| 3403 | let pieces = [], mode = 2, rest = part; | |
| 3404 | for (let pos = 0; ; ) { | |
| 3405 | if (rest == "..." && pos > 0 && pos + 3 == part.length) { | |
| 3406 | mode = 1; | |
| 3407 | break; | |
| 3408 | } | |
| 3409 | let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest); | |
| 3410 | if (!m) | |
| 3411 | throw new RangeError("Invalid path: " + part); | |
| 3412 | pieces.push(m[0] == "*" ? "" : m[0][0] == '"' ? JSON.parse(m[0]) : m[0]); | |
| 3413 | pos += m[0].length; | |
| 3414 | if (pos == part.length) | |
| 3415 | break; | |
| 3416 | let next = part[pos++]; | |
| 3417 | if (pos == part.length && next == "!") { | |
| 3418 | mode = 0; | |
| 3419 | break; | |
| 3420 | } | |
| 3421 | if (next != "/") | |
| 3422 | throw new RangeError("Invalid path: " + part); | |
| 3423 | rest = part.slice(pos); | |
| 3424 | } | |
| 3425 | let last = pieces.length - 1, inner = pieces[last]; | |
| 3426 | if (!inner) | |
| 3427 | throw new RangeError("Invalid path: " + part); | |
| 3428 | let rule = new Rule(tags2, mode, last > 0 ? pieces.slice(0, last) : null); | |
| 3429 | byName[inner] = rule.sort(byName[inner]); | |
| 3430 | } | |
| 3431 | } | |
| 3432 | return ruleNodeProp.add(byName); | |
| 3433 | } | |
| 3434 | var ruleNodeProp = new NodeProp({ | |
| 3435 | combine(a, b) { | |
| 3436 | let cur, root, take; | |
| 3437 | while (a || b) { | |
| 3438 | if (!a || b && a.depth >= b.depth) { | |
| 3439 | take = b; | |
| 3440 | b = b.next; | |
| 3441 | } else { | |
| 3442 | take = a; | |
| 3443 | a = a.next; | |
| 3444 | } | |
| 3445 | if (cur && cur.mode == take.mode && !take.context && !cur.context) | |
| 3446 | continue; | |
| 3447 | let copy = new Rule(take.tags, take.mode, take.context); | |
| 3448 | if (cur) | |
| 3449 | cur.next = copy; | |
| 3450 | else | |
| 3451 | root = copy; | |
| 3452 | cur = copy; | |
| 3453 | } | |
| 3454 | return root; | |
| 3455 | } | |
| 3456 | }); | |
| 3457 | var Rule = class { | |
| 3458 | constructor(tags2, mode, context, next) { | |
| 3459 | this.tags = tags2; | |
| 3460 | this.mode = mode; | |
| 3461 | this.context = context; | |
| 3462 | this.next = next; | |
| 3463 | } | |
| 3464 | get opaque() { | |
| 3465 | return this.mode == 0; | |
| 3466 | } | |
| 3467 | get inherit() { | |
| 3468 | return this.mode == 1; | |
| 3469 | } | |
| 3470 | sort(other) { | |
| 3471 | if (!other || other.depth < this.depth) { | |
| 3472 | this.next = other; | |
| 3473 | return this; | |
| 3474 | } | |
| 3475 | other.next = this.sort(other.next); | |
| 3476 | return other; | |
| 3477 | } | |
| 3478 | get depth() { | |
| 3479 | return this.context ? this.context.length : 0; | |
| 3480 | } | |
| 3481 | }; | |
| 3482 | Rule.empty = new Rule([], 2, null); | |
| 3483 | function tagHighlighter(tags2, options) { | |
| 3484 | let map = /* @__PURE__ */ Object.create(null); | |
| 3485 | for (let style of tags2) { | |
| 3486 | if (!Array.isArray(style.tag)) | |
| 3487 | map[style.tag.id] = style.class; | |
| 3488 | else | |
| 3489 | for (let tag of style.tag) | |
| 3490 | map[tag.id] = style.class; | |
| 3491 | } | |
| 3492 | let { scope, all = null } = options || {}; | |
| 3493 | return { | |
| 3494 | style: (tags3) => { | |
| 3495 | let cls = all; | |
| 3496 | for (let tag of tags3) { | |
| 3497 | for (let sub of tag.set) { | |
| 3498 | let tagClass = map[sub.id]; | |
| 3499 | if (tagClass) { | |
| 3500 | cls = cls ? cls + " " + tagClass : tagClass; | |
| 3501 | break; | |
| 3502 | } | |
| 3503 | } | |
| 3504 | } | |
| 3505 | return cls; | |
| 3506 | }, | |
| 3507 | scope | |
| 3508 | }; | |
| 3509 | } | |
| 3510 | var t = Tag.define; | |
| 3511 | var comment = t(); | |
| 3512 | var name = t(); | |
| 3513 | var typeName = t(name); | |
| 3514 | var propertyName = t(name); | |
| 3515 | var literal = t(); | |
| 3516 | var string = t(literal); | |
| 3517 | var number = t(literal); | |
| 3518 | var content = t(); | |
| 3519 | var heading = t(content); | |
| 3520 | var keyword = t(); | |
| 3521 | var operator = t(); | |
| 3522 | var punctuation = t(); | |
| 3523 | var bracket = t(punctuation); | |
| 3524 | var meta = t(); | |
| 3525 | var tags = { | |
| 3526 | /** | |
| 3527 | A comment. | |
| 3528 | */ | |
| 3529 | comment, | |
| 3530 | /** | |
| 3531 | A line [comment](#highlight.tags.comment). | |
| 3532 | */ | |
| 3533 | lineComment: t(comment), | |
| 3534 | /** | |
| 3535 | A block [comment](#highlight.tags.comment). | |
| 3536 | */ | |
| 3537 | blockComment: t(comment), | |
| 3538 | /** | |
| 3539 | A documentation [comment](#highlight.tags.comment). | |
| 3540 | */ | |
| 3541 | docComment: t(comment), | |
| 3542 | /** | |
| 3543 | Any kind of identifier. | |
| 3544 | */ | |
| 3545 | name, | |
| 3546 | /** | |
| 3547 | The [name](#highlight.tags.name) of a variable. | |
| 3548 | */ | |
| 3549 | variableName: t(name), | |
| 3550 | /** | |
| 3551 | A type [name](#highlight.tags.name). | |
| 3552 | */ | |
| 3553 | typeName, | |
| 3554 | /** | |
| 3555 | A tag name (subtag of [`typeName`](#highlight.tags.typeName)). | |
| 3556 | */ | |
| 3557 | tagName: t(typeName), | |
| 3558 | /** | |
| 3559 | A property or field [name](#highlight.tags.name). | |
| 3560 | */ | |
| 3561 | propertyName, | |
| 3562 | /** | |
| 3563 | An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)). | |
| 3564 | */ | |
| 3565 | attributeName: t(propertyName), | |
| 3566 | /** | |
| 3567 | The [name](#highlight.tags.name) of a class. | |
| 3568 | */ | |
| 3569 | className: t(name), | |
| 3570 | /** | |
| 3571 | A label [name](#highlight.tags.name). | |
| 3572 | */ | |
| 3573 | labelName: t(name), | |
| 3574 | /** | |
| 3575 | A namespace [name](#highlight.tags.name). | |
| 3576 | */ | |
| 3577 | namespace: t(name), | |
| 3578 | /** | |
| 3579 | The [name](#highlight.tags.name) of a macro. | |
| 3580 | */ | |
| 3581 | macroName: t(name), | |
| 3582 | /** | |
| 3583 | A literal value. | |
| 3584 | */ | |
| 3585 | literal, | |
| 3586 | /** | |
| 3587 | A string [literal](#highlight.tags.literal). | |
| 3588 | */ | |
| 3589 | string, | |
| 3590 | /** | |
| 3591 | A documentation [string](#highlight.tags.string). | |
| 3592 | */ | |
| 3593 | docString: t(string), | |
| 3594 | /** | |
| 3595 | A character literal (subtag of [string](#highlight.tags.string)). | |
| 3596 | */ | |
| 3597 | character: t(string), | |
| 3598 | /** | |
| 3599 | An attribute value (subtag of [string](#highlight.tags.string)). | |
| 3600 | */ | |
| 3601 | attributeValue: t(string), | |
| 3602 | /** | |
| 3603 | A number [literal](#highlight.tags.literal). | |
| 3604 | */ | |
| 3605 | number, | |
| 3606 | /** | |
| 3607 | An integer [number](#highlight.tags.number) literal. | |
| 3608 | */ | |
| 3609 | integer: t(number), | |
| 3610 | /** | |
| 3611 | A floating-point [number](#highlight.tags.number) literal. | |
| 3612 | */ | |
| 3613 | float: t(number), | |
| 3614 | /** | |
| 3615 | A boolean [literal](#highlight.tags.literal). | |
| 3616 | */ | |
| 3617 | bool: t(literal), | |
| 3618 | /** | |
| 3619 | Regular expression [literal](#highlight.tags.literal). | |
| 3620 | */ | |
| 3621 | regexp: t(literal), | |
| 3622 | /** | |
| 3623 | An escape [literal](#highlight.tags.literal), for example a | |
| 3624 | backslash escape in a string. | |
| 3625 | */ | |
| 3626 | escape: t(literal), | |
| 3627 | /** | |
| 3628 | A color [literal](#highlight.tags.literal). | |
| 3629 | */ | |
| 3630 | color: t(literal), | |
| 3631 | /** | |
| 3632 | A URL [literal](#highlight.tags.literal). | |
| 3633 | */ | |
| 3634 | url: t(literal), | |
| 3635 | /** | |
| 3636 | A language keyword. | |
| 3637 | */ | |
| 3638 | keyword, | |
| 3639 | /** | |
| 3640 | The [keyword](#highlight.tags.keyword) for the self or this | |
| 3641 | object. | |
| 3642 | */ | |
| 3643 | self: t(keyword), | |
| 3644 | /** | |
| 3645 | The [keyword](#highlight.tags.keyword) for null. | |
| 3646 | */ | |
| 3647 | null: t(keyword), | |
| 3648 | /** | |
| 3649 | A [keyword](#highlight.tags.keyword) denoting some atomic value. | |
| 3650 | */ | |
| 3651 | atom: t(keyword), | |
| 3652 | /** | |
| 3653 | A [keyword](#highlight.tags.keyword) that represents a unit. | |
| 3654 | */ | |
| 3655 | unit: t(keyword), | |
| 3656 | /** | |
| 3657 | A modifier [keyword](#highlight.tags.keyword). | |
| 3658 | */ | |
| 3659 | modifier: t(keyword), | |
| 3660 | /** | |
| 3661 | A [keyword](#highlight.tags.keyword) that acts as an operator. | |
| 3662 | */ | |
| 3663 | operatorKeyword: t(keyword), | |
| 3664 | /** | |
| 3665 | A control-flow related [keyword](#highlight.tags.keyword). | |
| 3666 | */ | |
| 3667 | controlKeyword: t(keyword), | |
| 3668 | /** | |
| 3669 | A [keyword](#highlight.tags.keyword) that defines something. | |
| 3670 | */ | |
| 3671 | definitionKeyword: t(keyword), | |
| 3672 | /** | |
| 3673 | A [keyword](#highlight.tags.keyword) related to defining or | |
| 3674 | interfacing with modules. | |
| 3675 | */ | |
| 3676 | moduleKeyword: t(keyword), | |
| 3677 | /** | |
| 3678 | An operator. | |
| 3679 | */ | |
| 3680 | operator, | |
| 3681 | /** | |
| 3682 | An [operator](#highlight.tags.operator) that dereferences something. | |
| 3683 | */ | |
| 3684 | derefOperator: t(operator), | |
| 3685 | /** | |
| 3686 | Arithmetic-related [operator](#highlight.tags.operator). | |
| 3687 | */ | |
| 3688 | arithmeticOperator: t(operator), | |
| 3689 | /** | |
| 3690 | Logical [operator](#highlight.tags.operator). | |
| 3691 | */ | |
| 3692 | logicOperator: t(operator), | |
| 3693 | /** | |
| 3694 | Bit [operator](#highlight.tags.operator). | |
| 3695 | */ | |
| 3696 | bitwiseOperator: t(operator), | |
| 3697 | /** | |
| 3698 | Comparison [operator](#highlight.tags.operator). | |
| 3699 | */ | |
| 3700 | compareOperator: t(operator), | |
| 3701 | /** | |
| 3702 | [Operator](#highlight.tags.operator) that updates its operand. | |
| 3703 | */ | |
| 3704 | updateOperator: t(operator), | |
| 3705 | /** | |
| 3706 | [Operator](#highlight.tags.operator) that defines something. | |
| 3707 | */ | |
| 3708 | definitionOperator: t(operator), | |
| 3709 | /** | |
| 3710 | Type-related [operator](#highlight.tags.operator). | |
| 3711 | */ | |
| 3712 | typeOperator: t(operator), | |
| 3713 | /** | |
| 3714 | Control-flow [operator](#highlight.tags.operator). | |
| 3715 | */ | |
| 3716 | controlOperator: t(operator), | |
| 3717 | /** | |
| 3718 | Program or markup punctuation. | |
| 3719 | */ | |
| 3720 | punctuation, | |
| 3721 | /** | |
| 3722 | [Punctuation](#highlight.tags.punctuation) that separates | |
| 3723 | things. | |
| 3724 | */ | |
| 3725 | separator: t(punctuation), | |
| 3726 | /** | |
| 3727 | Bracket-style [punctuation](#highlight.tags.punctuation). | |
| 3728 | */ | |
| 3729 | bracket, | |
| 3730 | /** | |
| 3731 | Angle [brackets](#highlight.tags.bracket) (usually `<` and `>` | |
| 3732 | tokens). | |
| 3733 | */ | |
| 3734 | angleBracket: t(bracket), | |
| 3735 | /** | |
| 3736 | Square [brackets](#highlight.tags.bracket) (usually `[` and `]` | |
| 3737 | tokens). | |
| 3738 | */ | |
| 3739 | squareBracket: t(bracket), | |
| 3740 | /** | |
| 3741 | Parentheses (usually `(` and `)` tokens). Subtag of | |
| 3742 | [bracket](#highlight.tags.bracket). | |
| 3743 | */ | |
| 3744 | paren: t(bracket), | |
| 3745 | /** | |
| 3746 | Braces (usually `{` and `}` tokens). Subtag of | |
| 3747 | [bracket](#highlight.tags.bracket). | |
| 3748 | */ | |
| 3749 | brace: t(bracket), | |
| 3750 | /** | |
| 3751 | Content, for example plain text in XML or markup documents. | |
| 3752 | */ | |
| 3753 | content, | |
| 3754 | /** | |
| 3755 | [Content](#highlight.tags.content) that represents a heading. | |
| 3756 | */ | |
| 3757 | heading, | |
| 3758 | /** | |
| 3759 | A level 1 [heading](#highlight.tags.heading). | |
| 3760 | */ | |
| 3761 | heading1: t(heading), | |
| 3762 | /** | |
| 3763 | A level 2 [heading](#highlight.tags.heading). | |
| 3764 | */ | |
| 3765 | heading2: t(heading), | |
| 3766 | /** | |
| 3767 | A level 3 [heading](#highlight.tags.heading). | |
| 3768 | */ | |
| 3769 | heading3: t(heading), | |
| 3770 | /** | |
| 3771 | A level 4 [heading](#highlight.tags.heading). | |
| 3772 | */ | |
| 3773 | heading4: t(heading), | |
| 3774 | /** | |
| 3775 | A level 5 [heading](#highlight.tags.heading). | |
| 3776 | */ | |
| 3777 | heading5: t(heading), | |
| 3778 | /** | |
| 3779 | A level 6 [heading](#highlight.tags.heading). | |
| 3780 | */ | |
| 3781 | heading6: t(heading), | |
| 3782 | /** | |
| 3783 | A prose [content](#highlight.tags.content) separator (such as a horizontal rule). | |
| 3784 | */ | |
| 3785 | contentSeparator: t(content), | |
| 3786 | /** | |
| 3787 | [Content](#highlight.tags.content) that represents a list. | |
| 3788 | */ | |
| 3789 | list: t(content), | |
| 3790 | /** | |
| 3791 | [Content](#highlight.tags.content) that represents a quote. | |
| 3792 | */ | |
| 3793 | quote: t(content), | |
| 3794 | /** | |
| 3795 | [Content](#highlight.tags.content) that is emphasized. | |
| 3796 | */ | |
| 3797 | emphasis: t(content), | |
| 3798 | /** | |
| 3799 | [Content](#highlight.tags.content) that is styled strong. | |
| 3800 | */ | |
| 3801 | strong: t(content), | |
| 3802 | /** | |
| 3803 | [Content](#highlight.tags.content) that is part of a link. | |
| 3804 | */ | |
| 3805 | link: t(content), | |
| 3806 | /** | |
| 3807 | [Content](#highlight.tags.content) that is styled as code or | |
| 3808 | monospace. | |
| 3809 | */ | |
| 3810 | monospace: t(content), | |
| 3811 | /** | |
| 3812 | [Content](#highlight.tags.content) that has a strike-through | |
| 3813 | style. | |
| 3814 | */ | |
| 3815 | strikethrough: t(content), | |
| 3816 | /** | |
| 3817 | Inserted text in a change-tracking format. | |
| 3818 | */ | |
| 3819 | inserted: t(), | |
| 3820 | /** | |
| 3821 | Deleted text. | |
| 3822 | */ | |
| 3823 | deleted: t(), | |
| 3824 | /** | |
| 3825 | Changed text. | |
| 3826 | */ | |
| 3827 | changed: t(), | |
| 3828 | /** | |
| 3829 | An invalid or unsyntactic element. | |
| 3830 | */ | |
| 3831 | invalid: t(), | |
| 3832 | /** | |
| 3833 | Metadata or meta-instruction. | |
| 3834 | */ | |
| 3835 | meta, | |
| 3836 | /** | |
| 3837 | [Metadata](#highlight.tags.meta) that applies to the entire | |
| 3838 | document. | |
| 3839 | */ | |
| 3840 | documentMeta: t(meta), | |
| 3841 | /** | |
| 3842 | [Metadata](#highlight.tags.meta) that annotates or adds | |
| 3843 | attributes to a given syntactic element. | |
| 3844 | */ | |
| 3845 | annotation: t(meta), | |
| 3846 | /** | |
| 3847 | Processing instruction or preprocessor directive. Subtag of | |
| 3848 | [meta](#highlight.tags.meta). | |
| 3849 | */ | |
| 3850 | processingInstruction: t(meta), | |
| 3851 | /** | |
| 3852 | [Modifier](#highlight.Tag^defineModifier) that indicates that a | |
| 3853 | given element is being defined. Expected to be used with the | |
| 3854 | various [name](#highlight.tags.name) tags. | |
| 3855 | */ | |
| 3856 | definition: Tag.defineModifier("definition"), | |
| 3857 | /** | |
| 3858 | [Modifier](#highlight.Tag^defineModifier) that indicates that | |
| 3859 | something is constant. Mostly expected to be used with | |
| 3860 | [variable names](#highlight.tags.variableName). | |
| 3861 | */ | |
| 3862 | constant: Tag.defineModifier("constant"), | |
| 3863 | /** | |
| 3864 | [Modifier](#highlight.Tag^defineModifier) used to indicate that | |
| 3865 | a [variable](#highlight.tags.variableName) or [property | |
| 3866 | name](#highlight.tags.propertyName) is being called or defined | |
| 3867 | as a function. | |
| 3868 | */ | |
| 3869 | function: Tag.defineModifier("function"), | |
| 3870 | /** | |
| 3871 | [Modifier](#highlight.Tag^defineModifier) that can be applied to | |
| 3872 | [names](#highlight.tags.name) to indicate that they belong to | |
| 3873 | the language's standard environment. | |
| 3874 | */ | |
| 3875 | standard: Tag.defineModifier("standard"), | |
| 3876 | /** | |
| 3877 | [Modifier](#highlight.Tag^defineModifier) that indicates a given | |
| 3878 | [names](#highlight.tags.name) is local to some scope. | |
| 3879 | */ | |
| 3880 | local: Tag.defineModifier("local"), | |
| 3881 | /** | |
| 3882 | A generic variant [modifier](#highlight.Tag^defineModifier) that | |
| 3883 | can be used to tag language-specific alternative variants of | |
| 3884 | some common tag. It is recommended for themes to define special | |
| 3885 | forms of at least the [string](#highlight.tags.string) and | |
| 3886 | [variable name](#highlight.tags.variableName) tags, since those | |
| 3887 | come up a lot. | |
| 3888 | */ | |
| 3889 | special: Tag.defineModifier("special") | |
| 3890 | }; | |
| 3891 | for (let name2 in tags) { | |
| 3892 | let val = tags[name2]; | |
| 3893 | if (val instanceof Tag) | |
| 3894 | val.name = name2; | |
| 3895 | } | |
| 3896 | var classHighlighter = tagHighlighter([ | |
| 3897 | { tag: tags.link, class: "tok-link" }, | |
| 3898 | { tag: tags.heading, class: "tok-heading" }, | |
| 3899 | { tag: tags.emphasis, class: "tok-emphasis" }, | |
| 3900 | { tag: tags.strong, class: "tok-strong" }, | |
| 3901 | { tag: tags.keyword, class: "tok-keyword" }, | |
| 3902 | { tag: tags.atom, class: "tok-atom" }, | |
| 3903 | { tag: tags.bool, class: "tok-bool" }, | |
| 3904 | { tag: tags.url, class: "tok-url" }, | |
| 3905 | { tag: tags.labelName, class: "tok-labelName" }, | |
| 3906 | { tag: tags.inserted, class: "tok-inserted" }, | |
| 3907 | { tag: tags.deleted, class: "tok-deleted" }, | |
| 3908 | { tag: tags.literal, class: "tok-literal" }, | |
| 3909 | { tag: tags.string, class: "tok-string" }, | |
| 3910 | { tag: tags.number, class: "tok-number" }, | |
| 3911 | { tag: [tags.regexp, tags.escape, tags.special(tags.string)], class: "tok-string2" }, | |
| 3912 | { tag: tags.variableName, class: "tok-variableName" }, | |
| 3913 | { tag: tags.local(tags.variableName), class: "tok-variableName tok-local" }, | |
| 3914 | { tag: tags.definition(tags.variableName), class: "tok-variableName tok-definition" }, | |
| 3915 | { tag: tags.special(tags.variableName), class: "tok-variableName2" }, | |
| 3916 | { tag: tags.definition(tags.propertyName), class: "tok-propertyName tok-definition" }, | |
| 3917 | { tag: tags.typeName, class: "tok-typeName" }, | |
| 3918 | { tag: tags.namespace, class: "tok-namespace" }, | |
| 3919 | { tag: tags.className, class: "tok-className" }, | |
| 3920 | { tag: tags.macroName, class: "tok-macroName" }, | |
| 3921 | { tag: tags.propertyName, class: "tok-propertyName" }, | |
| 3922 | { tag: tags.operator, class: "tok-operator" }, | |
| 3923 | { tag: tags.comment, class: "tok-comment" }, | |
| 3924 | { tag: tags.meta, class: "tok-meta" }, | |
| 3925 | { tag: tags.invalid, class: "tok-invalid" }, | |
| 3926 | { tag: tags.punctuation, class: "tok-punctuation" } | |
| 3927 | ]); | |
| 3928 | ||
| 3929 | // node_modules/@gdquest/lezer-gdscript/dist/index.mjs | |
| 3930 | var indent = 140; | |
| 3931 | var dedent = 141; | |
| 3932 | var newline = 142; | |
| 3933 | var blankLineStart = 143; | |
| 3934 | var newlineBracketed = 144; | |
| 3935 | var eof = 145; | |
| 3936 | var ParenL = 10; | |
| 3937 | var CallParamsLiteralExpressionNode = 11; | |
| 3938 | var CallParamsExpressionNode = 25; | |
| 3939 | var ArrayExpressionNode = 27; | |
| 3940 | var BracketL = 32; | |
| 3941 | var CallExpressionNode = 59; | |
| 3942 | var DictionaryExpressionNode = 63; | |
| 3943 | var BraceL = 64; | |
| 3944 | var GroupedExpressionNode = 66; | |
| 3945 | var CallParamsParameterNode = 70; | |
| 3946 | var bracketed = /* @__PURE__ */ new Set([ | |
| 3947 | GroupedExpressionNode, | |
| 3948 | ArrayExpressionNode, | |
| 3949 | DictionaryExpressionNode, | |
| 3950 | CallExpressionNode, | |
| 3951 | CallParamsExpressionNode, | |
| 3952 | CallParamsLiteralExpressionNode, | |
| 3953 | CallParamsParameterNode | |
| 3954 | ]); | |
| 3955 | var newline2 = "\n".charCodeAt(0); | |
| 3956 | var carriageReturn = "\r".charCodeAt(0); | |
| 3957 | var space = " ".charCodeAt(0); | |
| 3958 | var tab = " ".charCodeAt(0); | |
| 3959 | var hash = "#".charCodeAt(0); | |
| 3960 | var IndentLevel = class { | |
| 3961 | constructor(parent, depth) { | |
| 3962 | this.parent = parent; | |
| 3963 | this.depth = depth; | |
| 3964 | this.hash = (parent ? parent.hash + parent.hash << 8 : 0) + depth + (depth << 4); | |
| 3965 | } | |
| 3966 | }; | |
| 3967 | var topIndent = new IndentLevel(null, 0); | |
| 3968 | function isLineBreak(ch) { | |
| 3969 | return ch === newline2 || ch === carriageReturn; | |
| 3970 | } | |
| 3971 | var newlines = new ExternalTokenizer( | |
| 3972 | (input, stack) => { | |
| 3973 | let prev; | |
| 3974 | if (input.next < 0) { | |
| 3975 | input.acceptToken(eof); | |
| 3976 | } else if (stack.context.depth < 0) { | |
| 3977 | if (isLineBreak(input.next)) { | |
| 3978 | input.acceptToken(newlineBracketed, 1); | |
| 3979 | } | |
| 3980 | } else if (((prev = input.peek(-1)) < 0 || isLineBreak(prev)) && stack.canShift(blankLineStart)) { | |
| 3981 | let spaces = 0; | |
| 3982 | while (input.next === space || input.next === tab) { | |
| 3983 | input.advance(); | |
| 3984 | spaces++; | |
| 3985 | } | |
| 3986 | if (input.next === newline2 || input.next === carriageReturn || input.next === hash) { | |
| 3987 | input.acceptToken(blankLineStart, -spaces); | |
| 3988 | } | |
| 3989 | } else if (isLineBreak(input.next)) { | |
| 3990 | input.acceptToken(newline, 1); | |
| 3991 | } | |
| 3992 | }, | |
| 3993 | { contextual: true } | |
| 3994 | ); | |
| 3995 | function countIndent(space2) { | |
| 3996 | let depth = 0; | |
| 3997 | for (let i = 0; i < space2.length; i++) | |
| 3998 | depth += space2.charCodeAt(i) === tab ? 8 - depth % 8 : 1; | |
| 3999 | return depth; | |
| 4000 | } | |
| 4001 | var trackIndent = new ContextTracker({ | |
| 4002 | start: topIndent, | |
| 4003 | reduce(context, term) { | |
| 4004 | return context.depth < 0 && bracketed.has(term) ? context.parent : context; | |
| 4005 | }, | |
| 4006 | shift(context, term, stack, input) { | |
| 4007 | switch (term) { | |
| 4008 | case indent: | |
| 4009 | return new IndentLevel( | |
| 4010 | context, | |
| 4011 | countIndent(input.read(input.pos, stack.pos)) | |
| 4012 | ); | |
| 4013 | case dedent: | |
| 4014 | return context.parent; | |
| 4015 | case ParenL: | |
| 4016 | case BracketL: | |
| 4017 | case BraceL: | |
| 4018 | return new IndentLevel(context, -1); | |
| 4019 | default: | |
| 4020 | return context; | |
| 4021 | } | |
| 4022 | }, | |
| 4023 | hash(context) { | |
| 4024 | return context.hash; | |
| 4025 | } | |
| 4026 | }); | |
| 4027 | var indentation = new ExternalTokenizer((input, stack) => { | |
| 4028 | const contextDepth = stack.context.depth; | |
| 4029 | if (contextDepth < 0) | |
| 4030 | return; | |
| 4031 | const prev = input.peek(-1); | |
| 4032 | if (!(prev === newline2 || prev === carriageReturn)) { | |
| 4033 | return; | |
| 4034 | } | |
| 4035 | let chars = 0; | |
| 4036 | let depth = 0; | |
| 4037 | while (true) { | |
| 4038 | if (input.next === space) { | |
| 4039 | depth++; | |
| 4040 | } else if (input.next === tab) { | |
| 4041 | depth += 8 - depth % 8; | |
| 4042 | } else { | |
| 4043 | break; | |
| 4044 | } | |
| 4045 | input.advance(); | |
| 4046 | chars += 1; | |
| 4047 | } | |
| 4048 | if (depth !== contextDepth && input.next !== newline2 && input.next !== carriageReturn && input.next !== hash) { | |
| 4049 | if (depth < contextDepth) { | |
| 4050 | input.acceptToken(dedent, -chars); | |
| 4051 | } else { | |
| 4052 | input.acceptToken(indent); | |
| 4053 | } | |
| 4054 | } | |
| 4055 | }); | |
| 4056 | var gdscriptHighlighting = styleTags({ | |
| 4057 | "for while if elif else return break continue pass assert await match case": tags.controlKeyword, | |
| 4058 | "in not and or is del": tags.operatorKeyword, | |
| 4059 | "func class class_name extends const var": tags.definitionKeyword, | |
| 4060 | "preload load": tags.moduleKeyword, | |
| 4061 | "as PI TAU INF NaN": tags.keyword, | |
| 4062 | True: tags.bool, | |
| 4063 | False: tags.bool, | |
| 4064 | Null: tags.bool, | |
| 4065 | Comment: tags.lineComment, | |
| 4066 | Number: tags.number, | |
| 4067 | String: tags.string, | |
| 4068 | UpdateOp: tags.updateOperator, | |
| 4069 | ArithOp: tags.arithmeticOperator, | |
| 4070 | BitOp: tags.bitwiseOperator, | |
| 4071 | CompareOp: tags.compareOperator, | |
| 4072 | AssignOp: tags.definitionOperator, | |
| 4073 | "ClassNode/Identifier ClassNode/ExtendsStatement/Identifier VariableNode/TypeCast/Type/Identifier": tags.definition(tags.className), | |
| 4074 | "( )": tags.paren, | |
| 4075 | "[ ]": tags.squareBracket, | |
| 4076 | "{ }": tags.brace, | |
| 4077 | ".": tags.derefOperator, | |
| 4078 | ", ;": tags.separator | |
| 4079 | }); | |
| 4080 | var spec_Identifier = { __proto__: null, PI: 34, TAU: 36, INF: 38, NaN: 40, assert: 48, var: 70, const: 80, await: 86, in: 116, as: 122, func: 138, preload: 162, is: 176, class_name: 186, extends: 190, signal: 194, pass: 198, return: 202, class: 214, if: 222, elif: 226, else: 230, for: 234, match: 238, while: 254 }; | |
| 4081 | var parser = LRParser.deserialize({ | |
| 4082 | version: 14, | |
| 4083 | states: "KtQ`QUOOP#rOQOOOOQQ'#Cq'#CqOOQQ'#Ch'#ChO#wQUO'#CbO#|QUO'#CaO&OQYO'#CyO&lQUO'#CzO&qQUO'#CxO(pQYO'#FmO*hQUO'#CwO*oQYO'#FmO*|QUO'#DOOOQQ'#Fq'#FqO,lQYO'#C`O,dQYO'#C}O,yQUO'#DmO(wQUO'#DpOOQQ'#EQ'#EQO(wQUO'#EYOOQQ'#Fm'#FmOOQQ'#C`'#C`O.jQUO'#C_OOQR'#C_'#C_O.uQVO'#EmOOQR'#Ei'#EiOOQR'#Fg'#FgOOQR'#FQ'#FQQ`QUOOOOQQ'#Cl'#ClO1kQUO'#DOO1pQUO'#DTO(wQUO'#DWO1uQUO'#ElO1zQUO'#EOO1zQUO'#CsO2PQUO'#E[O2UQUO'#E^O2ZQUO'#E`OOQQ'#Eb'#EbO(wQUO'#EdO2`QUO'#EjO,yQUO'#EnO2eQUO'#EtO2jQUO'#EvO,yQUO'#FOP2oOUO'#FfPOOO)CAY)CAYO2zQUO,58|O3iQUO'#DQOOQQ,59q,59qO(wQUO,59iOOQQ,5:T,5:TO3nQUO'#CuO3uQYO,59fO5uQUO'#FTO5zQYO,59dOOQQ,59c,59cO8QQUO,59cOOQQ'#FU'#FUO8VQUO'#DOO8bQYO'#FlO8oQUO'#DrO8tQUO,59cO,yQUO,5:XOOQQ-E9S-E9SO8{QUO,59jO9QQUO,59oO9VQUO,5;UO9[QUO,5;WO(wQUO,59tO(wQUO,59tO(wQUO,59tO(wQUO,59tO(wQUO,59tO(wQUO,59tO(wQUO,59tO(wQUO,59tO(wQUO,59tO(wQUO,59tO(wQUO,5:nO(wQUO,59tO9aQUO,59tO3iQUO,5:UO9fQUO,5:qO:uQYO'#DoO;PQUO'#FtO;XQUO,5:XO;^QYO,5:[OOQQ,5:t,5:tOOQR'#Dy'#DyOOQR'#Ef'#EfO;eQUO'#FYO.jQUO,5;ROOQR,58y,58yOOQR'#FZ'#FZO<UQVO,5;XOOQR,5;X,5;XO,yQUO'#EpO>zQUO'#ErOOQR-E9O-E9OO?PQYO,59jO?[QYO,59oOOQQ,59r,59rO8oQUO,5;WOOQQ,5:j,5:jOOQQ,59_,59_OOQQ,5:v,5:vOOQQ,5:x,5:xO?gQUO,5:zO?uQYO,5;OO@SQUO,5;UO@[QYO,5;YO@fQUO,5;`O@kQUO,5;bO@[QYO,5;jPOOO,5<Q,5<QP@pOQO,5<QP@uOUO,5<QOAoQUO'#CgOOQQ1G.h1G.hOOQQ'#DS'#DSOOQQ,59l,59lOB}QYO1G/TOOQQ,59a,59aOCqQUO,59aOCvQUO'#FSOC{QYO1G/QOOQQ'#Cy'#CyOOQQ,5;o,5;oOOQQ-E9R-E9ROOQQ1G.}1G.}OE{QUO,5<WOFVQUO,5<WOFbQUO'#DtOFjQbO'#FuOFrQUO,5:^OFwQUO1G.}OF|QUO1G/sOGRQYO1G/UOG^QYO1G/ZO@SQUO1G0pO8oQUO1G0rOOQQ1G/`1G/`OI]QYO1G/`OIdQYO1G/`OK_QYO1G/`OMYQYO1G/`OMaQYO1G/`O! [QYO1G/`O! cQYO1G/`O!#ZQYO1G/`O!#eQYO1G/`O!#oQYO1G0YO!$qQYO1G/`O(wQUO1G/`OOQQ1G/p1G/pOOQQ'#EX'#EXOOQQ1G0]1G0]O,yQUO,59iO(wQUO,5:ZO!%qQUO,5<`O!%xQUO,5<`OOQQ1G/s1G/sOOQQ1G/v1G/vOOQQ,5;t,5;tOOQQ-E9W-E9WOOQR1G0m1G0mOOQR-E9X-E9XOOQR1G0s1G0sO@[QYO,5;[O!&QQUO'#DwOOQR,5;^,5;^OOQQ1G/U1G/UOOQQ1G/Z1G/ZO>zQUO1G0rOOQQ1G0f1G0fOOQR1G0p1G0pO>zQUO1G0pOOQR1G0t1G0tO,yQUO1G0zO!&XQUO1G0|OOQR1G1U1G1UPOOO1G1l1G1lP!&^OQO1G1lO!&cQUO'#FhOOQQ,59R,59RO!&kQUO,59ROOQQ1G.{1G.{OOQQ,5;n,5;nOOQQ-E9Q-E9QO!&pQYO,5;sO!&}QUO1G1rOOQQ-E9V-E9VO!'XQYO'#DVO!'jQYO'#FvO!'xQUO'#FvOOQQ,5:`,5:`O!(QQUO,5:`O3iQUO'#DvOOQQ,5<a,5<aOOQQ1G/x1G/xOOQQ7+$i7+$iOOQQ7+%_7+%_OOQQ7+$p7+$pOOQQ7+$u7+$uOOQR7+&[7+&[O>zQUO7+&[O>zQUO7+&^O(wQUO7+%tO!)QQYO7+$zO!+bQYO1G/TO!+lQYO1G/uOOQQ,5;q,5;qO!+vQUO1G1zOOQQ-E9T-E9TOOQR1G0v1G0vO!+}QVO'#DxOOQR'#D}'#D}OOQR,5:c,5:cOOQR7+&^7+&^O@[QYO7+&fO!+}QVO7+&hPOOO7+'W7+'WO!,SQUO,5<SO!,ZQUO,5<SOOQQ1G.m1G.mP(wQUO'#FXO(wQUO,5:aO!,cQUO,5<bO!,kQUO,5<bOOQQ1G/z1G/zOOQQ,5:b,5:bO!,sQYO'#EmOOQR<<Iv<<IvOOQR<<Ix<<IxO!/wQYO<<I`P,yQUO'#FVOOQQ'#D{'#D{O`QUO'#DzOOQR,5:d,5:dOOQR<<JQ<<JQO!0nQUO<<JSOOQQ,5;m,5;mO!0{QUO1G1nOOQQ-E9P-E9PO!1SQYO1G/{O!1^QYO,5;rOOQQ,5;r,5;rO!1lQUO1G1|OOQQ-E9U-E9UO!1tQYO,5;XO!3tQVO,5:fOOQQ'#E{'#E{OOQQ'#E|'#E|OOQQ'#E}'#E}OOQQ'#Ey'#EyO>zQUO'#ExOOQR'#F['#F[O!4OQVOAN?nO!4cQUO'#EzP@}QUO'#FRP!4hQUO'#FWOOQR'#D|'#D|OOQR1G0Q1G0QOOQR,5;d,5;dOOQR-E9Y-E9YOOQRG25YG25YOOQQ,5;f,5;fO!4mQYO'#CyO,yQUO'#EYO,yQUO'#DWO,yQUO,59iO,yQUO,59tO,yQUO,59tO,yQUO,59tO,yQUO,59tO,yQUO,59tO,yQUO,59tO,yQUO,59tO,yQUO,59tO,yQUO,59tO,yQUO,59tO,yQUO,59tO!4zQYO1G/TO!5UQYO1G/`O!5uQYO1G/`O!6fQYO1G/`O!7VQYO1G/`O!7vQYO1G/`O!8gQYO1G/`O!9WQYO1G/`O!;XQYO1G/`O!;cQYO1G/`O!;mQYO1G/`O,yQUO1G/`O!<^QUO'#DwOFrQUO1G0rOFrQUO1G0pOFrQUO7+&[OFrQUO7+&^O,yQUO7+%tO!>VQYO7+$zO!>vQYO7+&fO!@UQYO<<I`O!@lQYO'#C}O!@tQUO,59tOFrQUO'#ErO8oQUO,5;WO!@yQUO,5;UO!>vQYO,5;YO!>vQYO,5;jO!@yQUO1G0pO8oQUO1G0rO!ARQYO1G0YO!>vQYO,5;[O,yQUO1G0zO!AYQUO'#ElO!A_QUO'#EjO,yQUO'#EnO,yQUO'#FOO!AdQUO,5;UO!AiQUO,5;WO(wQUO,5:nO,yQUO'#EpO!AnQUO,5;`O!AsQUO'#DOO!BUQUO'#Et", | |
| 4084 | stateData: "!Bq~OPOS$XOS$UOS$TPQ~OVSOWUOYaO]RO^RO_ROamObmOcmOdmOhsOpYOsnOxoO{pO!ZcO!b`O!gqO!srO!ubO!}cO#PtO#RuO#TvO#VwO#XxO#_yO#czO#i{O#k|O#s}O$]RO$^RO$_QO$bVO$cVO~O$T!OO~OW!QO~OV#xXs#xXx#xX!g#xX#[TX#_#xX$STX$VTX~OY!VOu!ROomX}!eX!O!eX!P!eX!Q!eX!R!eX!S!eX!T!eX!U!eX!V!eX!W!eX!X!eX!Y!eX!Z!eX![!eX!_!eX!w!eX!z!eXf!eX!`!eX~O$f!TO$g!TO#[!eX$S!eX$V!eXj!eXX!eX!x!eX~P$hOW!WO~Oo!XO~O}$aX!O$aX!P$aX!Q$aX!R$aX!S$aX!T$aX!U$aX!V$aX!W$aX!X$aX!Y$aX!Z$aX![$aX!_$aX!w$aX!z$aX#[$aX$S$aX$V$aX$f$aX$g$aXf$aXj$aXu$aXX$aX!x$aX!`$aX~Oo!XO~P&vOVSOWUOYaO]RO^RO_ROamObmOcmOdmOpYOsnOxoO{pO!ZcO!b`O!g!`O!srO!ubO!}cO$]RO$^RO$_QO$bVO$cVO~Oj!ZO~P(wOY!VOp!aO!b!bO~P&vOVSOs!dOx!eO!g!gO#_!fO~O}!hO!O!iO!P!jO!Q!kO!R!lO!S!mO!T!nO!U!oO!V!pO!W!pO!X!qO!Y!qO!Z!tO![!sO!_!uO!w!rO!z!vO$f!TO$g!TO~O#[SX$SSX$VSX~P+_OVSOW&wOYaO]RO^RO_ROamObmOcmOdmOpYOsnOxoO{&yO!Z&xO!b`O!g!`O!srO!ubO!}&xO$]RO$^RO$_QO$bVO$cVO~O#[#OO$S!|O$V!}O~O#e#UO#g#VOV#aXW#aXY#aX]#aX^#aX_#aXa#aXb#aXc#aXd#aXh#aXp#aXs#aXx#aX{#aX!Z#aX!b#aX!g#aX!s#aX!u#aX!}#aX#P#aX#R#aX#T#aX#V#aX#X#aX#_#aX#c#aX#i#aX#k#aX#s#aX$P#aX$]#aX$^#aX$_#aX$b#aX$c#aX$R#aX$V#aX$l#aX~OW#XO~OW#YO~OW#[O~OY!VO~OW#_O~OW#`O~OW#aO~OW#cO~OW#eO~OW#fO~OP#iO$S#hO$X#jO~OY#kOVUasUaxUa!gUa#[Ua#_Ua$SUa$VUa~OW#mO~OX#pO~P(wO$d#rOona}na!Ona!Pna!Qna!Rna!Sna!Tna!Una!Vna!Wna!Xna!Yna!Zna![na!_na!wna!zna#[na$Sna$Vna$fna$gnafnajnaunaXna!xna!`na~OW#tO~Oo!XOYlapla}la!Ola!Pla!Qla!Rla!Sla!Tla!Ula!Vla!Wla!Xla!Yla!Zla![la!_la!bla!wla!zla#[la$Sla$Vla$fla$glaflajlaulaXla!xla!`la~Oj#wO~OVSOs!dOx!eO~Of#xOj$`XX$`X~P+_OY#zO~Oj#wO~P(wOW$PO~OW$QO~OW$RO~OW$SO~O![$aO~OW$cO~O}&{O!O&|O!P&}O!Q'OO!R'PO!S'QO!T'RO!U'SO!V'TO!W'TO!X'UO!Y'UO!Z'nO!['VO!_!uO!w(PO!z!vO$f&zO~Ou$fO$g$eO~P9kOf$gO!`$hX~O!`$iO~OX$jO~P+_OhsO#PtO#RuO#TvO#VwO#XxO#[#|X$S#|X$V#|X~P(wO#e#UO#g#VOV#aaW#aaY#aa]#aa^#aa_#aaa#aab#aac#aad#aah#aap#aas#aax#aa{#aa!Z#aa!b#aa!g#aa!s#aa!u#aa!}#aa#P#aa#R#aa#T#aa#V#aa#X#aa#_#aa#c#aa#i#aa#k#aa#s#aa$P#aa$]#aa$^#aa$_#aa$b#aa$c#aa$R#aa$V#aa$l#aa~Ou$qO~Ou!RO$fra$gra~Ou!RO$fwa$gwa~OY!VO#[#Sa$S#Sa$V#Sa~O#[#Wa$S#Wa$V#Wa~P+_Ou$qO#RuO~Ou$qO$g&zO~P9kO![$zO~Ou${O~O$S$}O~OP%OO$S$}O~O]RO^RO_ROamObmOcmOdmO$]RO$^RO$_QO~OX%QO~P@}O}!hO!O!iO!P!jO!Q!kO!R!lO!S!mO!T!nO!U!oO!V!pO!W!pO!X!qO!Y!qO!Z!tO![!sO!_!uO!w!rO!z!vO~O#[qi$Sqi$Vqi$fqi$gqifqijqiXqi!xqi!`qi~PAvOX%SO~OW%TO~O$d#rOoni}ni!Oni!Pni!Qni!Rni!Sni!Tni!Uni!Vni!Wni!Xni!Yni!Zni![ni!_ni!wni!zni#[ni$Sni$Vni$fni$gnifnijniuniXni!xni!`ni~Oj$`aX$`a~P(wOf%WOj$`aX$`a~OW%YOX%]O~O$k%_Ou$iX~Ou'dO~Oj%bO~O!`%cO~Ou!RO$fri$gri~Ou!RO$fwi$gwi~O}!hO!P|i!Q|i!R|i!S|i!T|i!U|i!V|i!W|i!X|i!Y|i!Z|i![|i!_|i!w|i!z|i#[|i$S|i$V|i$f|i$g|if|ij|iX|i!x|i!`|i~O!O|i~PGiO!O!iO~PGiO}!hO!O!iO!P!jO!R|i!S|i!T|i!U|i!V|i!W|i!X|i!Y|i!Z|i![|i!_|i!w|i!z|i#[|i$S|i$V|i$f|i$g|if|ij|iX|i!x|i!`|i~O!Q|i~PIkO}!hO!O!iO!P!jO!Q!kO!T!nO!U!oO!R|i!V|i!W|i!X|i!Y|i!Z|i![|i!_|i!w|i!z|i#[|i$S|i$V|i$f|i$g|if|ij|iX|i!x|i!`|i~O!S!mO~PKfO!S|i~PKfO}!hO!O!iO!P!jO!Q!kO!R|i!S|i!T|i!V|i!W|i!X|i!Y|i!Z|i![|i!_|i!w|i!z|i#[|i$S|i$V|i$f|i$g|if|ij|iX|i!x|i!`|i~O!U!oO~PMhO!Q!kO~PIkO}!hO!O!iO!P!jO!Q!kO!R!lO!S!mO!T!nO!U!oO!Z!tO![!sO!z!vO!X|i!Y|i!_|i!w|i#[|i$S|i$V|i$f|i$g|if|ij|iX|i!x|i!`|i~O!V|i!W|i~P! jO!V!pO!W!pO~P! jO!x%iO~P+_O!V|i!W|i!X|i!Y|i!Z|i![|i!_|i!w|i!z|i$f|i$g|if|i!`|i~O}!hO!O!iO!P!jO!Q!kO!R!lO!S!mO!T!nO!U!oO#[|i$S|i$V|ij|iX|i!x|i~P!#vO!`$ha~P,yOf%nO!`$ha~O$S!|O~P`O$S!|O~O$S%wO~Of%xOX$[X~OX%zO~Of#{aj#{aX#{a~P+_Oj$`iX$`i~P(wOu!ROXyXfyX$fyX$gyX~Of%}O$f%|O$g%|OX$jX~Of%}OX$jX~OX&PO~O!V|q!W|q!X|q!Y|q!Z|q![|q!_|q!w|q!z|q$f|q$g|qf|q!`|q~O}!hO!O!iO!P!jO!Q!kO!R!lO!S!mO!T!nO!U!oO#[|q$S|q$V|qj|qX|q!x|q~P!(VO}&{O!O&|O!P&}O!Q'OO!R'PO!S'QO!T'RO!U'SO!V'TO!W'TO!X'UO!Y'UO!Z'nO!['VO!_!uO!w(PO!z!vOuqi$fqi$gqi~Of!ci!`!ci~P!*QOf!ci!`!ci~P+_O!`$hi~P,yO$Q&WO~OX$[a~P@}Of&^OX$[a~OW%YOX$ja~Of&cOX$ja~O#e(QO#g'oOf#aXj#aX}#aX!O#aX!P#aX!Q#aX!R#aX!S#aX!T#aX!U#aX!V#aX!W#aX!X#aX!Y#aX!Z#aX![#aX!_#aX!w#aX!z#aX$f#aX$g#aXu#aXX#aX#[#aX$S#aX$V#aX!x#aX!`#aX~O}!hO!O!iO!P!jO!Q!kO!R!lO!S!mO!T!nO!U!oO!V!pO!W!pO!X!qO!Y!qO!Z!tO![!sO!w!rO!z!vO~O!_!vy#[!vy$S!vy$V!vy$f!vy$g!vyf!vyj!vyX!vy!x!vy!`!vy~P!.sOW&gOs&nO$l&iO~P@}OX$[i~P@}OX!iif!ii~P+_O$f%|O$g%|OX#zaf#za~OW%YOX$ji~O#e(QO#g'oOf#aaj#aa}#aa!O#aa!P#aa!Q#aa!R#aa!S#aa!T#aa!U#aa!V#aa!W#aa!X#aa!Y#aa!Z#aa![#aa!_#aa!w#aa!z#aa$f#aa$g#aau#aaX#aa#[#aa$S#aa$V#aa!x#aa!`#aa~O$R&qO$V&rO~P`OW&gOs&nO$R&qO$V!}O$l&iO~P@}OW&vO~OW%YO~O$f&zO$g&zOu!eX~P$hOfqi!`qi~P!*QO}&{Ou|i!O|i!P|i!Q|i!R|i!S|i!T|i!U|i~P!#vO}&{O!O&|Ou|i!P|i!Q|i!R|i!S|i!T|i!U|i~P!#vO}&{O!O&|O!P&}Ou|i!Q|i!R|i!S|i!T|i!U|i~P!#vO}&{O!O&|O!P&}O!Q'OO!S'QO!T'RO!U'SOu|i!R|i~P!#vO}&{O!O&|O!P&}O!Q'OO!T'RO!U'SOu|i!R|i!S|i~P!#vO}&{O!O&|O!P&}O!Q'OO!U'SOu|i!R|i!S|i!T|i~P!#vO}&{O!O&|O!P&}O!Q'OOu|i!R|i!S|i!T|i!U|i~P!#vO}&{O!O&|O!P&}O!Q'OO!R'PO!S'QO!T'RO!U'SO!Z'nO!['VO!z!vOu|i!X|i!Y|i!_|i!w|i$f|i$g|if|i!`|i~O!V|i!W|i~P!9wO!V'TO!W'TO~P!9wO}&{O!O&|O!P&}O!Q'OO!R'PO!S'QO!T'RO!U'SOu|i~P!#vOVSOWUOYaOhsOpYOsnOxoO{pO!ZcO!b`O!g'yO!srO!ubO!}cO#PtO#RuO#TvO#VwO#XxO#_'zO#c'{O#i(TO#k|O#s'|O$S!|O$bVO$cVO~P@}O}&{O!O&|O!P&}O!Q'OO!R'PO!S'QO!T'RO!U'SOu|q~P!(VOu'dO$g&zO~P9kO}&{O!O&|O!P&}O!Q'OO!R'PO!S'QO!T'RO!U'SO!V'TO!W'TO!X'UO!Y'UO!Z'nO!['VO!w(PO!z!vO~Ou!vy!_!vy$f!vy$g!vyf!vy!`!vy~P!?QO$f&zO$g&zO~O!['cO~Ou'dO#RuO~O!x'iO~P+_OW'pO~OW'qO~OW'tO~OW'uO~O!['xO~OVSOs!dOx!eO!g(OO#_'}O~OW(RO~O$^$]]!V!X!Z^_$_!uW$du!}o$l}!O!P!x!w~", | |
| 4085 | goto: "Ac$kPPP$l$t%P%YPPPP&t&wPPP(jPPPP(jP%PP*VP*e+z-a.yPP*e0`P1uP2W0`P2a*eP*ePPPPPPPPPPPPPP*e*ePP*eP4O*e*e*eP4X4`4h4k5m5q6O6R6X5m*eP*eP*ePP*eP6_*eP%PP6bP%PP%PP%PP6w7QP$l7YP7Y7Y7bP7lP7rP7YP7YP7z8O8S8S8S8S7YP8W8b8h8n8u:e:k:r:x;O;YPPPPPPPPP;`;c;mPPP;p;yPPP?bPP@yAPA`]jOl$q&X&f'd[fOl$q&X&f'dR$k#O_eOl#O$q&X&f'd^TOl#O$q&X&f'd#o!]Y[`acpxz}!T!V!^!a!b!h!i!j!k!l!m!n!o!p!q!r!s#U#x$a$e$f$g$z%W%i%n%{%|&V&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'i'x'{'|(P(Q(SR#l!Q#vdOY`aclpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#x$a$e$f$g$q$z%W%i%n%{%|&V&X&f&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'd'i'x'{'|(P(QQ%P#kU&]%x&^&oT&h&[&m$TROY`aclpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#k#x$a$e$f$g$q$z%W%i%n%x%{%|&V&X&[&^&f&m&o&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'd'i'x'{'|(P(QU!UUZ&wQ#]rQ#^sR$v#a#wdOY`aclpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#x$a$e$f$g$q$z%W%i%n%{%|&V&X&f&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'd'i'x'{'|(P(Q#wZOY`aclpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#x$a$e$f$g$q$z%W%i%n%{%|&V&X&f&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'd'i'x'{'|(P(Q#vWOY`aclpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#x$a$e$f$g$q$z%W%i%n%{%|&V&X&f&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'd'i'x'{'|(P(QR#u!X#wXOY`aclpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#x$a$e$f$g$q$z%W%i%n%{%|&V&X&f&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'd'i'x'{'|(P(Q#w]OY`aclpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#x$a$e$f$g$q$z%W%i%n%{%|&V&X&f&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'd'i'x'{'|(P(QU!SU%Y&wQ$s#XQ$t#YQ%d$PR%e$QQ#n!RQ$b!uR&Q%_#v]OY`aclpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#x$a$e$f$g$q$z%W%i%n%{%|&V&X&f&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'd'i'x'{'|(P(QQ%Z#zV&a%}&c&pS!x`!bV%m$g%n&VZ#{!`#[$S'p'uQ%[#zV&b%}&c&pR%`#{S$r#V'oS$w#c'qS$y#d'rS$|#g'sQ%a#|W%f$R$x'f'tS%p$p'wS%t$u'eS&S%g'gS&T%h'hS&Z%u'kR&s&kT%s$q'dQ#QfQ$m#PS%q$q'dR%v${R&Y%qQ&X%qR&[%vQ&r&fR&u&mR$d!v^eOl#O$q&X&f'dQ$x#cQ%g$RQ'f'qR'g'tQ#QfQ$m#PR&u&m]gOl$q&X&f'd]iOl$q&X&f'dYhOl$q&X&fR&R'dX#Rh#S&R&eS#Th&RT$o#S&eT&l&[&mT&k&[&mT&j&[&mQlOS#Wl&fR&f&XQ%y%PR&_%yQ#s!WR%U#sS!YWXR#v!YY[Ol$q&X&f#j!^Y`acpxz}!T!V!a!b!h!i!j!k!l!m!n!o!p!q!r!s#O#U#x$a$e$f$g$z%W%i%n%{%|&V&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'i'x'{'|(P(QU!c[!^(SR(S'dQ$h!xR%o$hS&O%Z%[R&d&OQ#y!_R%X#yQ#PfR$l#PQ#ShS$n#S&eR&e&RQ&m&[R&t&mR!PPWkOl&X&fT%r$q'dR%R#kQ![YQ#q!VR#}!a^^Ol#O$q&X&f'dU!_Y!V!aY!w`!b$g%n&VQ!zaS!{c&xS#Zp&yQ#bxQ#dzQ#g}Q#o!TS$T!h&{Q$U!iQ$V!jQ$W!kQ$X!lQ$Y!mQ$Z!nQ$[!oQ$]!pQ$^!qQ$_!rQ$`!sQ$p#UU%V#x%W%{Q%j$aQ%k$eQ%l$fQ%u$zQ&U%iQ&`%|Q'W&zQ'X&|Q'Y&}Q'Z'OQ'['PQ']'QQ'^'RQ'_'SQ'`'TQ'a'UQ'b'VQ'j'cQ'k'xQ'l'iQ'r'{Q's'|Q'v(PR'w(Q!h_OYaclpx!T!V!a!h!i!j!k!l!m!n!o!p!q!r!s#O#x$a$f$q%W%i%{%|&X&f'd(P!_'m`z}!b#U$e$g$z%n&V&x&y&z&{&|&}'O'P'Q'R'S'T'U'V'c'i'x'{'|(QQ!y`R$O!bQ#|!`Q$u#[Q%h$SQ'e'pR'h'uR%^#z", | |
| 4086 | nodeNames: "\u26A0 Comment Script SimpleStatement SmallStatement StandaloneAnnotationNode AnnotationNode @ Identifier ) ( CallParamsLiteralExpressionNode LiteralExpressionNode True False Null BuiltinConstants PI TAU INF NaN String , AssertNode assert CallParamsExpressionNode ] ArrayExpressionNode SubscriptExpressionNode VariableName GetNodeExpressionNode . [ AssignmentExpressionNode VariableNode var TypeCast : Type ConstantNode const ParameterNode AwaitExpressionNode await BinaryOperatorExpressionNode ArithOp ArithOp ArithOp BitOp CompareOp BitOp BitOp BitOp AndOp LogicOp OrOp LogicOp NotOp in CallExpressionNode CastExpressionNode as } DictionaryExpressionNode { DictionaryEntry GroupedExpressionNode IdentifierExpressionNode LambdaExpressionNode func CallParamsParameterNode AssignmentExpressionNode FunctionReturnType Body SuiteNodeBody Newline SuiteNode Indent Dedent ExpressionNodeBody PreloadExpressionNode preload SelfExpressionNode SelfToken TernaryOperatorExpressionNode TernaryOp TernaryOp TypeTestExpressionNode is ClassName UnaryOperatorNode ArithOp ClassNameStatement class_name ExtendsStatement extends SignalStatement signal PassStatement pass ReturnNode return Eof StatementGroup ; CompoundStatement ClassNode class FunctionNode IfNode IfClause if ElifClause elif ElseClause else ForNode for MatchNode match MatchBranchNode PatternNode VarPatternNode IdentifierPatternNode LiteralPatternNode WildcardPatternNode WhileNode while", | |
| 4087 | maxTerm: 166, | |
| 4088 | context: trackIndent, | |
| 4089 | nodeProps: [ | |
| 4090 | ["group", -2, 3, 105, "Statement", -18, 12, 27, 28, 30, 33, 42, 44, 59, 60, 63, 66, 67, 68, 80, 82, 84, 87, 90, "ExpressionNode", -3, 34, 39, 41, "AssignableNode"], | |
| 4091 | ["openedBy", 9, "("], | |
| 4092 | ["closedBy", 10, ")"] | |
| 4093 | ], | |
| 4094 | propSources: [gdscriptHighlighting], | |
| 4095 | skippedNodes: [0, 1], | |
| 4096 | repeatNodeCount: 11, | |
| 4097 | tokenData: "Ae~R|XY#{pq#{qr$Wrs$est(Vtu(quv(vvw)Vwx)jxy-[yz-az{-f{|-y|}.T}!O.Y!O!P.l!P!Q/w!Q!R0R!R![0s![!]2e!]!^2l!^!_2q!_!`3U!`!a3^!a!b3z!b!c4S!c!}4X!}#O4j#P#Q4o#Q#R4t#R#S4|#T#U5a#U#Y4X#Y#Z6t#Z#b4X#b#c9U#c#d<S#d#g4X#g#h=O#h#i>z#i#o4X#o#p@v#p#q@{#q#rA`~$QQ$X~XY#{pq#{R$]P!}P!_!`$`Q$eO!RQ~$hXOY$eZ]$e^r$ers%Ts#O$e#O#P%u#P;'S$e;'S;=`(P<%lO$e~%YX$_~OY$eZ]$e^r$ers%Ts#O$e#O#P%u#P;'S$e;'S;=`(P<%lO$e~%xVO#i$e#i#j&_#j#l$e#l#m&z#m;'S$e;'S;=`(P<%lO$e~&bS!QQQ)VO$fQ~)[Q!U~vw)b!_!`)Q~)gP!W~!_!`)Q~)mXOY)jZ])j^w)jwx*Yx#O)j#O#P*z#P;'S)j;'S;=`-U<%lO)j~*_X$_~OY)jZ])j^w)jwx*Yx#O)j#O#P*z#P;'S)j;'S;=`-U<%lO)j~*}VO#i)j#i#j+d#j#l)j#l#m,P#m;'S)j;'S;=`-U<%lO)j~+gS!Q![+s!c!i+s#T#Z+s#o#p,i~+vR!Q![,P!c!i,P#T#Z,P~,SR!Q![,]!c!i,]#T#Z,]~,`R!Q![)j!c!i)j#T#Z)j~,lR!Q![,u!c!i,u#T#Z,u~,xS!Q![,u!c!i,u#T#Z,u#q#r)j~-XP;=`<%l)j~-aOY~~-fOX~~-kQ!OQz{-q!_!`)Q~-vP}~!_!`)QR.QP!}P!PQ!_!`)Q~.YOf~V.aQ!}P!PQ!_!`)Q!`!a.gS.lO$kS~.qPo~!Q![.t~.yS$^~!Q![.t!g!h/V#R#S/q#X#Y/V~/YQ{|/`}!O/`~/cP!Q![/f~/kQ$^~!Q![/f#R#S/`~/tP!Q![.t~0OP$d~!OQ!_!`)Q~0WX$]~!O!P/q!Q![0s!d!e1_!g!h/V!z!{1v#R#S1X#U#V1_#X#Y/V#l#m1v~0xT$]~!O!P/q!Q![0s!g!h/V#R#S1X#X#Y/V~1[P!Q![0s~1bQ!Q!R1h!R!S1h~1mR$]~!Q!R1h!R!S1h#R#S1_~1yR!Q![2S!c!i2S#T#Z2S~2XS$]~!Q![2S!c!i2S#R#S1v#T#Z2S~2lOu~!x~~2qO#[~~2vQ!RQ!^!_2|!_!`$`~3RP!Q~!_!`)Q~3ZP$g~!_!`$`~3cQ!RQ!_!`$`!`!a3i~3nQ!Q~!_!`)Q!`!a3tQ3wP!_!`)Q~4PP!w~!a!b3t~4XOV~~4^SW~!Q![4X!c!}4X#R#S4X#T#o4X~4oOp~~4tOj~~4yP!T~!_!`)Q~5TSW~$l~!Q![4X!c!}4X#R#S4X#T#o4X~5fUW~!Q![4X!c!}4X#R#S4X#T#b4X#b#c5x#c#o4X~5}UW~!Q![4X!c!}4X#R#S4X#T#W4X#W#X6a#X#o4X~6hS!V~W~!Q![4X!c!}4X#R#S4X#T#o4X~6yTW~!Q![4X!c!}4X#R#S4X#T#U7Y#U#o4X~7_UW~!Q![4X!c!}4X#R#S4X#T#`4X#`#a7q#a#o4X~7vUW~!Q![4X!c!}4X#R#S4X#T#g4X#g#h8Y#h#o4X~8_UW~!Q![4X!c!}4X#R#S4X#T#X4X#X#Y8q#Y#o4X~8xS^~W~!Q![4X!c!}4X#R#S4X#T#o4X~9ZWW~!Q![4X!c!}4X#R#S4X#T#c4X#c#d9s#d#i4X#i#j:o#j#o4X~9xUW~!Q![4X!c!}4X#R#S4X#T#h4X#h#i:[#i#o4X~:cS!Z~W~!Q![4X!c!}4X#R#S4X#T#o4X~:tUW~!Q![4X!c!}4X#R#S4X#T#`4X#`#a;W#a#o4X~;]UW~!Q![4X!c!}4X#R#S4X#T#`4X#`#a;o#a#o4X~;vS_~W~!Q![4X!c!}4X#R#S4X#T#o4X~<XUW~!Q![4X!c!}4X#R#S4X#T#f4X#f#g<k#g#o4X~<rS!X~W~!Q![4X!c!}4X#R#S4X#T#o4X~=TUW~!Q![4X!c!}4X#R#S4X#T#X4X#X#Y=g#Y#o4X~=lUW~!Q![4X!c!}4X#R#S4X#T#`4X#`#a>O#a#o4X~>TUW~!Q![4X!c!}4X#R#S4X#T#Y4X#Y#Z>g#Z#o4X~>nS!u~W~!Q![4X!c!}4X#R#S4X#T#o4X~?PUW~!Q![4X!c!}4X#R#S4X#T#f4X#f#g?c#g#o4X~?hUW~!Q![4X!c!}4X#R#S4X#T#i4X#i#j?z#j#o4X~@PUW~!Q![4X!c!}4X#R#S4X#T#X4X#X#Y@c#Y#o4X~@jS]~W~!Q![4X!c!}4X#R#S4X#T#o4X~@{O!b~~AQQ!S~!_!`)Q#p#qAW~A]P!Y~!_!`)Q~AeO!`~", | |
| 4098 | tokenizers: [indentation, newlines, 0, 1, 2], | |
| 4099 | topRules: { "Script": [0, 2] }, | |
| 4100 | specialized: [{ term: 8, get: (value) => spec_Identifier[value] || -1 }], | |
| 4101 | tokenPrec: 3645 | |
| 4102 | }); | |
| 4103 | export { | |
| 4104 | parser | |
| 4105 | }; |