@futpib/parser 1.0.3 → 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 +89 -0
- package/build/bash.js +1 -0
- package/build/bashParser.d.ts +6 -0
- package/build/bashParser.js +335 -0
- package/build/bashParser.test.d.ts +1 -0
- package/build/bashParser.test.js +343 -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 +25 -2
- package/build/index.js +23 -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.d.ts +2 -0
- package/build/regexpParser.js +101 -0
- package/build/regexpParser.test.d.ts +1 -0
- package/build/regexpParser.test.js +114 -0
- package/build/regularExpression.d.ts +63 -0
- package/build/regularExpression.js +1 -0
- package/build/regularExpressionParser.d.ts +3 -0
- package/build/regularExpressionParser.js +600 -0
- package/build/regularExpressionParser.test.d.ts +1 -0
- package/build/regularExpressionParser.test.js +89 -0
- 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 +25 -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 +127 -0
- package/src/bashParser.test.ts +590 -0
- package/src/bashParser.ts +498 -0
- 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 +119 -2
- 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 +264 -0
- package/src/regexpParser.ts +126 -0
- package/src/regularExpression.ts +24 -0
- package/src/regularExpressionParser.test.ts +102 -0
- package/src/regularExpressionParser.ts +920 -0
- 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
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import * as fc from 'fast-check';
|
|
2
|
+
import {
|
|
3
|
+
type ZigRoot,
|
|
4
|
+
type ZigExpression,
|
|
5
|
+
type ZigTypeExpression,
|
|
6
|
+
type ZigStatement,
|
|
7
|
+
type ZigFnParam,
|
|
8
|
+
type ZigContainerMember,
|
|
9
|
+
type ZigBlockExpr,
|
|
10
|
+
} from './zig.js';
|
|
11
|
+
|
|
12
|
+
const zigKeywords = new Set([
|
|
13
|
+
'addrspace', 'align', 'allowzero', 'and', 'anyframe', 'anytype',
|
|
14
|
+
'asm', 'async', 'await', 'break', 'callconv', 'catch', 'comptime',
|
|
15
|
+
'const', 'continue', 'defer', 'else', 'enum', 'errdefer', 'error',
|
|
16
|
+
'export', 'extern', 'false', 'fn', 'for', 'if', 'inline',
|
|
17
|
+
'linksection', 'noalias', 'nosuspend', 'null', 'opaque', 'or',
|
|
18
|
+
'orelse', 'packed', 'pub', 'resume', 'return', 'struct',
|
|
19
|
+
'suspend', 'switch', 'test', 'threadlocal', 'true', 'try',
|
|
20
|
+
'undefined', 'union', 'unreachable', 'var', 'volatile', 'while',
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
const arbitraryZigIdentifier = fc.stringMatching(/^[a-zA-Z_][a-zA-Z0-9_]*$/).filter(
|
|
24
|
+
id => !zigKeywords.has(id),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// Leaf expressions - safe to use as operands without precedence issues
|
|
28
|
+
|
|
29
|
+
const arbitraryIdentifier: fc.Arbitrary<ZigExpression> = fc.record({
|
|
30
|
+
type: fc.constant('Identifier' as const),
|
|
31
|
+
name: arbitraryZigIdentifier,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const arbitraryIntegerLiteral: fc.Arbitrary<ZigExpression> = fc.record({
|
|
35
|
+
type: fc.constant('IntegerLiteral' as const),
|
|
36
|
+
value: fc.nat({ max: 999 }).map(n => String(n)),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const arbitraryStringLiteral: fc.Arbitrary<ZigExpression> = fc.record({
|
|
40
|
+
type: fc.constant('StringLiteral' as const),
|
|
41
|
+
value: fc.oneof(
|
|
42
|
+
fc.stringMatching(/^[a-zA-Z0-9 ]*$/),
|
|
43
|
+
fc.constantFrom('hello\nworld', 'tab\there', 'back\\slash', 'quote\ttab\nnewline'),
|
|
44
|
+
),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const arbitraryCharLiteral: fc.Arbitrary<ZigExpression> = fc.record({
|
|
48
|
+
type: fc.constant('CharLiteral' as const),
|
|
49
|
+
value: fc.stringMatching(/^[a-zA-Z0-9]$/),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const arbitraryEnumLiteral: fc.Arbitrary<ZigExpression> = fc.record({
|
|
53
|
+
type: fc.constant('EnumLiteral' as const),
|
|
54
|
+
name: arbitraryZigIdentifier,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const arbitraryBoolLiteral: fc.Arbitrary<ZigExpression> = fc.record({
|
|
58
|
+
type: fc.constant('BoolLiteral' as const),
|
|
59
|
+
value: fc.boolean(),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const arbitraryNullLiteral: fc.Arbitrary<ZigExpression> = fc.constant({
|
|
63
|
+
type: 'NullLiteral' as const,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const arbitraryUndefinedLiteral: fc.Arbitrary<ZigExpression> = fc.constant({
|
|
67
|
+
type: 'UndefinedLiteral' as const,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const arbitraryLeafExpression: fc.Arbitrary<ZigExpression> = fc.oneof(
|
|
71
|
+
{ weight: 3, arbitrary: arbitraryIdentifier },
|
|
72
|
+
{ weight: 2, arbitrary: arbitraryIntegerLiteral },
|
|
73
|
+
{ weight: 1, arbitrary: arbitraryStringLiteral },
|
|
74
|
+
{ weight: 1, arbitrary: arbitraryCharLiteral },
|
|
75
|
+
{ weight: 1, arbitrary: arbitraryEnumLiteral },
|
|
76
|
+
{ weight: 1, arbitrary: arbitraryBoolLiteral },
|
|
77
|
+
{ weight: 1, arbitrary: arbitraryNullLiteral },
|
|
78
|
+
{ weight: 1, arbitrary: arbitraryUndefinedLiteral },
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// Type expressions (simple ones for use in declarations)
|
|
82
|
+
|
|
83
|
+
const arbitrarySimpleTypeExpression: fc.Arbitrary<ZigTypeExpression> = arbitraryIdentifier as fc.Arbitrary<ZigTypeExpression>;
|
|
84
|
+
|
|
85
|
+
const arbitraryOptionalType: fc.Arbitrary<ZigTypeExpression> = fc.record({
|
|
86
|
+
type: fc.constant('OptionalType' as const),
|
|
87
|
+
child: arbitrarySimpleTypeExpression,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const arbitraryPointerType: fc.Arbitrary<ZigTypeExpression> = fc.record({
|
|
91
|
+
type: fc.constant('PointerType' as const),
|
|
92
|
+
size: fc.oneof(
|
|
93
|
+
fc.constant('one' as const),
|
|
94
|
+
fc.constant('many' as const),
|
|
95
|
+
fc.constant('slice' as const),
|
|
96
|
+
),
|
|
97
|
+
isConst: fc.boolean(),
|
|
98
|
+
child: arbitrarySimpleTypeExpression,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const arbitraryErrorUnionType: fc.Arbitrary<ZigTypeExpression> = fc.record({
|
|
102
|
+
type: fc.constant('ErrorUnionType' as const),
|
|
103
|
+
error: arbitrarySimpleTypeExpression,
|
|
104
|
+
payload: arbitrarySimpleTypeExpression,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const arbitraryTypeExpression: fc.Arbitrary<ZigTypeExpression> = fc.oneof(
|
|
108
|
+
{ weight: 4, arbitrary: arbitrarySimpleTypeExpression },
|
|
109
|
+
{ weight: 1, arbitrary: arbitraryOptionalType },
|
|
110
|
+
{ weight: 1, arbitrary: arbitraryPointerType },
|
|
111
|
+
{ weight: 1, arbitrary: arbitraryErrorUnionType },
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// Compound expressions (use leaf operands to avoid precedence issues)
|
|
115
|
+
|
|
116
|
+
const arbitraryBuiltinCallExpr: fc.Arbitrary<ZigExpression> = fc.record({
|
|
117
|
+
type: fc.constant('BuiltinCallExpr' as const),
|
|
118
|
+
name: arbitraryZigIdentifier,
|
|
119
|
+
args: fc.array(arbitraryLeafExpression, { maxLength: 2 }),
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const arbitraryFieldAccessExpr: fc.Arbitrary<ZigExpression> = fc.record({
|
|
123
|
+
type: fc.constant('FieldAccessExpr' as const),
|
|
124
|
+
operand: arbitraryIdentifier,
|
|
125
|
+
member: arbitraryZigIdentifier,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const arbitraryCallExpr: fc.Arbitrary<ZigExpression> = fc.record({
|
|
129
|
+
type: fc.constant('CallExpr' as const),
|
|
130
|
+
callee: arbitraryIdentifier,
|
|
131
|
+
args: fc.array(arbitraryLeafExpression, { maxLength: 2 }),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const arbitraryIndexExpr: fc.Arbitrary<ZigExpression> = fc.record({
|
|
135
|
+
type: fc.constant('IndexExpr' as const),
|
|
136
|
+
operand: arbitraryIdentifier,
|
|
137
|
+
index: arbitraryLeafExpression,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const arbitraryGroupedExpr: fc.Arbitrary<ZigExpression> = fc.record({
|
|
141
|
+
type: fc.constant('GroupedExpr' as const),
|
|
142
|
+
inner: arbitraryLeafExpression,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const arbitraryErrorSetExpr: fc.Arbitrary<ZigExpression> = fc.record({
|
|
146
|
+
type: fc.constant('ErrorSetExpr' as const),
|
|
147
|
+
names: fc.array(arbitraryZigIdentifier, { minLength: 1, maxLength: 3 }),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const arbitraryStructInitExpr: fc.Arbitrary<ZigExpression> = fc.record({
|
|
151
|
+
type: fc.constant('StructInitExpr' as const),
|
|
152
|
+
fields: fc.array(
|
|
153
|
+
fc.record({
|
|
154
|
+
type: fc.constant('StructInitField' as const),
|
|
155
|
+
name: arbitraryZigIdentifier,
|
|
156
|
+
value: arbitraryLeafExpression,
|
|
157
|
+
}),
|
|
158
|
+
{ maxLength: 3 },
|
|
159
|
+
),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const arbitraryArrayInitExpr: fc.Arbitrary<ZigExpression> = fc.record({
|
|
163
|
+
type: fc.constant('ArrayInitExpr' as const),
|
|
164
|
+
elements: fc.array(arbitraryLeafExpression, { maxLength: 3 }),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const arbitraryExpression: fc.Arbitrary<ZigExpression> = fc.oneof(
|
|
168
|
+
{ weight: 5, arbitrary: arbitraryLeafExpression },
|
|
169
|
+
{ weight: 1, arbitrary: arbitraryBuiltinCallExpr },
|
|
170
|
+
{ weight: 1, arbitrary: arbitraryFieldAccessExpr },
|
|
171
|
+
{ weight: 1, arbitrary: arbitraryCallExpr },
|
|
172
|
+
{ weight: 1, arbitrary: arbitraryIndexExpr },
|
|
173
|
+
{ weight: 1, arbitrary: arbitraryGroupedExpr },
|
|
174
|
+
{ weight: 1, arbitrary: arbitraryErrorSetExpr },
|
|
175
|
+
{ weight: 1, arbitrary: arbitraryStructInitExpr },
|
|
176
|
+
{ weight: 1, arbitrary: arbitraryArrayInitExpr },
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// Expressions safe to use in statement positions (don't start with keywords,
|
|
180
|
+
// which would cause the parser's while/for/block label detector to throw
|
|
181
|
+
// a non-recoverable error from zigIdentifierParser).
|
|
182
|
+
const arbitraryNonKeywordLeafExpression: fc.Arbitrary<ZigExpression> = fc.oneof(
|
|
183
|
+
{ weight: 3, arbitrary: arbitraryIdentifier },
|
|
184
|
+
{ weight: 2, arbitrary: arbitraryIntegerLiteral },
|
|
185
|
+
{ weight: 1, arbitrary: arbitraryStringLiteral },
|
|
186
|
+
{ weight: 1, arbitrary: arbitraryCharLiteral },
|
|
187
|
+
{ weight: 1, arbitrary: arbitraryEnumLiteral },
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
const arbitraryStatementSafeExpression: fc.Arbitrary<ZigExpression> = fc.oneof(
|
|
191
|
+
{ weight: 5, arbitrary: arbitraryNonKeywordLeafExpression },
|
|
192
|
+
{ weight: 1, arbitrary: arbitraryBuiltinCallExpr },
|
|
193
|
+
{ weight: 1, arbitrary: arbitraryFieldAccessExpr },
|
|
194
|
+
{ weight: 1, arbitrary: arbitraryCallExpr },
|
|
195
|
+
{ weight: 1, arbitrary: arbitraryIndexExpr },
|
|
196
|
+
{ weight: 1, arbitrary: arbitraryGroupedExpr },
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
// Statements
|
|
200
|
+
|
|
201
|
+
// Expression statements are bare expressions (no wrapper)
|
|
202
|
+
const arbitraryExprStmt: fc.Arbitrary<ZigStatement> = arbitraryStatementSafeExpression as fc.Arbitrary<ZigStatement>;
|
|
203
|
+
|
|
204
|
+
const arbitraryReturnStmt: fc.Arbitrary<ZigStatement> = fc.oneof(
|
|
205
|
+
fc.constant({ type: 'ReturnStmt' as const }),
|
|
206
|
+
fc.record({
|
|
207
|
+
type: fc.constant('ReturnStmt' as const),
|
|
208
|
+
value: arbitraryLeafExpression,
|
|
209
|
+
}),
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const arbitraryBreakStmt: fc.Arbitrary<ZigStatement> = fc.constant({
|
|
213
|
+
type: 'BreakStmt' as const,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const arbitraryContinueStmt: fc.Arbitrary<ZigStatement> = fc.constant({
|
|
217
|
+
type: 'ContinueStmt' as const,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const arbitraryVarDeclStmt: fc.Arbitrary<ZigStatement> = fc.record({
|
|
221
|
+
type: fc.constant('VarDecl' as const),
|
|
222
|
+
isConst: fc.boolean(),
|
|
223
|
+
isPub: fc.constant(false),
|
|
224
|
+
isExtern: fc.constant(false),
|
|
225
|
+
isComptime: fc.constant(false),
|
|
226
|
+
isThreadlocal: fc.constant(false),
|
|
227
|
+
name: arbitraryZigIdentifier,
|
|
228
|
+
}).chain(base =>
|
|
229
|
+
fc.oneof(
|
|
230
|
+
// With type and init
|
|
231
|
+
fc.record({
|
|
232
|
+
typeExpr: arbitraryTypeExpression,
|
|
233
|
+
initExpr: arbitraryLeafExpression,
|
|
234
|
+
}).map(extra => ({ ...base, ...extra })),
|
|
235
|
+
// With init only
|
|
236
|
+
fc.record({
|
|
237
|
+
initExpr: arbitraryLeafExpression,
|
|
238
|
+
}).map(extra => ({ ...base, ...extra })),
|
|
239
|
+
// With type only (extern style)
|
|
240
|
+
fc.record({
|
|
241
|
+
typeExpr: arbitraryTypeExpression,
|
|
242
|
+
}).map(extra => ({ ...base, isExtern: true, ...extra })),
|
|
243
|
+
),
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
const arbitraryAssignStmt: fc.Arbitrary<ZigStatement> = fc.record({
|
|
247
|
+
type: fc.constant('AssignStmt' as const),
|
|
248
|
+
target: arbitraryIdentifier as fc.Arbitrary<ZigExpression>,
|
|
249
|
+
operator: fc.oneof(
|
|
250
|
+
fc.constant('=' as const),
|
|
251
|
+
fc.constant('+=' as const),
|
|
252
|
+
fc.constant('-=' as const),
|
|
253
|
+
fc.constant('*=' as const),
|
|
254
|
+
),
|
|
255
|
+
value: arbitraryLeafExpression,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const arbitraryBlockStmt: fc.Arbitrary<ZigStatement> = fc.record({
|
|
259
|
+
type: fc.constant('BlockExpr' as const),
|
|
260
|
+
statements: fc.constant([] as ZigStatement[]),
|
|
261
|
+
}) as fc.Arbitrary<ZigStatement>;
|
|
262
|
+
|
|
263
|
+
const arbitraryDeferStmt: fc.Arbitrary<ZigStatement> = fc.record({
|
|
264
|
+
type: fc.constant('DeferStmt' as const),
|
|
265
|
+
isErrdefer: fc.boolean(),
|
|
266
|
+
body: arbitraryStatementSafeExpression as fc.Arbitrary<ZigStatement>,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const arbitraryStatement: fc.Arbitrary<ZigStatement> = fc.oneof(
|
|
270
|
+
{ weight: 2, arbitrary: arbitraryExprStmt },
|
|
271
|
+
{ weight: 2, arbitrary: arbitraryVarDeclStmt },
|
|
272
|
+
{ weight: 2, arbitrary: arbitraryReturnStmt },
|
|
273
|
+
{ weight: 1, arbitrary: arbitraryAssignStmt },
|
|
274
|
+
{ weight: 1, arbitrary: arbitraryBreakStmt },
|
|
275
|
+
{ weight: 1, arbitrary: arbitraryContinueStmt },
|
|
276
|
+
{ weight: 1, arbitrary: arbitraryBlockStmt },
|
|
277
|
+
{ weight: 1, arbitrary: arbitraryDeferStmt },
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
// Function parameters
|
|
281
|
+
|
|
282
|
+
const arbitraryFnParam: fc.Arbitrary<ZigFnParam> = fc.oneof(
|
|
283
|
+
// Named parameter
|
|
284
|
+
fc.record({
|
|
285
|
+
type: fc.constant('FnParam' as const),
|
|
286
|
+
name: arbitraryZigIdentifier,
|
|
287
|
+
isComptime: fc.constant(false),
|
|
288
|
+
isNoalias: fc.constant(false),
|
|
289
|
+
typeExpr: arbitraryTypeExpression,
|
|
290
|
+
}),
|
|
291
|
+
// Unnamed parameter
|
|
292
|
+
fc.record({
|
|
293
|
+
type: fc.constant('FnParam' as const),
|
|
294
|
+
isComptime: fc.constant(false),
|
|
295
|
+
isNoalias: fc.constant(false),
|
|
296
|
+
typeExpr: arbitraryTypeExpression,
|
|
297
|
+
}),
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
// Block expression
|
|
301
|
+
|
|
302
|
+
const arbitraryBlockExpr: fc.Arbitrary<ZigBlockExpr> = fc.record({
|
|
303
|
+
type: fc.constant('BlockExpr' as const),
|
|
304
|
+
statements: fc.array(arbitraryStatement, { maxLength: 3 }),
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// Top-level declarations
|
|
308
|
+
|
|
309
|
+
const arbitraryFnDecl: fc.Arbitrary<ZigContainerMember> = fc.oneof(
|
|
310
|
+
// Function with body
|
|
311
|
+
fc.record({
|
|
312
|
+
type: fc.constant('FnDecl' as const),
|
|
313
|
+
isPub: fc.boolean(),
|
|
314
|
+
isExtern: fc.constant(false),
|
|
315
|
+
isExport: fc.constant(false),
|
|
316
|
+
isInline: fc.constant(false),
|
|
317
|
+
isComptime: fc.constant(false),
|
|
318
|
+
name: arbitraryZigIdentifier,
|
|
319
|
+
params: fc.array(arbitraryFnParam, { maxLength: 2 }),
|
|
320
|
+
returnType: arbitraryTypeExpression,
|
|
321
|
+
body: arbitraryBlockExpr,
|
|
322
|
+
}),
|
|
323
|
+
// Extern function (no body)
|
|
324
|
+
fc.record({
|
|
325
|
+
type: fc.constant('FnDecl' as const),
|
|
326
|
+
isPub: fc.boolean(),
|
|
327
|
+
isExtern: fc.constant(true),
|
|
328
|
+
isExport: fc.constant(false),
|
|
329
|
+
isInline: fc.constant(false),
|
|
330
|
+
isComptime: fc.constant(false),
|
|
331
|
+
name: arbitraryZigIdentifier,
|
|
332
|
+
params: fc.array(arbitraryFnParam, { maxLength: 2 }),
|
|
333
|
+
returnType: arbitraryTypeExpression,
|
|
334
|
+
}),
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
const arbitraryVarDecl: fc.Arbitrary<ZigContainerMember> = fc.record({
|
|
338
|
+
type: fc.constant('VarDecl' as const),
|
|
339
|
+
isConst: fc.boolean(),
|
|
340
|
+
isPub: fc.boolean(),
|
|
341
|
+
isExtern: fc.constant(false),
|
|
342
|
+
isComptime: fc.constant(false),
|
|
343
|
+
isThreadlocal: fc.constant(false),
|
|
344
|
+
name: arbitraryZigIdentifier,
|
|
345
|
+
}).chain(base =>
|
|
346
|
+
fc.oneof(
|
|
347
|
+
// With type and init
|
|
348
|
+
fc.record({
|
|
349
|
+
typeExpr: arbitraryTypeExpression,
|
|
350
|
+
initExpr: arbitraryLeafExpression,
|
|
351
|
+
}).map(extra => ({ ...base, ...extra })),
|
|
352
|
+
// With init only
|
|
353
|
+
fc.record({
|
|
354
|
+
initExpr: arbitraryLeafExpression,
|
|
355
|
+
}).map(extra => ({ ...base, ...extra })),
|
|
356
|
+
),
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
const arbitraryTestDecl: fc.Arbitrary<ZigContainerMember> = fc.oneof(
|
|
360
|
+
fc.record({
|
|
361
|
+
type: fc.constant('TestDecl' as const),
|
|
362
|
+
name: fc.stringMatching(/^[a-zA-Z0-9 ]+$/),
|
|
363
|
+
body: arbitraryBlockExpr,
|
|
364
|
+
}),
|
|
365
|
+
fc.record({
|
|
366
|
+
type: fc.constant('TestDecl' as const),
|
|
367
|
+
body: arbitraryBlockExpr,
|
|
368
|
+
}),
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
const arbitraryContainerMember: fc.Arbitrary<ZigContainerMember> = fc.oneof(
|
|
372
|
+
{ weight: 3, arbitrary: arbitraryFnDecl },
|
|
373
|
+
{ weight: 3, arbitrary: arbitraryVarDecl },
|
|
374
|
+
{ weight: 1, arbitrary: arbitraryTestDecl },
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
export const arbitraryZigRoot: fc.Arbitrary<ZigRoot> = fc.record({
|
|
378
|
+
type: fc.constant('Root' as const),
|
|
379
|
+
members: fc.array(arbitraryContainerMember, { minLength: 1, maxLength: 4 }),
|
|
380
|
+
});
|
package/src/arrayParser.ts
CHANGED
|
@@ -8,7 +8,7 @@ export const createArrayParser = <ElementOutput, Sequence>(
|
|
|
8
8
|
const elements: ElementOutput[] = [];
|
|
9
9
|
|
|
10
10
|
while (true) {
|
|
11
|
-
|
|
11
|
+
using elementParserContext = parserContext.lookahead();
|
|
12
12
|
const initialPosition = elementParserContext.position;
|
|
13
13
|
try {
|
|
14
14
|
const element = await elementParser(elementParserContext);
|
|
@@ -24,8 +24,6 @@ export const createArrayParser = <ElementOutput, Sequence>(
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
throw error;
|
|
27
|
-
} finally {
|
|
28
|
-
elementParserContext.dispose();
|
|
29
27
|
}
|
|
30
28
|
}
|
|
31
29
|
};
|
package/src/backsmali.ts
CHANGED
|
@@ -7,19 +7,22 @@ import { smaliClass } from './smali.js';
|
|
|
7
7
|
export async function baksmaliClass(
|
|
8
8
|
dexStream: Uint8Array | AsyncIterable<Uint8Array>,
|
|
9
9
|
smaliFilePath: string,
|
|
10
|
+
dexEntry?: string,
|
|
10
11
|
): Promise<string> {
|
|
11
12
|
const inputFilePath = temporaryFile();
|
|
12
13
|
const outputDirectoryPath = temporaryDirectory();
|
|
13
14
|
|
|
14
15
|
await fs.writeFile(inputFilePath, dexStream);
|
|
15
16
|
|
|
17
|
+
const inputPath = dexEntry ? `${inputFilePath}/${dexEntry}` : inputFilePath;
|
|
18
|
+
|
|
16
19
|
await execa('baksmali', [
|
|
17
20
|
'disassemble',
|
|
18
21
|
'--classes',
|
|
19
22
|
'L' + smaliFilePath + ';',
|
|
20
23
|
'--output',
|
|
21
24
|
outputDirectoryPath,
|
|
22
|
-
|
|
25
|
+
inputPath,
|
|
23
26
|
]);
|
|
24
27
|
|
|
25
28
|
await fs.unlink(inputFilePath);
|
|
@@ -38,20 +41,23 @@ export async function baksmaliClass(
|
|
|
38
41
|
export async function backsmaliSmaliIsolateClass(
|
|
39
42
|
dexStream: Uint8Array | AsyncIterable<Uint8Array>,
|
|
40
43
|
smaliFilePath: string,
|
|
44
|
+
dexEntry?: string,
|
|
41
45
|
): Promise<Uint8Array> {
|
|
42
|
-
const smali = await baksmaliClass(dexStream, smaliFilePath);
|
|
46
|
+
const smali = await baksmaliClass(dexStream, smaliFilePath, dexEntry);
|
|
43
47
|
return smaliClass(smali);
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
export async function baksmaliListClasses(dexStream: Uint8Array | AsyncIterable<Uint8Array
|
|
50
|
+
export async function baksmaliListClasses(dexStream: Uint8Array | AsyncIterable<Uint8Array>, dexEntry?: string): Promise<string[]> {
|
|
47
51
|
const inputFilePath = temporaryFile();
|
|
48
52
|
|
|
49
53
|
await fs.writeFile(inputFilePath, dexStream);
|
|
50
54
|
|
|
55
|
+
const inputPath = dexEntry ? `${inputFilePath}/${dexEntry}` : inputFilePath;
|
|
56
|
+
|
|
51
57
|
const result = await execa('baksmali', [
|
|
52
58
|
'list',
|
|
53
59
|
'classes',
|
|
54
|
-
|
|
60
|
+
inputPath,
|
|
55
61
|
]);
|
|
56
62
|
|
|
57
63
|
await fs.unlink(inputFilePath);
|
|
@@ -72,3 +78,28 @@ export async function baksmaliListClasses(dexStream: Uint8Array | AsyncIterable<
|
|
|
72
78
|
|
|
73
79
|
return classes;
|
|
74
80
|
}
|
|
81
|
+
|
|
82
|
+
export async function baksmaliListDexFiles(apkStream: Uint8Array | AsyncIterable<Uint8Array>): Promise<string[]> {
|
|
83
|
+
const inputFilePath = temporaryFile();
|
|
84
|
+
|
|
85
|
+
await fs.writeFile(inputFilePath, apkStream);
|
|
86
|
+
|
|
87
|
+
const result = await execa('baksmali', [
|
|
88
|
+
'list',
|
|
89
|
+
'dex',
|
|
90
|
+
inputFilePath,
|
|
91
|
+
]);
|
|
92
|
+
|
|
93
|
+
await fs.unlink(inputFilePath);
|
|
94
|
+
|
|
95
|
+
if (result.stderr) {
|
|
96
|
+
throw new Error(`baksmali error: ${result.stderr}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const dexFiles = result.stdout
|
|
100
|
+
.split('\n')
|
|
101
|
+
.filter(line => line.trim())
|
|
102
|
+
.map(line => line.trim());
|
|
103
|
+
|
|
104
|
+
return dexFiles;
|
|
105
|
+
}
|
package/src/bash.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Word: a single argument/token (may contain expansions)
|
|
2
|
+
export type BashWord = {
|
|
3
|
+
parts: BashWordPart[];
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type BashWordPart =
|
|
7
|
+
| BashWordPartLiteral
|
|
8
|
+
| BashWordPartSingleQuoted
|
|
9
|
+
| BashWordPartDoubleQuoted
|
|
10
|
+
| BashWordPartVariable
|
|
11
|
+
| BashWordPartVariableBraced
|
|
12
|
+
| BashWordPartCommandSubstitution
|
|
13
|
+
| BashWordPartBacktickSubstitution
|
|
14
|
+
| BashWordPartArithmeticExpansion
|
|
15
|
+
| BashWordPartProcessSubstitution;
|
|
16
|
+
|
|
17
|
+
export type BashWordPartLiteral = {
|
|
18
|
+
type: 'literal';
|
|
19
|
+
value: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type BashWordPartSingleQuoted = {
|
|
23
|
+
type: 'singleQuoted';
|
|
24
|
+
value: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type BashWordPartDoubleQuoted = {
|
|
28
|
+
type: 'doubleQuoted';
|
|
29
|
+
parts: BashWordPart[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type BashWordPartVariable = {
|
|
33
|
+
type: 'variable';
|
|
34
|
+
name: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type BashWordPartVariableBraced = {
|
|
38
|
+
type: 'variableBraced';
|
|
39
|
+
name: string;
|
|
40
|
+
operator?: string;
|
|
41
|
+
operand?: BashWord;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type BashWordPartCommandSubstitution = {
|
|
45
|
+
type: 'commandSubstitution';
|
|
46
|
+
command: BashCommand;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type BashWordPartBacktickSubstitution = {
|
|
50
|
+
type: 'backtickSubstitution';
|
|
51
|
+
command: BashCommand;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type BashWordPartArithmeticExpansion = {
|
|
55
|
+
type: 'arithmeticExpansion';
|
|
56
|
+
expression: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type BashWordPartProcessSubstitution = {
|
|
60
|
+
type: 'processSubstitution';
|
|
61
|
+
direction: '<' | '>';
|
|
62
|
+
command: BashCommand;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Redirect: file descriptor operations
|
|
66
|
+
export type BashRedirect = {
|
|
67
|
+
fd?: number;
|
|
68
|
+
operator: '>' | '>>' | '<' | '<<' | '<<<' | '>&' | '<&' | '>|';
|
|
69
|
+
target: BashWord | BashHereDoc;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type BashHereDoc = {
|
|
73
|
+
type: 'hereDoc';
|
|
74
|
+
delimiter: string;
|
|
75
|
+
content: string;
|
|
76
|
+
quoted: boolean;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Assignment
|
|
80
|
+
export type BashAssignment = {
|
|
81
|
+
name: string;
|
|
82
|
+
value?: BashWord;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Simple command: name + args + redirects
|
|
86
|
+
export type BashSimpleCommand = {
|
|
87
|
+
type: 'simple';
|
|
88
|
+
name?: BashWord;
|
|
89
|
+
args: BashWord[];
|
|
90
|
+
redirects: BashRedirect[];
|
|
91
|
+
assignments: BashAssignment[];
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Compound commands (structural syntax only)
|
|
95
|
+
export type BashSubshell = {
|
|
96
|
+
type: 'subshell';
|
|
97
|
+
body: BashCommand;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export type BashBraceGroup = {
|
|
101
|
+
type: 'braceGroup';
|
|
102
|
+
body: BashCommand;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type BashCommandUnit = BashSimpleCommand | BashSubshell | BashBraceGroup;
|
|
106
|
+
|
|
107
|
+
// Pipeline: cmd1 | cmd2 | cmd3
|
|
108
|
+
export type BashPipeline = {
|
|
109
|
+
type: 'pipeline';
|
|
110
|
+
negated: boolean;
|
|
111
|
+
commands: BashCommandUnit[];
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export type BashCommandListSeparator = '&&' | '||' | ';' | '&' | '\n';
|
|
115
|
+
|
|
116
|
+
// Command list: pipelines connected by && || ; &
|
|
117
|
+
export type BashCommandList = {
|
|
118
|
+
type: 'list';
|
|
119
|
+
entries: {
|
|
120
|
+
pipeline: BashPipeline;
|
|
121
|
+
separator?: BashCommandListSeparator;
|
|
122
|
+
}[];
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Top-level
|
|
126
|
+
export type BashCommand = BashCommandList;
|
|
127
|
+
export type BashScript = BashCommand;
|