functionalscript 0.6.9 → 0.6.10
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 +2 -2
- package/bnf/data/module.f.d.ts +2 -0
- package/bnf/data/test.f.d.ts +1 -0
- package/bnf/data/test.f.js +11 -0
- package/bnf/module.f.d.ts +8 -0
- package/bnf/module.f.js +1 -1
- package/bnf/testlib.f.js +1 -0
- package/dev/module.f.d.ts +1 -1
- package/dev/module.f.js +7 -4
- package/djs/module.f.js +2 -1
- package/djs/parser/module.f.d.ts +7 -2
- package/djs/parser/module.f.js +80 -52
- package/djs/parser/test.f.d.ts +1 -0
- package/djs/parser/test.f.js +104 -76
- package/djs/tokenizer/module.f.d.ts +6 -2
- package/djs/tokenizer/module.f.js +12 -7
- package/djs/tokenizer/test.f.d.ts +1 -0
- package/djs/tokenizer/test.f.js +103 -87
- package/djs/transpiler/module.f.d.ts +3 -2
- package/djs/transpiler/module.f.js +3 -3
- package/djs/transpiler/test.f.js +2 -2
- package/io/module.js +5 -1
- package/issues/31-json.f.d.ts +1 -1
- package/issues/31-json.f.js +1 -1
- package/issues/demo/data/data.f.js +12 -0
- package/issues/demo/data/shared.f.js +3 -0
- package/issues/demo/fs/app.js +4 -0
- package/issues/demo/fs/math.f.js +4 -0
- package/issues/demo/test/test.f.js +13 -0
- package/js/tokenizer/module.f.d.ts +14 -2
- package/js/tokenizer/module.f.js +30 -17
- package/js/tokenizer/test.f.d.ts +1 -0
- package/js/tokenizer/test.f.js +159 -149
- package/json/parser/module.f.js +18 -9
- package/json/parser/test.f.js +16 -16
- package/json/tokenizer/module.f.d.ts +1 -1
- package/json/tokenizer/module.f.js +7 -6
- package/json/tokenizer/test.f.js +68 -68
- package/package.json +9 -11
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ FunctionalScript is a safe, purely functional programming language and a strict
|
|
|
8
8
|
|
|
9
9
|
- [JSON](https://en.wikipedia.org/wiki/JSON) and [JSON5](https://json5.org/) as subsets of JavaScript.
|
|
10
10
|
JSON is also a subset of FunctionalScript.
|
|
11
|
-
- [asm.JS](https://en.wikipedia.org/wiki/Asm.js)
|
|
11
|
+
- [asm.JS](https://en.wikipedia.org/wiki/Asm.js) (a precursor of [WebAssembly](https://en.wikipedia.org/wiki/WebAssembly)),
|
|
12
12
|
as a subset of JavaScript.
|
|
13
13
|
- [TypeScript](https://en.wikipedia.org/wiki/TypeScript), as a superset of JavaScript.
|
|
14
14
|
|
|
@@ -19,7 +19,7 @@ Learn more about
|
|
|
19
19
|
- [Purely Functional Programming in JavaScript](https://blog.bitsrc.io/purely-functional-programming-in-javascript-91114b1b2dff?sk=5f7132e56902f38fcf4c6164bfa681ed),
|
|
20
20
|
- [FunctionalScript and I/O](https://medium.com/@sergeyshandar/functionalscript-5cf817345376?sk=30b32189a81d1a2dad16c2244f32328d).
|
|
21
21
|
|
|
22
|
-
This repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and
|
|
22
|
+
This repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and distributed under [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.en.html#license-text). Let us know if you need another license by sending an [email](mailto:sergey.oss@proton.me).
|
|
23
23
|
|
|
24
24
|
## Getting Started
|
|
25
25
|
|
package/bnf/data/module.f.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { Rule as FRule } from '../module.f.ts';
|
|
2
2
|
export type TerminalRange = number;
|
|
3
3
|
export type Sequence = readonly string[];
|
|
4
|
+
/** A variant of rule names. */
|
|
4
5
|
export type Variant = {
|
|
5
6
|
readonly [k in string]: string;
|
|
6
7
|
};
|
|
7
8
|
export type Rule = Variant | Sequence | TerminalRange;
|
|
9
|
+
/** The full grammar */
|
|
8
10
|
export type RuleSet = Readonly<Record<string, Rule>>;
|
|
9
11
|
export declare const toData: (fr: FRule) => readonly [RuleSet, string];
|
|
10
12
|
/**
|
package/bnf/data/test.f.d.ts
CHANGED
package/bnf/data/test.f.js
CHANGED
|
@@ -4,5 +4,16 @@ export default {
|
|
|
4
4
|
toData: () => {
|
|
5
5
|
const c = toData(classic());
|
|
6
6
|
const d = toData(deterministic());
|
|
7
|
+
},
|
|
8
|
+
example: () => {
|
|
9
|
+
const grammar = {
|
|
10
|
+
space: 0x000020_000020,
|
|
11
|
+
digit: 0x000030_000039,
|
|
12
|
+
sequence: ['space', 'digit'],
|
|
13
|
+
spaceOrDigit: {
|
|
14
|
+
'whiteSpace': 'space',
|
|
15
|
+
'digit': 'digit',
|
|
16
|
+
}
|
|
17
|
+
};
|
|
7
18
|
}
|
|
8
19
|
};
|
package/bnf/module.f.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { type Array2 } from '../types/array/module.f.ts';
|
|
2
|
+
/**
|
|
3
|
+
* A range of symbols (48 bits)
|
|
4
|
+
* For example: 0xBBBBBB_EEEEEE
|
|
5
|
+
* - 0xBBBBBB is the first symbol
|
|
6
|
+
* - 0xEEEEEE is the last symbol
|
|
7
|
+
*/
|
|
2
8
|
export type TerminalRange = number;
|
|
9
|
+
/** A sequence of rules. */
|
|
3
10
|
export type Sequence = readonly Rule[];
|
|
11
|
+
/** A variant */
|
|
4
12
|
export type Variant = {
|
|
5
13
|
readonly [k in string]: Rule;
|
|
6
14
|
};
|
package/bnf/module.f.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { codePointListToString, stringToCodePointList } from "../text/utf16/module.f.js";
|
|
2
2
|
import { isArray2 } from "../types/array/module.f.js";
|
|
3
3
|
import { map, toArray, repeat as listRepeat } from "../types/list/module.f.js";
|
|
4
|
-
//
|
|
4
|
+
// Internals:
|
|
5
5
|
const { fromEntries, values } = Object;
|
|
6
6
|
const { fromCodePoint } = String;
|
|
7
7
|
/**
|
package/bnf/testlib.f.js
CHANGED
package/dev/module.f.d.ts
CHANGED
|
@@ -7,6 +7,6 @@ export type ModuleMap = {
|
|
|
7
7
|
readonly [k in string]: Module;
|
|
8
8
|
};
|
|
9
9
|
export declare const env: (io: Io) => (v: string) => string | undefined;
|
|
10
|
-
export declare const allFiles: (
|
|
10
|
+
export declare const allFiles: (io: Io) => (s: string) => Promise<readonly string[]>;
|
|
11
11
|
export declare const loadModuleMap: (io: Io) => Promise<ModuleMap>;
|
|
12
12
|
export declare const index: (io: Io) => Promise<number>;
|
package/dev/module.f.js
CHANGED
|
@@ -7,7 +7,8 @@ export const env = ({ process: { env } }) => a => {
|
|
|
7
7
|
typeof r.get === 'function' ? r.get() :
|
|
8
8
|
r.value;
|
|
9
9
|
};
|
|
10
|
-
export const allFiles = (
|
|
10
|
+
export const allFiles = (io) => (s) => {
|
|
11
|
+
const { fs: { promises: { readdir } }, process: { cwd } } = io;
|
|
11
12
|
const load = async (p) => {
|
|
12
13
|
let result = [];
|
|
13
14
|
for (const i of await readdir(p, { withFileTypes: true })) {
|
|
@@ -29,12 +30,14 @@ export const allFiles = ({ fs: { promises: { readdir } } }) => {
|
|
|
29
30
|
}
|
|
30
31
|
return result;
|
|
31
32
|
};
|
|
32
|
-
return load(
|
|
33
|
+
return load(s);
|
|
33
34
|
};
|
|
34
35
|
export const loadModuleMap = async (io) => {
|
|
35
36
|
const { fs: { existsSync }, asyncImport } = io;
|
|
36
37
|
let map = [];
|
|
37
|
-
|
|
38
|
+
const initCwd = env(io)('INIT_CWD');
|
|
39
|
+
const s = initCwd === undefined ? '.' : `${initCwd.replaceAll('\\', '/')}`;
|
|
40
|
+
for (const f of await allFiles(io)(s)) {
|
|
38
41
|
if (f.endsWith('.f.js') ||
|
|
39
42
|
(f.endsWith('.f.ts') && !existsSync(f.substring(0, f.length - 3) + '.js'))) {
|
|
40
43
|
const source = await asyncImport(f);
|
|
@@ -47,7 +50,7 @@ export const index = async (io) => {
|
|
|
47
50
|
updateVersion(io);
|
|
48
51
|
const jj = './deno.json';
|
|
49
52
|
const jsr_json = JSON.parse(await io.fs.promises.readFile(jj, 'utf8'));
|
|
50
|
-
const list = (await allFiles(io)).filter(v => v.endsWith('/module.f.ts') || v.endsWith('/module.ts'));
|
|
53
|
+
const list = (await allFiles(io)('.')).filter(v => v.endsWith('/module.f.ts') || v.endsWith('/module.ts'));
|
|
51
54
|
//console.log(list)
|
|
52
55
|
const exportsA = list.map(v => [v, `./${v.substring(2)}`]);
|
|
53
56
|
// console.log(exportsA)
|
package/djs/module.f.js
CHANGED
|
@@ -22,7 +22,8 @@ export const compile = ({ console: { error }, fs, process: { argv } }) => {
|
|
|
22
22
|
break;
|
|
23
23
|
}
|
|
24
24
|
case 'error': {
|
|
25
|
-
|
|
25
|
+
const metadata = result[1].metadata;
|
|
26
|
+
error(`${metadata?.path}:${metadata?.line}:${metadata?.column} - error: ${result[1].message}`);
|
|
26
27
|
break;
|
|
27
28
|
}
|
|
28
29
|
}
|
package/djs/parser/module.f.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import * as result from '../../types/result/module.f.ts';
|
|
2
2
|
import { type List } from '../../types/list/module.f.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { DjsTokenWithMetadata } from '../tokenizer/module.f.ts';
|
|
4
4
|
import { type OrderedMap } from '../../types/ordered_map/module.f.ts';
|
|
5
5
|
import type { Fs } from '../../io/module.f.ts';
|
|
6
6
|
import type { AstModule } from '../ast/module.f.ts';
|
|
7
|
+
import type { TokenMetadata } from '../../js/tokenizer/module.f.ts';
|
|
7
8
|
export type ParseContext = {
|
|
8
9
|
readonly fs: Fs;
|
|
9
10
|
readonly complete: OrderedMap<result.Result<AstModule, string>>;
|
|
10
11
|
readonly stack: List<string>;
|
|
11
12
|
};
|
|
12
|
-
export
|
|
13
|
+
export type ParseError = {
|
|
14
|
+
readonly message: string;
|
|
15
|
+
readonly metadata: TokenMetadata | null;
|
|
16
|
+
};
|
|
17
|
+
export declare const parseFromTokens: (tokenList: List<DjsTokenWithMetadata>) => result.Result<AstModule, ParseError>;
|
package/djs/parser/module.f.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as result from "../../types/result/module.f.js";
|
|
|
2
2
|
import { fold, first, drop, toArray, length, concat } from "../../types/list/module.f.js";
|
|
3
3
|
import { setReplace, at } from "../../types/ordered_map/module.f.js";
|
|
4
4
|
import { fromMap } from "../../types/object/module.f.js";
|
|
5
|
-
const parseInitialOp = token => state => {
|
|
5
|
+
const parseInitialOp = ({ token, metadata }) => state => {
|
|
6
6
|
switch (token.kind) {
|
|
7
7
|
case 'ws':
|
|
8
8
|
case 'nl':
|
|
@@ -16,40 +16,43 @@ const parseInitialOp = token => state => {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
return foldOp(token)({ ...state, state: 'exportValue', valueState: '', top: null, stack: null });
|
|
19
|
+
return foldOp({ token, metadata })({ ...state, state: 'exportValue', valueState: '', top: null, stack: null });
|
|
20
20
|
};
|
|
21
|
-
const parseNewLineRequiredOp = token => state => {
|
|
21
|
+
const parseNewLineRequiredOp = ({ token, metadata }) => state => {
|
|
22
22
|
switch (token.kind) {
|
|
23
23
|
case 'ws':
|
|
24
24
|
case '//':
|
|
25
25
|
case '/*': return state;
|
|
26
26
|
case 'nl': return { ...state, state: '' };
|
|
27
|
-
|
|
27
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
28
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
28
29
|
}
|
|
29
30
|
};
|
|
30
|
-
const parseExportOp = token => state => {
|
|
31
|
+
const parseExportOp = ({ token, metadata }) => state => {
|
|
31
32
|
switch (token.kind) {
|
|
32
33
|
case 'ws':
|
|
33
34
|
case 'nl':
|
|
34
35
|
case '//':
|
|
35
36
|
case '/*': return state;
|
|
37
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
36
38
|
case 'id': {
|
|
37
39
|
if (token.value === 'default')
|
|
38
40
|
return { ...state, state: 'exportValue', valueState: '', top: null, stack: null };
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
return { state: 'error', message: 'unexpected token' };
|
|
43
|
+
return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
42
44
|
};
|
|
43
|
-
const parseResultOp = token => state => {
|
|
45
|
+
const parseResultOp = ({ token, metadata }) => state => {
|
|
44
46
|
switch (token.kind) {
|
|
45
47
|
case 'ws':
|
|
46
48
|
case 'nl':
|
|
47
49
|
case '//':
|
|
48
|
-
case '/*':
|
|
49
|
-
|
|
50
|
+
case '/*':
|
|
51
|
+
case 'eof': return state;
|
|
52
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
50
53
|
}
|
|
51
54
|
};
|
|
52
|
-
const parseConstOp = token => state => {
|
|
55
|
+
const parseConstOp = ({ token, metadata }) => state => {
|
|
53
56
|
switch (token.kind) {
|
|
54
57
|
case 'ws':
|
|
55
58
|
case 'nl':
|
|
@@ -57,25 +60,27 @@ const parseConstOp = token => state => {
|
|
|
57
60
|
case '/*': return state;
|
|
58
61
|
case 'id': {
|
|
59
62
|
if (at(token.value)(state.module.refs) !== null)
|
|
60
|
-
return { state: 'error', message: 'duplicate id' };
|
|
63
|
+
return { state: 'error', error: { message: 'duplicate id', metadata } };
|
|
61
64
|
const cref = ['cref', length(state.module.consts)];
|
|
62
65
|
const refs = setReplace(token.value)(cref)(state.module.refs);
|
|
63
66
|
return { ...state, state: 'const+name', module: { ...state.module, refs: refs } };
|
|
64
67
|
}
|
|
65
|
-
|
|
68
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
69
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
66
70
|
}
|
|
67
71
|
};
|
|
68
|
-
const parseConstNameOp = token => state => {
|
|
72
|
+
const parseConstNameOp = ({ token, metadata }) => state => {
|
|
69
73
|
switch (token.kind) {
|
|
70
74
|
case 'ws':
|
|
71
75
|
case 'nl':
|
|
72
76
|
case '//':
|
|
73
77
|
case '/*': return state;
|
|
74
78
|
case '=': return { ...state, state: 'constValue', valueState: '', top: null, stack: null };
|
|
75
|
-
|
|
79
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
80
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
76
81
|
}
|
|
77
82
|
};
|
|
78
|
-
const parseImportOp = token => state => {
|
|
83
|
+
const parseImportOp = ({ token, metadata }) => state => {
|
|
79
84
|
switch (token.kind) {
|
|
80
85
|
case 'ws':
|
|
81
86
|
case 'nl':
|
|
@@ -83,29 +88,31 @@ const parseImportOp = token => state => {
|
|
|
83
88
|
case '/*': return state;
|
|
84
89
|
case 'id': {
|
|
85
90
|
if (at(token.value)(state.module.refs) !== null) {
|
|
86
|
-
return { state: 'error', message: 'duplicate id' };
|
|
91
|
+
return { state: 'error', error: { message: 'duplicate id', metadata } };
|
|
87
92
|
}
|
|
88
93
|
const aref = ['aref', length(state.module.modules)];
|
|
89
94
|
const refs = setReplace(token.value)(aref)(state.module.refs);
|
|
90
95
|
return { ...state, state: 'import+name', module: { ...state.module, refs: refs } };
|
|
91
96
|
}
|
|
92
|
-
|
|
97
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
98
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
93
99
|
}
|
|
94
100
|
};
|
|
95
|
-
const parseImportNameOp = token => state => {
|
|
101
|
+
const parseImportNameOp = ({ token, metadata }) => state => {
|
|
96
102
|
switch (token.kind) {
|
|
97
103
|
case 'ws':
|
|
98
104
|
case 'nl':
|
|
99
105
|
case '//':
|
|
100
106
|
case '/*': return state;
|
|
107
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
101
108
|
case 'id': {
|
|
102
109
|
if (token.value === 'from')
|
|
103
110
|
return { ...state, state: 'import+from' };
|
|
104
111
|
}
|
|
105
112
|
}
|
|
106
|
-
return { state: 'error', message: 'unexpected token' };
|
|
113
|
+
return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
107
114
|
};
|
|
108
|
-
const parseImportFromOp = token => state => {
|
|
115
|
+
const parseImportFromOp = ({ token, metadata }) => state => {
|
|
109
116
|
switch (token.kind) {
|
|
110
117
|
case 'ws':
|
|
111
118
|
case 'nl':
|
|
@@ -115,17 +122,18 @@ const parseImportFromOp = token => state => {
|
|
|
115
122
|
const modules = concat(state.module.modules)([token.value]);
|
|
116
123
|
return { ...state, state: 'nl', module: { ...state.module, modules: modules } };
|
|
117
124
|
}
|
|
118
|
-
|
|
125
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
126
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
119
127
|
}
|
|
120
128
|
};
|
|
121
129
|
const addKeyToObject = obj => key => (['object', obj[1], key]);
|
|
122
130
|
const addValueToObject = obj => value => (['object', setReplace(obj[2])(value)(obj[1]), '']);
|
|
123
131
|
const addToArray = array => value => (['array', concat(array[1])([value])]);
|
|
124
|
-
const pushKey = state => key => {
|
|
132
|
+
const pushKey = state => key => metadata => {
|
|
125
133
|
if (state.top?.[0] === 'object') {
|
|
126
134
|
return { ...state, valueState: '{k', top: addKeyToObject(state.top)(key), stack: state.stack };
|
|
127
135
|
}
|
|
128
|
-
return { state: 'error', message: 'error' };
|
|
136
|
+
return { state: 'error', error: { message: 'error', metadata } };
|
|
129
137
|
};
|
|
130
138
|
const pushValue = state => value => {
|
|
131
139
|
if (state.top === null) {
|
|
@@ -140,10 +148,10 @@ const pushValue = state => value => {
|
|
|
140
148
|
}
|
|
141
149
|
return { ...state, valueState: '{v', top: addValueToObject(state.top)(value), stack: state.stack };
|
|
142
150
|
};
|
|
143
|
-
const pushRef = state => name => {
|
|
151
|
+
const pushRef = state => name => metadata => {
|
|
144
152
|
const ref = at(name)(state.module.refs);
|
|
145
153
|
if (ref === null)
|
|
146
|
-
return { state: 'error', message: 'const not found' };
|
|
154
|
+
return { state: 'error', error: { message: 'const not found', metadata } };
|
|
147
155
|
return pushValue(state)(ref);
|
|
148
156
|
};
|
|
149
157
|
const startArray = state => {
|
|
@@ -192,27 +200,34 @@ const isValueToken = token => {
|
|
|
192
200
|
default: return false;
|
|
193
201
|
}
|
|
194
202
|
};
|
|
195
|
-
const parseValueOp = token => state => {
|
|
196
|
-
if (isValueToken(token)) {
|
|
197
|
-
return pushValue(state)(tokenToValue(token));
|
|
198
|
-
}
|
|
203
|
+
const parseValueOp = ({ token, metadata }) => state => {
|
|
199
204
|
switch (token.kind) {
|
|
200
|
-
case '
|
|
205
|
+
case ']':
|
|
206
|
+
if (state.valueState === '[,') {
|
|
207
|
+
return endArray(state);
|
|
208
|
+
}
|
|
209
|
+
return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
210
|
+
case 'id': return pushRef(state)(token.value)(metadata);
|
|
201
211
|
case '[': return startArray(state);
|
|
202
212
|
case '{': return startObject(state);
|
|
203
213
|
case 'ws':
|
|
204
214
|
case 'nl':
|
|
205
215
|
case '//':
|
|
206
216
|
case '/*': return state;
|
|
207
|
-
|
|
217
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
218
|
+
default:
|
|
219
|
+
if (isValueToken(token)) {
|
|
220
|
+
return pushValue(state)(tokenToValue(token));
|
|
221
|
+
}
|
|
222
|
+
return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
208
223
|
}
|
|
209
224
|
};
|
|
210
|
-
const parseArrayStartOp = token => state => {
|
|
225
|
+
const parseArrayStartOp = ({ token, metadata }) => state => {
|
|
211
226
|
if (isValueToken(token)) {
|
|
212
227
|
return pushValue(state)(tokenToValue(token));
|
|
213
228
|
}
|
|
214
229
|
switch (token.kind) {
|
|
215
|
-
case 'id': return pushRef(state)(token.value);
|
|
230
|
+
case 'id': return pushRef(state)(token.value)(metadata);
|
|
216
231
|
case '[': return startArray(state);
|
|
217
232
|
case ']': return endArray(state);
|
|
218
233
|
case '{': return startObject(state);
|
|
@@ -220,10 +235,11 @@ const parseArrayStartOp = token => state => {
|
|
|
220
235
|
case 'nl':
|
|
221
236
|
case '//':
|
|
222
237
|
case '/*': return state;
|
|
223
|
-
|
|
238
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
239
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
224
240
|
}
|
|
225
241
|
};
|
|
226
|
-
const parseArrayValueOp = token => state => {
|
|
242
|
+
const parseArrayValueOp = ({ token, metadata }) => state => {
|
|
227
243
|
switch (token.kind) {
|
|
228
244
|
case ']': return endArray(state);
|
|
229
245
|
case ',': return { ...state, valueState: '[,', top: state.top, stack: state.stack };
|
|
@@ -231,46 +247,53 @@ const parseArrayValueOp = token => state => {
|
|
|
231
247
|
case 'nl':
|
|
232
248
|
case '//':
|
|
233
249
|
case '/*': return state;
|
|
234
|
-
|
|
250
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
251
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
235
252
|
}
|
|
236
253
|
};
|
|
237
|
-
|
|
254
|
+
// allow identifier property names (#2410)
|
|
255
|
+
const parseObjectStartOp = ({ token, metadata }) => state => {
|
|
238
256
|
switch (token.kind) {
|
|
239
|
-
case 'string':
|
|
257
|
+
case 'string':
|
|
258
|
+
case 'id':
|
|
259
|
+
return pushKey(state)(String(token.value))(metadata);
|
|
240
260
|
case '}': return endObject(state);
|
|
241
261
|
case 'ws':
|
|
242
262
|
case 'nl':
|
|
243
263
|
case '//':
|
|
244
264
|
case '/*': return state;
|
|
245
|
-
|
|
265
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
266
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
246
267
|
}
|
|
247
268
|
};
|
|
248
|
-
const parseObjectKeyOp = token => state => {
|
|
269
|
+
const parseObjectKeyOp = ({ token, metadata }) => state => {
|
|
249
270
|
switch (token.kind) {
|
|
250
271
|
case ':': return { ...state, valueState: '{:', top: state.top, stack: state.stack };
|
|
251
272
|
case 'ws':
|
|
252
273
|
case 'nl':
|
|
253
274
|
case '//':
|
|
254
275
|
case '/*': return state;
|
|
255
|
-
|
|
276
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
277
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
256
278
|
}
|
|
257
279
|
};
|
|
258
|
-
const parseObjectColonOp = token => state => {
|
|
280
|
+
const parseObjectColonOp = ({ token, metadata }) => state => {
|
|
259
281
|
if (isValueToken(token)) {
|
|
260
282
|
return pushValue(state)(tokenToValue(token));
|
|
261
283
|
}
|
|
262
284
|
switch (token.kind) {
|
|
263
|
-
case 'id': return pushRef(state)(token.value);
|
|
285
|
+
case 'id': return pushRef(state)(token.value)(metadata);
|
|
264
286
|
case '[': return startArray(state);
|
|
265
287
|
case '{': return startObject(state);
|
|
266
288
|
case 'ws':
|
|
267
289
|
case 'nl':
|
|
268
290
|
case '//':
|
|
269
291
|
case '/*': return state;
|
|
270
|
-
|
|
292
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
293
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
271
294
|
}
|
|
272
295
|
};
|
|
273
|
-
const parseObjectNextOp = token => state => {
|
|
296
|
+
const parseObjectNextOp = ({ token, metadata }) => state => {
|
|
274
297
|
switch (token.kind) {
|
|
275
298
|
case '}': return endObject(state);
|
|
276
299
|
case ',': return { ...state, valueState: '{,', top: state.top, stack: state.stack };
|
|
@@ -278,17 +301,22 @@ const parseObjectNextOp = token => state => {
|
|
|
278
301
|
case 'nl':
|
|
279
302
|
case '//':
|
|
280
303
|
case '/*': return state;
|
|
281
|
-
|
|
304
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
305
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
282
306
|
}
|
|
283
307
|
};
|
|
284
|
-
const parseObjectCommaOp = token => state => {
|
|
308
|
+
const parseObjectCommaOp = ({ token, metadata }) => state => {
|
|
285
309
|
switch (token.kind) {
|
|
286
|
-
case '
|
|
310
|
+
case '}': return endObject(state);
|
|
311
|
+
case 'string':
|
|
312
|
+
case 'id':
|
|
313
|
+
return pushKey(state)(String(token.value))(metadata);
|
|
287
314
|
case 'ws':
|
|
288
315
|
case 'nl':
|
|
289
316
|
case '//':
|
|
290
317
|
case '/*': return state;
|
|
291
|
-
|
|
318
|
+
case 'eof': return { state: 'error', error: { message: 'unexpected end', metadata } };
|
|
319
|
+
default: return { state: 'error', error: { message: 'unexpected token', metadata } };
|
|
292
320
|
}
|
|
293
321
|
};
|
|
294
322
|
const foldOp = token => state => {
|
|
@@ -302,7 +330,7 @@ const foldOp = token => state => {
|
|
|
302
330
|
case 'const+name': return parseConstNameOp(token)(state);
|
|
303
331
|
case 'export': return parseExportOp(token)(state);
|
|
304
332
|
case 'result': return parseResultOp(token)(state);
|
|
305
|
-
case 'error': return { state: 'error',
|
|
333
|
+
case 'error': return { state: 'error', error: state.error };
|
|
306
334
|
case 'constValue':
|
|
307
335
|
case 'exportValue':
|
|
308
336
|
{
|
|
@@ -324,7 +352,7 @@ export const parseFromTokens = (tokenList) => {
|
|
|
324
352
|
const state = fold(foldOp)({ state: '', module: { refs: null, modules: null, consts: null } })(tokenList);
|
|
325
353
|
switch (state.state) {
|
|
326
354
|
case 'result': return result.ok([toArray(state.module.modules), toArray(state.module.consts)]);
|
|
327
|
-
case 'error': return result.error(state.
|
|
328
|
-
default: return result.error('unexpected end');
|
|
355
|
+
case 'error': return result.error(state.error);
|
|
356
|
+
default: return result.error({ message: 'unexpected end', metadata: null });
|
|
329
357
|
}
|
|
330
358
|
};
|