subscript 5.0.0 → 5.1.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 CHANGED
@@ -1,4 +1,4 @@
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
2
 
3
3
  _Subscript_ is micro-language with common syntax subset of C++, JS, Java, Python, Go, Rust, Swift, Objective C, Kotlin etc.<br/>
4
4
 
@@ -27,28 +27,9 @@ _Subscript_ is designed to be useful for:
27
27
  * custom DSL
28
28
 
29
29
  [_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.
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.
31
31
 
32
32
 
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
33
  ## Evaluation
53
34
 
54
35
  _Subscript_ parser generates lispy calltree (compatible with [frisk](https://npmjs.com/frisk)), which is compared to esprima AST has:
@@ -66,34 +47,32 @@ import {evaluate} from 'subscript.js'
66
47
  evaluate(['+', ['*', 'min', 60], '"sec"'], { min: 5 }) // min*60 + "sec" == "300sec"
67
48
  ```
68
49
 
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:
73
-
74
- * `"abc"` strings
75
- * `1.2e+3` floats
76
- * `()` expression groups or fn calls
77
- * `.`, `[]` property access
50
+ ## Extending
78
51
 
79
- Operators can be extended via `parse.operator` to add support for any unary/binary/postfix operators, calls, props or chains.
52
+ Default operators include common operators for the listed languages in the following precedence:
80
53
 
81
- Comments can be added via extending `parse.space`.
54
+ * `++ --` unary postfix
55
+ * `! + - ++ --` unary prefix
56
+ * `* / %`
57
+ * `+ -`
58
+ * `<< >> >>>`
59
+ * `< <= > >=`
60
+ * `== !=`
61
+ * `&`
62
+ * `^`
63
+ * `|`
64
+ * `&&`
65
+ * `||`
82
66
 
83
- For now see justin extension how things can be done.
67
+ 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
68
 
85
- <!--
86
69
  ```js
87
70
  import { parse, evaluate } from 'subscript.js'
88
71
 
89
- // add precedences
90
- // TODO
91
- // parse.operator['=>'] = 10
72
+ parse.operator('=>', 10) // precedence=10, type=default (0 - binary, 1 - postfix, -1 - prefix)
92
73
 
93
- // define evaluators
94
- // TODO
95
- // evaluate.operator['=>'] = ( args, body ) => evaluate(body, args)
96
- // evaluate.operator['|'] = ( a, ...b ) => a.pipe(...b)
74
+ evaluate.operator('=>', ( args, body ) => evaluate(body, args))
75
+ evaluate.operator('|', ( a, ...b ) => a.pipe(...b))
97
76
 
98
77
  let tree = parse(`
99
78
  interval(350)
@@ -103,7 +82,28 @@ let tree = parse(`
103
82
  `)
104
83
  evaluate(tree, { Math, map, take, interval, gaussian })
105
84
  ```
106
- -->
85
+
86
+ ---
87
+
88
+ Tokens are extensible via `parse.token` list, can be added support of _literals_, _regexes_, _strings_, _numbers_ and others.
89
+ Default tokens include:
90
+
91
+ * `"abc"` strings
92
+ * `1.2e+3` floats
93
+ * identifiers
94
+
95
+ ```js
96
+ import parse, {char} from 'subscript/parse.js'
97
+ import evaluate from 'subscript/evaluate.js'
98
+
99
+ conts ctx = {x:1}
100
+ parse.token.unshift(c => char(4) === 'this' ? ctx : null)
101
+ evaluate(parse(`this.x`)) // 1
102
+ ```
103
+
104
+ ---
105
+
106
+ Comments can be added via extending `parse.space`. See [justin.js](./justin.js) for more examples.
107
107
 
108
108
 
109
109
  ## Justin
@@ -111,6 +111,7 @@ evaluate(tree, { Math, map, take, interval, gaussian })
111
111
  _Justin_ extension (original [thread](https://github.com/endojs/Jessie/issues/66)) is minimal JS subset − JSON with JS expressions.<br/>
112
112
  It adds support of:
113
113
 
114
+ + `===`, `!==` operators
114
115
  + `**` binary operator
115
116
  + `~` unary operator
116
117
  + `'` strings
@@ -122,7 +123,6 @@ It adds support of:
122
123
  + unary word operators
123
124
  + `//`, `/* */` comments
124
125
  + `true`, `false`, `null`, `undefined` literals
125
- <!-- + `===`, `!==` operators -->
126
126
  <!-- + `?` chaining operator -->
127
127
  <!-- + `...x` unary operator -->
128
128
  <!-- + strings interpolation -->
@@ -279,7 +279,7 @@ Subscript shows relatively good performance within other evaluators:
279
279
  // 1 + (a * b / c % d) - 2.0 + -3e-3 * +4.4e4 / f.g[0] - i.j(+k == 1)(0)
280
280
  // parse 30k times
281
281
 
282
- subscript: ~200 ms
282
+ subscript: ~220 ms
283
283
  jsep: ~280 ms
284
284
  expr-eval: ~480 ms
285
285
  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,44 @@ 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
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
58
 
59
59
  export default evaluate
package/justin.js CHANGED
@@ -1,15 +1,8 @@
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)
7
-
8
- // ===, !==
9
- operator('===', 9)
10
- operator('!==', 9)
11
-
12
- // undefined
5
+ // literals
13
6
  const v = v => ({valueOf:()=>v})
14
7
  parse.token.splice(2,0, c =>
15
8
  c === 116 && char(4) === 'true' && skip(4) ? v(true) :
@@ -31,28 +24,6 @@ parse.token[1] = (q, qc, c, str) => {
31
24
  }
32
25
  const escape = {n:'\n', r:'\r', t:'\t', b:'\b', f:'\f', v:'\v'}
33
26
 
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
-
56
27
  // /**/, //
57
28
  parse.space = cc => {
58
29
  while (cc = code(), cc <= 32) {
@@ -66,28 +37,10 @@ parse.space = cc => {
66
37
  return cc
67
38
  }
68
39
 
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
40
  // {}
82
41
  parse.token.unshift((cc, node) => (
83
42
  cc === 123 && (skip(), node = map(['{', expr(0,125)]), skip(), node)
84
43
  ))
85
-
86
- operator('}')
87
- operator(':', 0)
88
- evaluate.operator['{'] = (...args)=>Object.fromEntries(args)
89
- evaluate.operator[':'] = (a,b)=>[a,b]
90
-
91
44
  const map = (n, args) => {
92
45
  if (!n[1]) args = []
93
46
  else if (n[1][0]==':') args = [n[1]]
@@ -95,6 +48,52 @@ const map = (n, args) => {
95
48
  return ['{', ...args]
96
49
  }
97
50
 
51
+ // parse operators
52
+ for (let i = 0, ops = [
53
+ ';', 1,,
54
+ '===', 9,,
55
+ '!==', 9,,
56
+ '**', 14,,
57
+ '~', 13, -1,
58
+ '?', 3, (node) => {
59
+ if (!node) err('Expected expression')
60
+ let a, b
61
+ skip(), parse.space(), a = expr()
62
+ if (code() !== 58) err('Expected :')
63
+ skip(), parse.space(), b = expr()
64
+ return ['?:', node, a, b]
65
+ },
66
+ '}',,,
67
+ ':', 0,,
68
+ 'in', 10, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(10)],
69
+ '[', 20, (node,arg) => !node && (
70
+ 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++])
74
+
75
+ // evaluate operators
76
+ for (let i = 0, ops = [
77
+ // **
78
+ '**', (...args)=>args.reduceRight((a,b)=>Math.pow(b,a)),
79
+
80
+ // ~
81
+ '~', a=>~a,
82
+
83
+ // ?:
84
+ '?:', (a,b,c)=>a?b:c,
85
+ // parse.operator(':')
86
+ // in
87
+ 'in', (a,b)=>a in b,
88
+
89
+ // []
90
+ '[', (...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
+ '{', (...args)=>Object.fromEntries(args),
93
+ ':', (a,b)=>[a,b]
94
+ ]; i < ops.length;) evaluate.operator(ops[i++],ops[i++])
95
+
96
+ // TODO ...
98
97
  // TODO: strings interpolation
99
98
 
100
99
  export default parse
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=>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};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "subscript",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
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
@@ -66,7 +66,7 @@ lookup = [],
66
66
  // @param op is operator string
67
67
  // @param prec is operator precedenc to check
68
68
  // @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) => (
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
70
  isop = l<2 ? // word operator must have space after
71
71
  !word ? c=>1 : c=>code(1)<=SPACE :
72
72
  !word ? c=>char(l)==op : c=>char(l)==op&&code(l)<=SPACE,
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,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};