Skip to content

Commit

Permalink
feat(parser): add ParseError
Browse files Browse the repository at this point in the history
  • Loading branch information
H1ghBre4k3r committed Sep 10, 2023
1 parent a367330 commit 3d95997
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 24 deletions.
13 changes: 13 additions & 0 deletions src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ pub enum Token {
Comment { value: String, position: Position },
}

impl Token {
pub fn position(&self) -> Position {
match self {
Token::Eq { position } => *position,
Token::Let { position } => *position,
Token::Id { position, .. } => *position,
Token::Num { position, .. } => *position,
Token::Semicolon { position } => *position,
Token::Comment { position, .. } => *position,
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LexError(String);

Expand Down
3 changes: 1 addition & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use self::lexer::*;
use self::parser::*;

fn main() -> Result<(), Box<dyn Error>> {
let input = r#"let a = 3;
"#;
let input = r#"let a = 3;"#;

let lexed = lex(input)?;

Expand Down
9 changes: 6 additions & 3 deletions src/parser/ast/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ mod num;

pub use self::num::*;

use std::{error::Error, iter::Peekable};
use std::iter::Peekable;

use crate::{lexer::Token, parser::FromTokens};
use crate::{
lexer::Token,
parser::{FromTokens, ParseError},
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Expression {
Num(Num),
}

impl FromTokens for Expression {
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, Box<dyn Error>>
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, ParseError>
where
I: Iterator<Item = Token>,
Self: Sized,
Expand Down
9 changes: 6 additions & 3 deletions src/parser/ast/expression/num.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use std::{error::Error, iter::Peekable};
use std::iter::Peekable;

use crate::{lexer::Token, parser::FromTokens};
use crate::{
lexer::Token,
parser::{FromTokens, ParseError},
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Num(u64);

impl FromTokens for Num {
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, Box<dyn Error>>
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, ParseError>
where
I: Iterator<Item = Token>,
Self: Sized,
Expand Down
50 changes: 39 additions & 11 deletions src/parser/ast/statement/initialization.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{error::Error, iter::Peekable};
use std::iter::Peekable;

use crate::{
lexer::Token,
parser::{ast::Expression, FromTokens},
parser::{ast::Expression, FromTokens, ParseError},
};

#[derive(Debug, Clone, PartialEq, Eq)]
Expand All @@ -12,27 +12,55 @@ pub struct Initialization {
}

impl FromTokens for Initialization {
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, Box<dyn Error>>
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, ParseError>
where
I: Iterator<Item = Token>,
Self: Sized,
{
let Some(Token::Let { .. }) = tokens.next() else {
todo!()
let next = tokens.next().ok_or(ParseError {
message: "Expeting 'let' in Initialization".into(),
position: None,
})?;
let Token::Let { .. } = next else {
return Err(ParseError {
message: "Expeting 'let' in Initialization".into(),
position: Some(next.position()),
});
};

let Some(Token::Id { value: id, .. }) = tokens.next() else {
todo!()
let next = tokens.next().ok_or(ParseError {
message: "Expecting identifier in Initialization".into(),
position: None,
})?;
let Token::Id { value: id, .. } = next else {
return Err(ParseError {
message: "Expecting identifier in Initialization".into(),
position: Some(next.position()),
});
};

let Some(Token::Eq { .. }) = tokens.next() else {
todo!()
let next = tokens.next().ok_or(ParseError {
message: "Expecting '=' in Initialization".into(),
position: None,
})?;
let Token::Eq { .. } = next else {
return Err(ParseError {
message: "Expecting '=' in Initialization".into(),
position: Some(next.position()),
});
};

let value = Expression::parse(tokens)?;

let Some(Token::Semicolon { .. }) = tokens.next() else {
todo!()
let next = tokens.next().ok_or(ParseError {
message: "Expecting ';' in Initialization".into(),
position: None,
})?;
let Token::Semicolon { .. } = next else {
return Err(ParseError {
message: "Expecting ';' in Initialization".into(),
position: Some(next.position()),
});
};

Ok(Initialization { id, value })
Expand Down
9 changes: 6 additions & 3 deletions src/parser/ast/statement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ mod initialization;

pub use self::initialization::*;

use std::{error::Error, iter::Peekable};
use std::iter::Peekable;

use crate::{lexer::Token, parser::FromTokens};
use crate::{
lexer::Token,
parser::{FromTokens, ParseError},
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Statement {
Initialization(Initialization),
}

impl FromTokens for Statement {
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, Box<dyn Error>>
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, ParseError>
where
I: Iterator<Item = Token>,
Self: Sized,
Expand Down
22 changes: 20 additions & 2 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
use std::{error::Error, iter::Peekable};
use std::{error::Error, fmt::Display, iter::Peekable};

mod ast;

use crate::lexer::Token;

use self::ast::Statement;

#[derive(Debug, Clone)]
pub struct ParseError {
message: String,
position: Option<(usize, usize)>,
}

impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some((line, col)) = self.position {
f.write_fmt(format_args!("{} ({}:{})", self.message, line, col))
} else {
f.write_str(&self.message)
}
}
}

impl Error for ParseError {}

pub trait FromTokens {
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, Box<dyn Error>>
fn parse<I>(tokens: &mut Peekable<I>) -> Result<Self, ParseError>
where
I: Iterator<Item = Token>,
Self: Sized;
Expand Down

0 comments on commit 3d95997

Please sign in to comment.