subscript 5.1.0 → 5.2.3

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=indianred"/></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,7 +30,7 @@ _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/5.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
36
  ## Evaluation
@@ -49,6 +52,8 @@ evaluate(['+', ['*', 'min', 60], '"sec"'], { min: 5 }) // min*60 + "sec" == "300
49
52
 
50
53
  ## Extending
51
54
 
55
+ ### Operators
56
+
52
57
  Default operators include common operators for the listed languages in the following precedence:
53
58
 
54
59
  * `++ --` unary postfix
@@ -83,14 +88,15 @@ let tree = parse(`
83
88
  evaluate(tree, { Math, map, take, interval, gaussian })
84
89
  ```
85
90
 
86
- ---
91
+ ### Tokens
87
92
 
88
- Tokens are extensible via `parse.token` list, can be added support of _literals_, _regexes_, _strings_, _numbers_ and others.
89
93
  Default tokens include:
90
94
 
91
95
  * `"abc"` strings
92
96
  * `1.2e+3` floats
93
- * identifiers
97
+ * `name` identifiers
98
+
99
+ Tokens are extensible via `parse.token` list, can be added support of _literals_, _regexes_, _strings_, _numbers_ and others.
94
100
 
95
101
  ```js
96
102
  import parse, {char} from 'subscript/parse.js'
@@ -101,7 +107,7 @@ parse.token.unshift(c => char(4) === 'this' ? ctx : null)
101
107
  evaluate(parse(`this.x`)) // 1
102
108
  ```
103
109
 
104
- ---
110
+ ### Spaces/comments
105
111
 
106
112
  Comments can be added via extending `parse.space`. See [justin.js](./justin.js) for more examples.
107
113
 
@@ -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: ~220 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
@@ -22,38 +22,4 @@ lookup = {},
22
22
  // multiple args allows shortcuts, lisp compatible, easy manual eval, functions anyways take multiple arguments
23
23
  operator = evaluate.operator = (op, fn) => lookup[op] = fn.length == 2 ? (...a)=>a.reduce(fn) : fn
24
24
 
25
- for (let fn,ops = [
26
- '!', a=>!a,
27
- '++', a=>++a,
28
- '--', a=>--a,
29
-
30
- '.', (a,b)=>a?a[b]:a,
31
-
32
- '%', (a,b)=>a%b,
33
- '/', (a,b)=>a/b,
34
- '*', (a,b)=>a*b,
35
-
36
- '+', (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
- ',', (a,b)=>(a,b)
57
- ]; fn=ops.pop();) operator(ops.pop(),fn)
58
-
59
25
  export default evaluate
package/justin.js CHANGED
@@ -1,61 +1,134 @@
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, err} from './parse.js'
3
+ import {parse, code, char, skip, expr, err, val} from './parse.js'
4
4
 
5
- // literals
6
- const v = v => ({valueOf:()=>v})
7
- parse.token.splice(2,0, c =>
8
- c === 116 && char(4) === 'true' && skip(4) ? v(true) :
9
- c === 102 && char(5) === 'false' && skip(5) ? v(false) :
10
- c === 110 && char(4) === 'null' && skip(4) ? v(null) :
11
- c === 117 && char(9) === 'undefined' && skip(9) ? v(undefined) :
12
- null
5
+ const PERIOD=46, OPAREN=40, CPAREN=41, CBRACK=93, SPACE=32,
6
+
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
10
+
11
+
12
+ // tokens
13
+ parse.token.push(
14
+ // 1.2e+3, .5 - fast & small version, but consumes corrupted nums as well
15
+ (number) => (
16
+ (number = skip(c => (c > 47 && c < 58) || c == PERIOD)) && (
17
+ (code() == 69 || code() == 101) && (number += skip(2) + skip(c => c >= 48 && c <= 57)),
18
+ isNaN(number = new Number(number)) ? err('Bad number') : number
19
+ )
20
+ ),
21
+
22
+ // "' with /
23
+ (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
+
33
+ // id
34
+ c => skip(c =>
35
+ (c >= 48 && c <= 57) || // 0..9
36
+ (c >= 65 && c <= 90) || // A...Z
37
+ (c >= 97 && c <= 122) || // a...z
38
+ c == 36 || c == 95 || // $, _,
39
+ (c >= 192 && c != 215 && c != 247) // any non-ASCII
40
+ )
13
41
  )
14
42
 
15
- // "' with /
16
- parse.token[1] = (q, qc, c, str) => {
17
- if (q !== 34 && q !== 39) return
18
- qc = char(), skip(), str = ''
19
- while (c=code(), c-q) {
20
- if (c === 92) skip(), str += escape[char()] || char(); else str+=char()
21
- skip()
22
- }
23
- return skip(), qc + str + qc
24
- }
25
43
  const escape = {n:'\n', r:'\r', t:'\t', b:'\b', f:'\f', v:'\v'}
26
44
 
45
+
27
46
  // /**/, //
28
47
  parse.space = cc => {
29
- while (cc = code(), cc <= 32) {
30
- skip()
31
- if (code() === 47)
48
+ while (cc = code(), cc <= 32 || cc === 47) {
49
+ if (cc <= 32) skip()
50
+ else if (cc === 47)
32
51
  // /**/
33
52
  if (code(1) === 42) skip(2), skip(c => c !== 42 && code(1) !== 47), skip(2)
34
53
  // //
35
54
  else if (code(1) === 47) skip(2), skip(c => c >= 32)
55
+ else break
36
56
  }
37
57
  return cc
38
58
  }
39
59
 
40
- // {}
41
- parse.token.unshift((cc, node) => (
42
- cc === 123 && (skip(), node = map(['{', expr(0,125)]), skip(), node)
43
- ))
44
- const map = (n, args) => {
45
- if (!n[1]) args = []
46
- else if (n[1][0]==':') args = [n[1]]
47
- else if (n[1][0]==',') args = n[1].slice(1)
48
- return ['{', ...args]
60
+
61
+ // operators
62
+ const addOps = (add, stride=2, list) => {
63
+ for (let i = 0; i < list.length; i+=stride) add(list[i], list[i+1], list[i+2])
49
64
  }
50
65
 
51
- // parse operators
52
- for (let i = 0, ops = [
53
- ';', 1,,
54
- '===', 9,,
55
- '!==', 9,,
56
- '**', 14,,
57
- '~', 13, -1,
58
- '?', 3, (node) => {
66
+ addOps(parse.operator, 3, [
67
+ // subscript ones
68
+ // TODO: add ,, as node here?
69
+ ',', PREC_SEQ,,
70
+
71
+ '|', PREC_OR,,
72
+ '||', PREC_SOME,,
73
+
74
+ '&', PREC_AND,,
75
+ '&&', PREC_EVERY,,
76
+
77
+ '^', PREC_XOR,,
78
+
79
+ // ==, !=
80
+ '==', PREC_EQ,,
81
+ '!=', PREC_EQ,,
82
+
83
+ // > >= >> >>>, < <= <<
84
+ '>', PREC_COMP,,
85
+ '>=', PREC_COMP,,
86
+ '>>', PREC_SHIFT,,
87
+ '>>>', PREC_SHIFT,,
88
+ '<', PREC_COMP,,
89
+ '<=', PREC_COMP,,
90
+ '<<', PREC_SHIFT,,
91
+
92
+ // + ++ - --
93
+ '+', PREC_SUM,,
94
+ '+', PREC_UNARY, -1,
95
+ '++', PREC_UNARY, -1,
96
+ '++', PREC_UNARY, +1,
97
+ '-', PREC_SUM,,
98
+ '-', PREC_UNARY, -1,
99
+ '--', PREC_UNARY, -1,
100
+ '--', PREC_UNARY, +1,
101
+
102
+ // !
103
+ '!', PREC_UNARY, -1,
104
+
105
+ // * / %
106
+ '*', PREC_MULT,,
107
+ '/', PREC_MULT,,
108
+ '%', PREC_MULT,,
109
+
110
+ // a.b
111
+ '.', PREC_CALL, (node,b) => node && [skip(),node, typeof (b = expr(PREC_CALL)) === 'string' ? '"' + b + '"' : b.valueOf()],
112
+
113
+ // a[b]
114
+ '[', PREC_CALL, (node) => (skip(), node = ['.', node, val(expr(0,CBRACK))], skip(), node),
115
+ ']',,,
116
+
117
+ // a(b)
118
+ '(', PREC_CALL, (node,b) => ( skip(), b=expr(0,CPAREN), skip(),
119
+ Array.isArray(b) && b[0]===',' ? (b[0]=node, b) : b ? [node, val(b)] : [node]
120
+ ),
121
+ // (a+b)
122
+ '(', PREC_GROUP, (node,b) => !node && (skip(), b=expr(0,CPAREN) || err(), skip(), b),
123
+ ')',,,
124
+
125
+ // justin extension
126
+ ';', PREC_SEQ,,
127
+ '===', PREC_EQ,,
128
+ '!==', PREC_EQ,,
129
+ '**', PREC_EXP,,
130
+ '~', PREC_UNARY, -1,
131
+ '?', PREC_TERN, (node) => {
59
132
  if (!node) err('Expected expression')
60
133
  let a, b
61
134
  skip(), parse.space(), a = expr()
@@ -64,37 +137,78 @@ for (let i = 0, ops = [
64
137
  return ['?:', node, a, b]
65
138
  },
66
139
  '}',,,
67
- ':', 0,,
68
- 'in', 10, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(10)],
69
- '[', 20, (node,arg) => !node && (
140
+ ':',,,
141
+ 'in', PREC_COMP, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(PREC_COMP)],
142
+
143
+ // as operator it's faster to lookup (no need to extra rule check), smaller and no conflict with word names
144
+ // [a,b,c]
145
+ '[', PREC_TOKEN, (node,arg) => !node && (
70
146
  skip(), arg=expr(0,93), skip(),
71
- !arg ? ['['] : arg[0] === ',' ? (arg[0]='[',arg) : ['[',arg]
72
- )
73
- ]; i < ops.length;) parse.operator(ops[i++],ops[i++],ops[i++])
147
+ !arg ? ['['] : arg[0] == ',' ? (arg[0]='[',arg) : ['[',arg]
148
+ ),
74
149
 
75
- // evaluate operators
76
- for (let i = 0, ops = [
77
- // **
78
- '**', (...args)=>args.reduceRight((a,b)=>Math.pow(b,a)),
150
+ // {a:0, b:1}
151
+ '{', PREC_TOKEN, (node,arg) => !node && (skip(), arg=expr(0,125), skip(),
152
+ !arg ? ['{'] : arg[0] == ':' ? ['{',arg] : arg[0] == ',' ? (arg[0]='{',arg) : ['{',arg])
153
+ ,
79
154
 
80
- // ~
81
- '~', a=>~a,
155
+ // literals
156
+ 'null', PREC_TOKEN, node=>!node&&(skip(4),v(null)),
157
+ 'false', PREC_TOKEN, node=>!node&&(skip(5),v(false)),
158
+ 'true', PREC_TOKEN, node=>!node&&(skip(4),v(true)),
159
+ 'undefined', PREC_TOKEN, node=>!node&&(skip(9),v(undefined)),
160
+ ])
161
+ const v = v => ({valueOf:()=>v})
162
+
163
+ addOps(evaluate.operator, 2, [
164
+ // subscript
165
+ '!', a=>!a,
166
+ '++', a=>++a,
167
+ '--', a=>--a,
82
168
 
83
- // ?:
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,
84
200
  '?:', (a,b,c)=>a?b:c,
85
- // parse.operator(':')
86
- // in
87
201
  'in', (a,b)=>a in b,
88
202
 
89
- // []
90
203
  '[', (...args) => Array(...args),
91
- // as operator it's faster to lookup (no need to call extra rule check), smaller and no conflict with word names
92
204
  '{', (...args)=>Object.fromEntries(args),
93
205
  ':', (a,b)=>[a,b]
94
- ]; i < ops.length;) evaluate.operator(ops[i++],ops[i++])
206
+ ])
95
207
 
96
208
  // TODO ...
97
209
  // TODO: strings interpolation
98
210
 
99
- export default parse
100
211
  export { parse, evaluate }
212
+
213
+ // code → evaluator
214
+ 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=>Array.isArray(r)&&("string"==typeof r[0]||e(r[0])),r=(a,n={},o,l)=>e(a)?("string"==typeof(o=a[0])&&(l=t[o]),"function"!=typeof(o=l||r(o,n))?o:o.call(...a.map((e=>r(e,n))))):a&&"string"==typeof a?'"'===a[0]?a.slice(1,-1):"@"===a[0]?a.slice(1):a in n?n[a]:a:a,t={},a=r.operator=(e,r)=>t[e]=2==r.length?(...e)=>e.reduce(r):r;for(let e,r=["!",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=r.pop();)a(r.pop(),e);var n,o,l=15,s=(e,r)=>(o=e,n=0,r=c(),n<o.length?f():r.valueOf()),f=(e="Bad syntax")=>{throw Error(e+" `"+o[n]+"` at "+n)},p=(e=1,r=n)=>{if("number"==typeof e)n+=e;else for(;e(u());)n++;return o.slice(r,n)},u=(e=0)=>o.charCodeAt(n+e),i=(e=1)=>o.substr(n,e),c=(e=0,r,t,a,n=0,o,l)=>{for(;(t=s.space())&&(l=d[t]?.(a,e)||!a&&h(t));)a=l;return r&&t!==r&&f("Unclosed paren"),a},v=(s.space=e=>{for(;(e=u())<=32;)n++;return e},s.token=[e=>(e=p((e=>e>47&&e<58||46==e)))&&((69==u()||101==u())&&(e+=p(2)+p((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?f("Bad number"):e),(e,r)=>34==e&&p()+p((r=>r-e))+p(),e=>p((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e))]),h=(e,r=0,t)=>{for(;r<v.length;)if(t=v[r++](e))return t},d=[],g=s.operator=(e,r=0,t=0,a,o=e.charCodeAt(0),l=e.length,v=d[o],h=e.toUpperCase()!==e,g)=>(g=l<2?h?e=>u(1)<=32:e=>1:h?r=>i(l)==e&&u(l)<=32:r=>i(l)==e,a=t?t>0?e=>e&&[p(l),e]:t<0?e=>!e&&[p(l),(c(r-1)||f()).valueOf()]:t:t=>{t=[e,t||f()];do{n+=l,t.push((c(r)||f()).valueOf())}while(s.space()==o&&g());return t},d[o]=(e,t)=>t<r&&g()&&a(e)||v&&v(e,t));for(let e=0,r=[",",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&&[p(),e,"string"==typeof(r=c(18))?'"'+r+'"':r.valueOf()],"[",18,e=>(n++,e=[".",e,c(0,93).valueOf()],n++,e),"]",,,"(",18,(e,r)=>(n++,r=c(0,41),n++,Array.isArray(r)&&","===r[0]?(r[0]=e,r):r?[e,r.valueOf()]:[e]),"(",19,(e,r)=>!e&&(++n,r=c(0,41)||f(),++n,r),")",,,];e<r.length;)g(r[e++],r[e++],r[e++]);var y=e=>({valueOf:()=>e});s.token.splice(2,0,(e=>116===e&&"true"===i(4)&&p(4)?y(!0):102===e&&"false"===i(5)&&p(5)?y(!1):110===e&&"null"===i(4)&&p(4)?y(null):117===e&&"undefined"===i(9)&&p(9)?y(void 0):null)),s.token[1]=(e,r,t,a)=>{if(34===e||39===e){for(r=i(),p(),a="";(t=u())-e;)92===t?(p(),a+=O[i()]||i()):a+=i(),p();return p(),r+a+r}};var O={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"};s.space=e=>{for(;(e=u())<=32;)p(),47===u()&&(42===u(1)?(p(2),p((e=>42!==e&&47!==u(1))),p(2)):47===u(1)&&(p(2),p((e=>e>=32))));return e},s.token.unshift(((e,r)=>123===e&&(p(),r=b(["{",c(0,125)]),p(),r)));var b=(e,r)=>(e[1]?":"==e[1][0]?r=[e[1]]:","==e[1][0]&&(r=e[1].slice(1)):r=[],["{",...r]);for(let e=0,r=[";",1,,"===",9,,"!==",9,,"**",14,,"~",13,-1,"?",3,e=>{let r,t;return e||f("Expected expression"),p(),s.space(),r=c(),58!==u()&&f("Expected :"),p(),s.space(),t=c(),["?:",e,r,t]},"}",,,":",0,,"in",10,e=>u(2)<=32&&[p(2),'"'+e+'"',c(10)],"[",20,(e,r)=>!e&&(p(),r=c(0,93),p(),r?","===r[0]?(r[0]="[",r):["[",r]:["["])];e<r.length;)s.operator(r[e++],r[e++],r[e++]);for(let e=0,t=(["**",(...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]]);e<t.length;)r.operator(t[e++],t[e++]);var A=s;export{A as default,r 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,s)=>t(e)?("string"==typeof(o=e[0])&&(s=n[o]),"function"!=typeof(o=s||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?s():d(a))),s=(t="Bad syntax")=>{throw Error(t+" `"+r[e]+"` at "+e)},f=(t=1,a=e)=>{if("number"==typeof t)e+=t;else for(;t(i());)e++;return r.slice(a,e)},i=(t=0)=>r.charCodeAt(e+t),l=(t=1)=>r.substr(e,t),p=(e=0,r,t,a,n=0,f,i)=>{for(;(t=o.space())&&(i=y[t]?.(a,e)||!a&&c(t));)a=i;return r&&t!==r&&s("Unclosed paren"),a},u=(o.space=r=>{for(;(r=i())<=32;)e++;return r},o.token=[]),c=(e,r=0,t)=>{for(;r<u.length;)if(t=u[r++](e))return t},y=[],d=(o.operator=(r,t=0,a=0,n,u=r.charCodeAt(0),c=r.length,h=y[u],v=a<=0&&r.toUpperCase()!==r)=>(n=a?a>0?e=>e&&[f(c),d(e)]:a<0?e=>!e&&[f(c),d(p(t-1))]:a:a=>{a=[r,a||s()];do{e+=c,a.push(d(p(t)))}while(o.space()==u&&(c<2||l(c)==r)&&(!v||i(c)<=32));return a},y[u]=(e,a)=>a<t&&(c<2||l(c)==r)&&(!v||i(c)<=32)&&n(e)||h&&h(e,a)),e=>Array.isArray(e)?e:(e||s()).valueOf()),h=10,v=15,g=20;o.token.push((e=>(e=f((e=>e>47&&e<58||46==e)))&&((69==i()||101==i())&&(e+=f(2)+f((e=>e>=48&&e<=57))),isNaN(e=new Number(e))?s("Bad number"):e)),((e,r,t,a)=>{if(34===e||39===e){for(r=l(),f(),a="";(t=i())-e;)92===t?(f(),a+=A[l()]||l()):a+=l(),f();return f(),r+a+r}}),(e=>f((e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e))));var A={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"};o.space=e=>{for(;(e=i())<=32||47===e;)if(e<=32)f();else if(47===e)if(42===i(1))f(2),f((e=>42!==e&&47!==i(1))),f(2);else{if(47!==i(1))break;f(2),f((e=>e>=32))}return e};var b=(e,r=2,t)=>{for(let a=0;a<t.length;a+=r)e(t[a],t[a+1],t[a+2])};b(o.operator,3,[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",h,,">=",h,,">>",11,,">>>",11,,"<",h,,"<=",h,,"<<",11,,"+",12,,"+",v,-1,"++",v,-1,"++",v,1,"-",12,,"-",v,-1,"--",v,-1,"--",v,1,"!",v,-1,"*",13,,"/",13,,"%",13,,".",18,(e,r)=>e&&[f(),e,"string"==typeof(r=p(18))?'"'+r+'"':r.valueOf()],"[",18,e=>(f(),e=[".",e,d(p(0,93))],f(),e),"]",,,"(",18,(e,r)=>(f(),r=p(0,41),f(),Array.isArray(r)&&","===r[0]?(r[0]=e,r):r?[e,d(r)]:[e]),"(",19,(e,r)=>!e&&(f(),r=p(0,41)||s(),f(),r),")",,,";",1,,"===",9,,"!==",9,,"**",14,,"~",v,-1,"?",3,e=>{let r,t;return e||s("Expected expression"),f(),o.space(),r=p(),58!==i()&&s("Expected :"),f(),o.space(),t=p(),["?:",e,r,t]},"}",,,":",,,"in",h,e=>i(2)<=32&&[f(2),'"'+e+'"',p(h)],"[",g,(e,r)=>!e&&(f(),r=p(0,93),f(),r?","==r[0]?(r[0]="[",r):["[",r]:["["]),"{",g,(e,r)=>!e&&(f(),r=p(0,125),f(),r?":"==r[0]?["{",r]:","==r[0]?(r[0]="{",r):["{",r]:["{"]),"null",g,e=>!e&&(f(4),m(null)),"false",g,e=>!e&&(f(5),m(!1)),"true",g,e=>!e&&(f(4),m(!0)),"undefined",g,e=>!e&&(f(9),m(void 0))]);var m=e=>({valueOf:()=>e});b(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 x=e=>(e="string"==typeof e?o(e):e,r=>a(e,r));export{x 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.1.0",
3
+ "version": "5.2.3",
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,27 @@ 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 = parse.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 = (
47
+ op, prec=0, type=0, map, c=op.charCodeAt(0), l=op.length,
48
+ prev=lookup[c],
49
+ spaced=type<=0&&op.toUpperCase()!==op // non-postfix word operator must have space after
50
+ ) => (
74
51
  map = !type ? node => { // binary, consume same-op group
75
52
  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())
53
+ do { idx+=l, node.push(val(expr(prec))) }
54
+ while (parse.space()==c && (l<2||char(l)==op) && (!spaced||code(l)<=SPACE))
78
55
  return node
79
56
  } :
80
- type > 0 ? node => node && [skip(l), node] : // postfix unary
81
- type < 0 ? node => !node && [skip(l), (expr(prec-1) || err()).valueOf()] : // prefix unary
57
+ type > 0 ? node => node && [skip(l), val(node)] : // postfix unary
58
+ type < 0 ? node => !node && [skip(l), val(expr(prec-1))] : // prefix unary
82
59
  type,
83
60
 
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++])
61
+ lookup[c] = (node, curPrec) =>
62
+ curPrec < prec && (l<2||char(l)==op) && (!spaced||code(l)<=SPACE) &&
63
+ map(node) || (prev && prev(node, curPrec))
64
+ ),
146
65
 
66
+ // in order to support literal tokens, we call valueOf any time we create or modify calltree node
67
+ val = node => Array.isArray(node) ? node : (node || err()).valueOf()
147
68
 
148
69
  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, val, 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_POSTFIX, +1,
62
+ '-', PREC_SUM,,
63
+ '-', PREC_UNARY, -1,
64
+ '--', PREC_UNARY, -1,
65
+ '--', PREC_POSTFIX, +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, val(expr(0,CBRACK))], 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, val(b)] : [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,t=15,a=(t,a)=>(r=t,e=0,a=f(),e<r.length?o():a.valueOf()),o=(t="Bad syntax")=>{throw Error(t+" `"+r[e]+"` at "+e)},n=(t=1,a=e)=>{if("number"==typeof t)e+=t;else for(;t(l());)e++;return r.slice(a,e)},l=(t=0)=>r.charCodeAt(e+t),s=(t=1)=>r.substr(e,t),f=(e=0,r,t,n,l=0,s,f)=>{for(;(t=a.space())&&(f=i[t]?.(n,e)||!n&&u(t));)n=f;return r&&t!==r&&o("Unclosed paren"),n},p=(a.space=r=>{for(;(r=l())<=32;)e++;return r},a.token=[e=>(e=n((e=>e>47&&e<58||46==e)))&&((69==l()||101==l())&&(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))]),u=(e,r=0,t)=>{for(;r<p.length;)if(t=p[r++](e))return t},i=[],c=a.operator=(r,t=0,p=0,u,c=r.charCodeAt(0),y=r.length,g=i[c],h=r.toUpperCase()!==r,v)=>(v=y<2?h?e=>l(1)<=32:e=>1:h?e=>s(y)==r&&l(y)<=32:e=>s(y)==r,u=p?p>0?e=>e&&[n(y),e]:p<0?e=>!e&&[n(y),(f(t-1)||o()).valueOf()]:p:n=>{n=[r,n||o()];do{e+=y,n.push((f(t)||o()).valueOf())}while(a.space()==c&&v());return n},i[c]=(e,r)=>r<t&&v()&&u(e)||g&&g(e,r));for(let r=0,a=[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",t,-1,"++",t,-1,"++",t,1,"-",12,,"-",t,-1,"--",t,-1,"--",t,1,"!",t,-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,t)=>(e++,t=f(0,41),e++,Array.isArray(t)&&","===t[0]?(t[0]=r,t):t?[r,t.valueOf()]:[r]),"(",19,(r,t)=>!r&&(++e,t=f(0,41)||o(),++e,t),")",,,];r<a.length;)c(a[r++],a[r++],a[r++]);var y=a,g=e=>Array.isArray(e)&&("string"==typeof e[0]||g(e[0])),h=(e,r={},t,a)=>g(e)?("string"==typeof(t=e[0])&&(a=v[t]),"function"!=typeof(t=a||h(t,r))?t:t.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={},d=h.operator=(e,r)=>v[e]=2==r.length?(...e)=>e.reduce(r):r;for(let e,r=["!",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=r.pop();)d(r.pop(),e);var 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 r,e,t=(t,o)=>(e=t,r=0,o=l(),r<e.length?a():y(o)),a=(t="Bad syntax")=>{throw Error(t+" `"+e[r]+"` at "+r)},o=(t=1,a=r)=>{if("number"==typeof t)r+=t;else for(;t(n());)r++;return e.slice(a,r)},n=(t=0)=>e.charCodeAt(r+t),s=(t=1)=>e.substr(r,t),l=(r=0,e,o,n,s=0,l,p)=>{for(;(o=t.space())&&(p=u[o]?.(n,r)||!n&&f(o));)n=p;return e&&o!==e&&a("Unclosed paren"),n},p=(t.space=e=>{for(;(e=n())<=32;)r++;return e},t.token=[]),f=(r,e=0,t)=>{for(;e<p.length;)if(t=p[e++](r))return t},u=[],i=t.operator=(e,p=0,f=0,i,c=e.charCodeAt(0),h=e.length,g=u[c],d=f<=0&&e.toUpperCase()!==e)=>(i=f?f>0?r=>r&&[o(h),y(r)]:f<0?r=>!r&&[o(h),y(l(p-1))]:f:o=>{o=[e,o||a()];do{r+=h,o.push(y(l(p)))}while(t.space()==c&&(h<2||s(h)==e)&&(!d||n(h)<=32));return o},u[c]=(r,t)=>t<p&&(h<2||s(h)==e)&&(!d||n(h)<=32)&&i(r)||g&&g(r,t)),y=r=>Array.isArray(r)?r:(r||a()).valueOf(),c=t,h=r=>Array.isArray(r)&&("string"==typeof r[0]||h(r[0])),g=(r,e={},t,a)=>h(r)?("string"==typeof(t=r[0])&&(a=d[t]),"function"!=typeof(t=a||g(t,e))?t:t.call(...r.map((r=>g(r,e))))):r&&"string"==typeof r?'"'===r[0]?r.slice(1,-1):"@"===r[0]?r.slice(1):r in e?e[r]:r:r,d={},A=g.operator=(r,e)=>d[r]=2==e.length?(...r)=>r.reduce(e):e,v=g;p.push((r=>(r=o((r=>r>47&&r<58||46==r)))&&((69==n()||101==n())&&(r+=o(2)+o((r=>r>=48&&r<=57))),isNaN(r=new Number(r))?err("Bad number"):r)),((r,e)=>34==r&&o()+o((e=>e-r))+o()),(r=>o((r=>r>=48&&r<=57||r>=65&&r<=90||r>=97&&r<=122||36==r||95==r||r>=192))));var m=(r,e=2,t)=>{for(let a=0;a<t.length;a+=e)r(t[a],t[a+1],t[a+2])};m(i,3,[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",15,-1,"++",15,-1,"++",16,1,"-",12,,"-",15,-1,"--",15,-1,"--",16,1,"!",15,-1,"*",13,,"/",13,,"%",13,,".",18,(r,e)=>r&&[o(),r,"string"==typeof(e=l(18))?'"'+e+'"':e.valueOf()],"[",18,r=>(o(),r=[".",r,y(l(0,93))],o(),r),"]",,,"(",18,(r,e)=>(o(),e=l(0,41),o(),Array.isArray(e)&&","===e[0]?(e[0]=r,e):e?[r,y(e)]:[r]),"(",19,(r,e)=>!r&&(o(),e=l(0,41)||err(),o(),e),")",,,]),m(A,2,["!",r=>!r,"++",r=>++r,"--",r=>--r,".",(r,e)=>r&&r[e],"%",(r,e)=>r%e,"/",(r,e)=>r/e,"*",(r,e)=>r*e,"+",(r,e)=>r+e,"-",(...r)=>r.length<2?-r:r.reduce(((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,"&&",(...r)=>r.every(Boolean),"||",(...r)=>r.some(Boolean),",",(r,e)=>e]);var b=r=>(r="string"==typeof r?c(r):r,e=>v(r,e));export{b as default,v as evaluate,c as parse};