subscript 5.1.0 → 5.2.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
@@ -85,13 +85,14 @@ evaluate(tree, { Math, map, take, interval, gaussian })
85
85
 
86
86
  ---
87
87
 
88
- Tokens are extensible via `parse.token` list, can be added support of _literals_, _regexes_, _strings_, _numbers_ and others.
89
88
  Default tokens include:
90
89
 
91
90
  * `"abc"` strings
92
91
  * `1.2e+3` floats
93
92
  * identifiers
94
93
 
94
+ Tokens are extensible via `parse.token` list, can be added support of _literals_, _regexes_, _strings_, _numbers_ and others.
95
+
95
96
  ```js
96
97
  import parse, {char} from 'subscript/parse.js'
97
98
  import evaluate from 'subscript/evaluate.js'
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
@@ -2,28 +2,69 @@
2
2
  import {evaluate} from './evaluate.js'
3
3
  import {parse, code, char, skip, expr, err} from './parse.js'
4
4
 
5
- // literals
5
+ const PERIOD=46, OPAREN=40, CPAREN=41, CBRACK=93, SPACE=32,
6
+
7
+ PREC_SEQ=1, 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
+
10
+
11
+ // tokens
6
12
  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
13
+ parse.token.push(
14
+ // TODO: better parser
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
+ // {}
35
+ (cc, node) => (
36
+ cc === 123 && (skip(), node = mapObj(['{', expr(0,125)]), skip(), node)
37
+ ),
38
+
39
+ // literal
40
+ c =>
41
+ c === 116 && char(4) === 'true' && skip(4) ? v(true) :
42
+ c === 102 && char(5) === 'false' && skip(5) ? v(false) :
43
+ c === 110 && char(4) === 'null' && skip(4) ? v(null) :
44
+ c === 117 && char(9) === 'undefined' && skip(9) ? v(undefined) :
45
+ null,
46
+
47
+ // id
48
+ c => skip(c =>
49
+ (c >= 48 && c <= 57) || // 0..9
50
+ (c >= 65 && c <= 90) || // A...Z
51
+ (c >= 97 && c <= 122) || // a...z
52
+ c == 36 || c == 95 || // $, _,
53
+ (c >= 192 && c != 215 && c != 247) // any non-ASCII
54
+ )
13
55
  )
14
56
 
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
57
  const escape = {n:'\n', r:'\r', t:'\t', b:'\b', f:'\f', v:'\v'}
26
58
 
59
+ // {}
60
+ const mapObj = (n, args) => (
61
+ args = !n[1] ? [] :
62
+ (n[1][0]==':') ? [n[1]] :
63
+ (n[1][0]==',') ? n[1].slice(1) : args,
64
+ ['{', ...args]
65
+ )
66
+
67
+
27
68
  // /**/, //
28
69
  parse.space = cc => {
29
70
  while (cc = code(), cc <= 32) {
@@ -37,19 +78,72 @@ parse.space = cc => {
37
78
  return cc
38
79
  }
39
80
 
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]
81
+
82
+ // operators
83
+ const addOps = (add, stride=2, list) => {
84
+ for (let i = 0; i < list.length; i+=stride) add(list[i], list[i+1], list[i+2])
49
85
  }
50
86
 
51
- // parse operators
52
- for (let i = 0, ops = [
87
+ addOps(parse.operator, 3, [
88
+ // subscript ones
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) => (skip(), node = ['.', node, expr(0,CBRACK).valueOf()], skip(), node),
136
+ ']',,,
137
+
138
+ // a(b)
139
+ '(', PREC_CALL, (node,b) => ( skip(), b=expr(0,CPAREN), skip(),
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 && (skip(), b=expr(0,CPAREN) || err(), skip(), b),
144
+ ')',,,
145
+
146
+ // justin extension
53
147
  ';', 1,,
54
148
  '===', 9,,
55
149
  '!==', 9,,
@@ -70,20 +164,46 @@ for (let i = 0, ops = [
70
164
  skip(), arg=expr(0,93), skip(),
71
165
  !arg ? ['['] : arg[0] === ',' ? (arg[0]='[',arg) : ['[',arg]
72
166
  )
73
- ]; i < ops.length;) parse.operator(ops[i++],ops[i++],ops[i++])
167
+ ])
74
168
 
75
- // evaluate operators
76
- for (let i = 0, ops = [
77
- // **
78
- '**', (...args)=>args.reduceRight((a,b)=>Math.pow(b,a)),
169
+ addOps(evaluate.operator, 2, [
170
+ // subscript
171
+ '!', a=>!a,
172
+ '++', a=>++a,
173
+ '--', a=>--a,
79
174
 
80
- // ~
81
- '~', a=>~a,
175
+ '.', (a,b)=>a?a[b]:a,
176
+
177
+ '%', (a,b)=>a%b,
178
+ '/', (a,b)=>a/b,
179
+ '*', (a,b)=>a*b,
180
+
181
+ '+', (a,b)=>a+b,
182
+ '-', (...a)=>a.length < 2 ? -a : a.reduce((a,b)=>a-b),
183
+
184
+ '>>>', (a,b)=>a>>>b,
185
+ '>>', (a,b)=>a>>b,
186
+ '<<', (a,b)=>a<<b,
187
+
188
+ '>=', (a,b)=>a>=b,
189
+ '>', (a,b)=>a>b,
190
+ '<=', (a,b)=>a<=b,
191
+ '<', (a,b)=>a<b,
82
192
 
83
- // ?:
193
+ '!=', (a,b)=>a!=b,
194
+ '==', (a,b)=>a==b,
195
+
196
+ '&', (a,b)=>a&b,
197
+ '^', (a,b)=>a^b,
198
+ '|', (a,b)=>a|b,
199
+ '&&', (...a)=>a.every(Boolean),
200
+ '||', (...a)=>a.some(Boolean),
201
+ ',', (a,b)=>(a,b),
202
+
203
+ // justin extension
204
+ '**', (...args)=>args.reduceRight((a,b)=>Math.pow(b,a)),
205
+ '~', a=>~a,
84
206
  '?:', (a,b,c)=>a?b:c,
85
- // parse.operator(':')
86
- // in
87
207
  'in', (a,b)=>a in b,
88
208
 
89
209
  // []
@@ -91,10 +211,12 @@ for (let i = 0, ops = [
91
211
  // as operator it's faster to lookup (no need to call extra rule check), smaller and no conflict with word names
92
212
  '{', (...args)=>Object.fromEntries(args),
93
213
  ':', (a,b)=>[a,b]
94
- ]; i < ops.length;) evaluate.operator(ops[i++],ops[i++])
214
+ ])
95
215
 
96
216
  // TODO ...
97
217
  // TODO: strings interpolation
98
218
 
99
- export default parse
100
219
  export { parse, evaluate }
220
+
221
+ // code → evaluator
222
+ 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,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)),15),h=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+=y[f()]||f()):a+=f(),s();return s(),r+a+r}}),((e,r)=>123===e&&(s(),r=g(["{",p(0,125)]),s(),r)),(e=>116===e&&"true"===f(4)&&s(4)?h(!0):102===e&&"false"===f(5)&&s(5)?h(!1):110===e&&"null"===f(4)&&s(4)?h(null):117===e&&"undefined"===f(9)&&s(9)?h(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 y={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},g=(e,r)=>(r=e[1]?":"==e[1][0]?[e[1]]:","==e[1][0]?e[1].slice(1):r:[],["{",...r]);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,,">",10,,">=",10,,">>",11,,">>>",11,,"<",10,,"<=",10,,"<<",11,,"+",12,,"+",d,-1,"++",d,-1,"++",d,1,"-",12,,"-",d,-1,"--",d,-1,"--",d,1,"!",d,-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,,"~",13,-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]},"}",,,":",0,,"in",10,e=>u(2)<=32&&[s(2),'"'+e+'"',p(10)],"[",20,(e,r)=>!e&&(s(),r=p(0,93),s(),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.1.0",
3
+ "version": "5.2.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
@@ -1,8 +1,4 @@
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
@@ -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
@@ -84,65 +61,4 @@ operator = parse.operator = (op, prec=0, type=0, map, c=op.charCodeAt(0), l=op.
84
61
  lookup[c] = (node, curPrec) => curPrec < prec && isop() && map(node) || (prev && prev(node, curPrec))
85
62
  )
86
63
 
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++])
146
-
147
-
148
64
  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,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 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};