1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | 'use strict';
|
16 |
|
17 | var P = require('parsimmon');
|
18 | var uuid = require('uuid');
|
19 | var flatten = require('./util').flatten;
|
20 | var CommonMarkUtils = require('@accordproject/markdown-common').CommonMarkUtils;
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | function mkVariable(variable, value) {
|
29 | var result = {};
|
30 | result.name = variable.name;
|
31 | result.elementType = variable.elementType;
|
32 | result.value = value;
|
33 | return result;
|
34 | }
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 | function variableEqual(value1, value2) {
|
43 | var type1 = typeof value1;
|
44 | var type2 = typeof value2;
|
45 | if (type1 === 'object' && type2 === 'object') {
|
46 | for (var key1 in value1) {
|
47 | if (!value2[key1]) {
|
48 | return false;
|
49 | }
|
50 | if (!variableEqual(value1[key1], value2[key1])) {
|
51 | return false;
|
52 | }
|
53 | }
|
54 | for (var key2 in value2) {
|
55 | if (!value1[key2]) {
|
56 | return false;
|
57 | }
|
58 | }
|
59 | } else if (value1 !== value2) {
|
60 | return false;
|
61 | }
|
62 | return true;
|
63 | }
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | function mkCompoundVariable(elementType, value) {
|
72 | var result = {};
|
73 | result.$class = elementType;
|
74 | for (var i = 0; i < value.length; i++) {
|
75 | var field = value[i];
|
76 | if (result[field.name]) {
|
77 | if (!variableEqual(result[field.name], field.value)) {
|
78 | var message = "Inconsistent values for variable ".concat(field.name, ": ").concat(result[field.name], " and ").concat(field.value);
|
79 | throw new Error(message);
|
80 | }
|
81 | } else {
|
82 | result[field.name] = field.value;
|
83 | }
|
84 | }
|
85 | if (result.this) {
|
86 | result = result.this;
|
87 | }
|
88 | return result;
|
89 | }
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | function mkCond(condNode, value) {
|
98 | var result = {};
|
99 | result.name = condNode.name;
|
100 | result.elementType = 'Boolean';
|
101 | result.value = value;
|
102 | return result;
|
103 | }
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 | function mkOpt(optNode, value) {
|
112 | var result = {};
|
113 | result.name = optNode.name;
|
114 | result.elementType = optNode.elementType;
|
115 | result.value = value;
|
116 | return result;
|
117 | }
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 | function mkList(listNode, value) {
|
126 | var result = {};
|
127 | result.name = listNode.name;
|
128 | result.elementType = 'List';
|
129 | result.value = [];
|
130 | for (var i = 0; i < value.length; i++) {
|
131 | var item = mkCompoundVariable(listNode.elementType, value[i]);
|
132 | result.value.push(item);
|
133 | }
|
134 | return result;
|
135 | }
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 | function mkJoin(joinNode, value) {
|
144 | var result = {};
|
145 | result.name = joinNode.name;
|
146 | result.elementType = 'List';
|
147 | result.value = [];
|
148 | for (var i = 0; i < value.length; i++) {
|
149 | result.value.push(mkCompoundVariable(joinNode.elementType, value[i]));
|
150 | }
|
151 | return result;
|
152 | }
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 | function mkClause(clause, value) {
|
161 | return mkCompoundVariable(clause.elementType, value.concat({
|
162 | 'name': 'clauseId',
|
163 | 'elementType': 'String',
|
164 | 'value': uuid.v4()
|
165 | }));
|
166 | }
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 | function mkWrappedClause(clause, src, value) {
|
176 | var result = {
|
177 | 'name': clause.name,
|
178 | 'elementType': clause.elementType,
|
179 | 'value': mkClause(clause, value)
|
180 | };
|
181 | if (src) {
|
182 | result.src = src;
|
183 | }
|
184 | return [result];
|
185 | }
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 | function mkContract(contract, value) {
|
194 | return mkCompoundVariable(contract.elementType, value.concat({
|
195 | 'name': 'contractId',
|
196 | 'elementType': 'String',
|
197 | 'value': uuid.v4()
|
198 | }));
|
199 | }
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 | function textParser(text) {
|
211 | return P.string(CommonMarkUtils.escapeText(text));
|
212 | }
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 | function stringLiteralParser() {
|
219 | return P.regexp(/"[^"]*"/).desc('A String literal "..."');
|
220 | }
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 | function nameParser() {
|
227 | return P.regexp(/[A-Za-z0-9_-]+/).desc('A name');
|
228 | }
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 | function choiceParser(parsers) {
|
236 | return P.alt.apply(null, parsers);
|
237 | }
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 | function choiceStringsParser(values) {
|
245 | return choiceParser(values.map(function (x) {
|
246 | return P.string(x);
|
247 | }));
|
248 | }
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 | function seqParser(parsers) {
|
256 | return P.seqMap.apply(null, parsers.concat([function () {
|
257 | var args = Array.prototype.slice.call(arguments);
|
258 | return args.filter(function (x) {
|
259 | return !(typeof x === 'string');
|
260 | });
|
261 | }]));
|
262 | }
|
263 |
|
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 | function seqFunParser(parsers) {
|
270 | return r => P.seqMap.apply(null, parsers.map(x => x(r)).concat([function () {
|
271 | var args = Array.prototype.slice.call(arguments);
|
272 | return args.filter(function (x) {
|
273 | return !(typeof x === 'string');
|
274 | });
|
275 | }]));
|
276 | }
|
277 |
|
278 |
|
279 |
|
280 |
|
281 |
|
282 | function computedParser() {
|
283 | return P.regexp(/{{%[^%]*%}}/).desc('A computed variable {{ ... }}');
|
284 | }
|
285 |
|
286 |
|
287 |
|
288 |
|
289 |
|
290 |
|
291 | function enumParser(enums) {
|
292 | return choiceStringsParser(enums).map(function (x) {
|
293 | return x;
|
294 | });
|
295 | }
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 | function conditionalParser(condNode, whenTrue, whenFalse) {
|
305 | return P.alt(whenTrue.map(x => true), whenFalse.map(x => false)).map(function (x) {
|
306 | return mkCond(condNode, x);
|
307 | });
|
308 | }
|
309 |
|
310 |
|
311 |
|
312 |
|
313 |
|
314 |
|
315 |
|
316 |
|
317 | function optionalParser(optNode, whenSome, whenNone) {
|
318 | return P.alt(whenSome.map(function (x) {
|
319 | return mkCompoundVariable(optNode.elementType, flatten(x));
|
320 | }), whenNone.map(x => null)).map(function (x) {
|
321 | return mkOpt(optNode, x);
|
322 | });
|
323 | }
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 | function listBlockParser(listNode, bullet, content) {
|
333 |
|
334 | return P.seq(P.alt(bullet, P.seq(P.string('\n'), bullet)), content).map(function (x) {
|
335 | return x[1];
|
336 | }).many().map(function (x) {
|
337 | return mkList(listNode, x);
|
338 | });
|
339 | }
|
340 |
|
341 |
|
342 |
|
343 |
|
344 |
|
345 |
|
346 |
|
347 |
|
348 | function ulistBlockParser(listNode, content, prefix) {
|
349 | return listBlockParser(listNode, P.seq(P.string(prefix), P.string('- ')), content);
|
350 | }
|
351 |
|
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 |
|
359 | function olistBlockParser(listNode, content, prefix) {
|
360 | return listBlockParser(listNode, P.seq(P.string(prefix), P.regexp(/[0-9]+/), P.string('. ')), content);
|
361 | }
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 | function joinBlockParser(joinNode, content) {
|
370 | var separator = joinNode.separator;
|
371 | return P.seq(content, P.seq(P.string(separator), content).map(x => x[1]).many()).map(function (x) {
|
372 | return [x[0]].concat(x[1]);
|
373 | }).map(function (x) {
|
374 | return mkJoin(joinNode, x);
|
375 | });
|
376 | }
|
377 |
|
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 |
|
384 | function withParser(elementType, content) {
|
385 | return content.map(function (x) {
|
386 | return mkCompoundVariable(elementType, flatten(x));
|
387 | });
|
388 | }
|
389 |
|
390 |
|
391 |
|
392 |
|
393 |
|
394 |
|
395 |
|
396 | function clauseParser(clause, content) {
|
397 | return content.skip(P.optWhitespace).map(function (x) {
|
398 | return mkClause(clause, flatten(x));
|
399 | });
|
400 | }
|
401 |
|
402 |
|
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 | function contractParser(contract, content) {
|
409 | return content.skip(P.optWhitespace).map(function (x) {
|
410 | return mkContract(contract, flatten(x));
|
411 | });
|
412 | }
|
413 |
|
414 |
|
415 |
|
416 |
|
417 |
|
418 |
|
419 |
|
420 | function wrappedClauseParser(clause, content) {
|
421 | var clauseEnd = P.string('}}\n');
|
422 | var clauseBefore = P.seq(P.string('\n\n{{#clause '), nameParser(), P.alt(P.seq(P.string(' src='), stringLiteralParser(), clauseEnd), clauseEnd));
|
423 | var clauseAfter = P.string('\n{{/clause}}');
|
424 | return P.seq(clauseBefore, content, clauseAfter).map(function (x) {
|
425 | var srcAttr = x[0][2];
|
426 | var src = srcAttr ? srcAttr[1].substring(1, srcAttr[1].length - 1) : null;
|
427 | return mkWrappedClause(clause, src, flatten(x[1]));
|
428 | });
|
429 | }
|
430 | module.exports.mkVariable = mkVariable;
|
431 | module.exports.mkCompoundVariable = mkCompoundVariable;
|
432 | module.exports.stringLiteralParser = stringLiteralParser;
|
433 | module.exports.textParser = textParser;
|
434 | module.exports.seqParser = seqParser;
|
435 | module.exports.seqFunParser = seqFunParser;
|
436 | module.exports.choiceStringsParser = choiceStringsParser;
|
437 | module.exports.computedParser = computedParser;
|
438 | module.exports.enumParser = enumParser;
|
439 | module.exports.conditionalParser = conditionalParser;
|
440 | module.exports.optionalParser = optionalParser;
|
441 | module.exports.ulistBlockParser = ulistBlockParser;
|
442 | module.exports.olistBlockParser = olistBlockParser;
|
443 | module.exports.joinBlockParser = joinBlockParser;
|
444 | module.exports.withParser = withParser;
|
445 | module.exports.clauseParser = clauseParser;
|
446 | module.exports.wrappedClauseParser = wrappedClauseParser;
|
447 | module.exports.contractParser = contractParser; |
\ | No newline at end of file |