Add errors for lexer and parser
This commit is contained in:
parent
c7f11e5091
commit
9b7a31c988
51
src/ast.rs
51
src/ast.rs
@ -1,10 +1,13 @@
|
|||||||
use crate::{lexer::Token, token_stream::TokenStream};
|
use crate::{
|
||||||
|
lexer::{Token, TokenList},
|
||||||
|
token_stream::{Error, TokenStream},
|
||||||
|
};
|
||||||
|
|
||||||
pub trait Parse
|
pub trait Parse
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized,
|
Self: std::marker::Sized,
|
||||||
{
|
{
|
||||||
fn parse(stream: TokenStream) -> Result<Self, ()>;
|
fn parse(stream: TokenStream) -> Result<Self, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -28,13 +31,13 @@ pub enum Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Expression {
|
impl Parse for Expression {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Expression, ()> {
|
fn parse(mut stream: TokenStream) -> Result<Expression, Error> {
|
||||||
let lhs = parse_primary_expression(&mut stream)?;
|
let lhs = parse_primary_expression(&mut stream)?;
|
||||||
parse_binop_rhs(&mut stream, lhs, 0)
|
parse_binop_rhs(&mut stream, lhs, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_primary_expression(stream: &mut TokenStream) -> Result<Expression, ()> {
|
fn parse_primary_expression(stream: &mut TokenStream) -> Result<Expression, Error> {
|
||||||
if let Ok(exp) = stream.parse() {
|
if let Ok(exp) = stream.parse() {
|
||||||
Ok(Expression::FunctionCall(Box::new(exp)))
|
Ok(Expression::FunctionCall(Box::new(exp)))
|
||||||
} else if let Ok(block) = stream.parse() {
|
} else if let Ok(block) = stream.parse() {
|
||||||
@ -48,10 +51,10 @@ fn parse_primary_expression(stream: &mut TokenStream) -> Result<Expression, ()>
|
|||||||
stream.expect(Token::ParenClose)?;
|
stream.expect(Token::ParenClose)?;
|
||||||
exp
|
exp
|
||||||
}
|
}
|
||||||
_ => Err(())?, // TODO: Add error raporting!
|
_ => Err(stream.expected_err("identifier, constant or parentheses")?)?,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(()) // TODO: Add error raporting!
|
Err(stream.expected_err("expression")?)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +67,7 @@ fn parse_binop_rhs(
|
|||||||
stream: &mut TokenStream,
|
stream: &mut TokenStream,
|
||||||
mut lhs: Expression,
|
mut lhs: Expression,
|
||||||
expr_prec: i8,
|
expr_prec: i8,
|
||||||
) -> Result<Expression, ()> {
|
) -> Result<Expression, Error> {
|
||||||
while let Some(token) = stream.peek() {
|
while let Some(token) = stream.peek() {
|
||||||
let curr_token_prec = token.get_token_prec();
|
let curr_token_prec = token.get_token_prec();
|
||||||
|
|
||||||
@ -89,7 +92,7 @@ fn parse_binop_rhs(
|
|||||||
lhs = match &token {
|
lhs = match &token {
|
||||||
Token::Plus => Expression::Binop(Add, Box::new(lhs), Box::new(rhs)),
|
Token::Plus => Expression::Binop(Add, Box::new(lhs), Box::new(rhs)),
|
||||||
Token::Times => Expression::Binop(Mult, Box::new(lhs), Box::new(rhs)),
|
Token::Times => Expression::Binop(Mult, Box::new(lhs), Box::new(rhs)),
|
||||||
_ => Err(())?, // TODO: Add error raporting!
|
_ => Err(stream.expected_err(TokenList(vec![Token::Plus, Token::Times]))?)?, // TODO: Add error raporting!
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +104,7 @@ fn parse_binop_rhs(
|
|||||||
pub struct FunctionCallExpression(String, Vec<Expression>);
|
pub struct FunctionCallExpression(String, Vec<Expression>);
|
||||||
|
|
||||||
impl Parse for FunctionCallExpression {
|
impl Parse for FunctionCallExpression {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
if let Some(Token::Identifier(name)) = stream.next() {
|
if let Some(Token::Identifier(name)) = stream.next() {
|
||||||
stream.expect(Token::ParenOpen)?;
|
stream.expect(Token::ParenOpen)?;
|
||||||
|
|
||||||
@ -119,7 +122,7 @@ impl Parse for FunctionCallExpression {
|
|||||||
|
|
||||||
Ok(FunctionCallExpression(name, args))
|
Ok(FunctionCallExpression(name, args))
|
||||||
} else {
|
} else {
|
||||||
Err(())? // TODO: Add error raporting!
|
Err(stream.expected_err("identifier")?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +131,7 @@ impl Parse for FunctionCallExpression {
|
|||||||
pub struct LetStatement(pub String, pub Expression);
|
pub struct LetStatement(pub String, pub Expression);
|
||||||
|
|
||||||
impl Parse for LetStatement {
|
impl Parse for LetStatement {
|
||||||
fn parse(mut stream: TokenStream) -> Result<LetStatement, ()> {
|
fn parse(mut stream: TokenStream) -> Result<LetStatement, Error> {
|
||||||
stream.expect(Token::LetKeyword)?;
|
stream.expect(Token::LetKeyword)?;
|
||||||
|
|
||||||
if let Some(Token::Identifier(variable)) = stream.next() {
|
if let Some(Token::Identifier(variable)) = stream.next() {
|
||||||
@ -138,7 +141,7 @@ impl Parse for LetStatement {
|
|||||||
stream.expect(Token::Semi)?;
|
stream.expect(Token::Semi)?;
|
||||||
Ok(LetStatement(variable, expression))
|
Ok(LetStatement(variable, expression))
|
||||||
} else {
|
} else {
|
||||||
Err(()) // TODO: Add error raporting!
|
Err(stream.expected_err("identifier")?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +150,7 @@ impl Parse for LetStatement {
|
|||||||
pub struct ImportStatement(Vec<String>);
|
pub struct ImportStatement(Vec<String>);
|
||||||
|
|
||||||
impl Parse for ImportStatement {
|
impl Parse for ImportStatement {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
stream.expect(Token::ImportKeyword)?;
|
stream.expect(Token::ImportKeyword)?;
|
||||||
|
|
||||||
let mut import_list = Vec::new();
|
let mut import_list = Vec::new();
|
||||||
@ -158,11 +161,11 @@ impl Parse for ImportStatement {
|
|||||||
if let Some(Token::Identifier(name)) = stream.next() {
|
if let Some(Token::Identifier(name)) = stream.next() {
|
||||||
import_list.push(name);
|
import_list.push(name);
|
||||||
} else {
|
} else {
|
||||||
Err(())? // TODO: Add error raporting!
|
Err(stream.expected_err("identifier")?)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(())? // TODO: Add error raporting!
|
Err(stream.expected_err("identifier")?)?
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.expect(Token::Semi)?;
|
stream.expect(Token::Semi)?;
|
||||||
@ -175,7 +178,7 @@ impl Parse for ImportStatement {
|
|||||||
pub struct FunctionDefinition(pub FunctionSignature, pub Block);
|
pub struct FunctionDefinition(pub FunctionSignature, pub Block);
|
||||||
|
|
||||||
impl Parse for FunctionDefinition {
|
impl Parse for FunctionDefinition {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
stream.expect(Token::FnKeyword)?;
|
stream.expect(Token::FnKeyword)?;
|
||||||
Ok(FunctionDefinition(stream.parse()?, stream.parse()?))
|
Ok(FunctionDefinition(stream.parse()?, stream.parse()?))
|
||||||
}
|
}
|
||||||
@ -187,13 +190,13 @@ pub struct FunctionSignature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for FunctionSignature {
|
impl Parse for FunctionSignature {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
if let Some(Token::Identifier(name)) = stream.next() {
|
if let Some(Token::Identifier(name)) = stream.next() {
|
||||||
stream.expect(Token::ParenOpen)?;
|
stream.expect(Token::ParenOpen)?;
|
||||||
stream.expect(Token::ParenClose)?;
|
stream.expect(Token::ParenClose)?;
|
||||||
Ok(FunctionSignature { name })
|
Ok(FunctionSignature { name })
|
||||||
} else {
|
} else {
|
||||||
Err(()) // TODO: Add error raporting!
|
Err(stream.expected_err("identifier")?)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,7 +205,7 @@ impl Parse for FunctionSignature {
|
|||||||
pub struct Block(pub Vec<BlockLevelStatement>, pub Option<Expression>);
|
pub struct Block(pub Vec<BlockLevelStatement>, pub Option<Expression>);
|
||||||
|
|
||||||
impl Parse for Block {
|
impl Parse for Block {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
let mut return_stmt = None;
|
let mut return_stmt = None;
|
||||||
stream.expect(Token::BraceOpen)?;
|
stream.expect(Token::BraceOpen)?;
|
||||||
@ -228,7 +231,7 @@ pub enum BlockLevelStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BlockLevelStatement {
|
impl Parse for BlockLevelStatement {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
use BlockLevelStatement as Stmt;
|
use BlockLevelStatement as Stmt;
|
||||||
Ok(match stream.peek() {
|
Ok(match stream.peek() {
|
||||||
Some(Token::LetKeyword) => Stmt::Let(stream.parse()?),
|
Some(Token::LetKeyword) => Stmt::Let(stream.parse()?),
|
||||||
@ -244,7 +247,7 @@ impl Parse for BlockLevelStatement {
|
|||||||
stream.expect(Token::Semi)?;
|
stream.expect(Token::Semi)?;
|
||||||
Stmt::Expression(e)
|
Stmt::Expression(e)
|
||||||
} else {
|
} else {
|
||||||
Err(())? // TODO: Add error raporting!
|
Err(stream.expected_err("expression")?)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -258,12 +261,14 @@ pub enum TopLevelStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for TopLevelStatement {
|
impl Parse for TopLevelStatement {
|
||||||
fn parse(mut stream: TokenStream) -> Result<Self, ()> {
|
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||||
use TopLevelStatement as Stmt;
|
use TopLevelStatement as Stmt;
|
||||||
Ok(match stream.peek() {
|
Ok(match stream.peek() {
|
||||||
Some(Token::ImportKeyword) => Stmt::Import(stream.parse()?),
|
Some(Token::ImportKeyword) => Stmt::Import(stream.parse()?),
|
||||||
Some(Token::FnKeyword) => Stmt::FunctionDefinition(stream.parse()?),
|
Some(Token::FnKeyword) => Stmt::FunctionDefinition(stream.parse()?),
|
||||||
_ => Err(())?, // TODO: Add error raporting!
|
_ => {
|
||||||
|
Err(stream.expected_err(TokenList(vec![Token::ImportKeyword, Token::FnKeyword]))?)?
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
src/lexer.rs
26
src/lexer.rs
@ -54,6 +54,30 @@ impl Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<String> for Token {
|
||||||
|
fn into(self) -> String {
|
||||||
|
format!("{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TokenList(pub Vec<Token>);
|
||||||
|
|
||||||
|
impl Into<String> for TokenList {
|
||||||
|
fn into(self) -> String {
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.map(|tok| tok.clone().into())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(" or ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<TokenList> for &[Token] {
|
||||||
|
fn into(self) -> TokenList {
|
||||||
|
TokenList(self.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FullToken {
|
pub struct FullToken {
|
||||||
pub token: Token,
|
pub token: Token,
|
||||||
@ -79,11 +103,11 @@ pub struct Cursor<'a> {
|
|||||||
impl<'a> Cursor<'a> {
|
impl<'a> Cursor<'a> {
|
||||||
fn next(&mut self) -> Option<char> {
|
fn next(&mut self) -> Option<char> {
|
||||||
let next = self.char_stream.next();
|
let next = self.char_stream.next();
|
||||||
self.position.0 += 1;
|
|
||||||
if let Some('\n') = next {
|
if let Some('\n') = next {
|
||||||
self.position.1 += 1;
|
self.position.1 += 1;
|
||||||
self.position.0 = 0;
|
self.position.0 = 0;
|
||||||
}
|
}
|
||||||
|
self.position.0 += 1;
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ mod token_stream;
|
|||||||
pub enum ReidError {
|
pub enum ReidError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
LexerError(#[from] lexer::Error),
|
LexerError(#[from] lexer::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
ParserError(#[from] token_stream::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(source: &str) -> Result<String, ReidError> {
|
pub fn compile(source: &str) -> Result<String, ReidError> {
|
||||||
@ -28,7 +30,7 @@ pub fn compile(source: &str) -> Result<String, ReidError> {
|
|||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) {
|
while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) {
|
||||||
let statement = token_stream.parse::<TopLevelStatement>().unwrap();
|
let statement = token_stream.parse::<TopLevelStatement>()?;
|
||||||
dbg!(&statement);
|
dbg!(&statement);
|
||||||
statements.push(statement);
|
statements.push(statement);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::Parse,
|
ast::Parse,
|
||||||
lexer::{FullToken, Token},
|
lexer::{FullToken, Position, Token},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TokenStream<'a, 'b> {
|
pub struct TokenStream<'a, 'b> {
|
||||||
@ -18,16 +18,24 @@ impl<'a, 'b> TokenStream<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect(&mut self, token: Token) -> Result<(), ()> {
|
pub fn expected_err<T: Into<String>>(&mut self, expected: T) -> Result<Error, Error> {
|
||||||
|
Ok(Error::Expected(
|
||||||
|
expected.into(),
|
||||||
|
self.peek().unwrap_or(Token::Eof),
|
||||||
|
self.get_next_position()?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect(&mut self, token: Token) -> Result<(), Error> {
|
||||||
if let Some(peeked) = self.peek() {
|
if let Some(peeked) = self.peek() {
|
||||||
if token == peeked {
|
if token == peeked {
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(self.expected_err(token)?)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(self.expected_err(token)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +57,7 @@ impl<'a, 'b> TokenStream<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse<T: Parse>(&mut self) -> Result<T, ()> {
|
pub fn parse<T: Parse>(&mut self) -> Result<T, Error> {
|
||||||
let mut ref_pos = self.position;
|
let mut ref_pos = self.position;
|
||||||
|
|
||||||
let position = self.position;
|
let position = self.position;
|
||||||
@ -67,6 +75,15 @@ impl<'a, 'b> TokenStream<'a, 'b> {
|
|||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_next_position(&self) -> Result<Position, Error> {
|
||||||
|
if self.tokens.is_empty() {
|
||||||
|
Err(Error::FileEmpty)
|
||||||
|
} else {
|
||||||
|
let token_idx = self.position.min(self.tokens.len() - 1);
|
||||||
|
Ok(self.tokens[token_idx].position)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for TokenStream<'_, '_> {
|
impl Drop for TokenStream<'_, '_> {
|
||||||
@ -76,3 +93,11 @@ impl Drop for TokenStream<'_, '_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("Expected {} at Ln {}, Col {}, got {:?}", .0, (.2).1, (.2).0, .1)]
|
||||||
|
Expected(String, Token, Position),
|
||||||
|
#[error("Source file contains no tokens")]
|
||||||
|
FileEmpty,
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user