@futpib/parser 1.0.4 → 1.0.7
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 +414 -131
- package/build/bashParser.test.js +233 -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 +4 -2
- package/build/index.js +3 -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/predicateElementParser.d.ts +3 -0
- package/build/predicateElementParser.js +10 -0
- 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 +396 -0
- package/src/bashParser.ts +564 -199
- 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 +11 -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/predicateElementParser.ts +22 -0
- 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.test.ts
CHANGED
|
@@ -2,6 +2,7 @@ import test from 'ava';
|
|
|
2
2
|
import { runParser, runParserWithRemainingInput } from './parser.js';
|
|
3
3
|
import { stringParserInputCompanion } from './parserInputCompanion.js';
|
|
4
4
|
import { bashScriptParser, bashWordParser, bashSimpleCommandParser } from './bashParser.js';
|
|
5
|
+
import type { BashSimpleCommand, BashWordPartLiteral } from './bash.js';
|
|
5
6
|
|
|
6
7
|
test('simple command parser - single word', async t => {
|
|
7
8
|
const result = await runParser(
|
|
@@ -166,6 +167,79 @@ test('double quoted string with variable', async t => {
|
|
|
166
167
|
}
|
|
167
168
|
});
|
|
168
169
|
|
|
170
|
+
test('double quoted string with trailing dollar', async t => {
|
|
171
|
+
const result = await runParser(
|
|
172
|
+
bashScriptParser,
|
|
173
|
+
'echo "hello$"',
|
|
174
|
+
stringParserInputCompanion,
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
178
|
+
if (cmd.type === 'simple') {
|
|
179
|
+
t.deepEqual(cmd.args[0], {
|
|
180
|
+
parts: [{
|
|
181
|
+
type: 'doubleQuoted',
|
|
182
|
+
parts: [
|
|
183
|
+
{ type: 'literal', value: 'hello' },
|
|
184
|
+
{ type: 'literal', value: '$' },
|
|
185
|
+
],
|
|
186
|
+
}],
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('double quoted string with only dollar', async t => {
|
|
192
|
+
const result = await runParser(
|
|
193
|
+
bashScriptParser,
|
|
194
|
+
'echo "$"',
|
|
195
|
+
stringParserInputCompanion,
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
199
|
+
if (cmd.type === 'simple') {
|
|
200
|
+
t.deepEqual(cmd.args[0], {
|
|
201
|
+
parts: [{
|
|
202
|
+
type: 'doubleQuoted',
|
|
203
|
+
parts: [
|
|
204
|
+
{ type: 'literal', value: '$' },
|
|
205
|
+
],
|
|
206
|
+
}],
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test('grep with dollar anchor in double quotes', async t => {
|
|
212
|
+
const result = await runParser(
|
|
213
|
+
bashScriptParser,
|
|
214
|
+
'grep "\\.ts$"',
|
|
215
|
+
stringParserInputCompanion,
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
219
|
+
if (cmd.type === 'simple') {
|
|
220
|
+
t.deepEqual(cmd.args[0], {
|
|
221
|
+
parts: [{
|
|
222
|
+
type: 'doubleQuoted',
|
|
223
|
+
parts: [
|
|
224
|
+
{ type: 'literal', value: '\\' },
|
|
225
|
+
{ type: 'literal', value: '.ts' },
|
|
226
|
+
{ type: 'literal', value: '$' },
|
|
227
|
+
],
|
|
228
|
+
}],
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test('pipeline with dollar anchor in double quoted grep pattern', async t => {
|
|
234
|
+
const result = await runParser(
|
|
235
|
+
bashScriptParser,
|
|
236
|
+
'ls -la /home | grep "\\.ts$" | grep -v "\\.test\\.ts"',
|
|
237
|
+
stringParserInputCompanion,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
t.is(result.entries[0].pipeline.commands.length, 3);
|
|
241
|
+
});
|
|
242
|
+
|
|
169
243
|
test('simple variable', async t => {
|
|
170
244
|
const result = await runParser(
|
|
171
245
|
bashScriptParser,
|
|
@@ -318,6 +392,191 @@ test('[[ treated as command name', async t => {
|
|
|
318
392
|
}
|
|
319
393
|
});
|
|
320
394
|
|
|
395
|
+
// Braced variable expansion: ${VAR}
|
|
396
|
+
test('braced variable expansion', async t => {
|
|
397
|
+
const result = await runParser(
|
|
398
|
+
bashScriptParser,
|
|
399
|
+
'echo ${HOME}',
|
|
400
|
+
stringParserInputCompanion,
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
404
|
+
if (cmd.type === 'simple') {
|
|
405
|
+
t.is(cmd.args[0].parts[0].type, 'variableBraced');
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// Braced variable with default: ${VAR:-default}
|
|
410
|
+
test('braced variable with default value', async t => {
|
|
411
|
+
const result = await runParser(
|
|
412
|
+
bashScriptParser,
|
|
413
|
+
'echo ${VAR:-default}',
|
|
414
|
+
stringParserInputCompanion,
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
418
|
+
if (cmd.type === 'simple') {
|
|
419
|
+
t.is(cmd.args[0].parts[0].type, 'variableBraced');
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// Arithmetic expansion: $((1+2))
|
|
424
|
+
test('arithmetic expansion', async t => {
|
|
425
|
+
const result = await runParser(
|
|
426
|
+
bashScriptParser,
|
|
427
|
+
'echo $((1+2))',
|
|
428
|
+
stringParserInputCompanion,
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
432
|
+
if (cmd.type === 'simple') {
|
|
433
|
+
t.is(cmd.args[0].parts[0].type, 'arithmeticExpansion');
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// Bare $ at end of unquoted word
|
|
438
|
+
test('bare dollar at end of unquoted word', async t => {
|
|
439
|
+
const result = await runParser(
|
|
440
|
+
bashScriptParser,
|
|
441
|
+
'echo foo$',
|
|
442
|
+
stringParserInputCompanion,
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
446
|
+
if (cmd.type === 'simple') {
|
|
447
|
+
t.deepEqual(cmd.args[0], {
|
|
448
|
+
parts: [
|
|
449
|
+
{ type: 'literal', value: 'foo' },
|
|
450
|
+
{ type: 'literal', value: '$' },
|
|
451
|
+
],
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Bare $ as its own unquoted word
|
|
457
|
+
test('bare dollar as standalone unquoted word', async t => {
|
|
458
|
+
const result = await runParser(
|
|
459
|
+
bashScriptParser,
|
|
460
|
+
'echo $',
|
|
461
|
+
stringParserInputCompanion,
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
465
|
+
if (cmd.type === 'simple') {
|
|
466
|
+
t.deepEqual(cmd.args[0], {
|
|
467
|
+
parts: [
|
|
468
|
+
{ type: 'literal', value: '$' },
|
|
469
|
+
],
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
// Comment after command
|
|
475
|
+
test('comment after command', async t => {
|
|
476
|
+
const result = await runParser(
|
|
477
|
+
bashScriptParser,
|
|
478
|
+
'echo hello # this is a comment',
|
|
479
|
+
stringParserInputCompanion,
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
483
|
+
if (cmd.type === 'simple') {
|
|
484
|
+
t.is(cmd.args.length, 1);
|
|
485
|
+
t.deepEqual(cmd.args[0], {
|
|
486
|
+
parts: [{ type: 'literal', value: 'hello' }],
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// ANSI-C quoting: $'...'
|
|
492
|
+
test('ansi-c quoting', async t => {
|
|
493
|
+
const result = await runParser(
|
|
494
|
+
bashScriptParser,
|
|
495
|
+
"echo $'hello\\nworld'",
|
|
496
|
+
stringParserInputCompanion,
|
|
497
|
+
);
|
|
498
|
+
|
|
499
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
500
|
+
if (cmd.type === 'simple') {
|
|
501
|
+
t.is(cmd.args.length, 1);
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// Braced variable in double quotes: "${VAR}"
|
|
506
|
+
test('braced variable in double quotes', async t => {
|
|
507
|
+
const result = await runParser(
|
|
508
|
+
bashScriptParser,
|
|
509
|
+
'echo "${HOME}"',
|
|
510
|
+
stringParserInputCompanion,
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
514
|
+
if (cmd.type === 'simple') {
|
|
515
|
+
const dq = cmd.args[0].parts[0];
|
|
516
|
+
if (dq.type === 'doubleQuoted') {
|
|
517
|
+
t.is(dq.parts[0].type, 'variableBraced');
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
// Arithmetic expansion in double quotes
|
|
523
|
+
test('arithmetic expansion in double quotes', async t => {
|
|
524
|
+
const result = await runParser(
|
|
525
|
+
bashScriptParser,
|
|
526
|
+
'echo "$((1+2))"',
|
|
527
|
+
stringParserInputCompanion,
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
531
|
+
if (cmd.type === 'simple') {
|
|
532
|
+
const dq = cmd.args[0].parts[0];
|
|
533
|
+
if (dq.type === 'doubleQuoted') {
|
|
534
|
+
t.is(dq.parts[0].type, 'arithmeticExpansion');
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
// Process substitution: <(cmd)
|
|
540
|
+
test('process substitution input', async t => {
|
|
541
|
+
const result = await runParser(
|
|
542
|
+
bashScriptParser,
|
|
543
|
+
'diff <(sort file1) <(sort file2)',
|
|
544
|
+
stringParserInputCompanion,
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
t.truthy(result);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
// Line continuation (backslash-newline)
|
|
551
|
+
test('line continuation', async t => {
|
|
552
|
+
const result = await runParser(
|
|
553
|
+
bashScriptParser,
|
|
554
|
+
'echo hello \\\nworld',
|
|
555
|
+
stringParserInputCompanion,
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
559
|
+
if (cmd.type === 'simple') {
|
|
560
|
+
t.is(cmd.args.length, 2);
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
// Hash in middle of unquoted word is literal, not a comment
|
|
565
|
+
test('hash in middle of unquoted word', async t => {
|
|
566
|
+
const result = await runParser(
|
|
567
|
+
bashScriptParser,
|
|
568
|
+
'echo foo#bar',
|
|
569
|
+
stringParserInputCompanion,
|
|
570
|
+
);
|
|
571
|
+
|
|
572
|
+
const cmd = result.entries[0].pipeline.commands[0];
|
|
573
|
+
if (cmd.type === 'simple') {
|
|
574
|
+
t.deepEqual(cmd.args[0], {
|
|
575
|
+
parts: [{ type: 'literal', value: 'foo#bar' }],
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
|
|
321
580
|
test('if treated as command name', async t => {
|
|
322
581
|
const result = await runParser(
|
|
323
582
|
bashScriptParser,
|
|
@@ -330,3 +589,140 @@ test('if treated as command name', async t => {
|
|
|
330
589
|
t.deepEqual(cmd.name, { parts: [{ type: 'literal', value: 'if' }] });
|
|
331
590
|
}
|
|
332
591
|
});
|
|
592
|
+
|
|
593
|
+
test('find -exec with {} placeholder', async t => {
|
|
594
|
+
const result = await runParser(
|
|
595
|
+
bashScriptParser,
|
|
596
|
+
'find . -name "*.tmp" -exec rm {} \\;',
|
|
597
|
+
stringParserInputCompanion,
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
601
|
+
t.is(cmd.name!.parts[0].type, 'literal');
|
|
602
|
+
t.is((cmd.name!.parts[0] as BashWordPartLiteral).value, 'find');
|
|
603
|
+
// {} should be parsed as a literal word argument
|
|
604
|
+
const braceArg = cmd.args[5]; // ., -name, "*.tmp", -exec, rm, {}, \;
|
|
605
|
+
t.is(braceArg.parts[0].type, 'literal');
|
|
606
|
+
t.is((braceArg.parts[0] as BashWordPartLiteral).value, '{}');
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
test('lone open brace as argument', async t => {
|
|
610
|
+
const result = await runParser(
|
|
611
|
+
bashScriptParser,
|
|
612
|
+
'echo {',
|
|
613
|
+
stringParserInputCompanion,
|
|
614
|
+
);
|
|
615
|
+
|
|
616
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
617
|
+
t.deepEqual(cmd.args[0], {
|
|
618
|
+
parts: [{ type: 'literal', value: '{' }],
|
|
619
|
+
});
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
test('close brace mid-word', async t => {
|
|
623
|
+
const result = await runParser(
|
|
624
|
+
bashScriptParser,
|
|
625
|
+
'echo foo}bar',
|
|
626
|
+
stringParserInputCompanion,
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
630
|
+
t.is(cmd.args.length, 1);
|
|
631
|
+
t.is(cmd.args[0].parts[0].type, 'literal');
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
test('open brace mid-word', async t => {
|
|
635
|
+
const result = await runParser(
|
|
636
|
+
bashScriptParser,
|
|
637
|
+
'echo foo{bar',
|
|
638
|
+
stringParserInputCompanion,
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
642
|
+
t.is(cmd.args.length, 1);
|
|
643
|
+
t.is(cmd.args[0].parts[0].type, 'literal');
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
test('braces mid-word like brace expansion', async t => {
|
|
647
|
+
const result = await runParser(
|
|
648
|
+
bashScriptParser,
|
|
649
|
+
'echo file.{c,h}',
|
|
650
|
+
stringParserInputCompanion,
|
|
651
|
+
);
|
|
652
|
+
|
|
653
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
654
|
+
t.is(cmd.args.length, 1);
|
|
655
|
+
t.is(cmd.args[0].parts[0].type, 'literal');
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
test('find -exec with {.} placeholder variant', async t => {
|
|
659
|
+
const result = await runParser(
|
|
660
|
+
bashScriptParser,
|
|
661
|
+
'echo {.}',
|
|
662
|
+
stringParserInputCompanion,
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
666
|
+
t.is(cmd.args.length, 1);
|
|
667
|
+
t.is(cmd.args[0].parts[0].type, 'literal');
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
test('lone close brace as argument', async t => {
|
|
671
|
+
const result = await runParser(
|
|
672
|
+
bashScriptParser,
|
|
673
|
+
'echo }',
|
|
674
|
+
stringParserInputCompanion,
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
678
|
+
t.deepEqual(cmd.args[0], {
|
|
679
|
+
parts: [{ type: 'literal', value: '}' }],
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
test('close brace at start of word', async t => {
|
|
684
|
+
const result = await runParser(
|
|
685
|
+
bashScriptParser,
|
|
686
|
+
'echo }hello',
|
|
687
|
+
stringParserInputCompanion,
|
|
688
|
+
);
|
|
689
|
+
|
|
690
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
691
|
+
t.is(cmd.args.length, 1);
|
|
692
|
+
t.is(cmd.args[0].parts[0].type, 'literal');
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
test('multi-line script with blank lines', async t => {
|
|
696
|
+
const result = await runParser(
|
|
697
|
+
bashScriptParser,
|
|
698
|
+
'echo hello\n\necho world',
|
|
699
|
+
stringParserInputCompanion,
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
t.is(result.entries.length, 2);
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
test('mid-script comment', async t => {
|
|
706
|
+
const result = await runParser(
|
|
707
|
+
bashScriptParser,
|
|
708
|
+
'echo hello\n# comment\necho world',
|
|
709
|
+
stringParserInputCompanion,
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
t.is(result.entries.length, 2);
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
test('nested parentheses in arithmetic expansion', async t => {
|
|
716
|
+
const result = await runParser(
|
|
717
|
+
bashScriptParser,
|
|
718
|
+
'echo $((1 + (2 * 3)))',
|
|
719
|
+
stringParserInputCompanion,
|
|
720
|
+
);
|
|
721
|
+
|
|
722
|
+
const cmd = result.entries[0].pipeline.commands[0] as BashSimpleCommand;
|
|
723
|
+
const arith = cmd.args[0].parts[0];
|
|
724
|
+
t.is(arith.type, 'arithmeticExpansion');
|
|
725
|
+
if (arith.type === 'arithmeticExpansion') {
|
|
726
|
+
t.is(arith.expression, '1 + (2 * 3)');
|
|
727
|
+
}
|
|
728
|
+
});
|