@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.
Files changed (262) hide show
  1. package/.claude/settings.local.json +24 -0
  2. package/.github/workflows/main.yml +1 -0
  3. package/build/androidPackageParser.js +30 -32
  4. package/build/arbitraryDalvikBytecode.d.ts +3 -3
  5. package/build/arbitraryDalvikBytecode.js +33 -27
  6. package/build/arbitraryDalvikExecutable.js +55 -17
  7. package/build/arbitraryJava.d.ts +31 -0
  8. package/build/arbitraryJava.js +532 -0
  9. package/build/arbitraryJavaScript.d.ts +3 -0
  10. package/build/arbitraryJavaScript.js +263 -0
  11. package/build/arbitraryJavascript.d.ts +3 -0
  12. package/build/arbitraryJavascript.js +263 -0
  13. package/build/arbitraryZig.d.ts +3 -0
  14. package/build/arbitraryZig.js +240 -0
  15. package/build/arbitraryZipStream.d.ts +1 -1
  16. package/build/arrayParser.js +72 -13
  17. package/build/backsmali.d.ts +4 -3
  18. package/build/backsmali.js +26 -6
  19. package/build/bash.d.ts +89 -0
  20. package/build/bash.js +1 -0
  21. package/build/bashParser.d.ts +6 -0
  22. package/build/bashParser.js +335 -0
  23. package/build/bashParser.test.d.ts +1 -0
  24. package/build/bashParser.test.js +343 -0
  25. package/build/bashParserEdgeCases.test.d.ts +1 -0
  26. package/build/bashParserEdgeCases.test.js +117 -0
  27. package/build/dalvikBytecodeParser/addressConversion.d.ts +110 -0
  28. package/build/dalvikBytecodeParser/addressConversion.js +334 -0
  29. package/build/dalvikBytecodeParser/formatParsers.d.ts +7 -6
  30. package/build/dalvikBytecodeParser/formatParsers.js +13 -14
  31. package/build/dalvikBytecodeParser.d.ts +60 -31
  32. package/build/dalvikBytecodeParser.js +92 -35
  33. package/build/dalvikBytecodeParser.test-d.d.ts +1 -0
  34. package/build/dalvikBytecodeParser.test-d.js +268 -0
  35. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +9 -8
  36. package/build/dalvikBytecodeUnparser/formatUnparsers.js +13 -12
  37. package/build/dalvikBytecodeUnparser.d.ts +2 -2
  38. package/build/dalvikBytecodeUnparser.js +23 -23
  39. package/build/dalvikBytecodeUnparser.test.js +7 -7
  40. package/build/dalvikExecutable.d.ts +3 -3
  41. package/build/dalvikExecutable.test-d.d.ts +1 -0
  42. package/build/dalvikExecutable.test-d.js +59 -0
  43. package/build/dalvikExecutableParser/typedNumbers.d.ts +18 -0
  44. package/build/dalvikExecutableParser/typedNumbers.js +3 -0
  45. package/build/dalvikExecutableParser.d.ts +2 -1
  46. package/build/dalvikExecutableParser.js +96 -77
  47. package/build/dalvikExecutableParser.test.js +24 -3
  48. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +3 -0
  49. package/build/dalvikExecutableUnparser/poolScanners.d.ts +2 -2
  50. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +3 -3
  51. package/build/dalvikExecutableUnparser/sectionUnparsers.js +26 -11
  52. package/build/dalvikExecutableUnparser.d.ts +2 -2
  53. package/build/dalvikExecutableUnparser.test.js +2 -1
  54. package/build/disjunctionParser.d.ts +5 -3
  55. package/build/disjunctionParser.js +79 -17
  56. package/build/disjunctionParser.test-d.d.ts +1 -0
  57. package/build/disjunctionParser.test-d.js +72 -0
  58. package/build/elementSwitchParser.d.ts +4 -0
  59. package/build/{exactElementSwitchParser.js → elementSwitchParser.js} +3 -4
  60. package/build/elementSwitchParser.test-d.d.ts +1 -0
  61. package/build/elementSwitchParser.test-d.js +44 -0
  62. package/build/exactSequenceParser.d.ts +4 -2
  63. package/build/exactSequenceParser.test-d.d.ts +1 -0
  64. package/build/exactSequenceParser.test-d.js +36 -0
  65. package/build/fetchCid.js +2 -66
  66. package/build/index.d.ts +25 -2
  67. package/build/index.js +23 -1
  68. package/build/index.test.js +16 -1
  69. package/build/inputReader.d.ts +10 -0
  70. package/build/inputReader.js +36 -0
  71. package/build/java.d.ts +502 -0
  72. package/build/java.js +2 -0
  73. package/build/javaKeyStoreParser.js +14 -17
  74. package/build/javaParser.d.ts +51 -0
  75. package/build/javaParser.js +1538 -0
  76. package/build/javaParser.test.d.ts +1 -0
  77. package/build/javaParser.test.js +1287 -0
  78. package/build/javaScript.d.ts +35 -0
  79. package/build/javaScript.js +1 -0
  80. package/build/javaScriptParser.d.ts +9 -0
  81. package/build/javaScriptParser.js +34 -0
  82. package/build/javaScriptUnparser.d.ts +3 -0
  83. package/build/javaScriptUnparser.js +4 -0
  84. package/build/javaScriptUnparser.test.d.ts +1 -0
  85. package/build/javaScriptUnparser.test.js +24 -0
  86. package/build/javaUnparser.d.ts +2 -0
  87. package/build/javaUnparser.js +519 -0
  88. package/build/javaUnparser.test.d.ts +1 -0
  89. package/build/javaUnparser.test.js +24 -0
  90. package/build/javascript.d.ts +35 -0
  91. package/build/javascript.js +1 -0
  92. package/build/javascriptParser.d.ts +9 -0
  93. package/build/javascriptParser.js +34 -0
  94. package/build/javascriptUnparser.d.ts +3 -0
  95. package/build/javascriptUnparser.js +4 -0
  96. package/build/javascriptUnparser.test.d.ts +1 -0
  97. package/build/javascriptUnparser.test.js +24 -0
  98. package/build/jsonParser.js +2 -12
  99. package/build/lazyMessageError.d.ts +3 -0
  100. package/build/lookaheadParser.js +60 -3
  101. package/build/negativeLookaheadParser.js +70 -11
  102. package/build/nonEmptyArrayParser.js +72 -13
  103. package/build/objectParser.d.ts +12 -0
  104. package/build/objectParser.js +31 -0
  105. package/build/objectParser.test-d.d.ts +1 -0
  106. package/build/objectParser.test-d.js +112 -0
  107. package/build/objectParser.test.d.ts +1 -0
  108. package/build/objectParser.test.js +55 -0
  109. package/build/optionalParser.js +69 -10
  110. package/build/parser.d.ts +4 -0
  111. package/build/parser.js +3 -1
  112. package/build/parser.test.js +114 -1
  113. package/build/parserConsumedSequenceParser.js +66 -7
  114. package/build/parserContext.d.ts +6 -0
  115. package/build/parserContext.js +20 -11
  116. package/build/parserError.d.ts +119 -27
  117. package/build/parserError.js +16 -8
  118. package/build/regexpParser.d.ts +2 -0
  119. package/build/regexpParser.js +101 -0
  120. package/build/regexpParser.test.d.ts +1 -0
  121. package/build/regexpParser.test.js +114 -0
  122. package/build/regularExpression.d.ts +63 -0
  123. package/build/regularExpression.js +1 -0
  124. package/build/regularExpressionParser.d.ts +3 -0
  125. package/build/regularExpressionParser.js +600 -0
  126. package/build/regularExpressionParser.test.d.ts +1 -0
  127. package/build/regularExpressionParser.test.js +89 -0
  128. package/build/separatedArrayParser.js +73 -14
  129. package/build/separatedNonEmptyArrayParser.js +73 -14
  130. package/build/sliceBoundedParser.js +62 -5
  131. package/build/smaliParser.d.ts +7 -7
  132. package/build/smaliParser.js +185 -268
  133. package/build/smaliParser.test.js +58 -0
  134. package/build/stringEscapes.d.ts +5 -0
  135. package/build/stringEscapes.js +244 -0
  136. package/build/symbolicExpression.d.ts +29 -0
  137. package/build/symbolicExpression.js +1 -0
  138. package/build/symbolicExpressionParser.d.ts +4 -0
  139. package/build/symbolicExpressionParser.js +123 -0
  140. package/build/symbolicExpressionParser.test.d.ts +1 -0
  141. package/build/symbolicExpressionParser.test.js +289 -0
  142. package/build/terminatedArrayParser.js +113 -38
  143. package/build/terminatedArrayParser.test.js +4 -2
  144. package/build/tupleParser.d.ts +7 -15
  145. package/build/tupleParser.js +1 -0
  146. package/build/unionParser.d.ts +5 -3
  147. package/build/unionParser.js +7 -2
  148. package/build/unionParser.test-d.d.ts +1 -0
  149. package/build/unionParser.test-d.js +72 -0
  150. package/build/unionParser.test.js +10 -11
  151. package/build/zig.d.ts +280 -0
  152. package/build/zig.js +2 -0
  153. package/build/zigParser.d.ts +3 -0
  154. package/build/zigParser.js +1119 -0
  155. package/build/zigParser.test.d.ts +1 -0
  156. package/build/zigParser.test.js +1590 -0
  157. package/build/zigUnparser.d.ts +2 -0
  158. package/build/zigUnparser.js +460 -0
  159. package/build/zigUnparser.test.d.ts +1 -0
  160. package/build/zigUnparser.test.js +24 -0
  161. package/build/zipParser.js +19 -32
  162. package/build/zipUnparser.js +19 -7
  163. package/build/zipUnparser.test.js +1 -1
  164. package/node_modules-@types/s-expression/index.d.ts +5 -0
  165. package/package.json +25 -6
  166. package/src/androidPackageParser.ts +33 -60
  167. package/src/arbitraryDalvikBytecode.ts +39 -31
  168. package/src/arbitraryDalvikExecutable.ts +65 -20
  169. package/src/arbitraryJava.ts +804 -0
  170. package/src/arbitraryJavaScript.ts +410 -0
  171. package/src/arbitraryZig.ts +380 -0
  172. package/src/arrayParser.ts +1 -3
  173. package/src/backsmali.ts +35 -4
  174. package/src/bash.ts +127 -0
  175. package/src/bashParser.test.ts +590 -0
  176. package/src/bashParser.ts +498 -0
  177. package/src/dalvikBytecodeParser/addressConversion.ts +496 -0
  178. package/src/dalvikBytecodeParser/formatParsers.ts +19 -29
  179. package/src/dalvikBytecodeParser.test-d.ts +310 -0
  180. package/src/dalvikBytecodeParser.ts +194 -69
  181. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +27 -26
  182. package/src/dalvikBytecodeUnparser.test.ts +7 -7
  183. package/src/dalvikBytecodeUnparser.ts +31 -30
  184. package/src/dalvikExecutable.test-d.ts +132 -0
  185. package/src/dalvikExecutable.ts +3 -3
  186. package/src/dalvikExecutableParser/typedNumbers.ts +11 -0
  187. package/src/dalvikExecutableParser.test.ts +37 -3
  188. package/src/dalvikExecutableParser.test.ts.md +163 -2
  189. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  190. package/src/dalvikExecutableParser.ts +121 -139
  191. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +4 -0
  192. package/src/dalvikExecutableUnparser/poolScanners.ts +6 -6
  193. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +38 -14
  194. package/src/dalvikExecutableUnparser.test.ts +3 -2
  195. package/src/dalvikExecutableUnparser.ts +4 -4
  196. package/src/disjunctionParser.test-d.ts +105 -0
  197. package/src/disjunctionParser.ts +18 -15
  198. package/src/elementSwitchParser.test-d.ts +74 -0
  199. package/src/elementSwitchParser.ts +51 -0
  200. package/src/exactSequenceParser.test-d.ts +43 -0
  201. package/src/exactSequenceParser.ts +13 -8
  202. package/src/fetchCid.ts +2 -76
  203. package/src/index.test.ts +22 -1
  204. package/src/index.ts +119 -2
  205. package/src/inputReader.ts +53 -0
  206. package/src/java.ts +708 -0
  207. package/src/javaKeyStoreParser.ts +18 -32
  208. package/src/javaParser.test.ts +1592 -0
  209. package/src/javaParser.ts +2640 -0
  210. package/src/javaScript.ts +36 -0
  211. package/src/javaScriptParser.ts +57 -0
  212. package/src/javaScriptUnparser.test.ts +37 -0
  213. package/src/javaScriptUnparser.ts +7 -0
  214. package/src/javaUnparser.test.ts +37 -0
  215. package/src/javaUnparser.ts +640 -0
  216. package/src/jsonParser.ts +6 -27
  217. package/src/lookaheadParser.ts +2 -6
  218. package/src/negativeLookaheadParser.ts +1 -3
  219. package/src/nonEmptyArrayParser.ts +1 -3
  220. package/src/objectParser.test-d.ts +152 -0
  221. package/src/objectParser.test.ts +71 -0
  222. package/src/objectParser.ts +69 -0
  223. package/src/optionalParser.ts +1 -3
  224. package/src/parser.test.ts +151 -4
  225. package/src/parser.ts +11 -1
  226. package/src/parserConsumedSequenceParser.ts +2 -4
  227. package/src/parserContext.ts +26 -11
  228. package/src/parserError.ts +17 -3
  229. package/src/regexpParser.test.ts +264 -0
  230. package/src/regexpParser.ts +126 -0
  231. package/src/regularExpression.ts +24 -0
  232. package/src/regularExpressionParser.test.ts +102 -0
  233. package/src/regularExpressionParser.ts +920 -0
  234. package/src/separatedArrayParser.ts +1 -3
  235. package/src/separatedNonEmptyArrayParser.ts +1 -3
  236. package/src/sliceBoundedParser.test.ts +2 -2
  237. package/src/sliceBoundedParser.ts +15 -19
  238. package/src/smaliParser.test.ts +64 -0
  239. package/src/smaliParser.test.ts.md +12 -12
  240. package/src/smaliParser.test.ts.snap +0 -0
  241. package/src/smaliParser.ts +246 -534
  242. package/src/stringEscapes.ts +253 -0
  243. package/src/symbolicExpression.ts +17 -0
  244. package/src/symbolicExpressionParser.test.ts +466 -0
  245. package/src/symbolicExpressionParser.ts +190 -0
  246. package/src/terminatedArrayParser.test.ts +9 -6
  247. package/src/terminatedArrayParser.ts +25 -29
  248. package/src/tupleParser.ts +21 -18
  249. package/src/unionParser.test-d.ts +105 -0
  250. package/src/unionParser.test.ts +18 -17
  251. package/src/unionParser.ts +28 -16
  252. package/src/zig.ts +411 -0
  253. package/src/zigParser.test.ts +1693 -0
  254. package/src/zigParser.ts +1745 -0
  255. package/src/zigUnparser.test.ts +37 -0
  256. package/src/zigUnparser.ts +615 -0
  257. package/src/zipParser.ts +20 -56
  258. package/src/zipUnparser.test.ts +1 -1
  259. package/src/zipUnparser.ts +22 -7
  260. package/tsconfig.json +2 -2
  261. package/build/exactElementSwitchParser.d.ts +0 -3
  262. package/src/exactElementSwitchParser.ts +0 -41
@@ -0,0 +1,2 @@
1
+ import { type Unparser } from './unparser.js';
2
+ export declare const zigSourceFileUnparser: Unparser<unknown, string>;
@@ -0,0 +1,460 @@
1
+ import { escapeZigString, escapeZigChar } from './stringEscapes.js';
2
+ function unparseExpression(node) {
3
+ switch (node.type) {
4
+ case 'Identifier':
5
+ return node.name;
6
+ case 'IntegerLiteral':
7
+ return node.value;
8
+ case 'FloatLiteral':
9
+ return node.value;
10
+ case 'StringLiteral':
11
+ return '"' + escapeZigString(node.value) + '"';
12
+ case 'MultilineStringLiteral':
13
+ return node.value;
14
+ case 'CharLiteral':
15
+ return "'" + escapeZigChar(node.value) + "'";
16
+ case 'EnumLiteral':
17
+ return '.' + node.name;
18
+ case 'BoolLiteral':
19
+ return node.value ? 'true' : 'false';
20
+ case 'NullLiteral':
21
+ return 'null';
22
+ case 'UndefinedLiteral':
23
+ return 'undefined';
24
+ case 'BinaryExpr':
25
+ return unparseExpression(node.left) + ' ' + unparseBinaryOp(node.operator) + ' ' + unparseExpression(node.right);
26
+ case 'UnaryExpr':
27
+ if (node.operator === '&') {
28
+ return '&' + unparseExpression(node.operand);
29
+ }
30
+ return node.operator + unparseExpression(node.operand);
31
+ case 'FieldAccessExpr':
32
+ return unparseExpression(node.operand) + '.' + node.member;
33
+ case 'IndexExpr':
34
+ return unparseExpression(node.operand) + '[' + unparseExpression(node.index) + ']';
35
+ case 'SliceExpr': {
36
+ let result = unparseExpression(node.operand) + '[' + unparseExpression(node.start) + '..';
37
+ if (node.end) {
38
+ result += unparseExpression(node.end);
39
+ }
40
+ result += ']';
41
+ return result;
42
+ }
43
+ case 'CallExpr':
44
+ return unparseExpression(node.callee) + '(' + node.args.map(a => unparseExpression(a)).join(', ') + ')';
45
+ case 'BuiltinCallExpr':
46
+ return '@' + node.name + '(' + node.args.map(a => unparseExpression(a)).join(', ') + ')';
47
+ case 'IfExpr': {
48
+ let result = 'if (' + unparseExpression(node.condition) + ')';
49
+ if (node.capture) {
50
+ result += ' |' + node.capture + '|';
51
+ }
52
+ result += ' ' + unparseExpression(node.body);
53
+ if (node.elseBody) {
54
+ result += ' else';
55
+ if (node.elseCapture) {
56
+ result += ' |' + node.elseCapture + '|';
57
+ }
58
+ result += ' ' + unparseExpression(node.elseBody);
59
+ }
60
+ return result;
61
+ }
62
+ case 'SwitchExpr': {
63
+ let result = 'switch (' + unparseExpression(node.operand) + ') {';
64
+ for (let i = 0; i < node.prongs.length; i++) {
65
+ if (i > 0) {
66
+ result += ',';
67
+ }
68
+ result += ' ' + unparseSwitchProng(node.prongs[i]);
69
+ }
70
+ if (node.prongs.length > 0) {
71
+ result += ',';
72
+ }
73
+ result += ' }';
74
+ return result;
75
+ }
76
+ case 'StructInitExpr': {
77
+ let result = '';
78
+ if (node.operand) {
79
+ result += unparseExpression(node.operand);
80
+ }
81
+ else {
82
+ result += '.';
83
+ }
84
+ result += '{ ';
85
+ result += node.fields.map(f => unparseStructInitField(f)).join(', ');
86
+ if (node.fields.length > 0) {
87
+ result += ', ';
88
+ }
89
+ result += '}';
90
+ return result;
91
+ }
92
+ case 'ArrayInitExpr': {
93
+ let result = '';
94
+ if (node.operand) {
95
+ result += unparseExpression(node.operand);
96
+ }
97
+ else {
98
+ result += '.';
99
+ }
100
+ result += '{ ';
101
+ result += node.elements.map(e => unparseExpression(e)).join(', ');
102
+ if (node.elements.length > 0) {
103
+ result += ', ';
104
+ }
105
+ result += '}';
106
+ return result;
107
+ }
108
+ case 'TryExpr':
109
+ return 'try ' + unparseExpression(node.operand);
110
+ case 'ComptimeExpr':
111
+ return 'comptime ' + unparseExpression(node.operand);
112
+ case 'BlockExpr':
113
+ return unparseBlockExpr(node);
114
+ case 'GroupedExpr':
115
+ return '(' + unparseExpression(node.inner) + ')';
116
+ case 'ErrorSetExpr':
117
+ return 'error{ ' + node.names.join(', ') + ' }';
118
+ case 'ErrorUnionType':
119
+ return unparseTypeExpression(node.error) + '!' + unparseTypeExpression(node.payload);
120
+ case 'PointerType':
121
+ return unparsePointerType(node);
122
+ case 'OptionalType':
123
+ return '?' + unparseTypeExpression(node.child);
124
+ case 'FnProtoType':
125
+ return 'fn(' + node.params.map(p => unparseFnParam(p)).join(', ') + ') ' + unparseTypeExpression(node.returnType);
126
+ case 'StructExpr': {
127
+ let result = 'struct { ';
128
+ for (const member of node.members) {
129
+ result += unparseContainerMember(member) + ' ';
130
+ }
131
+ result += '}';
132
+ return result;
133
+ }
134
+ case 'ArrayType': {
135
+ let result = '[' + unparseExpression(node.length);
136
+ if (node.sentinel) {
137
+ result += ':' + unparseExpression(node.sentinel);
138
+ }
139
+ result += ']';
140
+ result += unparseTypeExpression(node.child);
141
+ return result;
142
+ }
143
+ default:
144
+ throw new Error(`Unknown expression type: ${node.type}`);
145
+ }
146
+ }
147
+ function unparsePointerType(node) {
148
+ let result = '';
149
+ switch (node.size) {
150
+ case 'one':
151
+ result += '*';
152
+ break;
153
+ case 'many':
154
+ result += '[*]';
155
+ break;
156
+ case 'slice':
157
+ result += '[]';
158
+ break;
159
+ }
160
+ if (node.isConst) {
161
+ result += 'const ';
162
+ }
163
+ result += unparseTypeExpression(node.child);
164
+ return result;
165
+ }
166
+ function unparseTypeExpression(node) {
167
+ switch (node.type) {
168
+ case 'IdentifierType':
169
+ return node.name;
170
+ case 'PointerType':
171
+ return unparsePointerType(node);
172
+ case 'ArrayType': {
173
+ let result = '[' + unparseExpression(node.length);
174
+ if (node.sentinel) {
175
+ result += ':' + unparseExpression(node.sentinel);
176
+ }
177
+ result += ']';
178
+ result += unparseTypeExpression(node.child);
179
+ return result;
180
+ }
181
+ case 'OptionalType':
182
+ return '?' + unparseTypeExpression(node.child);
183
+ case 'ErrorUnionType':
184
+ return unparseTypeExpression(node.error) + '!' + unparseTypeExpression(node.payload);
185
+ case 'DotType':
186
+ return unparseTypeExpression(node.operand) + '.' + node.member;
187
+ case 'BuiltinType':
188
+ return '@' + node.name;
189
+ case 'FnProtoType':
190
+ return 'fn(' + node.params.map(p => unparseFnParam(p)).join(', ') + ') ' + unparseTypeExpression(node.returnType);
191
+ default:
192
+ return unparseExpression(node);
193
+ }
194
+ }
195
+ function unparseBinaryOp(op) {
196
+ switch (op) {
197
+ case 'and':
198
+ return 'and';
199
+ case 'or':
200
+ return 'or';
201
+ case 'orelse':
202
+ return 'orelse';
203
+ case 'catch':
204
+ return 'catch';
205
+ default:
206
+ return op;
207
+ }
208
+ }
209
+ function unparseSwitchProng(prong) {
210
+ let result = '';
211
+ if (prong.isElse) {
212
+ result += 'else';
213
+ }
214
+ else {
215
+ result += prong.cases.map(c => unparseExpression(c)).join(', ');
216
+ }
217
+ result += ' =>';
218
+ if (prong.capture) {
219
+ result += ' |' + prong.capture + '|';
220
+ }
221
+ result += ' ' + unparseExpression(prong.body);
222
+ return result;
223
+ }
224
+ function unparseStructInitField(field) {
225
+ return '.' + field.name + ' = ' + unparseExpression(field.value);
226
+ }
227
+ function unparseBlockExpr(node) {
228
+ let result = '';
229
+ if (node.label) {
230
+ result += node.label + ': ';
231
+ }
232
+ result += '{ ';
233
+ for (const stmt of node.statements) {
234
+ result += unparseStatement(stmt) + ' ';
235
+ }
236
+ result += '}';
237
+ return result;
238
+ }
239
+ function unparseStatement(node) {
240
+ switch (node.type) {
241
+ case 'AssignStmt':
242
+ return unparseExpression(node.target) + ' ' + node.operator + ' ' + unparseExpression(node.value) + ';';
243
+ case 'VarDecl':
244
+ return unparseVarDeclCommon(node);
245
+ case 'IfExpr': {
246
+ let result = 'if (' + unparseExpression(node.condition) + ')';
247
+ if (node.capture) {
248
+ result += ' |' + node.capture + '|';
249
+ }
250
+ result += ' ' + unparseStatement(node.body);
251
+ if (node.elseBody) {
252
+ result += ' else';
253
+ if (node.elseCapture) {
254
+ result += ' |' + node.elseCapture + '|';
255
+ }
256
+ result += ' ' + unparseStatement(node.elseBody);
257
+ }
258
+ return result;
259
+ }
260
+ case 'WhileStmt': {
261
+ let result = '';
262
+ if (node.label) {
263
+ result += node.label + ': ';
264
+ }
265
+ if (node.isInline) {
266
+ result += 'inline ';
267
+ }
268
+ result += 'while (' + unparseExpression(node.condition) + ')';
269
+ if (node.capture) {
270
+ result += ' |' + node.capture + '|';
271
+ }
272
+ if (node.continuation) {
273
+ result += ' : (' + unparseExpression(node.continuation) + ')';
274
+ }
275
+ result += ' ' + unparseStatement(node.body);
276
+ if (node.elseBody) {
277
+ result += ' else ' + unparseStatement(node.elseBody);
278
+ }
279
+ return result;
280
+ }
281
+ case 'ForStmt': {
282
+ let result = '';
283
+ if (node.label) {
284
+ result += node.label + ': ';
285
+ }
286
+ if (node.isInline) {
287
+ result += 'inline ';
288
+ }
289
+ result += 'for (' + node.inputs.map(i => unparseExpression(i)).join(', ') + ') |' + node.captures.join(', ') + '| ' + unparseStatement(node.body);
290
+ if (node.elseBody) {
291
+ result += ' else ' + unparseStatement(node.elseBody);
292
+ }
293
+ return result;
294
+ }
295
+ case 'ReturnStmt':
296
+ if (node.value) {
297
+ return 'return ' + unparseExpression(node.value) + ';';
298
+ }
299
+ return 'return;';
300
+ case 'BreakStmt': {
301
+ let result = 'break';
302
+ if (node.label) {
303
+ result += ' :' + node.label;
304
+ }
305
+ if (node.value) {
306
+ result += ' ' + unparseExpression(node.value);
307
+ }
308
+ result += ';';
309
+ return result;
310
+ }
311
+ case 'ContinueStmt': {
312
+ let result = 'continue';
313
+ if (node.label) {
314
+ result += ' :' + node.label;
315
+ }
316
+ result += ';';
317
+ return result;
318
+ }
319
+ case 'DeferStmt': {
320
+ let result = node.isErrdefer ? 'errdefer' : 'defer';
321
+ if (node.capture) {
322
+ result += ' |' + node.capture + '|';
323
+ }
324
+ result += ' ' + unparseStatement(node.body);
325
+ return result;
326
+ }
327
+ case 'BlockExpr':
328
+ return unparseBlockExpr(node);
329
+ default:
330
+ return unparseExpression(node) + ';';
331
+ }
332
+ }
333
+ function unparseVarDeclCommon(node) {
334
+ let result = '';
335
+ if (node.isPub) {
336
+ result += 'pub ';
337
+ }
338
+ if (node.isExtern) {
339
+ result += 'extern ';
340
+ }
341
+ if (node.isComptime) {
342
+ result += 'comptime ';
343
+ }
344
+ if (node.isThreadlocal) {
345
+ result += 'threadlocal ';
346
+ }
347
+ result += node.isConst ? 'const' : 'var';
348
+ result += ' ' + node.name;
349
+ if (node.typeExpr) {
350
+ result += ': ' + unparseTypeExpression(node.typeExpr);
351
+ }
352
+ if (node.alignExpr) {
353
+ result += ' align(' + unparseExpression(node.alignExpr) + ')';
354
+ }
355
+ if (node.initExpr) {
356
+ result += ' = ' + unparseExpression(node.initExpr);
357
+ }
358
+ result += ';';
359
+ return result;
360
+ }
361
+ function unparseFnParam(param) {
362
+ let result = '';
363
+ if (param.isComptime) {
364
+ result += 'comptime ';
365
+ }
366
+ if (param.isNoalias) {
367
+ result += 'noalias ';
368
+ }
369
+ if (param.name) {
370
+ result += param.name + ': ';
371
+ }
372
+ if (param.typeExpr) {
373
+ result += unparseTypeExpression(param.typeExpr);
374
+ }
375
+ return result;
376
+ }
377
+ function unparseContainerMember(node) {
378
+ switch (node.type) {
379
+ case 'FnDecl':
380
+ return unparseFnDecl(node);
381
+ case 'VarDecl':
382
+ return unparseVarDeclCommon(node);
383
+ case 'TestDecl':
384
+ return unparseTestDecl(node);
385
+ case 'UsingnamespaceDecl':
386
+ return unparseUsingnamespaceDecl(node);
387
+ case 'ContainerField':
388
+ return unparseContainerField(node);
389
+ default:
390
+ throw new Error(`Unknown container member type: ${node.type}`);
391
+ }
392
+ }
393
+ function unparseFnDecl(node) {
394
+ let result = '';
395
+ if (node.isPub) {
396
+ result += 'pub ';
397
+ }
398
+ if (node.isExtern) {
399
+ result += 'extern ';
400
+ }
401
+ if (node.isExport) {
402
+ result += 'export ';
403
+ }
404
+ if (node.isInline) {
405
+ result += 'inline ';
406
+ }
407
+ if (node.isComptime) {
408
+ result += 'comptime ';
409
+ }
410
+ result += 'fn ' + node.name + '(' + node.params.map(p => unparseFnParam(p)).join(', ') + ') ';
411
+ result += unparseTypeExpression(node.returnType);
412
+ if (node.body) {
413
+ result += ' ' + unparseBlockExpr(node.body);
414
+ }
415
+ else {
416
+ result += ';';
417
+ }
418
+ return result;
419
+ }
420
+ function unparseTestDecl(node) {
421
+ let result = 'test';
422
+ if (node.name) {
423
+ result += ' "' + escapeZigString(node.name) + '"';
424
+ }
425
+ result += ' ' + unparseBlockExpr(node.body);
426
+ return result;
427
+ }
428
+ function unparseUsingnamespaceDecl(node) {
429
+ let result = '';
430
+ if (node.isPub) {
431
+ result += 'pub ';
432
+ }
433
+ result += 'usingnamespace ' + unparseExpression(node.expression) + ';';
434
+ return result;
435
+ }
436
+ function unparseContainerField(node) {
437
+ let result = node.name;
438
+ if (node.typeExpr) {
439
+ result += ': ' + unparseTypeExpression(node.typeExpr);
440
+ }
441
+ if (node.alignExpr) {
442
+ result += ' align(' + unparseExpression(node.alignExpr) + ')';
443
+ }
444
+ if (node.defaultValue) {
445
+ result += ' = ' + unparseExpression(node.defaultValue);
446
+ }
447
+ result += ',';
448
+ return result;
449
+ }
450
+ export const zigSourceFileUnparser = async function* (input) {
451
+ const root = input;
452
+ let result = '';
453
+ for (let i = 0; i < root.members.length; i++) {
454
+ if (i > 0) {
455
+ result += '\n';
456
+ }
457
+ result += unparseContainerMember(root.members[i]);
458
+ }
459
+ yield result;
460
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import { testProp } from '@fast-check/ava';
2
+ import { arbitraryZigRoot } from './arbitraryZig.js';
3
+ import { zigSourceFileUnparser } from './zigUnparser.js';
4
+ import { zigSourceFileParser } from './zigParser.js';
5
+ import { runParser } from './parser.js';
6
+ import { runUnparser } from './unparser.js';
7
+ import { stringParserInputCompanion } from './parserInputCompanion.js';
8
+ import { stringUnparserOutputCompanion } from './unparserOutputCompanion.js';
9
+ const seed = process.env.SEED ? Number(process.env.SEED) : undefined;
10
+ async function collectString(asyncIterable) {
11
+ let result = '';
12
+ for await (const chunk of asyncIterable) {
13
+ result += chunk;
14
+ }
15
+ return result;
16
+ }
17
+ testProp('zigUnparser roundtrip', [arbitraryZigRoot], async (t, root) => {
18
+ const source = await collectString(runUnparser(zigSourceFileUnparser, root, stringUnparserOutputCompanion));
19
+ const reparsed = await runParser(zigSourceFileParser, source, stringParserInputCompanion);
20
+ t.deepEqual(reparsed, root);
21
+ }, {
22
+ verbose: true,
23
+ seed,
24
+ });
@@ -4,6 +4,7 @@ import { pipeline } from 'node:stream/promises';
4
4
  import invariant from 'invariant';
5
5
  import { createArrayParser } from './arrayParser.js';
6
6
  import { createExactSequenceParser } from './exactSequenceParser.js';
7
+ import { createObjectParser } from './objectParser.js';
7
8
  import { setParserName } from './parser.js';
8
9
  import { createTupleParser } from './tupleParser.js';
9
10
  import { promiseCompose } from './promiseCompose.js';
@@ -66,19 +67,15 @@ const zipEncryptionHeaderParser = async (parserContext) => {
66
67
  };
67
68
  const zipDataDescriptorSignature = Buffer.from('504b0708', 'hex');
68
69
  const zipDataDescriptorSignatureParser = createExactSequenceParser(zipDataDescriptorSignature);
69
- const zipDataDescriptorParser = promiseCompose(createTupleParser([
70
- createNegativeLookaheadParser(zipLocalFileHeaderSignatureParser),
70
+ const zipDataDescriptorParser = createObjectParser({
71
+ _notZipLocalFileHeaderSignature: createNegativeLookaheadParser(zipLocalFileHeaderSignatureParser),
71
72
  // FIXME: optional in spec
72
- // createOptionalParser(zipDataDescriptorSignatureParser),
73
- zipDataDescriptorSignatureParser,
74
- uint32LEParser,
75
- uint32LEParser,
76
- uint32LEParser,
77
- ]), ([_notZipLocalFileHeaderSignature, _zipDataDescriptorSignature, crc32, compressedSize, uncompressedSize,]) => ({
78
- crc32,
79
- compressedSize,
80
- uncompressedSize,
81
- }));
73
+ // _zipDataDescriptorSignature: createOptionalParser(zipDataDescriptorSignatureParser),
74
+ _zipDataDescriptorSignature: zipDataDescriptorSignatureParser,
75
+ crc32: uint32LEParser,
76
+ compressedSize: uint32LEParser,
77
+ uncompressedSize: uint32LEParser,
78
+ });
82
79
  setParserName(zipDataDescriptorParser, 'zipDataDescriptorParser');
83
80
  export const zipLocalFileParser = promiseCompose(parserCreatorCompose(() => zipLocalFileHeaderParser, zipLocalFileHeader => {
84
81
  const sizeInDataDescriptor = Boolean(zipLocalFileHeader.generalPurposeBitFlag & 0b0000_0000_0000_1000
@@ -176,26 +173,16 @@ export const zip64EndOfCentralDirectoryLocatorParser = async (parserContext) =>
176
173
  parserContext.invariant(false, 'Not implemented');
177
174
  };
178
175
  const zipFileCommentParser = promiseCompose(parserCreatorCompose(() => uint16LEParser, length => createFixedLengthSequenceParser(length))(), uint8Array => Buffer.from(uint8Array).toString('utf8'));
179
- const zipEndOfCentralDirectoryRecordParser_ = createTupleParser([
180
- createExactSequenceParser(Buffer.from('504b0506', 'hex')),
181
- uint16LEParser,
182
- uint16LEParser,
183
- uint16LEParser,
184
- uint16LEParser,
185
- uint32LEParser,
186
- uint32LEParser,
187
- zipFileCommentParser,
188
- ]);
189
- setParserName(zipEndOfCentralDirectoryRecordParser_, 'zipEndOfCentralDirectoryRecordParser_');
190
- export const zipEndOfCentralDirectoryRecordParser = promiseCompose(zipEndOfCentralDirectoryRecordParser_, ([_endOfCentralDirectoryRecordSignature, numberOfThisDisk, numberOfTheDiskWithTheStartOfTheCentralDirectory, totalNumberOfEntriesInTheCentralDirectoryOnThisDisk, totalNumberOfEntriesInTheCentralDirectory, sizeOfTheCentralDirectory, offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber, zipFileComment,]) => ({
191
- numberOfThisDisk,
192
- numberOfTheDiskWithTheStartOfTheCentralDirectory,
193
- totalNumberOfEntriesInTheCentralDirectoryOnThisDisk,
194
- totalNumberOfEntriesInTheCentralDirectory,
195
- sizeOfTheCentralDirectory,
196
- offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber,
197
- zipFileComment,
198
- }));
176
+ export const zipEndOfCentralDirectoryRecordParser = createObjectParser({
177
+ _endOfCentralDirectoryRecordSignature: createExactSequenceParser(Buffer.from('504b0506', 'hex')),
178
+ numberOfThisDisk: uint16LEParser,
179
+ numberOfTheDiskWithTheStartOfTheCentralDirectory: uint16LEParser,
180
+ totalNumberOfEntriesInTheCentralDirectoryOnThisDisk: uint16LEParser,
181
+ totalNumberOfEntriesInTheCentralDirectory: uint16LEParser,
182
+ sizeOfTheCentralDirectory: uint32LEParser,
183
+ offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber: uint32LEParser,
184
+ zipFileComment: zipFileCommentParser,
185
+ });
199
186
  setParserName(zipEndOfCentralDirectoryRecordParser, 'zipEndOfCentralDirectoryRecordParser');
200
187
  const zipParser_ = createTupleParser([
201
188
  createArrayParser(zipLocalFileParser),
@@ -78,6 +78,12 @@ export const createZipUnparser = ({ dataDescriptor = false, } = {}) => async fun
78
78
  ]);
79
79
  return [[zipEntry, promise.then(([, compressedContent]) => compressedContent)]];
80
80
  }));
81
+ const crc32ByZipFileEntry = new Map(zip.entries.flatMap(zipEntry => {
82
+ if (zipEntry.type !== 'file') {
83
+ return [];
84
+ }
85
+ return [[zipEntry, zlib.crc32(zipEntry.content)]];
86
+ }));
81
87
  const filePathByZipEntry = new Map(zip.entries.map(zipEntry => [zipEntry, zipEntry.type === 'file' ? zipEntry.path : zipEntry.path + '/']));
82
88
  const localHeaderPositionByZipEntry = new Map();
83
89
  for (const zipEntry of zip.entries) {
@@ -95,12 +101,18 @@ export const createZipUnparser = ({ dataDescriptor = false, } = {}) => async fun
95
101
  extraField: Buffer.alloc(0),
96
102
  };
97
103
  let shouldWriteDataDescriptor = false;
104
+ let actualCrc32 = 0;
105
+ let actualCompressedSize = 0;
106
+ let actualUncompressedSize = 0;
98
107
  if (zipEntry.type === 'file') {
99
108
  const compressedContent = await compressedContentByZipFileEntry.get(zipEntry);
100
109
  zipLocalFileHeader.compressionMethod = zipEntry.compression;
101
- zipLocalFileHeader.crc32 = 0; // TODO
102
- zipLocalFileHeader.compressedSize = compressedContent.length;
103
- zipLocalFileHeader.uncompressedSize = zipEntry.content.length;
110
+ actualCrc32 = crc32ByZipFileEntry.get(zipEntry);
111
+ actualCompressedSize = compressedContent.length;
112
+ actualUncompressedSize = zipEntry.content.length;
113
+ zipLocalFileHeader.crc32 = actualCrc32;
114
+ zipLocalFileHeader.compressedSize = actualCompressedSize;
115
+ zipLocalFileHeader.uncompressedSize = actualUncompressedSize;
104
116
  if (dataDescriptor) {
105
117
  shouldWriteDataDescriptor = true;
106
118
  zipLocalFileHeader.generalPurposeBitFlag |= 0b0000_0000_0000_1000;
@@ -115,9 +127,9 @@ export const createZipUnparser = ({ dataDescriptor = false, } = {}) => async fun
115
127
  yield compressedContent;
116
128
  if (shouldWriteDataDescriptor) {
117
129
  yield* zipDataDescriptorUnparser({
118
- crc32: zipLocalFileHeader.crc32,
119
- compressedSize: zipLocalFileHeader.compressedSize,
120
- uncompressedSize: zipLocalFileHeader.uncompressedSize,
130
+ crc32: actualCrc32,
131
+ compressedSize: actualCompressedSize,
132
+ uncompressedSize: actualUncompressedSize,
121
133
  }, unparserContext);
122
134
  }
123
135
  }
@@ -139,7 +151,7 @@ export const createZipUnparser = ({ dataDescriptor = false, } = {}) => async fun
139
151
  yield* dosDateTimeUnparser(zipEntry.date, unparserContext);
140
152
  if (zipEntry.type === 'file') {
141
153
  const compressedContent = await compressedContentByZipFileEntry.get(zipEntry);
142
- yield* uint32LEUnparser(0, unparserContext); // Crc32 // TODO
154
+ yield* uint32LEUnparser(crc32ByZipFileEntry.get(zipEntry), unparserContext);
143
155
  yield* uint32LEUnparser(compressedContent.length, unparserContext);
144
156
  yield* uint32LEUnparser(zipEntry.content.length, unparserContext);
145
157
  }
@@ -34,7 +34,7 @@ async function _7zList(zipFilePath) {
34
34
  throw new Error(`7z reports errors: ${stdout}`);
35
35
  }
36
36
  return {
37
- isEmptyZipfile: false, // TODO
37
+ isEmptyZipfile: /\b0 files\b/.test(stdout),
38
38
  };
39
39
  }
40
40
  testProp('zip', [
@@ -0,0 +1,5 @@
1
+ declare module 's-expression' {
2
+ type SExpressionResult = string | String | SExpressionResult[] | Error;
3
+ function sExpression(input: string): SExpressionResult;
4
+ export default sExpression;
5
+ }