Impl do parsing

This commit is contained in:
Shunsuke Shibayama 2022-08-28 11:32:50 +09:00
parent 3036637e48
commit 1985281e26
3 changed files with 48 additions and 1 deletions

View file

@ -2283,6 +2283,15 @@ impl LambdaSignature {
bounds, bounds,
} }
} }
pub fn do_sig(do_symbol: &Token) -> Self {
let parens = Some((do_symbol.clone(), do_symbol.clone()));
Self::new(
Params::new(vec![], vec![], parens),
None,
TypeBoundSpecs::empty(),
)
}
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]

View file

@ -53,6 +53,7 @@ enum PosOrKwArg {
pub enum Side { pub enum Side {
LhsAssign, LhsAssign,
LhsLambda, LhsLambda,
Do,
Rhs, Rhs,
} }
@ -156,6 +157,15 @@ impl Parser {
/// `(Rhs) , (LhsLambda) ->` /// `(Rhs) , (LhsLambda) ->`
/// `(Rhs) (LhsLambda) -> (Rhs);` /// `(Rhs) (LhsLambda) -> (Rhs);`
fn cur_side(&self) -> Side { fn cur_side(&self) -> Side {
match self.peek() {
Some(t) => {
let name = &t.inspect()[..];
if name == "do" || name == "do!" {
return Side::Do;
}
}
_ => {}
}
// 以降に=, ->などがないならすべて右辺値 // 以降に=, ->などがないならすべて右辺値
let opt_equal_pos = self.tokens.iter().skip(1).position(|t| t.is(Equal)); let opt_equal_pos = self.tokens.iter().skip(1).position(|t| t.is(Equal));
let opt_arrow_pos = self let opt_arrow_pos = self
@ -1655,6 +1665,29 @@ impl Parser {
Ok(Lambda::new(sig, op, body, self.counter)) Ok(Lambda::new(sig, op, body, self.counter))
} }
fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> {
debug_call_info!(self);
let do_symbol = self.lpop();
let sig = LambdaSignature::do_sig(&do_symbol);
let op = match &do_symbol.inspect()[..] {
"do" => Token::from_str(FuncArrow, "->"),
"do!" => Token::from_str(ProcArrow, "=>"),
_ => todo!(),
};
if self.cur_is(Colon) {
self.lpop();
let body = self.try_reduce_block().map_err(|_| self.stack_dec())?;
self.counter.inc();
self.level -= 1;
Ok(Lambda::new(sig, op, body, self.counter))
} else {
let expr = self.try_reduce_expr().map_err(|_| self.stack_dec())?;
let block = Block::new(vec![expr]);
self.level -= 1;
Ok(Lambda::new(sig, op, block, self.counter))
}
}
fn try_reduce_expr(&mut self) -> ParseResult<Expr> { fn try_reduce_expr(&mut self) -> ParseResult<Expr> {
debug_call_info!(self); debug_call_info!(self);
let mut stack = Vec::<ExprOrOp>::new(); let mut stack = Vec::<ExprOrOp>::new();
@ -1669,6 +1702,11 @@ impl Parser {
self.level -= 1; self.level -= 1;
Ok(Expr::Lambda(lambda)) Ok(Expr::Lambda(lambda))
} }
Side::Do => {
let lambda = self.try_reduce_do_block().map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(Expr::Lambda(lambda))
}
Side::Rhs => { Side::Rhs => {
stack.push(ExprOrOp::Expr( stack.push(ExprOrOp::Expr(
self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?, self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?,

View file

@ -1,7 +1,7 @@
if True, () -> log "hello" if True, () -> log "hello"
if! True, () => print! "hello" if! True, () => print! "hello"
# if True, () => print! "hello" # this should cause a type error # if True, () => print! "hello" # this should cause a type error
if True, () -> if True, do:
_x = "aaa" + input!() # this should cause an effect error _x = "aaa" + input!() # this should cause an effect error
print! "hello" # this should cause an effect error print! "hello" # this should cause an effect error