forked from AbleScript/ablescript
Implement function calls
- And printing - Revised terminology in Lexer - Control flow
This commit is contained in:
parent
b6bce72b94
commit
b7464f6ad3
|
@ -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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
126
src/parser.rs
126
src/parser.rs
|
@ -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()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue