forked from AbleScript/ablescript
Added function/variable parsing
- Added block support - TODO: Tidy it up
This commit is contained in:
parent
7026711b64
commit
3e2dc5fba9
|
@ -1,2 +1,10 @@
|
||||||
var hello = true;
|
functio test() {
|
||||||
var test;
|
functio nested() {
|
||||||
|
var c = false;
|
||||||
|
}
|
||||||
|
var a = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
functio another() {
|
||||||
|
var b = false;
|
||||||
|
}
|
19
src/error.rs
Normal file
19
src/error.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Error {
|
||||||
|
pub kind: ErrorKind,
|
||||||
|
pub position: Range<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ErrorKind {
|
||||||
|
SyntaxError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub fn panic(&self, span: &str) {
|
||||||
|
println!("{:?} occured at {:?}", self.kind, self.position);
|
||||||
|
println!(" {}", &span);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
mod base_55;
|
mod base_55;
|
||||||
|
mod error;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod tokens;
|
mod tokens;
|
||||||
mod variables;
|
mod variables;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
DeclareVariable { iden: String, init: Option<String> },
|
VariableDeclaration { iden: String, init: Option<String> },
|
||||||
}
|
FunctionDeclaration { iden: String, body: Vec<Expr> },
|
||||||
|
BfFDeclaration { iden: String, code: String },
|
||||||
|
}
|
||||||
|
|
|
@ -3,8 +3,11 @@ mod utils;
|
||||||
|
|
||||||
use item::Expr;
|
use item::Expr;
|
||||||
|
|
||||||
use crate::tokens::Token;
|
|
||||||
use crate::variables::Value;
|
use crate::variables::Value;
|
||||||
|
use crate::{
|
||||||
|
error::{Error, ErrorKind},
|
||||||
|
tokens::Token,
|
||||||
|
};
|
||||||
|
|
||||||
use logos::Logos;
|
use logos::Logos;
|
||||||
|
|
||||||
|
@ -18,7 +21,6 @@ pub enum ParseError {
|
||||||
/// Parser structure / state machine
|
/// Parser structure / state machine
|
||||||
pub struct Parser<'a> {
|
pub struct Parser<'a> {
|
||||||
lexer: logos::Lexer<'a, Token>,
|
lexer: logos::Lexer<'a, Token>,
|
||||||
ast: Vec<Expr>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
|
@ -26,31 +28,39 @@ impl<'a> Parser<'a> {
|
||||||
pub fn new(source: &'a str) -> Self {
|
pub fn new(source: &'a str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
lexer: Token::lexer(source),
|
lexer: Token::lexer(source),
|
||||||
ast: vec![],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start parsing Token Vector into Abstract Syntax Tree
|
/// Start parsing Token Vector into Abstract Syntax Tree
|
||||||
pub fn parse(&mut self) -> Vec<Expr> {
|
pub fn parse(&mut self) -> Vec<Expr> {
|
||||||
|
let mut ast = vec![];
|
||||||
while let Some(token) = self.lexer.next() {
|
while let Some(token) = self.lexer.next() {
|
||||||
let expr = match token {
|
let expr = match token {
|
||||||
Token::Variable => self.variable(),
|
Token::Variable => self.variable_declaration(),
|
||||||
tok => {
|
Token::Function => self.function_declaration(),
|
||||||
// TODO: Better error handling
|
Token::BfFunction => self.bff_declaration(),
|
||||||
println!("Parse error");
|
Token::RightBrace => return ast,
|
||||||
|
_ => Err(Error {
|
||||||
|
kind: ErrorKind::SyntaxError,
|
||||||
|
position: 0..0,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
match expr {
|
||||||
|
Ok(o) => ast.push(o),
|
||||||
|
Err(e) => {
|
||||||
|
e.panic(self.lexer.slice());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
self.ast.push(expr.unwrap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ast.clone()
|
ast
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse variable declaration
|
/// Parse variable declaration
|
||||||
///
|
///
|
||||||
/// `var [iden] = [literal];`
|
/// `var [iden] = [literal];`
|
||||||
fn variable(&mut self) -> Result<Expr, ParseError> {
|
fn variable_declaration(&mut self) -> Result<Expr, Error> {
|
||||||
let iden = self.require(Token::Identifier)?;
|
let iden = self.require(Token::Identifier)?;
|
||||||
|
|
||||||
let init = match self.lexer.next() {
|
let init = match self.lexer.next() {
|
||||||
|
@ -60,9 +70,39 @@ impl<'a> Parser<'a> {
|
||||||
self.require(Token::Semicolon)?;
|
self.require(Token::Semicolon)?;
|
||||||
Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
_ => return Err(ParseError::UnexpectedToken),
|
_ => {
|
||||||
|
return Err(Error {
|
||||||
|
kind: ErrorKind::SyntaxError,
|
||||||
|
position: self.lexer.span(),
|
||||||
|
})
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Expr::DeclareVariable { iden, init })
|
Ok(Expr::VariableDeclaration { iden, init })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declare function
|
||||||
|
///
|
||||||
|
/// `functio [iden] ([expr], [expr]) { ... }
|
||||||
|
fn function_declaration(&mut self) -> Result<Expr, Error> {
|
||||||
|
let iden = self.require(Token::Identifier)?;
|
||||||
|
self.require(Token::LeftParenthesis)?;
|
||||||
|
// TODO: Arguments
|
||||||
|
self.require(Token::RightParenthesis)?;
|
||||||
|
self.require(Token::LeftBrace)?;
|
||||||
|
let body = self.parse();
|
||||||
|
|
||||||
|
Ok(Expr::FunctionDeclaration { iden, body })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Declare BF FFI Function
|
||||||
|
///
|
||||||
|
/// `bff [iden] { ... }`
|
||||||
|
fn bff_declaration(&mut self) -> Result<Expr, Error> {
|
||||||
|
let iden = self.require(Token::Identifier)?;
|
||||||
|
self.require(Token::LeftBrace)?;
|
||||||
|
let code = self.require(Token::String)?; // <-- Nasty hack, but works
|
||||||
|
self.require(Token::RightBrace)?;
|
||||||
|
Ok(Expr::BfFDeclaration { iden, code })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use crate::tokens::{Abool, Token};
|
use crate::{
|
||||||
|
error::{Error, ErrorKind},
|
||||||
|
tokens::{Abool, Token},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{ParseError, Parser};
|
use super::{ParseError, Parser};
|
||||||
|
|
||||||
|
@ -20,11 +23,14 @@ pub fn num2abool(number: i32) -> Abool {
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
/// Require type of token as next and return it's value (sometimes irrelevant)
|
/// Require type of token as next and return it's value (sometimes irrelevant)
|
||||||
pub(super) fn require(&mut self, with: Token) -> Result<String, ParseError> {
|
pub(super) fn require(&mut self, with: Token) -> Result<String, Error> {
|
||||||
if self.lexer.next() == Some(with) {
|
if self.lexer.next() == Some(with) {
|
||||||
Ok(self.lexer.slice().to_owned())
|
Ok(self.lexer.slice().to_owned())
|
||||||
} else {
|
} else {
|
||||||
Err(ParseError::UnexpectedToken)
|
Err(Error {
|
||||||
|
kind: ErrorKind::SyntaxError,
|
||||||
|
position: self.lexer.span(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,23 @@ use logos::Logos;
|
||||||
|
|
||||||
#[derive(Logos, Debug, PartialEq)]
|
#[derive(Logos, Debug, PartialEq)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
|
// Literals
|
||||||
|
/// True, False
|
||||||
|
#[regex("true|false")]
|
||||||
|
Boolean,
|
||||||
|
|
||||||
|
/// Always, Sometimes, Never
|
||||||
|
#[regex("always|sometimes|never")]
|
||||||
|
Aboolean,
|
||||||
|
|
||||||
|
/// String
|
||||||
|
#[regex("\"(\\.|[^\"])*\"")]
|
||||||
|
String,
|
||||||
|
|
||||||
|
/// Integer
|
||||||
|
#[regex(r"[0-9]+")]
|
||||||
|
Integer,
|
||||||
|
|
||||||
/// A C-complaint identifier
|
/// A C-complaint identifier
|
||||||
#[regex(r"[a-zA-Z_][a-zA-Z_0-9]*")]
|
#[regex(r"[a-zA-Z_][a-zA-Z_0-9]*")]
|
||||||
Identifier,
|
Identifier,
|
||||||
|
@ -61,22 +78,6 @@ pub enum Token {
|
||||||
#[token("var")]
|
#[token("var")]
|
||||||
Variable,
|
Variable,
|
||||||
|
|
||||||
/// True, False
|
|
||||||
#[regex("true|false")]
|
|
||||||
Boolean,
|
|
||||||
|
|
||||||
/// Always, Sometimes, Never
|
|
||||||
#[regex("always|sometimes|never")]
|
|
||||||
Aboolean,
|
|
||||||
|
|
||||||
/// String
|
|
||||||
#[regex("\"(\\.|[^\"])*\"")]
|
|
||||||
String,
|
|
||||||
|
|
||||||
/// Integer
|
|
||||||
#[regex(r"[0-9]+")]
|
|
||||||
Integer,
|
|
||||||
|
|
||||||
/// Prints the preceding things
|
/// Prints the preceding things
|
||||||
#[token("print")]
|
#[token("print")]
|
||||||
Print,
|
Print,
|
||||||
|
|
Loading…
Reference in a new issue