-
Notifications
You must be signed in to change notification settings - Fork 0
/
grammar.js
174 lines (163 loc) · 5.33 KB
/
grammar.js
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
module.exports = grammar({
name: 'calyx',
extras: $ => [
/\s|\\\r?\n/,
$.comment
],
rules: {
source_file: $ => seq(
repeat($.import),
repeat(choice($.component, $.extern, $.primitive)),
optional($.metadata)
),
comment: $ => choice(
seq('//', /.*/, '\n'),
seq(/\/\*(.|\n)*\*\//)
),
import: $ => seq('import', $.string, ';'),
metadata_ci: $ => seq(/[mM][eE][tT][aA][dD][aA][tT][aA]/),
metadata: $ => seq($.metadata_ci, /#\{(.|\n)*\}#/),
// components
signature: $ => seq($.io_port_list, '->', $.io_port_list),
component: $ => seq(
optional($.comb_or_static),
'component',
$.ident, optional($.attributes),
$.signature, '{',
optional($.cells),
optional($.wires),
optional($.control),
'}'
),
comb_or_static: $ => choice(
'comb',
$.static_annotation,
seq('comb', $.static_annotation),
seq($.static_annotation, 'comb')
),
io_port: $ => seq(repeat($.at_attribute), $.ident, ':', choice($.number, $.ident)),
io_port_list: $ => seq('(', repeat(seq($.io_port, ',')), optional($.io_port), ')'),
// primitives
params: $ => seq('[', seq(repeat(seq($.ident, ',')), $.ident), ']'),
any_line: $ => /([^\}\n])*\n/,
primitive_blob: $ => seq(
'{',
repeat($.any_line),
'}'
),
primitive: $ => seq(
optional($.comb_or_static), 'primitive', $.ident, optional($.attributes),
optional($.params), $.signature,
optional($.primitive_blob),
';'
),
extern: $ => seq('extern', $.string, '{', repeat($.primitive), '}'),
// cells
cells: $ => seq('cells', '{', optional($.cells_inner), '}'),
cells_inner: $ => repeat1($.cell_assignment),
cell_assignment: $ => seq(
optional($.at_attribute), optional('ref'),
$.ident, '=', $.instantiation, optional(';')
),
instantiation: $ => seq($.ident, $.arg_list),
arg_list: $ => seq('(', repeat(seq($.number, optional(','))), ')'),
// wires
wires: $ => seq('wires', '{', optional($.wires_inner), '}'),
wires_inner: $ => repeat1(choice($.group, $.wire_assignment)),
group: $ => seq(
optional('comb'), 'group', $.ident, optional($.attributes),
'{',
repeat($.wire_assignment),
'}'
),
hole: $ => seq($.ident, '[', $.ident, ']'),
port: $ => choice(seq($.ident, '.', $.ident), $.ident),
lhs: $ => choice($.hole, $.port),
base_expr: $ => choice($.hole, $.port, $.literal),
expr: $ => choice(
$.base_expr,
$.cmp_expr,
seq('(', $.expr, ')'),
),
cmp_expr: $ => choice(
prec.left(6, seq($.expr, "==", $.expr)),
prec.left(5, seq($.expr, "!=", $.expr)),
prec.left(4, seq($.expr, "<=", $.expr)),
prec.left(3, seq($.expr, ">=", $.expr)),
prec.left(2, seq($.expr, ">", $.expr)),
prec.left(1, seq($.expr, "<", $.expr)),
),
term: $ => choice(
$.expr,
seq('!', $.expr),
prec.left(2, seq($.expr, '|', $.expr)),
prec.left(1, seq($.expr, '&', $.expr))
),
switch: $ => seq($.term, '?', $.base_expr),
wire_assignment: $ => seq(optional($.at_attribute), $.lhs, '=', choice($.switch, $.expr), ';'),
// control
control: $ => seq('control', '{', $.control_inner, '}'),
control_inner: $ => $.stmt,
enable: $ => seq(repeat($.at_attribute), optional($.ident), ';'),
invoke_ref_arg: $ => seq($.ident, '=', $.ident),
invoke_ref_args: $ => seq(
'[',
optional(seq(repeat(seq($.invoke_ref_arg, ',')), $.invoke_ref_arg)),
']'
),
invoke_arg: $ => seq($.ident, '=', choice($.port, $.literal)),
invoke_args: $ => seq(
'(',
optional(seq(repeat(seq($.invoke_arg, ',')), $.invoke_arg)),
')'
),
invoke: $ => seq(
repeat($.at_attribute), optional($.static_annotation), 'invoke',
$.ident,
optional($.invoke_ref_args),
$.invoke_args,
$.invoke_args,
optional(seq('with', $.ident)),
';'
),
seq: $ => seq(
repeat($.at_attribute), optional($.static_annotation),
'seq', '{',
repeat($.stmt),
'}'
),
par: $ => seq(
repeat($.at_attribute), optional($.static_annotation),
'par', '{',
repeat($.stmt),
'}'
),
port_with: $ => seq($.port, optional(seq('with', $.ident))),
block: $ => seq('{', $.stmt, '}'),
if_stmt: $ => seq(
repeat($.at_attribute), optional($.static_annotation),
'if', $.port_with, $.block,
optional(seq('else', choice($.block, $.if_stmt)))
),
while_stmt: $ => seq(repeat($.at_attribute), 'while', $.port_with, $.block),
repeat_stmt: $ => seq(repeat($.at_attribute), optional('static'), 'repeat', $.number, $.block),
stmt: $ => choice(
$.enable,
$.invoke,
$.seq,
$.par,
$.if_stmt,
$.while_stmt,
$.repeat_stmt
),
attribute: $ => seq($.string, "=", $.number),
attributes: $ => seq('<', seq(repeat(seq($.attribute, ',')), optional($.attribute)), '>'),
latency_annotation: $ => seq('<', $.number, '>'),
at_attribute: $ => seq('@', $.ident, optional(seq('(', $.number, ')'))),
static_annotation: $ => seq('static', optional($.latency_annotation)),
string: $ => /".*"/,
ident: $ => /[a-zA-Z_]+[a-zA-Z0-9_\-]*/,
number: $ => /[0-9]+/,
literal: $ => seq($.number, "'", choice('d', 'b', 'x', 'o'), $.number)
}
});