subscript 5.0.0 → 5.2.2

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 CHANGED
@@ -1,4 +1,7 @@
1
- # <!--<img alt="subscript" src="/subscript2.svg" height=42/>--> sub͘<em>script</em> <!--<sub>SUB͘<em>SCRIPT</em></sub>-->
1
+ # <img alt="subscript" src="/subscript2.svg" height=42/> <!--sub͘<em>script</em>--> <!--<sub>SUB͘<em>SCRIPT</em></sub>-->
2
+ <a href="https://github.com/spectjs/subscript/actions/workflows/node.js.yml"><img src="https://github.com/spectjs/subscript/actions/workflows/node.js.yml/badge.svg"/></a>
3
+ <a href="http://npmjs.org/subscript"><img src="https://img.shields.io/npm/v/subscript?color=orangered"/></a>
4
+ <a href="http://microjs.com/#subscript"><img src="https://img.shields.io/badge/microjs-subscript-blue?color=darkslateblue"/></a>
2
5
 
3
6
  _Subscript_ is micro-language with common syntax subset of C++, JS, Java, Python, Go, Rust, Swift, Objective C, Kotlin etc.<br/>
4
7
 
@@ -27,28 +30,9 @@ _Subscript_ is designed to be useful for:
27
30
  * custom DSL
28
31
 
29
32
  [_Jsep_](https://github.com/EricSmekens/jsep) is generally fine for the listed tasks, unless you need dependencies as small as possible.
30
- _Subscript_ has [2.5kb](https://npmfs.com/package/subscript/4.0.0/subscript.min.js) footprint vs [11.4kb](https://npmfs.com/package/jsep/1.2.0/dist/jsep.min.js) _jsep_, with better performance.
33
+ _Subscript_ has [2.5kb](https://npmfs.com/package/subscript/5.2.0/subscript.min.js) footprint vs [11.4kb](https://npmfs.com/package/jsep/1.2.0/dist/jsep.min.js) _jsep_, with _jsep+_ test coverage and better performance.
31
34
 
32
35
 
33
- ## Operators
34
-
35
- Default operators include common operators for the listed languages in the following precedence:
36
-
37
- * `++ --` unary postfix
38
- * `! + - ++ --` unary prefix
39
- * `* / %`
40
- * `+ -`
41
- * `<< >> >>>`
42
- * `< <= > >=`
43
- * `== !=`
44
- * `&`
45
- * `^`
46
- * `|`
47
- * `&&`
48
- * `||`
49
-
50
- All other operators can be extended, see [extension](#extension).
51
-
52
36
  ## Evaluation
53
37
 
54
38
  _Subscript_ parser generates lispy calltree (compatible with [frisk](https://npmjs.com/frisk)), which is compared to esprima AST has:
@@ -66,34 +50,34 @@ import {evaluate} from 'subscript.js'
66
50
  evaluate(['+', ['*', 'min', 60], '"sec"'], { min: 5 }) // min*60 + "sec" == "300sec"
67
51
  ```
68
52
 
69
- ## Extension
70
-
71
- Tokens are extensible via `parse.token` list, can be added support of _regex_, _array_, _object_, _interpolated string_ and others.
72
- Default tokens include:
53
+ ## Extending
73
54
 
74
- * `"abc"` strings
75
- * `1.2e+3` floats
76
- * `()` expression groups or fn calls
77
- * `.`, `[]` property access
55
+ ### Operators
78
56
 
79
- Operators can be extended via `parse.operator` to add support for any unary/binary/postfix operators, calls, props or chains.
57
+ Default operators include common operators for the listed languages in the following precedence:
80
58
 
81
- Comments can be added via extending `parse.space`.
59
+ * `++ --` unary postfix
60
+ * `! + - ++ --` unary prefix
61
+ * `* / %`
62
+ * `+ -`
63
+ * `<< >> >>>`
64
+ * `< <= > >=`
65
+ * `== !=`
66
+ * `&`
67
+ * `^`
68
+ * `|`
69
+ * `&&`
70
+ * `||`
82
71
 
83
- For now see justin extension how things can be done.
72
+ Operators can be extended via `parse.operator(str, prec, type)` and `evaluate.operator(str, fn)` functions for any unary/binary/postfix operators, calls, props, groups, arrays, objects etc.
84
73
 
85
- <!--
86
74
  ```js
87
75
  import { parse, evaluate } from 'subscript.js'
88
76
 
89
- // add precedences
90
- // TODO
91
- // parse.operator['=>'] = 10
77
+ parse.operator('=>', 10) // precedence=10, type=default (0 - binary, 1 - postfix, -1 - prefix)
92
78
 
93
- // define evaluators
94
- // TODO
95
- // evaluate.operator['=>'] = ( args, body ) => evaluate(body, args)
96
- // evaluate.operator['|'] = ( a, ...b ) => a.pipe(...b)
79
+ evaluate.operator('=>', ( args, body ) => evaluate(body, args))
80
+ evaluate.operator('|', ( a, ...b ) => a.pipe(...b))
97
81
 
98
82
  let tree = parse(`
99
83
  interval(350)
@@ -103,7 +87,29 @@ let tree = parse(`
103
87
  `)
104
88
  evaluate(tree, { Math, map, take, interval, gaussian })
105
89
  ```
106
- -->
90
+
91
+ ### Tokens
92
+
93
+ Default tokens include:
94
+
95
+ * `"abc"` strings
96
+ * `1.2e+3` floats
97
+ * `name` identifiers
98
+
99
+ Tokens are extensible via `parse.token` list, can be added support of _literals_, _regexes_, _strings_, _numbers_ and others.
100
+
101
+ ```js
102
+ import parse, {char} from 'subscript/parse.js'
103
+ import evaluate from 'subscript/evaluate.js'
104
+
105
+ conts ctx = {x:1}
106
+ parse.token.unshift(c => char(4) === 'this' ? ctx : null)
107
+ evaluate(parse(`this.x`)) // 1
108
+ ```
109
+
110
+ ### Spaces/comments
111
+
112
+ Comments can be added via extending `parse.space`. See [justin.js](./justin.js) for more examples.
107
113
 
108
114
 
109
115
  ## Justin
@@ -111,6 +117,7 @@ evaluate(tree, { Math, map, take, interval, gaussian })
111
117
  _Justin_ extension (original [thread](https://github.com/endojs/Jessie/issues/66)) is minimal JS subset − JSON with JS expressions.<br/>
112
118
  It adds support of:
113
119
 
120
+ + `===`, `!==` operators
114
121
  + `**` binary operator
115
122
  + `~` unary operator
116
123
  + `'` strings
@@ -122,7 +129,6 @@ It adds support of:
122
129
  + unary word operators
123
130
  + `//`, `/* */` comments
124
131
  + `true`, `false`, `null`, `undefined` literals
125
- <!-- + `===`, `!==` operators -->
126
132
  <!-- + `?` chaining operator -->
127
133
  <!-- + `...x` unary operator -->
128
134
  <!-- + strings interpolation -->
@@ -279,7 +285,7 @@ Subscript shows relatively good performance within other evaluators:
279
285
  // 1 + (a * b / c % d) - 2.0 + -3e-3 * +4.4e4 / f.g[0] - i.j(+k == 1)(0)
280
286
  // parse 30k times
281
287
 
282
- subscript: ~200 ms
288
+ subscript: ~230 ms
283
289
  jsep: ~280 ms
284
290
  expr-eval: ~480 ms
285
291
  jexl: ~1200 ms
package/evaluate.js CHANGED
@@ -4,10 +4,9 @@ export const isCmd = a => Array.isArray(a) && (typeof a[0] === 'string' || isCmd
4
4
  evaluate = (s, ctx={}, c, op) => {
5
5
  if (isCmd(s)) {
6
6
  c = s[0]
7
- if (typeof c === 'string') op = operator[c]
7
+ if (typeof c === 'string') op = lookup[c]
8
8
  c = op || evaluate(c, ctx) // [[a,b], c]
9
9
  if (typeof c !== 'function') return c
10
-
11
10
  return c.call(...s.map(a => evaluate(a,ctx)))
12
11
  }
13
12
  if (s && typeof s === 'string')
@@ -17,43 +16,10 @@ evaluate = (s, ctx={}, c, op) => {
17
16
 
18
17
  return s
19
18
  },
20
-
21
- reducer=fn=>(...a)=>a.reduce(fn),
19
+ lookup = {},
22
20
 
23
21
  // op evaluators
24
22
  // multiple args allows shortcuts, lisp compatible, easy manual eval, functions anyways take multiple arguments
25
- operator = evaluate.operator = {
26
- '!':a=>!a,
27
- '++':a=>++a,
28
- '--':a=>--a,
29
-
30
- '.':reducer((a,b)=>a?a[b]:a),
31
-
32
- '%':reducer((a,b)=>a%b),
33
- '/':reducer((a,b)=>a/b),
34
- '*':reducer((a,b)=>a*b),
35
-
36
- '+':reducer((a,b)=>a+b),
37
- '-':(...a)=>a.length < 2 ? -a : a.reduce((a,b)=>a-b),
38
-
39
- '>>>':(a,b)=>a>>>b,
40
- '>>':(a,b)=>a>>b,
41
- '<<':(a,b)=>a<<b,
42
-
43
- '>=':(a,b)=>a>=b,
44
- '>':(a,b)=>a>b,
45
- '<=':(a,b)=>a<=b,
46
- '<':(a,b)=>a<b,
47
-
48
- '!=':(a,b)=>a!=b,
49
- '==':(a,b)=>a==b,
50
-
51
- '&':(a,b)=>a&b,
52
- '^':(a,b)=>a^b,
53
- '|':(a,b)=>a|b,
54
- '&&':(...a)=>a.every(Boolean),
55
- '||':(...a)=>a.some(Boolean),
56
- ',':reducer((a,b)=>(a,b))
57
- }
23
+ operator = evaluate.operator = (op, fn) => lookup[op] = fn.length == 2 ? (...a)=>a.reduce(fn) : fn
58
24
 
59
25
  export default evaluate
package/justin.js CHANGED
@@ -1,57 +1,56 @@
1
1
  // justin lang https://github.com/endojs/Jessie/issues/66
2
2
  import {evaluate} from './evaluate.js'
3
- import {parse, code, char, skip, expr, operator, err} from './parse.js'
3
+ import {parse, code, char, skip, expr, err} from './parse.js'
4
4
 
5
- // ;
6
- operator(';', 1)
5
+ const PERIOD=46, OPAREN=40, CPAREN=41, CBRACK=93, SPACE=32,
7
6
 
8
- // ===, !==
9
- operator('===', 9)
10
- operator('!==', 9)
7
+ PREC_SEQ=1, PREC_TERN=3, PREC_SOME=4, PREC_EVERY=5, PREC_OR=6, PREC_XOR=7, PREC_AND=8,
8
+ PREC_EQ=9, PREC_COMP=10, PREC_SHIFT=11, PREC_SUM=12, PREC_MULT=13, PREC_UNARY=15, PREC_POSTFIX=16, PREC_CALL=18, PREC_GROUP=19,
9
+ PREC_EXP=14, PREC_TOKEN=20
11
10
 
12
- // undefined
11
+
12
+ // tokens
13
13
  const v = v => ({valueOf:()=>v})
14
- parse.token.splice(2,0, c =>
15
- c === 116 && char(4) === 'true' && skip(4) ? v(true) :
16
- c === 102 && char(5) === 'false' && skip(5) ? v(false) :
17
- c === 110 && char(4) === 'null' && skip(4) ? v(null) :
18
- c === 117 && char(9) === 'undefined' && skip(9) ? v(undefined) :
19
- null
14
+ parse.token.push(
15
+ // 1.2e+3, .5 - fast & small version, but consumes corrupted nums as well
16
+ (number) => (
17
+ (number = skip(c => (c > 47 && c < 58) || c == PERIOD)) && (
18
+ (code() == 69 || code() == 101) && (number += skip(2) + skip(c => c >= 48 && c <= 57)),
19
+ isNaN(number = new Number(number)) ? err('Bad number') : number
20
+ )
21
+ ),
22
+
23
+ // "' with /
24
+ (q, qc, c, str) => {
25
+ if (q !== 34 && q !== 39) return
26
+ qc = char(), skip(), str = ''
27
+ while (c=code(), c-q) {
28
+ if (c === 92) skip(), str += escape[char()] || char(); else str+=char()
29
+ skip()
30
+ }
31
+ return skip(), qc + str + qc
32
+ },
33
+
34
+ // literal
35
+ c =>
36
+ c === 116 && char(4) === 'true' && skip(4) ? v(true) :
37
+ c === 102 && char(5) === 'false' && skip(5) ? v(false) :
38
+ c === 110 && char(4) === 'null' && skip(4) ? v(null) :
39
+ c === 117 && char(9) === 'undefined' && skip(9) ? v(undefined) :
40
+ null,
41
+
42
+ // id
43
+ c => skip(c =>
44
+ (c >= 48 && c <= 57) || // 0..9
45
+ (c >= 65 && c <= 90) || // A...Z
46
+ (c >= 97 && c <= 122) || // a...z
47
+ c == 36 || c == 95 || // $, _,
48
+ (c >= 192 && c != 215 && c != 247) // any non-ASCII
49
+ )
20
50
  )
21
51
 
22
- // "' with /
23
- parse.token[1] = (q, qc, c, str) => {
24
- if (q !== 34 && q !== 39) return
25
- qc = char(), skip(), str = ''
26
- while (c=code(), c-q) {
27
- if (c === 92) skip(), str += escape[char()] || char(); else str+=char()
28
- skip()
29
- }
30
- return skip(), qc + str + qc
31
- }
32
52
  const escape = {n:'\n', r:'\r', t:'\t', b:'\b', f:'\f', v:'\v'}
33
53
 
34
- // **
35
- evaluate.operator['**'] = (...args)=>args.reduceRight((a,b)=>Math.pow(b,a))
36
- operator('**', 14)
37
-
38
- // ~
39
- operator('~', 13, -1)
40
- evaluate.operator['~'] = a=>~a
41
-
42
- // TODO ...
43
-
44
- // ?:
45
- evaluate.operator['?:']=(a,b,c)=>a?b:c
46
- operator('?', 3, (node) => {
47
- if (!node) err('Expected expression')
48
- let a, b
49
- skip(), parse.space(), a = expr()
50
- if (code() !== 58) err('Expected :')
51
- skip(), parse.space(), b = expr()
52
- return ['?:', node, a, b]
53
- })
54
- // operator(':')
55
54
 
56
55
  // /**/, //
57
56
  parse.space = cc => {
@@ -66,36 +65,152 @@ parse.space = cc => {
66
65
  return cc
67
66
  }
68
67
 
69
- // in
70
- evaluate.operator['in'] = (a,b)=>a in b
71
- operator('in', 10, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(10)])
72
-
73
- // []
74
- evaluate.operator['['] = (...args) => Array(...args)
75
- // as operator it's faster to lookup (no need to call extra rule check), smaller and no conflict with word names
76
- operator('[', 20, (node,arg) => !node && (
77
- skip(), arg=expr(0,93), skip(),
78
- !arg ? ['['] : arg[0] === ',' ? (arg[0]='[',arg) : ['[',arg]
79
- ))
80
-
81
- // {}
82
- parse.token.unshift((cc, node) => (
83
- cc === 123 && (skip(), node = map(['{', expr(0,125)]), skip(), node)
84
- ))
85
-
86
- operator('}')
87
- operator(':', 0)
88
- evaluate.operator['{'] = (...args)=>Object.fromEntries(args)
89
- evaluate.operator[':'] = (a,b)=>[a,b]
90
-
91
- const map = (n, args) => {
92
- if (!n[1]) args = []
93
- else if (n[1][0]==':') args = [n[1]]
94
- else if (n[1][0]==',') args = n[1].slice(1)
95
- return ['{', ...args]
68
+
69
+ // operators
70
+ const addOps = (add, stride=2, list) => {
71
+ for (let i = 0; i < list.length; i+=stride) add(list[i], list[i+1], list[i+2])
96
72
  }
97
73
 
74
+ addOps(parse.operator, 3, [
75
+ // subscript ones
76
+ // TODO: add ,, as node here?
77
+ ',', PREC_SEQ,,
78
+
79
+ '|', PREC_OR,,
80
+ '||', PREC_SOME,,
81
+
82
+ '&', PREC_AND,,
83
+ '&&', PREC_EVERY,,
84
+
85
+ '^', PREC_XOR,,
86
+
87
+ // ==, !=
88
+ '==', PREC_EQ,,
89
+ '!=', PREC_EQ,,
90
+
91
+ // > >= >> >>>, < <= <<
92
+ '>', PREC_COMP,,
93
+ '>=', PREC_COMP,,
94
+ '>>', PREC_SHIFT,,
95
+ '>>>', PREC_SHIFT,,
96
+ '<', PREC_COMP,,
97
+ '<=', PREC_COMP,,
98
+ '<<', PREC_SHIFT,,
99
+
100
+ // + ++ - --
101
+ '+', PREC_SUM,,
102
+ '+', PREC_UNARY, -1,
103
+ '++', PREC_UNARY, -1,
104
+ '++', PREC_UNARY, +1,
105
+ '-', PREC_SUM,,
106
+ '-', PREC_UNARY, -1,
107
+ '--', PREC_UNARY, -1,
108
+ '--', PREC_UNARY, +1,
109
+
110
+ // !
111
+ '!', PREC_UNARY, -1,
112
+
113
+ // * / %
114
+ '*', PREC_MULT,,
115
+ '/', PREC_MULT,,
116
+ '%', PREC_MULT,,
117
+
118
+ // a.b
119
+ '.', PREC_CALL, (node,b) => node && [skip(),node, typeof (b = expr(PREC_CALL)) === 'string' ? '"' + b + '"' : b.valueOf()],
120
+
121
+ // a[b]
122
+ '[', PREC_CALL, (node) => (skip(), node = ['.', node, expr(0,CBRACK).valueOf()], skip(), node),
123
+ ']',,,
124
+
125
+ // a(b)
126
+ '(', PREC_CALL, (node,b) => ( skip(), b=expr(0,CPAREN), skip(),
127
+ Array.isArray(b) && b[0]===',' ? (b[0]=node, b) : b ? [node, b.valueOf()] : [node]
128
+ ),
129
+ // (a+b)
130
+ '(', PREC_GROUP, (node,b) => !node && (skip(), b=expr(0,CPAREN) || err(), skip(), b),
131
+ ')',,,
132
+
133
+ // justin extension
134
+ ';', PREC_SEQ,,
135
+ '===', PREC_EQ,,
136
+ '!==', PREC_EQ,,
137
+ '**', PREC_EXP,,
138
+ '~', PREC_UNARY, -1,
139
+ '?', PREC_TERN, (node) => {
140
+ if (!node) err('Expected expression')
141
+ let a, b
142
+ skip(), parse.space(), a = expr()
143
+ if (code() !== 58) err('Expected :')
144
+ skip(), parse.space(), b = expr()
145
+ return ['?:', node, a, b]
146
+ },
147
+ '}',,,
148
+ ':',,,
149
+ 'in', PREC_COMP, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(PREC_COMP)],
150
+
151
+ // [a,b,c]
152
+ '[', PREC_TOKEN, (node,arg) => !node && (
153
+ skip(), arg=expr(0,93), skip(),
154
+ !arg ? ['['] : arg[0] == ',' ? (arg[0]='[',arg) : ['[',arg]
155
+ ),
156
+
157
+ // {a:0, b:1}
158
+ '{', PREC_TOKEN, (node,arg) => !node && (skip(), arg=expr(0,125), skip(),
159
+ !arg ? ['{'] : arg[0] == ':' ? ['{',arg] : arg[0] == ',' ? (arg[0]='{',arg) : ['[',arg])
160
+ ,
161
+ ])
162
+
163
+ addOps(evaluate.operator, 2, [
164
+ // subscript
165
+ '!', a=>!a,
166
+ '++', a=>++a,
167
+ '--', a=>--a,
168
+
169
+ '.', (a,b)=>a?a[b]:a,
170
+
171
+ '%', (a,b)=>a%b,
172
+ '/', (a,b)=>a/b,
173
+ '*', (a,b)=>a*b,
174
+
175
+ '+', (a,b)=>a+b,
176
+ '-', (...a)=>a.length < 2 ? -a : a.reduce((a,b)=>a-b),
177
+
178
+ '>>>', (a,b)=>a>>>b,
179
+ '>>', (a,b)=>a>>b,
180
+ '<<', (a,b)=>a<<b,
181
+
182
+ '>=', (a,b)=>a>=b,
183
+ '>', (a,b)=>a>b,
184
+ '<=', (a,b)=>a<=b,
185
+ '<', (a,b)=>a<b,
186
+
187
+ '!=', (a,b)=>a!=b,
188
+ '==', (a,b)=>a==b,
189
+
190
+ '&', (a,b)=>a&b,
191
+ '^', (a,b)=>a^b,
192
+ '|', (a,b)=>a|b,
193
+ '&&', (...a)=>a.every(Boolean),
194
+ '||', (...a)=>a.some(Boolean),
195
+ ',', (a,b)=>(a,b),
196
+
197
+ // justin extension
198
+ '**', (...args)=>args.reduceRight((a,b)=>Math.pow(b,a)),
199
+ '~', a=>~a,
200
+ '?:', (a,b,c)=>a?b:c,
201
+ 'in', (a,b)=>a in b,
202
+
203
+ // []
204
+ '[', (...args) => Array(...args),
205
+ // as operator it's faster to lookup (no need to call extra rule check), smaller and no conflict with word names
206
+ '{', (...args)=>Object.fromEntries(args),
207
+ ':', (a,b)=>[a,b]
208
+ ])
209
+
210
+ // TODO ...
98
211
  // TODO: strings interpolation
99
212
 
100
- export default parse
101
213
  export { parse, evaluate }
214
+
215
+ // code → evaluator
216
+ export default s => (s = typeof s == 'string' ? parse(s) : s, ctx => evaluate(s, ctx))
package/justin.min.js CHANGED
@@ -1 +1 @@
1
- var e,r,t=e=>Array.isArray(e)&&("string"==typeof e[0]||t(e[0])),a=(e,r={},o,l)=>t(e)?("string"==typeof(o=e[0])&&(l=n[o]),"function"!=typeof(o=l||a(o,r))?o:o.call(...e.map((e=>a(e,r))))):e&&"string"==typeof e?'"'===e[0]?e.slice(1,-1):"@"===e[0]?e.slice(1):e in r?r[e]:e:e,o=e=>(...r)=>r.reduce(e),n=a.operator={"!":e=>!e,"++":e=>++e,"--":e=>--e,".":o(((e,r)=>e&&e[r])),"%":o(((e,r)=>e%r)),"/":o(((e,r)=>e/r)),"*":o(((e,r)=>e*r)),"+":o(((e,r)=>e+r)),"-":(...e)=>e.length<2?-e:e.reduce(((e,r)=>e-r)),">>>":(e,r)=>e>>>r,">>":(e,r)=>e>>r,"<<":(e,r)=>e<<r,">=":(e,r)=>e>=r,">":(e,r)=>e>r,"<=":(e,r)=>e<=r,"<":(e,r)=>e<r,"!=":(e,r)=>e!=r,"==":(e,r)=>e==r,"&":(e,r)=>e&r,"^":(e,r)=>e^r,"|":(e,r)=>e|r,"&&":(...e)=>e.every(Boolean),"||":(...e)=>e.some(Boolean),",":o(((e,r)=>r))},l=15,s=(t,a)=>(r=t,e=0,a=c(),e<r.length?p():a.valueOf()),p=(t="Bad syntax")=>{throw Error(t+" `"+r[e]+"` at "+e)},u=(t=1,a=e)=>{if("number"==typeof t)e+=t;else for(;t(f());)e++;return r.slice(a,e)},f=(t=0)=>r.charCodeAt(e+t),i=(t=1)=>r.substr(e,t),c=(e=0,r,t,a,o=0,n,l)=>{for(;(t=s.space())&&(l=h[t]?.(a,e)||!a&&d(t));)a=l;return r&&t!==r&&p("Unclosed paren"),a},v=(s.space=r=>{for(;(r=f())<=32;)e++;return r},s.token=[e=>(e=u((e=>e>47&&e<58||46==e)))&&((69==f()||101==f())&&(e+=u(2)+u((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?p("Bad number"):e),(e,r)=>34==e&&u()+u((r=>r-e))+u(),e=>u((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e))]),d=(e,r=0,t)=>{for(;r<v.length;)if(t=v[r++](e))return t},h=[],y=(r,t=0,a=0,o,n=r.charCodeAt(0),l=r.length,v=h[n],d=r.toUpperCase()!==r,y)=>(y=l<2?d?e=>f(1)<=32:e=>1:d?e=>i(l)==r&&f(l)<=32:e=>i(l)==r,o=a?a>0?e=>e&&[u(l),e]:a<0?e=>!e&&[u(l),(c(t-1)||p()).valueOf()]:a:a=>{a=[r,a||p()];do{e+=l,a.push((c(t)||p()).valueOf())}while(s.space()==n&&y());return a},h[n]=(e,r)=>r<t&&y()&&o(e)||v&&v(e,r));for(let r=0,t=[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",l,-1,"++",l,-1,"++",l,1,"-",12,,"-",l,-1,"--",l,-1,"--",l,1,"!",l,-1,"*",13,,"/",13,,"%",13,,".",18,(e,r)=>e&&[u(),e,"string"==typeof(r=c(18))?'"'+r+'"':r.valueOf()],"[",18,r=>(e++,r=[".",r,c(0,93).valueOf()],e++,r),"]",,,"(",18,(r,t)=>(e++,t=c(0,41),e++,Array.isArray(t)&&","===t[0]?(t[0]=r,t):t?[r,t.valueOf()]:[r]),"(",19,(r,t)=>!r&&(++e,t=c(0,41)||p(),++e,t),")",,,];r<t.length;)y(t[r++],t[r++],t[r++]);y(";",1),y("===",9),y("!==",9);var g=e=>({valueOf:()=>e});s.token.splice(2,0,(e=>116===e&&"true"===i(4)&&u(4)?g(!0):102===e&&"false"===i(5)&&u(5)?g(!1):110===e&&"null"===i(4)&&u(4)?g(null):117===e&&"undefined"===i(9)&&u(9)?g(void 0):null)),s.token[1]=(e,r,t,a)=>{if(34===e||39===e){for(r=i(),u(),a="";(t=f())-e;)92===t?(u(),a+=O[i()]||i()):a+=i(),u();return u(),r+a+r}};var O={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"};a.operator["**"]=(...e)=>e.reduceRight(((e,r)=>Math.pow(r,e))),y("**",14),y("~",13,-1),a.operator["~"]=e=>~e,a.operator["?:"]=(e,r,t)=>e?r:t,y("?",3,(e=>{let r,t;return e||p("Expected expression"),u(),s.space(),r=c(),58!==f()&&p("Expected :"),u(),s.space(),t=c(),["?:",e,r,t]})),s.space=e=>{for(;(e=f())<=32;)u(),47===f()&&(42===f(1)?(u(2),u((e=>42!==e&&47!==f(1))),u(2)):47===f(1)&&(u(2),u((e=>e>=32))));return e},a.operator.in=(e,r)=>e in r,y("in",10,(e=>f(2)<=32&&[u(2),'"'+e+'"',c(10)])),a.operator["["]=(...e)=>Array(...e),y("[",20,((e,r)=>!e&&(u(),r=c(0,93),u(),r?","===r[0]?(r[0]="[",r):["[",r]:["["]))),s.token.unshift(((e,r)=>123===e&&(u(),r=b(["{",c(0,125)]),u(),r))),y("}"),y(":",0),a.operator["{"]=(...e)=>Object.fromEntries(e),a.operator[":"]=(e,r)=>[e,r];var b=(e,r)=>(e[1]?":"==e[1][0]?r=[e[1]]:","==e[1][0]&&(r=e[1].slice(1)):r=[],["{",...r]),A=s;export{A as default,a as evaluate,s as parse};
1
+ var e,r,t=e=>Array.isArray(e)&&("string"==typeof e[0]||t(e[0])),a=(e,r={},o,l)=>t(e)?("string"==typeof(o=e[0])&&(l=n[o]),"function"!=typeof(o=l||a(o,r))?o:o.call(...e.map((e=>a(e,r))))):e&&"string"==typeof e?'"'===e[0]?e.slice(1,-1):"@"===e[0]?e.slice(1):e in r?r[e]:e:e,n={},o=(a.operator=(e,r)=>n[e]=2==r.length?(...e)=>e.reduce(r):r,(t,a)=>(r=t,e=0,a=p(),e<r.length?l():a.valueOf())),l=(t="Bad syntax")=>{throw Error(t+" `"+r[e]+"` at "+e)},s=(t=1,a=e)=>{if("number"==typeof t)e+=t;else for(;t(u());)e++;return r.slice(a,e)},u=(t=0)=>r.charCodeAt(e+t),f=(t=1)=>r.substr(e,t),p=(e=0,r,t,a,n=0,s,u)=>{for(;(t=o.space())&&(u=v[t]?.(a,e)||!a&&c(t));)a=u;return r&&t!==r&&l("Unclosed paren"),a},i=(o.space=r=>{for(;(r=u())<=32;)e++;return r},o.token=[]),c=(e,r=0,t)=>{for(;r<i.length;)if(t=i[r++](e))return t},v=[],d=(o.operator=(r,t=0,a=0,n,i=r.charCodeAt(0),c=r.length,d=v[i],h=r.toUpperCase()!==r,y)=>(y=c<2?h?e=>u(1)<=32:e=>1:h?e=>f(c)==r&&u(c)<=32:e=>f(c)==r,n=a?a>0?e=>e&&[s(c),e]:a<0?e=>!e&&[s(c),(p(t-1)||l()).valueOf()]:a:a=>{a=[r,a||l()];do{e+=c,a.push((p(t)||l()).valueOf())}while(o.space()==i&&y());return a},v[i]=(e,r)=>r<t&&y()&&n(e)||d&&d(e,r)),10),h=15,y=e=>({valueOf:()=>e});o.token.push((e=>(e=s((e=>e>47&&e<58||46==e)))&&((69==u()||101==u())&&(e+=s(2)+s((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?l("Bad number"):e)),((e,r,t,a)=>{if(34===e||39===e){for(r=f(),s(),a="";(t=u())-e;)92===t?(s(),a+=g[f()]||f()):a+=f(),s();return s(),r+a+r}}),(e=>116===e&&"true"===f(4)&&s(4)?y(!0):102===e&&"false"===f(5)&&s(5)?y(!1):110===e&&"null"===f(4)&&s(4)?y(null):117===e&&"undefined"===f(9)&&s(9)?y(void 0):null),(e=>s((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e))));var g={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"};o.space=e=>{for(;(e=u())<=32;)s(),47===u()&&(42===u(1)?(s(2),s((e=>42!==e&&47!==u(1))),s(2)):47===u(1)&&(s(2),s((e=>e>=32))));return e};var O=(e,r=2,t)=>{for(let a=0;a<t.length;a+=r)e(t[a],t[a+1],t[a+2])};O(o.operator,3,[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",d,,">=",d,,">>",11,,">>>",11,,"<",d,,"<=",d,,"<<",11,,"+",12,,"+",h,-1,"++",h,-1,"++",h,1,"-",12,,"-",h,-1,"--",h,-1,"--",h,1,"!",h,-1,"*",13,,"/",13,,"%",13,,".",18,(e,r)=>e&&[s(),e,"string"==typeof(r=p(18))?'"'+r+'"':r.valueOf()],"[",18,e=>(s(),e=[".",e,p(0,93).valueOf()],s(),e),"]",,,"(",18,(e,r)=>(s(),r=p(0,41),s(),Array.isArray(r)&&","===r[0]?(r[0]=e,r):r?[e,r.valueOf()]:[e]),"(",19,(e,r)=>!e&&(s(),r=p(0,41)||l(),s(),r),")",,,";",1,,"===",9,,"!==",9,,"**",14,,"~",h,-1,"?",3,e=>{let r,t;return e||l("Expected expression"),s(),o.space(),r=p(),58!==u()&&l("Expected :"),s(),o.space(),t=p(),["?:",e,r,t]},"}",,,":",,,"in",d,e=>u(2)<=32&&[s(2),'"'+e+'"',p(d)],"[",20,(e,r)=>!e&&(s(),r=p(0,93),s(),r?","==r[0]?(r[0]="[",r):["[",r]:["["]),"{",20,(e,r)=>!e&&(s(),r=p(0,125),s(),r?":"==r[0]?["{",r]:","==r[0]?(r[0]="{",r):["[",r]:["{"])]),O(a.operator,2,["!",e=>!e,"++",e=>++e,"--",e=>--e,".",(e,r)=>e&&e[r],"%",(e,r)=>e%r,"/",(e,r)=>e/r,"*",(e,r)=>e*r,"+",(e,r)=>e+r,"-",(...e)=>e.length<2?-e:e.reduce(((e,r)=>e-r)),">>>",(e,r)=>e>>>r,">>",(e,r)=>e>>r,"<<",(e,r)=>e<<r,">=",(e,r)=>e>=r,">",(e,r)=>e>r,"<=",(e,r)=>e<=r,"<",(e,r)=>e<r,"!=",(e,r)=>e!=r,"==",(e,r)=>e==r,"&",(e,r)=>e&r,"^",(e,r)=>e^r,"|",(e,r)=>e|r,"&&",(...e)=>e.every(Boolean),"||",(...e)=>e.some(Boolean),",",(e,r)=>r,"**",(...e)=>e.reduceRight(((e,r)=>Math.pow(r,e))),"~",e=>~e,"?:",(e,r,t)=>e?r:t,"in",(e,r)=>e in r,"[",(...e)=>Array(...e),"{",(...e)=>Object.fromEntries(e),":",(e,r)=>[e,r]]);var b=e=>(e="string"==typeof e?o(e):e,r=>a(e,r));export{b as default,a as evaluate,o as parse};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "subscript",
3
- "version": "5.0.0",
3
+ "version": "5.2.2",
4
4
  "description": "Microlanguage with common syntax for JS/C++/Python/Rust",
5
5
  "main": "subscript.js",
6
6
  "type": "module",
package/parse.js CHANGED
@@ -1,13 +1,9 @@
1
- const PERIOD=46, OPAREN=40, CPAREN=41, CBRACK=93, SPACE=32,
2
-
3
- PREC_SEQ=1, PREC_SOME=4, PREC_EVERY=5, PREC_OR=6, PREC_XOR=7, PREC_AND=8,
4
- PREC_EQ=9, PREC_COMP=10, PREC_SHIFT=11, PREC_SUM=12, PREC_MULT=13, PREC_UNARY=15, PREC_POSTFIX=16, PREC_CALL=18, PREC_GROUP=19
5
-
1
+ const SPACE=32
6
2
 
7
3
  // current string & index
8
4
  let idx, cur
9
5
 
10
- export const parse = (str, tree) => (cur=str, idx=0, tree=expr(), idx<cur.length ? err() : tree.valueOf()),
6
+ export const parse = (str, tree) => (cur=str, idx=0, tree=expr(), idx<cur.length ? err() : val(tree)),
11
7
 
12
8
  err = (msg='Bad syntax') => { throw Error(msg + ' `' + cur[idx] + '` at ' + idx) },
13
9
 
@@ -37,26 +33,7 @@ expr = (prec=0, end, cc, node, i=0, map, newNode) => {
37
33
  space = parse.space = cc => { while (cc = code(), cc <= SPACE) idx++; return cc },
38
34
 
39
35
  // tokens
40
- tokens = parse.token = [
41
- // 1.2e+3, .5 - fast & small version, but consumes corrupted nums as well
42
- (number) => (
43
- (number = skip(c => (c > 47 && c < 58) || c == PERIOD)) && (
44
- (code() == 69 || code() == 101) && (number += skip(2) + skip(c => c >= 48 && c <= 57)),
45
- isNaN(number = new Number(number)) ? err('Bad number') : number
46
- )
47
- ),
48
- // "a"
49
- (q, qc) => q == 34 && (skip() + skip(c => c-q) + skip()),
50
- // id
51
- c => skip(c =>
52
- (c >= 48 && c <= 57) || // 0..9
53
- (c >= 65 && c <= 90) || // A...Z
54
- (c >= 97 && c <= 122) || // a...z
55
- c == 36 || c == 95 || // $, _,
56
- (c >= 192 && c != 215 && c != 247) // any non-ASCII
57
- )
58
- ],
59
-
36
+ tokens = parse.token = [],
60
37
  token = (c,i=0,node) => { while(i<tokens.length) if (node = tokens[i++](c)) return node },
61
38
 
62
39
  // operator lookup table
@@ -66,83 +43,23 @@ lookup = [],
66
43
  // @param op is operator string
67
44
  // @param prec is operator precedenc to check
68
45
  // @param map is either number +1 - postfix unary, -1 prefix unary, 0 binary, else - custom mapper function
69
- operator = (op, prec=0, type=0, map, c=op.charCodeAt(0), l=op.length, prev=lookup[c], word=op.toUpperCase()!==op, isop) => (
70
- isop = l<2 ? // word operator must have space after
71
- !word ? c=>1 : c=>code(1)<=SPACE :
72
- !word ? c=>char(l)==op : c=>char(l)==op&&code(l)<=SPACE,
73
-
46
+ operator = parse.operator = (op, prec=0, type=0, map, c=op.charCodeAt(0), l=op.length, prev=lookup[c], word=op.toUpperCase()!==op, isop) => (
74
47
  map = !type ? node => { // binary, consume same-op group
75
48
  node = [op, node || err()]
76
- // in order to support literal tokens, we call valueOf any time we create or modify calltree node
77
- do { idx+=l, node.push((expr(prec) || err()).valueOf()) } while (parse.space()==c && isop())
49
+ do { idx+=l, node.push(val(expr(prec))) }
50
+ while (parse.space()==c && (l<2||char(l)==op) && (!word||code(l)<=SPACE)) // word operator must have space after
78
51
  return node
79
52
  } :
80
- type > 0 ? node => node && [skip(l), node] : // postfix unary
81
- type < 0 ? node => !node && [skip(l), (expr(prec-1) || err()).valueOf()] : // prefix unary
53
+ type > 0 ? node => node && [skip(l), val(node)] : // postfix unary
54
+ type < 0 ? node => !node && [skip(l), val(expr(prec-1))] : // prefix unary
82
55
  type,
83
56
 
84
- lookup[c] = (node, curPrec) => curPrec < prec && isop() && map(node) || (prev && prev(node, curPrec))
85
- )
86
-
87
- // ,
88
- for (let i = 0, ops = [
89
- // TODO: add ,, as node here
90
- ',', PREC_SEQ,,
91
-
92
- '|', PREC_OR,,
93
- '||', PREC_SOME,,
94
-
95
- '&', PREC_AND,,
96
- '&&', PREC_EVERY,,
97
-
98
- '^', PREC_XOR,,
99
-
100
- // ==, !=
101
- '==', PREC_EQ,,
102
- '!=', PREC_EQ,,
103
-
104
- // > >= >> >>>, < <= <<
105
- '>', PREC_COMP,,
106
- '>=', PREC_COMP,,
107
- '>>', PREC_SHIFT,,
108
- '>>>', PREC_SHIFT,,
109
- '<', PREC_COMP,,
110
- '<=', PREC_COMP,,
111
- '<<', PREC_SHIFT,,
112
-
113
- // + ++ - --
114
- '+', PREC_SUM,,
115
- '+', PREC_UNARY, -1,
116
- '++', PREC_UNARY, -1,
117
- '++', PREC_UNARY, +1,
118
- '-', PREC_SUM,,
119
- '-', PREC_UNARY, -1,
120
- '--', PREC_UNARY, -1,
121
- '--', PREC_UNARY, +1,
122
-
123
- // ! ~
124
- '!', PREC_UNARY, -1,
125
-
126
- // * / %
127
- '*', PREC_MULT,,
128
- '/', PREC_MULT,,
129
- '%', PREC_MULT,,
130
-
131
- // a.b
132
- '.', PREC_CALL, (node,b) => node && [skip(),node, typeof (b = expr(PREC_CALL)) === 'string' ? '"' + b + '"' : b.valueOf()],
133
-
134
- // a[b]
135
- '[', PREC_CALL, (node) => (idx++, node = ['.', node, expr(0,CBRACK).valueOf()], idx++, node),
136
- ']',,,
137
-
138
- // a(b)
139
- '(', PREC_CALL, (node,b) => ( idx++, b=expr(0,CPAREN), idx++,
140
- Array.isArray(b) && b[0]===',' ? (b[0]=node, b) : b ? [node, b.valueOf()] : [node]
141
- ),
142
- // (a+b)
143
- '(', PREC_GROUP, (node,b) => !node && (++idx, b=expr(0,CPAREN) || err(), ++idx, b),
144
- ')',,,
145
- ]; i < ops.length;) operator(ops[i++],ops[i++],ops[i++])
57
+ lookup[c] = (node, curPrec) =>
58
+ curPrec < prec && (l<2||char(l)==op) && (!word||code(l)<=SPACE) &&
59
+ map(node) || (prev && prev(node, curPrec))
60
+ ),
146
61
 
62
+ // in order to support literal tokens, we call valueOf any time we create or modify calltree node
63
+ val = node => Array.isArray(node) ? node : (node || err()).valueOf()
147
64
 
148
65
  export default parse
package/subscript.js CHANGED
@@ -1,5 +1,128 @@
1
- import parse from './parse.js'
2
- import evaluate from './evaluate.js'
1
+ import parse, {skip, expr, code, tokens, operator as parseOp} from './parse.js'
2
+ import evaluate, {operator as evalOp} from './evaluate.js'
3
+
4
+ const PERIOD=46, OPAREN=40, CPAREN=41, CBRACK=93, SPACE=32,
5
+
6
+ PREC_SEQ=1, PREC_SOME=4, PREC_EVERY=5, PREC_OR=6, PREC_XOR=7, PREC_AND=8,
7
+ PREC_EQ=9, PREC_COMP=10, PREC_SHIFT=11, PREC_SUM=12, PREC_MULT=13, PREC_UNARY=15, PREC_POSTFIX=16, PREC_CALL=18, PREC_GROUP=19
8
+
9
+ tokens.push(
10
+ // 1.2e+3, .5 - fast & small version, but consumes corrupted nums as well
11
+ (number) => (
12
+ (number = skip(c => (c > 47 && c < 58) || c == PERIOD)) && (
13
+ (code() == 69 || code() == 101) && (number += skip(2) + skip(c => c >= 48 && c <= 57)),
14
+ isNaN(number = new Number(number)) ? err('Bad number') : number
15
+ )
16
+ ),
17
+ // "a"
18
+ (q, qc) => q == 34 && (skip() + skip(c => c-q) + skip()),
19
+ // id
20
+ c => skip(c =>
21
+ (c >= 48 && c <= 57) || // 0..9
22
+ (c >= 65 && c <= 90) || // A...Z
23
+ (c >= 97 && c <= 122) || // a...z
24
+ c == 36 || c == 95 || // $, _,
25
+ c >= 192 // any non-ASCII
26
+ )
27
+ )
28
+
29
+ const addOps = (add, stride=2, list) => {
30
+ for (let i = 0; i < list.length; i+=stride) add(list[i], list[i+1], list[i+2])
31
+ }
32
+
33
+ addOps(parseOp, 3, [
34
+ ',', PREC_SEQ,,
35
+
36
+ '|', PREC_OR,,
37
+ '||', PREC_SOME,,
38
+
39
+ '&', PREC_AND,,
40
+ '&&', PREC_EVERY,,
41
+
42
+ '^', PREC_XOR,,
43
+
44
+ // ==, !=
45
+ '==', PREC_EQ,,
46
+ '!=', PREC_EQ,,
47
+
48
+ // > >= >> >>>, < <= <<
49
+ '>', PREC_COMP,,
50
+ '>=', PREC_COMP,,
51
+ '>>', PREC_SHIFT,,
52
+ '>>>', PREC_SHIFT,,
53
+ '<', PREC_COMP,,
54
+ '<=', PREC_COMP,,
55
+ '<<', PREC_SHIFT,,
56
+
57
+ // + ++ - --
58
+ '+', PREC_SUM,,
59
+ '+', PREC_UNARY, -1,
60
+ '++', PREC_UNARY, -1,
61
+ '++', PREC_UNARY, +1,
62
+ '-', PREC_SUM,,
63
+ '-', PREC_UNARY, -1,
64
+ '--', PREC_UNARY, -1,
65
+ '--', PREC_UNARY, +1,
66
+
67
+ // ! ~
68
+ '!', PREC_UNARY, -1,
69
+
70
+ // * / %
71
+ '*', PREC_MULT,,
72
+ '/', PREC_MULT,,
73
+ '%', PREC_MULT,,
74
+
75
+ // a.b
76
+ '.', PREC_CALL, (node,b) => node && [skip(),node, typeof (b = expr(PREC_CALL)) === 'string' ? '"' + b + '"' : b.valueOf()],
77
+
78
+ // a[b]
79
+ '[', PREC_CALL, (node) => (skip(), node = ['.', node, expr(0,CBRACK).valueOf()], skip(), node),
80
+ ']',,,
81
+
82
+ // a(b)
83
+ '(', PREC_CALL, (node,b) => ( skip(), b=expr(0,CPAREN), skip(),
84
+ Array.isArray(b) && b[0]===',' ? (b[0]=node, b) : b ? [node, b.valueOf()] : [node]
85
+ ),
86
+ // (a+b)
87
+ '(', PREC_GROUP, (node,b) => !node && (skip(), b=expr(0,CPAREN) || err(), skip(), b),
88
+ ')',,,
89
+ ])
90
+
91
+
92
+ // evaluators
93
+ addOps(evalOp, 2, [
94
+ '!', a=>!a,
95
+ '++', a=>++a,
96
+ '--', a=>--a,
97
+
98
+ '.', (a,b)=>a?a[b]:a,
99
+
100
+ '%', (a,b)=>a%b,
101
+ '/', (a,b)=>a/b,
102
+ '*', (a,b)=>a*b,
103
+
104
+ '+', (a,b)=>a+b,
105
+ '-', (...a)=>a.length < 2 ? -a : a.reduce((a,b)=>a-b),
106
+
107
+ '>>>', (a,b)=>a>>>b,
108
+ '>>', (a,b)=>a>>b,
109
+ '<<', (a,b)=>a<<b,
110
+
111
+ '>=', (a,b)=>a>=b,
112
+ '>', (a,b)=>a>b,
113
+ '<=', (a,b)=>a<=b,
114
+ '<', (a,b)=>a<b,
115
+
116
+ '!=', (a,b)=>a!=b,
117
+ '==', (a,b)=>a==b,
118
+
119
+ '&', (a,b)=>a&b,
120
+ '^', (a,b)=>a^b,
121
+ '|', (a,b)=>a|b,
122
+ '&&', (...a)=>a.every(Boolean),
123
+ '||', (...a)=>a.some(Boolean),
124
+ ',', (a,b)=>(a,b)
125
+ ])
3
126
 
4
127
  export { parse, evaluate }
5
128
 
package/subscript.min.js CHANGED
@@ -1 +1 @@
1
- var e,r,a=15,t=(a,t)=>(r=a,e=0,t=f(),e<r.length?o():t.valueOf()),o=(a="Bad syntax")=>{throw Error(a+" `"+r[e]+"` at "+e)},n=(a=1,t=e)=>{if("number"==typeof a)e+=a;else for(;a(s());)e++;return r.slice(t,e)},s=(a=0)=>r.charCodeAt(e+a),l=(a=1)=>r.substr(e,a),f=(e=0,r,a,n,s=0,l,f)=>{for(;(a=t.space())&&(f=i[a]?.(n,e)||!n&&p(a));)n=f;return r&&a!==r&&o("Unclosed paren"),n},u=(t.space=r=>{for(;(r=s())<=32;)e++;return r},t.token=[e=>(e=n((e=>e>47&&e<58||46==e)))&&((69==s()||101==s())&&(e+=n(2)+n((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?o("Bad number"):e),(e,r)=>34==e&&n()+n((r=>r-e))+n(),e=>n((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e))]),p=(e,r=0,a)=>{for(;r<u.length;)if(a=u[r++](e))return a},i=[],c=(r,a=0,u=0,p,c=r.charCodeAt(0),y=r.length,g=i[c],h=r.toUpperCase()!==r,v)=>(v=y<2?h?e=>s(1)<=32:e=>1:h?e=>l(y)==r&&s(y)<=32:e=>l(y)==r,p=u?u>0?e=>e&&[n(y),e]:u<0?e=>!e&&[n(y),(f(a-1)||o()).valueOf()]:u:n=>{n=[r,n||o()];do{e+=y,n.push((f(a)||o()).valueOf())}while(t.space()==c&&v());return n},i[c]=(e,r)=>r<a&&v()&&p(e)||g&&g(e,r));for(let r=0,t=[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",a,-1,"++",a,-1,"++",a,1,"-",12,,"-",a,-1,"--",a,-1,"--",a,1,"!",a,-1,"*",13,,"/",13,,"%",13,,".",18,(e,r)=>e&&[n(),e,"string"==typeof(r=f(18))?'"'+r+'"':r.valueOf()],"[",18,r=>(e++,r=[".",r,f(0,93).valueOf()],e++,r),"]",,,"(",18,(r,a)=>(e++,a=f(0,41),e++,Array.isArray(a)&&","===a[0]?(a[0]=r,a):a?[r,a.valueOf()]:[r]),"(",19,(r,a)=>!r&&(++e,a=f(0,41)||o(),++e,a),")",,,];r<t.length;)c(t[r++],t[r++],t[r++]);var y=t,g=e=>Array.isArray(e)&&("string"==typeof e[0]||g(e[0])),h=(e,r={},a,t)=>g(e)?("string"==typeof(a=e[0])&&(t=d[a]),"function"!=typeof(a=t||h(a,r))?a:a.call(...e.map((e=>h(e,r))))):e&&"string"==typeof e?'"'===e[0]?e.slice(1,-1):"@"===e[0]?e.slice(1):e in r?r[e]:e:e,v=e=>(...r)=>r.reduce(e),d=h.operator={"!":e=>!e,"++":e=>++e,"--":e=>--e,".":v(((e,r)=>e&&e[r])),"%":v(((e,r)=>e%r)),"/":v(((e,r)=>e/r)),"*":v(((e,r)=>e*r)),"+":v(((e,r)=>e+r)),"-":(...e)=>e.length<2?-e:e.reduce(((e,r)=>e-r)),">>>":(e,r)=>e>>>r,">>":(e,r)=>e>>r,"<<":(e,r)=>e<<r,">=":(e,r)=>e>=r,">":(e,r)=>e>r,"<=":(e,r)=>e<=r,"<":(e,r)=>e<r,"!=":(e,r)=>e!=r,"==":(e,r)=>e==r,"&":(e,r)=>e&r,"^":(e,r)=>e^r,"|":(e,r)=>e|r,"&&":(...e)=>e.every(Boolean),"||":(...e)=>e.some(Boolean),",":v(((e,r)=>r))},A=h,O=e=>(e="string"==typeof e?y(e):e,r=>A(e,r));export{O as default,A as evaluate,y as parse};
1
+ var e,r,a=(a,o)=>(r=a,e=0,o=l(),e<r.length?t():y(o)),t=(a="Bad syntax")=>{throw Error(a+" `"+r[e]+"` at "+e)},o=(a=1,t=e)=>{if("number"==typeof a)e+=a;else for(;a(n());)e++;return r.slice(t,e)},n=(a=0)=>r.charCodeAt(e+a),s=(a=1)=>r.substr(e,a),l=(e=0,r,o,n,s=0,l,f)=>{for(;(o=a.space())&&(f=u[o]?.(n,e)||!n&&p(o));)n=f;return r&&o!==r&&t("Unclosed paren"),n},f=(a.space=r=>{for(;(r=n())<=32;)e++;return r},a.token=[]),p=(e,r=0,a)=>{for(;r<f.length;)if(a=f[r++](e))return a},u=[],i=a.operator=(r,f=0,p=0,i,c=r.charCodeAt(0),h=r.length,g=u[c],d=r.toUpperCase()!==r,v)=>(i=p?p>0?e=>e&&[o(h),y(e)]:p<0?e=>!e&&[o(h),y(l(f-1))]:p:o=>{o=[r,o||t()];do{e+=h,o.push(y(l(f)))}while(a.space()==c&&(h<2||s(h)==r)&&(!d||n(h)<=32));return o},u[c]=(e,a)=>a<f&&(h<2||s(h)==r)&&(!d||n(h)<=32)&&i(e)||g&&g(e,a)),y=e=>Array.isArray(e)?e:(e||t()).valueOf(),c=a,h=e=>Array.isArray(e)&&("string"==typeof e[0]||h(e[0])),g=(e,r={},a,t)=>h(e)?("string"==typeof(a=e[0])&&(t=d[a]),"function"!=typeof(a=t||g(a,r))?a:a.call(...e.map((e=>g(e,r))))):e&&"string"==typeof e?'"'===e[0]?e.slice(1,-1):"@"===e[0]?e.slice(1):e in r?r[e]:e:e,d={},v=g.operator=(e,r)=>d[e]=2==r.length?(...e)=>e.reduce(r):r,A=g,m=15;f.push((e=>(e=o((e=>e>47&&e<58||46==e)))&&((69==n()||101==n())&&(e+=o(2)+o((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?err("Bad number"):e)),((e,r)=>34==e&&o()+o((r=>r-e))+o()),(e=>o((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192))));var b=(e,r=2,a)=>{for(let t=0;t<a.length;t+=r)e(a[t],a[t+1],a[t+2])};b(i,3,[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",m,-1,"++",m,-1,"++",m,1,"-",12,,"-",m,-1,"--",m,-1,"--",m,1,"!",m,-1,"*",13,,"/",13,,"%",13,,".",18,(e,r)=>e&&[o(),e,"string"==typeof(r=l(18))?'"'+r+'"':r.valueOf()],"[",18,e=>(o(),e=[".",e,l(0,93).valueOf()],o(),e),"]",,,"(",18,(e,r)=>(o(),r=l(0,41),o(),Array.isArray(r)&&","===r[0]?(r[0]=e,r):r?[e,r.valueOf()]:[e]),"(",19,(e,r)=>!e&&(o(),r=l(0,41)||err(),o(),r),")",,,]),b(v,2,["!",e=>!e,"++",e=>++e,"--",e=>--e,".",(e,r)=>e&&e[r],"%",(e,r)=>e%r,"/",(e,r)=>e/r,"*",(e,r)=>e*r,"+",(e,r)=>e+r,"-",(...e)=>e.length<2?-e:e.reduce(((e,r)=>e-r)),">>>",(e,r)=>e>>>r,">>",(e,r)=>e>>r,"<<",(e,r)=>e<<r,">=",(e,r)=>e>=r,">",(e,r)=>e>r,"<=",(e,r)=>e<=r,"<",(e,r)=>e<r,"!=",(e,r)=>e!=r,"==",(e,r)=>e==r,"&",(e,r)=>e&r,"^",(e,r)=>e^r,"|",(e,r)=>e|r,"&&",(...e)=>e.every(Boolean),"||",(...e)=>e.some(Boolean),",",(e,r)=>r]);var B=e=>(e="string"==typeof e?c(e):e,r=>A(e,r));export{B as default,A as evaluate,c as parse};