proskomma-core 0.9.18 → 0.9.20

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 (124) hide show
  1. package/dist/bundle.js +1 -0
  2. package/dist/index.cjs +1 -0
  3. package/dist/module.mjs +1 -0
  4. package/package.json +26 -34
  5. package/dist/index.js +0 -8
  6. package/dist/index.js.LICENSE.txt +0 -23
  7. package/informations/meeting_01_march_2023.md +0 -38
  8. package/src/graph/index.cjs +0 -201
  9. package/src/graph/lib/do_cv.cjs +0 -249
  10. package/src/graph/lib/dump.cjs +0 -40
  11. package/src/graph/lib/remake_blocks.cjs +0 -57
  12. package/src/graph/lib/sequence_chars.cjs +0 -84
  13. package/src/graph/lib/sort.cjs +0 -39
  14. package/src/graph/lib/tribos.cjs +0 -97
  15. package/src/graph/lib/tribos_expression.cjs +0 -556
  16. package/src/graph/lib/tribos_ohm_UNUSED.cjs +0 -37
  17. package/src/graph/lib/tribos_step.cjs +0 -434
  18. package/src/graph/mutations/add.cjs +0 -91
  19. package/src/graph/mutations/delete.cjs +0 -61
  20. package/src/graph/mutations/index.cjs +0 -54
  21. package/src/graph/mutations/rehash.cjs +0 -17
  22. package/src/graph/mutations/tags.cjs +0 -120
  23. package/src/graph/mutations/update.cjs +0 -210
  24. package/src/graph/mutations/versification.cjs +0 -96
  25. package/src/graph/queries/block.cjs +0 -228
  26. package/src/graph/queries/cIndex.cjs +0 -87
  27. package/src/graph/queries/cell.cjs +0 -42
  28. package/src/graph/queries/cv.cjs +0 -19
  29. package/src/graph/queries/cvBook.cjs +0 -16
  30. package/src/graph/queries/cvChapter.cjs +0 -16
  31. package/src/graph/queries/cvIndex.cjs +0 -47
  32. package/src/graph/queries/cvNavigation.cjs +0 -116
  33. package/src/graph/queries/cvVerseElement.cjs +0 -84
  34. package/src/graph/queries/cvVerses.cjs +0 -14
  35. package/src/graph/queries/doc_set.cjs +0 -220
  36. package/src/graph/queries/document.cjs +0 -555
  37. package/src/graph/queries/idParts.cjs +0 -30
  38. package/src/graph/queries/index.cjs +0 -151
  39. package/src/graph/queries/inputBlockSpec.cjs +0 -17
  40. package/src/graph/queries/inputItemObject.cjs +0 -12
  41. package/src/graph/queries/input_att_spec.cjs +0 -14
  42. package/src/graph/queries/input_key_matches.cjs +0 -11
  43. package/src/graph/queries/input_key_value.cjs +0 -11
  44. package/src/graph/queries/input_key_values.cjs +0 -11
  45. package/src/graph/queries/input_selector_spec.cjs +0 -19
  46. package/src/graph/queries/item.cjs +0 -71
  47. package/src/graph/queries/itemGroup.cjs +0 -75
  48. package/src/graph/queries/key_value.cjs +0 -18
  49. package/src/graph/queries/kv_entry.cjs +0 -21
  50. package/src/graph/queries/kv_sequence.cjs +0 -151
  51. package/src/graph/queries/node.cjs +0 -44
  52. package/src/graph/queries/orig.cjs +0 -11
  53. package/src/graph/queries/regex_index.cjs +0 -18
  54. package/src/graph/queries/row_equals_spec.cjs +0 -11
  55. package/src/graph/queries/row_match_spec.cjs +0 -11
  56. package/src/graph/queries/selector_spec.cjs +0 -29
  57. package/src/graph/queries/sequence.cjs +0 -314
  58. package/src/graph/queries/table_sequence.cjs +0 -192
  59. package/src/graph/queries/tree_sequence.cjs +0 -58
  60. package/src/graph/queries/verseNumber.cjs +0 -44
  61. package/src/graph/queries/verseRange.cjs +0 -11
  62. package/src/graph/queries/versification.cjs +0 -25
  63. package/src/index.cjs +0 -583
  64. package/src/model/doc_set.cjs +0 -389
  65. package/src/model/doc_set_helpers/block.cjs +0 -232
  66. package/src/model/doc_set_helpers/enum.cjs +0 -87
  67. package/src/model/doc_set_helpers/item.cjs +0 -198
  68. package/src/model/doc_set_helpers/rehash.cjs +0 -53
  69. package/src/model/doc_set_helpers/selectors.cjs +0 -58
  70. package/src/model/doc_set_helpers/serialize.cjs +0 -22
  71. package/src/model/doc_set_helpers/unsuccinctify.cjs +0 -288
  72. package/src/model/doc_set_helpers/update.cjs +0 -290
  73. package/src/model/document.cjs +0 -369
  74. package/src/model/document_helpers/blocks.cjs +0 -135
  75. package/src/model/document_helpers/chapter_verse.cjs +0 -291
  76. package/src/model/document_helpers/pre_enums.cjs +0 -67
  77. package/src/model/document_helpers/sequences.cjs +0 -205
  78. package/src/model/document_helpers/serialize_succinct.cjs +0 -55
  79. package/src/model/document_helpers/succinct_filter.cjs +0 -102
  80. package/src/model/versifications/eng_vrs.cjs +0 -455
  81. package/src/model/versifications/index.cjs +0 -38
  82. package/src/model/versifications/lxx_vrs.cjs +0 -950
  83. package/src/model/versifications/org_vrs.cjs +0 -155
  84. package/src/model/versifications/rsc_vrs.cjs +0 -342
  85. package/src/model/versifications/rso_vrs.cjs +0 -541
  86. package/src/model/versifications/vul_vrs.cjs +0 -835
  87. package/src/parser/index.cjs +0 -504
  88. package/src/parser/lexers/index.cjs +0 -11
  89. package/src/parser/lexers/lexingRegexes.cjs +0 -45
  90. package/src/parser/lexers/nodes.cjs +0 -123
  91. package/src/parser/lexers/object_for_fragment.cjs +0 -123
  92. package/src/parser/lexers/tsv.cjs +0 -45
  93. package/src/parser/lexers/usfm.cjs +0 -17
  94. package/src/parser/lexers/usx/index.cjs +0 -7
  95. package/src/parser/lexers/usx/usx_lexer.cjs +0 -321
  96. package/src/parser/lib/tokenize.cjs +0 -37
  97. package/src/parser/model/index.cjs +0 -637
  98. package/src/parser/parser_specs.cjs +0 -781
  99. package/src/pipelines/perf2x/index.cjs +0 -7
  100. package/src/pipelines/perf2x/perf2PkJsonPipeline.json +0 -41
  101. package/src/pipelines/perf2x/perf2usfmPipeline.json +0 -65
  102. package/src/transforms/calculateUsfmChapterPositions.cjs +0 -106
  103. package/src/transforms/index.cjs +0 -9
  104. package/src/transforms/perf2PkJson.cjs +0 -534
  105. package/src/transforms/perf2usfm.cjs +0 -294
  106. package/src/util/byteArray.cjs +0 -251
  107. package/src/util/canons.cjs +0 -117
  108. package/src/util/enums.cjs +0 -41
  109. package/src/util/generateId.cjs +0 -6
  110. package/src/util/graftDefs.cjs +0 -15
  111. package/src/util/index.cjs +0 -29
  112. package/src/util/inspectSuccinct.cjs +0 -59
  113. package/src/util/itemDefs.cjs +0 -33
  114. package/src/util/parserConstantDefs.cjs +0 -30
  115. package/src/util/scopeDefs.cjs +0 -173
  116. package/src/util/scriptlike/blocksSpec.cjs +0 -192
  117. package/src/util/scriptlike/dodson_lexicon.xsl +0 -19
  118. package/src/util/scriptlike/dodson_lexicon_to_entries.cjs +0 -85
  119. package/src/util/scriptlike/open_scriptures_hebrew_lexicon.xsl +0 -28
  120. package/src/util/scriptlike/open_scriptures_hebrew_lexicon_to_entries.cjs +0 -85
  121. package/src/util/succinct.cjs +0 -159
  122. package/src/util/tags.cjs +0 -28
  123. package/src/util/tokenDefs.cjs +0 -27
  124. 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 };