forked from AbleScript/ablescript
Added parsing of conditionals
This commit is contained in:
parent
fc8c3a3499
commit
00a464321a
|
@ -1 +1,3 @@
|
|||
bff a {+++<<>>>[]]]][[]]}
|
||||
if (true) {
|
||||
var a = 3;
|
||||
}
|
|
@ -126,8 +126,9 @@ pub fn num2char(number: i32) -> char {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test] fn str_to_base55() {
|
||||
#[test]
|
||||
fn str_to_base55() {
|
||||
let chrs: Vec<i32> = "AbleScript".chars().map(char2num).collect();
|
||||
assert_eq!(chrs, &[-1, 2, 12, 5, -19, 3, 18, 9, 16, 20]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,4 +11,4 @@ pub enum ErrorKind {
|
|||
SyntaxError(String),
|
||||
EndOfTokenStream,
|
||||
InvalidIdentifier,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use crate::variables::Value;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Iden(pub String);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Expr {
|
||||
VariableDeclaration {
|
||||
|
@ -14,5 +17,11 @@ pub enum Expr {
|
|||
iden: String,
|
||||
body: String,
|
||||
},
|
||||
If {
|
||||
cond: Box<Expr>,
|
||||
body: Vec<Expr>,
|
||||
},
|
||||
|
||||
Literal(Value),
|
||||
Melo(Iden),
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@ mod utils;
|
|||
|
||||
use item::Expr;
|
||||
|
||||
use crate::tokens::Token;
|
||||
use crate::{
|
||||
error::{Error, ErrorKind},
|
||||
variables::Value,
|
||||
};
|
||||
use crate::{parser::item::Iden, tokens::Token};
|
||||
|
||||
use logos::Logos;
|
||||
|
||||
|
@ -50,13 +50,28 @@ impl<'a> Parser<'a> {
|
|||
let start = self.lexer.span().start;
|
||||
|
||||
match token {
|
||||
// Control flow
|
||||
Token::If => self.if_cond(),
|
||||
|
||||
// Declarations
|
||||
Token::Variable => self.variable_declaration(),
|
||||
Token::Function => self.function_declaration(),
|
||||
Token::BfFunction => self.bff_declaration(),
|
||||
|
||||
// Literals
|
||||
Token::String(x) => Ok(Expr::Literal(Value::Str(x))),
|
||||
Token::Integer(x) => Ok(Expr::Literal(Value::Int(x))),
|
||||
Token::Boolean(x) => Ok(Expr::Literal(Value::Bool(x))),
|
||||
Token::Aboolean(x) => Ok(Expr::Literal(Value::Abool(x))),
|
||||
|
||||
// Prefix keywords
|
||||
// Melo - ban variable from next usage (runtime error)
|
||||
Token::Melo => {
|
||||
let e = self.require_iden()?;
|
||||
self.require(Token::Semicolon)?;
|
||||
Ok(Expr::Melo(Iden(e)))
|
||||
}
|
||||
|
||||
_ => Err(Error {
|
||||
kind: ErrorKind::SyntaxError("Unexpected identifier".to_owned()),
|
||||
position: start..self.lexer.span().end,
|
||||
|
@ -99,25 +114,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
self.require(Token::LeftBrace)?;
|
||||
// Parse function body
|
||||
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_expr(Some(token))?);
|
||||
}
|
||||
let body = self.parse_body()?;
|
||||
|
||||
Ok(Expr::FunctionDeclaration { iden, body })
|
||||
}
|
||||
|
@ -161,4 +158,21 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
Ok(Expr::BfFDeclaration { iden, body })
|
||||
}
|
||||
|
||||
/// Parse If-expression
|
||||
pub fn if_cond(&mut self) -> Result<Expr, Error> {
|
||||
self.require(Token::LeftParenthesis)?;
|
||||
let cond = self.lexer.next();
|
||||
let cond = self.parse_expr(cond)?;
|
||||
self.require(Token::RightParenthesis)?;
|
||||
|
||||
self.require(Token::LeftBrace)?;
|
||||
|
||||
let body = self.parse_body()?;
|
||||
|
||||
Ok(Expr::If {
|
||||
cond: Box::new(cond),
|
||||
body,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::error::{Error, ErrorKind};
|
|||
use crate::tokens::Token;
|
||||
use crate::variables::Abool;
|
||||
|
||||
use super::Parser;
|
||||
use super::{item::Expr, Parser};
|
||||
|
||||
pub fn abool2num(abool: Abool) -> i32 {
|
||||
match abool {
|
||||
|
@ -51,4 +51,27 @@ impl<'a> Parser<'a> {
|
|||
position: self.lexer.span(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn parse_body(&mut self) -> Result<Vec<Expr>, 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_expr(Some(token))?);
|
||||
}
|
||||
Ok(body)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,38 @@ use crate::variables::Abool;
|
|||
|
||||
#[derive(Logos, Debug, PartialEq, Clone)]
|
||||
pub enum Token {
|
||||
#[token("functio")]
|
||||
Function,
|
||||
|
||||
/// Brain fuck FFI
|
||||
#[token("bff")]
|
||||
BfFunction,
|
||||
|
||||
/// Variable bro
|
||||
#[token("var")]
|
||||
Variable,
|
||||
|
||||
/// Prints the preceding things
|
||||
#[token("print")]
|
||||
Print,
|
||||
|
||||
/// Ban the following variable from ever being used again
|
||||
#[token("melo")]
|
||||
Melo,
|
||||
|
||||
#[token("T-Dark")]
|
||||
TDark,
|
||||
|
||||
// Expressions
|
||||
#[token("if")]
|
||||
If,
|
||||
|
||||
#[token("else")]
|
||||
Else,
|
||||
|
||||
#[token("loop")]
|
||||
Loop,
|
||||
|
||||
// Literals
|
||||
/// True, False
|
||||
#[regex("true|false", get_bool)]
|
||||
|
@ -88,38 +120,6 @@ pub enum Token {
|
|||
#[token("'.*'")]
|
||||
Char,
|
||||
|
||||
#[token("functio")]
|
||||
Function,
|
||||
|
||||
/// Brain fuck FFI
|
||||
#[token("bff")]
|
||||
BfFunction,
|
||||
|
||||
/// Variable bro
|
||||
#[token("var")]
|
||||
Variable,
|
||||
|
||||
/// Prints the preceding things
|
||||
#[token("print")]
|
||||
Print,
|
||||
|
||||
/// Ban the following variable from ever being used again
|
||||
#[token("melo")]
|
||||
Melo,
|
||||
|
||||
#[token("T-Dark")]
|
||||
TDark,
|
||||
|
||||
// Expressions
|
||||
#[token("if")]
|
||||
If,
|
||||
|
||||
#[token("else")]
|
||||
Else,
|
||||
|
||||
#[token("loop")]
|
||||
Loop,
|
||||
|
||||
#[regex(r"[ \t\n\f]+", logos::skip)]
|
||||
#[error]
|
||||
Error,
|
||||
|
@ -184,4 +184,4 @@ mod tests {
|
|||
let result: Vec<Token> = lexer.collect();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,4 +29,4 @@ pub enum Value {
|
|||
pub struct Variable {
|
||||
melo: bool,
|
||||
value: Value,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue