nifty_syntax/parser/
item.rs1use 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 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 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}