(P: ParseState, kwTok: Token)
| 3592 | } |
| 3593 | |
| 3594 | function parseDeclaration(P: ParseState, kwTok: Token): TsNode { |
| 3595 | const kw = leaf(P, kwTok.value, kwTok) |
| 3596 | const kids: TsNode[] = [kw] |
| 3597 | while (true) { |
| 3598 | skipBlanks(P.L) |
| 3599 | const c = peek(P.L) |
| 3600 | if ( |
| 3601 | c === '' || |
| 3602 | c === '\n' || |
| 3603 | c === ';' || |
| 3604 | c === '&' || |
| 3605 | c === '|' || |
| 3606 | c === ')' || |
| 3607 | c === '<' || |
| 3608 | c === '>' |
| 3609 | ) { |
| 3610 | break |
| 3611 | } |
| 3612 | const a = tryParseAssignment(P) |
| 3613 | if (a) { |
| 3614 | kids.push(a) |
| 3615 | continue |
| 3616 | } |
| 3617 | // Quoted string or concatenation: `export "FOO=bar"`, `export 'X'` |
| 3618 | if (c === '"' || c === "'" || c === '$') { |
| 3619 | const w = parseWord(P, 'arg') |
| 3620 | if (w) { |
| 3621 | kids.push(w) |
| 3622 | continue |
| 3623 | } |
| 3624 | break |
| 3625 | } |
| 3626 | // Flag like -a or bare variable name |
| 3627 | const save = saveLex(P.L) |
| 3628 | const tok = nextToken(P.L, 'arg') |
| 3629 | if (tok.type === 'WORD' || tok.type === 'NUMBER') { |
| 3630 | if (tok.value.startsWith('-')) { |
| 3631 | kids.push(leaf(P, 'word', tok)) |
| 3632 | } else if (isIdentStart(tok.value[0] ?? '')) { |
| 3633 | kids.push(mk(P, 'variable_name', tok.start, tok.end, [])) |
| 3634 | } else { |
| 3635 | kids.push(leaf(P, 'word', tok)) |
| 3636 | } |
| 3637 | } else { |
| 3638 | restoreLex(P.L, save) |
| 3639 | break |
| 3640 | } |
| 3641 | } |
| 3642 | const last = kids[kids.length - 1]! |
| 3643 | return mk(P, 'declaration_command', kw.startIndex, last.endIndex, kids) |
| 3644 | } |
| 3645 | |
| 3646 | function parseUnset(P: ParseState, kwTok: Token): TsNode { |
| 3647 | const kw = leaf(P, 'unset', kwTok) |
no test coverage detected