Implement function calls

- And printing
- Revised terminology in Lexer
- Control flow
This commit is contained in:
Erin 2021-06-07 11:00:06 +02:00 committed by ondra05
parent b6bce72b94
commit b7464f6ad3
3 changed files with 123 additions and 16 deletions

View file

@ -77,8 +77,8 @@ impl Stmt {
/// like math and logical operations or values. /// like math and logical operations or values.
#[derive(Debug)] #[derive(Debug)]
pub struct Expr { pub struct Expr {
kind: ExprKind, pub kind: ExprKind,
span: Span, pub span: Span,
} }
#[derive(Debug)] #[derive(Debug)]
@ -116,7 +116,6 @@ pub enum BinOpKind {
impl BinOpKind { impl BinOpKind {
pub fn from_token(t: crate::lexer::Token) -> Result<Self, crate::error::ErrorKind> { pub fn from_token(t: crate::lexer::Token) -> Result<Self, crate::error::ErrorKind> {
use crate::lexer::Token; use crate::lexer::Token;
use crate::error::*;
match t { match t {
Token::Plus => Ok(Self::Add), Token::Plus => Ok(Self::Add),
@ -129,7 +128,7 @@ impl BinOpKind {
Token::NotEqual => Ok(Self::NotEqual), Token::NotEqual => Ok(Self::NotEqual),
Token::And => Ok(Self::And), Token::And => Ok(Self::And),
Token::Or => Ok(Self::Or), Token::Or => Ok(Self::Or),
t=> Err(ErrorKind::UnexpectedToken(t)), t => Err(crate::error::ErrorKind::UnexpectedToken(t)),
} }
} }
} }

View file

@ -76,11 +76,11 @@ pub enum Token {
/// Brain fuck FFI /// Brain fuck FFI
#[token("bff")] #[token("bff")]
BfFunction, Bff,
/// Variable bro /// Variable bro
#[token("var")] #[token("var")]
Variable, Var,
/// Prints the preceding things /// Prints the preceding things
#[token("print")] #[token("print")]
@ -187,7 +187,7 @@ mod tests {
LeftParen, LeftParen,
RightParen, RightParen,
LeftCurly, LeftCurly,
Variable, Var,
Identifier("a".to_owned()), Identifier("a".to_owned()),
Equal, Equal,
Integer(3), Integer(3),

View file

@ -48,6 +48,29 @@ impl<'source> Parser<'source> {
self.functio_flow()?, self.functio_flow()?,
start..self.lexer.span().end, start..self.lexer.span().end,
)), )),
Token::Var => Ok(Stmt::new(self.var_flow()?, start..self.lexer.span().end)),
Token::Melo => Ok(Stmt::new(self.melo_flow()?, start..self.lexer.span().end)),
Token::Loop => Ok(Stmt::new(self.loop_flow()?, start..self.lexer.span().end)),
Token::Break => Ok(Stmt::new(
self.semi_terminated(StmtKind::Break)?,
start..self.lexer.span().end,
)),
Token::HopBack => Ok(Stmt::new(
self.semi_terminated(StmtKind::HopBack)?,
start..self.lexer.span().end,
)),
Token::Identifier(_)
| Token::Char
| Token::String(_)
| Token::Integer(_)
| Token::Abool(_)
| Token::Bool(_)
| Token::LeftParen => Ok(Stmt::new(
self.value_flow(token)?,
start..self.lexer.span().end,
)),
t => Err(Error { t => Err(Error {
kind: ErrorKind::UnexpectedToken(t), kind: ErrorKind::UnexpectedToken(t),
span: start..self.lexer.span().end, span: start..self.lexer.span().end,
@ -55,6 +78,14 @@ impl<'source> Parser<'source> {
} }
} }
/// Require statement to be semicolon terminated
///
/// Utility function for short statements
fn semi_terminated(&mut self, stmt_kind: StmtKind) -> Result<StmtKind, Error> {
self.require(Token::Semicolon)?;
Ok(stmt_kind)
}
/// Require next item to be equal with expected one /// Require next item to be equal with expected one
fn require(&mut self, expected: Token) -> Result<(), Error> { fn require(&mut self, expected: Token) -> Result<(), Error> {
match self.lexer.next() { match self.lexer.next() {
@ -121,11 +152,8 @@ impl<'source> Parser<'source> {
| Token::GreaterThan | Token::GreaterThan
| Token::And | Token::And
| Token::Or => Ok(Expr::new( | Token::Or => Ok(Expr::new(
self.op_flow( self.binop_flow(
match BinOpKind::from_token(token) { BinOpKind::from_token(token).map_err(|e| Error::new(e, self.lexer.span()))?,
Ok(op) => op,
Err(e) => return Err(Error::new(e, self.lexer.span())),
},
buf, buf,
)?, )?,
start..self.lexer.span().end, start..self.lexer.span().end,
@ -151,7 +179,7 @@ impl<'source> Parser<'source> {
/// Generates operation from LHS buffer and next expression as RHS /// Generates operation from LHS buffer and next expression as RHS
/// ///
/// This is unaware of precedence, as AbleScript do not have it /// This is unaware of precedence, as AbleScript do not have it
fn op_flow(&mut self, kind: BinOpKind, lhs: &mut Option<Expr>) -> Result<ExprKind, Error> { fn binop_flow(&mut self, kind: BinOpKind, lhs: &mut Option<Expr>) -> Result<ExprKind, Error> {
Ok(ExprKind::BinOp { Ok(ExprKind::BinOp {
lhs: Box::new( lhs: Box::new(
lhs.take() lhs.take()
@ -177,7 +205,7 @@ impl<'source> Parser<'source> {
} }
/// Parse a list of statements between curly braces /// Parse a list of statements between curly braces
fn parse_block(&mut self) -> Result<Block, Error> { fn get_block(&mut self) -> Result<Block, Error> {
self.require(Token::LeftCurly)?; self.require(Token::LeftCurly)?;
let mut block = vec![]; let mut block = vec![];
@ -190,6 +218,31 @@ impl<'source> Parser<'source> {
Ok(Block { block }) Ok(Block { block })
} }
/// If Statement parser gets any kind of value (Identifier or Literal)
/// It cannot parse it as it do not parse expressions. Instead of it it
/// will parse it to function call or print statement.
fn value_flow(&mut self, init: Token) -> Result<StmtKind, Error> {
let mut buf = Some(self.parse_expr(init, &mut None)?);
let r = loop {
match self.lexer.next().ok_or(Error::unexpected_eof())? {
Token::Print => break StmtKind::Print(buf.take().unwrap()),
Token::LeftParen => {
if let Some(Expr {
kind: ExprKind::Variable(iden),
span,
}) = buf
{
break self.functio_call_flow(Iden::new(iden, span))?;
}
}
t => buf = Some(self.parse_expr(t, &mut buf)?),
}
};
self.require(Token::Semicolon)?;
Ok(r)
}
/// Parse If flow /// Parse If flow
/// ///
/// Consists of condition and block, there is no else /// Consists of condition and block, there is no else
@ -198,7 +251,7 @@ impl<'source> Parser<'source> {
let cond = self.expr_flow(Token::RightParen)?; let cond = self.expr_flow(Token::RightParen)?;
let body = self.parse_block()?; let body = self.get_block()?;
Ok(StmtKind::If { cond, body }) Ok(StmtKind::If { cond, body })
} }
@ -233,8 +286,63 @@ impl<'source> Parser<'source> {
} }
} }
let body = self.parse_block()?; let body = self.get_block()?;
Ok(StmtKind::Functio { iden, args, body }) Ok(StmtKind::Functio { iden, args, body })
} }
/// Parse functio call flow
fn functio_call_flow(&mut self, iden: Iden) -> Result<StmtKind, Error> {
let mut args = vec![];
let mut buf = None;
loop {
match self.lexer.next().ok_or(Error::unexpected_eof())? {
Token::RightParen => {
if let Some(expr) = buf.take() {
args.push(expr)
}
break;
}
Token::Comma => match buf.take() {
Some(expr) => args.push(expr),
None => {
return Err(Error::new(
ErrorKind::UnexpectedToken(Token::Comma),
self.lexer.span(),
))
}
},
t => buf = Some(self.parse_expr(t, &mut buf)?),
}
}
Ok(StmtKind::Call { iden, args })
}
/// Parse variable declaration
fn var_flow(&mut self) -> Result<StmtKind, Error> {
let iden = self.get_iden()?;
let init = match self.lexer.next().ok_or(Error::unexpected_eof())? {
Token::Equal => Some(self.expr_flow(Token::Semicolon)?),
Token::Semicolon => None,
t => return Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
};
Ok(StmtKind::Var { iden, init })
}
/// Parse Melo flow
fn melo_flow(&mut self) -> Result<StmtKind, Error> {
let iden = self.get_iden()?;
self.semi_terminated(StmtKind::Melo(iden))
}
/// Parse loop flow
///
/// `loop` is an infinite loop, no condition, only body
fn loop_flow(&mut self) -> Result<StmtKind, Error> {
Ok(StmtKind::Loop {
body: self.get_block()?,
})
}
} }