erl_parse/cst/clauses/
mod.rs

1use erl_tokenize::tokens::{AtomToken, SymbolToken, VariableToken};
2use erl_tokenize::values::Symbol;
3use erl_tokenize::{Position, PositionRange};
4
5use self::parts::{ExceptionClass, StackTrace, WhenGuard};
6use crate::cst::commons::parts::{Args, Clauses, Sequence};
7use crate::cst::exprs::parts::Body;
8use crate::cst::types;
9use crate::cst::{GuardTest, Pattern, Type};
10use crate::traits::{Parse, TokenRead};
11use crate::{Parser, Result};
12
13pub mod parts;
14
15/// `Option<ExceptionClass>` `Pattern` `Option<WhenGuard>` `->` `Body`
16#[derive(Debug, Clone)]
17pub struct CatchClause {
18    pub class: Option<ExceptionClass>,
19    pub pattern: Pattern,
20    pub stacktrace: Option<StackTrace>,
21    pub guard: Option<WhenGuard>,
22    pub _arrow: SymbolToken,
23    pub body: Body,
24}
25impl Parse for CatchClause {
26    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
27    where
28        T: TokenRead,
29    {
30        Ok(CatchClause {
31            class: track!(parser.parse())?,
32            pattern: track!(parser.parse())?,
33            stacktrace: track!(parser.parse())?,
34            guard: track!(parser.parse())?,
35            _arrow: track!(parser.expect(&Symbol::RightArrow))?,
36            body: track!(parser.parse())?,
37        })
38    }
39}
40impl PositionRange for CatchClause {
41    fn start_position(&self) -> Position {
42        self.class
43            .as_ref()
44            .map(PositionRange::start_position)
45            .unwrap_or_else(|| self.pattern.start_position())
46    }
47    fn end_position(&self) -> Position {
48        self.body.end_position()
49    }
50}
51
52/// `Args<Type>` `->` `Type` `Option<Constraints>`
53#[derive(Debug, Clone)]
54pub struct SpecClause {
55    pub args: Args<Type>,
56    pub _arrow: SymbolToken,
57    pub return_type: Type,
58    pub constraints: Option<types::Constraints>,
59}
60impl Parse for SpecClause {
61    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
62    where
63        T: TokenRead,
64    {
65        Ok(SpecClause {
66            args: track!(parser.parse())?,
67            _arrow: track!(parser.expect(&Symbol::RightArrow))?,
68            return_type: track!(parser.parse())?,
69            constraints: track!(parser.parse())?,
70        })
71    }
72}
73impl PositionRange for SpecClause {
74    fn start_position(&self) -> Position {
75        self.args.start_position()
76    }
77    fn end_position(&self) -> Position {
78        self.constraints
79            .as_ref()
80            .map(PositionRange::end_position)
81            .unwrap_or_else(|| self.return_type.end_position())
82    }
83}
84
85/// `Pattern` `Option<WhenGuard>` `->` `Body`
86#[derive(Debug, Clone)]
87pub struct CaseClause {
88    pub pattern: Pattern,
89    pub guard: Option<WhenGuard>,
90    pub _arrow: SymbolToken,
91    pub body: Body,
92}
93impl Parse for CaseClause {
94    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
95    where
96        T: TokenRead,
97    {
98        Ok(CaseClause {
99            pattern: track!(parser.parse())?,
100            guard: track!(parser.parse())?,
101            _arrow: track!(parser.expect(&Symbol::RightArrow))?,
102            body: track!(parser.parse())?,
103        })
104    }
105}
106impl PositionRange for CaseClause {
107    fn start_position(&self) -> Position {
108        self.pattern.start_position()
109    }
110    fn end_position(&self) -> Position {
111        self.body.end_position()
112    }
113}
114
115/// `Clauses<Sequence<GuardTest>>` `->` `Body`
116#[derive(Debug, Clone)]
117pub struct IfClause {
118    pub guard: Clauses<Sequence<GuardTest>>,
119    pub _arrow: SymbolToken,
120    pub body: Body,
121}
122impl Parse for IfClause {
123    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
124    where
125        T: TokenRead,
126    {
127        Ok(IfClause {
128            guard: track!(parser.parse())?,
129            _arrow: track!(parser.expect(&Symbol::RightArrow))?,
130            body: track!(parser.parse())?,
131        })
132    }
133}
134impl PositionRange for IfClause {
135    fn start_position(&self) -> Position {
136        self.guard.start_position()
137    }
138    fn end_position(&self) -> Position {
139        self.body.end_position()
140    }
141}
142
143/// `Args<Pattern>` `Option<WhenGuard>` `->` `Body`
144#[derive(Debug, Clone)]
145pub struct FunClause {
146    pub patterns: Args<Pattern>,
147    pub guard: Option<WhenGuard>,
148    pub _arrow: SymbolToken,
149    pub body: Body,
150}
151impl Parse for FunClause {
152    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
153    where
154        T: TokenRead,
155    {
156        Ok(FunClause {
157            patterns: track!(parser.parse())?,
158            guard: track!(parser.parse())?,
159            _arrow: track!(parser.expect(&Symbol::RightArrow))?,
160            body: track!(parser.parse())?,
161        })
162    }
163}
164impl PositionRange for FunClause {
165    fn start_position(&self) -> Position {
166        self.patterns.start_position()
167    }
168    fn end_position(&self) -> Position {
169        self.body.end_position()
170    }
171}
172
173/// `VariableToken` `Args<Pattern>` `Option<WhenGuard>` `->` `Body`
174#[derive(Debug, Clone)]
175pub struct NamedFunClause {
176    pub name: VariableToken,
177    pub patterns: Args<Pattern>,
178    pub guard: Option<WhenGuard>,
179    pub _arrow: SymbolToken,
180    pub body: Body,
181}
182impl Parse for NamedFunClause {
183    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
184    where
185        T: TokenRead,
186    {
187        Ok(NamedFunClause {
188            name: track!(parser.parse())?,
189            patterns: track!(parser.parse())?,
190            guard: track!(parser.parse())?,
191            _arrow: track!(parser.expect(&Symbol::RightArrow))?,
192            body: track!(parser.parse())?,
193        })
194    }
195}
196impl PositionRange for NamedFunClause {
197    fn start_position(&self) -> Position {
198        self.name.start_position()
199    }
200    fn end_position(&self) -> Position {
201        self.body.end_position()
202    }
203}
204
205/// `AtomToken` `Args<Pattern>` `Option<WhenGuard>` `->` `Body`
206#[derive(Debug, Clone)]
207pub struct FunDeclClause {
208    pub name: AtomToken,
209    pub patterns: Args<Pattern>,
210    pub guard: Option<WhenGuard>,
211    pub _arrow: SymbolToken,
212    pub body: Body,
213}
214impl Parse for FunDeclClause {
215    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
216    where
217        T: TokenRead,
218    {
219        // TODO: handle predefined macros
220        Ok(FunDeclClause {
221            name: track!(parser.parse())?,
222            patterns: track!(parser.parse())?,
223            guard: track!(parser.parse())?,
224            _arrow: track!(parser.expect(&Symbol::RightArrow))?,
225            body: track!(parser.parse())?,
226        })
227    }
228}
229impl PositionRange for FunDeclClause {
230    fn start_position(&self) -> Position {
231        self.name.start_position()
232    }
233    fn end_position(&self) -> Position {
234        self.body.end_position()
235    }
236}