proskomma-core 0.9.18 → 0.9.19

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 (126) hide show
  1. package/dist/bundle.js +1 -0
  2. package/dist/index.cjs +1 -0
  3. package/dist/module.mjs +15888 -0
  4. package/package.json +23 -34
  5. package/dist/index.js +0 -8
  6. package/dist/index.js.LICENSE.txt +0 -23
  7. package/esm/package.json +0 -3
  8. package/esm/wrapper.mjs +0 -7
  9. package/informations/meeting_01_march_2023.md +0 -38
  10. package/src/graph/index.cjs +0 -201
  11. package/src/graph/lib/do_cv.cjs +0 -249
  12. package/src/graph/lib/dump.cjs +0 -40
  13. package/src/graph/lib/remake_blocks.cjs +0 -57
  14. package/src/graph/lib/sequence_chars.cjs +0 -84
  15. package/src/graph/lib/sort.cjs +0 -39
  16. package/src/graph/lib/tribos.cjs +0 -97
  17. package/src/graph/lib/tribos_expression.cjs +0 -556
  18. package/src/graph/lib/tribos_ohm_UNUSED.cjs +0 -37
  19. package/src/graph/lib/tribos_step.cjs +0 -434
  20. package/src/graph/mutations/add.cjs +0 -91
  21. package/src/graph/mutations/delete.cjs +0 -61
  22. package/src/graph/mutations/index.cjs +0 -54
  23. package/src/graph/mutations/rehash.cjs +0 -17
  24. package/src/graph/mutations/tags.cjs +0 -120
  25. package/src/graph/mutations/update.cjs +0 -210
  26. package/src/graph/mutations/versification.cjs +0 -96
  27. package/src/graph/queries/block.cjs +0 -228
  28. package/src/graph/queries/cIndex.cjs +0 -87
  29. package/src/graph/queries/cell.cjs +0 -42
  30. package/src/graph/queries/cv.cjs +0 -19
  31. package/src/graph/queries/cvBook.cjs +0 -16
  32. package/src/graph/queries/cvChapter.cjs +0 -16
  33. package/src/graph/queries/cvIndex.cjs +0 -47
  34. package/src/graph/queries/cvNavigation.cjs +0 -116
  35. package/src/graph/queries/cvVerseElement.cjs +0 -84
  36. package/src/graph/queries/cvVerses.cjs +0 -14
  37. package/src/graph/queries/doc_set.cjs +0 -220
  38. package/src/graph/queries/document.cjs +0 -555
  39. package/src/graph/queries/idParts.cjs +0 -30
  40. package/src/graph/queries/index.cjs +0 -151
  41. package/src/graph/queries/inputBlockSpec.cjs +0 -17
  42. package/src/graph/queries/inputItemObject.cjs +0 -12
  43. package/src/graph/queries/input_att_spec.cjs +0 -14
  44. package/src/graph/queries/input_key_matches.cjs +0 -11
  45. package/src/graph/queries/input_key_value.cjs +0 -11
  46. package/src/graph/queries/input_key_values.cjs +0 -11
  47. package/src/graph/queries/input_selector_spec.cjs +0 -19
  48. package/src/graph/queries/item.cjs +0 -71
  49. package/src/graph/queries/itemGroup.cjs +0 -75
  50. package/src/graph/queries/key_value.cjs +0 -18
  51. package/src/graph/queries/kv_entry.cjs +0 -21
  52. package/src/graph/queries/kv_sequence.cjs +0 -151
  53. package/src/graph/queries/node.cjs +0 -44
  54. package/src/graph/queries/orig.cjs +0 -11
  55. package/src/graph/queries/regex_index.cjs +0 -18
  56. package/src/graph/queries/row_equals_spec.cjs +0 -11
  57. package/src/graph/queries/row_match_spec.cjs +0 -11
  58. package/src/graph/queries/selector_spec.cjs +0 -29
  59. package/src/graph/queries/sequence.cjs +0 -314
  60. package/src/graph/queries/table_sequence.cjs +0 -192
  61. package/src/graph/queries/tree_sequence.cjs +0 -58
  62. package/src/graph/queries/verseNumber.cjs +0 -44
  63. package/src/graph/queries/verseRange.cjs +0 -11
  64. package/src/graph/queries/versification.cjs +0 -25
  65. package/src/index.cjs +0 -583
  66. package/src/model/doc_set.cjs +0 -389
  67. package/src/model/doc_set_helpers/block.cjs +0 -232
  68. package/src/model/doc_set_helpers/enum.cjs +0 -87
  69. package/src/model/doc_set_helpers/item.cjs +0 -198
  70. package/src/model/doc_set_helpers/rehash.cjs +0 -53
  71. package/src/model/doc_set_helpers/selectors.cjs +0 -58
  72. package/src/model/doc_set_helpers/serialize.cjs +0 -22
  73. package/src/model/doc_set_helpers/unsuccinctify.cjs +0 -288
  74. package/src/model/doc_set_helpers/update.cjs +0 -290
  75. package/src/model/document.cjs +0 -369
  76. package/src/model/document_helpers/blocks.cjs +0 -135
  77. package/src/model/document_helpers/chapter_verse.cjs +0 -291
  78. package/src/model/document_helpers/pre_enums.cjs +0 -67
  79. package/src/model/document_helpers/sequences.cjs +0 -205
  80. package/src/model/document_helpers/serialize_succinct.cjs +0 -55
  81. package/src/model/document_helpers/succinct_filter.cjs +0 -102
  82. package/src/model/versifications/eng_vrs.cjs +0 -455
  83. package/src/model/versifications/index.cjs +0 -38
  84. package/src/model/versifications/lxx_vrs.cjs +0 -950
  85. package/src/model/versifications/org_vrs.cjs +0 -155
  86. package/src/model/versifications/rsc_vrs.cjs +0 -342
  87. package/src/model/versifications/rso_vrs.cjs +0 -541
  88. package/src/model/versifications/vul_vrs.cjs +0 -835
  89. package/src/parser/index.cjs +0 -504
  90. package/src/parser/lexers/index.cjs +0 -11
  91. package/src/parser/lexers/lexingRegexes.cjs +0 -45
  92. package/src/parser/lexers/nodes.cjs +0 -123
  93. package/src/parser/lexers/object_for_fragment.cjs +0 -123
  94. package/src/parser/lexers/tsv.cjs +0 -45
  95. package/src/parser/lexers/usfm.cjs +0 -17
  96. package/src/parser/lexers/usx/index.cjs +0 -7
  97. package/src/parser/lexers/usx/usx_lexer.cjs +0 -321
  98. package/src/parser/lib/tokenize.cjs +0 -37
  99. package/src/parser/model/index.cjs +0 -637
  100. package/src/parser/parser_specs.cjs +0 -781
  101. package/src/pipelines/perf2x/index.cjs +0 -7
  102. package/src/pipelines/perf2x/perf2PkJsonPipeline.json +0 -41
  103. package/src/pipelines/perf2x/perf2usfmPipeline.json +0 -65
  104. package/src/transforms/calculateUsfmChapterPositions.cjs +0 -106
  105. package/src/transforms/index.cjs +0 -9
  106. package/src/transforms/perf2PkJson.cjs +0 -534
  107. package/src/transforms/perf2usfm.cjs +0 -294
  108. package/src/util/byteArray.cjs +0 -251
  109. package/src/util/canons.cjs +0 -117
  110. package/src/util/enums.cjs +0 -41
  111. package/src/util/generateId.cjs +0 -6
  112. package/src/util/graftDefs.cjs +0 -15
  113. package/src/util/index.cjs +0 -29
  114. package/src/util/inspectSuccinct.cjs +0 -59
  115. package/src/util/itemDefs.cjs +0 -33
  116. package/src/util/parserConstantDefs.cjs +0 -30
  117. package/src/util/scopeDefs.cjs +0 -173
  118. package/src/util/scriptlike/blocksSpec.cjs +0 -192
  119. package/src/util/scriptlike/dodson_lexicon.xsl +0 -19
  120. package/src/util/scriptlike/dodson_lexicon_to_entries.cjs +0 -85
  121. package/src/util/scriptlike/open_scriptures_hebrew_lexicon.xsl +0 -28
  122. package/src/util/scriptlike/open_scriptures_hebrew_lexicon_to_entries.cjs +0 -85
  123. package/src/util/succinct.cjs +0 -159
  124. package/src/util/tags.cjs +0 -28
  125. package/src/util/tokenDefs.cjs +0 -27
  126. package/src/util/versification.cjs +0 -364
@@ -1,39 +0,0 @@
1
- const utils = require('../../util/index.cjs');
2
-
3
- const ptCompare = (a, b) => {
4
- const bcA = a.headers.bookCode || 'GEN';
5
- const bcB = b.headers.bookCode || 'GEN';
6
- const posA = utils.canons.ptBooks[bcA] ? utils.canons.ptBooks[bcA].position : 999;
7
- const posB = utils.canons.ptBooks[bcB] ? utils.canons.ptBooks[bcB].position : 999;
8
- return posA - posB;
9
- };
10
-
11
- const alphaCompare = (a, b) => {
12
- const bcA = a.headers.bookCode || 'GEN';
13
- const bcB = b.headers.bookCode || 'GEN';
14
- return bcA.localeCompare(bcB);
15
- };
16
-
17
- const alpha2Compare = (a, b) => {
18
- const digits = [1, 2, 3, 4, 5, 6];
19
- let bcA = a.headers.bookCode || 'GEN';
20
-
21
- if (digits.includes(bcA[0])) {
22
- bcA = bcA.substring(1) + bcA[0];
23
- }
24
-
25
- let bcB = b.headers.bookCode || 'GEN';
26
-
27
- if (digits.includes(bcB[0])) {
28
- bcB = bcB.substring(1) + bcB[0];
29
- }
30
- return bcA.localeCompare(bcB);
31
- };
32
-
33
- const bookCodeCompareFunctions = {
34
- paratext: ptCompare,
35
- alpha: alphaCompare,
36
- alpha2: alpha2Compare,
37
- };
38
-
39
- module.exports = { bookCodeCompareFunctions };
@@ -1,97 +0,0 @@
1
- const xre = require('xregexp');
2
-
3
- const { expressions, doPredicate } = require('./tribos_expression.cjs');
4
- const { stepActions } = require('./tribos_step.cjs');
5
-
6
- class Tribos {
7
- constructor() {
8
- this.currentStepType = null;
9
- }
10
-
11
- doStep(docSet, allNodes, nodeLookup, result, queryStep) {
12
- for (const stepAction of stepActions) {
13
- const matches = xre.exec(queryStep, stepAction.regex);
14
-
15
- if (matches && stepAction.inputType === this.currentStepType) {
16
- let ret = stepAction.function(docSet, allNodes, nodeLookup, result, queryStep, matches);
17
-
18
- if (matches[stepAction.predicateCapture]) {
19
- ret = doPredicate(docSet, ret, matches[stepAction.predicateCapture]);
20
- }
21
- this.currentStepType = stepAction.outputType;
22
- return ret;
23
- }
24
- }
25
- return { errors: `Unable to match step ${queryStep}` };
26
- }
27
-
28
- parse1(docSet, allNodes, nodeLookup, result, queryArray) {
29
- if (queryArray.length > 0) {
30
- const stepResult = this.doStep(docSet, allNodes, nodeLookup, result, queryArray[0]);
31
-
32
- if (stepResult.errors || stepResult.data.length === 0) {
33
- return stepResult;
34
- } else {
35
- return this.parse1(docSet, allNodes, nodeLookup, stepResult, queryArray.slice(1));
36
- }
37
- } else {
38
- return result;
39
- }
40
- }
41
-
42
- queryArray(qs) {
43
- const ret = [];
44
-
45
- for (const s of qs.split('/')) {
46
- ret.push(s);
47
- }
48
- return ret;
49
- }
50
-
51
- indexNodes(docSet, nodes) {
52
- const ret = new Map();
53
-
54
- for (const [n, node] of nodes.entries()) {
55
- const nodeId = docSet.unsuccinctifyScopes(node.bs)[0][2].split('/')[1];
56
- ret.set(nodeId, n);
57
- }
58
- return ret;
59
- }
60
-
61
- doc() {
62
- return '** Steps **\n\n' +
63
- stepActions
64
- .map(sa => sa.doc)
65
- .map(d => `* ${d.title} *\n${d.syntax}\n${d.description}`)
66
- .join('\n\n') +
67
- '** Predicate Operators **\n\n' +
68
- Object.values(expressions)
69
- .filter(e => e.doc)
70
- .map(e => `${e.doc.operator}(${e.doc.args.map(a => '<' + a + '>').join(', ')}) => ${e.doc.result}\n${e.doc.description}`)
71
- .join('\n\n');
72
- }
73
-
74
- parse(docSet, nodes, queryString) {
75
- // console.log(`\n===> ${queryString}\n`);
76
- const result = this.parse1(
77
- docSet,
78
- nodes,
79
- this.indexNodes(docSet, nodes),
80
- { data: nodes },
81
- this.queryArray(queryString),
82
- );
83
-
84
- if (result.data) {
85
- switch (this.currentStepType) {
86
- case 'nodes':
87
- result.data = result.data.map(n => ({ id: docSet.unsuccinctifyScopes(n.bs)[0][2].split('/')[1] }));
88
- }
89
- }
90
-
91
- const ret = JSON.stringify(result, null, 2);
92
- // console.log(`${ret}\n`);
93
- return ret;
94
- }
95
- }
96
-
97
- module.exports = Tribos;
@@ -1,556 +0,0 @@
1
- const xre = require('xregexp');
2
-
3
- const aggregateFunctions = {
4
- equals: (docSet, node, a, b) => a === b,
5
- notEqual: (docSet, node, a, b) => a !== b,
6
- and: (docSet, node, ...args) => args.filter(a => !a).length === 0,
7
- or: (docSet, node, ...args) => args.filter(a => a).length > 0,
8
- not: (docSet, node, a) => !a,
9
- idRef: (docSet, node) => docSet.unsuccinctifyScopes(node.bs)[0][2].split('/')[1],
10
- parentIdRef: (docSet, node) => docSet.unsuccinctifyScopes(node.is).filter(s => s[2].startsWith('tTreeParent'))[0][2].split('/')[1],
11
- nChildren: (docSet, node) => docSet.unsuccinctifyScopes(node.is).filter(s => s[2].startsWith('tTreeChild')).length,
12
- contentRef: (docSet, node, label) => {
13
- const labelIG = docSet.sequenceItemsByScopes([node], ['tTreeContent/'], false)
14
- .filter(ig => {
15
- const key = ig[0].filter(s => s.startsWith('tTreeContent'))[0].split('/')[1];
16
- return key === label;
17
- });
18
- return labelIG[0] ?
19
- labelIG[0][1].filter(i => i[0] === 'token').map(t => t[2]).join('') :
20
- '';
21
- },
22
- hasContent: (docSet, node, label) => {
23
- const labelIG = docSet.sequenceItemsByScopes([node], ['tTreeContent/'], false)
24
- .filter(ig => {
25
- const key = ig[0].filter(s => s.startsWith('tTreeContent'))[0].split('/')[1];
26
- return key === label;
27
- });
28
- return labelIG.length > 0;
29
- },
30
- concat: (docSet, node, ...args) => args.join(''),
31
- startsWith: (docSet, node, a, b) => a.startsWith(b),
32
- endsWith: (docSet, node, a, b) => a.endsWith(b),
33
- contains: (docSet, node, a, b) => a.includes(b),
34
- matches: (docSet, node, a, b) => xre.test(a, xre(b)),
35
- int: (docSet, node, str) => parseInt(str),
36
- string: (docSet, node, int) => `${int}`,
37
- left: (docSet, node, str, int) => str.substring(0, int),
38
- right: (docSet, node, str, int) => str.substring(str.length - int),
39
- length: (docSet, node, str) => str.length,
40
- indexOf: (docSet, node, a, b) => a.indexOf(b),
41
- add: (docSet, node, ...args) => args.reduce((x, y) => x + y),
42
- mul: (docSet, node, ...args) => args.reduce((x, y) => x * y),
43
- sub: (docSet, node, a, b) => a - b,
44
- div: (docSet, node, a, b) => Math.floor(a / b),
45
- mod: (docSet, node, a, b) => a % b,
46
- gt: (docSet, node, a, b) => a > b,
47
- lt: (docSet, node, a, b) => a < b,
48
- ge: (docSet, node, a, b) => a >= b,
49
- le: (docSet, node, a, b) => a <= b,
50
- };
51
-
52
- const parseFunctions = {
53
- quotedString: str => str.substring(1, str.length - 1),
54
- int: str => parseInt(str),
55
- true: () => true,
56
- false: () => false,
57
- };
58
-
59
- const splitArgs = str => {
60
- const ret = [[]];
61
- let pos = 0;
62
- let nParen = 0;
63
- let inQuote = false;
64
-
65
- while (str && pos < str.length) {
66
- switch (str[pos]) {
67
- case '\\':
68
- ret[ret.length - 1].push(str[pos]);
69
-
70
- if (str[pos + 1] ==='\'') {
71
- ret[ret.length - 1].push(str[pos + 1]);
72
- pos++;
73
- }
74
- break;
75
- case '\'':
76
- ret[ret.length - 1].push(str[pos]);
77
- inQuote = !inQuote;
78
- break;
79
- case '(':
80
- if (inQuote) {
81
- ret[ret.length - 1].push(str[pos]);
82
- } else {
83
- ret[ret.length - 1].push(str[pos]);
84
- nParen++;
85
- }
86
- break;
87
- case ')':
88
- if (inQuote) {
89
- ret[ret.length - 1].push(str[pos]);
90
- } else {
91
- ret[ret.length - 1].push(str[pos]);
92
- nParen--;
93
- }
94
- break;
95
- case ',':
96
- if (!inQuote && nParen === 0) {
97
- ret.push([]);
98
-
99
- while (str[pos + 1] === ' ') {
100
- pos++;
101
- }
102
- } else {
103
- ret[ret.length - 1].push(str[pos]);
104
- }
105
- break;
106
- default:
107
- ret[ret.length - 1].push(str[pos]);
108
- }
109
- pos++;
110
- }
111
- return ret.map(e => e.join(''));
112
- };
113
-
114
- const expressions = {
115
- expression: { oneOf: ['stringExpression', 'intExpression', 'booleanExpression'] },
116
- booleanExpression: { oneOf: ['booleanPrimitive', 'equals', 'notEqual', 'and', 'or', 'not', 'contains', 'startsWith', 'endsWith', 'matches', 'gt', 'lt', 'ge', 'le', 'hasContent'] },
117
- stringExpression: { oneOf: ['concat', 'left', 'right', 'string', 'idRef', 'parentIdRef', 'contentRef', 'stringPrimitive'] },
118
- intExpression: { oneOf: ['length', 'indexOf', 'int', 'nChildren', 'intPrimitive', 'add', 'sub', 'mul', 'div', 'mod'] },
119
- equals: {
120
- regex: xre('^==\\((.+)\\)$'),
121
- doc: {
122
- operator: '==',
123
- args: ['expression', 'expression'],
124
- result: 'boolean',
125
- description: 'Are the arguments strictly equal?',
126
- },
127
- argStructure: [['expression', [2, 2]]],
128
- },
129
- notEqual: {
130
- regex: xre('^!=\\((.+)\\)$'),
131
- doc: {
132
- operator: '!=',
133
- args: ['expression', 'expression'],
134
- result: 'boolean',
135
- description: 'Are the arguments not strictly equal?',
136
- },
137
- argStructure: [['expression', [2, 2]]],
138
- },
139
- and: {
140
- regex: xre('^and\\((.+)\\)$'),
141
- doc: {
142
- operator: 'and',
143
- args: ['boolean', 'boolean', '...'],
144
- result: 'boolean',
145
- description: 'Are all the arguments true?',
146
- },
147
- breakOn: false,
148
- argStructure: [['booleanExpression', [2, null]]],
149
- },
150
- or: {
151
- regex: xre('^or\\((.+)\\)$'),
152
- doc: {
153
- operator: 'or',
154
- args: ['boolean', 'boolean'],
155
- result: 'boolean',
156
- description: 'Are any arguments true?',
157
- },
158
- breakOn: true,
159
- argStructure: [['booleanExpression', [2, null]]],
160
- },
161
- concat: {
162
- regex: xre('^concat\\((.+)\\)$'),
163
- doc: {
164
- operator: 'concat',
165
- args: ['string', 'string', '...'],
166
- result: 'string',
167
- description: 'Concatenates string arguments',
168
- },
169
- argStructure: [['stringExpression', [2, null]]],
170
- },
171
- contentRef: {
172
- regex: xre('^content\\((.+)\\)$'),
173
- doc: {
174
- operator: 'content',
175
- args: ['string'],
176
- result: 'string',
177
- description: 'String value of the specified content for the node',
178
- },
179
- argStructure: [['stringExpression', [1, 1]]],
180
- },
181
- hasContent: {
182
- regex: xre('^hasContent\\((.+)\\)$'),
183
- doc: {
184
- operator: 'hasContent',
185
- args: ['string'],
186
- result: 'boolean',
187
- description: 'Does the node have this content?',
188
- },
189
- argStructure: [['stringExpression', [1, 1]]],
190
- },
191
- contains: {
192
- regex: xre('^contains\\((.+)\\)$'),
193
- doc: {
194
- operator: 'contains',
195
- args: ['string', 'string'],
196
- result: 'boolean',
197
- description: 'Does the first string contain the second string?',
198
- },
199
- argStructure: [['stringExpression', [2, 2]]],
200
- },
201
- startsWith: {
202
- regex: xre('^startsWith\\((.+)\\)$'),
203
- doc: {
204
- operator: 'startsWith',
205
- args: ['string', 'string'],
206
- result: 'boolean',
207
- description: 'Does the first string start with the second string?',
208
- },
209
- argStructure: [['stringExpression', [2, 2]]],
210
- },
211
- endsWith: {
212
- regex: xre('^endsWith\\((.+)\\)$'),
213
- doc: {
214
- operator: 'endsWith',
215
- args: ['string', 'string'],
216
- result: 'boolean',
217
- description: 'Does the first string end with the second string?',
218
- },
219
- argStructure: [['stringExpression', [2, 2]]],
220
- },
221
- matches: {
222
- regex: xre('^matches\\((.+)\\)$'),
223
- doc: {
224
- operator: 'matches',
225
- args: ['string', 'regex'],
226
- result: 'boolean',
227
- description: 'Does the first string match the regex in the second string?',
228
- },
229
- argStructure: [['stringExpression', [2, 2]]],
230
- },
231
- left: {
232
- regex: xre('^left\\((.+)\\)$'),
233
- doc: {
234
- operator: 'left',
235
- args: ['string', 'integer'],
236
- result: 'string',
237
- description: 'The first n characters of the string',
238
- },
239
- argStructure: [['stringExpression', [1, 1]], ['intExpression', [1, 1]]],
240
- },
241
- right: {
242
- regex: xre('^right\\((.+)\\)$'),
243
- doc: {
244
- operator: 'right',
245
- args: ['string', 'integer'],
246
- result: 'string',
247
- description: 'The last n characters of the string',
248
- },
249
- argStructure: [['stringExpression', [1, 1]], ['intExpression', [1, 1]]],
250
- },
251
- length: {
252
- regex: xre('^length\\((.+)\\)$'),
253
- doc: {
254
- operator: 'length',
255
- args: ['string'],
256
- result: 'integer',
257
- description: 'The number of characters in the string',
258
- },
259
- argStructure: [['stringExpression', [1, 1]]],
260
- },
261
- indexOf: {
262
- regex: xre('^indexOf\\((.+)\\)$'),
263
- doc: {
264
- operator: 'indexOf',
265
- args: ['string', 'string'],
266
- result: 'number',
267
- description: 'The integer position at which the second string starts in the first string',
268
- },
269
- argStructure: [['stringExpression', [2, 2]]],
270
- },
271
- not: {
272
- regex: xre('^not\\((.+)\\)$'),
273
- doc: {
274
- operator: 'not',
275
- args: ['boolean'],
276
- result: 'boolean',
277
- description: 'The inverse boolean value of the argument',
278
- },
279
- argStructure: [['booleanExpression', [1, 1]]],
280
- },
281
- int: {
282
- regex: xre('^int\\((.+)\\)$'),
283
- doc: {
284
- operator: 'int',
285
- args: ['string'],
286
- result: 'integer',
287
- description: 'The integer value of the string',
288
- },
289
- argStructure: [['stringExpression', [1, 1]]],
290
- },
291
- string: {
292
- regex: xre('^string\\((.+)\\)$'),
293
- doc: {
294
- operator: 'string',
295
- args: ['integer'],
296
- result: 'string',
297
- description: 'The string value of the integer',
298
- },
299
- argStructure: [['intExpression', [1, 1]]],
300
- },
301
- idRef: {
302
- regex: xre('^id$'),
303
- doc: {
304
- operator: 'id',
305
- args: [],
306
- result: 'string',
307
- description: 'The node ID',
308
- },
309
- argStructure: [],
310
- },
311
- parentIdRef: {
312
- regex: xre('^parentId$'),
313
- doc: {
314
- operator: 'parentId',
315
- args: [],
316
- result: 'string',
317
- description: 'The node\'s parent ID',
318
- },
319
- argStructure: [],
320
- },
321
- nChildren: {
322
- regex: xre('^nChildren$'),
323
- doc: {
324
- operator: 'nChildren',
325
- args: [],
326
- result: 'int',
327
- description: 'The number of children of the node',
328
- },
329
- argStructure: [],
330
- },
331
- add: {
332
- regex: xre('^add\\((.+)\\)$'),
333
- doc: {
334
- operator: 'add',
335
- args: ['integer', '...'],
336
- result: 'integer',
337
- description: 'The numeric sum of the arguments',
338
- },
339
- argStructure: [['intExpression', [2, null]]],
340
- },
341
- mul: {
342
- regex: xre('^mul\\((.+)\\)$'),
343
- doc: {
344
- operator: 'mul',
345
- args: ['integer', '...'],
346
- result: 'integer',
347
- description: 'The numeric product of the arguments',
348
- },
349
- argStructure: [['intExpression', [2, null]]],
350
- },
351
- sub: {
352
- regex: xre('^sub\\((.+)\\)$'),
353
- doc: {
354
- operator: 'sub',
355
- args: ['integer', 'integer'],
356
- result: 'integer',
357
- description: 'The first integer minus the second',
358
- },
359
- argStructure: [['intExpression', [2, 2]]],
360
- },
361
- div: {
362
- regex: xre('^div\\((.+)\\)$'),
363
- doc: {
364
- operator: 'div',
365
- args: ['integer', 'integer'],
366
- result: 'integer',
367
- description: 'The first integer divided by the second',
368
- },
369
- argStructure: [['intExpression', [2, 2]]],
370
- },
371
- mod: {
372
- regex: xre('^mod\\((.+)\\)$'),
373
- doc: {
374
- operator: 'mod',
375
- args: ['integer', 'integer'],
376
- result: 'integer',
377
- description: 'The modulus of the first integer when divided by the second',
378
- },
379
- argStructure: [['intExpression', [2, 2]]],
380
- },
381
- gt: {
382
- regex: xre('^>\\((.+)\\)$'),
383
- doc: {
384
- operator: '>',
385
- args: ['integer', 'integer'],
386
- result: 'boolean',
387
- description: 'Is the first integer numerically greater than the second?',
388
- },
389
- argStructure: [['intExpression', [2, 2]]],
390
- },
391
- lt: {
392
- regex: xre('^<\\((.+)\\)$'),
393
- doc: {
394
- operator: '<',
395
- args: ['integer', 'integer'],
396
- result: 'boolean',
397
- description: 'Is the first integer numerically less than the second?',
398
- },
399
- argStructure: [['intExpression', [2, 2]]],
400
- },
401
- ge: {
402
- regex: xre('^>=\\((.+)\\)$'),
403
- doc: {
404
- operator: '>=',
405
- args: ['integer', 'integer'],
406
- result: 'boolean',
407
- description: 'Is the first integer numerically greater than or equal to the second?',
408
- },
409
- argStructure: [['intExpression', [2, 2]]],
410
- },
411
- le: {
412
- regex: xre('^<=\\((.+)\\)$'),
413
- doc: {
414
- operator: '<=',
415
- args: ['integer', 'integer'],
416
- result: 'boolean',
417
- description: 'Is the first integer numerically less than or equal to the second?',
418
- },
419
- argStructure: [['intExpression', [2, 2]]],
420
- },
421
- stringPrimitive: {
422
- regex: xre('^(\'([^\']|\\\\\')*\')$'),
423
- parseFunctions: [null, 'quotedString'],
424
- },
425
- intPrimitive: {
426
- regex: xre('^(-?[0-9]+)$'),
427
- parseFunctions: [null, 'int'],
428
- },
429
- booleanPrimitive: {
430
- regex: xre('^(true)|(false)$'),
431
- parseFunctions: [null, 'true', 'false'],
432
- },
433
- };
434
-
435
- const parseRegexExpression = (docSet, node, predicateString, expressionId, matches) => {
436
- // console.log(`parseRegexExpression ${predicateString} ${expressionId} ${matches}`);
437
- const expressionRecord = expressions[expressionId];
438
-
439
- if (!expressionRecord) {
440
- throw new Error(`Unknown expression ${expressionId} for predicate ${predicateString}`);
441
- }
442
-
443
- const nExpectedArgs = structure => [
444
- structure.map(a => a[1][0]).reduce((a, b) => a + b),
445
- structure.filter(a => a[1][1] === null).length > 0,
446
- ];
447
-
448
- if (expressionRecord.parseFunctions) {
449
- let found = false;
450
-
451
- for (const [n, parseFunction] of expressionRecord.parseFunctions.entries()) {
452
- if (!parseFunction || !matches[n]) {
453
- continue;
454
- }
455
- found = true;
456
- return { data: parseFunctions[parseFunction](matches[n]) };
457
- }
458
-
459
- if (!found) {
460
- return { errors: `Could not parse predicate ${predicateString}` };
461
- }
462
- } else {
463
- const argRecords = splitArgs(matches[1]);
464
- const argStructure = expressionRecord.argStructure;
465
- const argResults = [];
466
-
467
- if (argStructure.length > 0) {
468
- const nExpected = nExpectedArgs(argStructure);
469
-
470
- if (argRecords.length < nExpected[0]) {
471
- return { errors: `Expected at least ${nExpected[0]} args for '${expressionId}', found ${argRecords.length}` };
472
- }
473
-
474
- if (!nExpected[1] && argRecords.length > nExpected[0]) {
475
- return { errors: `Expected at most ${nExpected[0]} args for '${expressionId}', found ${argRecords.length}` };
476
- }
477
-
478
- let argRecordN = 0;
479
- let argStructureN = 0;
480
- let nOccs = 0;
481
-
482
- while (argRecordN < argRecords.length) {
483
- const argRecord = argRecords[argRecordN];
484
- const argResult = parseExpression(docSet, node, argRecord, argStructure[argStructureN][0]);
485
-
486
- if ('breakOn' in expressionRecord && !argRecord.errors && argResult.data === expressionRecord.breakOn) {
487
- return argResult;
488
- }
489
- argResults.push(argResult);
490
- argRecordN++;
491
- nOccs++;
492
-
493
- if (argStructure[argStructureN][1][1] && nOccs >= argStructure[argStructureN][1][1]) {
494
- argStructureN++;
495
- nOccs = 0;
496
- }
497
- }
498
- }
499
-
500
- if (argResults.filter(ar => ar.errors).length === 0) {
501
- // console.log(expressionId);
502
- const args = argResults.map(ar => ar.data);
503
- const aggregated = aggregateFunctions[expressionId](docSet, node, ...args);
504
- // console.log('aggregated', expressionId, argRecords, aggregated);
505
- return { data: aggregated };
506
- }
507
- return { errors: `Could not parse arguments to ${expressionId}: ${argRecords.filter(ar => ar.errors).map(ar => ar.errors).join('; ')}` };
508
- }
509
- };
510
-
511
- const parseExpression = (docSet, node, predicate, expressionId) => {
512
- // console.log(`parseExpression ${predicate}, ${expressionId}`);
513
- const expressionRecord = expressions[expressionId];
514
-
515
- if (!expressionRecord) {
516
- throw new Error(`Unknown expression ${expressionId} for predicate ${predicate}`);
517
- }
518
-
519
- if (expressionRecord.oneOf) {
520
- let errors = null;
521
-
522
- for (const option of expressionRecord.oneOf) {
523
- const optionResult = parseExpression(docSet, node, predicate, option);
524
-
525
- if (!optionResult.errors) {
526
- return optionResult;
527
- } else if (!errors || (optionResult.errors.length < errors.length)) {
528
- errors = optionResult.errors;
529
- }
530
- }
531
- return { errors: errors };
532
- } else {
533
- const matches = xre.exec(predicate, expressionRecord.regex);
534
-
535
- if (matches) {
536
- const reResult = parseRegexExpression(docSet, node, predicate, expressionId, matches);
537
- return reResult;
538
- } else {
539
- return { errors: `Could not match ${predicate}` };
540
- }
541
- }
542
- };
543
-
544
- const doPredicate = (docSet, result, predicateString) => ({
545
- data: result.data.filter(node => {
546
- const nodeResult = parseExpression(docSet, node, predicateString, 'booleanExpression');
547
-
548
- // console.log();
549
- if (nodeResult.errors) {
550
- throw new Error(`Predicate - ${nodeResult.errors}`);
551
- }
552
- return nodeResult.data;
553
- }),
554
- });
555
-
556
- module.exports = { expressions, doPredicate };