ocypode_lang/front/
parser.rs

1use std::str::FromStr;
2
3use crate::{
4    ast::*,
5    errors::{Error as OYError, Result as OYResult},
6    utils,
7};
8
9use super::ast::{Block, ExpressionStatement, Program, Statement};
10use bigdecimal::BigDecimal;
11use pest::{iterators::Pair, Parser};
12use pest_derive::Parser;
13
14/// The parser for the Ocypode Language. This is generated by the pest_derive crate from the grammar in `grammar.pest`.
15#[derive(Parser, Debug)]
16#[grammar = "grammar.pest"]
17pub struct OYParser;
18
19impl<'a> OYParser {
20    /// Parse the given source code to a program.
21    pub fn parse_program(input: &'a str) -> OYResult<Program> {
22        let program_pair = OYParser::parse(Rule::program, input)
23            .map_err(OYError::from)?
24            .next()
25            .unwrap();
26        let span = program_pair.as_span();
27        Ok((
28            program_pair
29                .into_inner()
30                .filter(|pair| pair.as_rule() != Rule::EOI)
31                .map(Self::parse_statement)
32                .collect::<OYResult<Vec<_>>>()?
33                .into_iter()
34                .flatten()
35                .collect(),
36            span,
37        ))
38    }
39
40    /// Parse the given source code to a statement.
41    pub fn parse_statement(statement: Pair<'a, Rule>) -> OYResult<Option<Statement>> {
42        match statement.as_rule() {
43            Rule::func_def => Ok(Some(Self::parse_function(statement)?)),
44            Rule::assignment => Ok(Some(Self::parse_assignment(statement)?)),
45            Rule::return_stmt => Ok(Some(Self::parse_return(statement)?)),
46            Rule::expression => Ok(Some(Statement::Expression(Self::parse_expression(
47                statement,
48            )?))),
49            Rule::statement => Self::parse_statement(statement.into_inner().next().unwrap()),
50            Rule::semicolon => Ok(None),
51            _ => {
52                dbg!(statement.as_rule());
53                unreachable!("This function only parse the statements")
54            }
55        }
56    }
57
58    /// Parse the given source code to a block.
59    pub fn parse_block(block: Pair<'a, Rule>) -> OYResult<Block> {
60        let span = block.as_span();
61        Ok(Block {
62            statements: block
63                .into_inner()
64                .map(Self::parse_statement)
65                .collect::<OYResult<Vec<Option<_>>>>()?
66                .into_iter()
67                .flatten()
68                .collect(),
69            span: span.into(),
70        })
71    }
72
73    /// Parse the given source code to a identifier.
74    /// Make sure that the given pair is a identifier, otherwise this will panic.
75    pub fn parse_ident(ident: Pair<'a, Rule>) -> Ident {
76        let span = ident.as_span();
77        let ident = ident.as_str().to_owned();
78        Ident {
79            ident: ident.as_str().to_owned(),
80            span: span.into(),
81        }
82    }
83
84    /// Parse the visibility.
85    /// Make sure that the given pair is a visibility, otherwise this will panic.
86    pub fn parse_visibility(visibility: Pair<'a, Rule>) -> Visibility {
87        match visibility.as_rule() {
88            Rule::PUBLIC => Visibility::Public,
89            Rule::PRIVATE => Visibility::Private,
90            Rule::visibility => Self::parse_visibility(visibility.into_inner().next().unwrap()),
91            _ => {
92                dbg!(visibility.as_rule());
93                unreachable!("This function only parse the visibility")
94            }
95        }
96    }
97
98    /// Parse the given source code to a expression.
99    pub fn parse_expression(expr: Pair<'a, Rule>) -> OYResult<ExpressionStatement> {
100        match expr.as_rule() {
101            Rule::func_call => Ok(ExpressionStatement::FunctionCall(
102                Self::parse_function_call(expr)?,
103            )),
104            Rule::value => Ok(ExpressionStatement::Value(Self::parse_value(expr)?)),
105            Rule::expression => Self::parse_expression(expr.into_inner().next().unwrap()),
106            Rule::anonymous_function => {
107                let anonymous_function = Self::parse_anonymous_function(expr)?;
108                Ok(ExpressionStatement::Value(ValueExpression::Object(
109                    ObjectExpression::Function(anonymous_function),
110                )))
111            }
112            _ => {
113                dbg!(expr.as_rule());
114                unreachable!("This function only parse the expressions")
115            }
116        }
117    }
118
119    /// Parse the given source code to a function call expression.
120    /// Make sure that the given pair is a function call expression, otherwise this will panic.
121    pub fn parse_function_call(func: Pair<'a, Rule>) -> OYResult<FunctionCallExpression> {
122        let span = func.as_span();
123        let mut inner = func.into_inner();
124        let callable = inner.next().unwrap();
125        let args = inner
126            .next()
127            .unwrap()
128            .into_inner()
129            .map(Self::parse_arg)
130            .collect::<OYResult<Vec<_>>>()?;
131        match callable.as_rule() {
132            Rule::IDENT => Ok(FunctionCallExpression {
133                callable: ValueExpression::Ident(Self::parse_ident(callable)),
134                args,
135                span: span.into(),
136            }),
137            Rule::anonymous_function => {
138                let anonymous_function = Self::parse_anonymous_function(callable)?;
139
140                Ok(FunctionCallExpression {
141                    callable: ValueExpression::Object(ObjectExpression::Function(
142                        anonymous_function,
143                    )),
144                    args,
145                    span: span.into(),
146                })
147            }
148            _ => {
149                dbg!(callable.as_rule());
150                unreachable!("This function only parse the function call expressions")
151            }
152        }
153    }
154
155    /// Parse the given source code to a return statement.
156    /// Make sure that the given pair is a return statement, otherwise this will panic.
157    pub fn parse_return(return_stmt: Pair<'a, Rule>) -> OYResult<Statement> {
158        let span = return_stmt.as_span();
159        let mut inner = return_stmt.into_inner();
160        Ok(Statement::Return(ReturnStatement {
161            value: Self::parse_expression(inner.next().unwrap())?,
162            span: span.into(),
163        }))
164    }
165
166    /// Parse the given source code to a value expression.
167    /// Make sure that the given pair is a value expression, otherwise this will panic.
168    pub fn parse_value(value: Pair<'a, Rule>) -> OYResult<ValueExpression> {
169        let span = value.as_span();
170        Ok(match value.as_rule() {
171            Rule::IDENT => ValueExpression::Ident(Self::parse_ident(value)),
172            Rule::string => ValueExpression::Object(ObjectExpression::String(
173                value.as_str()[1..value.as_str().len() - 1]
174                    .replace(r#"\\"#, r#"\"#)
175                    .replace(r#"\""#, r#"""#)
176                    .replace(r#"\n"#, "\n")
177                    .replace(r#"\t"#, "\t")
178                    .replace(r#"\r"#, "\r"),
179                span.into(),
180            )),
181            Rule::float => ValueExpression::Object(ObjectExpression::Float(
182                BigDecimal::from_str(value.as_str()).unwrap(),
183                span.into(),
184            )),
185            Rule::integer => ValueExpression::Object(ObjectExpression::Int(
186                BigDecimal::from_str(value.as_str()).unwrap(),
187                span.into(),
188            )),
189            Rule::boolean => ValueExpression::Object(ObjectExpression::Bool(
190                value.as_str().parse().unwrap(),
191                span.into(),
192            )),
193            Rule::array => ValueExpression::Object(ObjectExpression::Array(
194                value
195                    .into_inner()
196                    .map(Self::parse_expression)
197                    .collect::<OYResult<_>>()?,
198                span.into(),
199            )),
200            Rule::nil => ValueExpression::Object(ObjectExpression::Nil(span.into())),
201            Rule::value => Self::parse_value(value.into_inner().next().unwrap())?,
202            _ => {
203                dbg!(value.as_rule());
204                unreachable!("This function only parse the values")
205            }
206        })
207    }
208
209    /// Parse the given source code to an anonymous function.
210    /// Make sure that the given pair is an anonymous function, otherwise this will panic.
211    pub fn parse_anonymous_function(anonymous_func: Pair<'a, Rule>) -> OYResult<FunctionStatement> {
212        let span = anonymous_func.as_span();
213        let mut anonymous_inner = anonymous_func.into_inner();
214        let params = anonymous_inner
215            .next()
216            .unwrap()
217            .into_inner()
218            .map(Self::parse_param)
219            .collect::<OYResult<_>>()?;
220        let block = Self::parse_block(anonymous_inner.next().unwrap())?;
221        Ok(FunctionStatement {
222            ident: None,
223            params,
224            block: Some(block),
225            span: span.into(),
226            visibility: Visibility::Private,
227        })
228    }
229
230    /// Parse the given source code to a function statement.
231    /// Make sure that the given pair is a function statement, otherwise this will panic.
232    pub fn parse_function(func: Pair<'a, Rule>) -> OYResult<Statement> {
233        let span = func.as_span();
234        let mut inner = func.into_inner();
235        let visibility = Self::parse_visibility(inner.next().unwrap());
236        let ident = utils::check_ident_case(
237            Self::parse_ident(inner.next().unwrap()),
238            "function",
239            "the function name must be snake_case",
240            utils::Case::Snake,
241        )?;
242        let params = inner
243            .next()
244            .unwrap()
245            .into_inner()
246            .map(Self::parse_param)
247            .collect::<OYResult<Vec<_>>>()?;
248        let params = utils::cheeck_params(params, &ident)?;
249        let block = Some(Self::parse_block(inner.next().unwrap())?);
250        utils::check_main_function(&ident, &params, &visibility)?;
251        Ok(Statement::Function(FunctionStatement {
252            ident: Some(ident),
253            params,
254            block,
255            visibility,
256            span: span.into(),
257        }))
258    }
259
260    /// Parse the argument of a function call.
261    /// Make sure that the given pair is a function argument, otherwise this will panic.
262    pub fn parse_arg(arg: Pair<'a, Rule>) -> OYResult<Arg> {
263        let mut inner = arg.into_inner();
264        let is_unpack = inner.next().unwrap().as_str() == "...";
265        let expr = Self::parse_expression(inner.next().unwrap())?;
266        let span = expr.span();
267        Ok(Arg {
268            expr,
269            is_unpack,
270            span,
271        })
272    }
273
274    /// Parse the parameter of a function.
275    /// Make sure that the given pair is a function parameter, otherwise this will panic.
276    pub fn parse_param(param: Pair<'a, Rule>) -> OYResult<Param> {
277        let mut inner = param.into_inner();
278        let is_pack = inner.next().unwrap().as_str() == "*";
279        let ident = utils::check_ident_case(
280            Self::parse_ident(inner.next().unwrap()),
281            "parameter",
282            "the parameter name must be snake_case",
283            utils::Case::Snake,
284        )?;
285        Ok(Param { ident, is_pack })
286    }
287
288    /// Parse the given source code to a assignment statement.
289    /// Make sure that the given pair is a assignment statement, otherwise this will panic.
290    pub fn parse_assignment(assignment: Pair<'a, Rule>) -> OYResult<Statement> {
291        let span = assignment.as_span();
292        let mut inner = assignment.into_inner();
293        let ident = utils::check_ident_case(
294            Self::parse_ident(inner.next().unwrap()),
295            "variable",
296            "the variable name must be snake_case",
297            utils::Case::Snake,
298        )?;
299        let expression = Self::parse_expression(inner.next().unwrap())?;
300        Ok(Statement::Assignment(AssignmentStatement {
301            ident,
302            expression,
303            span: span.into(),
304        }))
305    }
306}