From b8ad15396dbd4bfebdf1ac0f6fb1ec20e780ec4d Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 6 Dec 2024 09:45:26 -0800 Subject: [PATCH] data list --- rust/pspp-derive/src/lib.rs | 2 +- rust/pspp/src/command/data_list.rs | 47 ++++++++---- rust/pspp/src/command/descriptives.rs | 10 +-- rust/pspp/src/command/mod.rs | 100 ++++++++++++++++++++++---- 4 files changed, 125 insertions(+), 34 deletions(-) diff --git a/rust/pspp-derive/src/lib.rs b/rust/pspp-derive/src/lib.rs index 26e1c64fd4..14e56ad4f0 100644 --- a/rust/pspp-derive/src/lib.rs +++ b/rust/pspp-derive/src/lib.rs @@ -166,7 +166,7 @@ fn derive_struct(ast: &DeriveInput, s: &DataStruct) -> Result Command { #[derive(Debug, pspp_derive::FromTokens)] #[pspp(add_lifetime)] -struct DataList<'a>(Vec>); +struct DataList<'a>(Seq1>, Seq1>); #[derive(Debug, pspp_derive::FromTokens)] #[pspp(add_lifetime)] @@ -67,18 +67,41 @@ enum File<'a> { Handle(&'a Identifier), } -#[derive(Debug, pspp_derive::FromTokens)] -#[pspp(add_lifetime)] +#[derive(Debug)] struct Record<'a> { slash: Slash, record: Option, - variables: Vec>, + variables: Seq0>, +} + +impl<'a> FromTokens<'a> for Record<'a> { + fn from_tokens(input: TokenSlice<'a>) -> ParseResult<'a, Self> { + println!("{input:?}"); + println!("{}:{}", file!(), line!()); + let mut diagnostics = crate::command::Diagnostics::default(); + println!("{}:{}", file!(), line!()); + let (field0, input) = FromTokens::from_tokens(input)?.take_diagnostics(&mut diagnostics); + println!("{}:{}", file!(), line!()); + let (field1, input) = FromTokens::from_tokens(input)?.take_diagnostics(&mut diagnostics); + println!("{}:{}", file!(), line!()); + let (field2, input) = FromTokens::from_tokens(input)?.take_diagnostics(&mut diagnostics); + println!("{}:{}", file!(), line!()); + Ok(Parsed::new( + Record { + slash: field0, + record: field1, + variables: field2, + }, + input, + diagnostics, + )) + } } #[derive(Debug, pspp_derive::FromTokens)] #[pspp(add_lifetime)] struct Variable<'a> { - names: Vec<&'a Identifier>, + names: Seq1<&'a Identifier>, location: Location<'a>, } @@ -119,15 +142,9 @@ mod tests { #[test] fn basics() { test( - "CROSSTABS r by c /STATISTICS=CHISQ -/CELLS=COUNT EXPECTED RESID SRESID ASRESID -/HIDESMALLCOUNTS COUNT=6. -", + r#"DATA LIST FILE="/data/hubdata.txt" RECORDS=3 +/1 DEPT 19 SEX 20 MOHIRED YRHIRED 12-15 +/2 SALARY 21-25."#, ); } - - #[test] - fn integer_mode() { - test("CROSSTABS VARIABLES=X (1,7) Y (1,7) /TABLES=X BY Y/WRITE=CELLS."); - } } diff --git a/rust/pspp/src/command/descriptives.rs b/rust/pspp/src/command/descriptives.rs index 20ab7587ff..604b02be41 100644 --- a/rust/pspp/src/command/descriptives.rs +++ b/rust/pspp/src/command/descriptives.rs @@ -1,6 +1,6 @@ use flagset::FlagSet; -use super::{Comma, Command, Equals, Punctuated, Subcommand}; +use super::{Comma, Command, Equals, Punctuated, Seq1, Subcommand}; use crate::command::{ FromTokens, Identifier, InParens, MismatchToError, ParseError, ParseResult, Parsed, Punct, Token, TokenSlice, VarRange, @@ -41,7 +41,7 @@ pub(super) fn descriptives_command() -> Command { #[derive(Debug, pspp_derive::FromTokens)] #[pspp(add_lifetime)] struct Descriptives<'a> { - subcommands: Vec>>, + subcommands: Seq1>>, } #[derive(Debug, pspp_derive::FromTokens)] @@ -49,11 +49,11 @@ struct Descriptives<'a> { enum DescriptivesSubcommand<'a> { #[pspp(default)] Variables(Option, Punctuated>), - Missing(Equals, Vec), + Missing(Equals, Seq1), Save, - Statistics(Equals, Vec), + Statistics(Equals, Seq1), Sort(Equals, Sort), - Format(Equals, Vec), + Format(Equals, Seq1), } #[derive(Debug, pspp_derive::FromTokens)] diff --git a/rust/pspp/src/command/mod.rs b/rust/pspp/src/command/mod.rs index 7b8ac31ce5..3c6871bd4f 100644 --- a/rust/pspp/src/command/mod.rs +++ b/rust/pspp/src/command/mod.rs @@ -189,7 +189,7 @@ where } #[derive(Debug, pspp_derive::FromTokens)] -#[pspp(syntax="/")] +#[pspp(syntax = "/")] pub struct Slash; #[derive(Debug)] @@ -204,17 +204,9 @@ impl<'a> FromTokens<'a> for Comma { } } -#[derive(Debug)] -pub struct Equals(Token); - -impl<'a> FromTokens<'a> for Equals { - fn from_tokens(input: TokenSlice<'a>) -> ParseResult<'a, Self> - where - Self: Sized, - { - _parse_token(input, &Token::Punct(Punct::Equals)).map(|p| p.map(|token| Equals(token))) - } -} +#[derive(Debug, pspp_derive::FromTokens)] +#[pspp(syntax = "=")] +pub struct Equals; #[derive(Debug)] struct By(Token); @@ -362,6 +354,88 @@ where } } +#[derive(Debug)] +pub struct Seq0(Vec); + +impl<'a, T> FromTokens<'a> for Seq0 +where + T: FromTokens<'a>, +{ + fn from_tokens(mut input: TokenSlice<'a>) -> ParseResult<'a, Self> + where + Self: Sized, + { + let mut values_vec = Vec::new(); + let mut warnings_vec = Vec::new(); + while !input.is_empty() { + match T::from_tokens(input) { + Ok(Parsed { + value, + rest, + diagnostics: mut warnings, + }) => { + warnings_vec.append(&mut warnings.0); + if input.len() == rest.len() { + break; + } + values_vec.push(value); + input = rest; + } + Err(ParseError::Mismatch(_)) => break, + Err(ParseError::Error(e)) => return Err(ParseError::Error(e)), + } + } + Ok(Parsed { + value: Seq0(values_vec), + rest: input, + diagnostics: Diagnostics(warnings_vec), + }) + } +} + +#[derive(Debug)] +pub struct Seq1(Vec); + +impl<'a, T> FromTokens<'a> for Seq1 +where + T: FromTokens<'a>, +{ + fn from_tokens(mut input: TokenSlice<'a>) -> ParseResult<'a, Self> + where + Self: Sized, + { + let mut values_vec = Vec::new(); + let mut warnings_vec = Vec::new(); + while !input.is_empty() { + match T::from_tokens(input) { + Ok(Parsed { + value, + rest, + diagnostics: mut warnings, + }) => { + warnings_vec.append(&mut warnings.0); + if input.len() == rest.len() { + break; + } + values_vec.push(value); + input = rest; + } + Err(ParseError::Mismatch(_)) => break, + Err(ParseError::Error(e)) => return Err(ParseError::Error(e)), + } + } + if values_vec.is_empty() { + return Err(ParseError::Mismatch(input.error("Syntax error.").into())); + } + Ok(Parsed { + value: Seq1(values_vec), + rest: input, + diagnostics: Diagnostics(warnings_vec), + }) + } +} + +/* impl<'a, T> FromTokens<'a> for Vec where T: FromTokens<'a>, @@ -393,7 +467,7 @@ where diagnostics: Diagnostics(warnings_vec), }) } -} +}*/ impl<'a> FromTokens<'a> for TokenSlice<'a> { fn from_tokens(input: TokenSlice<'a>) -> ParseResult<'a, Self> -- 2.30.2