Skip to content

Commit

Permalink
♻️ (parser): Refactor parser
Browse files Browse the repository at this point in the history
semver: chore
  • Loading branch information
Somfic committed Jul 9, 2024
1 parent 5d00474 commit 3543d63
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 42 deletions.
18 changes: 18 additions & 0 deletions src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ impl<'a> Snippet<'a> {
Snippet::new(file_id, Label::Primary, position, length, message)
}

pub fn primary_from_token(token: &Token<'a>, message: impl Into<String>) -> Snippet<'a> {
Snippet::primary(
token.range.file_id,
token.range.position,
token.range.length,
message,
)
}

pub fn secondary(
file_id: impl Into<&'a str>,
position: usize,
Expand All @@ -122,6 +131,15 @@ impl<'a> Snippet<'a> {
Snippet::new(file_id, Label::Secondary, position, length, message)
}

pub fn secondary_from_token(token: &Token<'a>, message: impl Into<String>) -> Snippet<'a> {
Snippet::secondary(
token.range.file_id,
token.range.position,
token.range.length,
message,
)
}

pub fn new(
file_id: impl Into<&'a str>,
label: Label,
Expand Down
8 changes: 6 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ fn main() -> Result<()> {
let scanner = scanner::Scanner::new(&files);
let scanner_pass = scanner.parse();

//sscanner_pass.print_diagnostics(&files);
// scanner_pass.print_diagnostics(&files);

let mut parser = parser::Parser::new(&scanner_pass.result);
let parser_pass = parser.parse();
let parser_pass = parser.parse().unwrap();

parser.print_diagnostics(&files);

let transpiler = BendTranspiler::transpile(&parser_pass);

println!("{}", transpiler);

Ok(())
}
2 changes: 1 addition & 1 deletion src/parser/ast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::{HashMap, HashSet};

use crate::{diagnostic::Range, scanner::lexeme::Token};
use crate::scanner::lexeme::Token;

#[derive(Debug, Clone, PartialEq)]
pub enum Symbol<'a> {
Expand Down
83 changes: 83 additions & 0 deletions src/parser/expression/binary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::parser::{
ast::{BinaryOperation, Expression},
lookup::{BindingPower, Lookup},
macros::expect_token,
ParseResult, Parser,
};

pub fn register(lookup: &mut Lookup) {
use crate::scanner::lexeme::TokenType;

lookup.add_left_expression_handler(TokenType::Plus, BindingPower::Additive, parse_addative);
lookup.add_left_expression_handler(TokenType::Minus, BindingPower::Additive, parse_subtractive);
lookup.add_left_expression_handler(
TokenType::Star,
BindingPower::Multiplicative,
parse_multiplicative,
);
lookup.add_left_expression_handler(
TokenType::Slash,
BindingPower::Multiplicative,
parse_dividing,
);
}

fn parse_addative<'a>(
parser: &mut Parser<'a>,
left: Expression,
binding_power: BindingPower,
) -> ParseResult<'a, Expression> {
expect_token!(parser, Plus)?;
let right = super::parse(parser, binding_power)?;

Ok(Expression::Binary(
Box::new(left),
BinaryOperation::Plus,
Box::new(right),
))
}

fn parse_subtractive<'a>(
parser: &mut Parser<'a>,
left: Expression,
binding_power: BindingPower,
) -> ParseResult<'a, Expression> {
expect_token!(parser, Minus)?;
let right = super::parse(parser, binding_power)?;

Ok(Expression::Binary(
Box::new(left),
BinaryOperation::Minus,
Box::new(right),
))
}

fn parse_multiplicative<'a>(
parser: &mut Parser<'a>,
left: Expression,
binding_power: BindingPower,
) -> ParseResult<'a, Expression> {
expect_token!(parser, Star)?;
let right = super::parse(parser, binding_power)?;

Ok(Expression::Binary(
Box::new(left),
BinaryOperation::Times,
Box::new(right),
))
}

fn parse_dividing<'a>(
parser: &mut Parser<'a>,
left: Expression,
binding_power: BindingPower,
) -> ParseResult<'a, Expression> {
expect_token!(parser, Slash)?;
let right = super::parse(parser, binding_power)?;

Ok(Expression::Binary(
Box::new(left),
BinaryOperation::Divide,
Box::new(right),
))
}
16 changes: 8 additions & 8 deletions src/parser/expression/literals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,37 @@ pub(crate) fn register(lookup: &mut Lookup) {
.add_expression_handler(TokenType::Boolean, parse_boolean);
}

fn parse_decimal<'a>(parser: &mut Parser) -> ParseResult<'a, Expression> {
fn parse_decimal<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Expression> {
let decimal = expect_token!(parser, Decimal)?;
let decimal = expect_value!(decimal, Decimal).clone();
let decimal = *expect_value!(decimal, Decimal);

Ok(Expression::Number(decimal))
}

fn parse_integer<'a>(parser: &mut Parser) -> ParseResult<'a, Expression> {
fn parse_integer<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Expression> {
let integer = expect_token!(parser, Integer)?;
let integer = expect_value!(integer, Integer).clone();
let integer = *expect_value!(integer, Integer);

Ok(Expression::Number(integer as f64))
}

fn parse_string<'a>(parser: &mut Parser) -> ParseResult<'a, Expression> {
fn parse_string<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Expression> {
let string = expect_token!(parser, String)?;
let string = expect_value!(string, String).clone();

Ok(Expression::String(string))
}

fn parse_identifier<'a>(parser: &mut Parser) -> ParseResult<'a, Expression> {
fn parse_identifier<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Expression> {
let identifier = expect_token!(parser, Identifier)?;
let identifier = expect_value!(identifier, Identifier).clone();

Ok(Expression::Identifier(identifier))
}

fn parse_boolean<'a>(parser: &mut Parser) -> ParseResult<'a, Expression> {
fn parse_boolean<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Expression> {
let boolean = expect_token!(parser, Boolean)?;
let boolean = expect_value!(boolean, Boolean).clone();
let boolean = *expect_value!(boolean, Boolean);

Ok(Expression::Boolean(boolean))
}
38 changes: 24 additions & 14 deletions src/parser/expression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
use crate::diagnostic::Diagnostic;

use super::{ast::Expression, lookup::BindingPower, macros::expect_token, ParseResult, Parser};
use std::collections::HashSet;
use crate::diagnostic::{Diagnostic, Snippet};

pub mod binary;
pub mod literals;

pub fn parse<'a>(
parser: &mut Parser<'a>,
binding_power: &BindingPower,
binding_power: BindingPower,
) -> ParseResult<'a, Expression> {
let token = expect_token!(parser)?;

let expression_handler = parser
.lookup
.expression_lookup
.get(&parser.peek().unwrap().token_type)
.ok_or(Diagnostic::error("P0001", "Expected a new expression"))?;
.get(&token.token_type)
.ok_or(
Diagnostic::error("P0001", "Expected a new expression").with_snippet(
Snippet::primary_from_token(token, "Expected an expression to start here"),
),
)?;

let mut left_hand_side = expression_handler(parser)?;

Expand All @@ -23,8 +28,9 @@ pub fn parse<'a>(
let token_binding_power = parser
.lookup
.binding_power_lookup
.get(&token.token_type)
.unwrap_or(&BindingPower::None);
.get(&parser.peek().unwrap().token_type)
.copied()
.unwrap_or_default();

if binding_power > token_binding_power {
break;
Expand All @@ -42,13 +48,17 @@ pub fn parse<'a>(
Ok(left_hand_side)
}

pub fn parse_addative<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Expression> {
let plus = expect_token!(parser, Plus)?;
let left = parse(parser, &BindingPower::Additive)?;
pub(crate) fn register(lookup: &mut super::lookup::Lookup) {
literals::register(lookup);
binary::register(lookup);

todo!()
lookup.add_expression_handler(crate::scanner::lexeme::TokenType::ParenOpen, parse_grouping);
}

pub(crate) fn register(lookup: &mut super::lookup::Lookup) {
literals::register(lookup);
fn parse_grouping<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Expression> {
expect_token!(parser, ParenOpen)?;
let expression = parse(parser, BindingPower::None)?;
expect_token!(parser, ParenClose)?;

Ok(Expression::Grouping(Box::new(expression)))
}
11 changes: 6 additions & 5 deletions src/parser/lookup.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use super::{
ast::{BinaryOperation, Expression, Statement, Type},
ast::{Expression, Statement, Type},
ParseResult, Parser,
};
use crate::scanner::lexeme::{TokenType, TokenValue};
use crate::scanner::lexeme::TokenType;
use core::panic;
use std::collections::HashMap;

#[derive(Debug, PartialEq, PartialOrd)]
#[derive(Default, Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum BindingPower {
#[default]
None = 0,
Comma = 1,
Assignment = 2,
Expand All @@ -22,11 +23,11 @@ pub enum BindingPower {
}

pub type TypeHandler<'a> = fn(&mut Parser<'a>) -> ParseResult<'a, Type>;
pub type LeftTypeHandler<'a> = fn(&mut Parser<'a>, Type, &BindingPower) -> ParseResult<'a, Type>;
pub type LeftTypeHandler<'a> = fn(&mut Parser<'a>, Type, BindingPower) -> ParseResult<'a, Type>;
pub type StatementHandler<'a> = fn(&mut Parser<'a>) -> ParseResult<'a, Statement>;
pub type ExpressionHandler<'a> = fn(&mut Parser<'a>) -> ParseResult<'a, Expression>;
pub type LeftExpressionHandler<'a> =
fn(&mut Parser<'a>, Expression, &BindingPower) -> ParseResult<'a, Expression>;
fn(&mut Parser<'a>, Expression, BindingPower) -> ParseResult<'a, Expression>;

pub struct Lookup<'a> {
pub statement_lookup: HashMap<TokenType, StatementHandler<'a>>,
Expand Down
44 changes: 40 additions & 4 deletions src/parser/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,48 @@ macro_rules! expect_token {
if let Some(TokenType::$token) = $parser.peek().map(|t| &t.token_type) {
Ok($parser.consume().unwrap())
} else {
Err(Diagnostic::error(
"expected_token",
format!("Expected token {:?}", TokenType::$token),
))
let token = $parser.peek().unwrap_or($parser.tokens.last().unwrap());
let position = if $parser.peek().is_none() {
token.range.position + token.range.length
} else {
token.range.position
};

Err(
Diagnostic::error("expected_token", format!("Expected {}", TokenType::$token))
.with_snippet(crate::diagnostic::Snippet::primary(
token.range.file_id,
position,
1,
format!("Expected {} here", TokenType::$token),
))
.with_note(format!(
"Expected {}, but got {} instead",
TokenType::$token,
token.token_type
)),
)
}
}};

($parser:ident) => {
if let Some(token) = $parser.peek() {
Ok(token)
} else {
let token = $parser.tokens.last().unwrap();

Err(
Diagnostic::error("expected_token", "Unexpected end of file")
.with_snippet(crate::diagnostic::Snippet::primary(
token.range.file_id,
token.range.position + token.range.length,
1,
"Unexpected end of file",
))
.with_note("Expected more code, but reached the end of the file"),
)
}
};
}

macro_rules! expect_value {
Expand Down
12 changes: 11 additions & 1 deletion src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,24 @@ impl<'a> Parser<'a> {

pub fn parse(&mut self) -> ParseResult<'a, Symbol<'a>> {
let mut statements = Vec::new();
let mut panic_mode = false;

while self.has_tokens() {
match statement::parse(self) {
Ok(statement) => {
if panic_mode {
panic_mode = false;
}

statements.push(statement);
}
Err(diagnostic) => {
self.diagnostics.insert(diagnostic);
if !panic_mode {
self.diagnostics.insert(diagnostic);
}

self.consume();
panic_mode = true;
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/parser/statement/enums.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::{
parser::{ast::Statement, lookup::Lookup, macros::expect_token, ParseResult, Parser},
scanner::lexeme::TokenType,
};

pub fn register(lookup: &mut Lookup) {
lookup.add_statement_handler(TokenType::Enum, parse_enum);
}

fn parse_enum<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Statement> {
expect_token!(parser, Enum)?;

todo!()
}
Loading

0 comments on commit 3543d63

Please sign in to comment.