1use spade_ast::{AttributeList, Binding, Expression, Register, Statement};
2use spade_common::location_info::{lspan, AsLabel, Loc, WithLocation};
3use spade_diagnostics::Diagnostic;
4use spade_macros::trace_parser;
5
6use crate::{
7 error::Result, item_type::UnitKindLocal, lexer::TokenKind, peek_for, KeywordPeekingParser,
8 ParseStackEntry, Parser,
9};
10
11pub(crate) struct BindingParser {}
12
13impl KeywordPeekingParser<Loc<Statement>> for BindingParser {
14 fn leading_tokens(&self) -> Vec<TokenKind> {
15 vec![TokenKind::Let]
16 }
17
18 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<Loc<Statement>> {
19 let _ = parser.eat_unconditional()?;
20
21 let (pattern, start_span) = parser.pattern()?.separate();
22
23 let ty = if parser.peek_and_eat(&TokenKind::Colon)?.is_some() {
24 Some(parser.type_spec()?)
25 } else {
26 None
27 };
28
29 parser.eat(&TokenKind::Assignment)?;
30 let (value, end_span) = parser.expression()?.separate();
31
32 Ok(Statement::Binding(Binding {
33 pattern,
34 ty,
35 value,
36 attrs: attributes.clone(),
37 })
38 .between(parser.file_id, &start_span, &end_span))
39 }
40}
41
42pub(crate) struct RegisterParser {}
43
44impl KeywordPeekingParser<Loc<Statement>> for RegisterParser {
45 fn leading_tokens(&self) -> Vec<TokenKind> {
46 vec![TokenKind::Reg]
47 }
48
49 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<Loc<Statement>> {
50 let start_token = parser.eat_unconditional()?;
51
52 let cond = if parser.peek_kind(&TokenKind::OpenBracket)? {
55 Some(
56 parser
57 .surrounded(
58 &TokenKind::OpenBracket,
59 Parser::expression,
60 &TokenKind::CloseBracket,
61 )?
62 .0,
63 )
64 } else {
65 None
66 };
67
68 if parser.peek_kind(&TokenKind::Semi)? || parser.peek_kind(&TokenKind::Asterisk)? {
70 let count = if let Some(ast) = parser.peek_and_eat(&TokenKind::Asterisk)? {
71 match parser.type_expression() {
72 Ok(t) => Some(t),
73 Err(diag) => {
74 return Err(
75 diag.secondary_label(ast, "* is used to specify a register count")
76 )
77 }
78 }
79 } else {
80 None
81 };
82
83 let full_loc = if let Some(c) = &count {
84 ().between(parser.file_id, &start_token, &c.loc())
85 } else {
86 ().at(parser.file_id, &start_token)
87 };
88
89 return Ok(Statement::PipelineRegMarker(count, cond).at_loc(&full_loc));
90 }
91
92 parser
93 .unit_context
94 .allows_reg(().at(parser.file_id, &start_token.span()))?;
95
96 let (clock, _clock_paren_span) = parser.surrounded(
98 &TokenKind::OpenParen,
99 |s| s.expression().map(Some),
100 &TokenKind::CloseParen,
101 )?;
102
103 let clock = clock.unwrap();
106
107 let pattern = parser.pattern()?;
109
110 let value_type = if parser.peek_and_eat(&TokenKind::Colon)?.is_some() {
112 Some(parser.type_spec()?)
113 } else {
114 None
115 };
116
117 let reset = parser.register_reset()?;
119 let initial = parser.register_initial()?;
120 let reset = match (reset, parser.register_reset()?) {
122 (Some(first), None) => Some(first),
123 (None, Some(second)) => Some(second),
124 (Some(first), Some(second)) => {
125 return Err(Diagnostic::error(
126 ().between_locs(&second.0, &second.1),
127 "Multiple resets specified",
128 )
129 .primary_label("Second reset")
130 .secondary_label(().between_locs(&first.0, &first.1), "First reset"))
131 }
132 (None, None) => None,
133 };
134
135 parser.eat(&TokenKind::Assignment)?;
137 let (value, end_span) = parser.expression()?.separate();
138
139 let span = lspan(start_token.span).merge(end_span);
140 let result = Statement::Register(
141 Register {
142 pattern,
143 clock,
144 reset,
145 initial,
146 value,
147 value_type,
148 attributes: attributes.clone(),
149 }
150 .at(parser.file_id, &span),
151 )
152 .at(parser.file_id, &span);
153 Ok(result)
154 }
155}
156
157impl<'a> Parser<'a> {
158 #[trace_parser]
159 pub fn register_reset_definition(&mut self) -> Result<(Loc<Expression>, Loc<Expression>)> {
160 let condition = self.expression()?;
161 self.eat(&TokenKind::Colon)?;
162 let value = self.expression()?;
163
164 Ok((condition, value))
165 }
166
167 #[trace_parser]
168 pub fn register_reset(&mut self) -> Result<Option<(Loc<Expression>, Loc<Expression>)>> {
169 peek_for!(self, &TokenKind::Reset);
170 let (reset, _) = self.surrounded(
171 &TokenKind::OpenParen,
172 |s| s.register_reset_definition().map(Some),
173 &TokenKind::CloseParen,
174 )?;
175 Ok(Some(reset.unwrap()))
177 }
178
179 #[trace_parser]
180 pub fn register_initial(&mut self) -> Result<Option<Loc<Expression>>> {
181 peek_for!(self, &TokenKind::Initial);
182 let (reset, _) = self.surrounded(
183 &TokenKind::OpenParen,
184 Self::expression,
185 &TokenKind::CloseParen,
186 )?;
187 Ok(Some(reset))
188 }
189}
190
191pub(crate) struct DeclParser {}
192
193impl KeywordPeekingParser<Loc<Statement>> for DeclParser {
194 fn leading_tokens(&self) -> Vec<TokenKind> {
195 vec![TokenKind::Decl]
196 }
197
198 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<Loc<Statement>> {
199 let start_token = parser.eat_unconditional()?;
200 parser.disallow_attributes(attributes, &start_token)?;
201
202 let mut identifiers = vec![];
203 while parser.peek_cond(|t| t.is_identifier(), "expected identifier")? {
204 identifiers.push(parser.identifier()?);
205
206 if parser.peek_and_eat(&TokenKind::Comma)?.is_none() {
207 break;
208 }
209 }
210
211 if identifiers.is_empty() {
212 return Err(Diagnostic::error(start_token.loc(), "empty decl statement")
213 .primary_label("this decl does not declare anything"));
214 }
215
216 let last_ident = identifiers.last().unwrap().clone();
217
218 Ok(Statement::Declaration(identifiers).between(
219 parser.file_id,
220 &start_token.span,
221 &last_ident,
222 ))
223 }
224}
225
226pub(crate) struct LabelParser {}
227
228impl KeywordPeekingParser<Loc<Statement>> for LabelParser {
229 fn leading_tokens(&self) -> Vec<TokenKind> {
230 vec![TokenKind::SingleQuote]
231 }
232
233 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<Loc<Statement>> {
234 let tok = parser.eat_unconditional()?;
235 parser.disallow_attributes(attributes, &tok)?;
236
237 let name = parser.identifier()?;
238 Ok(Statement::Label(name.clone()).between(parser.file_id, &tok.span, &name))
239 }
240}
241
242pub(crate) struct AssertParser {}
243
244impl KeywordPeekingParser<Loc<Statement>> for AssertParser {
245 fn leading_tokens(&self) -> Vec<TokenKind> {
246 vec![TokenKind::Assert]
247 }
248
249 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<Loc<Statement>> {
250 let tok = parser.eat_unconditional()?;
251 parser.disallow_attributes(attributes, &tok)?;
252
253 let expr = parser.expression()?;
254
255 Ok(Statement::Assert(expr.clone()).between(parser.file_id, &tok.span, &expr))
256 }
257}
258
259pub(crate) struct SetParser {}
260
261impl KeywordPeekingParser<Loc<Statement>> for SetParser {
262 fn leading_tokens(&self) -> Vec<TokenKind> {
263 vec![TokenKind::Set]
264 }
265
266 fn parse(&self, parser: &mut Parser, attributes: &AttributeList) -> Result<Loc<Statement>> {
267 let tok = parser.eat_unconditional()?;
268 parser.disallow_attributes(attributes, &tok)?;
269
270 let target = parser.expression()?;
271
272 parser.eat(&TokenKind::Assignment)?;
273
274 let value = parser.expression()?;
275
276 Ok(Statement::Set {
277 target,
278 value: value.clone(),
279 }
280 .between(parser.file_id, &tok.span, &value))
281 }
282}