forked from AbleScript/ablescript
Parser implements examples
- Function call is now stmt (muhehe)
This commit is contained in:
parent
18a1343e11
commit
c90d242b0f
|
@ -1,3 +1,3 @@
|
|||
var hi = "wonk";
|
||||
melo hi;
|
||||
hi print; #Should error out
|
||||
hi print; # Should error out
|
||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -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!(
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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()?;
|
||||
|
|
|
@ -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();
|
||||
/// 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(),
|
||||
})?;
|
||||
|
||||
while let Some(token) = self.lexer.peek() {
|
||||
match token {
|
||||
Token::Identifier(id) => {
|
||||
args.push(Expr::Identifier(Iden(id.clone())));
|
||||
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);
|
||||
}
|
||||
Token::RightParenthesis => break,
|
||||
_ => {
|
||||
let next = self.lexer.next();
|
||||
}
|
||||
}
|
||||
self.require(Token::Comma)?;
|
||||
_ => return Ok(buf.into()),
|
||||
};
|
||||
}
|
||||
self.require(Token::RightParenthesis)?;
|
||||
Ok(Expr::FunctionCall { iden, args })
|
||||
}
|
||||
|
||||
/// 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())
|
||||
}
|
||||
}
|
||||
|
|
13
src/repl.rs
13
src/repl.rs
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue