@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,640 @@
|
|
|
1
|
+
import { escapeJavaString } from './stringEscapes.js';
|
|
2
|
+
import { type Unparser } from './unparser.js';
|
|
3
|
+
|
|
4
|
+
type JavaAstNode = {
|
|
5
|
+
type: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const binaryOperatorMap: Record<string, string> = {
|
|
10
|
+
PLUS: '+',
|
|
11
|
+
MINUS: '-',
|
|
12
|
+
MULTIPLY: '*',
|
|
13
|
+
DIVIDE: '/',
|
|
14
|
+
REMAINDER: '%',
|
|
15
|
+
LESS: '<',
|
|
16
|
+
GREATER: '>',
|
|
17
|
+
LESS_EQUALS: '<=',
|
|
18
|
+
GREATER_EQUALS: '>=',
|
|
19
|
+
EQUALS: '==',
|
|
20
|
+
NOT_EQUALS: '!=',
|
|
21
|
+
AND: '&&',
|
|
22
|
+
OR: '||',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const assignOperatorMap: Record<string, string> = {
|
|
26
|
+
ASSIGN: '=',
|
|
27
|
+
PLUS: '+=',
|
|
28
|
+
MINUS: '-=',
|
|
29
|
+
MULTIPLY: '*=',
|
|
30
|
+
DIVIDE: '/=',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const prefixUnaryOperatorMap: Record<string, string> = {
|
|
34
|
+
PREFIX_INCREMENT: '++',
|
|
35
|
+
PREFIX_DECREMENT: '--',
|
|
36
|
+
MINUS: '-',
|
|
37
|
+
PLUS: '+',
|
|
38
|
+
LOGICAL_COMPLEMENT: '!',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const postfixUnaryOperatorMap: Record<string, string> = {
|
|
42
|
+
POSTFIX_INCREMENT: '++',
|
|
43
|
+
POSTFIX_DECREMENT: '--',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const primitiveTypeMap: Record<string, string> = {
|
|
47
|
+
BOOLEAN: 'boolean',
|
|
48
|
+
BYTE: 'byte',
|
|
49
|
+
CHAR: 'char',
|
|
50
|
+
DOUBLE: 'double',
|
|
51
|
+
FLOAT: 'float',
|
|
52
|
+
INT: 'int',
|
|
53
|
+
LONG: 'long',
|
|
54
|
+
SHORT: 'short',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const modifierKeywordMap: Record<string, string> = {
|
|
58
|
+
PUBLIC: 'public',
|
|
59
|
+
PROTECTED: 'protected',
|
|
60
|
+
PRIVATE: 'private',
|
|
61
|
+
STATIC: 'static',
|
|
62
|
+
FINAL: 'final',
|
|
63
|
+
ABSTRACT: 'abstract',
|
|
64
|
+
SYNCHRONIZED: 'synchronized',
|
|
65
|
+
NATIVE: 'native',
|
|
66
|
+
TRANSIENT: 'transient',
|
|
67
|
+
VOLATILE: 'volatile',
|
|
68
|
+
STRICTFP: 'strictfp',
|
|
69
|
+
DEFAULT: 'default',
|
|
70
|
+
SEALED: 'sealed',
|
|
71
|
+
NON_SEALED: 'non-sealed',
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
function flattenName(name: JavaAstNode): string {
|
|
75
|
+
if (name.qualifier) {
|
|
76
|
+
return flattenName(name.qualifier as JavaAstNode) + '.' + (name.identifier as string);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return name.identifier as string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function unparseType(node: JavaAstNode): string {
|
|
83
|
+
switch (node.type) {
|
|
84
|
+
case 'PrimitiveType':
|
|
85
|
+
return primitiveTypeMap[node.type_ as string]!;
|
|
86
|
+
|
|
87
|
+
case 'VoidType':
|
|
88
|
+
return 'void';
|
|
89
|
+
|
|
90
|
+
case 'ClassOrInterfaceType': {
|
|
91
|
+
let result = '';
|
|
92
|
+
if (node.scope) {
|
|
93
|
+
result = unparseType(node.scope as JavaAstNode) + '.';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
result += (node.name as JavaAstNode).identifier as string;
|
|
97
|
+
if (node.typeArguments) {
|
|
98
|
+
const typeArgs = node.typeArguments as JavaAstNode[];
|
|
99
|
+
if (typeArgs.length === 0) {
|
|
100
|
+
// Diamond is handled at the ObjectCreationExpr level
|
|
101
|
+
} else {
|
|
102
|
+
result += '<' + typeArgs.map(t => unparseType(t)).join(', ') + '>';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
case 'ArrayType': {
|
|
110
|
+
// Unwind to base type + count brackets
|
|
111
|
+
let base = node;
|
|
112
|
+
let brackets = 0;
|
|
113
|
+
while (base.type === 'ArrayType') {
|
|
114
|
+
brackets++;
|
|
115
|
+
base = base.componentType as JavaAstNode;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return unparseType(base) + '[]'.repeat(brackets);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
case 'WildcardType': {
|
|
122
|
+
let result = '?';
|
|
123
|
+
if (node.extendedType) {
|
|
124
|
+
result += ' extends ' + unparseType(node.extendedType as JavaAstNode);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (node.superType) {
|
|
128
|
+
result += ' super ' + unparseType(node.superType as JavaAstNode);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
case 'UnknownType':
|
|
135
|
+
return '';
|
|
136
|
+
|
|
137
|
+
default:
|
|
138
|
+
throw new Error(`Unknown type: ${node.type}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function unparseExpression(node: JavaAstNode): string {
|
|
143
|
+
switch (node.type) {
|
|
144
|
+
case 'NameExpr':
|
|
145
|
+
return (node.name as JavaAstNode).identifier as string;
|
|
146
|
+
|
|
147
|
+
case 'StringLiteralExpr':
|
|
148
|
+
return `"${escapeJavaString(node.value as string)}"`;
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
case 'IntegerLiteralExpr':
|
|
152
|
+
return node.value as string;
|
|
153
|
+
|
|
154
|
+
case 'NullLiteralExpr':
|
|
155
|
+
return 'null';
|
|
156
|
+
|
|
157
|
+
case 'BooleanLiteralExpr':
|
|
158
|
+
return node.value ? 'true' : 'false';
|
|
159
|
+
|
|
160
|
+
case 'ThisExpr':
|
|
161
|
+
return 'this';
|
|
162
|
+
|
|
163
|
+
case 'FieldAccessExpr':
|
|
164
|
+
return unparseExpression(node.scope as JavaAstNode) + '.' + ((node.name as JavaAstNode).identifier as string);
|
|
165
|
+
|
|
166
|
+
case 'ArrayAccessExpr':
|
|
167
|
+
return unparseExpression(node.name as JavaAstNode) + '[' + unparseExpression(node.index as JavaAstNode) + ']';
|
|
168
|
+
|
|
169
|
+
case 'MethodCallExpr': {
|
|
170
|
+
let result = '';
|
|
171
|
+
if (node.scope) {
|
|
172
|
+
result = unparseExpression(node.scope as JavaAstNode) + '.';
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
result += (node.name as JavaAstNode).identifier as string;
|
|
176
|
+
result += '(' + (node.arguments as JavaAstNode[]).map(a => unparseExpression(a)).join(', ') + ')';
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
case 'ObjectCreationExpr': {
|
|
181
|
+
const type_ = node.type_ as JavaAstNode;
|
|
182
|
+
let result = 'new ' + unparseType(type_);
|
|
183
|
+
// Diamond operator
|
|
184
|
+
if (type_.typeArguments) {
|
|
185
|
+
const typeArgs = type_.typeArguments as JavaAstNode[];
|
|
186
|
+
if (typeArgs.length === 0) {
|
|
187
|
+
result += '<>';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
result += '(' + (node.arguments as JavaAstNode[]).map(a => unparseExpression(a)).join(', ') + ')';
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
case 'BinaryExpr':
|
|
196
|
+
return unparseExpression(node.left as JavaAstNode)
|
|
197
|
+
+ ' ' + binaryOperatorMap[node.operator as string]
|
|
198
|
+
+ ' ' + unparseExpression(node.right as JavaAstNode);
|
|
199
|
+
|
|
200
|
+
case 'UnaryExpr': {
|
|
201
|
+
const operator = node.operator as string;
|
|
202
|
+
if (prefixUnaryOperatorMap[operator]) {
|
|
203
|
+
return prefixUnaryOperatorMap[operator] + unparseExpression(node.expression as JavaAstNode);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (postfixUnaryOperatorMap[operator]) {
|
|
207
|
+
return unparseExpression(node.expression as JavaAstNode) + postfixUnaryOperatorMap[operator];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
throw new Error(`Unknown unary operator: ${operator}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
case 'AssignExpr':
|
|
214
|
+
return unparseExpression(node.target as JavaAstNode)
|
|
215
|
+
+ ' ' + assignOperatorMap[node.operator as string]
|
|
216
|
+
+ ' ' + unparseExpression(node.value as JavaAstNode);
|
|
217
|
+
|
|
218
|
+
case 'ConditionalExpr':
|
|
219
|
+
return unparseExpression(node.condition as JavaAstNode)
|
|
220
|
+
+ ' ? ' + unparseExpression(node.thenExpr as JavaAstNode)
|
|
221
|
+
+ ' : ' + unparseExpression(node.elseExpr as JavaAstNode);
|
|
222
|
+
|
|
223
|
+
case 'CastExpr':
|
|
224
|
+
return '(' + unparseType(node.type_ as JavaAstNode) + ') ' + unparseExpression(node.expression as JavaAstNode);
|
|
225
|
+
|
|
226
|
+
case 'EnclosedExpr':
|
|
227
|
+
return '(' + unparseExpression(node.inner as JavaAstNode) + ')';
|
|
228
|
+
|
|
229
|
+
case 'InstanceOfExpr':
|
|
230
|
+
return unparseExpression(node.expression as JavaAstNode)
|
|
231
|
+
+ ' instanceof ' + unparseType(node.type_ as JavaAstNode);
|
|
232
|
+
|
|
233
|
+
case 'LambdaExpr': {
|
|
234
|
+
const params = node.parameters as JavaAstNode[];
|
|
235
|
+
const isEnclosing = node.isEnclosingParameters as boolean;
|
|
236
|
+
const body = node.body as JavaAstNode;
|
|
237
|
+
|
|
238
|
+
let paramStr: string;
|
|
239
|
+
if (isEnclosing) {
|
|
240
|
+
const paramParts = params.map(p => {
|
|
241
|
+
const paramType = p.type_ as JavaAstNode;
|
|
242
|
+
const paramName = (p.name as JavaAstNode).identifier as string;
|
|
243
|
+
if (paramType.type === 'UnknownType') {
|
|
244
|
+
return paramName;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return unparseType(paramType) + ' ' + paramName;
|
|
248
|
+
});
|
|
249
|
+
paramStr = '(' + paramParts.join(', ') + ')';
|
|
250
|
+
} else {
|
|
251
|
+
paramStr = (params[0]!.name as JavaAstNode).identifier as string;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let bodyStr: string;
|
|
255
|
+
if (body.type === 'BlockStmt') {
|
|
256
|
+
bodyStr = unparseBlockStmt(body);
|
|
257
|
+
} else if (body.type === 'ExpressionStmt') {
|
|
258
|
+
bodyStr = unparseExpression(body.expression as JavaAstNode);
|
|
259
|
+
} else {
|
|
260
|
+
bodyStr = unparseExpression(body);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return paramStr + ' -> ' + bodyStr;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
case 'VariableDeclarationExpr':
|
|
267
|
+
return unparseVariableDeclarationExpr(node);
|
|
268
|
+
|
|
269
|
+
case 'MarkerAnnotationExpr':
|
|
270
|
+
return '@' + flattenName(node.name as JavaAstNode);
|
|
271
|
+
|
|
272
|
+
default:
|
|
273
|
+
throw new Error(`Unknown expression type: ${node.type}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function unparseVariableDeclarationExpr(node: JavaAstNode): string {
|
|
278
|
+
const modifiers = node.modifiers as JavaAstNode[];
|
|
279
|
+
const annotations = node.annotations as JavaAstNode[];
|
|
280
|
+
const variables = node.variables as JavaAstNode[];
|
|
281
|
+
|
|
282
|
+
let result = '';
|
|
283
|
+
for (const ann of annotations) {
|
|
284
|
+
result += unparseExpression(ann) + ' ';
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
for (const mod of modifiers) {
|
|
288
|
+
result += modifierKeywordMap[mod.keyword as string] + ' ';
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Type comes from first variable
|
|
292
|
+
const type_ = variables[0]!.type_ as JavaAstNode;
|
|
293
|
+
result += unparseType(type_);
|
|
294
|
+
|
|
295
|
+
const varParts = variables.map(v => {
|
|
296
|
+
let varStr = ' ' + ((v.name as JavaAstNode).identifier as string);
|
|
297
|
+
if (v.initializer) {
|
|
298
|
+
varStr += ' = ' + unparseExpression(v.initializer as JavaAstNode);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return varStr;
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
result += varParts.join(',');
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function unparseBlockStmt(node: JavaAstNode): string {
|
|
309
|
+
const statements = node.statements as JavaAstNode[];
|
|
310
|
+
if (statements.length === 0) {
|
|
311
|
+
return '{}';
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return '{ ' + statements.map(s => unparseStatement(s)).join(' ') + ' }';
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function unparseStatement(node: JavaAstNode): string {
|
|
318
|
+
switch (node.type) {
|
|
319
|
+
case 'BlockStmt':
|
|
320
|
+
return unparseBlockStmt(node);
|
|
321
|
+
|
|
322
|
+
case 'ExpressionStmt':
|
|
323
|
+
return unparseExpression(node.expression as JavaAstNode) + ';';
|
|
324
|
+
|
|
325
|
+
case 'ReturnStmt': {
|
|
326
|
+
if (node.expression) {
|
|
327
|
+
return 'return ' + unparseExpression(node.expression as JavaAstNode) + ';';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return 'return;';
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
case 'ThrowStmt':
|
|
334
|
+
return 'throw ' + unparseExpression(node.expression as JavaAstNode) + ';';
|
|
335
|
+
|
|
336
|
+
case 'IfStmt': {
|
|
337
|
+
let result = 'if (' + unparseExpression(node.condition as JavaAstNode) + ') '
|
|
338
|
+
+ unparseStatement(node.thenStmt as JavaAstNode);
|
|
339
|
+
if (node.elseStmt) {
|
|
340
|
+
result += ' else ' + unparseStatement(node.elseStmt as JavaAstNode);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return result;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
case 'ForStmt': {
|
|
347
|
+
const init = node.initialization as JavaAstNode[];
|
|
348
|
+
let initStr = '';
|
|
349
|
+
if (init.length > 0) {
|
|
350
|
+
initStr = init.map(i => unparseExpression(i)).join(', ');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
let compareStr = '';
|
|
354
|
+
if (node.compare) {
|
|
355
|
+
compareStr = unparseExpression(node.compare as JavaAstNode);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const update = node.update as JavaAstNode[];
|
|
359
|
+
const updateStr = update.map(u => unparseExpression(u)).join(', ');
|
|
360
|
+
|
|
361
|
+
return 'for (' + initStr + '; ' + compareStr + '; ' + updateStr + ') '
|
|
362
|
+
+ unparseStatement(node.body as JavaAstNode);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
case 'ForEachStmt':
|
|
366
|
+
return 'for (' + unparseVariableDeclarationExpr(node.variable as JavaAstNode) + ' : '
|
|
367
|
+
+ unparseExpression(node.iterable as JavaAstNode) + ') '
|
|
368
|
+
+ unparseStatement(node.body as JavaAstNode);
|
|
369
|
+
|
|
370
|
+
case 'TryStmt': {
|
|
371
|
+
const resources = node.resources as JavaAstNode[];
|
|
372
|
+
let result = 'try';
|
|
373
|
+
if (resources.length > 0) {
|
|
374
|
+
result += ' (' + resources.map(r => unparseVariableDeclarationExpr(r)).join('; ') + ')';
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
result += ' ' + unparseBlockStmt(node.tryBlock as JavaAstNode);
|
|
378
|
+
|
|
379
|
+
const catchClauses = node.catchClauses as JavaAstNode[];
|
|
380
|
+
for (const clause of catchClauses) {
|
|
381
|
+
const param = clause.parameter as JavaAstNode;
|
|
382
|
+
const paramType = param.type_ as JavaAstNode;
|
|
383
|
+
const paramName = (param.name as JavaAstNode).identifier as string;
|
|
384
|
+
result += ' catch (' + unparseType(paramType) + ' ' + paramName + ') '
|
|
385
|
+
+ unparseBlockStmt(clause.body as JavaAstNode);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (node.finallyBlock) {
|
|
389
|
+
result += ' finally ' + unparseBlockStmt(node.finallyBlock as JavaAstNode);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
case 'SwitchStmt': {
|
|
396
|
+
const entries = node.entries as JavaAstNode[];
|
|
397
|
+
let result = 'switch (' + unparseExpression(node.selector as JavaAstNode) + ') {';
|
|
398
|
+
for (const entry of entries) {
|
|
399
|
+
const isDefault = entry.isDefault as boolean;
|
|
400
|
+
const labels = entry.labels as JavaAstNode[];
|
|
401
|
+
const statements = entry.statements as JavaAstNode[];
|
|
402
|
+
|
|
403
|
+
if (isDefault) {
|
|
404
|
+
result += ' default:';
|
|
405
|
+
} else {
|
|
406
|
+
for (const label of labels) {
|
|
407
|
+
result += ' case ' + unparseExpression(label) + ':';
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
for (const stmt of statements) {
|
|
412
|
+
result += ' ' + unparseStatement(stmt);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
result += '}';
|
|
417
|
+
return result;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
case 'ExplicitConstructorInvocationStmt': {
|
|
421
|
+
const keyword = (node.isThis as boolean) ? 'this' : 'super';
|
|
422
|
+
return keyword + '(' + (node.arguments as JavaAstNode[]).map(a => unparseExpression(a)).join(', ') + ');';
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
default:
|
|
426
|
+
throw new Error(`Unknown statement type: ${node.type}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function unparseAnnotations(annotations: JavaAstNode[]): string {
|
|
431
|
+
if (annotations.length === 0) {
|
|
432
|
+
return '';
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return annotations.map(a => unparseExpression(a)).join(' ') + ' ';
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function unparseModifiers(modifiers: JavaAstNode[]): string {
|
|
439
|
+
if (modifiers.length === 0) {
|
|
440
|
+
return '';
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return modifiers.map(m => modifierKeywordMap[m.keyword as string]).join(' ') + ' ';
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function unparseParameter(param: JavaAstNode): string {
|
|
447
|
+
let result = '';
|
|
448
|
+
result += unparseAnnotations(param.annotations as JavaAstNode[]);
|
|
449
|
+
result += unparseModifiers(param.modifiers as JavaAstNode[]);
|
|
450
|
+
const typeStr = unparseType(param.type_ as JavaAstNode);
|
|
451
|
+
if (typeStr) {
|
|
452
|
+
result += typeStr;
|
|
453
|
+
if (param.isVarArgs) {
|
|
454
|
+
result += '...';
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
result += ' ';
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
result += (param.name as JavaAstNode).identifier as string;
|
|
461
|
+
return result;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function unparseBodyDeclaration(node: JavaAstNode): string {
|
|
465
|
+
switch (node.type) {
|
|
466
|
+
case 'FieldDeclaration': {
|
|
467
|
+
const variables = node.variables as JavaAstNode[];
|
|
468
|
+
let result = unparseAnnotations(node.annotations as JavaAstNode[]);
|
|
469
|
+
result += unparseModifiers(node.modifiers as JavaAstNode[]);
|
|
470
|
+
result += unparseType(variables[0]!.type_ as JavaAstNode);
|
|
471
|
+
const varParts = variables.map(v => {
|
|
472
|
+
let varStr = ' ' + ((v.name as JavaAstNode).identifier as string);
|
|
473
|
+
if (v.initializer) {
|
|
474
|
+
varStr += ' = ' + unparseExpression(v.initializer as JavaAstNode);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return varStr;
|
|
478
|
+
});
|
|
479
|
+
result += varParts.join(',') + ';';
|
|
480
|
+
return result;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
case 'MethodDeclaration': {
|
|
484
|
+
let result = unparseAnnotations(node.annotations as JavaAstNode[]);
|
|
485
|
+
result += unparseModifiers(node.modifiers as JavaAstNode[]);
|
|
486
|
+
|
|
487
|
+
const typeParams = node.typeParameters as JavaAstNode[];
|
|
488
|
+
if (typeParams.length > 0) {
|
|
489
|
+
result += '<' + typeParams.map(tp => {
|
|
490
|
+
let tpStr = ((tp.name as JavaAstNode).identifier as string);
|
|
491
|
+
const bounds = tp.typeBound as JavaAstNode[];
|
|
492
|
+
if (bounds.length > 0) {
|
|
493
|
+
tpStr += ' extends ' + bounds.map(b => unparseType(b)).join(' & ');
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return tpStr;
|
|
497
|
+
}).join(', ') + '> ';
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
result += unparseType(node.type_ as JavaAstNode) + ' ';
|
|
501
|
+
result += (node.name as JavaAstNode).identifier as string;
|
|
502
|
+
result += '(' + (node.parameters as JavaAstNode[]).map(p => unparseParameter(p)).join(', ') + ')';
|
|
503
|
+
|
|
504
|
+
const thrownExceptions = node.thrownExceptions as JavaAstNode[];
|
|
505
|
+
if (thrownExceptions.length > 0) {
|
|
506
|
+
result += ' throws ' + thrownExceptions.map(e => unparseType(e)).join(', ');
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (node.body) {
|
|
510
|
+
result += ' ' + unparseBlockStmt(node.body as JavaAstNode);
|
|
511
|
+
} else {
|
|
512
|
+
result += ';';
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return result;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
case 'ConstructorDeclaration': {
|
|
519
|
+
let result = unparseAnnotations(node.annotations as JavaAstNode[]);
|
|
520
|
+
result += unparseModifiers(node.modifiers as JavaAstNode[]);
|
|
521
|
+
result += (node.name as JavaAstNode).identifier as string;
|
|
522
|
+
result += '(' + (node.parameters as JavaAstNode[]).map(p => unparseParameter(p)).join(', ') + ')';
|
|
523
|
+
|
|
524
|
+
const thrownExceptions = node.thrownExceptions as JavaAstNode[];
|
|
525
|
+
if (thrownExceptions.length > 0) {
|
|
526
|
+
result += ' throws ' + thrownExceptions.map(e => unparseType(e)).join(', ');
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
result += ' ' + unparseBlockStmt(node.body as JavaAstNode);
|
|
530
|
+
return result;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
case 'ClassOrInterfaceDeclaration':
|
|
534
|
+
case 'EnumDeclaration':
|
|
535
|
+
return unparseTypeDeclaration(node);
|
|
536
|
+
|
|
537
|
+
default:
|
|
538
|
+
throw new Error(`Unknown body declaration type: ${node.type}`);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
function unparseTypeDeclaration(node: JavaAstNode): string {
|
|
543
|
+
switch (node.type) {
|
|
544
|
+
case 'ClassOrInterfaceDeclaration': {
|
|
545
|
+
let result = unparseAnnotations(node.annotations as JavaAstNode[]);
|
|
546
|
+
result += unparseModifiers(node.modifiers as JavaAstNode[]);
|
|
547
|
+
result += (node.isInterface ? 'interface' : 'class') + ' ';
|
|
548
|
+
result += (node.name as JavaAstNode).identifier as string;
|
|
549
|
+
|
|
550
|
+
const typeParams = node.typeParameters as JavaAstNode[];
|
|
551
|
+
if (typeParams.length > 0) {
|
|
552
|
+
result += '<' + typeParams.map(tp => {
|
|
553
|
+
let tpStr = ((tp.name as JavaAstNode).identifier as string);
|
|
554
|
+
const bounds = tp.typeBound as JavaAstNode[];
|
|
555
|
+
if (bounds.length > 0) {
|
|
556
|
+
tpStr += ' extends ' + bounds.map(b => unparseType(b)).join(' & ');
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return tpStr;
|
|
560
|
+
}).join(', ') + '>';
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const extendedTypes = node.extendedTypes as JavaAstNode[];
|
|
564
|
+
if (extendedTypes.length > 0) {
|
|
565
|
+
result += ' extends ' + extendedTypes.map(t => unparseType(t)).join(', ');
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const implementedTypes = node.implementedTypes as JavaAstNode[];
|
|
569
|
+
if (implementedTypes.length > 0) {
|
|
570
|
+
result += ' implements ' + implementedTypes.map(t => unparseType(t)).join(', ');
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const members = node.members as JavaAstNode[];
|
|
574
|
+
if (members.length === 0) {
|
|
575
|
+
result += ' {}';
|
|
576
|
+
} else {
|
|
577
|
+
result += ' { ' + members.map(m => unparseBodyDeclaration(m)).join('\n') + ' }';
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return result;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
case 'EnumDeclaration': {
|
|
584
|
+
let result = unparseAnnotations(node.annotations as JavaAstNode[]);
|
|
585
|
+
result += unparseModifiers(node.modifiers as JavaAstNode[]);
|
|
586
|
+
result += 'enum ';
|
|
587
|
+
result += (node.name as JavaAstNode).identifier as string;
|
|
588
|
+
result += ' {}';
|
|
589
|
+
return result;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
default:
|
|
593
|
+
throw new Error(`Unknown type declaration type: ${node.type}`);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
export const javaCompilationUnitUnparser: Unparser<unknown, string> = async function * (input) {
|
|
598
|
+
const cu = input as JavaAstNode;
|
|
599
|
+
|
|
600
|
+
let result = '';
|
|
601
|
+
|
|
602
|
+
// Package declaration
|
|
603
|
+
if (cu.packageDeclaration) {
|
|
604
|
+
const pkg = cu.packageDeclaration as JavaAstNode;
|
|
605
|
+
result += unparseAnnotations(pkg.annotations as JavaAstNode[]);
|
|
606
|
+
result += 'package ' + flattenName(pkg.name as JavaAstNode) + ';';
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// Imports
|
|
610
|
+
const imports = cu.imports as JavaAstNode[];
|
|
611
|
+
for (const imp of imports) {
|
|
612
|
+
if (result.length > 0) {
|
|
613
|
+
result += '\n';
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
result += 'import ';
|
|
617
|
+
if (imp.isStatic) {
|
|
618
|
+
result += 'static ';
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
result += flattenName(imp.name as JavaAstNode);
|
|
622
|
+
if (imp.isAsterisk) {
|
|
623
|
+
result += '.*';
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
result += ';';
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Types
|
|
630
|
+
const types = cu.types as JavaAstNode[];
|
|
631
|
+
for (const type of types) {
|
|
632
|
+
if (result.length > 0) {
|
|
633
|
+
result += '\n';
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
result += unparseTypeDeclaration(type);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
yield result;
|
|
640
|
+
};
|
package/src/jsonParser.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { createParserAccessorParser } from './parserAccessorParser.js';
|
|
|
14
14
|
import { createElementParser } from './elementParser.js';
|
|
15
15
|
import { parserCreatorCompose } from './parserCreatorCompose.js';
|
|
16
16
|
import { createSeparatedArrayParser } from './separatedArrayParser.js';
|
|
17
|
+
import { createRegExpParser } from './regexpParser.js';
|
|
17
18
|
|
|
18
19
|
const whitespaceParser: Parser<unknown, string> = createArrayParser(createUnionParser([
|
|
19
20
|
createExactSequenceParser(' '),
|
|
@@ -78,32 +79,10 @@ export const jsonStringParser: Parser<string, string> = promiseCompose(
|
|
|
78
79
|
([ , string ]) => string,
|
|
79
80
|
);
|
|
80
81
|
|
|
81
|
-
export const jsonNumberParser: Parser<number, string> =
|
|
82
|
-
()
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
parserContext.invariant(
|
|
86
|
-
(
|
|
87
|
-
character === '-'
|
|
88
|
-
|| (character >= '0' && character <= '9')
|
|
89
|
-
|| character === '.'
|
|
90
|
-
|| character === 'e'
|
|
91
|
-
|| character === 'E'
|
|
92
|
-
|| character === '+'
|
|
93
|
-
),
|
|
94
|
-
'Expected "-", "0" to "9", ".", "e", "E", "+", got "%s"',
|
|
95
|
-
character,
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
return character;
|
|
99
|
-
},
|
|
100
|
-
)()),
|
|
101
|
-
characters => async parserContext => {
|
|
102
|
-
parserContext.invariant(characters.length > 0, 'Expected at least one character');
|
|
103
|
-
|
|
104
|
-
return Number(characters.join(''));
|
|
105
|
-
},
|
|
106
|
-
)();
|
|
82
|
+
export const jsonNumberParser: Parser<number, string> = promiseCompose(
|
|
83
|
+
createRegExpParser(/-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/),
|
|
84
|
+
match => Number(match[0]),
|
|
85
|
+
);
|
|
107
86
|
|
|
108
87
|
const jsonTrueParser: Parser<true, string> = promiseCompose(createExactSequenceParser('true'), () => true);
|
|
109
88
|
|
|
@@ -145,7 +124,7 @@ const jsonObjectParser: Parser<JsonObject, string> = promiseCompose(
|
|
|
145
124
|
whitespaceParser,
|
|
146
125
|
promiseCompose(
|
|
147
126
|
createTerminatedArrayParser(
|
|
148
|
-
createDisjunctionParser
|
|
127
|
+
createDisjunctionParser([
|
|
149
128
|
promiseCompose(
|
|
150
129
|
createTupleParser([
|
|
151
130
|
createParserAccessorParser(() => jsonObjectEntryParser),
|
package/src/lookaheadParser.ts
CHANGED
|
@@ -4,13 +4,9 @@ export const createLookaheadParser = <Output, Sequence>(
|
|
|
4
4
|
childParser: Parser<Output, Sequence>,
|
|
5
5
|
): Parser<Output, Sequence> => {
|
|
6
6
|
const lookaheadParser: Parser<Output, Sequence> = async parserContext => {
|
|
7
|
-
|
|
7
|
+
using childParserContext = parserContext.lookahead();
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
return await childParser(childParserContext);
|
|
11
|
-
} finally {
|
|
12
|
-
childParserContext.dispose();
|
|
13
|
-
}
|
|
9
|
+
return childParser(childParserContext);
|
|
14
10
|
};
|
|
15
11
|
|
|
16
12
|
setParserName(lookaheadParser, `(?=${getParserName(childParser)})`);
|