use std::fmt::{self, Display, Formatter}; use crate::Token; use super::{CompileError, Compiler}; pub type Parser<'a> = fn(&mut Compiler<'a>) -> Result<(), CompileError>; /// Rule that defines how to parse a token. #[derive(Debug, Clone, Copy)] pub struct ParseRule<'a> { pub prefix: Option>, pub infix: Option>, pub precedence: Precedence, } impl From<&Token<'_>> for ParseRule<'_> { fn from(token: &Token) -> Self { match token { Token::ArrowThin => ParseRule { prefix: Some(Compiler::expect_expression), infix: None, precedence: Precedence::None, }, Token::Async => todo!(), Token::Bang => ParseRule { prefix: Some(Compiler::parse_unary), infix: None, precedence: Precedence::Unary, }, Token::BangEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_comparison_binary), precedence: Precedence::Comparison, }, Token::Bool => ParseRule { prefix: Some(Compiler::expect_expression), infix: None, precedence: Precedence::None, }, Token::Boolean(_) => ParseRule { prefix: Some(Compiler::parse_boolean), infix: None, precedence: Precedence::None, }, Token::Break => todo!(), Token::Byte(_) => ParseRule { prefix: Some(Compiler::parse_byte), infix: None, precedence: Precedence::None, }, Token::Character(_) => ParseRule { prefix: Some(Compiler::parse_character), infix: None, precedence: Precedence::None, }, Token::Colon => ParseRule { prefix: Some(Compiler::expect_expression), infix: None, precedence: Precedence::None, }, Token::Comma => ParseRule { prefix: None, infix: None, precedence: Precedence::None, }, Token::Dot => ParseRule { prefix: Some(Compiler::expect_expression), infix: None, precedence: Precedence::None, }, Token::DoubleAmpersand => ParseRule { prefix: None, infix: Some(Compiler::parse_logical_binary), precedence: Precedence::LogicalAnd, }, Token::DoubleEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_comparison_binary), precedence: Precedence::Comparison, }, Token::DoublePipe => ParseRule { prefix: None, infix: Some(Compiler::parse_logical_binary), precedence: Precedence::LogicalOr, }, Token::DoubleDot => ParseRule { prefix: Some(Compiler::expect_expression), infix: None, precedence: Precedence::None, }, Token::Eof => ParseRule { prefix: None, infix: None, precedence: Precedence::None, }, Token::Equal => ParseRule { prefix: None, infix: None, precedence: Precedence::Assignment, }, Token::Else => ParseRule { prefix: None, infix: None, precedence: Precedence::None, }, Token::Float(_) => ParseRule { prefix: Some(Compiler::parse_float), infix: None, precedence: Precedence::None, }, Token::FloatKeyword => ParseRule { prefix: Some(Compiler::expect_expression), infix: None, precedence: Precedence::None, }, Token::Fn => ParseRule { prefix: Some(Compiler::parse_function), infix: None, precedence: Precedence::None, }, Token::Greater => ParseRule { prefix: None, infix: Some(Compiler::parse_comparison_binary), precedence: Precedence::Comparison, }, Token::GreaterEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_comparison_binary), precedence: Precedence::Comparison, }, Token::Identifier(_) => ParseRule { prefix: Some(Compiler::parse_variable), infix: None, precedence: Precedence::None, }, Token::If => ParseRule { prefix: Some(Compiler::parse_if), infix: None, precedence: Precedence::None, }, Token::Int => ParseRule { prefix: Some(Compiler::expect_expression), infix: None, precedence: Precedence::None, }, Token::Integer(_) => ParseRule { prefix: Some(Compiler::parse_integer), infix: None, precedence: Precedence::None, }, Token::LeftBrace => ParseRule { prefix: Some(Compiler::parse_block), infix: None, precedence: Precedence::None, }, Token::LeftParenthesis => ParseRule { prefix: Some(Compiler::parse_grouped), infix: Some(Compiler::parse_call), precedence: Precedence::Call, }, Token::LeftBracket => ParseRule { prefix: Some(Compiler::parse_list), infix: None, precedence: Precedence::None, }, Token::Less => ParseRule { prefix: None, infix: Some(Compiler::parse_comparison_binary), precedence: Precedence::Comparison, }, Token::LessEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_comparison_binary), precedence: Precedence::Comparison, }, Token::Let => ParseRule { prefix: Some(Compiler::parse_let_statement), infix: None, precedence: Precedence::Assignment, }, Token::Loop => todo!(), Token::Map => todo!(), Token::Minus => ParseRule { prefix: Some(Compiler::parse_unary), infix: Some(Compiler::parse_math_binary), precedence: Precedence::Term, }, Token::MinusEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Assignment, }, Token::Mut => ParseRule { prefix: None, infix: None, precedence: Precedence::None, }, Token::Percent => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Factor, }, Token::PercentEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Assignment, }, Token::Plus => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Term, }, Token::PlusEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Assignment, }, Token::Return => ParseRule { prefix: Some(Compiler::parse_return_statement), infix: None, precedence: Precedence::None, }, Token::RightBrace => ParseRule { prefix: None, infix: None, precedence: Precedence::None, }, Token::RightParenthesis => ParseRule { prefix: None, infix: None, precedence: Precedence::None, }, Token::RightBracket => ParseRule { prefix: None, infix: None, precedence: Precedence::None, }, Token::Semicolon => ParseRule { prefix: Some(Compiler::parse_semicolon), infix: None, precedence: Precedence::None, }, Token::Slash => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Factor, }, Token::SlashEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Assignment, }, Token::Star => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Factor, }, Token::StarEqual => ParseRule { prefix: None, infix: Some(Compiler::parse_math_binary), precedence: Precedence::Assignment, }, Token::Str => ParseRule { prefix: Some(Compiler::expect_expression), infix: None, precedence: Precedence::None, }, Token::String(_) => ParseRule { prefix: Some(Compiler::parse_string), infix: None, precedence: Precedence::None, }, Token::Struct => todo!(), Token::While => ParseRule { prefix: Some(Compiler::parse_while), infix: None, precedence: Precedence::None, }, } } } /// Operator precedence levels. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum Precedence { Primary = 9, Call = 8, Unary = 7, Factor = 6, Term = 5, Comparison = 4, LogicalAnd = 3, LogicalOr = 2, Assignment = 1, None = 0, } impl Precedence { pub fn increment(&self) -> Self { match self { Precedence::None => Precedence::Assignment, Precedence::Assignment => Precedence::LogicalOr, Precedence::LogicalOr => Precedence::LogicalAnd, Precedence::LogicalAnd => Precedence::Comparison, Precedence::Comparison => Precedence::Term, Precedence::Term => Precedence::Factor, Precedence::Factor => Precedence::Unary, Precedence::Unary => Precedence::Call, Precedence::Call => Precedence::Primary, Precedence::Primary => Precedence::Primary, } } } impl Display for Precedence { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{:?}", self) } }