From: Ben Pfaff Date: Sun, 15 Dec 2024 17:05:35 +0000 (-0800) Subject: got all of ctables X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b9635797b3fcfb37ef39aea9fa62fa56009dafe;p=pspp got all of ctables --- diff --git a/rust/pspp-derive/src/lib.rs b/rust/pspp-derive/src/lib.rs index 8934b3d34c..d13b46b708 100644 --- a/rust/pspp-derive/src/lib.rs +++ b/rust/pspp-derive/src/lib.rs @@ -31,63 +31,42 @@ fn derive_enum(ast: &DeriveInput, e: &DataEnum) -> Result { let mut body = TokenStream2::new(); let name = &ast.ident; let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - if struct_attrs.selector { - let mut variants = Vec::new(); - let mut default = None; - for (index, variant) in e.variants.iter().enumerate() { - let field_attrs = FieldAttrs::parse(&variant.attrs)?; - if field_attrs.default { - if default.is_none() { - default = Some(index); - } else { - return Err(Error::new(variant.span(), "Duplicate default variant")); - } - } - variants.push((variant, field_attrs)); - } - for (index, (variant, field_attrs)) in variants.iter().enumerate() { - if index > 0 { - body.extend(quote! { else }.into_iter()); - } - let ident = &variant.ident; + for variant in &e.variants { + let ident = &variant.ident; + let field_attrs = FieldAttrs::parse(&variant.attrs)?; + let selector = field_attrs.selector.unwrap_or(struct_attrs.selector); + let construction = construct_fields(&variant.fields, quote! { #name::#ident }, selector, None); + let fnname = format_ident!("construct_{ident}"); + body.extend(quote! { + fn #fnname #impl_generics(input: &TokenSlice) -> ParseResult<#name #ty_generics> #where_clause { let input = input.clone(); #construction } + }); + } + + for variant in &e.variants { + let ident = &variant.ident; + let fnname = format_ident!("construct_{ident}"); + let field_attrs = FieldAttrs::parse(&variant.attrs)?; + let selector = field_attrs.selector.unwrap_or(struct_attrs.selector); + if selector { let ident_string = ident.to_string(); - let match_expr = if let Some(syntax) = &field_attrs.syntax { + let select_expr = if let Some(syntax) = &field_attrs.syntax { quote! { input.skip_syntax(#syntax) } } else if ident_string.eq_ignore_ascii_case("all") { quote! { input.skip(&Token::Punct(Punct::All))} } else { quote! { input.skip_keyword(#ident_string)} }; - let construction = - construct_fields(&variant.fields, quote! { Self::#ident}, true, None); - body.extend(quote! { if let Some(input) = #match_expr { #construction } }); - } - if let Some(default) = default { - let (variant, _field_attrs) = &variants[default]; - let ident = &variant.ident; - let construction = - construct_fields(&variant.fields, quote! { Self::#ident}, true, None); - body.extend(quote! { else { #construction } }); + body.extend(quote! { if let Some(input) = #select_expr { return #fnname(&input); } }); } else { - body.extend( - quote! { else { Err(ParseError::Mismatch(input.error("Syntax error.").into())) } }, - ); - } - } else { - for (index, variant) in e.variants.iter().enumerate() { - let ident = &variant.ident; - let construction = - construct_fields(&variant.fields, quote! { #name::#ident }, false, None); - let fnname = format_ident!("construct{index}"); body.extend(quote! { - fn #fnname #impl_generics(input: &TokenSlice) -> ParseResult<#name #ty_generics> #where_clause { let input = input.clone(); #construction } - if let Ok(p) = #fnname(input) { - return Ok(p); + let result = #fnname(&input); + if let Ok(_) | Err(ParseError::Error(_)) = result { + return result; } }); } - body.extend(quote! { Err(ParseError::Mismatch(input.error("Syntax error.").into())) }); } + body.extend(quote! { Err(ParseError::Mismatch(input.error("Syntax error.").into())) }); let output = quote! { impl #impl_generics FromTokens for #name #ty_generics #where_clause { @@ -153,16 +132,11 @@ fn derive_struct(ast: &DeriveInput, s: &DataStruct) -> Result Result, - default: bool, + selector: Option, } impl FieldAttrs { @@ -193,8 +167,8 @@ impl FieldAttrs { meta.input.parse::()?; let syntax = meta.input.parse::()?; field_attrs.syntax = Some(syntax); - } else if meta.path.is_ident("default") { - field_attrs.default = true; + } else if meta.path.is_ident("no_selector") { + field_attrs.selector = Some(false); } else { return Err(Error::new(meta.path.span(), "Unknown attribute")); } diff --git a/rust/pspp/src/command/crosstabs.rs b/rust/pspp/src/command/crosstabs.rs index 3f6c3ab7f6..201b122e3d 100644 --- a/rust/pspp/src/command/crosstabs.rs +++ b/rust/pspp/src/command/crosstabs.rs @@ -42,12 +42,15 @@ mod keyword { #[derive(Debug, pspp_derive::FromTokens)] pub struct Count; + + #[derive(Debug, pspp_derive::FromTokens)] + pub struct Tables; } #[derive(Debug, pspp_derive::FromTokens)] enum CrosstabsSubcommand { - #[pspp(default)] - Tables(Option, Punctuated), + #[pspp(no_selector)] + Tables(Option<(keyword::Tables, Equals)>, Punctuated), Missing(Equals, Missing), Write(Option<(Equals, Write)>), HideSmallCounts(keyword::Count, Equals, Integer), diff --git a/rust/pspp/src/command/ctables.rs b/rust/pspp/src/command/ctables.rs index ce6adf5d9a..e7360e1f68 100644 --- a/rust/pspp/src/command/ctables.rs +++ b/rust/pspp/src/command/ctables.rs @@ -56,7 +56,7 @@ enum CTablesSubcommand { HideSmallCounts(keyword::Count, Equals, Integer), SLabels(Seq1), CLabels(CLabel), - Categories(Seq1), + Categories(Seq1), } #[derive(Debug, pspp_derive::FromTokens)] @@ -274,10 +274,15 @@ enum LabelDestination { } #[derive(Debug, pspp_derive::FromTokens)] -enum Category { +enum Categories { Variables(Equals, VarList), Order(Equals, Direction), Key(Equals, Key), + Missing(Equals, Include), + Total(Equals, Boolean), + Label(Equals, String), + Position(Equals, CategoryPosition), + Empty(Equals, Include), } #[derive(Debug, pspp_derive::FromTokens)] @@ -292,7 +297,20 @@ enum Direction { enum Key { Value, Label, - + #[pspp(no_selector)] + Summary(Summary), +} + +#[derive(Debug, pspp_derive::FromTokens)] +enum Include { + Include, + Exclude, +} + +#[derive(Debug, pspp_derive::FromTokens)] +enum CategoryPosition { + After, + Before, } mod keyword { diff --git a/rust/pspp/src/command/data_list.rs b/rust/pspp/src/command/data_list.rs index fb4a1896ee..dff6f16f4b 100644 --- a/rust/pspp/src/command/data_list.rs +++ b/rust/pspp/src/command/data_list.rs @@ -53,7 +53,7 @@ enum Setting { #[derive(Debug, pspp_derive::FromTokens)] enum Delimiter { - #[pspp(default)] // XXX this allows `STRING "string"` + #[pspp(no_selector)] String(String), Tab, } diff --git a/rust/pspp/src/command/descriptives.rs b/rust/pspp/src/command/descriptives.rs index 791de70054..57cafe1733 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, Seq1, Subcommand}; +use super::{Comma, Command, Equals, Punctuated, Seq1, Subcommands}; use crate::command::{ FromTokens, Identifier, InParens, MismatchToError, ParseError, ParseResult, Parsed, Punct, Token, TokenSlice, VarRange, @@ -14,24 +14,20 @@ pub(super) fn descriptives_command() -> Command { no_abbrev: false, name: "DESCRIPTIVES", run: Box::new(|context| { - let mut input = context.lexer.clone(); - while !input.is_empty() { - match >::from_tokens(&input) { - Ok(Parsed { - value: subcommand, - rest, - diagnostics, - }) => { - println!("\n{subcommand:?}"); - //println!("rest: {rest:?}"); - println!("warnings: {diagnostics:?}"); - //println!("{:?}", DescriptivesSubcommand::from_tokens(subcommand.0)); - input = rest; - } - Err(error) => { - println!("{error:?}"); - break; - } + let input = context.lexer.clone(); + match ::from_tokens(&input) { + Ok(Parsed { + value, + rest: _, + diagnostics, + }) => { + println!("\n{value:#?}"); + //println!("rest: {rest:?}"); + println!("warnings: {diagnostics:?}"); + //println!("{:?}", DescriptivesSubcommand::from_tokens(subcommand.0)); + } + Err(error) => { + println!("{error:?}"); } } }), @@ -40,18 +36,28 @@ pub(super) fn descriptives_command() -> Command { #[derive(Debug, pspp_derive::FromTokens)] struct Descriptives { - subcommands: Seq1>, + subcommands: Subcommands, } #[derive(Debug, pspp_derive::FromTokens)] enum DescriptivesSubcommand { - #[pspp(default)] - Variables(Option, Punctuated), Missing(Equals, Seq1), Save, Statistics(Equals, Seq1), Sort(Equals, Sort), Format(Equals, Seq1), + #[pspp(no_selector)] + Variables( + Option<(keyword::Variables, Equals)>, + Punctuated, + ), +} + +mod keyword { + use crate::command::{FromTokens, ParseResult, TokenSlice}; + + #[derive(Debug, pspp_derive::FromTokens)] + pub struct Variables; } #[derive(Debug, pspp_derive::FromTokens)]