work on ctables
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 14 Dec 2024 17:29:35 +0000 (09:29 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 14 Dec 2024 17:29:35 +0000 (09:29 -0800)
rust/pspp-derive/src/lib.rs
rust/pspp/src/command/crosstabs.rs
rust/pspp/src/command/ctables.rs
rust/pspp/src/command/mod.rs

index afc1f5665fdfd095565b74b06924789fcb6d8ed3..8934b3d34c153011bab31b237b3e3a55771fab7c 100644 (file)
@@ -152,11 +152,16 @@ fn construct_fields(
 fn derive_struct(ast: &DeriveInput, s: &DataStruct) -> Result<TokenStream2, Error> {
     let struct_attrs = StructAttrs::parse(&ast.attrs)?;
     let name = &ast.ident;
+    let syntax = if let Some(syntax) = struct_attrs.syntax.as_ref() {
+      syntax .clone()
+    } else {
+        Literal::string(&name.to_string())
+    };
     let construction = construct_fields(
         &s.fields,
         quote! {#name},
         false,
-        struct_attrs.syntax.as_ref(),
+        Some(&syntax)
     );
     let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
     let output = quote! {
index 7644169f2b28f14b46dbadb6c18ce8c40c2e2a86..3f6c3ab7f68e65b37c662564c9a2b4b6f8c1830a 100644 (file)
@@ -37,9 +37,12 @@ pub(super) fn crosstabs_command() -> Command {
 #[derive(Debug, pspp_derive::FromTokens)]
 struct Crosstabs(Subcommands<CrosstabsSubcommand>);
 
-#[derive(Debug, pspp_derive::FromTokens)]
-#[pspp(syntax = "COUNT")]
-struct CountKw;
+mod keyword {
+    use crate::command::{FromTokens, ParseResult, TokenSlice};
+
+    #[derive(Debug, pspp_derive::FromTokens)]
+    pub struct Count;
+}
 
 #[derive(Debug, pspp_derive::FromTokens)]
 enum CrosstabsSubcommand {
@@ -47,7 +50,7 @@ enum CrosstabsSubcommand {
     Tables(Option<Equals>, Punctuated<VarList, By>),
     Missing(Equals, Missing),
     Write(Option<(Equals, Write)>),
-    HideSmallCounts(CountKw, Equals, Integer),
+    HideSmallCounts(keyword::Count, Equals, Integer),
     ShowDim(Equals, Integer),
     Statistics(Equals, Punctuated<Statistic>),
     Cells(Equals, Punctuated<Cell>),
index 328bac997669f0701d81ef6d17f100c27aa97172..ce6adf5d9a8023369d73641e0ab939bed4d6497b 100644 (file)
@@ -1,3 +1,5 @@
+use std::fmt::Debug;
+
 use either::Either;
 use flagset::FlagSet;
 
@@ -46,9 +48,15 @@ struct CTables(Subcommands<CTablesSubcommand>);
 enum CTablesSubcommand {
     Table(Table),
     Format(Seq1<Format>),
-    VLabels(Seq1<VLabels>),
+    VLabels(Seq1<VLabel>),
     SMissing(SMissing),
     PCompute(And, Identifier, Equals, keyword::Expr, InParens<Expression>),
+    PProperties(And, Identifier, Seq0<PProperties>),
+    Weight(keyword::Variable, Equals, Identifier),
+    HideSmallCounts(keyword::Count, Equals, Integer),
+    SLabels(Seq1<SLabel>),
+    CLabels(CLabel),
+    Categories(Seq1<Category>),
 }
 
 #[derive(Debug, pspp_derive::FromTokens)]
@@ -64,7 +72,7 @@ enum Axis {
     Nest(Box<Axis>, Gt, Box<Axis>),
     Stack(Box<Axis>, Plus, Box<Axis>),
     Parens(InParens<Box<Axis>>),
-    Annotate(InSquares<Punctuated<Annotation>>),
+    Summary(InSquares<Punctuated<Summary>>),
 }
 
 #[derive(Debug, pspp_derive::FromTokens)]
@@ -74,7 +82,7 @@ enum Measurement {
 }
 
 #[derive(Debug, pspp_derive::FromTokens)]
-struct Annotation {
+struct Summary {
     function: Identifier,
     percentile: Option<Number>,
     label: Option<String>,
@@ -112,7 +120,7 @@ enum Unit {
 }
 
 #[derive(Debug, pspp_derive::FromTokens)]
-enum VLabels {
+enum VLabel {
     Variables(Equals, VarList),
     Display(Display),
 }
@@ -132,15 +140,73 @@ enum SMissing {
     Listwise,
 }
 
-#[derive(Debug, pspp_derive::FromTokens)]
+#[derive(pspp_derive::FromTokens)]
 struct Expression(MulExpression, Seq0<(Either<Plus, Dash>, Expression)>);
 
-#[derive(Debug, pspp_derive::FromTokens)]
-struct MulExpression(PowExpression, Seq0<(Either<Asterisk, Slash>, PowExpression)>);
+impl Debug for Expression {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        if self.1 .0.is_empty() {
+            self.0.fmt(f)
+        } else {
+            write!(f, "(")?;
+            self.0.fmt(f)?;
+            for (operator, operand) in &self.1 .0 {
+                if operator.is_left() {
+                    write!(f, " + ")?;
+                } else {
+                    write!(f, " - ")?;
+                }
+                operand.fmt(f)?;
+            }
+            write!(f, ")")
+        }
+    }
+}
 
-#[derive(Debug, pspp_derive::FromTokens)]
+#[derive(pspp_derive::FromTokens)]
+struct MulExpression(
+    PowExpression,
+    Seq0<(Either<Asterisk, Slash>, PowExpression)>,
+);
+
+impl Debug for MulExpression {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        if self.1 .0.is_empty() {
+            self.0.fmt(f)
+        } else {
+            write!(f, "(")?;
+            self.0.fmt(f)?;
+            for (operator, operand) in &self.1 .0 {
+                if operator.is_left() {
+                    write!(f, " * ")?;
+                } else {
+                    write!(f, " / ")?;
+                }
+                operand.fmt(f)?;
+            }
+            write!(f, ")")
+        }
+    }
+}
+
+#[derive(pspp_derive::FromTokens)]
 struct PowExpression(Terminal, Seq0<(Exp, PowExpression)>);
 
+impl Debug for PowExpression {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        if self.1 .0.is_empty() {
+            self.0.fmt(f)
+        } else {
+            write!(f, "(")?;
+            self.0.fmt(f)?;
+            for (_operator, operand) in &self.1 .0 {
+                write!(f, " ** {operand:?}")?;
+            }
+            write!(f, ")")
+        }
+    }
+}
+
 #[derive(Debug, pspp_derive::FromTokens)]
 #[pspp(no_selector)]
 enum Terminal {
@@ -168,52 +234,108 @@ enum Value {
     String(String),
 }
 
+#[derive(Debug, pspp_derive::FromTokens)]
+enum PProperties {
+    Label(Equals, String),
+    Format(Equals, Seq1<Summary>),
+    HideSourceCats(Equals, Boolean),
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Boolean {
+    Yes,
+    No,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum SLabel {
+    Position(Equals, Position),
+    Visible(Equals, Boolean),
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Position {
+    Column,
+    Row,
+    Layer,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum CLabel {
+    Auto,
+    RowLabels(Equals, LabelDestination),
+    ColLabels(Equals, LabelDestination),
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum LabelDestination {
+    Opposite,
+    Layer,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Category {
+    Variables(Equals, VarList),
+    Order(Equals, Direction),
+    Key(Equals, Key),
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Direction {
+    #[pspp(syntax = "A")]
+    Ascending,
+    #[pspp(syntax = "D")]
+    Descending,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Key {
+    Value,
+    Label,
+    
+}
+
 mod keyword {
     use crate::command::{FromTokens, ParseResult, TokenSlice};
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "default")]
     pub struct Default;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "expr")]
     pub struct Expr;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "zero")]
     pub struct Zero;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "blank")]
     pub struct Blank;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "thru")]
     pub struct Thru;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "hi")]
     pub struct Hi;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "lo")]
     pub struct Lo;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "missing")]
     pub struct Missing;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "othernm")]
     pub struct OtherNm;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "subtotal")]
     pub struct Subtotal;
 
     #[derive(Debug, pspp_derive::FromTokens)]
-    #[pspp(syntax = "total")]
     pub struct Total;
+
+    #[derive(Debug, pspp_derive::FromTokens)]
+    pub struct Variable;
+
+    #[derive(Debug, pspp_derive::FromTokens)]
+    pub struct Count;
 }
 
 #[cfg(test)]
@@ -237,7 +359,7 @@ mod tests {
     #[test]
     fn basics() {
         test(
-            "ctables /pcompute &all_drivers =expr([1 thru 2])
+            "ctables /pcompute &all_drivers =expr(1+2*3+4)
  /pcompute &all_drivers =expr(1).",
         );
     }
index a4f84bea9d1a48fe810f82955eef9da5a93d6058..b0480be4cb84ad950702509757df801b7f2756bc 100644 (file)
@@ -254,7 +254,6 @@ pub struct Asterisk;
 pub struct Exp;
 
 #[derive(Debug, pspp_derive::FromTokens)]
-#[pspp(syntax = "BY")]
 struct By;
 
 pub struct Punctuated<T, P = Option<Comma>> {
@@ -648,9 +647,14 @@ fn parse_syntax(input: &TokenSlice, syntax: &str) -> ParseResult<()> {
 
 pub type VarList = Punctuated<VarRange>;
 
-#[derive(Debug)]
 pub struct Number(f64);
 
+impl Debug for Number {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self.0)
+    }
+}
+
 impl FromTokens for Number {
     fn from_tokens(input: &TokenSlice) -> ParseResult<Self>
     where