@futpib/parser 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +24 -0
- package/.github/workflows/main.yml +1 -0
- package/build/androidPackageParser.js +30 -32
- package/build/arbitraryDalvikBytecode.d.ts +3 -3
- package/build/arbitraryDalvikBytecode.js +33 -27
- package/build/arbitraryDalvikExecutable.js +55 -17
- package/build/arbitraryJava.d.ts +31 -0
- package/build/arbitraryJava.js +532 -0
- package/build/arbitraryJavaScript.d.ts +3 -0
- package/build/arbitraryJavaScript.js +263 -0
- package/build/arbitraryJavascript.d.ts +3 -0
- package/build/arbitraryJavascript.js +263 -0
- package/build/arbitraryZig.d.ts +3 -0
- package/build/arbitraryZig.js +240 -0
- package/build/arbitraryZipStream.d.ts +1 -1
- package/build/arrayParser.js +72 -13
- package/build/backsmali.d.ts +4 -3
- package/build/backsmali.js +26 -6
- package/build/bash.d.ts +6 -1
- package/build/bashParser.js +131 -90
- package/build/bashParser.test.js +162 -0
- package/build/bashParserEdgeCases.test.d.ts +1 -0
- package/build/bashParserEdgeCases.test.js +117 -0
- package/build/dalvikBytecodeParser/addressConversion.d.ts +110 -0
- package/build/dalvikBytecodeParser/addressConversion.js +334 -0
- package/build/dalvikBytecodeParser/formatParsers.d.ts +7 -6
- package/build/dalvikBytecodeParser/formatParsers.js +13 -14
- package/build/dalvikBytecodeParser.d.ts +60 -31
- package/build/dalvikBytecodeParser.js +92 -35
- package/build/dalvikBytecodeParser.test-d.d.ts +1 -0
- package/build/dalvikBytecodeParser.test-d.js +268 -0
- package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +9 -8
- package/build/dalvikBytecodeUnparser/formatUnparsers.js +13 -12
- package/build/dalvikBytecodeUnparser.d.ts +2 -2
- package/build/dalvikBytecodeUnparser.js +23 -23
- package/build/dalvikBytecodeUnparser.test.js +7 -7
- package/build/dalvikExecutable.d.ts +3 -3
- package/build/dalvikExecutable.test-d.d.ts +1 -0
- package/build/dalvikExecutable.test-d.js +59 -0
- package/build/dalvikExecutableParser/typedNumbers.d.ts +18 -0
- package/build/dalvikExecutableParser/typedNumbers.js +3 -0
- package/build/dalvikExecutableParser.d.ts +2 -1
- package/build/dalvikExecutableParser.js +96 -77
- package/build/dalvikExecutableParser.test.js +24 -3
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +3 -0
- package/build/dalvikExecutableUnparser/poolScanners.d.ts +2 -2
- package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +3 -3
- package/build/dalvikExecutableUnparser/sectionUnparsers.js +26 -11
- package/build/dalvikExecutableUnparser.d.ts +2 -2
- package/build/dalvikExecutableUnparser.test.js +2 -1
- package/build/disjunctionParser.d.ts +5 -3
- package/build/disjunctionParser.js +79 -17
- package/build/disjunctionParser.test-d.d.ts +1 -0
- package/build/disjunctionParser.test-d.js +72 -0
- package/build/elementSwitchParser.d.ts +4 -0
- package/build/{exactElementSwitchParser.js → elementSwitchParser.js} +3 -4
- package/build/elementSwitchParser.test-d.d.ts +1 -0
- package/build/elementSwitchParser.test-d.js +44 -0
- package/build/exactSequenceParser.d.ts +4 -2
- package/build/exactSequenceParser.test-d.d.ts +1 -0
- package/build/exactSequenceParser.test-d.js +36 -0
- package/build/fetchCid.js +2 -66
- package/build/index.d.ts +3 -2
- package/build/index.js +2 -1
- package/build/index.test.js +16 -1
- package/build/inputReader.d.ts +10 -0
- package/build/inputReader.js +36 -0
- package/build/java.d.ts +502 -0
- package/build/java.js +2 -0
- package/build/javaKeyStoreParser.js +14 -17
- package/build/javaParser.d.ts +51 -0
- package/build/javaParser.js +1538 -0
- package/build/javaParser.test.d.ts +1 -0
- package/build/javaParser.test.js +1287 -0
- package/build/javaScript.d.ts +35 -0
- package/build/javaScript.js +1 -0
- package/build/javaScriptParser.d.ts +9 -0
- package/build/javaScriptParser.js +34 -0
- package/build/javaScriptUnparser.d.ts +3 -0
- package/build/javaScriptUnparser.js +4 -0
- package/build/javaScriptUnparser.test.d.ts +1 -0
- package/build/javaScriptUnparser.test.js +24 -0
- package/build/javaUnparser.d.ts +2 -0
- package/build/javaUnparser.js +519 -0
- package/build/javaUnparser.test.d.ts +1 -0
- package/build/javaUnparser.test.js +24 -0
- package/build/javascript.d.ts +35 -0
- package/build/javascript.js +1 -0
- package/build/javascriptParser.d.ts +9 -0
- package/build/javascriptParser.js +34 -0
- package/build/javascriptUnparser.d.ts +3 -0
- package/build/javascriptUnparser.js +4 -0
- package/build/javascriptUnparser.test.d.ts +1 -0
- package/build/javascriptUnparser.test.js +24 -0
- package/build/jsonParser.js +2 -12
- package/build/lazyMessageError.d.ts +3 -0
- package/build/lookaheadParser.js +60 -3
- package/build/negativeLookaheadParser.js +70 -11
- package/build/nonEmptyArrayParser.js +72 -13
- package/build/objectParser.d.ts +12 -0
- package/build/objectParser.js +31 -0
- package/build/objectParser.test-d.d.ts +1 -0
- package/build/objectParser.test-d.js +112 -0
- package/build/objectParser.test.d.ts +1 -0
- package/build/objectParser.test.js +55 -0
- package/build/optionalParser.js +69 -10
- package/build/parser.d.ts +4 -0
- package/build/parser.js +3 -1
- package/build/parser.test.js +114 -1
- package/build/parserConsumedSequenceParser.js +66 -7
- package/build/parserContext.d.ts +6 -0
- package/build/parserContext.js +20 -11
- package/build/parserError.d.ts +119 -27
- package/build/parserError.js +16 -8
- package/build/regexpParser.js +33 -3
- package/build/regexpParser.test.js +31 -0
- package/build/regularExpressionParser.js +35 -15
- package/build/separatedArrayParser.js +73 -14
- package/build/separatedNonEmptyArrayParser.js +73 -14
- package/build/sliceBoundedParser.js +62 -5
- package/build/smaliParser.d.ts +7 -7
- package/build/smaliParser.js +185 -268
- package/build/smaliParser.test.js +58 -0
- package/build/stringEscapes.d.ts +5 -0
- package/build/stringEscapes.js +244 -0
- package/build/symbolicExpression.d.ts +29 -0
- package/build/symbolicExpression.js +1 -0
- package/build/symbolicExpressionParser.d.ts +4 -0
- package/build/symbolicExpressionParser.js +123 -0
- package/build/symbolicExpressionParser.test.d.ts +1 -0
- package/build/symbolicExpressionParser.test.js +289 -0
- package/build/terminatedArrayParser.js +113 -38
- package/build/terminatedArrayParser.test.js +4 -2
- package/build/tupleParser.d.ts +7 -15
- package/build/tupleParser.js +1 -0
- package/build/unionParser.d.ts +5 -3
- package/build/unionParser.js +7 -2
- package/build/unionParser.test-d.d.ts +1 -0
- package/build/unionParser.test-d.js +72 -0
- package/build/unionParser.test.js +10 -11
- package/build/zig.d.ts +280 -0
- package/build/zig.js +2 -0
- package/build/zigParser.d.ts +3 -0
- package/build/zigParser.js +1119 -0
- package/build/zigParser.test.d.ts +1 -0
- package/build/zigParser.test.js +1590 -0
- package/build/zigUnparser.d.ts +2 -0
- package/build/zigUnparser.js +460 -0
- package/build/zigUnparser.test.d.ts +1 -0
- package/build/zigUnparser.test.js +24 -0
- package/build/zipParser.js +19 -32
- package/build/zipUnparser.js +19 -7
- package/build/zipUnparser.test.js +1 -1
- package/node_modules-@types/s-expression/index.d.ts +5 -0
- package/package.json +24 -6
- package/src/androidPackageParser.ts +33 -60
- package/src/arbitraryDalvikBytecode.ts +39 -31
- package/src/arbitraryDalvikExecutable.ts +65 -20
- package/src/arbitraryJava.ts +804 -0
- package/src/arbitraryJavaScript.ts +410 -0
- package/src/arbitraryZig.ts +380 -0
- package/src/arrayParser.ts +1 -3
- package/src/backsmali.ts +35 -4
- package/src/bash.ts +8 -1
- package/src/bashParser.test.ts +258 -0
- package/src/bashParser.ts +180 -143
- package/src/dalvikBytecodeParser/addressConversion.ts +496 -0
- package/src/dalvikBytecodeParser/formatParsers.ts +19 -29
- package/src/dalvikBytecodeParser.test-d.ts +310 -0
- package/src/dalvikBytecodeParser.ts +194 -69
- package/src/dalvikBytecodeUnparser/formatUnparsers.ts +27 -26
- package/src/dalvikBytecodeUnparser.test.ts +7 -7
- package/src/dalvikBytecodeUnparser.ts +31 -30
- package/src/dalvikExecutable.test-d.ts +132 -0
- package/src/dalvikExecutable.ts +3 -3
- package/src/dalvikExecutableParser/typedNumbers.ts +11 -0
- package/src/dalvikExecutableParser.test.ts +37 -3
- package/src/dalvikExecutableParser.test.ts.md +163 -2
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +121 -139
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +4 -0
- package/src/dalvikExecutableUnparser/poolScanners.ts +6 -6
- package/src/dalvikExecutableUnparser/sectionUnparsers.ts +38 -14
- package/src/dalvikExecutableUnparser.test.ts +3 -2
- package/src/dalvikExecutableUnparser.ts +4 -4
- package/src/disjunctionParser.test-d.ts +105 -0
- package/src/disjunctionParser.ts +18 -15
- package/src/elementSwitchParser.test-d.ts +74 -0
- package/src/elementSwitchParser.ts +51 -0
- package/src/exactSequenceParser.test-d.ts +43 -0
- package/src/exactSequenceParser.ts +13 -8
- package/src/fetchCid.ts +2 -76
- package/src/index.test.ts +22 -1
- package/src/index.ts +7 -1
- package/src/inputReader.ts +53 -0
- package/src/java.ts +708 -0
- package/src/javaKeyStoreParser.ts +18 -32
- package/src/javaParser.test.ts +1592 -0
- package/src/javaParser.ts +2640 -0
- package/src/javaScript.ts +36 -0
- package/src/javaScriptParser.ts +57 -0
- package/src/javaScriptUnparser.test.ts +37 -0
- package/src/javaScriptUnparser.ts +7 -0
- package/src/javaUnparser.test.ts +37 -0
- package/src/javaUnparser.ts +640 -0
- package/src/jsonParser.ts +6 -27
- package/src/lookaheadParser.ts +2 -6
- package/src/negativeLookaheadParser.ts +1 -3
- package/src/nonEmptyArrayParser.ts +1 -3
- package/src/objectParser.test-d.ts +152 -0
- package/src/objectParser.test.ts +71 -0
- package/src/objectParser.ts +69 -0
- package/src/optionalParser.ts +1 -3
- package/src/parser.test.ts +151 -4
- package/src/parser.ts +11 -1
- package/src/parserConsumedSequenceParser.ts +2 -4
- package/src/parserContext.ts +26 -11
- package/src/parserError.ts +17 -3
- package/src/regexpParser.test.ts +78 -0
- package/src/regexpParser.ts +35 -3
- package/src/regularExpressionParser.ts +36 -37
- package/src/separatedArrayParser.ts +1 -3
- package/src/separatedNonEmptyArrayParser.ts +1 -3
- package/src/sliceBoundedParser.test.ts +2 -2
- package/src/sliceBoundedParser.ts +15 -19
- package/src/smaliParser.test.ts +64 -0
- package/src/smaliParser.test.ts.md +12 -12
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +246 -534
- package/src/stringEscapes.ts +253 -0
- package/src/symbolicExpression.ts +17 -0
- package/src/symbolicExpressionParser.test.ts +466 -0
- package/src/symbolicExpressionParser.ts +190 -0
- package/src/terminatedArrayParser.test.ts +9 -6
- package/src/terminatedArrayParser.ts +25 -29
- package/src/tupleParser.ts +21 -18
- package/src/unionParser.test-d.ts +105 -0
- package/src/unionParser.test.ts +18 -17
- package/src/unionParser.ts +28 -16
- package/src/zig.ts +411 -0
- package/src/zigParser.test.ts +1693 -0
- package/src/zigParser.ts +1745 -0
- package/src/zigUnparser.test.ts +37 -0
- package/src/zigUnparser.ts +615 -0
- package/src/zipParser.ts +20 -56
- package/src/zipUnparser.test.ts +1 -1
- package/src/zipUnparser.ts +22 -7
- package/tsconfig.json +2 -2
- package/build/exactElementSwitchParser.d.ts +0 -3
- package/src/exactElementSwitchParser.ts +0 -41
package/src/bashParser.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { createOptionalParser } from './optionalParser.js';
|
|
|
10
10
|
import { createRegExpParser } from './regexpParser.js';
|
|
11
11
|
import { createNonEmptyArrayParser } from './nonEmptyArrayParser.js';
|
|
12
12
|
import { createSeparatedNonEmptyArrayParser } from './separatedNonEmptyArrayParser.js';
|
|
13
|
+
import { createObjectParser } from './objectParser.js';
|
|
13
14
|
import {
|
|
14
15
|
type BashWord,
|
|
15
16
|
type BashWordPart,
|
|
@@ -17,8 +18,11 @@ import {
|
|
|
17
18
|
type BashWordPartSingleQuoted,
|
|
18
19
|
type BashWordPartDoubleQuoted,
|
|
19
20
|
type BashWordPartVariable,
|
|
21
|
+
type BashWordPartVariableBraced,
|
|
20
22
|
type BashWordPartCommandSubstitution,
|
|
21
23
|
type BashWordPartBacktickSubstitution,
|
|
24
|
+
type BashWordPartArithmeticExpansion,
|
|
25
|
+
type BashWordPartProcessSubstitution,
|
|
22
26
|
type BashSimpleCommand,
|
|
23
27
|
type BashSubshell,
|
|
24
28
|
type BashBraceGroup,
|
|
@@ -30,14 +34,14 @@ import {
|
|
|
30
34
|
type BashCommand,
|
|
31
35
|
} from './bash.js';
|
|
32
36
|
|
|
33
|
-
// Whitespace (spaces
|
|
37
|
+
// Whitespace (spaces, tabs, and line continuations - not bare newlines which are significant)
|
|
34
38
|
const bashInlineWhitespaceParser: Parser<string, string> = promiseCompose(
|
|
35
|
-
createRegExpParser(/[ \t]+/),
|
|
39
|
+
createRegExpParser(/(?:[ \t]|\\\n)+/),
|
|
36
40
|
match => match[0],
|
|
37
41
|
);
|
|
38
42
|
|
|
39
43
|
const bashOptionalInlineWhitespaceParser: Parser<string, string> = promiseCompose(
|
|
40
|
-
createRegExpParser(/[ \t]*/),
|
|
44
|
+
createRegExpParser(/(?:[ \t]|\\\n)*/),
|
|
41
45
|
match => match[0],
|
|
42
46
|
);
|
|
43
47
|
|
|
@@ -49,26 +53,22 @@ const bashNewlineParser: Parser<string, string> = promiseCompose(
|
|
|
49
53
|
|
|
50
54
|
// Word characters (unquoted, no special chars)
|
|
51
55
|
// Note: {} are excluded so brace groups are parsed correctly
|
|
56
|
+
// # is excluded from the first character (starts a comment) but allowed mid-word
|
|
52
57
|
const bashUnquotedWordCharsParser: Parser<string, string> = promiseCompose(
|
|
53
|
-
createRegExpParser(/[^\s\n|&;<>(){}$`"'\\#]
|
|
58
|
+
createRegExpParser(/[^\s\n|&;<>(){}$`"'\\#][^\s\n|&;<>(){}$`"'\\]*/),
|
|
54
59
|
match => match[0],
|
|
55
60
|
);
|
|
56
61
|
|
|
57
62
|
// Single quoted string: '...'
|
|
58
|
-
const bashSingleQuotedParser: Parser<BashWordPartSingleQuoted, string> =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
([, value]) => ({
|
|
68
|
-
type: 'singleQuoted' as const,
|
|
69
|
-
value,
|
|
70
|
-
}),
|
|
71
|
-
);
|
|
63
|
+
const bashSingleQuotedParser: Parser<BashWordPartSingleQuoted, string> = createObjectParser({
|
|
64
|
+
type: 'singleQuoted' as const,
|
|
65
|
+
_open: createExactSequenceParser("'"),
|
|
66
|
+
value: promiseCompose(
|
|
67
|
+
createRegExpParser(/[^']*/),
|
|
68
|
+
match => match[0],
|
|
69
|
+
),
|
|
70
|
+
_close: createExactSequenceParser("'"),
|
|
71
|
+
});
|
|
72
72
|
|
|
73
73
|
// Variable name
|
|
74
74
|
const bashVariableNameParser: Parser<string, string> = promiseCompose(
|
|
@@ -77,47 +77,84 @@ const bashVariableNameParser: Parser<string, string> = promiseCompose(
|
|
|
77
77
|
);
|
|
78
78
|
|
|
79
79
|
// Simple variable: $var
|
|
80
|
-
const bashSimpleVariableParser: Parser<BashWordPartVariable, string> =
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
([, name]) => ({
|
|
86
|
-
type: 'variable' as const,
|
|
87
|
-
name,
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
80
|
+
const bashSimpleVariableParser: Parser<BashWordPartVariable, string> = createObjectParser({
|
|
81
|
+
type: 'variable' as const,
|
|
82
|
+
_dollar: createExactSequenceParser('$'),
|
|
83
|
+
name: bashVariableNameParser,
|
|
84
|
+
});
|
|
90
85
|
|
|
91
86
|
// Command substitution: $(...)
|
|
92
|
-
const bashCommandSubstitutionParser: Parser<BashWordPartCommandSubstitution, string> =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
([, , command]) => ({
|
|
101
|
-
type: 'commandSubstitution' as const,
|
|
102
|
-
command,
|
|
103
|
-
}),
|
|
104
|
-
);
|
|
87
|
+
const bashCommandSubstitutionParser: Parser<BashWordPartCommandSubstitution, string> = createObjectParser({
|
|
88
|
+
type: 'commandSubstitution' as const,
|
|
89
|
+
_open: createExactSequenceParser('$('),
|
|
90
|
+
_ws1: bashOptionalInlineWhitespaceParser,
|
|
91
|
+
command: createParserAccessorParser(() => bashCommandParser),
|
|
92
|
+
_ws2: bashOptionalInlineWhitespaceParser,
|
|
93
|
+
_close: createExactSequenceParser(')'),
|
|
94
|
+
});
|
|
105
95
|
|
|
106
96
|
// Backtick substitution: `...`
|
|
107
|
-
const bashBacktickSubstitutionParser: Parser<BashWordPartBacktickSubstitution, string> =
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
)
|
|
97
|
+
const bashBacktickSubstitutionParser: Parser<BashWordPartBacktickSubstitution, string> = createObjectParser({
|
|
98
|
+
type: 'backtickSubstitution' as const,
|
|
99
|
+
_open: createExactSequenceParser('`'),
|
|
100
|
+
command: createParserAccessorParser(() => bashCommandParser),
|
|
101
|
+
_close: createExactSequenceParser('`'),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Braced variable expansion: ${VAR} or ${VAR:-default}
|
|
105
|
+
const bashBracedVariableParser: Parser<BashWordPartVariableBraced, string> = createObjectParser({
|
|
106
|
+
type: 'variableBraced' as const,
|
|
107
|
+
_open: createExactSequenceParser('${'),
|
|
108
|
+
name: bashVariableNameParser,
|
|
109
|
+
operator: createOptionalParser(promiseCompose(
|
|
110
|
+
createRegExpParser(/:-|:=|:\+|:\?|-|=|\+|\?|##|#|%%|%/),
|
|
111
|
+
match => match[0],
|
|
112
|
+
)),
|
|
113
|
+
operand: createOptionalParser(createParserAccessorParser(() => bashWordParser)),
|
|
114
|
+
_close: createExactSequenceParser('}'),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Arithmetic expansion: $((expression))
|
|
118
|
+
const bashArithmeticExpansionParser: Parser<BashWordPartArithmeticExpansion, string> = createObjectParser({
|
|
119
|
+
type: 'arithmeticExpansion' as const,
|
|
120
|
+
_open: createExactSequenceParser('$(('),
|
|
121
|
+
expression: promiseCompose(
|
|
122
|
+
createRegExpParser(/(?:[^)]|\)(?!\)))*/),
|
|
123
|
+
match => match[0],
|
|
124
|
+
),
|
|
125
|
+
_close: createExactSequenceParser('))'),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// ANSI-C quoting: $'...'
|
|
129
|
+
const bashAnsiCQuotedParser: Parser<BashWordPartSingleQuoted, string> = createObjectParser({
|
|
130
|
+
type: 'singleQuoted' as const,
|
|
131
|
+
_prefix: createExactSequenceParser('$'),
|
|
132
|
+
_open: createExactSequenceParser("'"),
|
|
133
|
+
value: promiseCompose(
|
|
134
|
+
createRegExpParser(/(?:[^'\\]|\\.)*/),
|
|
135
|
+
match => match[0],
|
|
136
|
+
),
|
|
137
|
+
_close: createExactSequenceParser("'"),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Process substitution: <(cmd) or >(cmd)
|
|
141
|
+
const bashProcessSubstitutionParser: Parser<BashWordPartProcessSubstitution, string> = createObjectParser({
|
|
142
|
+
type: 'processSubstitution' as const,
|
|
143
|
+
direction: promiseCompose(
|
|
144
|
+
createRegExpParser(/[<>](?=\()/),
|
|
145
|
+
match => match[0] as '<' | '>',
|
|
146
|
+
),
|
|
147
|
+
_open: createExactSequenceParser('('),
|
|
148
|
+
_ws1: bashOptionalInlineWhitespaceParser,
|
|
149
|
+
command: createParserAccessorParser(() => bashCommandParser),
|
|
150
|
+
_ws2: bashOptionalInlineWhitespaceParser,
|
|
151
|
+
_close: createExactSequenceParser(')'),
|
|
152
|
+
});
|
|
118
153
|
|
|
119
154
|
// Double quoted string parts (inside "...")
|
|
120
155
|
const bashDoubleQuotedPartParser: Parser<BashWordPart, string> = createDisjunctionParser([
|
|
156
|
+
bashBracedVariableParser,
|
|
157
|
+
bashArithmeticExpansionParser,
|
|
121
158
|
bashSimpleVariableParser,
|
|
122
159
|
bashCommandSubstitutionParser,
|
|
123
160
|
bashBacktickSubstitutionParser,
|
|
@@ -137,29 +174,37 @@ const bashDoubleQuotedPartParser: Parser<BashWordPart, string> = createDisjuncti
|
|
|
137
174
|
value: match[0],
|
|
138
175
|
}),
|
|
139
176
|
),
|
|
177
|
+
// Bare $ not followed by a valid expansion start (e.g. $" at end of double-quoted string)
|
|
178
|
+
promiseCompose(
|
|
179
|
+
createRegExpParser(/\$/),
|
|
180
|
+
() => ({
|
|
181
|
+
type: 'literal' as const,
|
|
182
|
+
value: '$',
|
|
183
|
+
}),
|
|
184
|
+
),
|
|
185
|
+
// Bare \ not followed by a recognized escape character (treated as literal backslash in bash)
|
|
186
|
+
promiseCompose(
|
|
187
|
+
createRegExpParser(/\\/),
|
|
188
|
+
() => ({
|
|
189
|
+
type: 'literal' as const,
|
|
190
|
+
value: '\\',
|
|
191
|
+
}),
|
|
192
|
+
),
|
|
140
193
|
]);
|
|
141
194
|
|
|
142
195
|
// Double quoted string: "..."
|
|
143
|
-
const bashDoubleQuotedParser: Parser<BashWordPartDoubleQuoted, string> =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
([, parts]) => ({
|
|
150
|
-
type: 'doubleQuoted' as const,
|
|
151
|
-
parts,
|
|
152
|
-
}),
|
|
153
|
-
);
|
|
196
|
+
const bashDoubleQuotedParser: Parser<BashWordPartDoubleQuoted, string> = createObjectParser({
|
|
197
|
+
type: 'doubleQuoted' as const,
|
|
198
|
+
_open: createExactSequenceParser('"'),
|
|
199
|
+
parts: createArrayParser(bashDoubleQuotedPartParser),
|
|
200
|
+
_close: createExactSequenceParser('"'),
|
|
201
|
+
});
|
|
154
202
|
|
|
155
203
|
// Literal word part (unquoted)
|
|
156
|
-
const bashLiteralWordPartParser: Parser<BashWordPartLiteral, string> =
|
|
157
|
-
|
|
158
|
-
value
|
|
159
|
-
|
|
160
|
-
value,
|
|
161
|
-
}),
|
|
162
|
-
);
|
|
204
|
+
const bashLiteralWordPartParser: Parser<BashWordPartLiteral, string> = createObjectParser({
|
|
205
|
+
type: 'literal' as const,
|
|
206
|
+
value: bashUnquotedWordCharsParser,
|
|
207
|
+
});
|
|
163
208
|
|
|
164
209
|
// Escape sequence outside quotes
|
|
165
210
|
const bashEscapeParser: Parser<BashWordPartLiteral, string> = promiseCompose(
|
|
@@ -172,37 +217,42 @@ const bashEscapeParser: Parser<BashWordPartLiteral, string> = promiseCompose(
|
|
|
172
217
|
|
|
173
218
|
// Word part (any part of a word)
|
|
174
219
|
const bashWordPartParser: Parser<BashWordPart, string> = createDisjunctionParser([
|
|
220
|
+
bashAnsiCQuotedParser,
|
|
175
221
|
bashSingleQuotedParser,
|
|
176
222
|
bashDoubleQuotedParser,
|
|
223
|
+
bashBracedVariableParser,
|
|
224
|
+
bashArithmeticExpansionParser,
|
|
177
225
|
bashCommandSubstitutionParser,
|
|
178
226
|
bashBacktickSubstitutionParser,
|
|
179
227
|
bashSimpleVariableParser,
|
|
228
|
+
bashProcessSubstitutionParser,
|
|
180
229
|
bashEscapeParser,
|
|
181
230
|
bashLiteralWordPartParser,
|
|
231
|
+
// Bare $ not followed by a valid expansion start
|
|
232
|
+
promiseCompose(
|
|
233
|
+
createRegExpParser(/\$/),
|
|
234
|
+
() => ({
|
|
235
|
+
type: 'literal' as const,
|
|
236
|
+
value: '$',
|
|
237
|
+
}),
|
|
238
|
+
),
|
|
182
239
|
]);
|
|
183
240
|
|
|
184
241
|
// Word (sequence of word parts)
|
|
185
|
-
export const bashWordParser: Parser<BashWord, string> =
|
|
186
|
-
createNonEmptyArrayParser(bashWordPartParser),
|
|
187
|
-
|
|
188
|
-
);
|
|
242
|
+
export const bashWordParser: Parser<BashWord, string> = createObjectParser({
|
|
243
|
+
parts: createNonEmptyArrayParser(bashWordPartParser),
|
|
244
|
+
});
|
|
189
245
|
|
|
190
246
|
setParserName(bashWordParser, 'bashWordParser');
|
|
191
247
|
|
|
192
248
|
// Assignment: NAME=value or NAME=
|
|
193
|
-
const bashAssignmentParser: Parser<BashAssignment, string> =
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
]),
|
|
201
|
-
([name, value]) => ({
|
|
202
|
-
name,
|
|
203
|
-
value: value ?? undefined,
|
|
204
|
-
}),
|
|
205
|
-
);
|
|
249
|
+
const bashAssignmentParser: Parser<BashAssignment, string> = createObjectParser({
|
|
250
|
+
name: promiseCompose(
|
|
251
|
+
createRegExpParser(/[a-zA-Z_][a-zA-Z0-9_]*=/),
|
|
252
|
+
match => match[0].slice(0, -1),
|
|
253
|
+
),
|
|
254
|
+
value: createOptionalParser(bashWordParser),
|
|
255
|
+
});
|
|
206
256
|
|
|
207
257
|
// Redirect operators
|
|
208
258
|
const bashRedirectOperatorParser: Parser<BashRedirect['operator'], string> = createDisjunctionParser([
|
|
@@ -217,22 +267,15 @@ const bashRedirectOperatorParser: Parser<BashRedirect['operator'], string> = cre
|
|
|
217
267
|
]);
|
|
218
268
|
|
|
219
269
|
// Redirect: [n]op word
|
|
220
|
-
const bashRedirectParser: Parser<BashRedirect, string> =
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
]),
|
|
230
|
-
([fd, operator, , target]) => ({
|
|
231
|
-
fd: fd ?? undefined,
|
|
232
|
-
operator,
|
|
233
|
-
target,
|
|
234
|
-
}),
|
|
235
|
-
);
|
|
270
|
+
const bashRedirectParser: Parser<BashRedirect, string> = createObjectParser({
|
|
271
|
+
fd: createOptionalParser(promiseCompose(
|
|
272
|
+
createRegExpParser(/[0-9]+/),
|
|
273
|
+
match => Number.parseInt(match[0], 10),
|
|
274
|
+
)),
|
|
275
|
+
operator: bashRedirectOperatorParser,
|
|
276
|
+
_ws: bashOptionalInlineWhitespaceParser,
|
|
277
|
+
target: bashWordParser,
|
|
278
|
+
});
|
|
236
279
|
|
|
237
280
|
// Word with optional trailing whitespace - for use in arrays
|
|
238
281
|
const bashWordWithWhitespaceParser: Parser<BashWord, string> = promiseCompose(
|
|
@@ -254,8 +297,8 @@ const bashRedirectWithWhitespaceParser: Parser<BashRedirect, string> = promiseCo
|
|
|
254
297
|
|
|
255
298
|
// Word or redirect - for interleaved parsing in simple commands
|
|
256
299
|
const bashWordOrRedirectParser: Parser<{ type: 'word'; word: BashWord } | { type: 'redirect'; redirect: BashRedirect }, string> = createDisjunctionParser([
|
|
257
|
-
|
|
258
|
-
|
|
300
|
+
createObjectParser({ type: 'redirect' as const, redirect: bashRedirectWithWhitespaceParser }),
|
|
301
|
+
createObjectParser({ type: 'word' as const, word: bashWordWithWhitespaceParser }),
|
|
259
302
|
]);
|
|
260
303
|
|
|
261
304
|
// Simple command: [assignments] [name] [args] [redirects]
|
|
@@ -299,38 +342,28 @@ export const bashSimpleCommandParser: Parser<BashSimpleCommand, string> = promis
|
|
|
299
342
|
setParserName(bashSimpleCommandParser, 'bashSimpleCommandParser');
|
|
300
343
|
|
|
301
344
|
// Subshell: ( command )
|
|
302
|
-
const bashSubshellParser: Parser<BashSubshell, string> =
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
([, , body]) => ({
|
|
311
|
-
type: 'subshell' as const,
|
|
312
|
-
body,
|
|
313
|
-
}),
|
|
314
|
-
);
|
|
345
|
+
const bashSubshellParser: Parser<BashSubshell, string> = createObjectParser({
|
|
346
|
+
type: 'subshell' as const,
|
|
347
|
+
_open: createExactSequenceParser('('),
|
|
348
|
+
_ws1: bashOptionalInlineWhitespaceParser,
|
|
349
|
+
body: createParserAccessorParser(() => bashCommandParser),
|
|
350
|
+
_ws2: bashOptionalInlineWhitespaceParser,
|
|
351
|
+
_close: createExactSequenceParser(')'),
|
|
352
|
+
});
|
|
315
353
|
|
|
316
354
|
setParserName(bashSubshellParser, 'bashSubshellParser');
|
|
317
355
|
|
|
318
356
|
// Brace group: { command; }
|
|
319
|
-
const bashBraceGroupParser: Parser<BashBraceGroup, string> =
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
([, , body]) => ({
|
|
330
|
-
type: 'braceGroup' as const,
|
|
331
|
-
body,
|
|
332
|
-
}),
|
|
333
|
-
);
|
|
357
|
+
const bashBraceGroupParser: Parser<BashBraceGroup, string> = createObjectParser({
|
|
358
|
+
type: 'braceGroup' as const,
|
|
359
|
+
_open: createExactSequenceParser('{'),
|
|
360
|
+
_ws1: bashInlineWhitespaceParser,
|
|
361
|
+
body: createParserAccessorParser(() => bashCommandParser),
|
|
362
|
+
_ws2: bashOptionalInlineWhitespaceParser,
|
|
363
|
+
_semi: createOptionalParser(createExactSequenceParser(';')),
|
|
364
|
+
_ws3: bashOptionalInlineWhitespaceParser,
|
|
365
|
+
_close: createExactSequenceParser('}'),
|
|
366
|
+
});
|
|
334
367
|
|
|
335
368
|
setParserName(bashBraceGroupParser, 'bashBraceGroupParser');
|
|
336
369
|
|
|
@@ -390,15 +423,12 @@ const bashListSeparatorParser: Parser<'&&' | '||' | ';' | '&' | '\n', string> =
|
|
|
390
423
|
const bashCommandListParser: Parser<BashCommandList, string> = promiseCompose(
|
|
391
424
|
createTupleParser([
|
|
392
425
|
bashPipelineParser,
|
|
393
|
-
createArrayParser(
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
]),
|
|
400
|
-
([, separator, , pipeline]) => ({ separator, pipeline }),
|
|
401
|
-
)),
|
|
426
|
+
createArrayParser(createObjectParser({
|
|
427
|
+
_ws1: bashOptionalInlineWhitespaceParser,
|
|
428
|
+
separator: bashListSeparatorParser,
|
|
429
|
+
_ws2: bashOptionalInlineWhitespaceParser,
|
|
430
|
+
pipeline: bashPipelineParser,
|
|
431
|
+
})),
|
|
402
432
|
createOptionalParser(promiseCompose(
|
|
403
433
|
createTupleParser([
|
|
404
434
|
bashOptionalInlineWhitespaceParser,
|
|
@@ -448,12 +478,19 @@ export const bashCommandParser: Parser<BashCommand, string> = bashCommandListPar
|
|
|
448
478
|
|
|
449
479
|
setParserName(bashCommandParser, 'bashCommandParser');
|
|
450
480
|
|
|
451
|
-
//
|
|
481
|
+
// Comment: # through end of line
|
|
482
|
+
const bashOptionalCommentParser: Parser<string | undefined, string> = createOptionalParser(promiseCompose(
|
|
483
|
+
createRegExpParser(/#[^\n]*/),
|
|
484
|
+
match => match[0],
|
|
485
|
+
));
|
|
486
|
+
|
|
487
|
+
// Script parser (handles leading/trailing whitespace and comments)
|
|
452
488
|
export const bashScriptParser: Parser<BashCommand, string> = promiseCompose(
|
|
453
489
|
createTupleParser([
|
|
454
490
|
bashOptionalInlineWhitespaceParser,
|
|
455
491
|
bashCommandParser,
|
|
456
492
|
bashOptionalInlineWhitespaceParser,
|
|
493
|
+
bashOptionalCommentParser,
|
|
457
494
|
]),
|
|
458
495
|
([, command]) => command,
|
|
459
496
|
);
|