fez-lisp 1.0.37 → 1.0.38
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/index.js +2 -2
- package/package.json +1 -1
- package/src/parser.js +41 -0
- package/src/utils.js +3 -3
package/index.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import { evaluate } from './src/interpreter.js'
|
2
|
-
import { parse, stringify } from './src/parser.js'
|
2
|
+
import { parse, stringify, AST } from './src/parser.js'
|
3
3
|
import { fez, tree } from './src/utils.js'
|
4
4
|
import std from './lib/baked/std.js'
|
5
5
|
import { keywords } from './src/tokeniser.js'
|
6
6
|
import { WORD, APPLY, ATOM, VALUE, TYPE } from './src/enums.js'
|
7
7
|
const types = { WORD, APPLY, ATOM, VALUE, TYPE }
|
8
|
-
export { fez, parse, stringify, keywords, evaluate, std, types, tree }
|
8
|
+
export { fez, parse, stringify, keywords, evaluate, std, types, tree, AST }
|
package/package.json
CHANGED
package/src/parser.js
CHANGED
@@ -52,3 +52,44 @@ export const stringify = (ast) => {
|
|
52
52
|
else if (typeof ast === 'boolean') return +ast
|
53
53
|
else return ast
|
54
54
|
}
|
55
|
+
export const AST = {
|
56
|
+
parse: (source) => {
|
57
|
+
const tree = []
|
58
|
+
let head = tree,
|
59
|
+
stack = [tree],
|
60
|
+
acc = ''
|
61
|
+
for (let i = 0; i < source.length; ++i) {
|
62
|
+
const cursor = source[i]
|
63
|
+
if (cursor === '"') {
|
64
|
+
acc += '"'
|
65
|
+
++i
|
66
|
+
while (source[i] !== '"') {
|
67
|
+
acc += source[i]
|
68
|
+
++i
|
69
|
+
}
|
70
|
+
}
|
71
|
+
if (cursor === '[') {
|
72
|
+
head.push([])
|
73
|
+
stack.push(head)
|
74
|
+
head = head.at(-1)
|
75
|
+
} else if (cursor === ']' || cursor === ',') {
|
76
|
+
let token = acc
|
77
|
+
acc = ''
|
78
|
+
if (token) {
|
79
|
+
if (!head.length) head.push(Number(token))
|
80
|
+
else if (token[0] === '"' && token[token.length - 1] === '"')
|
81
|
+
head.push(token.substring(1, token.length - 1))
|
82
|
+
else head.push(Number(token))
|
83
|
+
}
|
84
|
+
if (cursor === ']') head = stack.pop()
|
85
|
+
} else acc += cursor
|
86
|
+
}
|
87
|
+
return tree[0]
|
88
|
+
},
|
89
|
+
stringify: (ast) =>
|
90
|
+
typeof ast === 'object'
|
91
|
+
? `[${ast.map(AST.stringify).join(',')}]`
|
92
|
+
: typeof ast === 'string'
|
93
|
+
? `"${ast}"`
|
94
|
+
: ast
|
95
|
+
}
|
package/src/utils.js
CHANGED
@@ -2,7 +2,7 @@ import std from '../lib/baked/std.js'
|
|
2
2
|
import { comp } from './compiler.js'
|
3
3
|
import { APPLY, KEYWORDS, TYPE, VALUE, WORD } from './enums.js'
|
4
4
|
import { run } from './interpreter.js'
|
5
|
-
import { isLeaf, parse } from './parser.js'
|
5
|
+
import { AST, isLeaf, parse } from './parser.js'
|
6
6
|
export const logError = (error) => console.log('\x1b[31m', error, '\x1b[0m')
|
7
7
|
export const logSuccess = (output) => console.log(output, '\x1b[0m')
|
8
8
|
export const removeNoCode = (source) =>
|
@@ -161,7 +161,7 @@ export const dfs = (tree, callback) => {
|
|
161
161
|
if (!isLeaf(tree)) for (const leaf of tree) dfs(leaf)
|
162
162
|
else callback(tree)
|
163
163
|
}
|
164
|
-
export const deepClone = (ast) =>
|
164
|
+
export const deepClone = (ast) => AST.parse(AST.stringify(ast))
|
165
165
|
export const fez = (source, options = {}) => {
|
166
166
|
const env = options.env ?? {}
|
167
167
|
try {
|
@@ -187,7 +187,7 @@ export const fez = (source, options = {}) => {
|
|
187
187
|
return run(ast, env)
|
188
188
|
} else if (Array.isArray(source)) {
|
189
189
|
const ast = !options.mutation
|
190
|
-
?
|
190
|
+
? AST.parse(AST.stringify(source).replace(new RegExp(/!/g), 'ǃ'))
|
191
191
|
: source
|
192
192
|
if (options.compile) {
|
193
193
|
const js = Object.values(comp(deepClone(ast))).join('')
|