diff --git a/lexer/src/lib.rs b/lexer/src/lib.rs index fff11a5..8340291 100644 --- a/lexer/src/lib.rs +++ b/lexer/src/lib.rs @@ -2,7 +2,11 @@ mod tests; use core::str; -use std::{borrow::Cow, fmt::Debug, slice::SliceIndex}; +use std::{ + borrow::Cow, + fmt::{Debug, Display}, + slice::SliceIndex, +}; use logos::Skip; pub use logos::{Logos, Span, SpannedIter}; @@ -396,9 +400,15 @@ fn accept_operator(lex: &mut Lexer<'_>) { #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct Slice<'a>(Cow<'a, [u8]>); +impl Display for Slice<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", String::from_utf8_lossy(&self.0).as_ref()) + } +} + impl Debug for Slice<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "\"{}\"", String::from_utf8_lossy(&self.0).as_ref()) + write!(f, "\"{self}\"") } } diff --git a/parser/src/ast.rs b/parser/src/ast.rs index f426f26..9ba3523 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -25,7 +25,7 @@ pub struct Rule<'a> { pub actions: Option>, } -#[derive(Debug, Clone)] +#[derive(Clone)] pub enum Atom<'a> { Variable(Variable<'a>), String(Slice<'a>), @@ -55,7 +55,7 @@ pub struct Identifier<'a> { pub literal: &'a str, } -#[derive(Debug, Clone, Copy)] +#[derive(Clone, Copy)] pub enum Variable<'a> { User(Identifier<'a>), Nr, @@ -82,7 +82,8 @@ pub enum Expr<'a> { Node(&'a ExprNode<'a>), } -pub type Body<'a> = Vec<'a, Statement<'a>>; +#[derive(Clone)] +pub struct Body<'a>(pub Vec<'a, Statement<'a>>); pub type Pattern<'a> = Either, SpecialPattern>; #[derive(Debug, Clone)] @@ -436,13 +437,19 @@ impl BindingPower for Ternary { } } +impl<'a> From>> for Body<'a> { + fn from(value: Vec<'a, Statement<'a>>) -> Self { + Self(value) + } +} + impl Debug for Expr<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Leaf(atom) => write!(f, "{atom:?}"), Self::Node(expr) => match expr { ExprNode::FunctionCall(ident, args) => { - write!(f, "(call Identifier({ident:?})")?; + write!(f, "({ident:?}")?; for arg in args { write!(f, " {arg:?}")?; } @@ -456,127 +463,3 @@ impl Debug for Expr<'_> { } } } - -struct ListLispFmt<'a, T: Debug>(&'a [T]); -struct ListLispCasesFmt<'a, I: Debug, T: Debug>(&'a [(I, Vec<'a, T>)]); - -impl Debug for Statement<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Statement::Expression(expr) => write!(f, "{expr:?}"), - Self::Command { - name, - args, - redirection, - } => { - if let Some(rx) = redirection { - write!(f, "(redir {rx:?} ({name:?}{:?}))", ListLispFmt(args)) - } else { - write!(f, "({name:?}{:?})", ListLispFmt(args)) - } - } - Self::If { - condition, - then_body, - else_body, - } => { - if let Some(else_body) = else_body { - write!( - f, - "(if {condition:?} (body{:?}) Some(body{:?}))", - ListLispFmt(then_body), - ListLispFmt(else_body) - ) - } else { - write!( - f, - "(if {condition:?} (body{:?}) None)", - ListLispFmt(then_body) - ) - } - } - Self::While { - condition, - then_body, - } => write!( - f, - "(while {condition:?} (body{:?}))", - ListLispFmt(then_body) - ), - Self::DoWhile { - then_body, - condition, - } => write!( - f, - "(do-while (body{:?}) {condition:?})", - ListLispFmt(then_body) - ), - Self::For { - init, - condition, - update, - body, - } => { - write!( - f, - "(for {init:?} {condition:?} {update:?} (body{:?}))", - ListLispFmt(body) - ) - } - Self::ForEach { place, array, body } => { - write!( - f, - "(for-each {place:?} {array:?} (body{:?}))", - ListLispFmt(body) - ) - } - Self::Switch { - scrutinee, - branches, - default, - } => { - if let Some((dx, i)) = default { - write!( - f, - "(switch {scrutinee:?} (cases{:?}) (body{:?}) {i})", - ListLispCasesFmt(branches), - ListLispFmt(dx) - ) - } else { - write!( - f, - "(switch {scrutinee:?} (cases{:?}))", - ListLispCasesFmt(branches) - ) - } - } - Self::Continue => write!(f, "(continue)"), - Self::Break => write!(f, "(break)"), - Self::Return(expr) => write!(f, "(return {expr:?})"), - } - } -} - -impl Debug for ListLispFmt<'_, T> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for e in self.0 { - write!(f, " {e:?}")?; - } - Ok(()) - } -} - -impl Debug for ListLispCasesFmt<'_, I, T> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for (i, e) in self.0 { - write!(f, " (case {i:?} (eval{:?})", ListLispFmt(e))?; - } - Ok(()) - } -} - -impl Debug for Identifier<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}::{}", self.namespace, self.literal) - } -} diff --git a/parser/src/lib.rs b/parser/src/lib.rs index c645574..1097d78 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -1,5 +1,6 @@ mod ast; mod lex; +mod sexpr; use std::{fmt::Debug, mem::replace}; @@ -173,7 +174,7 @@ impl<'a> Parser<'a> { match lex.expect_next()? { Token::ClosedBrace => { if depth == 0 { - break Ok(body); + break Ok(Body(body)); } depth -= 1; } @@ -238,7 +239,7 @@ impl<'a> Parser<'a> { return Err(ParsingError::UnexpectedToken); }; lex.expect(&Token::ClosedParent)?; - let body: Vec<'_, Statement<'_>> = self.parse_statement_body(lex)?; + let body = self.parse_statement_body(lex)?; Statement::ForEach { place: *place, array: *array, @@ -259,12 +260,14 @@ impl<'a> Parser<'a> { match case.take() { Some(Right(())) => { default = Some(( - replace(&mut body, Vec::new_in(self.arena)), + replace(&mut body, Vec::new_in(self.arena)).into(), branches.len(), )); } - Some(Left(atom)) => branches - .push((atom, replace(&mut body, Vec::new_in(self.arena)))), + Some(Left(atom)) => branches.push(( + atom, + replace(&mut body, Vec::new_in(self.arena)).into(), + )), _ => {} } case = Some(Left(self.parse_case(lex)?)); @@ -273,7 +276,10 @@ impl<'a> Parser<'a> { if default.is_some() || matches!(case, Some(Right(()))) { return Err(ParsingError::UnexpectedToken); } else if let Some(Left(atom)) = case { - branches.push((atom, replace(&mut body, Vec::new_in(self.arena)))); + branches.push(( + atom, + replace(&mut body, Vec::new_in(self.arena)).into(), + )); } case = Some(Right(())); } else { @@ -285,8 +291,8 @@ impl<'a> Parser<'a> { } } match case.take() { - Some(Right(())) => default = Some((body, branches.len())), - Some(Left(atom)) => branches.push((atom, body)), + Some(Right(())) => default = Some((body.into(), branches.len())), + Some(Left(atom)) => branches.push((atom, body.into())), _ => {} } @@ -360,7 +366,7 @@ impl<'a> Parser<'a> { if lex.peek_is(&Token::OpenBrace) { self.parse_body(lex) } else { - Ok(vec![in self.arena; self.parse_statement(lex)?]) + Ok(vec![in self.arena; self.parse_statement(lex)?].into()) } } diff --git a/parser/src/sexpr.rs b/parser/src/sexpr.rs new file mode 100644 index 0000000..31d1926 --- /dev/null +++ b/parser/src/sexpr.rs @@ -0,0 +1,249 @@ +use std::fmt::{Debug, Formatter, Result}; + +use crate::ast::{Atom, Body, Identifier, Statement, Variable}; + +const PRETTY_PRINT_INDENT: usize = 2; + +fn fmt_vars(f: &mut Formatter<'_>) -> (bool, usize, String) { + let ni = f.width().unwrap_or(0) + PRETTY_PRINT_INDENT; + (f.alternate(), ni, " ".repeat(ni)) +} + +impl Debug for Statement<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let (alt, ni, pad) = fmt_vars(f); + + match self { + Statement::Expression(expr) => { + if alt { + write!(f, "{expr:#ni$?}") + } else { + write!(f, "{expr:?}") + } + } + Self::Command { + name, + args, + redirection, + } => { + if let Some(rx) = redirection { + if alt { + write!( + f, + "(redir {rx:?}\n{pad}({name:?}{:#width$?}))", + ListLispFmt(args), + width = ni + ) + } else { + write!(f, "(redir {rx:?} ({name:?}{:?}))", ListLispFmt(args)) + } + } else { + if alt { + write!(f, "({name:?}{:#width$?})", ListLispFmt(args), width = ni) + } else { + write!(f, "({name:?}{:?}", ListLispFmt(args)) + } + } + } + Self::If { + condition, + then_body, + else_body, + } => { + if alt { + write!(f, "(if {condition:?}\n{pad}")?; + write!(f, "{then_body:#ni$?}")?; + if let Some(else_body) = else_body { + write!(f, "\n{pad}Some({else_body:#ni$?})") + } else { + write!(f, "\n{pad}None)") + } + } else if let Some(else_body) = else_body { + write!(f, "(if {condition:?} {then_body:?} Some({else_body:?})") + } else { + write!(f, "(if {condition:?} {then_body:?} None)") + } + } + Self::While { + condition, + then_body, + } => { + if alt { + write!(f, "(while {condition:?}\n{pad}{then_body:#ni$?})") + } else { + write!(f, "(while {condition:?} {then_body:?})") + } + } + Self::DoWhile { + then_body, + condition, + } => { + if alt { + write!(f, "(do-while\n{pad}{then_body:#ni$?}\n{pad}{condition:?})") + } else { + write!(f, "(do-while {then_body:?} {condition:?})") + } + } + Self::For { + init, + condition, + update, + body, + } => { + if alt { + write!( + f, + "(for\n{pad}{init:?}\n{pad}{condition:?}\n{pad}{update:?}\n{pad}{body:#ni$?})" + ) + } else { + write!(f, "(for {init:?} {condition:?} {update:?} {body:?})") + } + } + Self::ForEach { place, array, body } => { + if alt { + write!(f, "(for-each {place:?} {array:?}\n{pad}{body:#ni$?})") + } else { + write!(f, "(for-each {place:?} {array:?} {body:?})") + } + } + Self::Switch { + scrutinee, + branches, + default, + } => { + if alt { + if let Some((dx, i)) = default { + write!( + f, + "(switch {scrutinee:?}\n{pad}(cases{:#width$?})\n{pad}Some({dx:?}) {i})", + ListLispCasesFmt(branches.as_slice()), + width = ni + ) + } else { + write!( + f, + "(switch {scrutinee:?}\n{pad}(cases{:#width$?}))", + ListLispCasesFmt(branches), + width = ni + ) + } + } else { + if let Some((dx, i)) = default { + write!( + f, + "(switch {scrutinee:?} (cases{:?}) Some({dx:?}) {i})", + ListLispCasesFmt(branches.as_slice()) + ) + } else { + write!( + f, + "(switch {scrutinee:?} (cases{:?}))", + ListLispCasesFmt(branches) + ) + } + } + } + Self::Continue => write!(f, "(continue)"), + Self::Break => write!(f, "(break)"), + Self::Return(expr) => { + if alt { + write!(f, "(return {expr:#ni$?})") + } else { + write!(f, "(return {expr:?})") + } + } + } + } +} + +struct ListLispFmt<'a, T: Debug>(&'a [T]); +impl Debug for ListLispFmt<'_, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let (alt, ni, pad) = fmt_vars(f); + for e in self.0 { + if alt { + write!(f, "\n{pad}{e:#ni$?}")?; + } else { + write!(f, " {e:?}")?; + } + } + Ok(()) + } +} + +struct ListLispCasesFmt<'a, T: Debug>(&'a [(T, Body<'a>)]); +impl Debug for ListLispCasesFmt<'_, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let (alt, ni, pad) = fmt_vars(f); + for (i, e) in self.0 { + if alt { + write!( + f, + "\n{pad}(case {i:?}\n{pad} {:#width$?})", + e, + width = ni + PRETTY_PRINT_INDENT + )?; + } else { + write!(f, " (case {i:?} {e:?}")?; + } + } + Ok(()) + } +} + +impl Debug for Identifier<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{}::{}", self.namespace, self.literal) + } +} + +impl Debug for Body<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let (alt, ni, pad) = fmt_vars(f); + write!(f, "(body")?; + for e in &self.0 { + if alt { + write!(f, "\n{pad}{e:#ni$?}")?; + } else { + write!(f, " {e:?}")?; + } + } + write!(f, ")") + } +} + +impl Debug for Atom<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self { + Self::Variable(var) => write!(f, "{var:?}"), + Self::String(str) => write!(f, "{str:?}"), + Self::Number(num) => write!(f, "{num}"), + Self::Regex(rgx) => write!(f, "/{rgx}/"), + Self::BigInt() | Self::BigFloat() => unimplemented!(), + } + } +} + +impl Debug for Variable<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self { + Self::User(ident) => ident.fmt(f), + Self::Nr => write!(f, "NR"), + Self::Nf => write!(f, "NF"), + Self::Fs => write!(f, "FS"), + Self::Rs => write!(f, "RS"), + Self::Ofs => write!(f, "OFS"), + Self::Ors => write!(f, "ORS"), + Self::Filename => write!(f, "FILENAME"), + Self::Argc => write!(f, "ARGC"), + Self::Argv => write!(f, "ARGV"), + Self::Subsep => write!(f, "SUBSEP"), + Self::Fnr => write!(f, "FNR"), + Self::Argind => write!(f, "ARGIND"), + Self::Ofmt => write!(f, "OFMT"), + Self::Rstart => write!(f, "RSTART"), + Self::Rlength => write!(f, "RLENGTH"), + Self::Environ => write!(f, "ENVIRON"), + } + } +}