function parsing and stuff..
This commit is contained in:
parent
c7d5e4e6c0
commit
a2632ca06e
|
|
@ -6,7 +6,7 @@ use chumsky::{
|
||||||
extra::{self, SimpleState},
|
extra::{self, SimpleState},
|
||||||
input::{IterInput, MapExtra},
|
input::{IterInput, MapExtra},
|
||||||
pratt::{infix, left, postfix, prefix, right},
|
pratt::{infix, left, postfix, prefix, right},
|
||||||
prelude::{Recursive, choice, just, recursive},
|
prelude::{Recursive, choice, just, none_of, recursive, via_parser},
|
||||||
recursive::{Direct, Indirect},
|
recursive::{Direct, Indirect},
|
||||||
select, text,
|
select, text,
|
||||||
};
|
};
|
||||||
|
|
@ -424,13 +424,9 @@ pub enum Visibility {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ParseError<'a> {
|
pub enum ParseError {
|
||||||
#[error("End of file.")]
|
#[error("expected a valid if condition expression")]
|
||||||
EOF,
|
IfCondition,
|
||||||
#[error("Unexpected token: {0:?}")]
|
|
||||||
UnexpectedToken(Token<'a>),
|
|
||||||
#[error("Not a type.")]
|
|
||||||
NotAType,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
|
@ -594,11 +590,16 @@ where
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expr(&self) -> impl Parser<'src, TokenInput<'src>, PlaceOrValue, ParserExtra> + Clone {
|
pub fn expr(
|
||||||
|
&self,
|
||||||
|
) -> impl Parser<'src, TokenInput<'src>, PlaceOrValue, ParserExtra> + Clone + use<'src, 'b>
|
||||||
|
{
|
||||||
self.expr.clone()
|
self.expr.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function(&self) -> impl Parser<'src, TokenInput<'src>, Index, ParserExtra> + Clone {
|
pub fn function(
|
||||||
|
&self,
|
||||||
|
) -> impl Parser<'src, TokenInput<'src>, Index, ParserExtra> + Clone + use<'src, 'b> {
|
||||||
self.function.clone()
|
self.function.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -627,6 +628,8 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
let constant = select! {
|
let constant = select! {
|
||||||
|
Token::True => (Intern::new(Value::Bool(true)), Intern::new(InnerType::Bool)),
|
||||||
|
Token::False => (Intern::new(Value::Bool(false)), Intern::new(InnerType::Bool)),
|
||||||
Token::FloatingConstant(lexeme)|
|
Token::FloatingConstant(lexeme)|
|
||||||
Token::DotFloatingConstant(lexeme)|
|
Token::DotFloatingConstant(lexeme)|
|
||||||
Token::FloatingExpConstant(lexeme)|
|
Token::FloatingExpConstant(lexeme)|
|
||||||
|
|
@ -732,9 +735,25 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_value(idx: PlaceOrValue, e: &mut E) -> PlaceOrValue {
|
||||||
|
match idx {
|
||||||
|
PlaceOrValue::Place(index) => e.state().push(AstNode::PlaceToValue { expr: index }),
|
||||||
|
PlaceOrValue::Value(index) => index,
|
||||||
|
}
|
||||||
|
.as_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_place(idx: PlaceOrValue, e: &mut E) -> PlaceOrValue {
|
||||||
|
match idx {
|
||||||
|
PlaceOrValue::Value(index) => e.state().push(AstNode::ValueToPlace { expr: index }),
|
||||||
|
PlaceOrValue::Place(index) => index,
|
||||||
|
}
|
||||||
|
.as_place()
|
||||||
|
}
|
||||||
|
|
||||||
fn create_expr(
|
fn create_expr(
|
||||||
&'_ self,
|
&'_ self,
|
||||||
) -> Box<impl Parser<'src, TokenInput<'src>, PlaceOrValue, ParserExtra> + Clone + use<'src, 'b>>
|
) -> impl Parser<'src, TokenInput<'src>, PlaceOrValue, ParserExtra> + Clone + use<'src, 'b>
|
||||||
{
|
{
|
||||||
let assignment = choice((
|
let assignment = choice((
|
||||||
just(Token::Equal),
|
just(Token::Equal),
|
||||||
|
|
@ -780,22 +799,6 @@ where
|
||||||
|
|
||||||
let r#as = just(Token::As).ignore_then(type_parser::<ParserExtra>());
|
let r#as = just(Token::As).ignore_then(type_parser::<ParserExtra>());
|
||||||
|
|
||||||
fn into_value(idx: PlaceOrValue, e: &mut E) -> PlaceOrValue {
|
|
||||||
match idx {
|
|
||||||
PlaceOrValue::Place(index) => e.state().push(AstNode::PlaceToValue { expr: index }),
|
|
||||||
PlaceOrValue::Value(index) => index,
|
|
||||||
}
|
|
||||||
.as_value()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_place(idx: PlaceOrValue, e: &mut E) -> PlaceOrValue {
|
|
||||||
match idx {
|
|
||||||
PlaceOrValue::Value(index) => e.state().push(AstNode::ValueToPlace { expr: index }),
|
|
||||||
PlaceOrValue::Place(index) => index,
|
|
||||||
}
|
|
||||||
.as_place()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: postfix: function call, field access, array subscript
|
// TODO: postfix: function call, field access, array subscript
|
||||||
let _expr = self.expr.clone();
|
let _expr = self.expr.clone();
|
||||||
|
|
||||||
|
|
@ -806,12 +809,12 @@ where
|
||||||
just(Token::CloseSquareBracket),
|
just(Token::CloseSquareBracket),
|
||||||
)
|
)
|
||||||
// subscript takes a value as the index
|
// subscript takes a value as the index
|
||||||
.map_with(into_value);
|
.map_with(Self::into_value);
|
||||||
|
|
||||||
let arguments = _expr
|
let arguments = _expr
|
||||||
.clone()
|
.clone()
|
||||||
// arguments take values
|
// arguments take values
|
||||||
.map_with(into_value)
|
.map_with(Self::into_value)
|
||||||
.map(PlaceOrValue::index)
|
.map(PlaceOrValue::index)
|
||||||
.separated_by(just(Token::Comma))
|
.separated_by(just(Token::Comma))
|
||||||
.allow_trailing()
|
.allow_trailing()
|
||||||
|
|
@ -823,7 +826,7 @@ where
|
||||||
let assignment_expr = self.simple_expr().pratt((
|
let assignment_expr = self.simple_expr().pratt((
|
||||||
postfix(100, subscript, |expr, index: PlaceOrValue, e: &mut E| {
|
postfix(100, subscript, |expr, index: PlaceOrValue, e: &mut E| {
|
||||||
let node = AstNode::Subscript {
|
let node = AstNode::Subscript {
|
||||||
expr: into_value(expr, e).index(),
|
expr: Self::into_value(expr, e).index(),
|
||||||
index: index.index(),
|
index: index.index(),
|
||||||
};
|
};
|
||||||
// subscript yields a place
|
// subscript yields a place
|
||||||
|
|
@ -831,7 +834,7 @@ where
|
||||||
}),
|
}),
|
||||||
postfix(100, arguments, |callee, arguments, e: &mut E| {
|
postfix(100, arguments, |callee, arguments, e: &mut E| {
|
||||||
let node = AstNode::CallExpr {
|
let node = AstNode::CallExpr {
|
||||||
callee: into_value(callee, e).index(),
|
callee: Self::into_value(callee, e).index(),
|
||||||
arguments,
|
arguments,
|
||||||
};
|
};
|
||||||
// function call yields a value
|
// function call yields a value
|
||||||
|
|
@ -839,7 +842,7 @@ where
|
||||||
}),
|
}),
|
||||||
postfix(100, field, |expr, field: &str, e: &mut E| {
|
postfix(100, field, |expr, field: &str, e: &mut E| {
|
||||||
let node = AstNode::FieldAccess {
|
let node = AstNode::FieldAccess {
|
||||||
expr: into_place(expr, e).index(),
|
expr: Self::into_place(expr, e).index(),
|
||||||
field: field.to_string(),
|
field: field.to_string(),
|
||||||
};
|
};
|
||||||
// field access yields a place
|
// field access yields a place
|
||||||
|
|
@ -847,15 +850,15 @@ where
|
||||||
}),
|
}),
|
||||||
postfix(99, r#as, |expr, ty, e: &mut E| {
|
postfix(99, r#as, |expr, ty, e: &mut E| {
|
||||||
let node = AstNode::ExplicitCast {
|
let node = AstNode::ExplicitCast {
|
||||||
expr: into_value(expr, e).index(),
|
expr: Self::into_value(expr, e).index(),
|
||||||
ty,
|
ty,
|
||||||
};
|
};
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
prefix(95, prefixes, |op, expr, e: &mut E| {
|
prefix(95, prefixes, |op, expr, e: &mut E| {
|
||||||
let node = match op {
|
let node = match op {
|
||||||
Token::Bang => AstNode::Not(into_value(expr, e).index()),
|
Token::Bang => AstNode::Not(Self::into_value(expr, e).index()),
|
||||||
Token::Minus => AstNode::Negate(into_value(expr, e).index()),
|
Token::Minus => AstNode::Negate(Self::into_value(expr, e).index()),
|
||||||
Token::Star => {
|
Token::Star => {
|
||||||
return e
|
return e
|
||||||
.state()
|
.state()
|
||||||
|
|
@ -863,15 +866,15 @@ where
|
||||||
.as_place();
|
.as_place();
|
||||||
}
|
}
|
||||||
Token::Ampersand => AstNode::AddressOf {
|
Token::Ampersand => AstNode::AddressOf {
|
||||||
expr: into_place(expr, e).index(),
|
expr: Self::into_place(expr, e).index(),
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(90), multiplicative, |left, op, right, e: &mut E| {
|
infix(left(90), multiplicative, |left, op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = match op {
|
let node = match op {
|
||||||
Token::Star => AstNode::Multiply { left, right },
|
Token::Star => AstNode::Multiply { left, right },
|
||||||
Token::Slash => AstNode::Divide { left, right },
|
Token::Slash => AstNode::Divide { left, right },
|
||||||
|
|
@ -881,8 +884,8 @@ where
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(80), additive, |left, op, right, e: &mut E| {
|
infix(left(80), additive, |left, op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = match op {
|
let node = match op {
|
||||||
Token::Plus => AstNode::Add { left, right },
|
Token::Plus => AstNode::Add { left, right },
|
||||||
Token::Minus => AstNode::Subtract { left, right },
|
Token::Minus => AstNode::Subtract { left, right },
|
||||||
|
|
@ -891,8 +894,8 @@ where
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(70), shift, |left, op, right, e: &mut E| {
|
infix(left(70), shift, |left, op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = match op {
|
let node = match op {
|
||||||
Token::LessLess => AstNode::ShiftLeft { left, right },
|
Token::LessLess => AstNode::ShiftLeft { left, right },
|
||||||
Token::GreaterGreater => AstNode::ShiftRight { left, right },
|
Token::GreaterGreater => AstNode::ShiftRight { left, right },
|
||||||
|
|
@ -901,8 +904,8 @@ where
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(60), relational, |left, op, right, e: &mut E| {
|
infix(left(60), relational, |left, op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = match op {
|
let node = match op {
|
||||||
Token::Less => AstNode::Less { left, right },
|
Token::Less => AstNode::Less { left, right },
|
||||||
Token::LessEqual => AstNode::LessEq { left, right },
|
Token::LessEqual => AstNode::LessEq { left, right },
|
||||||
|
|
@ -913,8 +916,8 @@ where
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(50), equality, |left, op, right, e: &mut E| {
|
infix(left(50), equality, |left, op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = match op {
|
let node = match op {
|
||||||
Token::EqualEqual => AstNode::Eq { left, right },
|
Token::EqualEqual => AstNode::Eq { left, right },
|
||||||
Token::BangEqual => AstNode::NotEq { left, right },
|
Token::BangEqual => AstNode::NotEq { left, right },
|
||||||
|
|
@ -923,42 +926,42 @@ where
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(40), and, |left, _op, right, e: &mut E| {
|
infix(left(40), and, |left, _op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = AstNode::BitAnd { left, right };
|
let node = AstNode::BitAnd { left, right };
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(30), xor, |left, _op, right, e: &mut E| {
|
infix(left(30), xor, |left, _op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = AstNode::BitXor { left, right };
|
let node = AstNode::BitXor { left, right };
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(20), or, |left, _op, right, e: &mut E| {
|
infix(left(20), or, |left, _op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = AstNode::BitOr { left, right };
|
let node = AstNode::BitOr { left, right };
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(10), logical_and, |left, _op, right, e: &mut E| {
|
infix(left(10), logical_and, |left, _op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = AstNode::LogicalAnd { left, right };
|
let node = AstNode::LogicalAnd { left, right };
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(left(5), logical_or, |left, _op, right, e: &mut E| {
|
infix(left(5), logical_or, |left, _op, right, e: &mut E| {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = AstNode::LogicalOr { left, right };
|
let node = AstNode::LogicalOr { left, right };
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
}),
|
}),
|
||||||
infix(right(1), assignment, |left, op, right, e: &mut E| {
|
infix(right(1), assignment, |left, op, right, e: &mut E| {
|
||||||
let dest = into_place(left, e).index();
|
let dest = Self::into_place(left, e).index();
|
||||||
let right = into_value(right, e).index();
|
let right = Self::into_value(right, e).index();
|
||||||
let node = if op == Token::Equal {
|
let node = if op == Token::Equal {
|
||||||
AstNode::Assignment { dest, expr: right }
|
AstNode::Assignment { dest, expr: right }
|
||||||
} else {
|
} else {
|
||||||
let left = into_value(left, e).index();
|
let left = Self::into_value(left, e).index();
|
||||||
let right = match op {
|
let right = match op {
|
||||||
Token::PlusEqual => e.state().push(AstNode::Add { left, right }),
|
Token::PlusEqual => e.state().push(AstNode::Add { left, right }),
|
||||||
Token::MinusEqual => e.state().push(AstNode::Subtract { left, right }),
|
Token::MinusEqual => e.state().push(AstNode::Subtract { left, right }),
|
||||||
|
|
@ -980,17 +983,43 @@ where
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
||||||
let else_expr = just(Token::Else).ignore_then(_expr.clone());
|
let expr = choice((self.if_else_expr(), assignment_expr)).labelled("expression");
|
||||||
|
|
||||||
let if_expr = just(Token::If)
|
expr
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_else_expr(
|
||||||
|
&self,
|
||||||
|
) -> impl Parser<'src, TokenInput<'src>, PlaceOrValue, ParserExtra> + Clone + use<'src, 'b>
|
||||||
|
{
|
||||||
|
let else_expr = just(Token::Else).ignore_then(self.expr());
|
||||||
|
|
||||||
|
just(Token::If)
|
||||||
.ignore_then(
|
.ignore_then(
|
||||||
_expr
|
self.expr()
|
||||||
.clone()
|
.map_with(Self::into_value)
|
||||||
.map_with(into_value)
|
|
||||||
.map(PlaceOrValue::index)
|
.map(PlaceOrValue::index)
|
||||||
.delimited_by(just(Token::OpenParens), just(Token::CloseParens)),
|
.delimited_by(just(Token::OpenParens), just(Token::CloseParens))
|
||||||
|
.recover_with(via_parser({
|
||||||
|
// parenthised recovery:
|
||||||
|
recursive(|recovery| {
|
||||||
|
just(Token::OpenParens)
|
||||||
|
.ignored()
|
||||||
|
.ignore_then(choice((
|
||||||
|
none_of([Token::CloseParens, Token::OpenParens]).map(|_| ()),
|
||||||
|
recovery.map(|_| ()),
|
||||||
|
)))
|
||||||
|
.repeated()
|
||||||
|
.then_ignore(just(Token::CloseParens))
|
||||||
|
})
|
||||||
|
.map_with(|_, e: &mut E| {
|
||||||
|
e.state().push(AstNode::Error {
|
||||||
|
err: Box::new(ParseError::IfCondition),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})),
|
||||||
)
|
)
|
||||||
.then(_expr.clone())
|
.then(self.expr())
|
||||||
.then(else_expr.or_not())
|
.then(else_expr.or_not())
|
||||||
.map_with(|((condition, then), or), e: &mut E| {
|
.map_with(|((condition, then), or), e: &mut E| {
|
||||||
// TODO: determine placeness from branches
|
// TODO: determine placeness from branches
|
||||||
|
|
@ -1000,11 +1029,7 @@ where
|
||||||
r#else: or.map(PlaceOrValue::index),
|
r#else: or.map(PlaceOrValue::index),
|
||||||
};
|
};
|
||||||
e.state().push(node).as_value()
|
e.state().push(node).as_value()
|
||||||
});
|
})
|
||||||
|
|
||||||
let expr = choice((if_expr, assignment_expr)).labelled("expression");
|
|
||||||
|
|
||||||
Box::new(expr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn global_decl(&self) -> impl Parser<'src, TokenInput<'src>, Index, ParserExtra> + Clone {
|
fn global_decl(&self) -> impl Parser<'src, TokenInput<'src>, Index, ParserExtra> + Clone {
|
||||||
|
|
@ -1071,7 +1096,7 @@ mod pretty;
|
||||||
mod tests {
|
mod tests {
|
||||||
use chumsky::{Parser, extra::SimpleState};
|
use chumsky::{Parser, extra::SimpleState};
|
||||||
|
|
||||||
use crate::{Ast, AstNode, new_token_input, pretty, type_parser};
|
use crate::{Ast, AstNode, ParserCtx, ParserExtra, new_token_input, pretty, type_parser};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn print_ast_node_size() {
|
fn print_ast_node_size() {
|
||||||
|
|
@ -1131,24 +1156,51 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_ast<'src, T>(
|
||||||
|
tokens: crate::TokenInput<'src>,
|
||||||
|
parser: impl Parser<'src, crate::TokenInput<'src>, T, ParserExtra>,
|
||||||
|
) {
|
||||||
|
let mut state = SimpleState(Ast::new());
|
||||||
|
let out = parser.parse_with_state(tokens, &mut state);
|
||||||
|
let ast = state.0;
|
||||||
|
let mut pretty = pretty::PrettyPrint::new();
|
||||||
|
pretty.print(&ast);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_exprs() {
|
fn parse_exprs() {
|
||||||
let ctx = crate::ParserCtx::new();
|
let ctx = crate::ParserCtx::new();
|
||||||
let print_ast = |tokens| {
|
|
||||||
let mut state = SimpleState(Ast::new());
|
|
||||||
let out = ctx.function().parse_with_state(tokens, &mut state).unwrap();
|
|
||||||
let ast = state.0;
|
|
||||||
let mut pretty = pretty::PrettyPrint::new();
|
|
||||||
pretty.print(&ast);
|
|
||||||
};
|
|
||||||
|
|
||||||
print_ast(new_token_input(
|
print_ast(new_token_input("true"), ctx.expr());
|
||||||
r#"
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_fns() {
|
||||||
|
let ctx = crate::ParserCtx::new();
|
||||||
|
|
||||||
|
print_ast(
|
||||||
|
new_token_input(
|
||||||
|
r#"
|
||||||
fn my_function(a: i32, b: *const u8) -> i32 {
|
fn my_function(a: i32, b: *const u8) -> i32 {
|
||||||
x = a + 1;
|
x = a + 1;
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
));
|
),
|
||||||
|
ctx.function(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_if_expr() {
|
||||||
|
let ctx = crate::ParserCtx::new();
|
||||||
|
print_ast(
|
||||||
|
new_token_input(
|
||||||
|
r#"
|
||||||
|
if (true) 1 / 2 else true
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
ctx.if_else_expr(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -277,13 +277,22 @@ impl PrettyPrint {
|
||||||
self.with_indent([*condition].into_iter(), |this, idx| {
|
self.with_indent([*condition].into_iter(), |this, idx| {
|
||||||
this.stuff(ast, idx);
|
this.stuff(ast, idx);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.push_line("THEN".to_string());
|
||||||
if let Some(r#else) = r#else {
|
if let Some(r#else) = r#else {
|
||||||
self.stuff(ast, *then);
|
self.with_indent(core::iter::once(*then), |this, idx| {
|
||||||
|
this.stuff(ast, idx);
|
||||||
|
});
|
||||||
*self.indents.last_mut().unwrap() = Indent::End;
|
*self.indents.last_mut().unwrap() = Indent::End;
|
||||||
self.stuff(ast, *r#else);
|
self.push_line("ELSE".to_string());
|
||||||
|
self.with_indent(core::iter::once(*r#else), |this, idx| {
|
||||||
|
this.stuff(ast, idx);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
*self.indents.last_mut().unwrap() = Indent::End;
|
*self.indents.last_mut().unwrap() = Indent::End;
|
||||||
self.stuff(ast, *then);
|
self.with_indent(core::iter::once(*then), |this, idx| {
|
||||||
|
this.stuff(ast, idx);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
self.indents.pop();
|
self.indents.pop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue