--- /dev/null
+use flagset::FlagSet;
+
+use super::{Command, Subcommand};
+use crate::command::{
+ parse_token, FromTokens, Identifier, InParens, MismatchToError, ParseError, ParseResult,
+ Parsed, Punct, Token, TokenSlice, Vars,
+};
+
+pub(super) fn descriptives_command() -> Command {
+ Command {
+ allowed_states: FlagSet::full(),
+ enhanced_only: false,
+ testing_only: false,
+ no_abbrev: false,
+ name: "DESCRIPTIVES",
+ run: Box::new(|context| {
+ let mut input = context.lexer;
+ while !input.is_empty() {
+ match <Subcommand<DescriptivesSubcommand>>::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;
+ }
+ }
+ }
+ }),
+ }
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+#[pspp(add_lifetime)]
+struct Descriptives<'a> {
+ subcommands: Vec<Subcommand<DescriptivesSubcommand<'a>>>,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+#[pspp(add_lifetime, required_equals)]
+enum DescriptivesSubcommand<'a> {
+ #[pspp(default)]
+ Variables(Vec<DescriptivesVars<'a>>),
+ Missing(Vec<Missing>),
+ Save,
+ Statistics(Vec<Statistic>),
+ Sort(Sort),
+ Format(Vec<Format>),
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Missing {
+ Variable,
+ Listwise,
+ Include,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Format {
+ Labels,
+ NoLabels,
+ Index,
+ NoIndex,
+ Line,
+ Serial,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+#[pspp(add_lifetime)]
+struct DescriptivesVars<'a> {
+ vars: Vars<'a>,
+ z_name: Option<InParens<&'a Identifier>>,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+struct Sort {
+ key: SortKey,
+ direction: Option<Direction>,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum SortKey {
+ Mean,
+ SMean,
+ Stddev,
+ Variance,
+ Range,
+ Min,
+ Max,
+ Sum,
+ Skewness,
+ Kurtosis,
+ Name,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Direction {
+ #[pspp(syntax = "(A)")]
+ Ascending,
+ #[pspp(syntax = "(D)")]
+ Descending,
+}
+
+#[derive(Debug, pspp_derive::FromTokens)]
+enum Statistic {
+ Default,
+ Mean,
+ SeMean,
+ Stddev,
+ Variance,
+ Range,
+ Sum,
+ Min,
+ Max,
+ Skewness,
+ Kurtosis,
+ All,
+}
+
+#[cfg(test)]
+mod tests {
+ use std::sync::Arc;
+
+ use encoding_rs::UTF_8;
+
+ use crate::{
+ engine::Engine,
+ lex::lexer::{Source, SourceFile},
+ };
+
+ fn test(syntax: &str) {
+ let mut engine = Engine::new();
+ engine.run(Source::new_default(&Arc::new(
+ SourceFile::for_file_contents(syntax.to_string(), Some("test.sps".to_string()), UTF_8),
+ )));
+ }
+
+ #[test]
+ fn basics() {
+ test("descript a to b (c) all/stat=all/format=serial.");
+ }
+
+ #[test]
+ fn include_missing() {
+ test("descript all/stat=all/format=serial/missing=include.");
+ }
+
+ #[test]
+ fn include_missing_listwise() {
+ test("descript all/stat=all/format=serial/missing=listwise.");
+ test("descript all/stat=all/format=serial/missing=listwise include.");
+ }
+
+ #[test]
+ fn mean_only() {
+ test("descript all/stat=mean.");
+ }
+
+ #[test]
+ fn z_scores() {
+ test("DESCRIPTIVES /VAR=a b /SAVE.");
+ }
+
+ #[test]
+ fn syntax_errors() {
+ test(
+ "\
+DESCRIPTIVES MISSING=**.
+DESCRIPTIVES FORMAT=**.
+DESCRIPTIVES STATISTICS=**.
+DESCRIPTIVES SORT=**.
+DESCRIPTIVES SORT=NAME (**).
+DESCRIPTIVES SORT=NAME (A **).
+DESCRIPTIVES **.
+DESCRIPTIVES x/ **.
+DESCRIPTIVES MISSING=INCLUDE.
+",
+ );
+ }
+}
#![allow(dead_code)]
use std::{fmt::Write, ops::RangeFrom, sync::OnceLock};
+use descriptives::descriptives_command;
use flagset::{flags, FlagSet};
use pspp_derive::FromTokens;
message::{Diagnostic, Diagnostics},
};
+pub mod descriptives;
+
flags! {
enum State: u8 {
/// No active dataset yet defined.
}
}
-#[derive(Debug, FromTokens)]
-#[pspp(add_lifetime)]
-struct Descriptives<'a> {
- subcommands: Vec<Subcommand<DescriptivesSubcommand<'a>>>,
-}
-
#[derive(Debug)]
struct Subcommand<T>(pub T);
}
}
-#[derive(Debug, FromTokens)]
-#[pspp(add_lifetime, required_equals)]
-enum DescriptivesSubcommand<'a> {
- #[pspp(default)]
- Variables(Vec<DescriptivesVars<'a>>),
- Missing(Vec<Missing>),
- Save,
- Statistics(Vec<Statistic>),
- Sort(Sort),
- Format(Vec<Format>),
-}
-
-#[derive(Debug, FromTokens)]
-enum Missing {
- Variable,
- Listwise,
- Include,
-}
-
-#[derive(Debug, FromTokens)]
-enum Format {
- Labels,
- NoLabels,
- Index,
- NoIndex,
- Line,
- Serial,
-}
-
-#[derive(Debug, FromTokens)]
-#[pspp(add_lifetime)]
-struct DescriptivesVars<'a> {
- vars: Vars<'a>,
- z_name: Option<InParens<&'a Identifier>>,
-}
-
#[derive(Debug)]
struct InParens<T>(pub T);
}
}
-#[derive(Debug, FromTokens)]
-struct Sort {
- key: SortKey,
- direction: Option<Direction>,
-}
-
-#[derive(Debug, FromTokens)]
-enum SortKey {
- Mean,
- SMean,
- Stddev,
- Variance,
- Range,
- Min,
- Max,
- Sum,
- Skewness,
- Kurtosis,
- Name,
-}
-
-#[derive(Debug, FromTokens)]
-enum Direction {
- #[pspp(syntax = "(A)")]
- Ascending,
- #[pspp(syntax = "(D)")]
- Descending,
-}
-
-#[derive(Debug, FromTokens)]
-enum Statistic {
- Default,
- Mean,
- SeMean,
- Stddev,
- Variance,
- Range,
- Sum,
- Min,
- Max,
- Skewness,
- Kurtosis,
- All,
-}
-
fn collect_subcommands<'a>(src: &'a TokenSlice) -> Vec<TokenSlice<'a>> {
src.split(|token| token.token == Token::Punct(Punct::Slash))
.filter(|slice| !slice.is_empty())
fn commands() -> &'static [Command] {
fn new_commands() -> Vec<Command> {
vec![
- Command {
- allowed_states: FlagSet::full(),
- enhanced_only: false,
- testing_only: false,
- no_abbrev: false,
- name: "DESCRIPTIVES",
- run: Box::new(|context| {
- let mut input = context.lexer;
- while !input.is_empty() {
- match <Subcommand<DescriptivesSubcommand>>::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;
- }
- }
- }
- }),
- },
+ descriptives_command(),
Command {
allowed_states: FlagSet::full(),
enhanced_only: false,
(self.error)(diagnostic);
}
}
-
-#[cfg(test)]
-mod tests {
- mod descriptives {
- use std::sync::Arc;
-
- use encoding_rs::UTF_8;
-
- use crate::{
- engine::Engine,
- lex::lexer::{Source, SourceFile},
- };
-
- fn test(syntax: &str) {
- let mut engine = Engine::new();
- engine.run(Source::new_default(&Arc::new(
- SourceFile::for_file_contents(
- syntax.to_string(),
- Some("test.sps".to_string()),
- UTF_8,
- ),
- )));
- }
-
- #[test]
- fn basics() {
- test("descript a to b (c) all/stat=all/format=serial.");
- }
-
- #[test]
- fn include_missing() {
- test("descript all/stat=all/format=serial/missing=include.");
- }
-
- #[test]
- fn include_missing_listwise() {
- test("descript all/stat=all/format=serial/missing=listwise.");
- test("descript all/stat=all/format=serial/missing=listwise include.");
- }
-
- #[test]
- fn mean_only() {
- test("descript all/stat=mean.");
- }
-
- #[test]
- fn z_scores() {
- test("DESCRIPTIVES /VAR=a b /SAVE.");
- }
-
- #[test]
- fn syntax_errors() {
- test("\
-DESCRIPTIVES MISSING=**.
-DESCRIPTIVES FORMAT=**.
-DESCRIPTIVES STATISTICS=**.
-DESCRIPTIVES SORT=**.
-DESCRIPTIVES SORT=NAME (**).
-DESCRIPTIVES SORT=NAME (A **).
-DESCRIPTIVES **.
-DESCRIPTIVES x/ **.
-DESCRIPTIVES MISSING=INCLUDE.
-");
- }
- }
-}