forked from AbleScript/ablescript
Parser implements examples
- Function call is now stmt (muhehe)
This commit is contained in:
parent
91bd015e9b
commit
4a9b656093
13
src/main.rs
13
src/main.rs
|
@ -8,6 +8,7 @@ mod repl;
|
||||||
mod variables;
|
mod variables;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
|
use logos::Source;
|
||||||
use parser::Parser;
|
use parser::Parser;
|
||||||
fn main() {
|
fn main() {
|
||||||
// variables::test();
|
// variables::test();
|
||||||
|
@ -34,7 +35,17 @@ fn main() {
|
||||||
// Parse
|
// Parse
|
||||||
let mut parser = Parser::new(&source);
|
let mut parser = Parser::new(&source);
|
||||||
let ast = parser.init();
|
let ast = parser.init();
|
||||||
println!("{:#?}", ast);
|
match ast {
|
||||||
|
Ok(ast) => println!("{:#?}", ast),
|
||||||
|
Err(e) => {
|
||||||
|
println!(
|
||||||
|
"Error `{:?}` occured at span: {:?} = `{:?}`",
|
||||||
|
e.kind,
|
||||||
|
e.position.clone(),
|
||||||
|
source.slice(e.position)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
println!(
|
println!(
|
||||||
|
|
|
@ -27,7 +27,6 @@ pub enum Expr {
|
||||||
Subtract { left: Box<Expr>, right: Box<Expr> },
|
Subtract { left: Box<Expr>, right: Box<Expr> },
|
||||||
Multiply { left: Box<Expr>, right: Box<Expr> },
|
Multiply { left: Box<Expr>, right: Box<Expr> },
|
||||||
Divide { left: Box<Expr>, right: Box<Expr> },
|
Divide { left: Box<Expr>, right: Box<Expr> },
|
||||||
FunctionCall { iden: Iden, args: Vec<Expr> },
|
|
||||||
Literal(Value),
|
Literal(Value),
|
||||||
Identifier(Iden),
|
Identifier(Iden),
|
||||||
}
|
}
|
||||||
|
@ -56,6 +55,10 @@ pub enum Stmt {
|
||||||
cond: Box<Item>,
|
cond: Box<Item>,
|
||||||
body: Vec<Item>,
|
body: Vec<Item>,
|
||||||
},
|
},
|
||||||
|
FunctionCall {
|
||||||
|
iden: Iden,
|
||||||
|
args: Vec<Expr>,
|
||||||
|
},
|
||||||
|
Print(Expr),
|
||||||
Melo(Iden),
|
Melo(Iden),
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,11 @@ impl<'a> Parser<'a> {
|
||||||
if token.is_none() {
|
if token.is_none() {
|
||||||
return Ok(self.ast.clone());
|
return Ok(self.ast.clone());
|
||||||
};
|
};
|
||||||
|
if matches!(token, Some(Token::Comment)) {
|
||||||
let expr = self.parse_item(token)?;
|
continue;
|
||||||
self.ast.push(expr);
|
}
|
||||||
|
let item = self.parse_item(token)?;
|
||||||
|
self.ast.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,9 +114,15 @@ impl<'a> Parser<'a> {
|
||||||
fn function_declaration(&mut self) -> ParseResult {
|
fn function_declaration(&mut self) -> ParseResult {
|
||||||
let iden = self.require_iden()?;
|
let iden = self.require_iden()?;
|
||||||
self.require(Token::LeftParenthesis)?;
|
self.require(Token::LeftParenthesis)?;
|
||||||
let args = vec![];
|
let mut args = vec![];
|
||||||
self.require(Token::RightParenthesis)?;
|
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)?;
|
self.require(Token::LeftBrace)?;
|
||||||
// Parse function body
|
// Parse function body
|
||||||
let body = self.parse_body()?;
|
let body = self.parse_body()?;
|
||||||
|
|
|
@ -2,12 +2,17 @@ use super::*;
|
||||||
|
|
||||||
type ExprResult = Result<Expr, Error>;
|
type ExprResult = Result<Expr, Error>;
|
||||||
|
|
||||||
|
/// Generate infix expression by pattern left <op> right
|
||||||
|
///
|
||||||
|
/// Credits: `@! ! Reiter#4543`
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! gen_infix {
|
macro_rules! gen_infix {
|
||||||
($($fn_name: ident => $type: tt);*$(;)?) => {$(
|
($($fn_name: ident => $type: tt);*$(;)?) => {$(
|
||||||
|
/// Generated function for infix operator
|
||||||
fn $fn_name(&mut self, left: Expr) -> ExprResult {
|
fn $fn_name(&mut self, left: Expr) -> ExprResult {
|
||||||
|
self.lexer.next();
|
||||||
let next = self.lexer.next();
|
let next = self.lexer.next();
|
||||||
let right = self.ensure_expr(next)?;
|
let right = self.parse_expr(next)?;
|
||||||
Ok(Expr::$type { left: Box::new(left), right: Box::new(right) })
|
Ok(Expr::$type { left: Box::new(left), right: Box::new(right) })
|
||||||
})*
|
})*
|
||||||
};
|
};
|
||||||
|
@ -15,14 +20,23 @@ macro_rules! gen_infix {
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
pub(super) fn parse_ops(&mut self, token: Token) -> ParseResult {
|
pub(super) fn parse_ops(&mut self, token: Token) -> ParseResult {
|
||||||
let mut buf: Expr = self.ensure_expr(Some(token))?;
|
if matches!(self.lexer.peek(), Some(Token::LeftParenthesis)) {
|
||||||
|
return self.fn_call(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf: Expr = self.parse_expr(Some(token))?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
buf = match self.lexer.next() {
|
buf = match self.lexer.peek() {
|
||||||
Some(Token::Addition) => self.addition(buf)?,
|
Some(Token::Addition) => self.addition(buf)?,
|
||||||
Some(Token::Subtract) => self.subtract(buf)?,
|
Some(Token::Subtract) => self.subtract(buf)?,
|
||||||
Some(Token::Multiply) => self.multiply(buf)?,
|
Some(Token::Multiply) => self.multiply(buf)?,
|
||||||
Some(Token::Divide) => self.divide(buf)?,
|
Some(Token::Divide) => self.divide(buf)?,
|
||||||
|
Some(Token::Print) => {
|
||||||
|
self.lexer.next();
|
||||||
|
self.require(Token::Semicolon)?;
|
||||||
|
return Ok(Stmt::Print(buf).into());
|
||||||
|
}
|
||||||
_ => return Ok(buf.into()),
|
_ => return Ok(buf.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,41 +51,84 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure that input token is an expression
|
/// Ensure that input token is an expression
|
||||||
fn ensure_expr(&mut self, token: Option<Token>) -> ExprResult {
|
fn parse_expr(&mut self, token: Option<Token>) -> ExprResult {
|
||||||
let token = token.ok_or(Error {
|
let token = token.ok_or(Error {
|
||||||
kind: ErrorKind::EndOfTokenStream,
|
kind: ErrorKind::EndOfTokenStream,
|
||||||
position: self.lexer.span(),
|
position: self.lexer.span(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
match token {
|
match token {
|
||||||
Token::Boolean(b) => Ok(Expr::Literal(Value::Bool(b))),
|
Token::Boolean(b) => Ok(Expr::Literal(Value::Bool(b))),
|
||||||
Token::Integer(i) => Ok(Expr::Literal(Value::Int(i))),
|
Token::Integer(i) => Ok(Expr::Literal(Value::Int(i))),
|
||||||
Token::String(s) => Ok(Expr::Literal(Value::Str(s))),
|
Token::String(s) => Ok(Expr::Literal(Value::Str(s))),
|
||||||
Token::Aboolean(a) => Ok(Expr::Literal(Value::Abool(a))),
|
Token::Aboolean(a) => Ok(Expr::Literal(Value::Abool(a))),
|
||||||
Token::Identifier(i) => Ok(Expr::Identifier(Iden(i))),
|
Token::Identifier(i) => Ok(Expr::Identifier(Iden(i))),
|
||||||
|
Token::LeftParenthesis => self.parse_paren(),
|
||||||
t => Err(self.unexpected_token(Some(t))),
|
t => Err(self.unexpected_token(Some(t))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse function call
|
/// Parse parenthesieted expression
|
||||||
fn fn_call(&mut self, iden: Iden) -> ExprResult {
|
fn parse_paren(&mut self) -> ExprResult {
|
||||||
return todo!();
|
|
||||||
self.lexer.next();
|
|
||||||
let mut args: Vec<Expr> = Vec::new();
|
|
||||||
|
|
||||||
while let Some(token) = self.lexer.peek() {
|
|
||||||
match token {
|
|
||||||
Token::Identifier(id) => {
|
|
||||||
args.push(Expr::Identifier(Iden(id.clone())));
|
|
||||||
self.lexer.next();
|
|
||||||
}
|
|
||||||
Token::RightParenthesis => break,
|
|
||||||
_ => {
|
|
||||||
let next = self.lexer.next();
|
let next = self.lexer.next();
|
||||||
|
let mut buf = self.parse_expr(next)?;
|
||||||
|
loop {
|
||||||
|
let next = self.lexer.peek().clone().ok_or(Error {
|
||||||
|
kind: ErrorKind::EndOfTokenStream,
|
||||||
|
position: self.lexer.span(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
buf = match Some(next) {
|
||||||
|
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::LeftParenthesis) => {
|
||||||
|
return Err(Error {
|
||||||
|
kind: ErrorKind::SyntaxError(
|
||||||
|
"Function call isn't an expression!".to_owned(),
|
||||||
|
),
|
||||||
|
position: self.lexer.span(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Some(Token::RightParenthesis) => {
|
||||||
|
self.lexer.next();
|
||||||
|
return Ok(buf);
|
||||||
|
}
|
||||||
|
_ => return Ok(buf.into()),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.require(Token::Comma)?;
|
|
||||||
|
/// 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;
|
||||||
}
|
}
|
||||||
self.require(Token::RightParenthesis)?;
|
|
||||||
Ok(Expr::FunctionCall { iden, args })
|
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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/repl.rs
13
src/repl.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use logos::Source;
|
||||||
use rustyline::Editor;
|
use rustyline::Editor;
|
||||||
|
|
||||||
use crate::parser::Parser;
|
use crate::parser::Parser;
|
||||||
|
@ -14,7 +15,17 @@ pub fn repl() {
|
||||||
}
|
}
|
||||||
let mut parser = Parser::new(&line);
|
let mut parser = Parser::new(&line);
|
||||||
let ast = parser.init();
|
let ast = parser.init();
|
||||||
println!("{:#?}", ast);
|
match ast {
|
||||||
|
Ok(ast) => println!("{:?}", ast),
|
||||||
|
Err(e) => {
|
||||||
|
println!(
|
||||||
|
"Error `{:?}` occured at span: {:?} = `{:?}`",
|
||||||
|
e.kind,
|
||||||
|
e.position.clone(),
|
||||||
|
line.slice(e.position)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(rustyline::error::ReadlineError::Eof) => {
|
Err(rustyline::error::ReadlineError::Eof) => {
|
||||||
println!("bye");
|
println!("bye");
|
||||||
|
|
Loading…
Reference in a new issue