Parser implements examples

- Function call is now stmt (muhehe)
This commit is contained in:
Erin 2021-05-02 15:43:25 +02:00 committed by ondra05
parent 91bd015e9b
commit 4a9b656093
6 changed files with 122 additions and 32 deletions

View file

@ -1,3 +1,3 @@
var hi = "wonk";
melo hi;
hi print; #Should error out
hi print; # Should error out

View file

@ -8,6 +8,7 @@ mod repl;
mod variables;
use clap::{App, Arg};
use logos::Source;
use parser::Parser;
fn main() {
// variables::test();
@ -34,7 +35,17 @@ fn main() {
// Parse
let mut parser = Parser::new(&source);
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 => {
println!(

View file

@ -27,7 +27,6 @@ pub enum Expr {
Subtract { left: Box<Expr>, right: Box<Expr> },
Multiply { left: Box<Expr>, right: Box<Expr> },
Divide { left: Box<Expr>, right: Box<Expr> },
FunctionCall { iden: Iden, args: Vec<Expr> },
Literal(Value),
Identifier(Iden),
}
@ -56,6 +55,10 @@ pub enum Stmt {
cond: Box<Item>,
body: Vec<Item>,
},
FunctionCall {
iden: Iden,
args: Vec<Expr>,
},
Print(Expr),
Melo(Iden),
}

View file

@ -35,9 +35,11 @@ impl<'a> Parser<'a> {
if token.is_none() {
return Ok(self.ast.clone());
};
let expr = self.parse_item(token)?;
self.ast.push(expr);
if matches!(token, Some(Token::Comment)) {
continue;
}
let item = self.parse_item(token)?;
self.ast.push(item);
}
}
@ -112,9 +114,15 @@ impl<'a> Parser<'a> {
fn function_declaration(&mut self) -> ParseResult {
let iden = self.require_iden()?;
self.require(Token::LeftParenthesis)?;
let args = vec![];
self.require(Token::RightParenthesis)?;
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()?;

View file

@ -2,12 +2,17 @@ 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.ensure_expr(next)?;
let right = self.parse_expr(next)?;
Ok(Expr::$type { left: Box::new(left), right: Box::new(right) })
})*
};
@ -15,14 +20,23 @@ macro_rules! gen_infix {
impl<'a> Parser<'a> {
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 {
buf = match self.lexer.next() {
buf = match self.lexer.peek() {
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::Print) => {
self.lexer.next();
self.require(Token::Semicolon)?;
return Ok(Stmt::Print(buf).into());
}
_ => return Ok(buf.into()),
}
}
@ -37,41 +51,84 @@ impl<'a> Parser<'a> {
}
/// 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 {
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(s))),
Token::Aboolean(a) => Ok(Expr::Literal(Value::Abool(a))),
Token::Identifier(i) => Ok(Expr::Identifier(Iden(i))),
Token::LeftParenthesis => self.parse_paren(),
t => Err(self.unexpected_token(Some(t))),
}
}
/// Parse function call
fn fn_call(&mut self, iden: Iden) -> 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,
_ => {
/// Parse parenthesieted expression
fn parse_paren(&mut self) -> ExprResult {
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())
}
}

View file

@ -1,3 +1,4 @@
use logos::Source;
use rustyline::Editor;
use crate::parser::Parser;
@ -14,7 +15,17 @@ pub fn repl() {
}
let mut parser = Parser::new(&line);
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) => {
println!("bye");