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)] #[derive(Debug, PartialEq, Clone, Hash)]
pub struct Block { pub struct Block {
pub block: Vec<Stmt>, pub block: Vec<Stmt>,
@ -80,7 +92,7 @@ pub enum StmtKind {
init: Option<Expr>, init: Option<Expr>,
}, },
Assign { Assign {
ident: Ident, assignable: Assignable,
value: Expr, value: Expr,
}, },

View file

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

View file

@ -355,15 +355,25 @@ impl<'source> Parser<'source> {
// Variable Assignment // Variable Assignment
Token::Equal => { Token::Equal => {
if let Some(Expr { let assignable = buf.take().and_then(|buf| match buf.kind {
kind: ExprKind::Variable(ident), ExprKind::Variable(ident) => Some(Assignable {
span, ident: Ident::new(ident, buf.span),
}) = buf kind: AssignableKind::Variable,
{ }),
ExprKind::Index { expr, index } => self.cart_assignable_flow(*expr, *index),
_ => None,
});
if let Some(assignable) = assignable {
break StmtKind::Assign { break StmtKind::Assign {
ident: Ident::new(ident, span), assignable,
value: self.expr_flow(Token::Semicolon)?, 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) 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 /// Parse If flow
/// ///
/// Consists of condition and block, there is no else /// Consists of condition and block, there is no else
@ -431,7 +462,11 @@ impl<'source> Parser<'source> {
let body = self.get_block()?; let body = self.get_block()?;
Ok(StmtKind::Functio { ident, params, body }) Ok(StmtKind::Functio {
ident,
params,
body,
})
} }
/// Parse BF function declaration /// Parse BF function declaration