cortex_lang/parsing/
parser.rs

1use std::collections::HashMap;
2
3use pest::iterators::Pair;
4use pest::Parser;
5use pest_derive::Parser;
6use thiserror::Error;
7use paste::paste;
8
9use super::ast::{expression::{Atom, BinaryOperator, ConditionBody, EqResult, Expression, ExpressionTail, IdentExpression, MulResult, OptionalIdentifier, Parameter, PathIdent, Primary, SumResult, UnaryOperator}, program::Program, statement::Statement, top_level::{BasicBody, Body, Function, Struct, TopLevel}, r#type::CortexType};
10
11macro_rules! operator_parser {
12    ($name:ident, $typ:ty, $prev_name:ident, $prev_typ:ty) => {
13        paste! {
14            fn [<parse_ $name>](pair: Pair<Rule>) -> Result<$typ, ParseError> {
15                let mut pairs = pair.into_inner();
16                let first = Self::[<parse_ $prev_name>](pairs.next().unwrap())?;
17                let mut pair_iter = pairs.into_iter().peekable();
18                let mut rest = Vec::<(BinaryOperator, $prev_typ)>::new();
19                while pair_iter.peek().is_some() {
20                    let first_pair = pair_iter.next().unwrap();
21                    let second_pair = pair_iter.next().unwrap();
22                    let op = Self::parse_binop(first_pair)?;
23                    let right = Self::[<parse_ $prev_name>](second_pair)?;
24                    rest.push((op, right));
25                }
26                Ok(
27                    $typ {
28                        first: first,
29                        rest: rest,
30                    }
31                )
32            }
33        }
34    }
35}
36
37#[derive(Parser)]
38#[grammar = "grammar.pest"] // relative to src
39struct PestCortexParser;
40
41pub struct CortexParser;
42
43#[derive(Error, Debug)]
44pub enum ParseError {
45    #[error("Failed to parse statement '{0}'")]
46    FailStatement(String),
47    #[error("Failed to parse expression '{0}'")]
48    FailExpression(String),
49    #[error("Failed to parse atom '{0}'")]
50    FailAtom(String),
51    #[error("Failed to parse expression tail '{0}'")]
52    FailTail(String),
53    #[error("Failed to parse path '{0}'")]
54    FailPath(String),
55    #[error("Failed to parse identifier '{0}'")]
56    FailOptionalIdentifier(String),
57    #[error("Failed to parse type '{0}'")]
58    FailType(String),
59    #[error("Failed to parse top level declaration '{0}'")]
60    FailTopLevel(String),
61    #[error("Operator does not exist '{0}'")]
62    OperatorDoesNotExist(String),
63    #[error("Failed to parse program")]
64    FailProgram,
65}
66
67impl CortexParser {
68    pub fn parse_statement(input: &str) -> Result<Statement, ParseError> {
69        let pair = PestCortexParser::parse(Rule::statement, input);
70        match pair {
71            Ok(mut v) => Self::parse_stmt_pair(v.next().unwrap()),
72            Err(_) => Err(ParseError::FailStatement(String::from(input))),
73        }
74    }
75    pub fn parse_expression(input: &str) -> Result<Expression, ParseError> {
76        let pair = PestCortexParser::parse(Rule::expr, input);
77        match pair {
78            Ok(mut v) => Self::parse_expr_pair(v.next().unwrap()),
79            Err(_) => Err(ParseError::FailExpression(String::from(input))),
80        }
81    }
82    pub fn parse_type(input: &str) -> Result<CortexType, ParseError> {
83        let pair = PestCortexParser::parse(Rule::typ, input);
84        match pair {
85            Ok(mut v) => Self::parse_type_pair(v.next().unwrap()),
86            Err(_) => Err(ParseError::FailType(String::from(input))),
87        }
88    }
89    pub fn parse_function(input: &str) -> Result<Function, ParseError> {
90        let pair = PestCortexParser::parse(Rule::function, input);
91        match pair {
92            Ok(mut v) => Self::parse_func_pair(v.next().unwrap()),
93            Err(_) => Err(ParseError::FailType(String::from(input))),
94        }
95    }
96    pub fn parse_struct(input: &str) -> Result<Struct, ParseError> {
97        let pair = PestCortexParser::parse(Rule::r#struct, input);
98        match pair {
99            Ok(mut v) => Self::parse_struct_pair(v.next().unwrap()),
100            Err(_) => Err(ParseError::FailType(String::from(input))),
101        }
102    }
103    pub fn parse_top_level(input: &str) -> Result<TopLevel, ParseError> {
104        let pair = PestCortexParser::parse(Rule::topLevel, input);
105        match pair {
106            Ok(mut v) => Self::parse_toplevel_pair(v.next().unwrap()),
107            Err(_) => Err(ParseError::FailType(String::from(input))),
108        }
109    }
110    pub fn parse_path(input: &str) -> Result<PathIdent, ParseError> {
111        let pair = PestCortexParser::parse(Rule::pathIdent, input);
112        match pair {
113            Ok(mut v) => Self::parse_path_ident(v.next().unwrap()),
114            Err(_) => Err(ParseError::FailType(String::from(input))),
115        }
116    }
117    pub fn parse_program(input: &str) -> Result<Program, ParseError> {
118        let pair = PestCortexParser::parse(Rule::program, input);
119        match pair {
120            Ok(mut v) => Self::parse_program_pair(v.next().unwrap()),
121            Err(_) => Err(ParseError::FailProgram),
122        }
123    }
124    
125    fn parse_program_pair(pair: Pair<Rule>) -> Result<Program, ParseError> {
126        let pairs = pair.into_inner();
127        let mut content = Vec::<TopLevel>::new();
128        for p in pairs {
129            if p.as_rule() != Rule::EOI {
130                let t = Self::parse_toplevel_pair(p)?;
131                content.push(t);
132            }
133        }
134        Ok(Program { content: content })
135    }
136
137    fn parse_toplevel_pair(mut pair: Pair<Rule>) -> Result<TopLevel, ParseError> {
138        pair = pair.into_inner().next().unwrap();
139        match pair.as_rule() {
140            Rule::function => {
141                Ok(TopLevel::Function(Self::parse_func_pair(pair)?))
142            },
143            Rule::r#struct => {
144                Ok(TopLevel::Struct(Self::parse_struct_pair(pair)?))
145            },
146            Rule::import => {
147                let name: &str;
148                let mut is_string = false;
149                let p = pair.into_inner().next().unwrap();
150                if p.as_rule() == Rule::string {
151                    name = p.into_inner().next().unwrap().as_str();
152                    is_string = true;
153                } else {
154                    name = p.as_str();
155                }
156                Ok(TopLevel::Import { name: String::from(name), is_string_import: is_string })
157            },
158            Rule::module => {
159                let mut pairs = pair.into_inner();
160                let name = pairs.next().unwrap().as_str();
161                let mut contents = Vec::<TopLevel>::new();
162                for p in pairs {
163                    let toplevel = Self::parse_toplevel_pair(p)?;
164                    contents.push(toplevel);
165                }
166                Ok(TopLevel::Module { name: String::from(name), contents: contents })
167            },
168            _ => Err(ParseError::FailTopLevel(String::from(pair.as_str()))),
169        }
170    }
171
172    fn parse_stmt_pair(mut pair: Pair<Rule>) -> Result<Statement, ParseError> {
173        pair = pair.into_inner().next().unwrap();
174        let orig = pair.as_str();
175        match pair.as_rule() {
176            Rule::expr => {
177                let expression = Self::parse_expr_pair(pair)?;
178                Ok(Statement::Expression(expression))
179            },
180            Rule::throw => {
181                let expression = Self::parse_expr_pair(pair.into_inner().next().unwrap())?;
182                Ok(Statement::Throw(expression))
183            },
184            Rule::varDec => {
185                let is_const = pair.as_str().starts_with("const");
186                let mut pairs = pair.into_inner();
187                let name = Self::parse_opt_ident(pairs.next().unwrap())?;
188                let third_pair = pairs.next().unwrap();
189                let mut typ: Option<CortexType> = None;
190                let init_value = 
191                    if third_pair.as_rule() == Rule::typ {
192                        typ = Some(Self::parse_type_pair(third_pair)?);
193                        Self::parse_expr_pair(pairs.next().unwrap())?
194                    } else {
195                        Self::parse_expr_pair(third_pair)?
196                    };
197                Ok(Statement::VariableDeclaration { 
198                    name: name,
199                    is_const: is_const,
200                    typ: typ,
201                    initial_value: init_value,
202                })
203            },
204            Rule::varAssign => {
205                let mut pairs = pair.into_inner();
206                let left = Self::parse_ident_expr(pairs.next().unwrap())?;
207                let value;
208                let op;
209                let next = pairs.next().unwrap();
210                match next.as_rule() {
211                    Rule::arithLogicBinOp => {
212                        op = Some(Self::parse_binop(next.into_inner().next().unwrap())?);
213                        value = Self::parse_expr_pair(pairs.next().unwrap())?;
214                    },
215                    Rule::expr => {
216                        op = None;
217                        value = Self::parse_expr_pair(next)?;
218                    },
219                    _ => return Err(ParseError::FailStatement(String::from(orig)))
220                }
221
222                Ok(Statement::VariableAssignment { 
223                    name: left,
224                    value: value,
225                    op: op,
226                })
227            },
228            Rule::r#while => {
229                let mut pairs = pair.into_inner();
230                let cond = Self::parse_expr_pair(pairs.next().unwrap())?;
231                let body = Self::parse_body(pairs.next().unwrap())?;
232                Ok(Statement::WhileLoop(ConditionBody { condition: cond, body: body }))
233            },
234            _ => Err(ParseError::FailStatement(String::from(pair.as_str()))),
235        }
236    }
237
238    fn parse_primary(pair: Pair<Rule>) -> Result<Primary, ParseError> {
239        let mut pairs = pair.into_inner();
240        let atom_pair = pairs.next().unwrap();
241        let atom = Self::parse_atom_pair(atom_pair.into_inner().next().unwrap())?;
242        let mut expr_tail = ExpressionTail::None;
243        let next = pairs.next();
244        if next.is_some() {
245            let expr_tail_pair = next.unwrap();
246            expr_tail = Self::parse_expr_tail_pair(expr_tail_pair)?;
247        }
248        Ok(Primary {
249            atom: atom,
250            tail: expr_tail,
251        })
252    }
253    operator_parser!(mul_result, MulResult, primary, Primary);
254    operator_parser!(sum_result, SumResult, mul_result, MulResult);
255    operator_parser!(eq_result, EqResult, sum_result, SumResult);
256    operator_parser!(expr_pair, Expression, eq_result, EqResult);
257
258    fn parse_atom_pair(pair: Pair<Rule>) -> Result<Atom, ParseError> {
259        match pair.as_rule() {
260            Rule::number => {
261                let value: f64 = pair.as_str().parse().unwrap();
262                Ok(Atom::Number(value))
263            },
264            Rule::boolean => {
265                let value: bool = pair.as_str().parse().unwrap();
266                Ok(Atom::Boolean(value))
267            },
268            Rule::string => {
269                Ok(Atom::String(String::from(pair.into_inner().next().unwrap().as_str())))
270            },
271            Rule::null => {
272                Ok(Atom::Null)
273            },
274            Rule::void => {
275                Ok(Atom::Void)
276            },
277            Rule::pathIdent => {
278                Ok(Atom::PathIdent(Self::parse_path_ident(pair)?))
279            },
280            Rule::expr => {
281                Ok(Atom::Expression(Box::new(Self::parse_expr_pair(pair)?)))
282            },
283            Rule::call => {
284                let mut pairs = pair.into_inner();
285                let name = Self::parse_path_ident(pairs.next().unwrap())?;
286                let mut args: Vec<Expression> = Vec::new();
287                for arg in pairs {
288                    let parsed_arg = Self::parse_expr_pair(arg)?;
289                    args.push(parsed_arg);
290                }
291                Ok(Atom::Call(name, args))
292            },
293            Rule::structConstruction => {
294                let mut pairs = pair.into_inner();
295                let name = Self::parse_path_ident(pairs.next().unwrap())?;
296                let mut assignments = Vec::new();
297                for p in pairs {
298                    let mut member_init = p.into_inner();
299                    let name = member_init.next().unwrap().as_str();
300                    let expr = Self::parse_expr_pair(member_init.next().unwrap())?;
301                    assignments.push((String::from(name), expr));
302                }
303                Ok(Atom::StructConstruction { name: name, assignments: assignments })
304            },
305            Rule::r#if => {
306                let mut pairs = pair.into_inner();
307                let first_cond = Self::parse_expr_pair(pairs.next().unwrap())?;
308                let first_body = Self::parse_body(pairs.next().unwrap())?;
309                let elifs_pair = pairs.next().unwrap();
310                let elifs_pairs = elifs_pair.into_inner();
311                let mut elifs = Vec::<ConditionBody>::new();
312                for p in elifs_pairs {
313                    elifs.push(Self::parse_condition_body(p)?);
314                }
315                let op_else_pair = pairs.next();
316                let else_body = 
317                    if let Some(else_pair) = op_else_pair {
318                        Some(Box::new(Self::parse_body(else_pair.into_inner().next().unwrap())?))
319                    } else {
320                        None
321                    };
322
323                Ok(Atom::IfStatement { 
324                    first: Box::new(ConditionBody { condition: first_cond, body: first_body }),
325                    conds: elifs,
326                    last: else_body,
327                })
328            },
329            Rule::unOpAtom => {
330                let mut pairs = pair.into_inner();
331                let unop = Self::parse_unop(pairs.next().unwrap())?;
332                let expr = Self::parse_expr_pair(pairs.next().unwrap())?;
333                Ok(Atom::UnaryOperation { op: unop, exp: Box::new(expr) })
334            },
335            _ => Err(ParseError::FailAtom(String::from(pair.as_str()))),
336        }
337    }
338
339    fn parse_expr_tail_pair(pair: Pair<Rule>) -> Result<ExpressionTail, ParseError> {
340        match pair.as_rule() {
341            Rule::exprTail => {
342                if let Some(tail_pair) = pair.into_inner().next() {
343                    match tail_pair.as_rule() {
344                        Rule::postfixBangTail => {
345                            let next = Self::parse_expr_tail_pair(tail_pair.into_inner().next().unwrap())?;
346                            Ok(ExpressionTail::PostfixBang { next: Box::new(next) })
347                        },
348                        Rule::memberAccessTail => {
349                            let mut pairs = tail_pair.into_inner();
350                            let member = pairs.next().unwrap().as_str();
351                            let next = Self::parse_expr_tail_pair(pairs.next().unwrap())?;
352                            Ok(ExpressionTail::MemberAccess { member: String::from(member), next: Box::new(next) })
353                        },
354                        _ => Err(ParseError::FailTail(String::from(tail_pair.as_str()))),
355                    }
356                } else {
357                    Ok(ExpressionTail::None)
358                }
359            }
360            _ => Err(ParseError::FailTail(String::from(pair.as_str()))),
361        }
362    }
363
364    fn parse_condition_body(pair: Pair<Rule>) -> Result<ConditionBody, ParseError> {
365        let mut pairs = pair.into_inner();
366        let cond = Self::parse_expr_pair(pairs.next().unwrap())?;
367        let body = Self::parse_body(pairs.next().unwrap())?;
368        Ok(ConditionBody {
369            condition: cond,
370            body: body,
371        })
372    }
373
374    fn parse_binop(pair: Pair<Rule>) -> Result<BinaryOperator, ParseError> {
375        match pair.as_rule() {
376            Rule::add => Ok(BinaryOperator::Add),
377            Rule::sub => Ok(BinaryOperator::Subtract),
378            Rule::mul => Ok(BinaryOperator::Multiply),
379            Rule::div => Ok(BinaryOperator::Divide),
380            Rule::rem => Ok(BinaryOperator::Remainder),
381            Rule::and => Ok(BinaryOperator::LogicAnd),
382            Rule::or => Ok(BinaryOperator::LogicOr),
383            Rule::eq => Ok(BinaryOperator::IsEqual),
384            Rule::neq => Ok(BinaryOperator::IsNotEqual),
385            Rule::lt => Ok(BinaryOperator::IsLessThan),
386            Rule::lte => Ok(BinaryOperator::IsLessThanOrEqualTo),
387            Rule::gt => Ok(BinaryOperator::IsGreaterThan),
388            Rule::gte => Ok(BinaryOperator::IsGreaterThanOrEqualTo),
389            _ => Err(ParseError::OperatorDoesNotExist(String::from(pair.as_str()))),
390        }
391    }
392    fn parse_unop(pair: Pair<Rule>) -> Result<UnaryOperator, ParseError> {
393        match pair.as_rule() {
394            Rule::negate => Ok(UnaryOperator::Negate),
395            Rule::invert => Ok(UnaryOperator::Invert),
396            _ => Err(ParseError::OperatorDoesNotExist(String::from(pair.as_str()))),
397        }
398    }
399
400    fn parse_path_ident(pair: Pair<Rule>) -> Result<PathIdent, ParseError> {
401        let mut names = Vec::<String>::new();
402        for p in pair.into_inner() {
403            let name = String::from(p.as_str());
404            names.push(name);
405        }
406        Ok(PathIdent {
407            path: names,
408        })
409    }
410
411    fn parse_ident_expr(pair: Pair<Rule>) -> Result<IdentExpression, ParseError> {
412        let mut pairs = pair.into_inner();
413        let path = Self::parse_path_ident(pairs.next().unwrap())?;
414        let mut chain = Vec::new();
415        for p in pairs {
416            chain.push(String::from(p.as_str()));
417        }
418        Ok(IdentExpression {
419            base: path,
420            chain: chain,
421        })
422    }
423
424    fn parse_type_pair(pair: Pair<Rule>) -> Result<CortexType, ParseError> {
425        let nullable = pair.as_str().contains("?");
426        let path_pair = pair.into_inner().next().unwrap();
427        let path_str = String::from(path_pair.as_str());
428        let ident = Self::parse_path_ident(path_pair)?;
429        if ident.get_back().map_err(|_e| ParseError::FailPath(path_str))? == "any" {
430            Ok(CortexType::any(nullable))
431        } else {
432            Ok(CortexType::new(ident, nullable))
433        }
434    }
435
436    fn parse_opt_ident(pair: Pair<Rule>) -> Result<OptionalIdentifier, ParseError> {
437        if pair.as_str() == "~" {
438            Ok(OptionalIdentifier::Ignore)
439        } else {
440            Ok(OptionalIdentifier::Ident(String::from(pair.as_str())))
441        }
442    }
443
444    fn parse_struct_pair(pair: Pair<Rule>) -> Result<Struct, ParseError> {
445        let mut pairs = pair.into_inner();
446        let name = Self::parse_opt_ident(pairs.next().unwrap())?;
447        let field_params = Self::parse_param_list(pairs.next().unwrap())?;
448        let mut fields = HashMap::new();
449        for p in field_params {
450            fields.insert(p.name, p.typ);
451        }
452        
453        Ok(
454            Struct { 
455                name: name,
456                fields: fields,
457            }
458        )
459    }
460
461    fn parse_func_pair(pair: Pair<Rule>) -> Result<Function, ParseError> {
462        let mut pairs = pair.into_inner();
463        let name = Self::parse_opt_ident(pairs.next().unwrap())?;
464        let params = Self::parse_param_list(pairs.next().unwrap())?;
465        let return_type = Self::parse_type_pair(pairs.next().unwrap())?;
466        let body = Self::parse_body(pairs.next().unwrap())?;
467        Ok(Function {
468            name: name,
469            params: params,
470            return_type: return_type,
471            body: Body::Basic(body),
472        })
473    }
474
475    fn parse_param_list(pair: Pair<Rule>) -> Result<Vec<Parameter>, ParseError> {
476        let pairs = pair.into_inner();
477        let mut params = Vec::<Parameter>::new();
478        for p in pairs {
479            params.push(Self::parse_param(p)?);
480        }
481        Ok(params)
482    }
483    fn parse_param(pair: Pair<Rule>) -> Result<Parameter, ParseError> {
484        let mut pairs = pair.into_inner();
485        let ident = pairs.next().unwrap().as_str();
486        let typ = Self::parse_type_pair(pairs.next().unwrap())?;
487        Ok(
488            Parameter {
489                name: String::from(ident),
490                typ: typ,
491            }
492        )
493    }
494
495    fn parse_body(pair: Pair<Rule>) -> Result<BasicBody, ParseError> {
496        let mut result: Option<Expression> = None;
497        let mut statements = Vec::<Statement>::new();
498
499        let mut iter = pair.into_inner().peekable();
500        while let Some(p) = iter.next() {
501            let is_last = iter.peek().is_none();
502            if is_last {
503                if p.as_rule() == Rule::expr {
504                    result = Some(Self::parse_expr_pair(p)?);
505                } else {
506                    statements.push(Self::parse_stmt_pair(p)?);
507                }
508            } else {
509                statements.push(Self::parse_stmt_pair(p)?);
510            }
511        }
512        Ok(
513            BasicBody {
514                statements: statements,
515                result: result,
516            }
517        )
518    }
519}