You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Avoid ad-hocs - that signals inconsistency of design. High-level API is for a reason, we need to use it and if it doesn't fit, we need to improve it.
3
+
`/features` represent generic language features, not only JS: avoid js-specific checks.
4
+
For features you implement or any changes, if relevant please add tests, update spec.md, docs.md and README.md, as well as REPL and other relevant files. Make sure tests pass.
5
+
Make sure API and feature code is intuitive and user-friendly: prefer `unary`/`binary`/`nary`/`group`/`token` calls in the right order ( eg. first `|`, then `||`, then `||=` ) rather than low-level parsing. Eg. feature should not use `cur`, `idx` and use `skip` instead.
6
+
The project is planned to be built with jz - simple javascript subset compiling to wasm, so don't use complex structures like Proxy, classes etc.
7
+
By introducing a change, think how would that scale to various dialects and compile targets. Also make sure it doesn't compromise performance and doesn't bloat the code. Justin must be faster than jsep.
8
+
By writing parser feature, aim for raw tree shape parsed with minimal code rather than edge cases validation.
***Safe** — sandboxed, blocks `__proto__`, `constructor`, no global access
6
+
***Fast** — Pratt parser engine, see [benchmarks](#performance)
7
+
***Portable** — universal expression format, any compile target
8
+
***Metacircular** — can parse and compile itself
9
+
***Extensible** — pluggable syntax for building custom DSL
6
10
7
-
* expressions evaluators, calculators
8
-
* subsets of languages
9
-
* sandboxes, playgrounds, safe eval
10
-
* custom DSL
11
-
* preprocessors
12
-
* templates
11
+
## Usage
13
12
14
-
_Subscript_ has [3.5kb](https://npmfs.com/package/subscript/7.4.3/subscript.min.js) footprint <!-- (compare 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_) -->, good [performance](#performance) and extensive test coverage.
`if else for while do let const var function class return throw try catch switch import export /regex/`
84
50
```js
85
-
importsubscriptfrom'subscript/justin'
86
-
import'subscript/feature/loop.js'
87
-
88
-
let sum =subscript(`
89
-
let sum = 0;
90
-
for (i = 0; i < 10; i += 1) sum += i;
91
-
sum
51
+
importjessiefrom'subscript/jessie.js'
52
+
53
+
let fn =jessie(`
54
+
function factorial(n) {
55
+
if (n <= 1) return 1
56
+
return n * factorial(n - 1)
57
+
}
58
+
factorial(5)
92
59
`)
93
-
sum() //45
60
+
fn({}) //120
94
61
```
95
62
63
+
Jessie can parse and compile its own source.
64
+
96
65
97
66
## Parse / Compile
98
67
@@ -110,157 +79,113 @@ fn = compile(tree)
110
79
fn({ a: {b:1}, c:2 }) // 2
111
80
```
112
81
113
-
### Syntax Tree
114
-
115
-
AST has simplified lispy tree structure (inspired by [frisk](https://ghub.io/frisk) / [nisp](https://github.com/ysmood/nisp)), opposed to [ESTree](https://github.com/estree/estree):
82
+
## Extension
116
83
117
-
* not limited to particular language (JS), can be compiled to different targets;
118
-
* reflects execution sequence, rather than code layout;
119
-
* has minimal overhead, directly maps to operators;
[, value] // literal — [0] empty distinguishes from operator
132
-
[op, a] // unary — prefix operator
133
-
[op, a, null] // unary — postfix operator (null marks postfix)
134
-
[op, a, b] // binary
135
-
[op, a, b, c] // n-ary / ternary
136
-
137
-
// operators
138
-
['+', a, b] // a + b
139
-
['.', a, 'b'] // a.b — property access
140
-
['[]', a, b] // a[b] — bracket access
141
-
['()', a] // (a) — grouping
142
-
['()', a, b] // a(b) — function call
143
-
['()', a, null] // a() — call with no args
144
-
145
-
// literals & structures
146
-
[, 1] // 1
147
-
[, 'hello'] // "hello"
148
-
['[]', [',', ...]] // [a, b] — array literal
149
-
['{}', [':', ...]] // {a: b} — object literal
150
-
151
-
// justin extensions
152
-
['?', a, b, c] // a ? b : c — ternary
153
-
['=>', params, x] // (a) => x — arrow function
154
-
['...', a] // ...a — spread
155
-
156
-
// control flow (extra)
157
-
['if', cond, then, else]
158
-
['while', cond, body]
159
-
['for', init, cond, step, body]
160
-
161
-
// postfix example
162
-
['++', 'a'] // ++a
163
-
['++', 'a', null] // a++
164
-
['px', [,5]] // 5px (unit suffix)
96
+
importjustinfrom'subscript/justin.js'
97
+
justin('[1,2,3] ∩ [2,3,4]')({}) // [2, 3]
165
98
```
166
99
167
-
### Stringify
100
+
See [docs.md](./docs.md) for full API.
101
+
102
+
103
+
## Syntax Tree
168
104
169
-
To convert tree back to code, there's codegenerator function:
105
+
Expressions parse to a minimal JSON-compatible AST:
170
106
171
107
```js
172
-
import { stringify } from'subscript.js'
108
+
import { parse } from'subscript'
173
109
174
-
stringify(['+', ['*', 'min', [,60]], [,'sec']])
175
-
//'min * 60 + "sec"'
110
+
parse('a + b * 2')
111
+
//['+', 'a', ['*', 'b', [, 2]]]
176
112
```
177
113
178
-
## Extending
179
-
180
-
_Subscript_ provides premade language [features](./feature) and API to customize syntax:
114
+
AST has simplified lispy tree structure (inspired by [frisk](https://ghub.io/frisk) / [nisp](https://github.com/ysmood/nisp)), opposed to [ESTree](https://github.com/estree/estree):
181
115
182
-
*`unary(str, precedence, postfix=false)` − register unary operator, either prefix `⚬a` or postfix `a⚬`.
0 commit comments