1use crate::{
19 common::Identifier,
20 expressions::{
21 ArrayInitializerExpression,
22 ArrayInlineExpression,
23 CircuitInlineExpression,
24 Expression,
25 PostfixExpression,
26 TernaryExpression,
27 UnaryExpression,
28 },
29 operations::{BinaryOperation, UnaryOperation},
30 values::Value,
31};
32
33use crate::expressions::TupleExpression;
34use from_pest::{ConversionError, FromPest, Void};
35use pest::{
36 error::Error,
37 iterators::{Pair, Pairs},
38 prec_climber::{Assoc, Operator, PrecClimber},
39 Parser,
40 Span,
41};
42
43#[derive(Parser)]
44#[grammar = "leo.pest"]
45pub struct LanguageParser;
46
47pub fn parse(input: &str) -> Result<Pairs<Rule>, Error<Rule>> {
48 LanguageParser::parse(Rule::file, input)
49}
50
51pub(crate) fn span_into_string(span: Span) -> String {
52 span.as_str().to_string()
53}
54
55lazy_static! {
56 static ref PRECEDENCE_CLIMBER: PrecClimber<Rule> = precedence_climber();
57}
58
59fn precedence_climber() -> PrecClimber<Rule> {
62 PrecClimber::new(vec![
63 Operator::new(Rule::operation_or, Assoc::Left),
64 Operator::new(Rule::operation_and, Assoc::Left),
65 Operator::new(Rule::operation_eq, Assoc::Left)
66 | Operator::new(Rule::operation_ne, Assoc::Left)
67 | Operator::new(Rule::operation_ge, Assoc::Left)
68 | Operator::new(Rule::operation_gt, Assoc::Left)
69 | Operator::new(Rule::operation_le, Assoc::Left)
70 | Operator::new(Rule::operation_lt, Assoc::Left),
71 Operator::new(Rule::operation_add, Assoc::Left) | Operator::new(Rule::operation_sub, Assoc::Left),
72 Operator::new(Rule::operation_mul, Assoc::Left) | Operator::new(Rule::operation_div, Assoc::Left),
73 Operator::new(Rule::operation_pow, Assoc::Left),
74 ])
75}
76
77fn parse_term(pair: Pair<Rule>) -> Expression {
78 match pair.as_rule() {
79 Rule::expression_term => {
80 let clone = pair.clone();
81 let next = clone.into_inner().next().unwrap();
82 match next.as_rule() {
83 Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), Rule::expression_tuple => {
85 Expression::Tuple(TupleExpression::from_pest(&mut pair.into_inner()).unwrap())
86 }
87 Rule::expression_array_inline => {
88 Expression::ArrayInline(ArrayInlineExpression::from_pest(&mut pair.into_inner()).unwrap())
89 }
90 Rule::expression_array_initializer => Expression::ArrayInitializer(Box::new(
91 ArrayInitializerExpression::from_pest(&mut pair.into_inner()).unwrap(),
92 )),
93 Rule::expression_circuit_inline => {
94 Expression::CircuitInline(CircuitInlineExpression::from_pest(&mut pair.into_inner()).unwrap())
95 }
96 Rule::expression_conditional => {
97 Expression::Ternary(Box::new(TernaryExpression::from_pest(&mut pair.into_inner()).unwrap()))
98 }
99 Rule::expression_unary => {
100 let span = next.as_span();
102 let mut inner = next.into_inner();
103 let operation = match inner.next().unwrap().as_rule() {
104 Rule::operation_unary => {
105 UnaryOperation::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap()
106 }
107 rule => unreachable!("`expression_unary` should yield `operation_unary`, found {:#?}", rule),
108 };
109 let expression = parse_term(inner.next().unwrap());
110 Expression::Unary(Box::new(UnaryExpression {
111 operation,
112 expression,
113 span,
114 }))
115 }
116 Rule::expression_postfix => {
117 Expression::Postfix(PostfixExpression::from_pest(&mut pair.into_inner()).unwrap())
118 }
119 Rule::value => Expression::Value(Value::from_pest(&mut pair.into_inner()).unwrap()),
120 Rule::identifier => Expression::Identifier(Identifier::from_pest(&mut pair.into_inner()).unwrap()),
121 rule => unreachable!(
122 "`term` should contain one of ['value', 'identifier', 'expression', 'expression_not', 'expression_increment', 'expression_decrement'], found {:#?}",
123 rule
124 ),
125 }
126 }
127 rule => unreachable!(
128 "`parse_expression_term` should be invoked on `Rule::expression_term`, found {:#?}",
129 rule
130 ),
131 }
132}
133
134fn binary_expression<'ast>(lhs: Expression<'ast>, pair: Pair<'ast, Rule>, rhs: Expression<'ast>) -> Expression<'ast> {
135 let (start, _) = lhs.span().clone().split();
136 let (_, end) = rhs.span().clone().split();
137 let span = start.span(&end);
138
139 match pair.as_rule() {
140 Rule::operation_or => Expression::binary(BinaryOperation::Or, lhs, rhs, span),
141 Rule::operation_and => Expression::binary(BinaryOperation::And, lhs, rhs, span),
142 Rule::operation_eq => Expression::binary(BinaryOperation::Eq, lhs, rhs, span),
143 Rule::operation_ne => Expression::binary(BinaryOperation::Ne, lhs, rhs, span),
144 Rule::operation_ge => Expression::binary(BinaryOperation::Ge, lhs, rhs, span),
145 Rule::operation_gt => Expression::binary(BinaryOperation::Gt, lhs, rhs, span),
146 Rule::operation_le => Expression::binary(BinaryOperation::Le, lhs, rhs, span),
147 Rule::operation_lt => Expression::binary(BinaryOperation::Lt, lhs, rhs, span),
148 Rule::operation_add => Expression::binary(BinaryOperation::Add, lhs, rhs, span),
149 Rule::operation_sub => Expression::binary(BinaryOperation::Sub, lhs, rhs, span),
150 Rule::operation_mul => Expression::binary(BinaryOperation::Mul, lhs, rhs, span),
151 Rule::operation_div => Expression::binary(BinaryOperation::Div, lhs, rhs, span),
152 Rule::operation_pow => Expression::binary(BinaryOperation::Pow, lhs, rhs, span),
153 _ => unreachable!(),
154 }
155}
156
157impl<'ast> FromPest<'ast> for Expression<'ast> {
158 type FatalError = Void;
159 type Rule = Rule;
160
161 fn from_pest(pest: &mut Pairs<'ast, Rule>) -> Result<Self, ConversionError<Void>> {
162 let pair = pest.peek().ok_or(::from_pest::ConversionError::NoMatch)?;
163 match pair.as_rule() {
164 Rule::expression => {
165 pest.next();
167 Ok(PRECEDENCE_CLIMBER.climb(pair.into_inner(), parse_term, binary_expression))
168 }
169 _ => Err(ConversionError::NoMatch),
170 }
171 }
172}