Added Assignable support in parser / AST

This commit is contained in:
Erin 2021-10-12 22:14:20 +02:00 committed by ondra05
parent 1a5d2edee1
commit ea79e805f2
3 changed files with 63 additions and 11 deletions

View file

@ -38,6 +38,18 @@ impl Hash for Ident {
}
}
#[derive(Debug, PartialEq, Clone, Hash)]
pub struct Assignable {
pub ident: Ident,
pub kind: AssignableKind,
}
#[derive(Debug, PartialEq, Clone, Hash)]
pub enum AssignableKind {
Variable,
Cart { indices: Vec<Expr> },
}
#[derive(Debug, PartialEq, Clone, Hash)]
pub struct Block {
pub block: Vec<Stmt>,
@ -80,7 +92,7 @@ pub enum StmtKind {
init: Option<Expr>,
},
Assign {
ident: Ident,
assignable: Assignable,
value: Expr,
},

View file

@ -197,7 +197,11 @@ impl ExecEnv {
self.decl_var(&ident.ident, init);
}
StmtKind::Functio { ident, params, body } => {
StmtKind::Functio {
ident,
params,
body,
} => {
self.decl_var(
&ident.ident,
Value::Functio(Functio::AbleFunctio {
@ -240,9 +244,10 @@ impl ExecEnv {
HaltStatus::Hopback(_) => continue,
}
},
StmtKind::Assign { ident, value } => {
StmtKind::Assign { assignable, value } => {
// TODO: Assigning to carts
let value = self.eval_expr(value)?;
self.get_var_mut(ident)?.value.replace(value);
self.get_var_mut(&assignable.ident)?.value.replace(value);
}
StmtKind::Break => {
return Ok(HaltStatus::Break(stmt.span.clone()));

View file

@ -355,15 +355,25 @@ impl<'source> Parser<'source> {
// Variable Assignment
Token::Equal => {
if let Some(Expr {
kind: ExprKind::Variable(ident),
span,
}) = buf
{
let assignable = buf.take().and_then(|buf| match buf.kind {
ExprKind::Variable(ident) => Some(Assignable {
ident: Ident::new(ident, buf.span),
kind: AssignableKind::Variable,
}),
ExprKind::Index { expr, index } => self.cart_assignable_flow(*expr, *index),
_ => None,
});
if let Some(assignable) = assignable {
break StmtKind::Assign {
ident: Ident::new(ident, span),
assignable,
value: self.expr_flow(Token::Semicolon)?,
};
} else {
return Err(Error::new(
ErrorKind::UnexpectedToken(Token::Equal),
self.lexer.span(),
));
}
}
@ -385,6 +395,27 @@ impl<'source> Parser<'source> {
Ok(r)
}
/// Parse Cart Assignable flow
fn cart_assignable_flow(&mut self, mut buf: Expr, index: Expr) -> Option<Assignable> {
let mut indices = vec![index];
let ident = loop {
match buf.kind {
ExprKind::Variable(ident) => break ident,
ExprKind::Index { expr, index } => {
indices.push(*index);
buf = *expr;
}
_ => return None,
}
};
indices.reverse();
Some(Assignable {
ident: Ident::new(ident, buf.span),
kind: AssignableKind::Cart { indices },
})
}
/// Parse If flow
///
/// Consists of condition and block, there is no else
@ -431,7 +462,11 @@ impl<'source> Parser<'source> {
let body = self.get_block()?;
Ok(StmtKind::Functio { ident, params, body })
Ok(StmtKind::Functio {
ident,
params,
body,
})
}
/// Parse BF function declaration