subscript 5.2.1 → 5.3.1

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,6 +1,6 @@
1
1
  # <img alt="subscript" src="/subscript2.svg" height=42/> <!--sub͘<em>script</em>--> <!--<sub>SUB͘<em>SCRIPT</em></sub>-->
2
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>
3
+ <a href="http://npmjs.org/subscript"><img src="https://img.shields.io/npm/v/subscript?color=indianred"/></a>
4
4
  <a href="http://microjs.com/#subscript"><img src="https://img.shields.io/badge/microjs-subscript-blue?color=darkslateblue"/></a>
5
5
 
6
6
  _Subscript_ is micro-language with common syntax subset of C++, JS, Java, Python, Go, Rust, Swift, Objective C, Kotlin etc.<br/>
@@ -24,13 +24,13 @@ _Subscript_ is designed to be useful for:
24
24
 
25
25
  * templates (perfect match with [template parts](https://github.com/github/template-parts))
26
26
  * expressions evaluators, calculators
27
- * subsets of languages (eg. [justin](#justin)) <!-- see sonr, mineural -->
27
+ * configurable subsets of languages (eg. [justin](#justin)) <!-- see sonr, mineural -->
28
28
  * mocking language features (eg. pipe operator)
29
29
  * sandboxes, playgrounds, safe eval
30
30
  * custom DSL
31
31
 
32
32
  [_Jsep_](https://github.com/EricSmekens/jsep) is generally fine for the listed tasks, unless you need dependencies as small as possible.
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_ and more test coverage and 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.
34
34
 
35
35
 
36
36
  ## Evaluation
@@ -285,7 +285,7 @@ Subscript shows relatively good performance within other evaluators:
285
285
  // 1 + (a * b / c % d) - 2.0 + -3e-3 * +4.4e4 / f.g[0] - i.j(+k == 1)(0)
286
286
  // parse 30k times
287
287
 
288
- subscript: ~220 ms
288
+ subscript: ~230 ms
289
289
  jsep: ~280 ms
290
290
  expr-eval: ~480 ms
291
291
  jexl: ~1200 ms
package/justin.js CHANGED
@@ -1,6 +1,6 @@
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
5
  const PERIOD=46, OPAREN=40, CPAREN=41, CBRACK=93, SPACE=32,
6
6
 
@@ -10,7 +10,6 @@ PREC_EXP=14, PREC_TOKEN=20
10
10
 
11
11
 
12
12
  // tokens
13
- const v = v => ({valueOf:()=>v})
14
13
  parse.token.push(
15
14
  // 1.2e+3, .5 - fast & small version, but consumes corrupted nums as well
16
15
  (number) => (
@@ -31,14 +30,6 @@ parse.token.push(
31
30
  return skip(), qc + str + qc
32
31
  },
33
32
 
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
33
  // id
43
34
  c => skip(c =>
44
35
  (c >= 48 && c <= 57) || // 0..9
@@ -54,13 +45,14 @@ const escape = {n:'\n', r:'\r', t:'\t', b:'\b', f:'\f', v:'\v'}
54
45
 
55
46
  // /**/, //
56
47
  parse.space = cc => {
57
- while (cc = code(), cc <= 32) {
58
- skip()
59
- if (code() === 47)
48
+ while (cc = code(), cc <= 32 || cc === 47) {
49
+ if (cc <= 32) skip()
50
+ else if (cc === 47)
60
51
  // /**/
61
52
  if (code(1) === 42) skip(2), skip(c => c !== 42 && code(1) !== 47), skip(2)
62
53
  // //
63
54
  else if (code(1) === 47) skip(2), skip(c => c >= 32)
55
+ else break
64
56
  }
65
57
  return cc
66
58
  }
@@ -119,15 +111,15 @@ addOps(parse.operator, 3, [
119
111
  '.', PREC_CALL, (node,b) => node && [skip(),node, typeof (b = expr(PREC_CALL)) === 'string' ? '"' + b + '"' : b.valueOf()],
120
112
 
121
113
  // a[b]
122
- '[', PREC_CALL, (node) => (skip(), node = ['.', node, expr(0,CBRACK).valueOf()], skip(), node),
114
+ '[', PREC_CALL, (node) => (skip(), node = ['.', node, val(expr(0,CBRACK))], node),
123
115
  ']',,,
124
116
 
125
117
  // 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]
118
+ '(', PREC_CALL, (node,b) => ( skip(), b=expr(0,CPAREN),
119
+ Array.isArray(b) && b[0]===',' ? (b[0]=node, b) : b ? [node, val(b)] : [node]
128
120
  ),
129
121
  // (a+b)
130
- '(', PREC_GROUP, (node,b) => !node && (skip(), b=expr(0,CPAREN) || err(), skip(), b),
122
+ '(', PREC_GROUP, (node,b) => !node && (skip(), b=expr(0,CPAREN) || err(), b),
131
123
  ')',,,
132
124
 
133
125
  // justin extension
@@ -148,17 +140,25 @@ addOps(parse.operator, 3, [
148
140
  ':',,,
149
141
  'in', PREC_COMP, (node) => code(2) <= 32 && [skip(2), '"'+node+'"', expr(PREC_COMP)],
150
142
 
143
+ // as operator it's faster to lookup (no need to extra rule check), smaller and no conflict with word names
151
144
  // [a,b,c]
152
145
  '[', PREC_TOKEN, (node,arg) => !node && (
153
- skip(), arg=expr(0,93), skip(),
146
+ skip(), arg=expr(0,93),
154
147
  !arg ? ['['] : arg[0] == ',' ? (arg[0]='[',arg) : ['[',arg]
155
148
  ),
156
149
 
157
150
  // {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])
151
+ '{', PREC_TOKEN, (node,arg) => !node && (skip(), arg=expr(0,125),
152
+ !arg ? ['{'] : arg[0] == ':' ? ['{',arg] : arg[0] == ',' ? (arg[0]='{',arg) : ['{',arg])
160
153
  ,
154
+
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)),
161
160
  ])
161
+ const v = v => ({valueOf:()=>v})
162
162
 
163
163
  addOps(evaluate.operator, 2, [
164
164
  // subscript
@@ -200,9 +200,7 @@ addOps(evaluate.operator, 2, [
200
200
  '?:', (a,b,c)=>a?b:c,
201
201
  'in', (a,b)=>a in b,
202
202
 
203
- // []
204
203
  '[', (...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
204
  '{', (...args)=>Object.fromEntries(args),
207
205
  ':', (a,b)=>[a,b]
208
206
  ])
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,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};
1
+ const e=r=>Array.isArray(r)&&("string"==typeof r[0]||e(r[0])),r=(n,o={},s,a)=>e(n)?("string"==typeof(s=n[0])&&(a=t[s]),"function"!=typeof(s=a||r(s,o))?s:s.call(...n.map((e=>r(e,o))))):n&&"string"==typeof n?'"'===n[0]?n.slice(1,-1):"@"===n[0]?n.slice(1):n in o?o[n]:n:n,t={};let n,o;r.operator=(e,r)=>t[e]=2==r.length?(...e)=>e.reduce(r):r;const s=(e,r)=>(o=e,n=0,r=p(),n<o.length?a():d(r)),a=(e="Bad syntax")=>{throw Error(e+" `"+o[n]+"` at "+n)},f=(e=1,r=n)=>{if("number"==typeof e)n+=e;else for(;e(i());)n++;return o.slice(r,n)},i=(e=0)=>o.charCodeAt(n+e),l=(e=1)=>o.substr(n,e),p=(e=0,r,t,o,f=0,i,l)=>{for(;(t=s.space())&&(l=y[t]?.(o,e)||!o&&u(t));)o=l;return r&&(t!=r?a("Unclosed paren"):n++),o};s.space=e=>{for(;(e=i())<=32;)n++;return e};const c=s.token=[],u=(e,r=0,t)=>{for(;r<c.length;)if(t=c[r++](e))return t},y=[];s.operator=(e,r=0,t=0,o,a=e.charCodeAt(0),c=e.length,u=y[a],h=t<=0&&e.toUpperCase()!==e)=>(o=t?t>0?e=>e&&[f(c),d(e)]:t<0?e=>!e&&[f(c),d(p(r-1))]:t:t=>{t=[e,d(t)];do{n+=c,t.push(d(p(r)))}while(s.space()==a&&(c<2||l(c)==e)&&(!h||i(c)<=32));return t},y[a]=(t,n)=>n<r&&(c<2||l(c)==e)&&(!h||i(c)<=32)&&o(t)||u&&u(t,n));const d=e=>Array.isArray(e)?e:(e||a()).valueOf();s.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))?a("Bad number"):e)),((e,r,t,n)=>{if(34===e||39===e){for(r=l(),f(),n="";(t=i())-e;)92===t?(f(),n+=h[l()]||l()):n+=l(),f();return f(),r+n+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))));const h={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"};s.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};const g=(e,r=2,t)=>{for(let n=0;n<t.length;n+=r)e(t[n],t[n+1],t[n+2])};g(s.operator,3,[",",1,,"|",6,,"||",4,,"&",8,,"&&",5,,"^",7,,"==",9,,"!=",9,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",15,-1,"++",15,-1,"++",15,1,"-",12,,"-",15,-1,"--",15,-1,"--",15,1,"!",15,-1,"*",13,,"/",13,,"%",13,,".",18,(e,r)=>e&&[f(),e,"string"==typeof(r=p(18))?'"'+r+'"':r.valueOf()],"[",18,e=>(f(),[".",e,d(p(0,93))]),"]",,,"(",18,(e,r)=>(f(),r=p(0,41),Array.isArray(r)&&","===r[0]?(r[0]=e,r):r?[e,d(r)]:[e]),"(",19,(e,r)=>!e&&(f(),p(0,41)||a()),")",,,";",1,,"===",9,,"!==",9,,"**",14,,"~",15,-1,"?",3,e=>{let r,t;return e||a("Expected expression"),f(),s.space(),r=p(),58!==i()&&a("Expected :"),f(),s.space(),t=p(),["?:",e,r,t]},"}",,,":",,,"in",10,e=>i(2)<=32&&[f(2),'"'+e+'"',p(10)],"[",20,(e,r)=>!e&&(f(),(r=p(0,93))?","==r[0]?(r[0]="[",r):["[",r]:["["]),"{",20,(e,r)=>!e&&(f(),(r=p(0,125))?":"==r[0]?["{",r]:","==r[0]?(r[0]="{",r):["{",r]:["{"]),"null",20,e=>!e&&(f(4),A(null)),"false",20,e=>!e&&(f(5),A(!1)),"true",20,e=>!e&&(f(4),A(!0)),"undefined",20,e=>!e&&(f(9),A(void 0))]);const A=e=>({valueOf:()=>e});g(r.operator,2,["!",e=>!e,"++",e=>++e,"--",e=>--e,".",(e,r)=>e?e[r]:e,"%",(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?s(e):e,t=>r(e,t));export{b 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.2.1",
3
+ "version": "5.3.1",
4
4
  "description": "Microlanguage with common syntax for JS/C++/Python/Rust",
5
5
  "main": "subscript.js",
6
6
  "type": "module",
@@ -18,9 +18,9 @@
18
18
  "test": "test"
19
19
  },
20
20
  "scripts": {
21
- "build": "esbuild subscript.js --bundle --format=esm --minify --outfile=subscript.min.js",
21
+ "build": "rollup subscript.js --file subscript.min.js --format esm --name \"Subscript\"",
22
22
  "minify": "terser subscript.min.js -o subscript.min.js --module -c passes=3 -m",
23
- "build-justin": "esbuild justin.js --bundle --format=esm --minify --outfile=justin.min.js",
23
+ "build-justin": "rollup justin.js --file justin.min.js --format esm --name \"Justin\"",
24
24
  "minify-justin": "terser justin.min.js -o justin.min.js --module -c passes=3 -m",
25
25
  "test": "node test"
26
26
  },
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "homepage": "https://github.com/spectjs/subscript#readme",
56
56
  "devDependencies": {
57
- "esbuild": "^0.13.14",
57
+ "rollup": "^2.60.2",
58
58
  "terser": "^5.10.0"
59
59
  }
60
60
  }
package/parse.js CHANGED
@@ -3,7 +3,7 @@ const SPACE=32
3
3
  // current string & index
4
4
  let idx, cur
5
5
 
6
- 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)),
7
7
 
8
8
  err = (msg='Bad syntax') => { throw Error(msg + ' `' + cur[idx] + '` at ' + idx) },
9
9
 
@@ -24,7 +24,8 @@ expr = (prec=0, end, cc, node, i=0, map, newNode) => {
24
24
  (cc=parse.space()) && (newNode = lookup[cc]?.(node, prec) || (!node && token(cc)) )
25
25
  ) node = newNode;
26
26
 
27
- if (end && cc !== end) err('Unclosed paren')
27
+ // skip end character, if expected
28
+ if (end) cc != end ? err('Unclosed paren') : idx++
28
29
 
29
30
  return node
30
31
  },
@@ -43,22 +44,27 @@ lookup = [],
43
44
  // @param op is operator string
44
45
  // @param prec is operator precedenc to check
45
46
  // @param map is either number +1 - postfix unary, -1 prefix unary, 0 binary, else - custom mapper function
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) => (
47
- isop = l<2 ? // word operator must have space after
48
- !word ? c=>1 : c=>code(1)<=SPACE :
49
- !word ? c=>char(l)==op : c=>char(l)==op&&code(l)<=SPACE,
50
-
47
+ operator = parse.operator = (
48
+ op, prec=0, type=0, map, c=op.charCodeAt(0), l=op.length,
49
+ prev=lookup[c],
50
+ spaced=type<=0&&op.toUpperCase()!==op // non-postfix word operator must have space after
51
+ ) => (
51
52
  map = !type ? node => { // binary, consume same-op group
52
- node = [op, node || err()]
53
- // in order to support literal tokens, we call valueOf any time we create or modify calltree node
54
- do { idx+=l, node.push((expr(prec) || err()).valueOf()) } while (parse.space()==c && isop())
53
+ node = [op, val(node)]
54
+ do { idx+=l, node.push(val(expr(prec))) }
55
+ while (parse.space()==c && (l<2||char(l)==op) && (!spaced||code(l)<=SPACE))
55
56
  return node
56
57
  } :
57
- type > 0 ? node => node && [skip(l), node] : // postfix unary
58
- type < 0 ? node => !node && [skip(l), (expr(prec-1) || err()).valueOf()] : // prefix unary
58
+ type > 0 ? node => node && [skip(l), val(node)] : // postfix unary
59
+ type < 0 ? node => !node && [skip(l), val(expr(prec-1))] : // prefix unary
59
60
  type,
60
61
 
61
- lookup[c] = (node, curPrec) => curPrec < prec && isop() && map(node) || (prev && prev(node, curPrec))
62
- )
62
+ lookup[c] = (node, curPrec) =>
63
+ curPrec < prec && (l<2||char(l)==op) && (!spaced||code(l)<=SPACE) &&
64
+ map(node) || (prev && prev(node, curPrec))
65
+ ),
66
+
67
+ // in order to support literal tokens, we call valueOf any time we create or modify calltree node
68
+ val = node => Array.isArray(node) ? node : (node || err()).valueOf()
63
69
 
64
70
  export default parse
package/subscript.js CHANGED
@@ -1,4 +1,4 @@
1
- import parse, {skip, expr, code, tokens, operator as parseOp} from './parse.js'
1
+ import parse, {skip, expr, code, tokens, val, operator as parseOp, err} from './parse.js'
2
2
  import evaluate, {operator as evalOp} from './evaluate.js'
3
3
 
4
4
  const PERIOD=46, OPAREN=40, CPAREN=41, CBRACK=93, SPACE=32,
@@ -58,11 +58,11 @@ addOps(parseOp, 3, [
58
58
  '+', PREC_SUM,,
59
59
  '+', PREC_UNARY, -1,
60
60
  '++', PREC_UNARY, -1,
61
- '++', PREC_UNARY, +1,
61
+ '++', PREC_POSTFIX, +1,
62
62
  '-', PREC_SUM,,
63
63
  '-', PREC_UNARY, -1,
64
64
  '--', PREC_UNARY, -1,
65
- '--', PREC_UNARY, +1,
65
+ '--', PREC_POSTFIX, +1,
66
66
 
67
67
  // ! ~
68
68
  '!', PREC_UNARY, -1,
@@ -76,15 +76,15 @@ addOps(parseOp, 3, [
76
76
  '.', PREC_CALL, (node,b) => node && [skip(),node, typeof (b = expr(PREC_CALL)) === 'string' ? '"' + b + '"' : b.valueOf()],
77
77
 
78
78
  // a[b]
79
- '[', PREC_CALL, (node) => (skip(), node = ['.', node, expr(0,CBRACK).valueOf()], skip(), node),
79
+ '[', PREC_CALL, (node) => (skip(), node = ['.', node, val(expr(0,CBRACK))], node),
80
80
  ']',,,
81
81
 
82
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]
83
+ '(', PREC_CALL, (node,b) => ( skip(), b=expr(0,CPAREN),
84
+ Array.isArray(b) && b[0]===',' ? (b[0]=node, b) : b ? [node, val(b)] : [node]
85
85
  ),
86
86
  // (a+b)
87
- '(', PREC_GROUP, (node,b) => !node && (skip(), b=expr(0,CPAREN) || err(), skip(), b),
87
+ '(', PREC_GROUP, (node,b) => !node && (skip(), b=expr(0,CPAREN) || err(), b),
88
88
  ')',,,
89
89
  ])
90
90
 
package/subscript.min.js CHANGED
@@ -1 +1 @@
1
- var e,r,a=(a,o)=>(r=a,e=0,o=l(),e<r.length?t():o.valueOf()),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=p[o]?.(n,e)||!n&&u(o));)n=f;return r&&o!==r&&t("Unclosed paren"),n},f=(a.space=r=>{for(;(r=n())<=32;)e++;return r},a.token=[]),u=(e,r=0,a)=>{for(;r<f.length;)if(a=f[r++](e))return a},p=[],i=a.operator=(r,f=0,u=0,i,c=r.charCodeAt(0),y=r.length,h=p[c],g=r.toUpperCase()!==r,v)=>(v=y<2?g?e=>n(1)<=32:e=>1:g?e=>s(y)==r&&n(y)<=32:e=>s(y)==r,i=u?u>0?e=>e&&[o(y),e]:u<0?e=>!e&&[o(y),(l(f-1)||t()).valueOf()]:u:o=>{o=[r,o||t()];do{e+=y,o.push((l(f)||t()).valueOf())}while(a.space()==c&&v());return o},p[c]=(e,r)=>r<f&&v()&&i(e)||h&&h(e,r)),c=a,y=e=>Array.isArray(e)&&("string"==typeof e[0]||y(e[0])),h=(e,r={},a,t)=>y(e)?("string"==typeof(a=e[0])&&(t=g[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,g={},v=h.operator=(e,r)=>g[e]=2==r.length?(...e)=>e.reduce(r):r,d=h,A=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 O=(e,r=2,a)=>{for(let t=0;t<a.length;t+=r)e(a[t],a[t+1],a[t+2])};O(i,3,[",",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&&[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),")",,,]),O(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 m=e=>(e="string"==typeof e?c(e):e,r=>d(e,r));export{m as default,d as evaluate,c as parse};
1
+ let e,r;const t=(t,n)=>(r=t,e=0,n=l(),e<r.length?o():c(n)),o=(t="Bad syntax")=>{throw Error(t+" `"+r[e]+"` at "+e)},n=(t=1,o=e)=>{if("number"==typeof t)e+=t;else for(;t(a());)e++;return r.slice(o,e)},a=(t=0)=>r.charCodeAt(e+t),s=(t=1)=>r.substr(e,t),l=(r=0,n,a,s,l=0,p,u)=>{for(;(a=t.space())&&(u=i[a]?.(s,r)||!s&&f(a));)s=u;return n&&(a!=n?o("Unclosed paren"):e++),s};t.space=r=>{for(;(r=a())<=32;)e++;return r};const p=t.token=[],f=(e,r=0,t)=>{for(;r<p.length;)if(t=p[r++](e))return t},i=[],u=t.operator=(r,o=0,p=0,f,u=r.charCodeAt(0),y=r.length,h=i[u],g=p<=0&&r.toUpperCase()!==r)=>(f=p?p>0?e=>e&&[n(y),c(e)]:p<0?e=>!e&&[n(y),c(l(o-1))]:p:n=>{n=[r,c(n)];do{e+=y,n.push(c(l(o)))}while(t.space()==u&&(y<2||s(y)==r)&&(!g||a(y)<=32));return n},i[u]=(e,t)=>t<o&&(y<2||s(y)==r)&&(!g||a(y)<=32)&&f(e)||h&&h(e,t)),c=e=>Array.isArray(e)?e:(e||o()).valueOf(),y=e=>Array.isArray(e)&&("string"==typeof e[0]||y(e[0])),h=(e,r={},t,o)=>y(e)?("string"==typeof(t=e[0])&&(o=g[t]),"function"!=typeof(t=o||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,g={},d=h.operator=(e,r)=>g[e]=2==r.length?(...e)=>e.reduce(r):r;p.push((e=>(e=n((e=>e>47&&e<58||46==e)))&&((69==a()||101==a())&&(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))));const A=(e,r=2,t)=>{for(let o=0;o<t.length;o+=r)e(t[o],t[o+1],t[o+2])};A(u,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,(e,r)=>e&&[n(),e,"string"==typeof(r=l(18))?'"'+r+'"':r.valueOf()],"[",18,e=>(n(),[".",e,c(l(0,93))]),"]",,,"(",18,(e,r)=>(n(),r=l(0,41),Array.isArray(r)&&","===r[0]?(r[0]=e,r):r?[e,c(r)]:[e]),"(",19,(e,r)=>!e&&(n(),l(0,41)||o()),")",,,]),A(d,2,["!",e=>!e,"++",e=>++e,"--",e=>--e,".",(e,r)=>e?e[r]:e,"%",(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 m=e=>(e="string"==typeof e?t(e):e,r=>h(e,r));export{m as default,h as evaluate,t as parse};