diff --git a/src/ast.rs b/src/ast.rs --- a/src/ast.rs +++ b/src/ast.rs @@ -8,23 +8,23 @@ pub enum Expr { Binary { left: Box>, - op: BinaryOp, + op: Spanned, right: Box>, }, Grouping { inner: Box>, }, Literal { - lit: Literal, + lit: Spanned, }, Unary { - op: UnaryOp, + op: Spanned, expr: Box>, }, } impl Expr { - pub fn binary(lhs: Spanned, op: BinaryOp, rhs: Spanned) -> Spanned { + pub fn binary(lhs: Spanned, op: Spanned, rhs: Spanned) -> Spanned { let span = lhs.span().join(&rhs.span()); let e = Self::Binary { left: Box::new(lhs), @@ -48,13 +48,13 @@ Spanned::new(e, span) } - pub fn literal(lit: Literal) -> Spanned { - let span = lit.span; + pub fn literal(lit: Spanned) -> Spanned { + let span = lit.span(); let e = Self::Literal { lit }; Spanned::new(e, span) } - pub fn unary(op: UnaryOp, expr: Spanned) -> Spanned { - let span = op.span.join(&expr.span()); + pub fn unary(op: Spanned, expr: Spanned) -> Spanned { + let span = op.span().join(&expr.span()); let e = Self::Unary { op, expr: Box::new(expr), @@ -92,10 +92,7 @@ other => panic!("expected unary expression, got {:?}", other.as_str()), } } -} -#[cfg(test)] -impl Expr { fn as_str(&self) -> &'static str { match self { Expr::Binary { .. } => "binary", @@ -106,14 +103,8 @@ } } -#[derive(Clone, Copy, Debug)] -pub struct BinaryOp { - pub kind: BinaryOpKind, - pub span: Span, -} - #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum BinaryOpKind { +pub enum BinaryOp { // Equality Eq, NotEq, @@ -133,20 +124,8 @@ Div, } -impl BinaryOp { - pub fn new(kind: BinaryOpKind, span: Span) -> Self { - Self { kind, span } - } -} - #[derive(Clone, Debug)] -pub struct Literal { - pub kind: LiteralKind, - pub span: Span, -} - -#[derive(Clone, Debug)] -pub enum LiteralKind { +pub enum Literal { String(String), Number(f64), Bool(bool), @@ -154,99 +133,72 @@ } impl Literal { - pub fn string(val: String, span: Span) -> Self { - Self { - kind: LiteralKind::String(val), - span, - } + pub fn string(val: String, span: Span) -> Spanned { + Spanned::new(Self::String(val), span) } - pub fn number(val: f64, span: Span) -> Self { - Self { - kind: LiteralKind::Number(val), - span, - } + pub fn number(val: f64, span: Span) -> Spanned { + Spanned::new(Self::Number(val), span) } - pub fn bool(val: bool, span: Span) -> Self { - Self { - kind: LiteralKind::Bool(val), - span, - } + pub fn bool(val: bool, span: Span) -> Spanned { + Spanned::new(Self::Bool(val), span) } - pub fn nil(span: Span) -> Self { - Self { - kind: LiteralKind::Nil, - span, - } + pub fn nil(span: Span) -> Spanned { + Spanned::new(Self::Nil, span) } } #[cfg(test)] impl Literal { pub fn unwrap_string(&self) -> &str { - match &self.kind { - LiteralKind::String(s) => s.as_str(), + match &self { + Literal::String(s) => s.as_str(), other => panic!("expected string literal, got {:?}", other.as_str()), } } pub fn unwrap_number(&self) -> f64 { - match &self.kind { - LiteralKind::Number(n) => *n, + match &self { + Literal::Number(n) => *n, other => panic!("expected number literal, got {:?}", other.as_str()), } } pub fn unwrap_bool(&self) -> bool { - match &self.kind { - LiteralKind::Bool(b) => *b, + match &self { + Literal::Bool(b) => *b, other => panic!("expected bool literal, got {:?}", other.as_str()), } } pub fn is_nil(&self) -> bool { - matches!(&self.kind, LiteralKind::Nil) + matches!(&self, Literal::Nil) } -} -#[cfg(test)] -impl LiteralKind { fn as_str(&self) -> &'static str { match self { - LiteralKind::String(_) => "string", - LiteralKind::Number(_) => "number", - LiteralKind::Bool(_) => "bool", - LiteralKind::Nil => "nil", + Literal::String(_) => "string", + Literal::Number(_) => "number", + Literal::Bool(_) => "bool", + Literal::Nil => "nil", } } } -#[derive(Clone, Copy, Debug)] -pub struct UnaryOp { - pub kind: UnaryOpKind, - pub span: Span, -} - #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum UnaryOpKind { +pub enum UnaryOp { Negative, Invert, } impl UnaryOp { - pub fn negative(span: Span) -> Self { - Self { - span, - kind: UnaryOpKind::Negative, - } + pub fn negative(span: Span) -> Spanned { + Spanned::new(Self::Negative, span) } - pub fn invert(span: Span) -> Self { - Self { - span, - kind: UnaryOpKind::Invert, - } + pub fn invert(span: Span) -> Spanned { + Spanned::new(Self::Invert, span) } } diff --git a/src/parser.rs b/src/parser.rs --- a/src/parser.rs +++ b/src/parser.rs @@ -4,7 +4,7 @@ use crate::ast::UnaryOp; use crate::span::Spanned; use crate::{ - ast::{Ast, BinaryOp, BinaryOpKind, Expr, Literal}, + ast::{Ast, BinaryOp, Expr, Literal}, match_token::MatchToken, token::{Token, TokenKind}, }; @@ -66,15 +66,15 @@ let mut expr = self.[]()?; while let Some(op) = self.pop_if_map(|t| { - let kind = match t.kind { - $(TokenKind::$token_kind => BinaryOpKind::$op_kind,)* - $(TokenKind::$shared_kind => BinaryOpKind::$shared_kind,)* + let op = match t.kind { + $(TokenKind::$token_kind => BinaryOp::$op_kind,)* + $(TokenKind::$shared_kind => BinaryOp::$shared_kind,)* _ => return None, }; - Some(BinaryOp::new(kind, t.span)) + Some(Spanned::new(op, t.span)) }) { tracing::debug!( - kind = ?op.kind, + kind = ?&op, concat!("found ", stringify!($category), " operator") ); let rhs = self.parse_expr()?; @@ -138,7 +138,7 @@ }; Some(lit) }) { - tracing::debug!(lit_kind = ?lit.kind, span = %lit.span, "parsed literal"); + tracing::debug!(lit = ?&lit, span = ?lit.span(), "parsed literal"); Expr::literal(lit) } else { self.parse_grouping()? @@ -279,14 +279,11 @@ parse(tokens).unwrap_err() } - fn assert_binary_expr_op(input_map: &[(&'static str, BinaryOpKind)]) { + fn assert_binary_expr_op(input_map: &[(&'static str, BinaryOp)]) { for (input, expected_op) in input_map { let e = parse_to_expr(&format!("1 {input} 2")); let (left, parsed_op, right) = e.unwrap_binary(); - assert_eq!( - parsed_op.kind, *expected_op, - "should parse to `{expected_op:?}`" - ); + assert_eq!(parsed_op, expected_op, "should parse to `{expected_op:?}`"); assert_eq!(left.unwrap_literal().unwrap_number(), 1.0); assert_eq!(right.unwrap_literal().unwrap_number(), 2.0); } @@ -297,10 +294,10 @@ let expr = parse_to_expr("1 + -1"); let (left, op, right) = expr.unwrap_binary(); assert_eq!(left.unwrap_literal().unwrap_number(), 1.0); - assert_eq!(op.kind, BinaryOpKind::Add); + assert_eq!(*op, BinaryOp::Add); let (u_op, u_expr) = right.unwrap_unary(); - assert_eq!(u_op.kind, UnaryOpKind::Negative); + assert_eq!(*u_op, UnaryOp::Negative); assert_eq!(u_expr.unwrap_literal().unwrap_number(), 1.0); } @@ -311,14 +308,14 @@ #[test] fn parses_equality_expr() { - use BinaryOpKind::*; + use BinaryOp::*; start_test_tracing(); assert_binary_expr_op(&[("==", Eq), ("!=", NotEq)]); } #[test] fn parses_comparison_expr() { - use BinaryOpKind::*; + use BinaryOp::*; start_test_tracing(); assert_binary_expr_op(&[ (">", Greater), @@ -330,31 +327,31 @@ #[test] fn parses_term_expr() { - use BinaryOpKind::*; + use BinaryOp::*; start_test_tracing(); assert_binary_expr_op(&[("+", Add), ("-", Sub)]); } #[test] fn parses_factor_expr() { - use BinaryOpKind::*; + use BinaryOp::*; start_test_tracing(); assert_binary_expr_op(&[("*", Mult), ("/", Div)]); } #[test] fn parses_unary_expr() { - fn assert_unary_expr_op(input: &str, expected_op: UnaryOpKind) { + fn assert_unary_expr_op(input: &str, expected_op: UnaryOp) { let expr = parse_to_expr(&format!("{input} 1")); let (op, inner) = expr.unwrap_unary(); - assert_eq!(op.kind, expected_op, "should parse to op `{expected_op:?}`"); + assert_eq!(*op, expected_op, "should parse to op `{expected_op:?}`"); assert_eq!(inner.unwrap_literal().unwrap_number(), 1.0); } start_test_tracing(); - assert_unary_expr_op("-", UnaryOpKind::Negative); - assert_unary_expr_op("!", UnaryOpKind::Invert); + assert_unary_expr_op("-", UnaryOp::Negative); + assert_unary_expr_op("!", UnaryOp::Invert); } #[test]