jslike 1.4.0 → 1.4.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/dist/esm/ast/nodes.js +236 -0
- package/dist/esm/cli/wang-run.js +89 -0
- package/dist/esm/cli/wang-validate.js +87 -0
- package/dist/esm/editor/monaco/index.js +234 -0
- package/dist/esm/editor/wang-prism.js +136 -0
- package/dist/esm/errors/enhanced-error.js +124 -0
- package/dist/esm/index.js +182 -0
- package/dist/esm/interpreter/index.js +201 -0
- package/dist/esm/interpreter/interpreter.js +2155 -0
- package/dist/esm/metadata/index.js +531 -0
- package/dist/esm/parser.js +6241 -0
- package/dist/esm/resolvers/memory.js +17 -0
- package/dist/esm/runtime/builtins.js +517 -0
- package/dist/esm/runtime/environment.js +85 -0
- package/dist/esm/validator/index.js +100 -0
- package/dist/index.cjs +10 -4
- package/dist/index.d.cts +13 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.js +10 -4
- package/package.json +3 -2
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
// AST Node Constructors
|
|
2
|
+
|
|
3
|
+
export const Program = (body) => ({
|
|
4
|
+
type: 'Program',
|
|
5
|
+
body
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const Literal = (value) => ({
|
|
9
|
+
type: 'Literal',
|
|
10
|
+
value
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const Identifier = (name) => ({
|
|
14
|
+
type: 'Identifier',
|
|
15
|
+
name
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const BinaryExpression = (operator, left, right) => ({
|
|
19
|
+
type: 'BinaryExpression',
|
|
20
|
+
operator,
|
|
21
|
+
left,
|
|
22
|
+
right
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const UnaryExpression = (operator, argument, prefix = true) => ({
|
|
26
|
+
type: 'UnaryExpression',
|
|
27
|
+
operator,
|
|
28
|
+
argument,
|
|
29
|
+
prefix
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export const UpdateExpression = (operator, argument, prefix = true) => ({
|
|
33
|
+
type: 'UpdateExpression',
|
|
34
|
+
operator,
|
|
35
|
+
argument,
|
|
36
|
+
prefix
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const AssignmentExpression = (operator, left, right) => ({
|
|
40
|
+
type: 'AssignmentExpression',
|
|
41
|
+
operator,
|
|
42
|
+
left,
|
|
43
|
+
right
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export const LogicalExpression = (operator, left, right) => ({
|
|
47
|
+
type: 'LogicalExpression',
|
|
48
|
+
operator,
|
|
49
|
+
left,
|
|
50
|
+
right
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const ConditionalExpression = (test, consequent, alternate) => ({
|
|
54
|
+
type: 'ConditionalExpression',
|
|
55
|
+
test,
|
|
56
|
+
consequent,
|
|
57
|
+
alternate
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const CallExpression = (callee, args) => ({
|
|
61
|
+
type: 'CallExpression',
|
|
62
|
+
callee,
|
|
63
|
+
arguments: args
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
export const MemberExpression = (object, property, computed = false) => ({
|
|
67
|
+
type: 'MemberExpression',
|
|
68
|
+
object,
|
|
69
|
+
property,
|
|
70
|
+
computed
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const ArrayExpression = (elements) => ({
|
|
74
|
+
type: 'ArrayExpression',
|
|
75
|
+
elements
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export const ObjectExpression = (properties) => ({
|
|
79
|
+
type: 'ObjectExpression',
|
|
80
|
+
properties
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const Property = (key, value, shorthand = false) => ({
|
|
84
|
+
type: 'Property',
|
|
85
|
+
key,
|
|
86
|
+
value,
|
|
87
|
+
shorthand
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export const FunctionExpression = (id, params, body) => ({
|
|
91
|
+
type: 'FunctionExpression',
|
|
92
|
+
id,
|
|
93
|
+
params,
|
|
94
|
+
body
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export const ArrowFunctionExpression = (params, body, expression = false) => ({
|
|
98
|
+
type: 'ArrowFunctionExpression',
|
|
99
|
+
params,
|
|
100
|
+
body,
|
|
101
|
+
expression
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export const VariableDeclaration = (kind, declarations) => ({
|
|
105
|
+
type: 'VariableDeclaration',
|
|
106
|
+
kind,
|
|
107
|
+
declarations
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export const VariableDeclarator = (id, init = null) => ({
|
|
111
|
+
type: 'VariableDeclarator',
|
|
112
|
+
id,
|
|
113
|
+
init
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
export const FunctionDeclaration = (id, params, body) => ({
|
|
117
|
+
type: 'FunctionDeclaration',
|
|
118
|
+
id,
|
|
119
|
+
params,
|
|
120
|
+
body
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
export const BlockStatement = (body) => ({
|
|
124
|
+
type: 'BlockStatement',
|
|
125
|
+
body
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
export const ExpressionStatement = (expression) => ({
|
|
129
|
+
type: 'ExpressionStatement',
|
|
130
|
+
expression
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
export const ReturnStatement = (argument = null) => ({
|
|
134
|
+
type: 'ReturnStatement',
|
|
135
|
+
argument
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export const IfStatement = (test, consequent, alternate = null) => ({
|
|
139
|
+
type: 'IfStatement',
|
|
140
|
+
test,
|
|
141
|
+
consequent,
|
|
142
|
+
alternate
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
export const WhileStatement = (test, body) => ({
|
|
146
|
+
type: 'WhileStatement',
|
|
147
|
+
test,
|
|
148
|
+
body
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
export const DoWhileStatement = (body, test) => ({
|
|
152
|
+
type: 'DoWhileStatement',
|
|
153
|
+
body,
|
|
154
|
+
test
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
export const ForStatement = (init, test, update, body) => ({
|
|
158
|
+
type: 'ForStatement',
|
|
159
|
+
init,
|
|
160
|
+
test,
|
|
161
|
+
update,
|
|
162
|
+
body
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
export const ForInStatement = (left, right, body) => ({
|
|
166
|
+
type: 'ForInStatement',
|
|
167
|
+
left,
|
|
168
|
+
right,
|
|
169
|
+
body
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
export const ForOfStatement = (left, right, body) => ({
|
|
173
|
+
type: 'ForOfStatement',
|
|
174
|
+
left,
|
|
175
|
+
right,
|
|
176
|
+
body
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
export const BreakStatement = (label = null) => ({
|
|
180
|
+
type: 'BreakStatement',
|
|
181
|
+
label
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
export const ContinueStatement = (label = null) => ({
|
|
185
|
+
type: 'ContinueStatement',
|
|
186
|
+
label
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
export const ThrowStatement = (argument) => ({
|
|
190
|
+
type: 'ThrowStatement',
|
|
191
|
+
argument
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
export const TryStatement = (block, handler = null, finalizer = null) => ({
|
|
195
|
+
type: 'TryStatement',
|
|
196
|
+
block,
|
|
197
|
+
handler,
|
|
198
|
+
finalizer
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
export const CatchClause = (param, body) => ({
|
|
202
|
+
type: 'CatchClause',
|
|
203
|
+
param,
|
|
204
|
+
body
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
export const SwitchStatement = (discriminant, cases) => ({
|
|
208
|
+
type: 'SwitchStatement',
|
|
209
|
+
discriminant,
|
|
210
|
+
cases
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
export const SwitchCase = (test, consequent) => ({
|
|
214
|
+
type: 'SwitchCase',
|
|
215
|
+
test,
|
|
216
|
+
consequent
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
export const NewExpression = (callee, args) => ({
|
|
220
|
+
type: 'NewExpression',
|
|
221
|
+
callee,
|
|
222
|
+
arguments: args
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
export const ThisExpression = () => ({
|
|
226
|
+
type: 'ThisExpression'
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
export const SequenceExpression = (expressions) => ({
|
|
230
|
+
type: 'SequenceExpression',
|
|
231
|
+
expressions
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
export const EmptyStatement = () => ({
|
|
235
|
+
type: 'EmptyStatement'
|
|
236
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile } from 'fs/promises';
|
|
4
|
+
import { stdin } from 'process';
|
|
5
|
+
import { execute } from '../index.js';
|
|
6
|
+
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
|
|
9
|
+
// Parse flags
|
|
10
|
+
const verbose = args.includes('--verbose');
|
|
11
|
+
const quiet = args.includes('--quiet');
|
|
12
|
+
const help = args.includes('--help') || args.includes('-h');
|
|
13
|
+
|
|
14
|
+
// Filter out flags to get file path
|
|
15
|
+
const filePath = args.find(arg => !arg.startsWith('--') && arg !== '-h');
|
|
16
|
+
|
|
17
|
+
if (help) {
|
|
18
|
+
console.log(`
|
|
19
|
+
Wang Language Runtime
|
|
20
|
+
|
|
21
|
+
Usage:
|
|
22
|
+
wang-run <file> Execute a Wang file
|
|
23
|
+
wang-run - Read from stdin
|
|
24
|
+
wang-run --help Show this help message
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--verbose Show detailed execution information
|
|
28
|
+
--quiet Suppress extra output
|
|
29
|
+
-h, --help Show this help message
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
wang-run script.wang
|
|
33
|
+
echo "console.log('test')" | wang-run -
|
|
34
|
+
`.trim());
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function readStdin() {
|
|
39
|
+
const chunks = [];
|
|
40
|
+
for await (const chunk of stdin) {
|
|
41
|
+
chunks.push(chunk);
|
|
42
|
+
}
|
|
43
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function run() {
|
|
47
|
+
try {
|
|
48
|
+
let code;
|
|
49
|
+
|
|
50
|
+
if (filePath === '-') {
|
|
51
|
+
// Read from stdin
|
|
52
|
+
code = await readStdin();
|
|
53
|
+
} else if (filePath) {
|
|
54
|
+
// Read from file
|
|
55
|
+
code = await readFile(filePath, 'utf8');
|
|
56
|
+
} else {
|
|
57
|
+
console.error('Error: No input file specified');
|
|
58
|
+
console.error('Use --help for usage information');
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (verbose) {
|
|
63
|
+
console.log('🚀 Executing Wang code...');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Execute the code
|
|
67
|
+
await execute(code);
|
|
68
|
+
|
|
69
|
+
if (verbose) {
|
|
70
|
+
console.log('✅ Execution completed successfully');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
process.exit(0);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
// For file not found errors, show generic error message
|
|
76
|
+
if (error.code === 'ENOENT') {
|
|
77
|
+
console.error('Error:', error.message);
|
|
78
|
+
} else {
|
|
79
|
+
console.error('❌ Execution failed:');
|
|
80
|
+
console.error(error.message);
|
|
81
|
+
if (verbose) {
|
|
82
|
+
console.error(error.stack);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
run();
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile } from 'fs/promises';
|
|
4
|
+
import { stdin } from 'process';
|
|
5
|
+
import { parse } from 'acorn';
|
|
6
|
+
import { isTopLevelAwait } from '../index.js';
|
|
7
|
+
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
|
|
10
|
+
// Parse flags
|
|
11
|
+
const showAst = args.includes('--ast');
|
|
12
|
+
const help = args.includes('--help') || args.includes('-h');
|
|
13
|
+
|
|
14
|
+
// Filter out flags to get file path
|
|
15
|
+
const filePath = args.find(arg => !arg.startsWith('--') && arg !== '-h');
|
|
16
|
+
|
|
17
|
+
if (help) {
|
|
18
|
+
console.log(`
|
|
19
|
+
Wang Language Validator
|
|
20
|
+
|
|
21
|
+
Usage:
|
|
22
|
+
wang-validate <file> Validate a Wang file
|
|
23
|
+
wang-validate - Read from stdin
|
|
24
|
+
wang-validate --help Show this help message
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--ast Show the Abstract Syntax Tree
|
|
28
|
+
-h, --help Show this help message
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
wang-validate script.wang
|
|
32
|
+
echo "let x = 1" | wang-validate -
|
|
33
|
+
wang-validate script.wang --ast
|
|
34
|
+
`.trim());
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function readStdin() {
|
|
39
|
+
const chunks = [];
|
|
40
|
+
for await (const chunk of stdin) {
|
|
41
|
+
chunks.push(chunk);
|
|
42
|
+
}
|
|
43
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function validate() {
|
|
47
|
+
try {
|
|
48
|
+
let code;
|
|
49
|
+
|
|
50
|
+
if (filePath === '-') {
|
|
51
|
+
// Read from stdin
|
|
52
|
+
code = await readStdin();
|
|
53
|
+
} else if (filePath) {
|
|
54
|
+
// Read from file
|
|
55
|
+
code = await readFile(filePath, 'utf8');
|
|
56
|
+
} else {
|
|
57
|
+
console.error('Error: No input file specified');
|
|
58
|
+
console.error('Use --help for usage information');
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Check for top-level await
|
|
63
|
+
const hasAwait = isTopLevelAwait(code);
|
|
64
|
+
|
|
65
|
+
// Parse the code to validate syntax
|
|
66
|
+
const ast = parse(code, {
|
|
67
|
+
ecmaVersion: 'latest',
|
|
68
|
+
sourceType: hasAwait ? 'module' : 'script',
|
|
69
|
+
locations: true
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
console.log('✅ Valid Wang syntax');
|
|
73
|
+
|
|
74
|
+
if (showAst) {
|
|
75
|
+
console.log('\nAST:');
|
|
76
|
+
console.log(JSON.stringify(ast, null, 2));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
process.exit(0);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error('❌ Invalid Wang syntax:');
|
|
82
|
+
console.error(error.message);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
validate();
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// Wang Language Definition for Monaco Editor
|
|
2
|
+
export const wangLanguage = {
|
|
3
|
+
defaultToken: 'invalid',
|
|
4
|
+
tokenPostfix: '.wang',
|
|
5
|
+
|
|
6
|
+
keywords: [
|
|
7
|
+
'let',
|
|
8
|
+
'const',
|
|
9
|
+
'var',
|
|
10
|
+
'if',
|
|
11
|
+
'else',
|
|
12
|
+
'for',
|
|
13
|
+
'while',
|
|
14
|
+
'do',
|
|
15
|
+
'break',
|
|
16
|
+
'continue',
|
|
17
|
+
'return',
|
|
18
|
+
'function',
|
|
19
|
+
'class',
|
|
20
|
+
'extends',
|
|
21
|
+
'constructor',
|
|
22
|
+
'async',
|
|
23
|
+
'await',
|
|
24
|
+
'import',
|
|
25
|
+
'export',
|
|
26
|
+
'from',
|
|
27
|
+
'as',
|
|
28
|
+
'try',
|
|
29
|
+
'catch',
|
|
30
|
+
'finally',
|
|
31
|
+
'throw',
|
|
32
|
+
'this',
|
|
33
|
+
'super',
|
|
34
|
+
'new',
|
|
35
|
+
'typeof',
|
|
36
|
+
'instanceof',
|
|
37
|
+
'in',
|
|
38
|
+
'of',
|
|
39
|
+
],
|
|
40
|
+
|
|
41
|
+
typeKeywords: [],
|
|
42
|
+
|
|
43
|
+
operators: [
|
|
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
|
+
symbols: /[=><!~?:&|+\-*\/\^%]+/,
|
|
84
|
+
|
|
85
|
+
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
|
|
86
|
+
|
|
87
|
+
tokenizer: {
|
|
88
|
+
root: [
|
|
89
|
+
// Identifiers and keywords
|
|
90
|
+
[
|
|
91
|
+
/[a-zA-Z_$][\w$]*/,
|
|
92
|
+
{
|
|
93
|
+
cases: {
|
|
94
|
+
'@keywords': 'keyword',
|
|
95
|
+
'true|false|null|undefined': 'constant',
|
|
96
|
+
'@default': 'identifier',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
|
|
101
|
+
// Whitespace
|
|
102
|
+
{ include: '@whitespace' },
|
|
103
|
+
|
|
104
|
+
// Delimiters and operators
|
|
105
|
+
[/[{}()\[\]]/, '@brackets'],
|
|
106
|
+
[/[<>](?!@symbols)/, '@brackets'],
|
|
107
|
+
[
|
|
108
|
+
/@symbols/,
|
|
109
|
+
{
|
|
110
|
+
cases: {
|
|
111
|
+
'@operators': 'operator',
|
|
112
|
+
'@default': '',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
|
|
117
|
+
// Numbers
|
|
118
|
+
[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
|
|
119
|
+
[/0[xX][0-9a-fA-F]+/, 'number.hex'],
|
|
120
|
+
[/\d+/, 'number'],
|
|
121
|
+
|
|
122
|
+
// Delimiter
|
|
123
|
+
[/[;,.]/, 'delimiter'],
|
|
124
|
+
|
|
125
|
+
// Strings
|
|
126
|
+
[/"([^"\\]|\\.)*$/, 'string.invalid'],
|
|
127
|
+
[/'([^'\\]|\\.)*$/, 'string.invalid'],
|
|
128
|
+
[/"/, 'string', '@string_double'],
|
|
129
|
+
[/'/, 'string', '@string_single'],
|
|
130
|
+
|
|
131
|
+
// Template literals
|
|
132
|
+
[/`/, 'string.template', '@template'],
|
|
133
|
+
|
|
134
|
+
// Regular expressions
|
|
135
|
+
[/\/(?=([^\/\\]|\\.)+\/)/, 'regexp', '@regexp'],
|
|
136
|
+
],
|
|
137
|
+
|
|
138
|
+
whitespace: [
|
|
139
|
+
[/[ \t\r\n]+/, ''],
|
|
140
|
+
[/\/\*/, 'comment', '@comment'],
|
|
141
|
+
[/\/\/.*$/, 'comment'],
|
|
142
|
+
],
|
|
143
|
+
|
|
144
|
+
comment: [
|
|
145
|
+
[/[^\/*]+/, 'comment'],
|
|
146
|
+
[/\*\//, 'comment', '@pop'],
|
|
147
|
+
[/[\/*]/, 'comment'],
|
|
148
|
+
],
|
|
149
|
+
|
|
150
|
+
string_double: [
|
|
151
|
+
[/[^\\"]+/, 'string'],
|
|
152
|
+
[/@escapes/, 'string.escape'],
|
|
153
|
+
[/\\./, 'string.escape.invalid'],
|
|
154
|
+
[/"/, 'string', '@pop'],
|
|
155
|
+
],
|
|
156
|
+
|
|
157
|
+
string_single: [
|
|
158
|
+
[/[^\\']+/, 'string'],
|
|
159
|
+
[/@escapes/, 'string.escape'],
|
|
160
|
+
[/\\./, 'string.escape.invalid'],
|
|
161
|
+
[/'/, 'string', '@pop'],
|
|
162
|
+
],
|
|
163
|
+
|
|
164
|
+
template: [
|
|
165
|
+
[/[^`\\$]+/, 'string.template'],
|
|
166
|
+
[/@escapes/, 'string.escape'],
|
|
167
|
+
[/\\./, 'string.escape.invalid'],
|
|
168
|
+
[/\${/, { token: 'delimiter.bracket', next: '@templateExpression' }],
|
|
169
|
+
[/`/, 'string.template', '@pop'],
|
|
170
|
+
],
|
|
171
|
+
|
|
172
|
+
templateExpression: [[/}/, { token: 'delimiter.bracket', next: '@pop' }], { include: 'root' }],
|
|
173
|
+
|
|
174
|
+
regexp: [
|
|
175
|
+
[
|
|
176
|
+
/(\{)(\d+(?:,\d*)?)(\})/,
|
|
177
|
+
['regexp.escape.control', 'regexp.escape.control', 'regexp.escape.control'],
|
|
178
|
+
],
|
|
179
|
+
[/(\[)([^\]\\]|\\.)*(\])/, 'regexp.escape.control'],
|
|
180
|
+
[/(\()(\?:|\?=|\?!)/, ['regexp.escape.control', 'regexp.escape.control']],
|
|
181
|
+
[/[()]/, 'regexp.escape.control'],
|
|
182
|
+
[/@escapes/, 'regexp.escape'],
|
|
183
|
+
[/\\./, 'regexp.escape'],
|
|
184
|
+
[/\/[gimsuy]*/, { token: 'regexp', bracket: '@close', next: '@pop' }],
|
|
185
|
+
[/./, 'regexp'],
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Register the language with Monaco
|
|
191
|
+
export function registerWangLanguage(monaco) {
|
|
192
|
+
monaco.languages.register({ id: 'wang' });
|
|
193
|
+
monaco.languages.setMonarchTokensProvider('wang', wangLanguage);
|
|
194
|
+
|
|
195
|
+
// Configuration for brackets and auto-closing
|
|
196
|
+
monaco.languages.setLanguageConfiguration('wang', {
|
|
197
|
+
comments: {
|
|
198
|
+
lineComment: '//',
|
|
199
|
+
blockComment: ['/*', '*/'],
|
|
200
|
+
},
|
|
201
|
+
brackets: [
|
|
202
|
+
['{', '}'],
|
|
203
|
+
['[', ']'],
|
|
204
|
+
['(', ')'],
|
|
205
|
+
],
|
|
206
|
+
autoClosingPairs: [
|
|
207
|
+
{ open: '{', close: '}' },
|
|
208
|
+
{ open: '[', close: ']' },
|
|
209
|
+
{ open: '(', close: ')' },
|
|
210
|
+
{ open: '"', close: '"', notIn: ['string'] },
|
|
211
|
+
{ open: "'", close: "'", notIn: ['string'] },
|
|
212
|
+
{ open: '`', close: '`', notIn: ['string'] },
|
|
213
|
+
{ open: '/*', close: '*/' },
|
|
214
|
+
],
|
|
215
|
+
surroundingPairs: [
|
|
216
|
+
{ open: '{', close: '}' },
|
|
217
|
+
{ open: '[', close: ']' },
|
|
218
|
+
{ open: '(', close: ')' },
|
|
219
|
+
{ open: '"', close: '"' },
|
|
220
|
+
{ open: "'", close: "'" },
|
|
221
|
+
{ open: '`', close: '`' },
|
|
222
|
+
],
|
|
223
|
+
folding: {
|
|
224
|
+
markers: {
|
|
225
|
+
start: new RegExp('^\\s*//\\s*#?region\\b'),
|
|
226
|
+
end: new RegExp('^\\s*//\\s*#?endregion\\b'),
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
indentationRules: {
|
|
230
|
+
increaseIndentPattern: new RegExp('^.*(\\{[^}]*|\\([^)]*|\\[[^\\]]*)$'),
|
|
231
|
+
decreaseIndentPattern: new RegExp('^\\s*(\\}|\\)|\\])'),
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
}
|