forked from AbleScript/ablescript
Deleted old parser
This commit is contained in:
parent
4bda25c9f3
commit
2c15f3dc17
|
@ -1,87 +0,0 @@
|
||||||
use crate::variables::Value;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
|
||||||
pub struct Iden(pub String);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum Item {
|
|
||||||
Expr(Expr),
|
|
||||||
Stmt(Stmt),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Expr> for Item {
|
|
||||||
fn from(e: Expr) -> Self {
|
|
||||||
Item::Expr(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Iden> for Item {
|
|
||||||
fn from(i: Iden) -> Self {
|
|
||||||
Item::Expr(Expr::Identifier(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Stmt> for Item {
|
|
||||||
fn from(s: Stmt) -> Self {
|
|
||||||
Item::Stmt(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum Expr {
|
|
||||||
Add { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Subtract { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Multiply { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Divide { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Lt { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Gt { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Eq { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Neq { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
And { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Or { left: Box<Expr>, right: Box<Expr> },
|
|
||||||
Not(Box<Expr>),
|
|
||||||
Literal(Value),
|
|
||||||
Identifier(Iden),
|
|
||||||
}
|
|
||||||
impl From<Iden> for Expr {
|
|
||||||
fn from(i: Iden) -> Self {
|
|
||||||
Self::Identifier(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum Stmt {
|
|
||||||
VariableDeclaration {
|
|
||||||
iden: Iden,
|
|
||||||
init: Option<Expr>,
|
|
||||||
},
|
|
||||||
FunctionDeclaration {
|
|
||||||
iden: Iden,
|
|
||||||
args: Vec<Iden>,
|
|
||||||
body: Vec<Item>,
|
|
||||||
},
|
|
||||||
BfFDeclaration {
|
|
||||||
iden: Iden,
|
|
||||||
body: String,
|
|
||||||
},
|
|
||||||
If {
|
|
||||||
cond: Expr,
|
|
||||||
body: Vec<Item>,
|
|
||||||
},
|
|
||||||
FunctionCall {
|
|
||||||
iden: Iden,
|
|
||||||
args: Vec<Expr>,
|
|
||||||
},
|
|
||||||
Loop {
|
|
||||||
body: Vec<Item>,
|
|
||||||
},
|
|
||||||
|
|
||||||
VarAssignment {
|
|
||||||
iden: Iden,
|
|
||||||
value: Expr,
|
|
||||||
},
|
|
||||||
Break,
|
|
||||||
HopBack,
|
|
||||||
Print(Expr),
|
|
||||||
Melo(Iden),
|
|
||||||
}
|
|
|
@ -1,311 +0,0 @@
|
||||||
pub mod item;
|
|
||||||
mod ops;
|
|
||||||
mod utils;
|
|
||||||
|
|
||||||
use item::Item;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
error::{Error, ErrorKind},
|
|
||||||
lexer::PeekableLexer,
|
|
||||||
parser::item::{Expr, Stmt},
|
|
||||||
variables::Value,
|
|
||||||
};
|
|
||||||
use crate::{lexer::Token, parser::item::Iden};
|
|
||||||
|
|
||||||
pub type ParseResult = Result<Item, Error>;
|
|
||||||
|
|
||||||
/// Parser structure / state machine
|
|
||||||
pub struct Parser<'a> {
|
|
||||||
lexer: PeekableLexer<'a>,
|
|
||||||
ast: Vec<Item>,
|
|
||||||
tdark: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
|
||||||
/// Create a new parser object
|
|
||||||
pub fn new(source: &'a str) -> Self {
|
|
||||||
Self {
|
|
||||||
lexer: PeekableLexer::lexer(source),
|
|
||||||
ast: Vec::new(),
|
|
||||||
tdark: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init(&mut self) -> Result<Vec<Item>, Error> {
|
|
||||||
loop {
|
|
||||||
let token = self.lexer.next();
|
|
||||||
|
|
||||||
match token {
|
|
||||||
Some(Token::Comment) => continue,
|
|
||||||
Some(Token::TDark) => {
|
|
||||||
let mut block = self.tdark_block()?;
|
|
||||||
self.ast.append(&mut block);
|
|
||||||
}
|
|
||||||
None => return Ok(self.ast.clone()),
|
|
||||||
_ => {
|
|
||||||
let item = self.parse_item(token)?;
|
|
||||||
self.ast.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_item(&mut self, token: Option<Token>) -> ParseResult {
|
|
||||||
if matches!(token, None) {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::EndOfTokenStream,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let token = token.unwrap();
|
|
||||||
let start = self.lexer.span().start;
|
|
||||||
|
|
||||||
match token {
|
|
||||||
Token::Identifier(_)
|
|
||||||
| Token::Aboolean(_)
|
|
||||||
| Token::Boolean(_)
|
|
||||||
| Token::Integer(_)
|
|
||||||
| Token::String(_)
|
|
||||||
| Token::Nul
|
|
||||||
| Token::LeftParenthesis
|
|
||||||
| Token::Assignment
|
|
||||||
| Token::LogNot => self.parse_ops(token),
|
|
||||||
|
|
||||||
// Control flow
|
|
||||||
Token::If => self.if_cond(),
|
|
||||||
Token::Loop => self.loop_block(),
|
|
||||||
|
|
||||||
Token::HopBack => {
|
|
||||||
self.require(Token::Semicolon)?;
|
|
||||||
Ok(Stmt::HopBack.into())
|
|
||||||
}
|
|
||||||
Token::Break => {
|
|
||||||
self.require(Token::Semicolon)?;
|
|
||||||
Ok(Stmt::Break.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Declarations
|
|
||||||
Token::Variable => self.variable_declaration(),
|
|
||||||
Token::Function => self.function_declaration(),
|
|
||||||
Token::BfFunction => self.bff_declaration(),
|
|
||||||
|
|
||||||
// Prefix keywords
|
|
||||||
// Melo - ban variable from next usage (runtime error)
|
|
||||||
Token::Melo => {
|
|
||||||
let e = self.require_iden()?;
|
|
||||||
self.require(Token::Semicolon)?;
|
|
||||||
Ok(Stmt::Melo(e).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => Err(Error {
|
|
||||||
kind: ErrorKind::SyntaxError("Unexpected token".to_owned()),
|
|
||||||
position: start..self.lexer.span().end,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse variable declaration
|
|
||||||
///
|
|
||||||
/// `var [iden] = [literal];`
|
|
||||||
fn variable_declaration(&mut self) -> ParseResult {
|
|
||||||
let iden = self.require_iden()?;
|
|
||||||
|
|
||||||
let peek = self.lexer.peek().clone();
|
|
||||||
let init = match peek {
|
|
||||||
Some(Token::Semicolon) => {
|
|
||||||
self.lexer.next();
|
|
||||||
None
|
|
||||||
}
|
|
||||||
Some(Token::Assignment) => {
|
|
||||||
self.lexer.next();
|
|
||||||
let next = self.lexer.next();
|
|
||||||
let mut value = self.parse_expr(next)?;
|
|
||||||
loop {
|
|
||||||
let peek = self.lexer.peek().clone();
|
|
||||||
value = match peek {
|
|
||||||
Some(Token::Semicolon) => break,
|
|
||||||
None => {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::EndOfTokenStream,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Some(t) => self.parse_operation(Some(t), value)?,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
self.lexer.next();
|
|
||||||
Some(value)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::SyntaxError("Unexpected token".to_owned()),
|
|
||||||
position: self.lexer.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Stmt::VariableDeclaration { iden, init }.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Declare function
|
|
||||||
///
|
|
||||||
/// `functio [iden] ([expr], [expr]) { ... }
|
|
||||||
fn function_declaration(&mut self) -> ParseResult {
|
|
||||||
let iden = self.require_iden()?;
|
|
||||||
|
|
||||||
self.require(Token::LeftParenthesis)?;
|
|
||||||
let mut args = vec![];
|
|
||||||
loop {
|
|
||||||
let next = self.lexer.next();
|
|
||||||
match next {
|
|
||||||
Some(Token::RightParenthesis) => break,
|
|
||||||
Some(Token::Identifier(i)) => args.push(Iden(i)),
|
|
||||||
_ => return Err(self.unexpected_token(None)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.require(Token::LeftBrace)?;
|
|
||||||
|
|
||||||
// Parse function body
|
|
||||||
let body = self.parse_body()?;
|
|
||||||
|
|
||||||
Ok(Stmt::FunctionDeclaration { iden, args, body }.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Declare BF FFI Function
|
|
||||||
///
|
|
||||||
/// `bff [iden] { ... }`
|
|
||||||
fn bff_declaration(&mut self) -> ParseResult {
|
|
||||||
let iden = self.require_iden()?;
|
|
||||||
self.require(Token::LeftBrace)?;
|
|
||||||
|
|
||||||
let mut body = String::new();
|
|
||||||
loop {
|
|
||||||
let token = {
|
|
||||||
match self.lexer.next() {
|
|
||||||
Some(t) => t,
|
|
||||||
None => {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::EndOfTokenStream,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
body.push_str(match token {
|
|
||||||
Token::OpGt
|
|
||||||
| Token::OpLt
|
|
||||||
| Token::Addition
|
|
||||||
| Token::Subtract
|
|
||||||
| Token::FullStop
|
|
||||||
| Token::Comma
|
|
||||||
| Token::LeftBracket
|
|
||||||
| Token::RightBracket => self.lexer.slice(),
|
|
||||||
Token::RightBrace => break,
|
|
||||||
_ => return Err(self.unexpected_token(None)),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Ok(Stmt::BfFDeclaration { iden, body }.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse If-stmt
|
|
||||||
pub fn if_cond(&mut self) -> ParseResult {
|
|
||||||
self.require(Token::LeftParenthesis)?;
|
|
||||||
let cond = self.parse_paren()?;
|
|
||||||
self.require(Token::LeftBrace)?;
|
|
||||||
|
|
||||||
let body = self.parse_body()?;
|
|
||||||
|
|
||||||
Ok(Stmt::If { cond, body }.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse loop
|
|
||||||
pub fn loop_block(&mut self) -> ParseResult {
|
|
||||||
self.require(Token::LeftBrace)?;
|
|
||||||
let body = self.parse_body()?;
|
|
||||||
|
|
||||||
Ok(Stmt::Loop { body }.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// T-Dark block parsing
|
|
||||||
pub fn tdark_block(&mut self) -> Result<Vec<Item>, Error> {
|
|
||||||
self.require(Token::LeftBrace)?;
|
|
||||||
self.tdark = true;
|
|
||||||
let mut body = Vec::new();
|
|
||||||
loop {
|
|
||||||
let token = {
|
|
||||||
match self.lexer.next() {
|
|
||||||
Some(t) => t,
|
|
||||||
None => {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::EndOfTokenStream,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if token == Token::RightBrace {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
body.push(self.parse_item(Some(token))?);
|
|
||||||
}
|
|
||||||
self.tdark = false;
|
|
||||||
Ok(body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use Expr::*;
|
|
||||||
use Stmt::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn control_flow() {
|
|
||||||
let code = r#"loop { var a = 3 + 2; if (a == 5) { break; } }"#;
|
|
||||||
|
|
||||||
let expected: &[Item] = &[Item::Stmt(Loop {
|
|
||||||
body: vec![
|
|
||||||
VariableDeclaration {
|
|
||||||
iden: Iden("a".to_owned()),
|
|
||||||
init: Some(Add {
|
|
||||||
left: Box::new(Literal(Value::Int(3))),
|
|
||||||
right: Box::new(Literal(Value::Int(2))),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
If {
|
|
||||||
cond: Eq {
|
|
||||||
left: Box::new(Iden("a".to_owned()).into()),
|
|
||||||
right: Box::new(Literal(Value::Int(5)).into()),
|
|
||||||
},
|
|
||||||
body: vec![Break.into()],
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
],
|
|
||||||
})];
|
|
||||||
let ast = Parser::new(code).init().unwrap();
|
|
||||||
|
|
||||||
assert_eq!(ast, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn tdark() {
|
|
||||||
let code = r#"T-Dark { var lang = nul; lang print; }"#;
|
|
||||||
let expected: &[Item] = &[
|
|
||||||
VariableDeclaration {
|
|
||||||
iden: Iden("script".to_owned()),
|
|
||||||
init: Some(Literal(Value::Nul)),
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
Print(Iden("script".to_owned()).into()).into(),
|
|
||||||
];
|
|
||||||
|
|
||||||
let ast = Parser::new(code).init().unwrap();
|
|
||||||
|
|
||||||
assert_eq!(ast, expected)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,197 +0,0 @@
|
||||||
use super::*;
|
|
||||||
|
|
||||||
type ExprResult = Result<Expr, Error>;
|
|
||||||
|
|
||||||
/// Generate infix expression by pattern left <op> right
|
|
||||||
///
|
|
||||||
/// Credits: `@! ! Reiter#4543`
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! gen_infix {
|
|
||||||
($($fn_name: ident => $type: tt);*$(;)?) => {$(
|
|
||||||
/// Generated function for infix operator
|
|
||||||
fn $fn_name(&mut self, left: Expr) -> ExprResult {
|
|
||||||
self.lexer.next();
|
|
||||||
let next = self.lexer.next();
|
|
||||||
let right = self.parse_expr(next)?;
|
|
||||||
Ok(Expr::$type { left: Box::new(left), right: Box::new(right) })
|
|
||||||
})*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
|
||||||
pub(super) fn parse_ops(&mut self, token: Token) -> ParseResult {
|
|
||||||
// Statements
|
|
||||||
match self.lexer.peek() {
|
|
||||||
Some(Token::LeftParenthesis) => return self.fn_call(token),
|
|
||||||
Some(Token::Assignment) => return self.parse_assignment(token),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut buf: Expr = self.parse_expr(Some(token))?;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let peek = self.lexer.peek().clone();
|
|
||||||
buf = match peek {
|
|
||||||
// Print statement
|
|
||||||
Some(Token::Print) => {
|
|
||||||
self.lexer.next();
|
|
||||||
self.require(Token::Semicolon)?;
|
|
||||||
return Ok(Stmt::Print(buf).into());
|
|
||||||
}
|
|
||||||
None => return Ok(buf.into()),
|
|
||||||
|
|
||||||
// An expression
|
|
||||||
_ => self.parse_operation(peek, buf)?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Match and perform
|
|
||||||
pub(super) fn parse_operation(&mut self, token: Option<Token>, buf: Expr) -> ExprResult {
|
|
||||||
match token {
|
|
||||||
Some(Token::Addition) => self.addition(buf),
|
|
||||||
Some(Token::Subtract) => self.subtract(buf),
|
|
||||||
Some(Token::Multiply) => self.multiply(buf),
|
|
||||||
Some(Token::Divide) => self.divide(buf),
|
|
||||||
Some(Token::OpLt) => self.cmplt(buf),
|
|
||||||
Some(Token::OpGt) => self.cmpgt(buf),
|
|
||||||
Some(Token::OpEq) => self.cmpeq(buf),
|
|
||||||
Some(Token::OpNeq) => self.cmpneq(buf),
|
|
||||||
Some(Token::LogAnd) => self.logand(buf),
|
|
||||||
Some(Token::LogOr) => self.logor(buf),
|
|
||||||
Some(Token::LeftParenthesis) => Err(Error {
|
|
||||||
kind: ErrorKind::SyntaxError("Function call isn't an expression!".to_owned()),
|
|
||||||
position: self.lexer.span(),
|
|
||||||
}),
|
|
||||||
Some(_) | None => Err(self.unexpected_token(None)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_assignment(&mut self, token: Token) -> ParseResult {
|
|
||||||
self.lexer.next();
|
|
||||||
|
|
||||||
// Extract identifier
|
|
||||||
let iden = if let Token::Identifier(i) = token {
|
|
||||||
Iden(i)
|
|
||||||
} else {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::InvalidIdentifier,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let next = self.lexer.next();
|
|
||||||
let mut value = self.parse_expr(next)?;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let peek = self.lexer.peek().clone();
|
|
||||||
value = match peek {
|
|
||||||
Some(Token::Semicolon) => break,
|
|
||||||
None => {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::EndOfTokenStream,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Some(t) => self.parse_operation(Some(t), value)?,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
self.lexer.next();
|
|
||||||
|
|
||||||
Ok(Stmt::VarAssignment { iden, value }.into())
|
|
||||||
}
|
|
||||||
// Generate infix
|
|
||||||
gen_infix! {
|
|
||||||
addition => Add;
|
|
||||||
subtract => Subtract;
|
|
||||||
multiply => Multiply;
|
|
||||||
divide => Divide;
|
|
||||||
cmplt => Lt;
|
|
||||||
cmpgt => Gt;
|
|
||||||
cmpeq => Eq;
|
|
||||||
cmpneq => Neq;
|
|
||||||
logand => And;
|
|
||||||
logor => Or;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ensure that input token is an expression
|
|
||||||
pub(super) fn parse_expr(&mut self, token: Option<Token>) -> ExprResult {
|
|
||||||
let token = token.ok_or(Error {
|
|
||||||
kind: ErrorKind::EndOfTokenStream,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
match token {
|
|
||||||
Token::Boolean(b) => Ok(Expr::Literal(Value::Bool(b))),
|
|
||||||
Token::Integer(i) => Ok(Expr::Literal(Value::Int(i))),
|
|
||||||
Token::String(s) => Ok(Expr::Literal(Value::Str(if self.tdark {
|
|
||||||
s.replace("lang", "script")
|
|
||||||
} else {
|
|
||||||
s
|
|
||||||
}))),
|
|
||||||
Token::Aboolean(a) => Ok(Expr::Literal(Value::Abool(a))),
|
|
||||||
Token::Identifier(i) => Ok(Expr::Identifier(Iden(if self.tdark {
|
|
||||||
i.replace("lang", "script")
|
|
||||||
} else {
|
|
||||||
i
|
|
||||||
}))),
|
|
||||||
Token::Nul => Ok(Expr::Literal(Value::Nul)),
|
|
||||||
Token::LogNot => {
|
|
||||||
let next = self.lexer.next();
|
|
||||||
Ok(Expr::Not(Box::new(self.parse_expr(next)?)))
|
|
||||||
}
|
|
||||||
Token::LeftParenthesis => self.parse_paren(),
|
|
||||||
t => Err(self.unexpected_token(Some(t))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse parenthesieted expression
|
|
||||||
pub(super) fn parse_paren(&mut self) -> ExprResult {
|
|
||||||
let next = self.lexer.next();
|
|
||||||
let mut buf = self.parse_expr(next)?;
|
|
||||||
loop {
|
|
||||||
let peek = self.lexer.peek().clone();
|
|
||||||
buf = match peek {
|
|
||||||
Some(Token::RightParenthesis) => {
|
|
||||||
self.lexer.next();
|
|
||||||
return Ok(buf);
|
|
||||||
}
|
|
||||||
None => return Ok(buf),
|
|
||||||
Some(t) => self.parse_operation(Some(t), buf)?,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse function call
|
|
||||||
fn fn_call(&mut self, token: Token) -> ParseResult {
|
|
||||||
let iden = if let Token::Identifier(i) = token {
|
|
||||||
Iden(i)
|
|
||||||
} else {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::InvalidIdentifier,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
self.lexer.next();
|
|
||||||
let mut args = Vec::new();
|
|
||||||
loop {
|
|
||||||
let next = self.lexer.next();
|
|
||||||
|
|
||||||
// No argument function
|
|
||||||
if matches!(next, Some(Token::RightParenthesis)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
args.push(self.parse_expr(next)?);
|
|
||||||
match self.lexer.next() {
|
|
||||||
Some(Token::RightParenthesis) => break,
|
|
||||||
Some(Token::Comma) => continue,
|
|
||||||
_ => return Err(self.unexpected_token(None)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.require(Token::Semicolon)?;
|
|
||||||
Ok(Stmt::FunctionCall { iden, args }.into())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
use crate::{
|
|
||||||
error::{Error, ErrorKind},
|
|
||||||
lexer::Token,
|
|
||||||
variables::Abool,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
item::{Iden, Item},
|
|
||||||
Parser,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn abool2num(abool: Abool) -> i32 {
|
|
||||||
match abool {
|
|
||||||
Abool::Never => -1,
|
|
||||||
Abool::Sometimes => 0,
|
|
||||||
Abool::Always => 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn num2abool(number: i32) -> Abool {
|
|
||||||
match number {
|
|
||||||
-1 => Abool::Never,
|
|
||||||
0 => Abool::Sometimes,
|
|
||||||
1 => Abool::Always,
|
|
||||||
_ => Abool::Sometimes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
|
||||||
/// Require type of token as next and return it's value (sometimes irrelevant)
|
|
||||||
pub(super) fn require(&mut self, with: Token) -> Result<String, Error> {
|
|
||||||
if self.lexer.next() == Some(with.clone()) {
|
|
||||||
Ok(self.lexer.slice().to_owned())
|
|
||||||
} else {
|
|
||||||
Err(self.unexpected_token(Some(with)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Require an identifier on next and return it
|
|
||||||
pub(super) fn require_iden(&mut self) -> Result<Iden, Error> {
|
|
||||||
if let Some(Token::Identifier(id)) = self.lexer.next() {
|
|
||||||
if self.tdark {
|
|
||||||
Ok(Iden(id.replace("lang", "script")))
|
|
||||||
} else {
|
|
||||||
Ok(Iden(id))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(Error {
|
|
||||||
kind: ErrorKind::InvalidIdentifier,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Throw unexpected token error (optionally what was expected)
|
|
||||||
pub(super) fn unexpected_token(&mut self, expected: Option<Token>) -> Error {
|
|
||||||
let error_msg = match expected {
|
|
||||||
Some(s) => format!(
|
|
||||||
"Unexpected token: `{}` (required: `{:?}`)",
|
|
||||||
self.lexer.slice(),
|
|
||||||
s
|
|
||||||
),
|
|
||||||
None => format!("Unexpected token: `{}`", self.lexer.slice(),),
|
|
||||||
};
|
|
||||||
Error {
|
|
||||||
kind: ErrorKind::SyntaxError(error_msg),
|
|
||||||
position: self.lexer.span(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn parse_body(&mut self) -> Result<Vec<Item>, Error> {
|
|
||||||
let mut body = Vec::new();
|
|
||||||
loop {
|
|
||||||
let token = {
|
|
||||||
match self.lexer.next() {
|
|
||||||
Some(t) => t,
|
|
||||||
None => {
|
|
||||||
return Err(Error {
|
|
||||||
kind: ErrorKind::EndOfTokenStream,
|
|
||||||
position: self.lexer.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if token == Token::RightBrace {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
body.push(self.parse_item(Some(token))?);
|
|
||||||
}
|
|
||||||
Ok(body)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue