1use super::*;
18use snarkvm::prelude::Itertools;
19
20use leo_errors::{ParserError, Result, TypeCheckerError};
21use leo_span::{Symbol, sym};
22
23impl ParserContext<'_> {
24 pub fn parse_program(&mut self) -> Result<Program> {
26 let mut imports = IndexMap::new();
27 let mut program_scopes = IndexMap::new();
28
29 let mut parsed_program_scope = false;
31
32 while self.has_next() {
33 match &self.token.token {
34 Token::Import => {
35 let (id, import) = self.parse_import()?;
36 imports.insert(id, import);
37 }
38 Token::Program => {
39 match parsed_program_scope {
40 true => {
42 return Err(ParserError::only_one_program_scope_is_allowed(self.token.span).into());
43 }
44 false => {
45 parsed_program_scope = true;
46 let program_scope = self.parse_program_scope()?;
47 program_scopes.insert(program_scope.program_id.name.name, program_scope);
48 }
49 }
50 }
51 _ => return Err(Self::unexpected_item(&self.token, &[Token::Import, Token::Program]).into()),
52 }
53 }
54
55 if !parsed_program_scope {
57 return Err(ParserError::missing_program_scope(self.token.span).into());
58 }
59
60 Ok(Program { modules: IndexMap::new(), imports, stubs: IndexMap::new(), program_scopes })
61 }
62
63 fn unexpected_item(token: &SpannedToken, expected: &[Token]) -> ParserError {
64 ParserError::unexpected(
65 &token.token,
66 expected.iter().map(|x| format!("'{x}'")).collect::<Vec<_>>().join(", "),
67 token.span,
68 )
69 }
70
71 pub(super) fn parse_import(&mut self) -> Result<(Symbol, (Program, Span))> {
74 let start = self.expect(&Token::Import)?;
76
77 let import_name = self.expect_identifier()?;
79
80 self.expect(&Token::Dot)?;
82
83 if !self.eat(&Token::Aleo) {
85 return Err(ParserError::invalid_network(self.token.span).into());
87 }
88
89 let end = self.expect(&Token::Semicolon)?;
90
91 Ok((import_name.name, (Program::default(), start + end)))
93 }
94
95 fn parse_program_scope(&mut self) -> Result<ProgramScope> {
97 let start = self.expect(&Token::Program)?;
99
100 let name = self.expect_identifier()?;
102
103 self.program_name = Some(name.name);
105
106 self.expect(&Token::Dot)?;
108
109 let network_span = self.expect(&Token::Aleo).map_err(|_| ParserError::invalid_network(self.token.span))?;
111
112 let program_id = ProgramId {
114 name,
115 network: Identifier { name: sym::aleo, id: self.node_builder.next_id(), span: network_span },
116 };
117
118 self.expect(&Token::LeftCurly)?;
120
121 if !self.annotations.is_empty() {
123 self.emit_err(ParserError::custom("Unexpected dangling annotation", self.annotations[0].span))
124 }
125
126 let mut consts: Vec<(Symbol, ConstDeclaration)> = Vec::new();
128 let (mut transitions, mut functions) = (Vec::new(), Vec::new());
129 let mut structs: Vec<(Symbol, Composite)> = Vec::new();
130 let mut mappings: Vec<(Symbol, Mapping)> = Vec::new();
131 let mut constructor = None;
132
133 while self.has_next() {
134 match &self.token.token {
135 Token::Const => {
136 let declaration = self.parse_const_declaration_statement()?;
137 consts.push((Symbol::intern(&declaration.place.to_string()), declaration));
138 }
139 Token::Struct | Token::Record => {
140 let (id, struct_) = self.parse_struct()?;
141 structs.push((id, struct_));
142 }
143 Token::Mapping => {
144 let (id, mapping) = self.parse_mapping()?;
145 mappings.push((id, mapping));
146 }
147 Token::At => {
148 let annotation = self.parse_annotation()?;
149 self.annotations.push(annotation);
150 }
151 Token::Async if self.look_ahead(1, |t| &t.token) == &Token::Constructor => {
152 if constructor.is_some() {
154 return Err(TypeCheckerError::custom(
155 "A program can only have one constructor.",
156 self.token.span,
157 )
158 .into());
159 }
160 let constructor_ = self.parse_constructor()?;
161 constructor = Some(constructor_);
162 }
163 Token::Async | Token::Function | Token::Transition | Token::Inline | Token::Script => {
164 let (id, function) = self.parse_function()?;
165
166 if function.variant.is_transition() {
168 transitions.push((id, function));
169 } else {
170 functions.push((id, function));
171 }
172 }
173 Token::RightCurly => break,
174 _ => {
175 return Err(Self::unexpected_item(&self.token, &[
176 Token::Const,
177 Token::Struct,
178 Token::Record,
179 Token::Mapping,
180 Token::At,
181 Token::Async,
182 Token::Function,
183 Token::Transition,
184 Token::Inline,
185 Token::Script,
186 Token::RightCurly,
187 ])
188 .into());
189 }
190 }
191 }
192
193 if !self.annotations.is_empty() {
195 self.emit_err(ParserError::custom("Unexpected dangling annotation", self.annotations[0].span))
196 }
197
198 let end = self.expect(&Token::RightCurly)?;
200
201 Ok(ProgramScope {
202 program_id,
203 consts,
204 structs,
205 mappings,
206 constructor,
207 functions: [transitions, functions].concat(),
208 span: start + end,
209 })
210 }
211
212 pub fn parse_module(&mut self, path: &[Symbol]) -> Result<Module> {
214 let mut consts: Vec<(Symbol, ConstDeclaration)> = Vec::new();
216 let mut functions = Vec::new();
217 let mut structs: Vec<(Symbol, Composite)> = Vec::new();
218
219 while self.has_next() {
220 match &self.token.token {
222 Token::Const => {
223 let declaration = self.parse_const_declaration_statement()?;
224 consts.push((Symbol::intern(&declaration.place.to_string()), declaration));
225 }
226 Token::Struct => {
227 let (id, struct_) = self.parse_struct()?;
228 structs.push((id, struct_));
229 }
230 Token::Inline => {
231 let (id, function) = self.parse_function()?;
232
233 functions.push((id, function));
234 }
235 Token::RightCurly => break,
236 _ => {
237 return Err(Self::unexpected_item(&self.token, &[
238 Token::Const,
239 Token::Struct,
240 Token::Inline,
241 Token::RightCurly,
242 ])
243 .into());
244 }
245 }
246 }
247
248 Ok(Module {
249 program_name: self.program_name.unwrap_or_default(),
250 path: path.to_owned(),
251 consts,
252 functions,
253 structs,
254 })
255 }
256
257 fn parse_struct_members(&mut self) -> Result<(Vec<Member>, Span)> {
259 let mut members = Vec::new();
260
261 while !self.check(&Token::RightCurly) {
262 let variable = self.parse_member_variable_declaration()?;
263
264 if !self.check(&Token::RightCurly) && !self.eat(&Token::Comma) {
265 self.emit_err(ParserError::comma_expected_after_member(self.token.span));
266 }
267
268 members.push(variable);
269 }
270 let span = self.expect(&Token::RightCurly)?;
271
272 Ok((members, span))
273 }
274
275 pub(super) fn parse_typed_ident(&mut self) -> Result<(Identifier, Type, Span)> {
277 let name = self.expect_identifier()?;
278 self.expect(&Token::Colon)?;
279 let (type_, span) = self.parse_type()?;
280
281 Ok((name, type_, name.span + span))
282 }
283
284 fn parse_member_variable_declaration(&mut self) -> Result<Member> {
286 let mode = self.parse_mode()?;
287
288 let (identifier, type_, span) = self.parse_typed_ident()?;
289
290 Ok(Member { mode, identifier, type_, span, id: self.node_builder.next_id() })
291 }
292
293 pub(super) fn parse_struct(&mut self) -> Result<(Symbol, Composite)> {
295 let is_record = matches!(&self.token.token, Token::Record);
296 let start = self.expect_any(&[Token::Struct, Token::Record])?;
297
298 let file_type = self.look_ahead(1, |t| &t.token);
300 if self.token.token == Token::Dot && (file_type == &Token::Aleo) {
301 return Err(ParserError::cannot_declare_external_struct(self.token.span).into());
302 }
303
304 let struct_name = self.expect_identifier()?;
305
306 let const_parameters = if self.eat(&Token::DoubleColon) {
307 self.parse_bracket_comma_list(|p| p.parse_const_parameter().map(Some))?.0
308 } else {
309 vec![]
310 };
311
312 self.expect(&Token::LeftCurly)?;
313 let (members, end) = self.parse_struct_members()?;
314
315 let external = if is_record { self.program_name } else { None };
317
318 Ok((struct_name.name, Composite {
319 identifier: struct_name,
320 const_parameters,
321 members,
322 external,
323 is_record,
324 span: start + end,
325 id: self.node_builder.next_id(),
326 }))
327 }
328
329 pub(super) fn parse_mapping(&mut self) -> Result<(Symbol, Mapping)> {
331 let start = self.expect(&Token::Mapping)?;
332 let identifier = self.expect_identifier()?;
333 self.expect(&Token::Colon)?;
334 let (key_type, _) = self.parse_type()?;
335 self.expect(&Token::BigArrow)?;
336 let (value_type, _) = self.parse_type()?;
337 let end = self.expect(&Token::Semicolon)?;
338 Ok((identifier.name, Mapping {
339 identifier,
340 key_type,
341 value_type,
342 span: start + end,
343 id: self.node_builder.next_id(),
344 }))
345 }
346
347 pub(super) fn parse_mode(&mut self) -> Result<Mode> {
350 let private = self.eat(&Token::Private).then_some(self.prev_token.span);
351 let public = self.eat(&Token::Public).then_some(self.prev_token.span);
352 let constant = self.eat(&Token::Constant).then_some(self.prev_token.span);
353
354 match (private, public, constant) {
355 (None, None, None) => Ok(Mode::None),
356 (Some(_), None, None) => Ok(Mode::Private),
357 (None, Some(_), None) => Ok(Mode::Public),
358 (None, None, Some(_)) => Ok(Mode::Constant),
359 _ => {
360 let mut spans = [private, public, constant].into_iter().flatten();
361
362 let starting_span = spans.next().unwrap();
364 let summed_span = spans.fold(starting_span, |span, next| span + next);
366 Err(ParserError::inputs_multiple_variable_modes_specified(summed_span).into())
368 }
369 }
370 }
371
372 fn parse_input(&mut self) -> Result<Input> {
374 let mode = self.parse_mode()?;
375 let name = self.expect_identifier()?;
376 self.expect(&Token::Colon)?;
377
378 let (type_, type_span) = self.parse_type()?;
379 let span = name.span() + type_span;
380
381 Ok(Input { identifier: name, mode, type_, span, id: self.node_builder.next_id() })
382 }
383
384 fn parse_output(&mut self) -> Result<Output> {
386 let mode = self.parse_mode()?;
387 let (type_, span) = self.parse_type()?;
388 Ok(Output { mode, type_, span, id: self.node_builder.next_id() })
389 }
390
391 fn parse_annotation(&mut self) -> Result<Annotation> {
393 let start = self.expect(&Token::At)?;
395 let identifier = match self.token.token {
396 Token::Program => {
397 Identifier { name: sym::program, span: self.expect(&Token::Program)?, id: self.node_builder.next_id() }
398 }
399 _ => self.expect_identifier()?,
400 };
401 let mut span = start + identifier.span;
402
403 if identifier.span.hi - start.lo > 1 + identifier.name.to_string().len() as u32 {
406 return Err(ParserError::space_in_annotation(span).into());
407 }
408
409 let mut map = IndexMap::new();
410
411 if self.eat(&Token::LeftParen) {
412 loop {
413 let key = match self.token.token {
414 Token::Mapping => Identifier {
415 name: sym::mapping,
416 span: self.expect(&Token::Mapping)?,
417 id: self.node_builder.next_id(),
418 },
419 Token::Address => Identifier {
420 name: sym::address,
421 span: self.expect(&Token::Address)?,
422 id: self.node_builder.next_id(),
423 },
424 _ => self.expect_identifier()?,
425 };
426 self.expect(&Token::Assign)?;
427 if let Token::StaticString(s) = &self.token.token {
428 map.insert(key.name, s.clone());
429 self.bump();
430 } else {
431 return Err(ParserError::unexpected(&self.token.token, "a string", self.token.span).into());
432 }
433
434 match &self.token.token {
435 Token::Comma => {
436 self.bump();
437 if let Token::RightParen = &self.token.token {
438 span = span + self.token.span;
439 self.bump();
440 break;
441 }
442 }
443 Token::RightParen => {
444 span = span + self.token.span;
445 self.bump();
446 break;
447 }
448 _ => return Err(ParserError::unexpected(&self.token.token, ", or )", self.token.span).into()),
449 }
450 }
451 }
452
453 Ok(Annotation { identifier, span, id: self.node_builder.next_id(), map })
454 }
455
456 fn parse_function(&mut self) -> Result<(Symbol, Function)> {
459 let annotations = self.annotations.drain(..).collect();
461 let (is_async, start_async) =
463 if self.token.token == Token::Async { (true, self.expect(&Token::Async)?) } else { (false, Span::dummy()) };
464 let (variant, start) = match self.token.token.clone() {
466 Token::Inline => (Variant::Inline, self.expect(&Token::Inline)?),
467 Token::Script => (Variant::Script, self.expect(&Token::Script)?),
468 Token::Function => {
469 (if is_async { Variant::AsyncFunction } else { Variant::Function }, self.expect(&Token::Function)?)
470 }
471 Token::Transition => (
472 if is_async { Variant::AsyncTransition } else { Variant::Transition },
473 self.expect(&Token::Transition)?,
474 ),
475 _ => self.unexpected("'function', 'transition', or 'inline'")?,
476 };
477 let name = self.expect_identifier()?;
478
479 let const_parameters = if self.eat(&Token::DoubleColon) {
480 self.parse_bracket_comma_list(|p| p.parse_const_parameter().map(Some))?.0
481 } else {
482 vec![]
483 };
484
485 let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_input().map(Some))?;
487
488 let output = match self.eat(&Token::Arrow) {
490 false => vec![],
491 true => {
492 self.disallow_struct_construction = true;
493 let output = match self.peek_is_left_par() {
494 true => self.parse_paren_comma_list(|p| p.parse_output().map(Some))?.0,
495 false => vec![self.parse_output()?],
496 };
497 self.disallow_struct_construction = false;
498 output
499 }
500 };
501
502 let (_has_empty_block, block) = match &self.token.token {
505 Token::LeftCurly => (false, self.parse_block()?),
506 Token::Semicolon => {
507 let semicolon = self.expect(&Token::Semicolon)?;
508 (true, Block { statements: Vec::new(), span: semicolon, id: self.node_builder.next_id() })
510 }
511 _ => self.unexpected("block or semicolon")?,
512 };
513
514 let span = if start_async == Span::dummy() { start + block.span } else { start_async + block.span };
515
516 Ok((
517 name.name,
518 Function::new(
519 annotations,
520 variant,
521 name,
522 const_parameters,
523 inputs,
524 output,
525 block,
526 span,
527 self.node_builder.next_id(),
528 ),
529 ))
530 }
531
532 pub(crate) fn parse_constructor(&mut self) -> Result<Constructor> {
534 let annotations = self.annotations.drain(..).collect_vec();
536 let start = self.expect(&Token::Async)?;
538 let _ = self.expect(&Token::Constructor)?;
540 let _ = self.expect(&Token::LeftParen)?;
542 let _ = self.expect(&Token::RightParen)?;
544 let block = self.parse_block()?;
546
547 let start = match annotations.is_empty() {
549 true => start,
550 false => annotations[0].span,
551 };
552
553 Ok(Constructor { span: start + block.span, annotations, block, id: self.node_builder.next_id() })
554 }
555}