-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.mjs
117 lines (90 loc) · 2.55 KB
/
parser.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { lang, empty, succeed } from 'parser-lang';
function Ident(name) {
return { type: 'ident', name };
}
const isIdent = (o, value) => o != null && o.type === 'ident' && (value == null || o.name === value);
function Punc(punc) {
return { type: 'punc', punc };
}
const isPunc = (o, value) => o != null && o.type === 'punc' && (value == null || o.punc === value);
let { tokens } = lang`
empty = @${empty()} ;
sp = /[\s]+/ ;
optSp = sp | @${succeed()} ;
ident = /[a-zA-Z][a-zA-Z0-9]*/ > ${Ident} ;
punc = /[\{\}\[\]:,|]/ > ${Punc} ;
ellipses = '...' > ${Punc} ;
token = ident | punc | ellipses ;
tokens = optSp token tokens > ${([, t, ts]) => ([t, ...ts])}
| optSp empty > ${() => []};
`;
function DataDecl(name, bindings) {
return {
type: 'DataDecl',
name, bindings,
};
}
function Binding(name, bindingType) {
return {
type: 'Binding',
name, bindingType,
};
}
function BaseType(name) {
return {
type: 'BaseType',
name,
};
}
function ArrayType(type) {
return {
type: 'ArrayType',
innerType: type,
};
}
function UnionType(alternatives) {
return {
type: 'UnionType',
alternatives,
};
}
function Mixin(name) {
return {
type: 'Mixin', name,
};
}
let { definitions } = lang`
empty = @${empty()} ;
comma = !${o => isPunc(o, ',')} ;
optComma = comma | @${succeed()} ;
colon = !${o => isPunc(o, ':')} ;
pipe = !${o => isPunc(o, '|')} ;
ellipses = !${o => isPunc(o, '...')} ;
ident = !${isIdent} ;
punc = !${isPunc} ;
dataKwd = !${o => isIdent(o, 'data')} ;
openCurly = !${o => isPunc(o, '{')} ;
closeCurly = !${o => isPunc(o, '}')} ;
openSquare = !${o => isPunc(o, '[')} ;
closeSquare = !${o => isPunc(o, ']')} ;
baseType = openSquare unionType closeSquare > ${([, type]) => ArrayType(type)}
| ident > ${({ name }) => BaseType(name)}
;
unionType = baseType (pipe baseType)+ > ${([t, ts]) => UnionType([t, ...ts.map(([, snd]) => snd)])}
| baseType
;
binding = ident colon unionType > ${([{ name }, , type]) => Binding(name, type)}
| ellipses ident > ${([, { name }]) => Mixin(name)}
;
declBody = binding (comma binding )* optComma > ${([head, tail]) => [head, ...tail.map(([, snd]) => snd)]} ;
dataDecl = dataKwd ident openCurly closeCurly > ${([, { name }]) => DataDecl(name, [])}
| dataKwd ident openCurly declBody closeCurly > ${([, { name }, , bindings]) => DataDecl(name, bindings)}
;
definitions = dataDecl* ;
`;
function lex(s) {
return tokens.tryParse(s);
}
export default function parse(s) {
return definitions.tryParse(lex(s));
}