arrow_parser/
parse_stmt.rs1use crate::ast::Expression;
2use crate::ast::Node;
3use crate::ast::Statement;
4use crate::error::SyntaxErrorType;
5use crate::error::SyntaxResult;
6use crate::parse::Parser;
7use crate::symbol::ScopeType;
8use crate::token::TokenType;
9use crate::token::TokenTypeSet;
10
11impl<'a> Parser<'a> {
12 pub fn parse_stmt(&mut self, require_semicolon: bool) -> SyntaxResult<Node<Statement>> {
13 let stmt = match self.peek()?.typ {
14 TokenType::KeywordBreak => self.parse_stmt_break(),
15 TokenType::KeywordContinue => self.parse_stmt_continue(),
16 TokenType::KeywordFor => self.parse_stmt_for(),
17 TokenType::KeywordLet => self.parse_stmt_let(),
18 TokenType::KeywordLoop => self.parse_stmt_loop(),
19 TokenType::KeywordReturn => self.parse_stmt_return(),
20 _ => {
21 let expr = self.parse_expr_until(TokenTypeSet::new(&[
22 TokenType::Equals,
23 TokenType::Semicolon,
24 TokenType::BraceClose,
25 ]))?;
26 let stmt = if self.consume_if(TokenType::Equals)?.is_match() {
27 let value = self.parse_expr(TokenType::Semicolon)?;
28 self.new_statement(expr.loc + value.loc, match *expr.stx {
29 Expression::Field {
30 object,
31 field,
32 optional,
33 } => Statement::FieldAssign {
34 object,
35 field,
36 value,
37 optional,
38 },
39 Expression::Index {
40 object,
41 index,
42 optional,
43 } => Statement::IndexAssign {
44 object,
45 index,
46 value,
47 optional,
48 },
49 Expression::Var { name } => Statement::VarAssign {
50 variable: name,
51 value,
52 },
53 _ => {
54 return Err(
55 expr
56 .loc
57 .error(SyntaxErrorType::InvalidAssigmentTarget, None),
58 )
59 }
60 })
61 } else {
62 self.new_statement(expr.loc, Statement::Expression { expression: expr })
63 };
64 Ok(stmt)
65 }
66 }?;
67 if require_semicolon {
68 self.require(TokenType::Semicolon)?;
69 };
70 Ok(stmt)
71 }
72
73 pub fn parse_stmt_break(&mut self) -> SyntaxResult<Node<Statement>> {
74 let loc = self.require(TokenType::KeywordBreak)?.loc;
75 Ok(self.new_statement(loc, Statement::Break))
76 }
77
78 pub fn parse_stmt_continue(&mut self) -> SyntaxResult<Node<Statement>> {
79 let loc = self.require(TokenType::KeywordContinue)?.loc;
80 Ok(self.new_statement(loc, Statement::Continue))
81 }
82
83 pub fn parse_stmt_for(&mut self) -> SyntaxResult<Node<Statement>> {
84 let parent_scope = self.enter_new_scope(ScopeType::Block);
85 let loc_start = self.require(TokenType::KeywordFor)?.loc;
86 let (_, variable) = self.require_identifier_as_string()?;
87 assert!(self.scope.add_symbol(variable.clone()));
88 self.require(TokenType::KeywordIn)?;
89 let iterable = self.parse_expr(TokenType::BraceOpen)?;
90 let body = self.parse_expr_block_without_new_scope()?;
91 match body.stx.as_ref() {
92 Expression::Block {
93 result: Some(..), ..
94 } => return Err(body.loc.error(SyntaxErrorType::LoopCannotResult, None)),
95 _ => {}
96 };
97 let stmt = self.new_statement(loc_start + body.loc, Statement::For {
98 variable,
99 iterable,
100 body,
101 });
102 self.return_to_scope(parent_scope);
103 Ok(stmt)
104 }
105
106 pub fn parse_stmt_let(&mut self) -> SyntaxResult<Node<Statement>> {
107 let loc_start = self.require(TokenType::KeywordLet)?.loc;
108 let (variable_loc, variable) = self.require_identifier_as_string()?;
109 if !self.scope.add_symbol(variable.clone()) {
110 return Err(variable_loc.error(SyntaxErrorType::RedeclaredVar, None));
111 };
112 self.require(TokenType::Equals)?;
113 let value = self.parse_expr(TokenType::Semicolon)?;
114 Ok(self.new_statement(loc_start + value.loc, Statement::Let { variable, value }))
115 }
116
117 pub fn parse_stmt_loop(&mut self) -> SyntaxResult<Node<Statement>> {
118 let loc_start = self.require(TokenType::KeywordLoop)?.loc;
119 let body = self.parse_expr_block()?;
120 match body.stx.as_ref() {
121 Expression::Block {
122 result: Some(..), ..
123 } => return Err(body.loc.error(SyntaxErrorType::LoopCannotResult, None)),
124 _ => {}
125 };
126 Ok(self.new_statement(loc_start + body.loc, Statement::Loop { body }))
127 }
128
129 pub fn parse_stmt_return(&mut self) -> SyntaxResult<Node<Statement>> {
130 let loc_start = self.require(TokenType::KeywordReturn)?.loc;
131 let value = if self.peek()?.typ == TokenType::Semicolon {
132 None
133 } else {
134 Some(self.parse_expr(TokenType::Semicolon)?)
135 };
136 Ok(self.new_statement(loc_start, Statement::Return { value }))
137 }
138}