imerss-bioinfo 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -0
- package/build.js +196 -0
- package/docs/css/imerss-viz-all.css +1227 -0
- package/docs/css/imerss-viz-wp-overrides.css +70 -0
- package/docs/css/pepiowelh.css +76 -0
- package/docs/css/xetthecum-external.css +47 -0
- package/docs/css/xetthecum-shared.css +80 -0
- package/docs/css/xetthecum.css +526 -0
- package/docs/js/imerss-viz-all.js +58 -0
- package/docs/js/imerss-viz-all.js.map +1 -0
- package/docs/js/jquery.js +10881 -0
- package/index.html +81 -0
- package/index.js +7 -0
- package/indexWithJustMap.html +92 -0
- package/indexWithMap.html +79 -0
- package/indexWithMapHoweSound.html +91 -0
- package/indexWithMapPepiowelh.html +119 -0
- package/indexWithMapValdes.html +90 -0
- package/indexWithMapXetthecum.html +90 -0
- package/package.json +50 -0
- package/src/WoRMS/taxonAPI.js +13 -0
- package/src/arphify.js +662 -0
- package/src/assignNames.js +103 -0
- package/src/auxBuild/restoreJQuery.js +1 -0
- package/src/buildSource/Comprehensive Lists.html +42 -0
- package/src/buildSource/Data Paper Part I Visualisation.html +50 -0
- package/src/buildSource/Galiano Life List.html +43 -0
- package/src/buildSource/Metchosin/index.html +22 -0
- package/src/buildSource/Pe'pi'ow'elh.html +72 -0
- package/src/buildSource/Squamish Life List.html +48 -0
- package/src/buildSource/Valdes Island Biodiversity.html +64 -0
- package/src/buildSource/Xetthecum.html +40 -0
- package/src/buildSource/dataPaperSunburstAndMap.html +30 -0
- package/src/buildSource/index.html +224 -0
- package/src/client/css/imerss-viz-wp-overrides.css +70 -0
- package/src/client/css/imerss-viz.css +531 -0
- package/src/client/css/pepiowelh.css +76 -0
- package/src/client/css/xetthecum-external.css +47 -0
- package/src/client/css/xetthecum-shared.css +80 -0
- package/src/client/css/xetthecum.css +526 -0
- package/src/client/html/imerss-viz-map-only.html +75 -0
- package/src/client/html/imerss-viz-map-pepi.html +77 -0
- package/src/client/html/imerss-viz-map-xetthecum.html +90 -0
- package/src/client/html/imerss-viz-map.html +75 -0
- package/src/client/html/imerss-viz.html +58 -0
- package/src/client/html/importing Xetthecum patterns.txt +10 -0
- package/src/client/html/xetthecum-patterns.html +27 -0
- package/src/client/img/Animalia_2.svg +1 -0
- package/src/client/img/Animalia_Annelida.svg +655 -0
- package/src/client/img/Animalia_Chaetognatha.svg +72 -0
- package/src/client/img/Animalia_Cnidaria.svg +173 -0
- package/src/client/img/Animalia_Ctenophora.svg +298 -0
- package/src/client/img/Animalia_Nemertea.svg +54 -0
- package/src/client/img/Animalia_Phoronida.svg +271 -0
- package/src/client/img/Animalia_Platyhelminthes.svg +58 -0
- package/src/client/img/Animalia_Porifera.svg +220 -0
- package/src/client/img/Animalia_Sipuncula.svg +155 -0
- package/src/client/img/Arachnoidiscus_schmidtii_web_1-2-scaled.webp +0 -0
- package/src/client/img/Arrow-down.svg +11 -0
- package/src/client/img/Arrow-up.svg +6 -0
- package/src/client/img/Chromista.svg +1 -0
- package/src/client/img/Pepiowelh/BlackNoWe2-wb-bb.png +0 -0
- package/src/client/img/Pepiowelh/BlackNoWe2-wb.png +0 -0
- package/src/client/img/Pepiowelh/BlackNoWe2.png +0 -0
- package/src/client/img/Pepiowelh/Ecocultural Mapping Banner.svg +1 -0
- package/src/client/img/Plankton.jpg +0 -0
- package/src/client/img/Plantae.svg +1 -0
- package/src/client/img/Plantae_2.svg +1 -0
- package/src/client/img/Protista.svg +1 -0
- package/src/client/img/Valdes/Valdes Island Conservancy.jpg +0 -0
- package/src/client/img/Xetthecum/Agricultural.jpg +0 -0
- package/src/client/img/Xetthecum/Anthropogenic_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Broad_Leaf.jpg +0 -0
- package/src/client/img/Xetthecum/Caves.jpg +0 -0
- package/src/client/img/Xetthecum/Coastal_Bluffs.jpg +0 -0
- package/src/client/img/Xetthecum/Conifer_Pole_Sapling.jpg +0 -0
- package/src/client/img/Xetthecum/Developed.jpg +0 -0
- package/src/client/img/Xetthecum/Dock.jpg +0 -0
- package/src/client/img/Xetthecum/Eelgrass.jpg +0 -0
- package/src/client/img/Xetthecum/Forests_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Freshwater_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Greig_Creek.jpg +0 -0
- package/src/client/img/Xetthecum/Intertidal.jpg +0 -0
- package/src/client/img/Xetthecum/Laughlin_Lake.jpg +0 -0
- package/src/client/img/Xetthecum/Marine_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Mature_Conifer_Forest.jpg +0 -0
- package/src/client/img/Xetthecum/Porlier_Pass_Road.jpg +0 -0
- package/src/client/img/Xetthecum/Riparian.jpg +0 -0
- package/src/client/img/Xetthecum/Rural.jpg +0 -0
- package/src/client/img/Xetthecum/Subtidal.jpg +0 -0
- package/src/client/img/Xetthecum/Wetland.jpg +0 -0
- package/src/client/img/Xetthecum/Woodland.jpg +0 -0
- package/src/client/img/Xetthecum/Woodland_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Xetthecum.jpg +0 -0
- package/src/client/img/Xetthecum/Young_Conifer_Forest.jpg +0 -0
- package/src/client/img/Xetthecum/Young_Mixed_Forest.jpg +0 -0
- package/src/client/img/Xetthecum/food.svg +38 -0
- package/src/client/img/Xetthecum/indicator.svg +52 -0
- package/src/client/img/Xetthecum/material.svg +186 -0
- package/src/client/img/Xetthecum/medicinal.svg +62 -0
- package/src/client/img/Xetthecum/missing-value.svg +3 -0
- package/src/client/img/Xetthecum/spiritual.svg +13 -0
- package/src/client/img/Xetthecum/trade.svg +74 -0
- package/src/client/img/audio.svg +5 -0
- package/src/client/img/external-link.svg +3 -0
- package/src/client/img/selected-eye.svg +4 -0
- package/src/client/img/selected-tick.svg +3 -0
- package/src/client/img/thumbs/BCLeps.jpg +0 -0
- package/src/client/img/thumbs/Checklist.jpg +0 -0
- package/src/client/img/thumbs/Data-Paper-Figma.jpg +0 -0
- package/src/client/img/thumbs/Galiano-Data-Paper.jpg +0 -0
- package/src/client/img/thumbs/Galiano.jpg +0 -0
- package/src/client/img/thumbs/Maxwell.jpg +0 -0
- package/src/client/img/thumbs/Squamish.jpg +0 -0
- package/src/client/img/thumbs/Valdes.jpg +0 -0
- package/src/client/img/thumbs/Xetthecum.jpg +0 -0
- package/src/client/img/up-arrow.svg +4 -0
- package/src/client/js/autocomplete.js +53 -0
- package/src/client/js/checklist.js +179 -0
- package/src/client/js/colour.js +139 -0
- package/src/client/js/datasetControls.js +212 -0
- package/src/client/js/imerss-viz.js +1397 -0
- package/src/client/js/leafletMap.js +357 -0
- package/src/client/js/leafletMapWithGrid.js +337 -0
- package/src/client/js/leafletMapWithRegions.js +381 -0
- package/src/client/js/renderSVG.js +108 -0
- package/src/client/js/tabs.js +53 -0
- package/src/client/js/xetthecum.js +106 -0
- package/src/client/json/emptyPhyloMap.json +1 -0
- package/src/client/json/kingdomPhyloMap.json +17 -0
- package/src/client/json/phyloMap.json +58 -0
- package/src/compare.js +97 -0
- package/src/compilecsv.js +47 -0
- package/src/dataProcessing/LZ4.js +27 -0
- package/src/dataProcessing/coordinatePatch.js +151 -0
- package/src/dataProcessing/readCSV.js +107 -0
- package/src/dataProcessing/readCSVwithMap.js +90 -0
- package/src/dataProcessing/readCSVwithoutMap.js +25 -0
- package/src/dataProcessing/readJSON.js +23 -0
- package/src/dataProcessing/sqlite.js +174 -0
- package/src/dataProcessing/summarise.js +122 -0
- package/src/dataProcessing/taxonScrape.js +14 -0
- package/src/dataProcessing/worker.js +31 -0
- package/src/dataProcessing/writeCSV.js +34 -0
- package/src/dataProcessing/writeJSON.js +15 -0
- package/src/dbtaxa.js +96 -0
- package/src/deAuthorise.js +48 -0
- package/src/deqgis.js +148 -0
- package/src/expressions/expr.js +65 -0
- package/src/expressions/jsep.js +925 -0
- package/src/filterFirst.js +51 -0
- package/src/geom/geoJSON.js +121 -0
- package/src/iNaturalist/examples/api.inaturalist.org-v1-taxa!q=Acmispon americanus americanus.json +200 -0
- package/src/iNaturalist/examples/api.inaturalist.org-v1-taxa!q=Flabellina japonica.json +61 -0
- package/src/iNaturalist/examples/www.inaturalist.org-taxa-877359.json +132 -0
- package/src/iNaturalist/iNatUrls.js +17 -0
- package/src/iNaturalist/obsAPI.js +150 -0
- package/src/iNaturalist/taxonAPI.js +460 -0
- package/src/inatObs.js +120 -0
- package/src/inattify.js +123 -0
- package/src/intersect.js +80 -0
- package/src/intersectFilter.js +48 -0
- package/src/landlocked.js +137 -0
- package/src/lib/jquery.binarytransport.js +51 -0
- package/src/lib/lz4-commentary.txt +9 -0
- package/src/lib/lz4.js +73 -0
- package/src/lib/point-in-polygon.js +36 -0
- package/src/lz4.js +40 -0
- package/src/marmalise.js +333 -0
- package/src/materialise.js +68 -0
- package/src/reintegrate.js +71 -0
- package/src/taxonomise.js +615 -0
- package/src/unscrewGBIF.js +44 -0
- package/src/utils/dataSource.js +173 -0
- package/src/utils/settleStructure.js +62 -0
- package/src/utils/utils.js +92 -0
- package/src/viz/plethify.js +39 -0
- package/src/wormify.js +154 -0
- package/src/xetthecum/xetthecumFilters.js +126 -0
- package/test/testDataSource.js +182 -0
- package/test/testiNatObsSource.js +38 -0
- package/test/testiNatSource.js +50 -0
|
@@ -0,0 +1,925 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
|
|
3
|
+
// This file was taken from revision 25fcb53 of https://github.com/EricSmekens/jsep/blob/master/src/jsep.js
|
|
4
|
+
// since we need the fix which axed "LogicalExpression" but need to defeat the insufferable ES6 modules crap
|
|
5
|
+
// which prevents it from loading. The "export" keyword was removed from the top of the file and a standard
|
|
6
|
+
// CJS export was put at the bottom. Probably when jsep 0.5.0 is released we can update to it
|
|
7
|
+
|
|
8
|
+
// JavaScript Expression Parser (JSEP) <%= version %>
|
|
9
|
+
// JSEP may be freely distributed under the MIT License
|
|
10
|
+
// https://ericsmekens.github.io/jsep/
|
|
11
|
+
class Jsep {
|
|
12
|
+
/**
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
static get version() {
|
|
16
|
+
// To be filled in by the template
|
|
17
|
+
return '<%= version %>';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
static toString() {
|
|
24
|
+
return 'JavaScript Expression Parser (JSEP) v' + Jsep.version;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// ==================== CONFIG ================================
|
|
28
|
+
/**
|
|
29
|
+
* @method addUnaryOp
|
|
30
|
+
* @param {string} op_name The name of the unary op to add
|
|
31
|
+
* @returns {Jsep}
|
|
32
|
+
*/
|
|
33
|
+
static addUnaryOp(op_name) {
|
|
34
|
+
Jsep.max_unop_len = Math.max(op_name.length, Jsep.max_unop_len);
|
|
35
|
+
Jsep.unary_ops[op_name] = 1;
|
|
36
|
+
return Jsep;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @method jsep.addBinaryOp
|
|
41
|
+
* @param {string} op_name The name of the binary op to add
|
|
42
|
+
* @param {number} precedence The precedence of the binary op (can be a float)
|
|
43
|
+
* @returns {Jsep}
|
|
44
|
+
*/
|
|
45
|
+
static addBinaryOp(op_name, precedence) {
|
|
46
|
+
Jsep.max_binop_len = Math.max(op_name.length, Jsep.max_binop_len);
|
|
47
|
+
Jsep.binary_ops[op_name] = precedence;
|
|
48
|
+
return Jsep;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @method addIdentifierChar
|
|
53
|
+
* @param {string} char The additional character to treat as a valid part of an identifier
|
|
54
|
+
* @returns {Jsep}
|
|
55
|
+
*/
|
|
56
|
+
static addIdentifierChar(char) {
|
|
57
|
+
Jsep.additional_identifier_chars.add(char);
|
|
58
|
+
return Jsep;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @method addLiteral
|
|
63
|
+
* @param {string} literal_name The name of the literal to add
|
|
64
|
+
* @param {*} literal_value The value of the literal
|
|
65
|
+
* @returns {Jsep}
|
|
66
|
+
*/
|
|
67
|
+
static addLiteral(literal_name, literal_value) {
|
|
68
|
+
Jsep.literals[literal_name] = literal_value;
|
|
69
|
+
return Jsep;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @method removeUnaryOp
|
|
74
|
+
* @param {string} op_name The name of the unary op to remove
|
|
75
|
+
* @returns {Jsep}
|
|
76
|
+
*/
|
|
77
|
+
static removeUnaryOp(op_name) {
|
|
78
|
+
delete Jsep.unary_ops[op_name];
|
|
79
|
+
if (op_name.length === Jsep.max_unop_len) {
|
|
80
|
+
Jsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);
|
|
81
|
+
}
|
|
82
|
+
return Jsep;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @method removeAllUnaryOps
|
|
87
|
+
* @returns {Jsep}
|
|
88
|
+
*/
|
|
89
|
+
static removeAllUnaryOps() {
|
|
90
|
+
Jsep.unary_ops = {};
|
|
91
|
+
Jsep.max_unop_len = 0;
|
|
92
|
+
|
|
93
|
+
return Jsep;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @method removeIdentifierChar
|
|
98
|
+
* @param {string} char The additional character to stop treating as a valid part of an identifier
|
|
99
|
+
* @returns {Jsep}
|
|
100
|
+
*/
|
|
101
|
+
static removeIdentifierChar(char) {
|
|
102
|
+
Jsep.additional_identifier_chars.delete(char);
|
|
103
|
+
return Jsep;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @method removeBinaryOp
|
|
108
|
+
* @param {string} op_name The name of the binary op to remove
|
|
109
|
+
* @returns {Jsep}
|
|
110
|
+
*/
|
|
111
|
+
static removeBinaryOp(op_name) {
|
|
112
|
+
delete Jsep.binary_ops[op_name];
|
|
113
|
+
|
|
114
|
+
if (op_name.length === Jsep.max_binop_len) {
|
|
115
|
+
Jsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return Jsep;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @method removeAllBinaryOps
|
|
123
|
+
* @returns {Jsep}
|
|
124
|
+
*/
|
|
125
|
+
static removeAllBinaryOps() {
|
|
126
|
+
Jsep.binary_ops = {};
|
|
127
|
+
Jsep.max_binop_len = 0;
|
|
128
|
+
|
|
129
|
+
return Jsep;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @method removeLiteral
|
|
134
|
+
* @param {string} literal_name The name of the literal to remove
|
|
135
|
+
* @returns {Jsep}
|
|
136
|
+
*/
|
|
137
|
+
static removeLiteral(literal_name) {
|
|
138
|
+
delete Jsep.literals[literal_name];
|
|
139
|
+
return Jsep;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @method removeAllLiterals
|
|
144
|
+
* @returns {Jsep}
|
|
145
|
+
*/
|
|
146
|
+
static removeAllLiterals() {
|
|
147
|
+
Jsep.literals = {};
|
|
148
|
+
|
|
149
|
+
return Jsep;
|
|
150
|
+
}
|
|
151
|
+
// ==================== END CONFIG ============================
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @returns {string}
|
|
156
|
+
*/
|
|
157
|
+
get char() {
|
|
158
|
+
return this.expr.charAt(this.index);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @returns {number}
|
|
163
|
+
*/
|
|
164
|
+
get code() {
|
|
165
|
+
return this.expr.charCodeAt(this.index);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @param {string} expr a string with the passed in express
|
|
171
|
+
* @returns Jsep
|
|
172
|
+
*/
|
|
173
|
+
constructor(expr) {
|
|
174
|
+
// `index` stores the character number we are currently at
|
|
175
|
+
// All of the gobbles below will modify `index` as we move along
|
|
176
|
+
this.expr = expr;
|
|
177
|
+
this.index = 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* static top-level parser
|
|
182
|
+
* @returns {jsep.Expression}
|
|
183
|
+
*/
|
|
184
|
+
static parse(expr) {
|
|
185
|
+
return (new Jsep(expr)).parse();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Get the longest key length of any object
|
|
190
|
+
* @param {object} obj
|
|
191
|
+
* @returns {number}
|
|
192
|
+
*/
|
|
193
|
+
static getMaxKeyLen(obj) {
|
|
194
|
+
return Math.max(0, ...Object.keys(obj).map(k => k.length));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* `ch` is a character code in the next three functions
|
|
199
|
+
* @param {number} ch
|
|
200
|
+
* @returns {boolean}
|
|
201
|
+
*/
|
|
202
|
+
static isDecimalDigit(ch) {
|
|
203
|
+
return (ch >= 48 && ch <= 57); // 0...9
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Returns the precedence of a binary operator or `0` if it isn't a binary operator. Can be float.
|
|
208
|
+
* @param {string} op_val
|
|
209
|
+
* @returns {number}
|
|
210
|
+
*/
|
|
211
|
+
static binaryPrecedence(op_val) {
|
|
212
|
+
return Jsep.binary_ops[op_val] || 0;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Looks for start of identifier
|
|
217
|
+
* @param {number} ch
|
|
218
|
+
* @returns {boolean}
|
|
219
|
+
*/
|
|
220
|
+
static isIdentifierStart(ch) {
|
|
221
|
+
return (ch >= 65 && ch <= 90) || // A...Z
|
|
222
|
+
(ch >= 97 && ch <= 122) || // a...z
|
|
223
|
+
(ch >= 128 && !Jsep.binary_ops[String.fromCharCode(ch)]) || // any non-ASCII that is not an operator
|
|
224
|
+
(Jsep.additional_identifier_chars.has(String.fromCharCode(ch))); // additional characters
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @param {number} ch
|
|
229
|
+
* @returns {boolean}
|
|
230
|
+
*/
|
|
231
|
+
static isIdentifierPart(ch) {
|
|
232
|
+
return Jsep.isIdentifierStart(ch) || Jsep.isDecimalDigit(ch);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* throw error at index of the expression
|
|
237
|
+
* @param {string} message
|
|
238
|
+
* @throws
|
|
239
|
+
*/
|
|
240
|
+
throwError(message) {
|
|
241
|
+
const error = new Error(message + ' at character ' + this.index);
|
|
242
|
+
error.index = this.index;
|
|
243
|
+
error.description = message;
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Push `index` up to the next non-space character
|
|
249
|
+
*/
|
|
250
|
+
gobbleSpaces() {
|
|
251
|
+
let ch = this.code;
|
|
252
|
+
// Whitespace
|
|
253
|
+
while (ch === Jsep.SPACE_CODE
|
|
254
|
+
|| ch === Jsep.TAB_CODE
|
|
255
|
+
|| ch === Jsep.LF_CODE
|
|
256
|
+
|| ch === Jsep.CR_CODE) {
|
|
257
|
+
ch = this.expr.charCodeAt(++this.index);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Top-level method to parse all expressions and returns compound or single node
|
|
263
|
+
* @returns {jsep.Expression}
|
|
264
|
+
*/
|
|
265
|
+
parse() {
|
|
266
|
+
const nodes = this.gobbleExpressions();
|
|
267
|
+
|
|
268
|
+
// If there's only one expression just try returning the expression
|
|
269
|
+
if (nodes.length === 1) {
|
|
270
|
+
return nodes[0];
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
return {
|
|
274
|
+
type: Jsep.COMPOUND,
|
|
275
|
+
body: nodes
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* top-level parser (but can be reused within as well)
|
|
282
|
+
* @param {number} [untilICode]
|
|
283
|
+
* @returns {jsep.Expression[]}
|
|
284
|
+
*/
|
|
285
|
+
gobbleExpressions(untilICode) {
|
|
286
|
+
let nodes = [], ch_i, node;
|
|
287
|
+
|
|
288
|
+
while (this.index < this.expr.length) {
|
|
289
|
+
ch_i = this.code;
|
|
290
|
+
|
|
291
|
+
// Expressions can be separated by semicolons, commas, or just inferred without any
|
|
292
|
+
// separators
|
|
293
|
+
if (ch_i === Jsep.SEMCOL_CODE || ch_i === Jsep.COMMA_CODE) {
|
|
294
|
+
this.index++; // ignore separators
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
// Try to gobble each expression individually
|
|
298
|
+
if (node = this.gobbleExpression()) {
|
|
299
|
+
nodes.push(node);
|
|
300
|
+
// If we weren't able to find a binary expression and are out of room, then
|
|
301
|
+
// the expression passed in probably has too much
|
|
302
|
+
}
|
|
303
|
+
else if (this.index < this.expr.length) {
|
|
304
|
+
if (ch_i === untilICode) {
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
this.throwError('Unexpected "' + this.char + '"');
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return nodes;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
//
|
|
316
|
+
/**
|
|
317
|
+
* The main parsing function. Much of this code is dedicated to ternary expressions
|
|
318
|
+
* @returns {?jsep.Expression}
|
|
319
|
+
*/
|
|
320
|
+
gobbleExpression() {
|
|
321
|
+
const test = this.gobbleBinaryExpression();
|
|
322
|
+
|
|
323
|
+
this.gobbleSpaces();
|
|
324
|
+
|
|
325
|
+
if (this.code === Jsep.QUMARK_CODE) {
|
|
326
|
+
// Ternary expression: test ? consequent : alternate
|
|
327
|
+
this.index++;
|
|
328
|
+
const consequent = this.gobbleExpression();
|
|
329
|
+
|
|
330
|
+
if (!consequent) {
|
|
331
|
+
this.throwError('Expected expression');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
this.gobbleSpaces();
|
|
335
|
+
|
|
336
|
+
if (this.code === Jsep.COLON_CODE) {
|
|
337
|
+
this.index++;
|
|
338
|
+
const alternate = this.gobbleExpression();
|
|
339
|
+
|
|
340
|
+
if (!alternate) {
|
|
341
|
+
this.throwError('Expected expression');
|
|
342
|
+
}
|
|
343
|
+
return {
|
|
344
|
+
type: Jsep.CONDITIONAL_EXP,
|
|
345
|
+
test,
|
|
346
|
+
consequent,
|
|
347
|
+
alternate
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
this.throwError('Expected :');
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
return test;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Search for the operation portion of the string (e.g. `+`, `===`)
|
|
361
|
+
* Start by taking the longest possible binary operations (3 characters: `===`, `!==`, `>>>`)
|
|
362
|
+
* and move down from 3 to 2 to 1 character until a matching binary operation is found
|
|
363
|
+
* then, return that binary operation
|
|
364
|
+
* @returns {string|boolean}
|
|
365
|
+
*/
|
|
366
|
+
gobbleBinaryOp() {
|
|
367
|
+
this.gobbleSpaces();
|
|
368
|
+
let to_check = this.expr.substr(this.index, Jsep.max_binop_len);
|
|
369
|
+
let tc_len = to_check.length;
|
|
370
|
+
|
|
371
|
+
while (tc_len > 0) {
|
|
372
|
+
// Don't accept a binary op when it is an identifier.
|
|
373
|
+
// Binary ops that start with a identifier-valid character must be followed
|
|
374
|
+
// by a non identifier-part valid character
|
|
375
|
+
if (Jsep.binary_ops.hasOwnProperty(to_check) && (
|
|
376
|
+
!Jsep.isIdentifierStart(this.code) ||
|
|
377
|
+
(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))
|
|
378
|
+
)) {
|
|
379
|
+
this.index += tc_len;
|
|
380
|
+
return to_check;
|
|
381
|
+
}
|
|
382
|
+
to_check = to_check.substr(0, --tc_len);
|
|
383
|
+
}
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* This function is responsible for gobbling an individual expression,
|
|
389
|
+
* e.g. `1`, `1+2`, `a+(b*2)-Math.sqrt(2)`
|
|
390
|
+
* @returns {?jsep.BinaryExpression}
|
|
391
|
+
*/
|
|
392
|
+
gobbleBinaryExpression() {
|
|
393
|
+
let node, biop, prec, stack, biop_info, left, right, i, cur_biop;
|
|
394
|
+
|
|
395
|
+
// First, try to get the leftmost thing
|
|
396
|
+
// Then, check to see if there's a binary operator operating on that leftmost thing
|
|
397
|
+
left = this.gobbleToken();
|
|
398
|
+
biop = this.gobbleBinaryOp();
|
|
399
|
+
|
|
400
|
+
// If there wasn't a binary operator, just return the leftmost node
|
|
401
|
+
if (!biop) {
|
|
402
|
+
return left;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Otherwise, we need to start a stack to properly place the binary operations in their
|
|
406
|
+
// precedence structure
|
|
407
|
+
biop_info = { value: biop, prec: Jsep.binaryPrecedence(biop)};
|
|
408
|
+
|
|
409
|
+
right = this.gobbleToken();
|
|
410
|
+
|
|
411
|
+
if (!right) {
|
|
412
|
+
this.throwError("Expected expression after " + biop);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
stack = [left, biop_info, right];
|
|
416
|
+
|
|
417
|
+
// Properly deal with precedence using [recursive descent](http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm)
|
|
418
|
+
while ((biop = this.gobbleBinaryOp())) {
|
|
419
|
+
prec = Jsep.binaryPrecedence(biop);
|
|
420
|
+
|
|
421
|
+
if (prec === 0) {
|
|
422
|
+
this.index -= biop.length;
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
biop_info = { value: biop, prec };
|
|
427
|
+
|
|
428
|
+
cur_biop = biop;
|
|
429
|
+
|
|
430
|
+
// Reduce: make a binary expression from the three topmost entries.
|
|
431
|
+
while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
|
|
432
|
+
right = stack.pop();
|
|
433
|
+
biop = stack.pop().value;
|
|
434
|
+
left = stack.pop();
|
|
435
|
+
node = {
|
|
436
|
+
type: Jsep.BINARY_EXP,
|
|
437
|
+
operator: biop,
|
|
438
|
+
left,
|
|
439
|
+
right
|
|
440
|
+
};
|
|
441
|
+
stack.push(node);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
node = this.gobbleToken();
|
|
445
|
+
|
|
446
|
+
if (!node) {
|
|
447
|
+
this.throwError("Expected expression after " + cur_biop);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
stack.push(biop_info, node);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
i = stack.length - 1;
|
|
454
|
+
node = stack[i];
|
|
455
|
+
|
|
456
|
+
while (i > 1) {
|
|
457
|
+
node = {
|
|
458
|
+
type: Jsep.BINARY_EXP,
|
|
459
|
+
operator: stack[i - 1].value,
|
|
460
|
+
left: stack[i - 2],
|
|
461
|
+
right: node
|
|
462
|
+
};
|
|
463
|
+
i -= 2;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return node;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* An individual part of a binary expression:
|
|
471
|
+
* e.g. `foo.bar(baz)`, `1`, `"abc"`, `(a % 2)` (because it's in parenthesis)
|
|
472
|
+
* @returns {boolean|jsep.Expression}
|
|
473
|
+
*/
|
|
474
|
+
gobbleToken() {
|
|
475
|
+
let ch, to_check, tc_len, node;
|
|
476
|
+
|
|
477
|
+
this.gobbleSpaces();
|
|
478
|
+
ch = this.code;
|
|
479
|
+
|
|
480
|
+
if (Jsep.isDecimalDigit(ch) || ch === Jsep.PERIOD_CODE) {
|
|
481
|
+
// Char code 46 is a dot `.` which can start off a numeric literal
|
|
482
|
+
return this.gobbleNumericLiteral();
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (ch === Jsep.SQUOTE_CODE || ch === Jsep.DQUOTE_CODE) {
|
|
486
|
+
// Single or double quotes
|
|
487
|
+
node = this.gobbleStringLiteral();
|
|
488
|
+
}
|
|
489
|
+
else if (ch === Jsep.OBRACK_CODE) {
|
|
490
|
+
node = this.gobbleArray();
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
to_check = this.expr.substr(this.index, Jsep.max_unop_len);
|
|
494
|
+
tc_len = to_check.length;
|
|
495
|
+
|
|
496
|
+
while (tc_len > 0) {
|
|
497
|
+
// Don't accept an unary op when it is an identifier.
|
|
498
|
+
// Unary ops that start with a identifier-valid character must be followed
|
|
499
|
+
// by a non identifier-part valid character
|
|
500
|
+
if (Jsep.unary_ops.hasOwnProperty(to_check) && (
|
|
501
|
+
!Jsep.isIdentifierStart(this.code) ||
|
|
502
|
+
(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))
|
|
503
|
+
)) {
|
|
504
|
+
this.index += tc_len;
|
|
505
|
+
return {
|
|
506
|
+
type: Jsep.UNARY_EXP,
|
|
507
|
+
operator: to_check,
|
|
508
|
+
argument: this.gobbleToken(),
|
|
509
|
+
prefix: true
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
to_check = to_check.substr(0, --tc_len);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (Jsep.isIdentifierStart(ch)) {
|
|
517
|
+
node = this.gobbleIdentifier();
|
|
518
|
+
}
|
|
519
|
+
else if (ch === Jsep.OPAREN_CODE) { // open parenthesis
|
|
520
|
+
node = this.gobbleGroup();
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if (!node) {
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
this.gobbleSpaces();
|
|
529
|
+
|
|
530
|
+
ch = this.code;
|
|
531
|
+
|
|
532
|
+
// Gobble properties of of identifiers/strings/arrays/groups.
|
|
533
|
+
// e.g. `foo`, `bar.baz`, `foo['bar'].baz`
|
|
534
|
+
// It also gobbles function calls:
|
|
535
|
+
// e.g. `Math.acos(obj.angle)`
|
|
536
|
+
|
|
537
|
+
while (ch === Jsep.PERIOD_CODE || ch === Jsep.OBRACK_CODE || ch === Jsep.OPAREN_CODE) {
|
|
538
|
+
this.index++;
|
|
539
|
+
|
|
540
|
+
if (ch === Jsep.PERIOD_CODE) {
|
|
541
|
+
this.gobbleSpaces();
|
|
542
|
+
node = {
|
|
543
|
+
type: Jsep.MEMBER_EXP,
|
|
544
|
+
computed: false,
|
|
545
|
+
object: node,
|
|
546
|
+
property: this.gobbleIdentifier()
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
else if (ch === Jsep.OBRACK_CODE) {
|
|
550
|
+
node = {
|
|
551
|
+
type: Jsep.MEMBER_EXP,
|
|
552
|
+
computed: true,
|
|
553
|
+
object: node,
|
|
554
|
+
property: this.gobbleExpression()
|
|
555
|
+
};
|
|
556
|
+
this.gobbleSpaces();
|
|
557
|
+
ch = this.code;
|
|
558
|
+
if (ch !== Jsep.CBRACK_CODE) {
|
|
559
|
+
this.throwError('Unclosed [');
|
|
560
|
+
}
|
|
561
|
+
this.index++;
|
|
562
|
+
}
|
|
563
|
+
else if (ch === Jsep.OPAREN_CODE) {
|
|
564
|
+
// A function call is being made; gobble all the arguments
|
|
565
|
+
node = {
|
|
566
|
+
type: Jsep.CALL_EXP,
|
|
567
|
+
'arguments': this.gobbleArguments(Jsep.CPAREN_CODE),
|
|
568
|
+
callee: node
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
this.gobbleSpaces();
|
|
572
|
+
ch = this.code;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
return node;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Parse simple numeric literals: `12`, `3.4`, `.5`. Do this by using a string to
|
|
580
|
+
* keep track of everything in the numeric literal and then calling `parseFloat` on that string
|
|
581
|
+
* @returns {jsep.Literal}
|
|
582
|
+
*/
|
|
583
|
+
gobbleNumericLiteral() {
|
|
584
|
+
let number = '', ch, chCode;
|
|
585
|
+
|
|
586
|
+
while (Jsep.isDecimalDigit(this.code)) {
|
|
587
|
+
number += this.expr.charAt(this.index++);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
if (this.code === Jsep.PERIOD_CODE) { // can start with a decimal marker
|
|
591
|
+
number += this.expr.charAt(this.index++);
|
|
592
|
+
|
|
593
|
+
while (Jsep.isDecimalDigit(this.code)) {
|
|
594
|
+
number += this.expr.charAt(this.index++);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
ch = this.char;
|
|
599
|
+
|
|
600
|
+
if (ch === 'e' || ch === 'E') { // exponent marker
|
|
601
|
+
number += this.expr.charAt(this.index++);
|
|
602
|
+
ch = this.char;
|
|
603
|
+
|
|
604
|
+
if (ch === '+' || ch === '-') { // exponent sign
|
|
605
|
+
number += this.expr.charAt(this.index++);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
while (Jsep.isDecimalDigit(this.code)) { // exponent itself
|
|
609
|
+
number += this.expr.charAt(this.index++);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
if (!Jsep.isDecimalDigit(this.expr.charCodeAt(this.index - 1)) ) {
|
|
613
|
+
this.throwError('Expected exponent (' + number + this.char + ')');
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
chCode = this.code;
|
|
618
|
+
|
|
619
|
+
// Check to make sure this isn't a variable name that start with a number (123abc)
|
|
620
|
+
if (Jsep.isIdentifierStart(chCode)) {
|
|
621
|
+
this.throwError('Variable names cannot start with a number (' +
|
|
622
|
+
number + this.char + ')');
|
|
623
|
+
}
|
|
624
|
+
else if (chCode === Jsep.PERIOD_CODE) {
|
|
625
|
+
this.throwError('Unexpected period');
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
return {
|
|
629
|
+
type: Jsep.LITERAL,
|
|
630
|
+
value: parseFloat(number),
|
|
631
|
+
raw: number
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Parses a string literal, staring with single or double quotes with basic support for escape codes
|
|
637
|
+
* e.g. `"hello world"`, `'this is\nJSEP'`
|
|
638
|
+
* @returns {jsep.Literal}
|
|
639
|
+
*/
|
|
640
|
+
gobbleStringLiteral() {
|
|
641
|
+
let str = '';
|
|
642
|
+
let quote = this.expr.charAt(this.index++);
|
|
643
|
+
let closed = false;
|
|
644
|
+
|
|
645
|
+
while (this.index < this.expr.length) {
|
|
646
|
+
let ch = this.expr.charAt(this.index++);
|
|
647
|
+
|
|
648
|
+
if (ch === quote) {
|
|
649
|
+
closed = true;
|
|
650
|
+
break;
|
|
651
|
+
}
|
|
652
|
+
else if (ch === '\\') {
|
|
653
|
+
// Check for all of the common escape codes
|
|
654
|
+
ch = this.expr.charAt(this.index++);
|
|
655
|
+
|
|
656
|
+
switch (ch) {
|
|
657
|
+
case 'n': str += '\n'; break;
|
|
658
|
+
case 'r': str += '\r'; break;
|
|
659
|
+
case 't': str += '\t'; break;
|
|
660
|
+
case 'b': str += '\b'; break;
|
|
661
|
+
case 'f': str += '\f'; break;
|
|
662
|
+
case 'v': str += '\x0B'; break;
|
|
663
|
+
default : str += ch;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
str += ch;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (!closed) {
|
|
672
|
+
this.throwError('Unclosed quote after "' + str + '"');
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return {
|
|
676
|
+
type: Jsep.LITERAL,
|
|
677
|
+
value: str,
|
|
678
|
+
raw: quote + str + quote
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Gobbles only identifiers
|
|
684
|
+
* e.g.: `foo`, `_value`, `$x1`
|
|
685
|
+
* Also, this function checks if that identifier is a literal:
|
|
686
|
+
* (e.g. `true`, `false`, `null`) or `this`
|
|
687
|
+
* @returns {jsep.Expression}
|
|
688
|
+
*/
|
|
689
|
+
gobbleIdentifier() {
|
|
690
|
+
let ch = this.code, start = this.index, identifier;
|
|
691
|
+
|
|
692
|
+
if (Jsep.isIdentifierStart(ch)) {
|
|
693
|
+
this.index++;
|
|
694
|
+
}
|
|
695
|
+
else {
|
|
696
|
+
this.throwError('Unexpected ' + this.char);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
while (this.index < this.expr.length) {
|
|
700
|
+
ch = this.code;
|
|
701
|
+
|
|
702
|
+
if (Jsep.isIdentifierPart(ch)) {
|
|
703
|
+
this.index++;
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
identifier = this.expr.slice(start, this.index);
|
|
710
|
+
|
|
711
|
+
if (Jsep.literals.hasOwnProperty(identifier)) {
|
|
712
|
+
return {
|
|
713
|
+
type: Jsep.LITERAL,
|
|
714
|
+
value: Jsep.literals[identifier],
|
|
715
|
+
raw: identifier
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
else if (identifier === Jsep.this_str) {
|
|
719
|
+
return { type: Jsep.THIS_EXP };
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
return {
|
|
723
|
+
type: Jsep.IDENTIFIER,
|
|
724
|
+
name: identifier
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Gobbles a list of arguments within the context of a function call
|
|
731
|
+
* or array literal. This function also assumes that the opening character
|
|
732
|
+
* `(` or `[` has already been gobbled, and gobbles expressions and commas
|
|
733
|
+
* until the terminator character `)` or `]` is encountered.
|
|
734
|
+
* e.g. `foo(bar, baz)`, `my_func()`, or `[bar, baz]`
|
|
735
|
+
* @param {string} termination
|
|
736
|
+
* @returns {jsep.Expression[]}
|
|
737
|
+
*/
|
|
738
|
+
gobbleArguments(termination) {
|
|
739
|
+
const args = [];
|
|
740
|
+
let closed = false;
|
|
741
|
+
let separator_count = 0;
|
|
742
|
+
|
|
743
|
+
while (this.index < this.expr.length) {
|
|
744
|
+
this.gobbleSpaces();
|
|
745
|
+
let ch_i = this.code;
|
|
746
|
+
|
|
747
|
+
if (ch_i === termination) { // done parsing
|
|
748
|
+
closed = true;
|
|
749
|
+
this.index++;
|
|
750
|
+
|
|
751
|
+
if (termination === Jsep.CPAREN_CODE && separator_count && separator_count >= args.length){
|
|
752
|
+
this.throwError('Unexpected token ' + String.fromCharCode(termination));
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
else if (ch_i === Jsep.COMMA_CODE) { // between expressions
|
|
758
|
+
this.index++;
|
|
759
|
+
separator_count++;
|
|
760
|
+
|
|
761
|
+
if (separator_count !== args.length) { // missing argument
|
|
762
|
+
if (termination === Jsep.CPAREN_CODE) {
|
|
763
|
+
this.throwError('Unexpected token ,');
|
|
764
|
+
}
|
|
765
|
+
else if (termination === Jsep.CBRACK_CODE) {
|
|
766
|
+
for (let arg = args.length; arg < separator_count; arg++) {
|
|
767
|
+
args.push(null);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
const node = this.gobbleExpression();
|
|
774
|
+
|
|
775
|
+
if (!node || node.type === Jsep.COMPOUND) {
|
|
776
|
+
this.throwError('Expected comma');
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
args.push(node);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if (!closed) {
|
|
784
|
+
this.throwError('Expected ' + String.fromCharCode(termination));
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
return args;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Responsible for parsing a group of things within parentheses `()`
|
|
792
|
+
* that have no identifier in front (so not a function call)
|
|
793
|
+
* This function assumes that it needs to gobble the opening parenthesis
|
|
794
|
+
* and then tries to gobble everything within that parenthesis, assuming
|
|
795
|
+
* that the next thing it should see is the close parenthesis. If not,
|
|
796
|
+
* then the expression probably doesn't have a `)`
|
|
797
|
+
* @returns {boolean|jsep.Expression}
|
|
798
|
+
*/
|
|
799
|
+
gobbleGroup() {
|
|
800
|
+
this.index++;
|
|
801
|
+
let nodes = this.gobbleExpressions(Jsep.CPAREN_CODE);
|
|
802
|
+
if (this.code === Jsep.CPAREN_CODE) {
|
|
803
|
+
this.index++;
|
|
804
|
+
if (nodes.length === 1) {
|
|
805
|
+
return nodes[0];
|
|
806
|
+
}
|
|
807
|
+
else if (!nodes.length) {
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
return {
|
|
812
|
+
type: Jsep.SEQUENCE_EXP,
|
|
813
|
+
expressions: nodes,
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
this.throwError('Unclosed (');
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Responsible for parsing Array literals `[1, 2, 3]`
|
|
824
|
+
* This function assumes that it needs to gobble the opening bracket
|
|
825
|
+
* and then tries to gobble the expressions as arguments.
|
|
826
|
+
* @returns {jsep.ArrayExpression}
|
|
827
|
+
*/
|
|
828
|
+
gobbleArray() {
|
|
829
|
+
this.index++;
|
|
830
|
+
|
|
831
|
+
return {
|
|
832
|
+
type: Jsep.ARRAY_EXP,
|
|
833
|
+
elements: this.gobbleArguments(Jsep.CBRACK_CODE)
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// Backward Compatibility (before adding the static fields):
|
|
839
|
+
const jsep = expr => (new Jsep(expr)).parse();
|
|
840
|
+
const staticMethods = Object.getOwnPropertyNames(Jsep);
|
|
841
|
+
staticMethods
|
|
842
|
+
.slice(staticMethods.indexOf('version'), staticMethods.indexOf('removeAllLiterals') + 1)
|
|
843
|
+
.forEach((m) => {
|
|
844
|
+
jsep[m] = Jsep[m];
|
|
845
|
+
});
|
|
846
|
+
// export default jsep;
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
// Static fields:
|
|
850
|
+
Object.assign(Jsep, {
|
|
851
|
+
// Node Types
|
|
852
|
+
// ----------
|
|
853
|
+
// This is the full set of types that any JSEP node can be.
|
|
854
|
+
// Store them here to save space when minified
|
|
855
|
+
COMPOUND: 'Compound',
|
|
856
|
+
SEQUENCE_EXP: 'SequenceExpression',
|
|
857
|
+
IDENTIFIER: 'Identifier',
|
|
858
|
+
MEMBER_EXP: 'MemberExpression',
|
|
859
|
+
LITERAL: 'Literal',
|
|
860
|
+
THIS_EXP: 'ThisExpression',
|
|
861
|
+
CALL_EXP: 'CallExpression',
|
|
862
|
+
UNARY_EXP: 'UnaryExpression',
|
|
863
|
+
BINARY_EXP: 'BinaryExpression',
|
|
864
|
+
CONDITIONAL_EXP: 'ConditionalExpression',
|
|
865
|
+
ARRAY_EXP: 'ArrayExpression',
|
|
866
|
+
|
|
867
|
+
TAB_CODE: 9,
|
|
868
|
+
LF_CODE: 10,
|
|
869
|
+
CR_CODE: 13,
|
|
870
|
+
SPACE_CODE: 32,
|
|
871
|
+
PERIOD_CODE: 46, // '.'
|
|
872
|
+
COMMA_CODE: 44, // ','
|
|
873
|
+
SQUOTE_CODE: 39, // single quote
|
|
874
|
+
DQUOTE_CODE: 34, // double quotes
|
|
875
|
+
OPAREN_CODE: 40, // (
|
|
876
|
+
CPAREN_CODE: 41, // )
|
|
877
|
+
OBRACK_CODE: 91, // [
|
|
878
|
+
CBRACK_CODE: 93, // ]
|
|
879
|
+
QUMARK_CODE: 63, // ?
|
|
880
|
+
SEMCOL_CODE: 59, // ;
|
|
881
|
+
COLON_CODE: 58, // :
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
// Operations
|
|
885
|
+
// ----------
|
|
886
|
+
// Use a quickly-accessible map to store all of the unary operators
|
|
887
|
+
// Values are set to `1` (it really doesn't matter)
|
|
888
|
+
unary_ops: {
|
|
889
|
+
'-': 1,
|
|
890
|
+
'!': 1,
|
|
891
|
+
'~': 1,
|
|
892
|
+
'+': 1
|
|
893
|
+
},
|
|
894
|
+
|
|
895
|
+
// Also use a map for the binary operations but set their values to their
|
|
896
|
+
// binary precedence for quick reference:
|
|
897
|
+
// see [Order of operations](http://en.wikipedia.org/wiki/Order_of_operations#Programming_language)
|
|
898
|
+
binary_ops: {
|
|
899
|
+
'||': 1, '&&': 2, '|': 3, '^': 4, '&': 5,
|
|
900
|
+
'==': 6, '!=': 6, '===': 6, '!==': 6,
|
|
901
|
+
'<': 7, '>': 7, '<=': 7, '>=': 7,
|
|
902
|
+
'<<': 8, '>>': 8, '>>>': 8,
|
|
903
|
+
'+': 9, '-': 9,
|
|
904
|
+
'*': 10, '/': 10, '%': 10
|
|
905
|
+
},
|
|
906
|
+
|
|
907
|
+
// Additional valid identifier chars, apart from a-z, A-Z and 0-9 (except on the starting char)
|
|
908
|
+
additional_identifier_chars: new Set(['$', '_']),
|
|
909
|
+
|
|
910
|
+
// Literals
|
|
911
|
+
// ----------
|
|
912
|
+
// Store the values to return for the various literals we may encounter
|
|
913
|
+
literals: {
|
|
914
|
+
'true': true,
|
|
915
|
+
'false': false,
|
|
916
|
+
'null': null
|
|
917
|
+
},
|
|
918
|
+
|
|
919
|
+
// Except for `this`, which is special. This could be changed to something like `'self'` as well
|
|
920
|
+
this_str: 'this',
|
|
921
|
+
});
|
|
922
|
+
Jsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);
|
|
923
|
+
Jsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);
|
|
924
|
+
|
|
925
|
+
module.exports = Jsep;
|