Skip to main content

nifty_syntax/parser/
item.rs

1//! Top-level declarations and type expressions.
2
3use super::{ParseResult, Parser};
4use crate::ast::{
5    Expr, ExprKind, FnDecl, Item, NamedElement, StateDecl, Stmt, StmtKind, StructDecl, TypeExpr,
6    TypeExprKind, TypedName, ViewDecl,
7};
8use crate::token::TokenKind;
9
10use super::expr::TrailingBlocks;
11
12impl Parser<'_> {
13    pub(super) fn parse_item(&mut self) -> ParseResult<Item> {
14        match self.peek() {
15            TokenKind::State => self.parse_state().map(Item::State),
16            TokenKind::Struct => self.parse_struct().map(Item::Struct),
17            TokenKind::Fn => self.parse_fn().map(Item::Fn),
18            TokenKind::View => self.parse_view().map(Item::View),
19            TokenKind::Ident if self.peek_nth(1) == TokenKind::Ident => {
20                self.parse_named().map(Item::Named)
21            }
22            _ => self.parse_stmt().map(Item::Stmt),
23        }
24    }
25
26    /// `element name(…) { … }`: the element's call, with a name between its element and
27    /// its arguments.
28    fn parse_named(&mut self) -> ParseResult<NamedElement> {
29        let start = self.current().span.start;
30        let element = self.expect_ident()?;
31        let name = self.expect_ident()?;
32        if !self.at(TokenKind::LParen) {
33            return self.unexpected("`(` after the name");
34        }
35        let callee = Expr {
36            kind: ExprKind::Name(element.name),
37            span: element.span,
38        };
39        let call = self.parse_call(callee, TrailingBlocks::Allowed)?;
40        Ok(NamedElement {
41            name,
42            call: Stmt {
43                kind: StmtKind::Expr(call),
44                span: self.span_from(start),
45            },
46        })
47    }
48
49    fn parse_state(&mut self) -> ParseResult<StateDecl> {
50        let start = self.bump().span.start;
51        let name = self.expect_ident()?;
52        let ty = self.parse_type_annotation()?;
53        self.expect(TokenKind::Eq)?;
54        let value = self.parse_expr(TrailingBlocks::Allowed)?;
55        Ok(StateDecl {
56            name,
57            ty,
58            value,
59            span: self.span_from(start),
60        })
61    }
62
63    fn parse_struct(&mut self) -> ParseResult<StructDecl> {
64        let start = self.bump().span.start;
65        let name = self.expect_ident()?;
66        self.expect(TokenKind::LBrace)?;
67        let mut fields = Vec::new();
68        loop {
69            self.skip_newlines();
70            if self.eat(TokenKind::RBrace).is_some() {
71                break;
72            }
73            fields.push(self.parse_typed_name()?);
74            match self.peek() {
75                TokenKind::Comma | TokenKind::Newline => {
76                    self.bump();
77                }
78                TokenKind::RBrace => {}
79                _ => return self.unexpected("`,` or a new line between fields"),
80            }
81        }
82        Ok(StructDecl {
83            name,
84            fields,
85            span: self.span_from(start),
86        })
87    }
88
89    fn parse_fn(&mut self) -> ParseResult<FnDecl> {
90        let start = self.bump().span.start;
91        let name = self.expect_ident()?;
92        self.expect(TokenKind::LParen)?;
93        let params = self.comma_list(TokenKind::RParen, Self::parse_typed_name)?;
94        let return_type = match self.eat(TokenKind::Arrow) {
95            Some(_) => Some(self.parse_type()?),
96            None => None,
97        };
98        let body = self.parse_block()?;
99        Ok(FnDecl {
100            name,
101            params,
102            return_type,
103            body,
104            span: self.span_from(start),
105        })
106    }
107
108    fn parse_view(&mut self) -> ParseResult<ViewDecl> {
109        let start = self.bump().span.start;
110        let name = self.expect_ident()?;
111        let params = match self.eat(TokenKind::LParen) {
112            Some(_) => self.comma_list(TokenKind::RParen, Self::parse_typed_name)?,
113            None => Vec::new(),
114        };
115        let body = self.parse_block()?;
116        Ok(ViewDecl {
117            name,
118            params,
119            body,
120            span: self.span_from(start),
121        })
122    }
123
124    fn parse_typed_name(&mut self) -> ParseResult<TypedName> {
125        let name = self.expect_ident()?;
126        self.expect(TokenKind::Colon)?;
127        let ty = self.parse_type()?;
128        Ok(TypedName { name, ty })
129    }
130
131    /// An optional `: Type`.
132    pub(super) fn parse_type_annotation(&mut self) -> ParseResult<Option<TypeExpr>> {
133        match self.eat(TokenKind::Colon) {
134            Some(_) => self.parse_type().map(Some),
135            None => Ok(None),
136        }
137    }
138
139    fn parse_type(&mut self) -> ParseResult<TypeExpr> {
140        let start = self.current().span.start;
141        let kind = match self.peek() {
142            TokenKind::Ident => {
143                let token = self.bump();
144                TypeExprKind::Named(self.text(token.span).to_owned())
145            }
146            TokenKind::LBracket => {
147                self.bump();
148                let element = self.parse_type()?;
149                self.expect(TokenKind::RBracket)?;
150                TypeExprKind::List(Box::new(element))
151            }
152            _ => return self.unexpected("a type"),
153        };
154        Ok(TypeExpr {
155            kind,
156            span: self.span_from(start),
157        })
158    }
159}