subscript 7.4.6 → 7.5.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 +11 -10
- package/justin.js +82 -82
- package/justin.min.js +1 -1
- package/package.json +1 -1
- package/parse.js +88 -88
- package/subscript.js +108 -120
- package/subscript.min.js +1 -1
package/README.md
CHANGED
|
@@ -11,10 +11,10 @@ _Subscript_ is expression evaluator / microlanguage with [common syntax](https:/
|
|
|
11
11
|
import subscript, { parse, compile } from './subscript.js'
|
|
12
12
|
|
|
13
13
|
// create expression evaluator
|
|
14
|
-
let fn = subscript('a.b + c
|
|
15
|
-
fn({ a: { b:1 }, c:
|
|
14
|
+
let fn = subscript('a.b + Math.sqrt(c - 1)')
|
|
15
|
+
fn({ a: { b:1 }, c: 5, Math }) // 3
|
|
16
16
|
|
|
17
|
-
// or
|
|
17
|
+
// --- or ---
|
|
18
18
|
// parse expression
|
|
19
19
|
let tree = parse('a.b + c')
|
|
20
20
|
tree // ['+', ['.', 'a', 'b'], 'c']
|
|
@@ -28,12 +28,12 @@ fn({a:{b:1}, c:2}) // 3
|
|
|
28
28
|
|
|
29
29
|
_Subscript_ is designed to be useful for:
|
|
30
30
|
|
|
31
|
-
* templates (
|
|
31
|
+
* templates (eg. [sprae](https://github.com/dy/sprae), [templize](https://github.com/dy/templize))
|
|
32
32
|
* expressions evaluators, calculators
|
|
33
|
-
*
|
|
34
|
-
* pluggable/mock language features (eg. pipe operator)
|
|
33
|
+
* subsets of languages (eg. [justin](#justin))
|
|
34
|
+
* pluggable/configurable/mock language features (eg. pipe operator)
|
|
35
35
|
* sandboxes, playgrounds, safe eval
|
|
36
|
-
* custom DSL (see [
|
|
36
|
+
* custom DSL (see [mell](https://github.com/dy/lino)) <!-- uneural -->
|
|
37
37
|
* preprocessors (see [prepr](https://github.com/dy/prepr))
|
|
38
38
|
|
|
39
39
|
_Subscript_ has [3.5kb](https://npmfs.com/package/subscript/7.4.3/subscript.min.js) footprint, compared to [11.4kb](https://npmfs.com/package/jsep/1.2.0/dist/jsep.min.js) _jsep_ + [4.5kb](https://npmfs.com/package/expression-eval/5.0.0/dist/expression-eval.module.js) _expression-eval_, with better test coverage and better performance.
|
|
@@ -105,16 +105,16 @@ import script, { operator, unary, binary, token } from './subscript.js'
|
|
|
105
105
|
|
|
106
106
|
// add ~ unary operator with precedence 15
|
|
107
107
|
unary('~', 15)
|
|
108
|
-
operator('~', a => ~a)
|
|
108
|
+
operator('~', a => ctx => ~a)
|
|
109
109
|
|
|
110
110
|
// add === binary operator with precedence 9
|
|
111
111
|
binary('===', 9)
|
|
112
|
-
operator('===', (a, b) => a===b)
|
|
112
|
+
operator('===', (a, b) => ctx => ctx[a]===ctx[b])
|
|
113
113
|
|
|
114
114
|
// add boolean literals
|
|
115
115
|
token('true', 20, prev => ['',true])
|
|
116
116
|
token('false', 20, prev => ['',false])
|
|
117
|
-
operator('', boolNode => ctx => boolNode[1]
|
|
117
|
+
operator('', boolNode => ctx => boolNode[1])
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
See [subscript.js](subscript.js) or [justin.js](./justin.js) for examples.
|
|
@@ -331,5 +331,6 @@ math-parser: -
|
|
|
331
331
|
* [math-parser](https://www.npmjs.com/package/math-parser)
|
|
332
332
|
* [math.js](https://mathjs.org/docs/expressions/parsing.html)
|
|
333
333
|
* [nx-compile](https://github.com/nx-js/compiler-util)
|
|
334
|
+
* [built-in-math-eval](https://github.com/mauriciopoppe/built-in-math-eval)
|
|
334
335
|
|
|
335
336
|
<p align=center><a href="https://github.com/krsnzd/license/">🕉</a></p>
|
package/justin.js
CHANGED
|
@@ -1,94 +1,94 @@
|
|
|
1
1
|
// justin lang https://github.com/endojs/Jessie/issues/66
|
|
2
|
-
import { skip, cur, idx, err, expr } from './parse.js'
|
|
3
|
-
import compile from './compile.js'
|
|
2
|
+
import { skip, cur, idx, err, expr, lookup, token } from './parse.js'
|
|
3
|
+
import compile, { operator } from './compile.js'
|
|
4
4
|
import subscript, { set } from './subscript.js'
|
|
5
5
|
|
|
6
|
-
const PERIOD=46, OPAREN=40, CPAREN=41, OBRACK=91, CBRACK=93, SPACE=32, DQUOTE=34, QUOTE=39, _0=48, _9=57, BSLASH=92,
|
|
7
|
-
PREC_SEQ=1, PREC_COND=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_EXP=14, PREC_UNARY=15, PREC_POSTFIX=16, PREC_CALL=18, PREC_GROUP=19
|
|
6
|
+
const PERIOD = 46, OPAREN = 40, CPAREN = 41, OBRACK = 91, CBRACK = 93, SPACE = 32, DQUOTE = 34, QUOTE = 39, _0 = 48, _9 = 57, BSLASH = 92,
|
|
7
|
+
PREC_SEQ = 1, PREC_COND = 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_EXP = 14, PREC_UNARY = 15, PREC_POSTFIX = 16, PREC_CALL = 18, PREC_GROUP = 19
|
|
9
9
|
|
|
10
|
-
let escape = {n:'\n', r:'\r', t:'\t', b:'\b', f:'\f', v:'\v'},
|
|
11
|
-
string = q => (qc, c, str='') => {
|
|
12
|
-
qc&&err('Unexpected string') // must not follow another token
|
|
10
|
+
let escape = { n: '\n', r: '\r', t: '\t', b: '\b', f: '\f', v: '\v' },
|
|
11
|
+
string = q => (qc, c, str = '') => {
|
|
12
|
+
qc && err('Unexpected string') // must not follow another token
|
|
13
13
|
skip()
|
|
14
|
-
while (c=cur.charCodeAt(idx), c-q) {
|
|
15
|
-
if (c === BSLASH) skip(), c=skip(), str += escape[c] || c
|
|
14
|
+
while (c = cur.charCodeAt(idx), c - q) {
|
|
15
|
+
if (c === BSLASH) skip(), c = skip(), str += escape[c] || c
|
|
16
16
|
else str += skip()
|
|
17
17
|
}
|
|
18
18
|
skip()
|
|
19
19
|
return ['', str]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
]
|
|
91
|
-
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// operators
|
|
23
|
+
set('===', PREC_EQ, (a, b) => a === b)
|
|
24
|
+
set('!==', PREC_EQ, (a, b) => a !== b)
|
|
25
|
+
set('~', PREC_UNARY, (a) => ~a)
|
|
26
|
+
|
|
27
|
+
// ?:
|
|
28
|
+
token('?', PREC_COND, (a, b, c) => a && (b = expr(2, 58)) && (c = expr(3), ['?', a, b, c]))
|
|
29
|
+
operator('?', (a, b, c) => (a = compile(a), b = compile(b), c = compile(c), ctx => a(ctx) ? b(ctx) : c(ctx)))
|
|
30
|
+
|
|
31
|
+
set('??', PREC_OR, (a, b) => a ?? b)
|
|
32
|
+
|
|
33
|
+
// a?.[, a?.( - postfix operator
|
|
34
|
+
token('?.', PREC_CALL, a => a && ['?.', a])
|
|
35
|
+
operator('?.', a => (a = compile(a), ctx => a(ctx) || (() => { })))
|
|
36
|
+
|
|
37
|
+
// a?.b - optional chain operator
|
|
38
|
+
token('?.', PREC_CALL, (a, b) => a && (b = expr(PREC_CALL), !b?.map) && ['?.', a, b])
|
|
39
|
+
operator('?.', (a, b) => b && (a = compile(a), ctx => a(ctx)?.[b]))
|
|
40
|
+
|
|
41
|
+
// a?.x() - keep context
|
|
42
|
+
operator('(', (a, b, path, args) => b != null && a[0] === '?.' && (
|
|
43
|
+
args = b == '' ? () => [] : // a()
|
|
44
|
+
b[0] === ',' ? (b = b.slice(1).map(compile), ctx => b.map(a => a(ctx))) : // a(b,c)
|
|
45
|
+
(b = compile(b), ctx => [b(ctx)]), // a(b)
|
|
46
|
+
path = a[2], a = compile(a[1]), ctx => a(ctx)?.[path](...args(ctx))
|
|
47
|
+
))
|
|
48
|
+
|
|
49
|
+
// a in b
|
|
50
|
+
set('in', PREC_COMP, (a, b) => a in b)
|
|
51
|
+
|
|
52
|
+
// "' with /
|
|
53
|
+
lookup[DQUOTE] = string(DQUOTE)
|
|
54
|
+
lookup[QUOTE] = string(QUOTE)
|
|
55
|
+
|
|
56
|
+
// /**/, //
|
|
57
|
+
token('/*', 20, (a, prec) => (skip(c => c !== 42 && cur.charCodeAt(idx + 1) !== 47), skip(2), a || expr(prec) || ['']))
|
|
58
|
+
token('//', 20, (a, prec) => (skip(c => c >= 32), a || expr(prec) || ['']))
|
|
59
|
+
|
|
60
|
+
// literals
|
|
61
|
+
token('null', 20, a => a ? err() : ['', null])
|
|
62
|
+
token('true', 20, a => a ? err() : ['', true])
|
|
63
|
+
token('false', 20, a => a ? err() : ['', false])
|
|
64
|
+
token('undefined', 20, a => a ? err() : ['', undefined])
|
|
65
|
+
|
|
66
|
+
// FIXME: make sure that is right
|
|
67
|
+
set(';', -20, (...args) => { for (let i = args.length; i--;) if (args[i] != null) return args[i] })
|
|
68
|
+
|
|
69
|
+
// right order
|
|
70
|
+
// '**', (a,prec,b=expr(PREC_EXP-1)) => ctx=>a(ctx)**b(ctx), PREC_EXP,
|
|
71
|
+
set('**', -PREC_EXP, (a, b) => a ** b)
|
|
72
|
+
|
|
73
|
+
// [a,b,c]
|
|
74
|
+
token('[', 20, (a) => !a && ['[', expr(0, 93) || ''])
|
|
75
|
+
operator('[', (a, b) => !b && (
|
|
76
|
+
!a ? () => [] : // []
|
|
77
|
+
a[0] === ',' ? (a = a.slice(1).map(compile), ctx => a.map(a => a(ctx))) : // [a,b,c]
|
|
78
|
+
(a = compile(a), ctx => [a(ctx)]) // [a]
|
|
79
|
+
))
|
|
80
|
+
|
|
81
|
+
// {a:1, b:2, c:3}
|
|
82
|
+
token('{', 20, a => !a && (['{', expr(0, 125) || '']))
|
|
83
|
+
operator('{', (a, b) => (
|
|
84
|
+
!a ? ctx => ({}) : // {}
|
|
85
|
+
a[0] === ',' ? (a = a.slice(1).map(compile), ctx => Object.fromEntries(a.map(a => a(ctx)))) : // {a:1,b:2}
|
|
86
|
+
a[0] === ':' ? (a = compile(a), ctx => Object.fromEntries([a(ctx)])) : // {a:1}
|
|
87
|
+
(b = compile(a), ctx => ({ [a]: b(ctx) }))
|
|
88
|
+
))
|
|
89
|
+
|
|
90
|
+
token(':', 1.1, (a, b) => (b = expr(1.1) || err(), [':', a, b]))
|
|
91
|
+
operator(':', (a, b) => (b = compile(b), a = Array.isArray(a) ? compile(a) : (a => a).bind(0, a), ctx => [a(ctx), b(ctx)]))
|
|
92
92
|
|
|
93
93
|
export default subscript
|
|
94
94
|
export * from './subscript.js'
|
package/justin.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let e,t,r=r=>(e=0,t=r,r=s(),t[e]?l():r||""),l=(r="Bad syntax",l=t[e],n=t.slice(0,e).split("\n"),a=n.pop())=>{throw SyntaxError(`${r} ${l?`\`${l}\` `:""}at ${n.length}:${a.length}`,n.length)},n=(r="Bad syntax",l=t[e],n=t.slice(0,e).split("\n"),a=n.pop())=>{let s=t.slice(e-10,e).split("\n").pop(),i=t.slice(e+1,e+10).split("\n").shift(),h=n.length+":"+a.length;throw EvalError(`${r} at ${h} \`${s+l+i}\`\n${" ".repeat(18+r.length+h.length+s.length+1)}^`)},a=(r=1,l=e,n)=>{if("number"==typeof r)e+=r;else for(;n=r(t.charCodeAt(e));)e+=n;return t.slice(l,e)},s=(t=0,n,a,s,i,h)=>{for(;(a=r.space())&&(i=((h=o[a])&&h(s,t))??(!s&&r.id()));)s=i;return n&&(a==n?e++:l()),s},i=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e,h=r.space=r=>{for(;(r=t.charCodeAt(e))<=32;)e++;return r},p=r.id=e=>a(i),o=[],c=(r,l=32,n,a=r.charCodeAt(0),s=r.length,h=o[a],p=r.toUpperCase()!==r)=>o[a]=(a,o,c=e)=>o<l&&(s<2||t.substr(e,s)==r)&&(!p||!i(t.charCodeAt(e+s)))&&(e+=s,n(a,o))||(e=c,h?.(a,o)),
|
|
1
|
+
let e,t,r=r=>(e=0,t=r,r=s(),t[e]?l():r||""),l=(r="Bad syntax",l=t[e],n=t.slice(0,e).split("\n"),a=n.pop())=>{throw SyntaxError(`${r} ${l?`\`${l}\` `:""}at ${n.length}:${a.length}`,n.length)},n=(r="Bad syntax",l=t[e],n=t.slice(0,e).split("\n"),a=n.pop())=>{let s=t.slice(e-10,e).split("\n").pop(),i=t.slice(e+1,e+10).split("\n").shift(),h=n.length+":"+a.length;throw EvalError(`${r} at ${h} \`${s+l+i}\`\n${" ".repeat(18+r.length+h.length+s.length+1)}^`)},a=(r=1,l=e,n)=>{if("number"==typeof r)e+=r;else for(;n=r(t.charCodeAt(e));)e+=n;return t.slice(l,e)},s=(t=0,n,a,s,i,h)=>{for(;(a=r.space())&&(i=((h=o[a])&&h(s,t))??(!s&&r.id()));)s=i;return n&&(a==n?e++:l()),s},i=e=>e>=48&&e<=57||e>=65&&e<=90||e>=97&&e<=122||36==e||95==e||e>=192&&215!=e&&247!=e,h=r.space=r=>{for(;(r=t.charCodeAt(e))<=32;)e++;return r},p=r.id=e=>a(i),o=[],c=(r,l=32,n,a=r.charCodeAt(0),s=r.length,h=o[a],p=r.toUpperCase()!==r)=>o[a]=(a,o,c=e)=>o<l&&(s<2||t.substr(e,s)==r)&&(!p||!i(t.charCodeAt(e+s)))&&(e+=s,n(a,o))||(e=c,h?.(a,o)),g=(e,t,r=0)=>c(e,t,((l,n)=>l&&(n=s(t-r/2))&&[e,l,n])),f=(e,t,r)=>c(e,t,(l=>r?l&&[e,l]:!l&&(l=s(t-.5))&&[e,l])),u=(e,t,r)=>{c(e,t,((l,n)=>(l||r)&&((n=s(t))||r)&&((!l||l[0]!==e)&&(l=[e,l]),(n||r)&&l.push(n),l)))};const d=e=>Array.isArray(e)?m[e[0]](...e.slice(1)):t=>t?.[e],m={},A=(e,t,r=m[e])=>m[e]=(...e)=>t(...e)||r&&r(...e),b=e=>(e=r(e),t=>(e.call?e:e=d(e))(t)),$=(e,t,r)=>r.length?r.length>1?(g(e,Math.abs(t),t<0),A(e,((e,t)=>t&&(e=d(e),t=d(t),e.length||t.length?l=>r(e(l),t(l)):(e=r(e(),t()),()=>e))))):(f(e,t),A(e,((e,t)=>!t&&((e=d(e)).length?t=>r(e(t)):(e=r(e()),()=>e))))):(u(e,Math.abs(t),t<0),A(e,((...e)=>(e=e.map(d),t=>r(...e.map((e=>e(t)))))))),y=e=>e?l():["",(e=+a((e=>46===e||e>=48&&e<=57||(69===e||101===e?2:0))))!=e?l():e],C=(e,t,r,l)=>(c(e,t,(r=>r?["++"===e?"-":"+",[e,r],["",1]]:[e,s(t-1)])),A(e,l=(e,t)=>"("===e[0]?l(e[1]):"."===e[0]?(t=e[2],e=d(e[1]),l=>r(e(l),t)):"["===e[0]?([,e,t]=e,e=d(e),t=d(t),l=>r(e(l),t(l))):t=>r(t,e)));A("",(e=>()=>e)),o[34]=e=>e?l():["",(a()+a((e=>e-34?1:0))+(a()||l("Bad string"))).slice(1,-1)],o[46]=e=>!e&&y();for(let e=0;e<9;e++)o[48+e]=y;$(",",1,((...e)=>e[e.length-1])),$("||",4,((...e)=>{let t,r=0;for(;!t&&r<e.length;)t=e[r++];return t})),$("&&",5,((...e)=>{let t=0,r=!0;for(;r&&t<e.length;)r=e[t++];return r})),$("+",12,((e,t)=>e+t)),$("-",12,((e,t)=>e-t)),$("*",13,((e,t)=>e*t)),$("/",13,((e,t)=>e/t)),$("%",13,((e,t)=>e%t)),$("|",6,((e,t)=>e|t)),$("&",8,((e,t)=>e&t)),$("^",7,((e,t)=>e^t)),$("==",9,((e,t)=>e==t)),$("!=",9,((e,t)=>e!=t)),$(">",10,((e,t)=>e>t)),$(">=",10,((e,t)=>e>=t)),$("<",10,((e,t)=>e<t)),$("<=",10,((e,t)=>e<=t)),$(">>",11,((e,t)=>e>>t)),$(">>>",11,((e,t)=>e>>>t)),$("<<",11,((e,t)=>e<<t)),$("+",15,(e=>+e)),$("-",15,(e=>-e)),$("!",15,(e=>!e)),C("++",15,((e,t)=>++e[t])),C("--",15,((e,t)=>--e[t])),c("[",18,(e=>e&&["[",e,s(0,93)||l()])),A("[",((e,t)=>t&&(e=d(e),t=d(t),r=>e(r)[t(r)]))),c(".",18,((e,t)=>e&&(t=s(18))&&[".",e,t])),A(".",((e,t)=>(e=d(e),t=t[0]?t:t[1],r=>e(r)[t]))),c("(",18,(e=>!e&&["(",s(0,41)||l()])),c("(",18,((e,t)=>e&&((t=s(0,41))?["(",e,t]:["(",e,""]))),A("(",((e,t,r,l)=>null==t?d(e):(l=""==t?()=>[]:","===t[0]?(t=t.slice(1).map(d),e=>t.map((t=>t(e)))):(t=d(t),e=>[t(e)]),"."===e[0]?(r=e[2],e=d(e[1]),t=>e(t)[r](...l(t))):"["===e[0]?(r=d(e[2]),e=d(e[1]),t=>e(t)[r(t)](...l(t))):(e=d(e),t=>e(t)(...l(t))))));let x={n:"\n",r:"\r",t:"\t",b:"\b",f:"\f",v:"\v"},E=r=>(n,s,i="")=>{for(n&&l("Unexpected string"),a();(s=t.charCodeAt(e))-r;)92===s?(a(),s=a(),i+=x[s]||s):i+=a();return a(),["",i]};$("===",9,((e,t)=>e===t)),$("!==",9,((e,t)=>e!==t)),$("~",15,(e=>~e)),c("?",3,((e,t,r)=>e&&(t=s(2,58))&&["?",e,t,s(3)])),A("?",((e,t,r)=>(e=d(e),t=d(t),r=d(r),l=>e(l)?t(l):r(l)))),$("??",6,((e,t)=>e??t)),c("?.",18,(e=>e&&["?.",e])),A("?.",(e=>(e=d(e),t=>e(t)||(()=>{})))),c("?.",18,((e,t)=>e&&!(t=s(18))?.map&&["?.",e,t])),A("?.",((e,t)=>t&&(e=d(e),r=>e(r)?.[t]))),A("(",((e,t,r,l)=>null!=t&&"?."===e[0]&&(l=""==t?()=>[]:","===t[0]?(t=t.slice(1).map(d),e=>t.map((t=>t(e)))):(t=d(t),e=>[t(e)]),r=e[2],e=d(e[1]),t=>e(t)?.[r](...l(t))))),$("in",10,((e,t)=>e in t)),o[34]=E(34),o[39]=E(39),c("/*",20,((r,l)=>(a((r=>42!==r&&47!==t.charCodeAt(e+1))),a(2),r||s(l)||[""]))),c("//",20,((e,t)=>(a((e=>e>=32)),e||s(t)||[""]))),c("null",20,(e=>e?l():["",null])),c("true",20,(e=>e?l():["",!0])),c("false",20,(e=>e?l():["",!1])),c("undefined",20,(e=>e?l():["",void 0])),$(";",-20,((...e)=>{for(let t=e.length;t--;)if(null!=e[t])return e[t]})),$("**",-14,((e,t)=>e**t)),c("[",20,(e=>!e&&["[",s(0,93)||""])),A("[",((e,t)=>!t&&(e?","===e[0]?(e=e.slice(1).map(d),t=>e.map((e=>e(t)))):(e=d(e),t=>[e(t)]):()=>[]))),c("{",20,(e=>!e&&["{",s(0,125)||""])),A("{",((e,t)=>e?","===e[0]?(e=e.slice(1).map(d),t=>Object.fromEntries(e.map((e=>e(t))))):":"===e[0]?(e=d(e),t=>Object.fromEntries([e(t)])):(t=d(e),r=>({[e]:t(r)})):e=>({}))),c(":",1.1,((e,t)=>[":",e,s(1.1)||l()])),A(":",((e,t)=>(t=d(t),e=Array.isArray(e)?d(e):(e=>e).bind(0,e),r=>[e(r),t(r)])));export{g as binary,d as compile,t as cur,b as default,l as err,s as expr,p as id,e as idx,i as isId,n as longErr,o as lookup,u as nary,A as operator,m as operators,r as parse,$ as set,a as skip,h as space,c as token,f as unary};
|
package/package.json
CHANGED
package/parse.js
CHANGED
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
const SPACE=32
|
|
1
|
+
const SPACE = 32
|
|
2
2
|
|
|
3
3
|
// current string, index and collected ids
|
|
4
4
|
export let idx, cur,
|
|
5
5
|
|
|
6
|
-
// no handling tagged literals since easily done on user side with cache, if needed
|
|
7
|
-
parse = s => (idx=0, cur=s, s = expr(), cur[idx] ? err() : s || ''),
|
|
8
|
-
|
|
9
|
-
err = (msg='Bad syntax', frag=cur[idx], prev=cur.slice(0,idx).split('\n'), last=prev.pop()) => {
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
|
|
13
|
-
longErr = (msg='Bad syntax',
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
skip = (is=1, from=idx, l) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
// a + b - c
|
|
31
|
-
expr = (prec=0, end, cc, token, newNode, fn) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
6
|
+
// no handling tagged literals since easily done on user side with cache, if needed
|
|
7
|
+
parse = s => (idx = 0, cur = s, s = expr(), cur[idx] ? err() : s || ''),
|
|
8
|
+
|
|
9
|
+
err = (msg = 'Bad syntax', frag = cur[idx], prev = cur.slice(0, idx).split('\n'), last = prev.pop()) => {
|
|
10
|
+
throw SyntaxError(`${msg} ${frag ? `\`${frag}\` ` : ''}at ${prev.length}:${last.length}`, prev.length)
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
longErr = (msg = 'Bad syntax',
|
|
14
|
+
frag = cur[idx],
|
|
15
|
+
lines = cur.slice(0, idx).split('\n'),
|
|
16
|
+
last = lines.pop()
|
|
17
|
+
) => {
|
|
18
|
+
let before = cur.slice(idx - 10, idx).split('\n').pop()
|
|
19
|
+
let after = cur.slice(idx + 1, idx + 10).split('\n').shift()
|
|
20
|
+
let location = lines.length + ':' + last.length
|
|
21
|
+
throw EvalError(`${msg} at ${location} \`${before + frag + after}\`\n${' '.repeat(18 + msg.length + location.length + before.length + 1)}^`)
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
skip = (is = 1, from = idx, l) => {
|
|
25
|
+
if (typeof is == 'number') idx += is
|
|
26
|
+
else while (l = is(cur.charCodeAt(idx))) idx += l
|
|
27
|
+
return cur.slice(from, idx)
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
// a + b - c
|
|
31
|
+
expr = (prec = 0, end, cc, token, newNode, fn) => {
|
|
32
|
+
// chunk/token parser
|
|
33
|
+
while (
|
|
34
|
+
(cc = parse.space()) && // till not end
|
|
35
|
+
// FIXME: extra work is happening here, when lookup bails out due to lower precedence -
|
|
36
|
+
// it makes extra `space` call for parent exprs on the same character to check precedence again
|
|
37
|
+
(newNode =
|
|
38
|
+
((fn = lookup[cc]) && fn(token, prec)) ?? // if operator with higher precedence isn't found
|
|
39
|
+
(!token && parse.id()) // parse literal or quit. token seqs are forbidden: `a b`, `a "b"`, `1.32 a`
|
|
40
|
+
)
|
|
41
|
+
) token = newNode;
|
|
42
|
+
|
|
43
|
+
// check end character
|
|
44
|
+
// FIXME: can't show "Unclosed paren", because can be unknown operator within group as well
|
|
45
|
+
if (end) cc == end ? idx++ : err()
|
|
46
|
+
|
|
47
|
+
return token
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
isId = c =>
|
|
51
|
+
(c >= 48 && c <= 57) || // 0..9
|
|
52
|
+
(c >= 65 && c <= 90) || // A...Z
|
|
53
|
+
(c >= 97 && c <= 122) || // a...z
|
|
54
|
+
c == 36 || c == 95 || // $, _,
|
|
55
|
+
(c >= 192 && c != 215 && c != 247), // any non-ASCII
|
|
56
|
+
|
|
57
|
+
// skip space chars, return first non-space character
|
|
58
|
+
space = parse.space = cc => { while ((cc = cur.charCodeAt(idx)) <= SPACE) idx++; return cc },
|
|
59
|
+
|
|
60
|
+
id = parse.id = n => skip(isId),
|
|
61
|
+
|
|
62
|
+
// operator/token lookup table
|
|
63
|
+
// lookup[0] is id parser to let configs redefine it
|
|
64
|
+
lookup = [],
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
// create operator checker/mapper (see examples)
|
|
68
|
+
token = (
|
|
69
|
+
op,
|
|
70
|
+
prec = SPACE,
|
|
71
|
+
map,
|
|
72
|
+
c = op.charCodeAt(0),
|
|
73
|
+
l = op.length,
|
|
74
|
+
prev = lookup[c],
|
|
75
|
+
word = op.toUpperCase() !== op // make sure word boundary comes after word operator
|
|
76
|
+
) => lookup[c] = (a, curPrec, from = idx) =>
|
|
77
|
+
(curPrec < prec && (l < 2 || cur.substr(idx, l) == op) && (!word || !isId(cur.charCodeAt(idx + l))) && (idx += l, map(a, curPrec))) ||
|
|
78
|
+
(idx = from, prev?.(a, curPrec)),
|
|
79
|
+
|
|
80
|
+
// right assoc is indicated by negative precedence (meaning go from right to left)
|
|
81
|
+
binary = (op, prec, right = 0) => token(op, prec, (a, b) => a && (b = expr(prec - right / 2)) && [op, a, b]),
|
|
82
|
+
unary = (op, prec, post) => token(op, prec, a => post ? (a && [op, a]) : (!a && (a = expr(prec - .5)) && [op, a])),
|
|
83
|
+
nary = (op, prec, skips) => {
|
|
84
|
+
token(op, prec, (a, b) => (
|
|
85
|
+
(a || skips) && // if lhs exists or we're ok to skip
|
|
86
|
+
(b = expr(prec), b || skips) && // either rhs exists or we're ok to skip rhs
|
|
87
|
+
(
|
|
88
|
+
(!a || a[0] !== op) && (a = [op, a]), // if beginning of sequence - init node
|
|
89
|
+
(b || skips) && a.push(b),
|
|
90
|
+
a
|
|
91
|
+
))
|
|
40
92
|
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// check end character
|
|
44
|
-
// FIXME: can't show "Unclose paren", because can be unknown operator within group as well
|
|
45
|
-
if (end) cc==end?idx++:err()
|
|
46
|
-
|
|
47
|
-
return token
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
isId = c =>
|
|
51
|
-
(c >= 48 && c <= 57) || // 0..9
|
|
52
|
-
(c >= 65 && c <= 90) || // A...Z
|
|
53
|
-
(c >= 97 && c <= 122) || // a...z
|
|
54
|
-
c == 36 || c == 95 || // $, _,
|
|
55
|
-
(c >= 192 && c != 215 && c != 247), // any non-ASCII
|
|
56
|
-
|
|
57
|
-
// skip space chars, return first non-space character
|
|
58
|
-
space = parse.space = cc => { while ((cc = cur.charCodeAt(idx)) <= SPACE) idx++; return cc },
|
|
59
|
-
|
|
60
|
-
id = parse.id = n => skip(isId),
|
|
61
|
-
|
|
62
|
-
// operator/token lookup table
|
|
63
|
-
// lookup[0] is id parser to let configs redefine it
|
|
64
|
-
lookup = [],
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// create operator checker/mapper (see examples)
|
|
68
|
-
token = (
|
|
69
|
-
op,
|
|
70
|
-
prec=SPACE,
|
|
71
|
-
map,
|
|
72
|
-
c=op.charCodeAt(0),
|
|
73
|
-
l=op.length,
|
|
74
|
-
prev=lookup[c],
|
|
75
|
-
word=op.toUpperCase()!==op // make sure word boundary comes after word operator
|
|
76
|
-
) => lookup[c] = (a, curPrec, from=idx) =>
|
|
77
|
-
(curPrec<prec && (l<2||cur.substr(idx,l)==op) && (!word||!isId(cur.charCodeAt(idx+l))) && (idx+=l, map(a, curPrec))) ||
|
|
78
|
-
(idx=from, prev?.(a, curPrec)),
|
|
79
|
-
|
|
80
|
-
// right assoc is indicated by negative precedence (meaning go from right to left)
|
|
81
|
-
binary = (op, prec, right=0) => token(op, prec, (a, b) => a && (b=expr(prec-right/2)) && [op,a,b] ),
|
|
82
|
-
unary = (op, prec, post) => token(op, prec, a => post ? (a && [op, a]) : (!a && (a=expr(prec-.5)) && [op, a])),
|
|
83
|
-
nary = (op, prec, skips) => {
|
|
84
|
-
token(op, prec, (a, b) => (
|
|
85
|
-
(a || skips) && // if lhs exists or we're ok to skip
|
|
86
|
-
(b=expr(prec), b||skips) && // either rhs exists or we're ok to skip rhs
|
|
87
|
-
(
|
|
88
|
-
(!a || a[0] !== op) && (a = [op,a]), // if beginning of sequence - init node
|
|
89
|
-
(b || skips) && a.push(b),
|
|
90
|
-
a
|
|
91
|
-
))
|
|
92
|
-
)
|
|
93
|
-
}
|
|
93
|
+
}
|
|
94
94
|
|
|
95
95
|
export default parse
|
package/subscript.js
CHANGED
|
@@ -1,128 +1,116 @@
|
|
|
1
1
|
import parse, { lookup, nary, binary, unary, token, skip, err, expr } from './parse.js'
|
|
2
2
|
import compile, { operator } from './compile.js'
|
|
3
3
|
|
|
4
|
-
const OPAREN=40, CPAREN=41, OBRACK=91, CBRACK=93, SPACE=32, DQUOTE=34, PERIOD=46, _0=48, _9=57,
|
|
5
|
-
PREC_SEQ=1, PREC_SOME=4, PREC_EVERY=5, PREC_OR=6, PREC_XOR=7, PREC_AND=8,
|
|
6
|
-
PREC_EQ=9, PREC_COMP=10, PREC_SHIFT=11, PREC_SUM=12, PREC_MULT=13, PREC_UNARY=15, PREC_POSTFIX=16, PREC_CALL=18
|
|
7
|
-
|
|
8
|
-
const subscript = s => (s=parse(s),ctx => (s.call?s:(s=compile(s)))(ctx)),
|
|
9
|
-
|
|
10
|
-
// set any operator
|
|
11
|
-
// right assoc is indicated by negative precedence (meaning go from right to left)
|
|
12
|
-
set = (op, prec, fn) =>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
4
|
+
const OPAREN = 40, CPAREN = 41, OBRACK = 91, CBRACK = 93, SPACE = 32, DQUOTE = 34, PERIOD = 46, _0 = 48, _9 = 57,
|
|
5
|
+
PREC_SEQ = 1, PREC_SOME = 4, PREC_EVERY = 5, PREC_OR = 6, PREC_XOR = 7, PREC_AND = 8,
|
|
6
|
+
PREC_EQ = 9, PREC_COMP = 10, PREC_SHIFT = 11, PREC_SUM = 12, PREC_MULT = 13, PREC_UNARY = 15, PREC_POSTFIX = 16, PREC_CALL = 18
|
|
7
|
+
|
|
8
|
+
const subscript = s => (s = parse(s), ctx => (s.call ? s : (s = compile(s)))(ctx)),
|
|
9
|
+
|
|
10
|
+
// set any operator
|
|
11
|
+
// right assoc is indicated by negative precedence (meaning go from right to left)
|
|
12
|
+
set = (op, prec, fn) => (
|
|
13
|
+
!fn.length ? (
|
|
14
|
+
nary(op, Math.abs(prec), prec < 0),
|
|
15
|
+
operator(op, (...args) => (args = args.map(compile), ctx => fn(...args.map(arg => arg(ctx)))))
|
|
16
|
+
) :
|
|
17
|
+
fn.length > 1 ? (
|
|
18
|
+
binary(op, Math.abs(prec), prec < 0),
|
|
19
|
+
operator(op,
|
|
20
|
+
(a, b) => b && (a = compile(a), b = compile(b), !a.length && !b.length ? (a = fn(a(), b()), () => a) : ctx => fn(a(ctx), b(ctx)))
|
|
21
|
+
)
|
|
22
|
+
) :
|
|
23
|
+
(
|
|
24
|
+
unary(op, prec),
|
|
25
|
+
operator(op, (a, b) => !b && (a = compile(a), !a.length ? (a = fn(a()), () => a) : ctx => fn(a(ctx))))
|
|
26
|
+
)
|
|
27
|
+
),
|
|
28
|
+
|
|
29
|
+
num = a => a ? err() : ['', (a = +skip(c => c === PERIOD || (c >= _0 && c <= _9) || (c === 69 || c === 101 ? 2 : 0))) != a ? err() : a],
|
|
30
|
+
|
|
31
|
+
// create increment-assign pair from fn
|
|
32
|
+
inc = (op, prec, fn, ev) => (
|
|
33
|
+
token(op, prec, a => a ? [op === '++' ? '-' : '+', [op, a], ['', 1]] : [op, expr(prec - 1)]), // ++a → [++, a], a++ → [-,[++,a],1]
|
|
34
|
+
operator(op, ev = (a, b) => (
|
|
35
|
+
a[0] === '(' ? ev(a[1]) : // ++(((a)))
|
|
36
|
+
a[0] === '.' ? (b = a[2], a = compile(a[1]), ctx => fn(a(ctx), b)) : // ++a.b
|
|
37
|
+
a[0] === '[' ? ([, a, b] = a, a = compile(a), b = compile(b), ctx => fn(a(ctx), b(ctx))) : // ++a[b]
|
|
38
|
+
(ctx => fn(ctx, a)) // ++a
|
|
39
|
+
))
|
|
27
40
|
)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// a
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
],
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
(a,b) => (a=compile(a),b=!b[0]?b[1]:b, ctx => a(ctx)[b]) // a.true, a.1 → needs to work fine
|
|
100
|
-
],
|
|
101
|
-
|
|
102
|
-
// (a,b,c), (a)
|
|
103
|
-
'(', PREC_CALL, [
|
|
104
|
-
a => !a && ['(', expr(0,CPAREN)||err()],
|
|
105
|
-
compile
|
|
106
|
-
],
|
|
107
|
-
|
|
108
|
-
// a(b,c,d), a()
|
|
109
|
-
'(', PREC_CALL, [
|
|
110
|
-
(a,b) => a && (b = expr(0,CPAREN), b ? ['(', a, b] : ['(', a, '']),
|
|
111
|
-
(a,b,path,args) => b!=null && (
|
|
112
|
-
args = b=='' ? () => [] : // a()
|
|
113
|
-
b[0] === ',' ? (b=b.slice(1).map(compile), ctx => b.map(a=>a(ctx))) : // a(b,c)
|
|
114
|
-
(b=compile(b), ctx => [b(ctx)]), // a(b)
|
|
115
|
-
|
|
116
|
-
a[0] === '.' ? (path=a[2], a=compile(a[1]), ctx => a(ctx)[path](...args(ctx))) : // a.b(...args)
|
|
117
|
-
a[0] === '[' ? (path=compile(a[2]), a=compile(a[1]), ctx => a(ctx)[path(ctx)](...args(ctx))) : // a[b](...args)
|
|
118
|
-
(a=compile(a), ctx => a(ctx)(...args(ctx))) // a(...args)
|
|
119
|
-
)
|
|
120
|
-
]
|
|
121
|
-
]
|
|
122
|
-
|
|
123
|
-
for (;list[2];) set(...list.splice(0,3))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
// literals
|
|
44
|
+
// null operator returns first value (needed for direct literals)
|
|
45
|
+
operator('', v => () => v)
|
|
46
|
+
|
|
47
|
+
// "a"
|
|
48
|
+
lookup[DQUOTE] = (a) => a ? err() : ['', (skip() + skip(c => c - DQUOTE ? 1 : 0) + (skip() || err('Bad string'))).slice(1, -1)]
|
|
49
|
+
|
|
50
|
+
// .1
|
|
51
|
+
lookup[PERIOD] = a => !a && num()
|
|
52
|
+
|
|
53
|
+
// 0-9
|
|
54
|
+
for (let i = 0; i < 9; i++) lookup[_0 + i] = num
|
|
55
|
+
|
|
56
|
+
// sequences
|
|
57
|
+
set(',', PREC_SEQ, (...args) => args[args.length - 1])
|
|
58
|
+
set('||', PREC_SOME, (...args) => { let i = 0, v; for (; !v && i < args.length;) v = args[i++]; return v })
|
|
59
|
+
set('&&', PREC_EVERY, (...args) => { let i = 0, v = true; for (; v && i < args.length;) v = args[i++]; return v })
|
|
60
|
+
|
|
61
|
+
// binaries
|
|
62
|
+
set('+', PREC_SUM, (a, b) => a + b)
|
|
63
|
+
set('-', PREC_SUM, (a, b) => a - b)
|
|
64
|
+
set('*', PREC_MULT, (a, b) => a * b)
|
|
65
|
+
set('/', PREC_MULT, (a, b) => a / b)
|
|
66
|
+
set('%', PREC_MULT, (a, b) => a % b)
|
|
67
|
+
set('|', PREC_OR, (a, b) => a | b)
|
|
68
|
+
set('&', PREC_AND, (a, b) => a & b)
|
|
69
|
+
set('^', PREC_XOR, (a, b) => a ^ b)
|
|
70
|
+
set('==', PREC_EQ, (a, b) => a == b)
|
|
71
|
+
set('!=', PREC_EQ, (a, b) => a != b)
|
|
72
|
+
set('>', PREC_COMP, (a, b) => a > b)
|
|
73
|
+
set('>=', PREC_COMP, (a, b) => a >= b)
|
|
74
|
+
set('<', PREC_COMP, (a, b) => a < b)
|
|
75
|
+
set('<=', PREC_COMP, (a, b) => a <= b)
|
|
76
|
+
set('>>', PREC_SHIFT, (a, b) => a >> b)
|
|
77
|
+
set('>>>', PREC_SHIFT, (a, b) => a >>> b)
|
|
78
|
+
set('<<', PREC_SHIFT, (a, b) => a << b)
|
|
79
|
+
|
|
80
|
+
// unaries
|
|
81
|
+
set('+', PREC_UNARY, a => +a)
|
|
82
|
+
set('-', PREC_UNARY, a => -a)
|
|
83
|
+
set('!', PREC_UNARY, a => !a)
|
|
84
|
+
|
|
85
|
+
// increments
|
|
86
|
+
inc('++', PREC_UNARY, (a, b) => ++a[b])
|
|
87
|
+
inc('--', PREC_UNARY, (a, b) => --a[b])
|
|
88
|
+
|
|
89
|
+
// a[b]
|
|
90
|
+
token('[', PREC_CALL, a => a && ['[', a, expr(0, CBRACK) || err()])
|
|
91
|
+
operator('[', (a, b) => b && (a = compile(a), b = compile(b), ctx => a(ctx)[b(ctx)]))
|
|
92
|
+
|
|
93
|
+
// a.b
|
|
94
|
+
token('.', PREC_CALL, (a, b) => a && (b = expr(PREC_CALL)) && ['.', a, b])
|
|
95
|
+
operator('.', (a, b) => (a = compile(a), b = !b[0] ? b[1] : b, ctx => a(ctx)[b])) // a.true, a.1 → needs to work fine
|
|
96
|
+
|
|
97
|
+
// (a,b,c), (a)
|
|
98
|
+
token('(', PREC_CALL, a => !a && ['(', expr(0, CPAREN) || err()])
|
|
99
|
+
|
|
100
|
+
// a(b,c,d), a()
|
|
101
|
+
token('(', PREC_CALL, (a, b) => a && (b = expr(0, CPAREN), b ? ['(', a, b] : ['(', a, '']))
|
|
102
|
+
operator('(', (a, b, path, args) => b == null ? compile(a, b) : (
|
|
103
|
+
args = b == '' ? () => [] : // a()
|
|
104
|
+
b[0] === ',' ? (b = b.slice(1).map(compile), ctx => b.map(a => a(ctx))) : // a(b,c)
|
|
105
|
+
(b = compile(b), ctx => [b(ctx)]), // a(b)
|
|
106
|
+
|
|
107
|
+
a[0] === '.' ? (path = a[2], a = compile(a[1]), ctx => a(ctx)[path](...args(ctx))) : // a.b(...args)
|
|
108
|
+
a[0] === '[' ? (path = compile(a[2]), a = compile(a[1]), ctx => a(ctx)[path(ctx)](...args(ctx))) : // a[b](...args)
|
|
109
|
+
(a = compile(a), ctx => a(ctx)(...args(ctx))) // a(...args)
|
|
110
|
+
)
|
|
111
|
+
)
|
|
124
112
|
|
|
125
113
|
export default subscript
|
|
126
|
-
export {set}
|
|
114
|
+
export { set }
|
|
127
115
|
export * from './parse.js'
|
|
128
116
|
export * from './compile.js'
|
package/subscript.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let t,e,l=l=>(t=0,e=l,l=s(),e[t]?r():l||""),r=(l="Bad syntax",r=e[t],
|
|
1
|
+
let t,e,l=l=>(t=0,e=l,l=s(),e[t]?r():l||""),r=(l="Bad syntax",r=e[t],n=e.slice(0,t).split("\n"),a=n.pop())=>{throw SyntaxError(`${l} ${r?`\`${r}\` `:""}at ${n.length}:${a.length}`,n.length)},n=(l="Bad syntax",r=e[t],n=e.slice(0,t).split("\n"),a=n.pop())=>{let s=e.slice(t-10,t).split("\n").pop(),h=e.slice(t+1,t+10).split("\n").shift(),p=n.length+":"+a.length;throw EvalError(`${l} at ${p} \`${s+r+h}\`\n${" ".repeat(18+l.length+p.length+s.length+1)}^`)},a=(l=1,r=t,n)=>{if("number"==typeof l)t+=l;else for(;n=l(e.charCodeAt(t));)t+=n;return e.slice(r,t)},s=(e=0,n,a,s,h,p)=>{for(;(a=l.space())&&(h=((p=g[a])&&p(s,e))??(!s&&l.id()));)s=h;return n&&(a==n?t++:r()),s},h=t=>t>=48&&t<=57||t>=65&&t<=90||t>=97&&t<=122||36==t||95==t||t>=192&&215!=t&&247!=t,p=l.space=l=>{for(;(l=e.charCodeAt(t))<=32;)t++;return l},o=l.id=t=>a(h),g=[],i=(l,r=32,n,a=l.charCodeAt(0),s=l.length,p=g[a],o=l.toUpperCase()!==l)=>g[a]=(a,g,i=t)=>g<r&&(s<2||e.substr(t,s)==l)&&(!o||!h(e.charCodeAt(t+s)))&&(t+=s,n(a,g))||(t=i,p?.(a,g)),c=(t,e,l=0)=>i(t,e,((r,n)=>r&&(n=s(e-l/2))&&[t,r,n])),d=(t,e,l)=>i(t,e,(r=>l?r&&[t,r]:!r&&(r=s(e-.5))&&[t,r])),f=(t,e,l)=>{i(t,e,((r,n)=>(r||l)&&((n=s(e))||l)&&((!r||r[0]!==t)&&(r=[t,r]),(n||l)&&r.push(n),r)))};const u=t=>Array.isArray(t)?$[t[0]](...t.slice(1)):e=>e?.[t],$={},y=(t,e,l=$[t])=>$[t]=(...t)=>e(...t)||l&&l(...t),A=t=>(t=l(t),e=>(t.call?t:t=u(t))(e)),m=(t,e,l)=>l.length?l.length>1?(c(t,Math.abs(e),e<0),y(t,((t,e)=>e&&(t=u(t),e=u(e),t.length||e.length?r=>l(t(r),e(r)):(t=l(t(),e()),()=>t))))):(d(t,e),y(t,((t,e)=>!e&&((t=u(t)).length?e=>l(t(e)):(t=l(t()),()=>t))))):(f(t,Math.abs(e),e<0),y(t,((...t)=>(t=t.map(u),e=>l(...t.map((t=>t(e)))))))),C=t=>t?r():["",(t=+a((t=>46===t||t>=48&&t<=57||(69===t||101===t?2:0))))!=t?r():t],b=(t,e,l,r)=>(i(t,e,(l=>l?["++"===t?"-":"+",[t,l],["",1]]:[t,s(e-1)])),y(t,r=(t,e)=>"("===t[0]?r(t[1]):"."===t[0]?(e=t[2],t=u(t[1]),r=>l(t(r),e)):"["===t[0]?([,t,e]=t,t=u(t),e=u(e),r=>l(t(r),e(r))):e=>l(e,t)));y("",(t=>()=>t)),g[34]=t=>t?r():["",(a()+a((t=>t-34?1:0))+(a()||r("Bad string"))).slice(1,-1)],g[46]=t=>!t&&C();for(let t=0;t<9;t++)g[48+t]=C;m(",",1,((...t)=>t[t.length-1])),m("||",4,((...t)=>{let e,l=0;for(;!e&&l<t.length;)e=t[l++];return e})),m("&&",5,((...t)=>{let e=0,l=!0;for(;l&&e<t.length;)l=t[e++];return l})),m("+",12,((t,e)=>t+e)),m("-",12,((t,e)=>t-e)),m("*",13,((t,e)=>t*e)),m("/",13,((t,e)=>t/e)),m("%",13,((t,e)=>t%e)),m("|",6,((t,e)=>t|e)),m("&",8,((t,e)=>t&e)),m("^",7,((t,e)=>t^e)),m("==",9,((t,e)=>t==e)),m("!=",9,((t,e)=>t!=e)),m(">",10,((t,e)=>t>e)),m(">=",10,((t,e)=>t>=e)),m("<",10,((t,e)=>t<e)),m("<=",10,((t,e)=>t<=e)),m(">>",11,((t,e)=>t>>e)),m(">>>",11,((t,e)=>t>>>e)),m("<<",11,((t,e)=>t<<e)),m("+",15,(t=>+t)),m("-",15,(t=>-t)),m("!",15,(t=>!t)),b("++",15,((t,e)=>++t[e])),b("--",15,((t,e)=>--t[e])),i("[",18,(t=>t&&["[",t,s(0,93)||r()])),y("[",((t,e)=>e&&(t=u(t),e=u(e),l=>t(l)[e(l)]))),i(".",18,((t,e)=>t&&(e=s(18))&&[".",t,e])),y(".",((t,e)=>(t=u(t),e=e[0]?e:e[1],l=>t(l)[e]))),i("(",18,(t=>!t&&["(",s(0,41)||r()])),i("(",18,((t,e)=>t&&((e=s(0,41))?["(",t,e]:["(",t,""]))),y("(",((t,e,l,r)=>null==e?u(t):(r=""==e?()=>[]:","===e[0]?(e=e.slice(1).map(u),t=>e.map((e=>e(t)))):(e=u(e),t=>[e(t)]),"."===t[0]?(l=t[2],t=u(t[1]),e=>t(e)[l](...r(e))):"["===t[0]?(l=u(t[2]),t=u(t[1]),e=>t(e)[l(e)](...r(e))):(t=u(t),e=>t(e)(...r(e))))));export{c as binary,u as compile,e as cur,A as default,r as err,s as expr,o as id,t as idx,h as isId,n as longErr,g as lookup,f as nary,y as operator,$ as operators,l as parse,m as set,a as skip,p as space,i as token,d as unary};
|