1use std::collections::HashMap;
2use std::iter::Iterator;
3
4use super::expr_parser::*;
5use super::error::*;
6use super::tokens::*;
7use crate::ast::*;
8use crate::span::*;
9
10pub type ParseErr<T> = Result<T, ParserError>;
11
12macro_rules! consume_token {
13
14 ($input: expr, $state: expr) => {{
15 let next = $input.next()
16 .ok_or(parser_error!(ParserErrorKind::UnexpectedEOI, $state))?
17 .map_err(|e| parser_error!(ParserErrorKind::TokenizerError(e), $state))?;
18 next.to_data()
19 }};
20
21 ($input: expr, $token: pat, $state: expr) => {{
22 let next = $input.next()
23 .ok_or(parser_error!(ParserErrorKind::UnexpectedEOI, $state))?
24 .map_err(|e| parser_error!(ParserErrorKind::TokenizerError(e), $state))?;
25 let data = next.to_data();
26 match data.1 {
27 $token => data,
28 _ => Err(parser_error!(ParserErrorKind::UnexpectedToken(data.1), $state, Some(data.0)))?,
29 }
30 }};
31
32 ($input: expr, $token: pat => $e: expr, $state: expr) => {{
33 let next = $input.next()
34 .ok_or(parser_error!(ParserErrorKind::UnexpectedEOI, $state))?
35 .map_err(|e| parser_error!(ParserErrorKind::TokenizerError(e), $state))?;
36 let data = next.to_data();
37 match data.1 {
38 $token => (data.0, $e),
39 _ => Err(parser_error!(ParserErrorKind::UnexpectedToken(data.1), $state, Some(data.0)))?,
40 }
41 }};
42}
43
44macro_rules! peek_token {
45 ($tokenizer: expr, $lam: expr, $state: expr) => {
46 ($tokenizer)
47 .peek($lam)
48 .ok_or(parser_error!(ParserErrorKind::UnexpectedEOI, $state))?
49 .map_err(|e| parser_error!(e.into(), $state))?
50 };
51}
52
53pub fn module(tokens: &mut BufferedTokenizer) -> ParseErr<Module> {
54 enum ModDec {
55 Struct,
56 Opaque,
57 Annotation,
58 Function(bool),
59 Use,
60 Err,
61 }
62
63 let mut name = None;
64 if peek_token!(
65 tokens,
66 |tok| match tok {
67 Token::Mod => true,
68 _ => false,
69 },
70 parser_state!("module", "mod-decl")
71 ) {
72 name = Some(production!(
74 module_decl(tokens),
75 parser_state!("module", "mod-decl")
76 ));
77 }
78
79 let mut decls = Vec::new();
80 let mut anno = Vec::new();
81
82 while tokens.has_next() {
83 match peek_token!(
84 tokens,
85 |tok| match tok {
86 Token::Struct => ModDec::Struct,
87 Token::Pound => ModDec::Annotation,
88 Token::Fn => ModDec::Function(false),
89 Token::Builtin => ModDec::Function(true),
90 Token::Opaque => ModDec::Opaque,
91 Token::Use => ModDec::Use,
92 _ => ModDec::Err,
93 },
94 parser_state!("module", "decl-kind")
95 ) {
96 ModDec::Opaque => {
97 decls.push(DeclStmt::Opaque(production!(
98 opaque_decl(tokens, anno),
99 parser_state!("module", "opaque-decl")
100 )));
101 anno = Vec::new();
102 }
103
104 ModDec::Struct => {
105 decls.push(DeclStmt::Struct(production!(
106 struct_decl(tokens, anno),
107 parser_state!("module", "struct-decl")
108 )));
109 anno = Vec::new();
110 }
111
112 ModDec::Annotation => {
113 anno = production!(
114 annotations(tokens),
115 parser_state!("module", "annotation")
116 );
117 }
118
119 ModDec::Function(is_builtin) => {
120 decls.push(production!(
121 fn_decl(tokens, anno, is_builtin),
122 parser_state!("module", "fn-decl")
123 ));
124 anno = Vec::new();
125 }
126
127 ModDec::Use => {
128 decls.push(production!(
129 use_decl(tokens),
130 parser_state!("module", "use-decl")
131 ));
132 anno = Vec::new();
133 }
134
135 ModDec::Err => {
136 unimplemented!("Unexpected token: {:?}", tokens.next().unwrap())
137 }
138 }
139 }
140
141 let module = Module(name, decls);
142
143 Ok(module)
144}
145
146fn annotations(tokens: &mut BufferedTokenizer) -> ParseErr<Vec<Annotation>> {
147 let mut annotations = Vec::new();
148
149 while peek_token!(
150 tokens,
151 |tok| match tok {
152 Token::Pound => true,
153 _ => false,
154 },
155 parser_state!("annotations", "more-annotation-indication")
156 ) {
157 let _pound = consume_token!(
158 tokens,
159 Token::Pound,
160 parser_state!("annotations", "pound")
161 );
162 let _lbracket = consume_token!(
163 tokens,
164 Token::LBracket,
165 parser_state!("annotations", "lbracket")
166 );
167 annotations.push(Annotation {
168 keys: production!(
169 kv_list(tokens),
170 parser_state!("annotations", "kv-list")
171 ),
172 });
173 let _rbracket = consume_token!(
174 tokens,
175 Token::RBracket,
176 parser_state!("annotations", "rbracket")
177 );
178 }
179
180 Ok(annotations)
181}
182
183fn kv_list(
184 tokens: &mut BufferedTokenizer,
185) -> ParseErr<Vec<(Ident, Option<String>)>> {
186 let mut list = vec![kv_pair(tokens)?];
187
188 loop {
189 if peek_token!(
190 tokens,
191 |tok| match tok {
192 Token::Comma => true,
193 _ => false,
194 },
195 parser_state!("kv-list", "comma-separator")
196 ) {
197 let _comma = consume_token!(
198 tokens,
199 Token::Comma,
200 parser_state!("kv-list", "comma-separator")
201 );
202 if peek_token!(
203 tokens,
204 |tok| match tok {
205 Token::RBracket => false,
206 _ => true,
207 },
208 parser_state!("kv-list", "rbracket")
209 ) {
210 list.push(production!(
211 kv_pair(tokens),
212 parser_state!("kv-list", "kv-pair")
213 ));
214 continue;
215 }
216 }
217
218 break;
219 }
220
221 Ok(list)
222}
223
224fn kv_pair(
225 tokens: &mut BufferedTokenizer,
226) -> ParseErr<(Ident, Option<String>)> {
227 let (_, ident) = consume_token!(tokens,
228 Token::Identifier(i) => i,
229 parser_state!("kvpair", "key"));
230
231 if peek_token!(
232 tokens,
233 |tok| match tok {
234 Token::Assign => true,
235 _ => false,
236 },
237 parser_state!("kv-pair", "=")
238 ) {
239 let _assign = consume_token!(
240 tokens,
241 Token::Assign,
242 parser_state!("kvpair", "assign")
243 );
244 let (_, v) = consume_token!(tokens,
245 Token::StringLiteral(s) => s,
246 parser_state!("kvpair", "value"));
247 Ok((Ident(ident), Some(v)))
248 } else {
249 Ok((Ident(ident), None))
250 }
251}
252
253fn use_decl(tokens: &mut BufferedTokenizer) -> ParseErr<DeclStmt> {
254 let (uspan, _) =
255 consume_token!(tokens, Token::Use, parser_state!("use-decl", "use"));
256 let (mspan, module) = consume_token!(tokens,
257 Token::Identifier(i) => Ident(i),
258 parser_state!("use-decl", "name"));
259 let _semi = consume_token!(
260 tokens,
261 Token::Semi,
262 parser_state!("use-decl", "semicolon")
263 );
264
265 let span = LocationSpan::combine(uspan, mspan.clone());
266
267 let use_decl = UseDecl(AstNode::new(module, mspan));
268
269 let use_decl = DeclStmt::Use(AstNode::new(use_decl, span));
270
271 Ok(use_decl)
272}
273
274fn where_clause(tokens: &mut BufferedTokenizer) -> ParseErr<WhereClause> {
275 let _where = consume_token!(
276 tokens,
277 Token::Where,
278 parser_state!("where-clause", "where")
279 );
280
281 let mut parameter_constraints = HashMap::new();
282
283 loop {
284 let (param_span, parameter) = consume_token!(
285 tokens,
286 Token::Identifier(ident) => Ident(ident),
287 parser_state!("where-clause-constraints", "param"));
288 let _colon = consume_token!(
289 tokens,
290 Token::Colon,
291 parser_state!("where-clause-constraints", "colon")
292 );
293 let annotation = production!(
294 type_annotation(tokens),
295 parser_state!("where-clause-constraints", "annotation")
296 );
297
298 parameter_constraints
299 .entry(AstNode::new(parameter, param_span))
300 .or_insert(Vec::new())
301 .push(annotation);
302
303 if peek_token!(
304 tokens,
305 |tok| match tok {
306 Token::Comma => true,
307 _ => false,
308 },
309 parser_state!("where-clause-constraints", "comma?")
310 ) {
311 let _comma = consume_token!(
312 tokens,
313 Token::Comma,
314 parser_state!("where-clause-constraints", "comma")
315 );
316 } else {
317 break;
320 }
321 }
322
323 let where_clause = WhereClause(parameter_constraints);
324 Ok(where_clause)
325}
326
327#[cfg(test)]
328pub fn testfn_decl(tokens: &mut BufferedTokenizer) -> ParseErr<Function> {
329 let decl = fn_decl(tokens, vec![], false)?;
330 match decl {
331 DeclStmt::Function(f) => Ok(f.to_data().0),
332 _ => unreachable!(),
333 }
334}
335
336fn fn_decl(
337 tokens: &mut BufferedTokenizer,
338 annotations: Vec<Annotation>,
339 is_builtin: bool,
340) -> ParseErr<DeclStmt> {
341 let mut span = Span::dummy();
342 if is_builtin {
343 let (bloc, _builtin) = consume_token!(
344 tokens,
345 Token::Builtin,
346 parser_state!("fn-decl", "builtin")
347 );
348 span = bloc;
349 }
350
351 let (fnloc, _) =
352 consume_token!(tokens, Token::Fn, parser_state!("fn-decl", "fn"));
353 if !is_builtin {
354 span = fnloc;
355 }
356
357 let (idloc, ident) = consume_token!(tokens,
358 Token::Identifier(i) => Ident(i),
359 parser_state!("fn-decl", "name"));
360 let _lparen = consume_token!(
361 tokens,
362 Token::LParen,
363 parser_state!("fn-decl", "(type?) parameter lparen")
364 );
365
366 let type_params = if peek_token!(
367 tokens,
368 |tok| match tok {
369 Token::Type => true,
370 _ => false,
371 },
372 parser_state!("fn-decl", "type parameters?")
373 ) {
374 let params = Some(type_param_list_post_lparen(tokens)?);
375
376 let _lparen = consume_token!(
378 tokens,
379 Token::LParen,
380 parser_state!("fn-decl", "parameter lparen")
381 );
382
383 params
384 } else {
385 None
386 };
387
388 let params = if peek_token!(
389 tokens,
390 |tok| match tok {
391 Token::Unchecked => true,
392 _ => false,
393 },
394 parser_state!("fn-decl", "UNCHECKED paramter")
395 ) {
396 let _unchecked = consume_token!(
397 tokens,
398 Token::Unchecked,
399 parser_state!("fn-decl", "UNCHECKED parameter")
400 );
401 BuiltinFnParams::Unchecked
402 } else {
403 if peek_token!(
404 tokens,
405 |tok| match tok {
406 Token::RParen => false,
407 _ => true,
408 },
409 parser_state!("fn-decl", "rparen")
410 ) {
411 BuiltinFnParams::Checked(Some(production!(
412 fn_param_list(tokens),
413 parser_state!("fn-decl", "fn-param-list")
414 )))
415 } else {
416 BuiltinFnParams::Checked(None)
417 }
418 };
419
420 let (rloc, _) = consume_token!(
421 tokens,
422 Token::RParen,
423 parser_state!("fn-decl", "parameter rparen")
424 );
425 span = Span::combine(span, rloc);
426
427 let mut return_type = None;
428 if peek_token!(
429 tokens,
430 |tok| match tok {
431 Token::Arrow => true,
432 _ => false,
433 },
434 parser_state!("fn-decl", "return type arrow?")
435 ) {
436 let _arrow = consume_token!(
437 tokens,
438 Token::Arrow,
439 parser_state!("fn-decl", "return type arrow")
440 );
441 return_type = Some(production!(
442 type_annotation(tokens),
443 parser_state!("fn-decl", "return type")
444 ));
445 }
446
447 let where_clause = if peek_token!(
448 tokens,
449 |tok| match tok {
450 Token::Where => true,
451 _ => false,
452 },
453 parser_state!("fn-decl", "where-clause?")
454 ) {
455 Some(production!(
456 where_clause(tokens),
457 parser_state!("fn-decl", "where-clause")
458 ))
459 } else {
460 None
461 };
462
463 let mut body: Option<AstNode<Block>> = None;
464 if !is_builtin {
465 body = Some(block(tokens)?);
466 }
467
468 if is_builtin {
469 let (semiloc, _) = consume_token!(
470 tokens,
471 Token::Semi,
472 parser_state!("fn-decl", "builtin-semicolon")
473 );
474 span = Span::combine(span, semiloc);
475 }
476
477 if is_builtin {
478 Ok(DeclStmt::BuiltinFunction(AstNode::new(
479 BuiltinFunction {
480 name: AstNode::new(ident, idloc),
481 params: params,
482 return_type: return_type,
483 annotations: annotations,
484 type_params: type_params,
485 where_clause: where_clause,
486 },
487 span,
488 )))
489 } else {
490 let params = match params {
491 BuiltinFnParams::Unchecked => {
492 return Err(parser_error!(
493 ParserErrorKind::NonbuiltinUncheckedParameters,
494 parser_state!("fn-decl", "param-validation")
495 ));
496 }
497 BuiltinFnParams::Checked(p) => p,
498 };
499
500 let body = match body {
501 Some(b) => b,
502 None => {
503 return Err(parser_error!(
504 ParserErrorKind::NoFnBody,
505 parser_state!("fn-decl", "body")
506 ));
507 }
508 };
509
510 Ok(DeclStmt::Function(AstNode::new(
511 Function {
512 name: AstNode::new(ident, idloc),
513 params: params,
514 return_type: return_type,
515 body: body,
516 annotations: annotations,
517 type_params: type_params,
518 where_clause: where_clause,
519 },
520 span,
521 )))
522 }
523}
524
525pub fn fn_param_list(
526 tokens: &mut BufferedTokenizer,
527) -> ParseErr<Vec<AstNode<FnParameter>>> {
528 let mut list = vec![production!(
529 fn_param(tokens),
530 parser_state!("fn-param-list", "fn-param")
531 )];
532
533 loop {
534 if peek_token!(
535 tokens,
536 |tok| match tok {
537 Token::Comma => true,
538 _ => false,
539 },
540 parser_state!("fn-param-list", "comma separator")
541 ) {
542 let _comma = consume_token!(
543 tokens,
544 Token::Comma,
545 parser_state!("fn-param-list", "comma separator")
546 );
547 if peek_token!(
548 tokens,
549 |tok| match tok {
550 Token::RParen => false,
551 _ => true,
552 },
553 parser_state!("fn-param-list", "rparen")
554 ) {
555 list.push(production!(
556 fn_param(tokens),
557 parser_state!("fn-param-list", "fn-param")
558 ));
559 continue;
560 }
561 }
562
563 break;
564 }
565
566 Ok(list)
567}
568
569fn fn_param(tokens: &mut BufferedTokenizer) -> ParseErr<AstNode<FnParameter>> {
570 let (idloc, ident) = consume_token!(tokens,
571 Token::Identifier(i) => Ident(i),
572 parser_state!("fn-param", "parameter name"));
573 let _colon = consume_token!(
574 tokens,
575 Token::Colon,
576 parser_state!("fn-param", "param type colon")
577 );
578 let ann = production!(
579 type_annotation(tokens),
580 parser_state!("fn-param", "param-type")
581 );
582
583 let span = Span::combine(idloc.clone(), ann.span());
584 let param = FnParameter {
585 name: AstNode::new(ident, idloc),
586 param_type: ann,
587 };
588
589 Ok(AstNode::new(param, span))
590}
591
592#[cfg(test)]
593pub fn teststruct_decl(tokens: &mut BufferedTokenizer) -> ParseErr<Struct> {
594 let decl = struct_decl(tokens, vec![])?.to_data().0;
595 Ok(decl)
596}
597
598fn opaque_decl(
599 tokens: &mut BufferedTokenizer,
600 anns: Vec<Annotation>,
601) -> ParseErr<AstNode<Opaque>> {
602 let (opaque_loc, _) = consume_token!(
603 tokens,
604 Token::Opaque,
605 parser_state!("opaque-decl", "opaque")
606 );
607 let (name_loc, struct_name) = consume_token!(tokens,
608 Token::Identifier(i) => Ident(i),
609 parser_state!("opaque-decl", "name"));
610
611 let type_params = if peek_token!(
612 tokens,
613 |tok| match tok {
614 Token::LParen => true,
615
616 _ => false,
617 },
618 parser_state!("opaque-decl", "type-parameters?")
619 ) {
620 Some(type_param_list(tokens)?)
621 } else {
622 None
623 };
624
625 let where_clause = if peek_token!(
626 tokens,
627 |tok| match tok {
628 Token::Where => true,
629 _ => false,
630 },
631 parser_state!("struct-decl", "where-clause?")
632 ) {
633 Some(production!(
634 where_clause(tokens),
635 parser_state!("struct-decl", "where-clause")
636 ))
637 } else {
638 None
639 };
640
641 let (semi_loc, _) = consume_token!(
642 tokens,
643 Token::Semi,
644 parser_state!("opaque-decl", "end-semi")
645 );
646
647 let overall_span = LocationSpan::combine(opaque_loc, semi_loc);
648
649 Ok(AstNode::new(
650 Opaque {
651 name: AstNode::new(struct_name, name_loc),
652 annotations: anns,
653 type_params: type_params,
654 where_clause: where_clause,
655 },
656 overall_span,
657 ))
658}
659
660fn struct_decl(
661 tokens: &mut BufferedTokenizer,
662 anns: Vec<Annotation>,
663) -> ParseErr<AstNode<Struct>> {
664 let (struct_loc, _) = consume_token!(
665 tokens,
666 Token::Struct,
667 parser_state!("struct-decl", "struct")
668 );
669 let (name_loc, struct_name) = consume_token!(tokens,
670 Token::Identifier(i) => Ident(i),
671 parser_state!("struct-decl", "name"));
672
673 let type_params = if peek_token!(
674 tokens,
675 |tok| match tok {
676 Token::LParen => true,
677
678 _ => false,
679 },
680 parser_state!("struct-decl", "type-parameters?")
681 ) {
682 Some(type_param_list(tokens)?)
683 } else {
684 None
685 };
686
687 let where_clause = if peek_token!(
688 tokens,
689 |tok| match tok {
690 Token::Where => true,
691 _ => false,
692 },
693 parser_state!("struct-decl", "where-clause?")
694 ) {
695 Some(production!(
696 where_clause(tokens),
697 parser_state!("struct-decl", "where-clause")
698 ))
699 } else {
700 None
701 };
702
703 let _lbrace = consume_token!(
704 tokens,
705 Token::LBrace,
706 parser_state!("struct-decl", "fields lbrace")
707 );
708
709 let body = if peek_token!(
711 tokens,
712 |tok| match tok {
713 Token::RBrace => false,
714 _ => true,
715 },
716 parser_state!("struct-decl", "fields rbrace")
717 ) {
718 let body = production!(
719 struct_field_list(tokens),
720 parser_state!("struct-decl", "field-list")
721 );
722 StructBody(Some(body))
723 } else {
724 StructBody(None)
726 };
727
728 let (rloc, _) = consume_token!(
730 tokens,
731 Token::RBrace,
732 parser_state!("struct-decl", "fields rbrace")
733 );
734
735 let overall_span = LocationSpan::combine(struct_loc, rloc);
736
737 Ok(AstNode::new(
738 Struct {
739 name: AstNode::new(struct_name, name_loc),
740 body: body,
741 annotations: anns,
742 type_params: type_params,
743 where_clause: where_clause,
744 },
745 overall_span,
746 ))
747}
748
749fn struct_field_list(
750 tokens: &mut BufferedTokenizer,
751) -> ParseErr<Vec<StructField>> {
752 let mut list = vec![production!(
753 struct_field(tokens),
754 parser_state!("struct-field-list", "struct-field")
755 )];
756
757 loop {
758 if peek_token!(
759 tokens,
760 |tok| match tok {
761 Token::Comma => true,
762 _ => false,
763 },
764 parser_state!("struct-field-list", "comma separator")
765 ) {
766 let _comma = consume_token!(
767 tokens,
768 Token::Comma,
769 parser_state!("struct-field-list", "comma separator")
770 );
771 if peek_token!(
772 tokens,
773 |tok| match tok {
774 Token::RBrace => false,
775 _ => true,
776 },
777 parser_state!("struct-field-list", "rbrace")
778 ) {
779 list.push(production!(
780 struct_field(tokens),
781 parser_state!("struct-field-list", "struct-field")
782 ));
783 continue;
784 }
785 }
786
787 break;
788 }
789
790 Ok(list)
791}
792
793fn struct_field(tokens: &mut BufferedTokenizer) -> ParseErr<StructField> {
794 let (idloc, ident) = consume_token!(tokens,
795 Token::Identifier(i) => Ident(i),
796 parser_state!("struct-field", "name"));
797 let _colon = consume_token!(
798 tokens,
799 Token::Colon,
800 parser_state!("struct-field", "field type colon")
801 );
802 let ann = production!(
803 type_annotation(tokens),
804 parser_state!("struct-field", "type annotation")
805 );
806
807 Ok(StructField {
808 name: AstNode::new(ident, idloc),
809 field_type: ann,
810 })
811}
812
813fn module_decl(tokens: &mut BufferedTokenizer) -> ParseErr<AstNode<Ident>> {
814 let (modloc, _) =
816 consume_token!(tokens, Token::Mod, parser_state!("mod-decl", "mod"));
817 let (_idloc, ident) = consume_token!(tokens,
818 Token::Identifier(i) => Ident(i),
819 parser_state!("mod-decl", "name"));
820 let (semiloc, _) = consume_token!(
821 tokens,
822 Token::Semi,
823 parser_state!("mod-decl", "semicolon")
824 );
825
826 let span = LocationSpan::combine(modloc, semiloc);
827 Ok(AstNode::new(ident, span))
828}
829
830pub fn type_annotation(
831 tokens: &mut BufferedTokenizer,
832) -> ParseErr<AstNode<TypeAnnotation>> {
833 enum TypeAnnDec {
834 Module,
835 FnType,
836 ArrayType,
837 WidthConstraint,
838 Err,
839 }
840
841 match peek_token!(
842 tokens,
843 |tok| match tok {
844 Token::Fn => TypeAnnDec::FnType,
845 Token::Identifier(_) => TypeAnnDec::Module,
846 Token::LBracket => TypeAnnDec::ArrayType,
847 Token::Base => TypeAnnDec::WidthConstraint,
848 Token::LBrace => TypeAnnDec::WidthConstraint,
849
850 _ => TypeAnnDec::Err,
851 },
852 parser_state!("type-annotation", "annotation-kind")
853 ) {
854 TypeAnnDec::Module => {
855 let (bind, span) = production!(
856 module_binding(tokens),
857 parser_state!("type-annotation", "module-binding")
858 )
859 .to_data();
860
861 let bind = if peek_token!(
862 tokens,
863 |tok| match tok {
864 Token::LParen => true,
865 _ => false,
866 },
867 parser_state!("type-annotation", "type-arguments")
868 ) {
869 let type_arg_list = production!(
870 type_arg_list(tokens),
871 parser_state!("type-annotation", "type-app")
872 );
873
874 TypedPath::Parameterized(bind, type_arg_list)
875 } else {
876 TypedPath::NillArity(bind)
877 };
878
879 Ok(AstNode::new(TypeAnnotation::Path(bind), span))
880 }
881
882 TypeAnnDec::FnType => Ok(production!(
883 fn_type(tokens),
884 parser_state!("type-annotation", "fn-type")
885 )),
886
887 TypeAnnDec::ArrayType => Ok(production!(
888 array_type(tokens),
889 parser_state!("type-annotation", "array-type")
890 )),
891
892 TypeAnnDec::WidthConstraint => {
893 let constraints = production!(
894 width_constraint_list(tokens),
895 parser_state!("type-annotation", "width-constraint-list")
896 );
897
898 let (constraints, constraints_span) = constraints.to_data();
899
900 Ok(AstNode::new(
901 TypeAnnotation::WidthConstraint(constraints),
902 constraints_span,
903 ))
904 }
905
906 TypeAnnDec::Err => unimplemented!(),
907 }
908}
909
910fn width_constraint_list(
911 tokens: &mut BufferedTokenizer,
912) -> ParseErr<AstNode<Vec<AstNode<WidthConstraint>>>> {
913 let first = production!(
914 width_constraint(tokens),
915 parser_state!("width-constraint-list", "constraint[0]")
916 );
917
918 let mut span = first.span();
919 let mut constraints = vec![first];
920 let mut counter = 1;
921 while peek_token!(
922 tokens,
923 |tok| match tok {
924 Token::Plus => true,
925 _ => false,
926 },
927 parser_state!(
928 "width-constraint-list",
929 &format!("peek-constraint[{}]", counter)
930 )
931 ) {
932 let _plus = consume_token!(
933 tokens,
934 Token::Plus,
935 parser_state!("width-constraint-list", "constraint-concat")
936 );
937 let next_constraint = production!(
938 width_constraint(tokens),
939 parser_state!(
940 "width-constraint-list",
941 &format!("constraint[{}]", counter)
942 )
943 );
944
945 span = LocationSpan::combine(span, next_constraint.span());
946 constraints.push(next_constraint);
947
948 counter += 1;
949 }
950
951 let constraints = AstNode::new(constraints, span);
952 Ok(constraints)
953}
954
955fn width_constraint(
956 tokens: &mut BufferedTokenizer,
957) -> ParseErr<AstNode<WidthConstraint>> {
958 enum WCDec {
959 Base,
960 Anon,
961 Error(Token),
962 }
963
964 match peek_token!(
965 tokens,
966 |tok| match tok {
967 Token::LBrace => WCDec::Anon,
968 Token::Base => WCDec::Base,
969 _ => WCDec::Error(tok.clone()),
970 },
971 parser_state!("width-constraint", "constraint-peek")
972 ) {
973 WCDec::Base => {
974 let (base_loc, _) = consume_token!(
975 tokens,
976 Token::Base,
977 parser_state!("width-constraint", "base")
978 );
979 let (name, name_loc) = production!(
980 type_annotation(tokens),
981 parser_state!("width-constraint", "constraint-base")
982 )
983 .to_data();
984
985 let span = LocationSpan::combine(base_loc, name_loc.clone());
986
987 let constraint = AstNode::new(
988 WidthConstraint::BaseStruct(AstNode::new(name, name_loc)),
989 span,
990 );
991
992 Ok(constraint)
993 }
994
995 WCDec::Anon => {
996 let (l_loc, _) = consume_token!(
997 tokens,
998 Token::LBrace,
999 parser_state!("width-constraint", "anonymous-open")
1000 );
1001 let fields = production!(
1002 struct_field_list(tokens),
1003 parser_state!("width-constraint", "anonymous-struct")
1004 )
1005 .into_iter()
1006 .map(|struct_field| (struct_field.name, struct_field.field_type))
1007 .collect();
1008
1009 let (r_loc, _) = consume_token!(
1010 tokens,
1011 Token::RBrace,
1012 parser_state!("width-constraint", "anonymous-close")
1013 );
1014 let span = LocationSpan::combine(l_loc, r_loc);
1015 let constraint =
1016 AstNode::new(WidthConstraint::Anonymous(fields), span);
1017
1018 Ok(constraint)
1019 }
1020
1021 WCDec::Error(tok) => panic!("{}", tok),
1022 }
1023}
1024
1025pub fn module_binding(
1026 tokens: &mut BufferedTokenizer,
1027) -> ParseErr<AstNode<ModulePath>> {
1028 let mut path = Vec::new();
1029 let (floc, first) = consume_token!(tokens,
1030 Token::Identifier(i) => Ident(i),
1031 parser_state!("module-binding", "root"));
1032
1033 let mut binding_span = floc.clone();
1034 path.push(AstNode::new(first, floc));
1035
1036 if peek_token!(
1037 tokens,
1038 |tok| match tok {
1039 Token::ColonColon => true,
1040 _ => false,
1041 },
1042 parser_state!("module-binding", "segment coloncolon")
1043 ) {
1044 let _coloncolon = consume_token!(
1045 tokens,
1046 Token::ColonColon,
1047 parser_state!("module-binding", "segment coloncolon")
1048 );
1049 let (nloc, next) = consume_token!(tokens,
1050 Token::Identifier(i) => Ident(i),
1051 parser_state!("module-binding", "segment name"));
1052 path.push(AstNode::new(next, nloc.clone()));
1053 binding_span = LocationSpan::combine(binding_span, nloc);
1054 }
1055
1056 Ok(AstNode::new(ModulePath(path), binding_span))
1057}
1058
1059fn array_type(
1060 tokens: &mut BufferedTokenizer,
1061) -> ParseErr<AstNode<TypeAnnotation>> {
1062 let (lloc, _) = consume_token!(
1063 tokens,
1064 Token::LBracket,
1065 parser_state!("array-type", "lbracket")
1066 );
1067 let base_type = Box::new(production!(
1068 type_annotation(tokens),
1069 parser_state!("array-type", "base-type")
1070 ));
1071 let _semi = consume_token!(
1072 tokens,
1073 Token::Semi,
1074 parser_state!("array-type", "semicolon")
1075 );
1076 let (_, number) = consume_token!(tokens,
1077 Token::IntLiteral(i) => i,
1078 parser_state!("array-type", "array size"));
1079 let (rloc, _) = consume_token!(
1080 tokens,
1081 Token::RBracket,
1082 parser_state!("array-type", "rbracket")
1083 );
1084
1085 let array_type_span = LocationSpan::combine(lloc, rloc);
1086
1087 if number <= 0 {
1088 unimplemented!(
1089 "Parser error: number of elements must be greater than 0. Found {}",
1090 number
1091 );
1092 }
1093
1094 Ok(AstNode::new(
1095 TypeAnnotation::Array(base_type, number as u64),
1096 array_type_span,
1097 ))
1098}
1099
1100fn fn_type(
1101 tokens: &mut BufferedTokenizer,
1102) -> ParseErr<AstNode<TypeAnnotation>> {
1103 let (fnloc, _) =
1104 consume_token!(tokens, Token::Fn, parser_state!("fn-type", "fn"));
1105 let _lparen = consume_token!(
1106 tokens,
1107 Token::LParen,
1108 parser_state!("fn-type", "(type?)param lparen")
1109 );
1110
1111 let type_params = if peek_token!(
1112 tokens,
1113 |tok| match tok {
1114 Token::Type => true,
1115 _ => false,
1116 },
1117 parser_state!("fn-type", "type?")
1118 ) {
1119 let type_params = production!(
1120 type_param_list_post_lparen(tokens),
1121 parser_state!("fn-type", "type-params")
1122 );
1123
1124 let _lparen = consume_token!(
1126 tokens,
1127 Token::LParen,
1128 parser_state!("fn-type", "param lparen")
1129 );
1130
1131 Some(type_params)
1132 } else {
1133 None
1134 };
1135
1136 let mut params = None;
1137 if peek_token!(
1138 tokens,
1139 |tok| match tok {
1140 Token::RParen => false,
1141 _ => true,
1142 },
1143 parser_state!("fn-type", "param rparen")
1144 ) {
1145 params = Some(production!(
1146 fn_type_params(tokens),
1147 parser_state!("fn-type", "fn-type-params")
1148 ));
1149 }
1150
1151 let (rparenloc, _) = consume_token!(
1152 tokens,
1153 Token::RParen,
1154 parser_state!("fn-type", "param rparen")
1155 );
1156
1157 let mut fn_type_span = LocationSpan::combine(fnloc, rparenloc);
1158
1159 let mut return_type = None;
1160 if peek_token!(
1161 tokens,
1162 |tok| match tok {
1163 Token::Arrow => true,
1164 _ => false,
1165 },
1166 parser_state!("fn-type", "return type arrow")
1167 ) {
1168 let _arrow = consume_token!(
1169 tokens,
1170 Token::Arrow,
1171 parser_state!("fn-type", "return type arrow")
1172 );
1173 let ret = production!(
1174 type_annotation(tokens),
1175 parser_state!("fn-type", "return type")
1176 );
1177 let return_span = ret.span();
1178
1179 return_type = Some(Box::new(ret));
1180 fn_type_span = Span::combine(fn_type_span, return_span);
1181 }
1182
1183 Ok(AstNode::new(
1184 TypeAnnotation::FnType(type_params, params, return_type),
1185 fn_type_span,
1186 ))
1187}
1188
1189fn fn_type_params(
1190 tokens: &mut BufferedTokenizer,
1191) -> ParseErr<Vec<AstNode<TypeAnnotation>>> {
1192 let mut list = vec![production!(
1193 type_annotation(tokens),
1194 parser_state!("fn-type-params", "param-type")
1195 )];
1196
1197 loop {
1198 if peek_token!(
1199 tokens,
1200 |tok| match tok {
1201 Token::Comma => true,
1202 _ => false,
1203 },
1204 parser_state!("fn-type-params", "comma separator")
1205 ) {
1206 let _comma = consume_token!(
1207 tokens,
1208 Token::Comma,
1209 parser_state!("fn-type-params", "comma separator")
1210 );
1211 if peek_token!(
1212 tokens,
1213 |tok| match tok {
1214 Token::RParen => false,
1215 _ => true,
1216 },
1217 parser_state!("fn-type-params", "rparen")
1218 ) {
1219 list.push(production!(
1220 type_annotation(tokens),
1221 parser_state!("fn-type-params", "param-type")
1222 ));
1223 continue;
1224 }
1225 }
1226
1227 break;
1228 }
1229
1230 Ok(list)
1231}
1232
1233pub fn block(tokens: &mut BufferedTokenizer) -> ParseErr<AstNode<Block>> {
1234 let (lloc, _) =
1235 consume_token!(tokens, Token::LBrace, parser_state!("block", "lbrace"));
1236
1237 let mut stmts = Vec::new();
1238 while peek_token!(
1240 tokens,
1241 |tok| match tok {
1242 Token::RBrace => false,
1243 _ => true,
1244 },
1245 parser_state!("block", "rbrace")
1246 ) {
1247 stmts.push(production!(stmt(tokens), parser_state!("block", "stmt")));
1248 }
1249
1250 let (rloc, _) =
1251 consume_token!(tokens, Token::RBrace, parser_state!("block", "rbrace"));
1252
1253 let span = LocationSpan::combine(lloc, rloc);
1254
1255 let block = Block(stmts);
1256
1257 Ok(AstNode::new(block, span))
1258}
1259
1260#[cfg(test)]
1261pub fn teststmt(tokens: &mut BufferedTokenizer) -> ParseErr<Stmt> {
1262 stmt(tokens)
1263}
1264
1265fn stmt(tokens: &mut BufferedTokenizer) -> ParseErr<Stmt> {
1266 enum StmtDec {
1267 Continue,
1268 Break,
1269 Return,
1270
1271 While,
1272 If,
1273
1274 LocalVar,
1275 PotentialAssign,
1276
1277 Expr,
1278 }
1279
1280 let stmt = match peek_token!(
1281 tokens,
1282 |tok| match tok {
1283 Token::Continue => StmtDec::Continue,
1284 Token::Break => StmtDec::Break,
1285 Token::Return => StmtDec::Return,
1286
1287 Token::While => StmtDec::While,
1288 Token::If => StmtDec::If,
1289
1290 Token::Let => StmtDec::LocalVar,
1291
1292 Token::Identifier(_) => StmtDec::PotentialAssign,
1293
1294 _ => StmtDec::Expr,
1295 },
1296 parser_state!("stmt", "stmt kind")
1297 ) {
1298 StmtDec::Continue => Stmt::ExprStmt(production!(
1299 continue_stmt(tokens),
1300 parser_state!("stmt", "continue")
1301 )),
1302
1303 StmtDec::Break => Stmt::ExprStmt(production!(
1304 break_stmt(tokens),
1305 parser_state!("stmt", "break")
1306 )),
1307
1308 StmtDec::Return => Stmt::ExprStmt(production!(
1309 return_stmt(tokens),
1310 parser_state!("stmt", "return")
1311 )),
1312
1313 StmtDec::While => Stmt::ExprStmt(production!(
1314 while_stmt(tokens),
1315 parser_state!("stmt", "while")
1316 )),
1317
1318 StmtDec::If => Stmt::ExprStmt(production!(
1319 if_stmt(tokens),
1320 parser_state!("stmt", "if")
1321 )),
1322
1323 StmtDec::LocalVar => Stmt::ExprStmt(production!(
1324 local_var_decl(tokens),
1325 parser_state!("stmt", "local-var-decl")
1326 )),
1327
1328 StmtDec::PotentialAssign => production!(
1329 potential_assign(tokens),
1330 parser_state!("stmt", "potential-assign")
1331 ),
1332
1333 StmtDec::Expr => {
1334 let expr = production!(
1335 piped_expr(tokens, &[Delimiter::Semi]),
1336 parser_state!("stmt", "stmt-expr")
1337 );
1338
1339 let _semi = consume_token!(
1340 tokens,
1341 Token::Semi,
1342 parser_state!("stmt-expr", "semicolon")
1343 );
1344
1345 Stmt::Expr(expr)
1346 }
1347 };
1348
1349 Ok(stmt)
1350}
1351
1352fn potential_assign(tokens: &mut BufferedTokenizer) -> ParseErr<Stmt> {
1353 enum Dec {
1354 AccessPath,
1355 ModulePath,
1356 FnCallOrTypeArgFnCall,
1357 Indexing,
1358 DefSingletonAssignment,
1359 DefSingletonExpr,
1360 }
1361
1362 enum PathDec {
1363 Assign,
1364 Expr,
1365 }
1366
1367 let (base_span, base_ident) = consume_token!(tokens,
1368 Token::Identifier(ident) => Ident(ident),
1369 parser_state!("potential-assign", "root"));
1370
1371 let path = match peek_token!(
1376 tokens,
1377 |tok| match tok {
1378 Token::Dot => Dec::AccessPath,
1379 Token::ColonColon => Dec::ModulePath,
1380 Token::LParen => Dec::FnCallOrTypeArgFnCall,
1381 Token::LBracket => Dec::Indexing,
1382 Token::Assign => Dec::DefSingletonAssignment,
1383 _ => Dec::DefSingletonExpr,
1384 },
1385 parser_state!("potential-assign", "lhs kind")
1386 ) {
1387 Dec::AccessPath => {
1388 let span = base_span;
1389 let root = PathSegment::Ident(AstNode::new(base_ident, span));
1390
1391 let (path, _span) = production!(
1392 access_path(tokens, root),
1393 parser_state!("potential-assign", "access-path")
1394 )
1395 .to_data();
1396
1397 match path {
1398 Expr::FieldAccess(path) => path,
1399 _ => unreachable!(),
1400 }
1401 }
1402
1403 Dec::ModulePath => {
1404 let path = production!(
1408 expr_module_path(tokens, base_ident, base_span),
1409 parser_state!("stmt-expr-module-path", "module-path")
1410 );
1411
1412 let expr = production!(
1413 prebase_piped_expr(tokens, path, &[Delimiter::Semi]),
1414 parser_state!("stmt-expr-module-path", "expr")
1415 );
1416
1417 let _semi = consume_token!(
1418 tokens,
1419 Token::Semi,
1420 parser_state!("stmt-expr-module-path", "semicolon")
1421 );
1422
1423 return Ok(Stmt::Expr(expr));
1424 }
1425
1426 Dec::FnCallOrTypeArgFnCall => {
1427 let path =
1431 ModulePath(vec![AstNode::new(base_ident, base_span.clone())]);
1432 let path_span = base_span.clone();
1433
1434 let (lspan, _lparen) = consume_token!(
1435 tokens,
1436 Token::LParen,
1437 parser_state!("stmt-expr-potential-fn-call", "lparen")
1438 );
1439
1440 let (type_args, args, args_span) = if peek_token!(
1441 tokens,
1442 |tok| match tok {
1443 Token::Type => true,
1444 _ => false,
1445 },
1446 parser_state!("stmt-expr-potential-fn-call", "type-args?")
1447 ) {
1448 let type_args = production!(
1449 type_arg_list_post_lparen(tokens),
1450 parser_state!("stmt-expr-fn-call", "type-args")
1451 );
1452
1453 enum LocalDec {
1454 TypeApp,
1455 FnCall,
1456 Err,
1457 }
1458
1459 match peek_token!(
1461 tokens,
1462 |tok| match tok {
1463 Token::LParen => LocalDec::FnCall,
1464 Token::Semi => LocalDec::TypeApp,
1465
1466 _ => LocalDec::Err,
1467 },
1468 parser_state!(
1469 "stmt-expr-fn-call-or-type-app?",
1470 "fn-call-lparen"
1471 )
1472 ) {
1473 LocalDec::TypeApp => {
1474 let _semi = consume_token!(
1477 tokens,
1478 Token::Semi,
1479 parser_state!("stmt-expr-type-app", "semicolon")
1480 );
1481 let typed_path =
1482 TypedPath::Parameterized(path, type_args);
1483 let typed_path =
1484 Expr::Path(AstNode::new(typed_path, path_span.clone()));
1485 return Ok(Stmt::Expr(AstNode::new(
1486 typed_path, path_span,
1487 )));
1488 }
1489
1490 LocalDec::FnCall => (),
1491
1492 LocalDec::Err => unimplemented!(
1493 "Unexpected token: {:?}",
1494 tokens.next().unwrap()
1495 ),
1496 }
1497
1498 let (args, args_span) = production!(
1499 fn_args(tokens),
1500 parser_state!("expr-module-path", "fn-call")
1501 )
1502 .to_data();
1503
1504 (Some(type_args), args, args_span)
1505 } else {
1506 let (args, args_span) = production!(
1507 fn_args_post_lparen(tokens, lspan),
1508 parser_state!("stmt-expr-fn-call", "fn-args")
1509 )
1510 .to_data();
1511
1512 (None, args, args_span)
1513 };
1514
1515 let args =
1516 args.map(|v| v.into_iter().map(|a| a.to_data().0).collect());
1517
1518 let fn_path = match type_args {
1519 Some(args) => TypedPath::Parameterized(path, args),
1520 None => TypedPath::NillArity(path),
1521 };
1522
1523 let fn_call = FnCall {
1524 path: AstNode::new(fn_path, base_span.clone()),
1525 args: args,
1526 };
1527
1528 let span = Span::combine(base_span, args_span);
1529 let expr_base = AstNode::new(fn_call, span.clone());
1530 let expr_base = AstNode::new(Expr::FnCall(expr_base), span);
1531
1532 let expr = production!(
1533 prebase_piped_expr(tokens, expr_base, &[Delimiter::Semi]),
1534 parser_state!("stmt-expr-fn-call", "expr")
1535 );
1536
1537 let _semi = consume_token!(
1538 tokens,
1539 Token::Semi,
1540 parser_state!("stmt-expr-fn-call", "semicolon")
1541 );
1542
1543 return Ok(Stmt::Expr(expr));
1544 }
1545
1546 Dec::Indexing => {
1547 let _lbracket = consume_token!(
1548 tokens,
1549 Token::LBracket,
1550 parser_state!("potential_assign-indexing", "lbracket")
1551 );
1552 let indexer = production!(
1553 piped_expr(tokens, &[Delimiter::RBracket]),
1554 parser_state!("potential_assign-indexing", "indexer-expr")
1555 );
1556 let (indexer, _) = indexer.to_data();
1557 let (_rspan, _rbracket) = consume_token!(
1558 tokens,
1559 Token::RBracket,
1560 parser_state!("potential_assign-indexing", "rbracket")
1561 );
1562
1563 if peek_token!(
1564 tokens,
1565 |tok| match tok {
1566 Token::Dot => true,
1567 _ => false,
1568 },
1569 parser_state!("potential-assign", "is-access-path")
1570 ) {
1571 let span = base_span;
1573 let root = PathSegment::Indexing(
1574 AstNode::new(base_ident, span),
1575 Box::new(indexer),
1576 );
1577
1578 let (path, _span) = production!(
1579 access_path(tokens, root),
1580 parser_state!("potential-assign", "access-path")
1581 )
1582 .to_data();
1583 match path {
1584 Expr::FieldAccess(path) => path,
1585 _ => unreachable!(),
1586 }
1587 } else {
1588 let span = base_span;
1590 let root = PathSegment::Indexing(
1591 AstNode::new(base_ident, span.clone()),
1592 Box::new(indexer),
1593 );
1594
1595 let path = vec![root];
1596 let path = Path(path);
1597
1598 AstNode::new(path, span)
1599 }
1600 }
1601
1602 Dec::DefSingletonAssignment => {
1603 let _assignop = consume_token!(
1604 tokens,
1605 Token::Assign,
1606 parser_state!("assignment", "=")
1607 );
1608
1609 let value = production!(
1610 piped_expr(tokens, &[Delimiter::Semi]),
1611 parser_state!("assignment", "value")
1612 );
1613 let (value, value_span) = value.to_data();
1614
1615 let _semi = consume_token!(
1616 tokens,
1617 Token::Semi,
1618 parser_state!("assignment", "semicolon")
1619 );
1620
1621 let segment =
1622 PathSegment::Ident(AstNode::new(base_ident, base_span.clone()));
1623 let path = vec![segment];
1624 let path = AstNode::new(Path(path), base_span.clone());
1625
1626 let assignment_span = Span::combine(base_span, value_span);
1627 let assignment = Assignment {
1628 name: path,
1629 value: value,
1630 };
1631
1632 let assignment = ExprStmt::Assignment(assignment);
1633
1634 return Ok(Stmt::ExprStmt(AstNode::new(
1635 assignment,
1636 assignment_span,
1637 )));
1638 }
1639
1640 Dec::DefSingletonExpr => {
1641 let _span = base_span;
1644 let expr = production!(
1645 piped_expr(tokens, &[Delimiter::Semi]),
1646 parser_state!("expr-stmt-singleton", "expr")
1647 );
1648
1649 let _semi = consume_token!(
1650 tokens,
1651 Token::Semi,
1652 parser_state!("expr-stmt-singleton", "semicolon")
1653 );
1654
1655 return Ok(Stmt::Expr(expr));
1656 }
1657 };
1658
1659 match peek_token!(
1663 tokens,
1664 |tok| match tok {
1665 Token::Assign => PathDec::Assign,
1666 _ => PathDec::Expr,
1667 },
1668 parser_state!("full-path-potential-assign", "=;")
1669 ) {
1670 PathDec::Assign => {
1671 let path = path;
1672
1673 let _assign = consume_token!(
1674 tokens,
1675 Token::Assign,
1676 parser_state!("assignment", "=")
1677 );
1678
1679 let (value, value_span) = production!(
1680 piped_expr(tokens, &[Delimiter::Semi]),
1681 parser_state!("assignment", "expr")
1682 )
1683 .to_data();
1684
1685 let _semi = consume_token!(
1686 tokens,
1687 Token::Semi,
1688 parser_state!("assignment", "semicolon")
1689 );
1690
1691 let span = Span::combine(path.span(), value_span);
1692 let assignment = Assignment {
1693 name: path,
1694 value: value,
1695 };
1696
1697 Ok(Stmt::ExprStmt(AstNode::new(
1698 ExprStmt::Assignment(assignment),
1699 span,
1700 )))
1701 }
1702
1703 PathDec::Expr => {
1704 let _span = path.span();
1705 let _path = Expr::FieldAccess(path);
1706
1707 let expr = production!(
1708 piped_expr(tokens, &[Delimiter::Semi]),
1709 parser_state!("stmt-expr-path", "expr")
1710 );
1711
1712 let _semi = consume_token!(
1713 tokens,
1714 Token::Semi,
1715 parser_state!("stmt-expr-path", "semicolon")
1716 );
1717
1718 Ok(Stmt::Expr(expr))
1719 }
1720 }
1721}
1722
1723fn local_var_decl(
1724 tokens: &mut BufferedTokenizer,
1725) -> ParseErr<AstNode<ExprStmt>> {
1726 let (letloc, _) = consume_token!(
1727 tokens,
1728 Token::Let,
1729 parser_state!("local-var-decl", "let")
1730 );
1731
1732 let (iloc, ident) = consume_token!(tokens,
1733 Token::Identifier(i) => Ident(i),
1734 parser_state!("local-var-decl", "name"));
1735 let ident = AstNode::new(ident, iloc);
1736
1737 let mut type_anno = None;
1738
1739 if peek_token!(
1740 tokens,
1741 |tok| match tok {
1742 Token::Colon => true,
1743 _ => false,
1744 },
1745 parser_state!("local-var-decl", "type colon")
1746 ) {
1747 let _colon = consume_token!(
1748 tokens,
1749 Token::Colon,
1750 parser_state!("local-var-decl", "type colon")
1751 );
1752 type_anno = Some(production!(
1753 type_annotation(tokens),
1754 parser_state!("local-var-decl", "type annotation")
1755 ));
1756 }
1757
1758 let _assign = consume_token!(
1759 tokens,
1760 Token::Assign,
1761 parser_state!("local-var-decl", "=")
1762 );
1763
1764 let init_value = production!(
1765 piped_expr(tokens, &[Delimiter::Semi]),
1766 parser_state!("local-var-decl", "value")
1767 )
1768 .to_data();
1769
1770 let (semiloc, _) = consume_token!(
1771 tokens,
1772 Token::Semi,
1773 parser_state!("local-var-decl", "semicolon")
1774 );
1775
1776 let span = LocationSpan::combine(letloc, semiloc);
1777
1778 let local_var_decl = LocalVarDecl {
1779 var_type: type_anno,
1780 var_name: ident,
1781 var_init: init_value.0,
1782 };
1783
1784 Ok(AstNode::new(ExprStmt::LocalVarDecl(local_var_decl), span))
1785}
1786
1787fn if_stmt(tokens: &mut BufferedTokenizer) -> ParseErr<AstNode<ExprStmt>> {
1788 enum IfDec {
1789 Elif,
1790 Else,
1791 End,
1792 }
1793
1794 let (ifloc, _) =
1795 consume_token!(tokens, Token::If, parser_state!("if-stmt", "if"));
1796
1797 let mut end = ifloc.clone();
1798
1799 let first_branch = production!(
1800 if_branch(tokens),
1801 parser_state!("if-stmt", "first branch")
1802 );
1803 end = first_branch.block.span();
1804
1805 let mut branches = vec![first_branch];
1806 let mut default_branch = None;
1807
1808 loop {
1809 match peek_token!(
1810 tokens,
1811 |tok| match tok {
1812 Token::Elif => IfDec::Elif,
1813 Token::Else => IfDec::Else,
1814
1815 _ => IfDec::End,
1816 },
1817 parser_state!("if-stmt", "branches")
1818 ) {
1819 IfDec::Elif => {
1820 let _elif = consume_token!(
1821 tokens,
1822 Token::Elif,
1823 parser_state!("if-stmt", "elif")
1824 );
1825
1826 let branch = production!(
1827 if_branch(tokens),
1828 parser_state!("if-stmt", "elif branch")
1829 );
1830 end = branch.block.span();
1831
1832 branches.push(branch);
1833 }
1834
1835 IfDec::Else => {
1836 let _else = consume_token!(
1837 tokens,
1838 Token::Else,
1839 parser_state!("if-stmt", "else")
1840 );
1841 let block = production!(
1842 block(tokens),
1843 parser_state!("if-stmt", "else-block")
1844 );
1845
1846 end = block.span();
1847 default_branch = Some(block);
1848
1849 break;
1850 }
1851
1852 IfDec::End => break,
1853 }
1854 }
1855
1856 let span = Span::combine(ifloc, end);
1857
1858 let if_stmt = If {
1859 branches: branches,
1860 default_block: default_branch,
1861 };
1862
1863 Ok(AstNode::new(ExprStmt::If(if_stmt), span))
1864}
1865
1866fn if_branch(tokens: &mut BufferedTokenizer) -> ParseErr<Branch> {
1867 let conditional = piped_expr(tokens, &[Delimiter::LBrace])?;
1868
1869 let block = production!(block(tokens), parser_state!("if-branch", "block"));
1870
1871 let branch = Branch {
1872 conditional: conditional,
1873 block: block,
1874 };
1875
1876 Ok(branch)
1877}
1878
1879fn while_stmt(tokens: &mut BufferedTokenizer) -> ParseErr<AstNode<ExprStmt>> {
1880 let (whileloc, _) = consume_token!(
1881 tokens,
1882 Token::While,
1883 parser_state!("while-stmt", "while")
1884 );
1885
1886 let conditional = production!(
1887 piped_expr(tokens, &[Delimiter::LBrace]),
1888 parser_state!("while-stmt", "condition")
1889 );
1890
1891 let block =
1892 production!(block(tokens), parser_state!("while-stmt", "block"));
1893
1894 let span = Span::combine(whileloc, block.span());
1895
1896 let while_stmt = While {
1897 conditional: conditional,
1898 block: block,
1899 };
1900
1901 Ok(AstNode::new(ExprStmt::While(while_stmt), span))
1902}
1903
1904fn return_stmt(tokens: &mut BufferedTokenizer) -> ParseErr<AstNode<ExprStmt>> {
1905 let (returnloc, _) = consume_token!(
1906 tokens,
1907 Token::Return,
1908 parser_state!("return-stmt", "return")
1909 );
1910
1911 let mut end = returnloc.clone();
1912
1913 let expr = if peek_token!(
1914 tokens,
1915 |tok| match tok {
1916 Token::Semi => true,
1917 _ => false,
1918 },
1919 parser_state!("return-stmt", "semi-colon")
1920 ) {
1921 let (semiloc, _) = consume_token!(
1923 tokens,
1924 Token::Semi,
1925 parser_state!("return-stmt", "semicolon")
1926 );
1927 end = semiloc;
1928
1929 None
1930 } else {
1931 let expr = production!(
1933 piped_expr(tokens, &[Delimiter::Semi]),
1934 parser_state!("return-stmt", "expr")
1935 );
1936
1937 let _semi = consume_token!(
1938 tokens,
1939 Token::Semi,
1940 parser_state!("return-stmt", "semicolon")
1941 );
1942
1943 end = expr.span();
1944
1945 Some(expr)
1946 };
1947
1948 let span = Span::combine(returnloc, end);
1949 Ok(AstNode::new(
1950 ExprStmt::Return(span.clone(), expr.map(|e| e.to_data().0)),
1951 span,
1952 ))
1953}
1954
1955fn continue_stmt(
1956 tokens: &mut BufferedTokenizer,
1957) -> ParseErr<AstNode<ExprStmt>> {
1958 let (contloc, _) = consume_token!(
1959 tokens,
1960 Token::Continue,
1961 parser_state!("continue-stmt", "continue")
1962 );
1963 let (semiloc, _) = consume_token!(
1964 tokens,
1965 Token::Semi,
1966 parser_state!("continue-stmt", "semicolon")
1967 );
1968
1969 let span = LocationSpan::combine(contloc, semiloc);
1970 Ok(AstNode::new(ExprStmt::Continue(span.clone()), span))
1971}
1972
1973fn break_stmt(tokens: &mut BufferedTokenizer) -> ParseErr<AstNode<ExprStmt>> {
1974 let (contloc, _) = consume_token!(
1975 tokens,
1976 Token::Break,
1977 parser_state!("break-stmt", "break")
1978 );
1979 let (semiloc, _) = consume_token!(
1980 tokens,
1981 Token::Semi,
1982 parser_state!("break-stmt", "semicolon")
1983 );
1984
1985 let span = LocationSpan::combine(contloc, semiloc);
1986 Ok(AstNode::new(ExprStmt::Break(span.clone()), span))
1987}
1988
1989fn type_param_list(tokens: &mut BufferedTokenizer) -> ParseErr<TypeParams> {
1990 let _lparen = consume_token!(
1991 tokens,
1992 Token::LParen,
1993 parser_state!("type_param_list", "lparen")
1994 );
1995
1996 type_param_list_post_lparen(tokens)
1997}
1998
1999fn type_param_list_post_lparen(
2000 tokens: &mut BufferedTokenizer,
2001) -> ParseErr<TypeParams> {
2002 let _type = consume_token!(
2003 tokens,
2004 Token::Type,
2005 parser_state!("type-param-list", "type")
2006 );
2007
2008 let mut type_params = vec![consume_token!(tokens,
2009 Token::Identifier(ident) => Ident(ident),
2010 parser_state!("type-param-list", "type-param"))];
2011
2012 loop {
2013 if peek_token!(
2014 tokens,
2015 |tok| match tok {
2016 Token::Comma => true,
2017 _ => false,
2018 },
2019 parser_state!("type-param-list", "comma-separator")
2020 ) {
2021 let _comma = consume_token!(
2022 tokens,
2023 Token::Comma,
2024 parser_state!("type-param-list", "comma-separator")
2025 );
2026 if peek_token!(
2027 tokens,
2028 |tok| match tok {
2029 Token::RParen => false,
2030 _ => true,
2031 },
2032 parser_state!("type-param-list", "rparen?")
2033 ) {
2034 type_params.push(consume_token!(tokens,
2035 Token::Identifier(ident) => Ident(ident),
2036 parser_state!("type-param-list", "type-param")));
2037 continue;
2038 }
2039 }
2040
2041 break;
2042 }
2043
2044 let _rparen = consume_token!(
2045 tokens,
2046 Token::RParen,
2047 parser_state!("type-param-list", "rparen")
2048 );
2049
2050 let type_params = type_params
2051 .into_iter()
2052 .map(|(span, ident)| AstNode::new(ident, span))
2053 .collect::<Vec<_>>();
2054
2055 Ok(TypeParams {
2056 params: type_params,
2057 })
2058}
2059
2060pub fn type_arg_list(
2061 tokens: &mut BufferedTokenizer,
2062) -> ParseErr<Vec<AstNode<TypeAnnotation>>> {
2063 let _lparen = consume_token!(
2064 tokens,
2065 Token::LParen,
2066 parser_state!("type-arg-list", "lparen")
2067 );
2068
2069 type_arg_list_post_lparen(tokens)
2070}
2071
2072pub fn type_arg_list_post_lparen(
2073 tokens: &mut BufferedTokenizer,
2074) -> ParseErr<Vec<AstNode<TypeAnnotation>>> {
2075 let _type = consume_token!(
2076 tokens,
2077 Token::Type,
2078 parser_state!("type-arg-list", "type")
2079 );
2080
2081 let mut type_args = vec![production!(
2082 type_annotation(tokens),
2083 parser_state!("type-arg-list", "type-arg")
2084 )];
2085
2086 loop {
2087 if peek_token!(
2088 tokens,
2089 |tok| match tok {
2090 Token::Comma => true,
2091 _ => false,
2092 },
2093 parser_state!("type-arg-list", "comma-separator")
2094 ) {
2095 let _comma = consume_token!(
2096 tokens,
2097 Token::Comma,
2098 parser_state!("type-arg-list", "comma-separator")
2099 );
2100 if peek_token!(
2101 tokens,
2102 |tok| match tok {
2103 Token::RParen => false,
2104 _ => true,
2105 },
2106 parser_state!("type-arg-list", "rparen?")
2107 ) {
2108 type_args.push(production!(
2109 type_annotation(tokens),
2110 parser_state!("type-arg-list", "type-arg")
2111 ));
2112 continue;
2113 }
2114 }
2115
2116 break;
2117 }
2118
2119 let _rparen = consume_token!(
2120 tokens,
2121 Token::RParen,
2122 parser_state!("type-arg-list", "rparen")
2123 );
2124
2125 Ok(type_args)
2126}