Skip to main content

smpl/parser/
parser.rs

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        // Found mod declaration
73        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            // No more commas
318            // Assume no more where clause constraints
319            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        // Consume next lparen for actual parameters
377        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    // Check if no struct fields
710    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        // Empty struct body
725        StructBody(None)
726    };
727
728    // Get Keys
729    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    // Consume MOD
815    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        // Consume parameter lparen
1125        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    // Parse for all statements untile '}'
1239    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    // Check if there is a full Access Path
1372    // If there is module path or function call, parse for expr ';'
1373    // If there is a 'ident = ...', parse for assignment
1374    // If there is a 'ident op ...', parse for expr ';'
1375    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            // Expecting: expr ';'
1405            // Module paths are not lvalues
1406
1407            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            // Expecting: expr ';'
1428            // Function calls are not lvalues
1429
1430            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                // Checks if a function call or a typed path
1460                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                        // TODO: type arg spans
1475                        // A type-app, NOT a function call
1476                        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                // Access path with indexing as root
1572                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                //Single indexing
1589                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            // Expecting: expr ';'
1642            // 'ident op' is not a lvalue
1643            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    // Found a full path
1660    // Check if it's an assignment or expression
1661
1662    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        // No expression
1922        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        // Expression
1932        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}