From d568653a17bbf60e4867d33590b8ddb4b2bc7c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kha=C3=AFs=20COLIN?= Date: Sun, 4 May 2025 14:09:33 +0200 Subject: [PATCH] feat(parser): parse tokens into commands --- notes.org | 8 ++ src/lib.rs | 1 + src/parser.rs | 83 +++++++++++++++++++ .../osdb__parser__tests__parse_exit.snap | 11 +++ ...parser__tests__parse_multiple_correct.snap | 23 +++++ ...rser__tests__parse_multiple_incorrect.snap | 68 +++++++++++++++ ...__parser__tests__parse_multiple_mixed.snap | 32 +++++++ ...parser__tests__parse_single_correct-2.snap | 11 +++ ...parser__tests__parse_single_correct-3.snap | 11 +++ ...parser__tests__parse_single_correct-4.snap | 11 +++ ...parser__tests__parse_single_correct-5.snap | 11 +++ ...__parser__tests__parse_single_correct.snap | 11 +++ ...rser__tests__parse_single_incorrect-2.snap | 20 +++++ ...rser__tests__parse_single_incorrect-3.snap | 20 +++++ ...rser__tests__parse_single_incorrect-4.snap | 20 +++++ ...rser__tests__parse_single_incorrect-5.snap | 20 +++++ ...parser__tests__parse_single_incorrect.snap | 20 +++++ 17 files changed, 381 insertions(+) create mode 100644 src/parser.rs create mode 100644 src/snapshots/osdb__parser__tests__parse_exit.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_multiple_correct.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_multiple_incorrect.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_multiple_mixed.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_correct-2.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_correct-3.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_correct-4.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_correct-5.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_correct.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_incorrect-2.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_incorrect-3.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_incorrect-4.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_incorrect-5.snap create mode 100644 src/snapshots/osdb__parser__tests__parse_single_incorrect.snap diff --git a/notes.org b/notes.org index e059314..a6233fd 100644 --- a/notes.org +++ b/notes.org @@ -179,6 +179,14 @@ CLOCK: [2025-05-04 dim. 13:45]--[2025-05-04 dim. 13:56] => 0:11 :EFFORT: 10 :END: +*** DONE create a generic parse command that parses string into tokens into Command +:PROPERTIES: +:EFFORT: 10 +:END: +:LOGBOOK: +CLOCK: [2025-05-04 dim. 14:01]--[2025-05-04 dim. 14:14] => 0:13 +:END: + *** TODO parse tokens into meta-commands :PROPERTIES: :EFFORT: 10 diff --git a/src/lib.rs b/src/lib.rs index 5117e84..6683a24 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,5 +3,6 @@ pub mod cli; pub mod command; pub mod error_display; pub mod meta_commands; +pub mod parser; pub mod statements; pub mod tokens; diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..949a1bc --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,83 @@ +use std::collections::VecDeque; + +use crate::{ + command::{Command, CommandParseError}, + statements::Statement, + tokens::tokenize, +}; + +pub fn parse(file: String, input: String) -> Result, Vec> { + let mut tokens: VecDeque<_> = tokenize(input, file) + .map_err(|x| x.into_iter().map(|x| x.into()).collect::>())? + .into(); + let mut cmds = Vec::new(); + let errs = Vec::new(); + while let Some(token) = tokens.pop_front() { + match token.data { + crate::tokens::TokenData::Insert => cmds.push(Command::Statement(Statement::Insert)), + crate::tokens::TokenData::Select => cmds.push(Command::Statement(Statement::Select)), + crate::tokens::TokenData::MetaCommand(meta_command) => { + cmds.push(Command::MetaCommand(meta_command)) + } + crate::tokens::TokenData::EndOfFile => (), + } + } + if errs.is_empty() { + Ok(cmds) + } else { + Err(errs) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use insta::assert_debug_snapshot; + + #[test] + fn test_parse_single_correct() { + let file = String::from(""); + assert_debug_snapshot!(parse(file.clone(), String::from(".exit"))); + assert_debug_snapshot!(parse(file.clone(), String::from("select"))); + assert_debug_snapshot!(parse(file.clone(), String::from("sElEcT"))); + assert_debug_snapshot!(parse(file.clone(), String::from("INSERT"))); + assert_debug_snapshot!(parse(file.clone(), String::from("InSErT"))); + } + + #[test] + fn test_parse_single_incorrect() { + let file = String::from(""); + assert_debug_snapshot!(parse(file.clone(), String::from(".halp"))); + assert_debug_snapshot!(parse(file.clone(), String::from("salect"))); + assert_debug_snapshot!(parse(file.clone(), String::from("sAlEcT"))); + assert_debug_snapshot!(parse(file.clone(), String::from("INSART"))); + assert_debug_snapshot!(parse(file.clone(), String::from("InSArT"))); + } + + #[test] + fn test_parse_multiple_correct() { + let file = String::from(""); + assert_debug_snapshot!(parse( + file.clone(), + String::from(".exit select select insert select") + )); + } + + #[test] + fn test_parse_multiple_incorrect() { + let file = String::from(""); + assert_debug_snapshot!(parse( + file.clone(), + String::from(".halp salect selact inset seiect") + )); + } + + #[test] + fn test_parse_multiple_mixed() { + let file = String::from(""); + assert_debug_snapshot!(parse( + file.clone(), + String::from(".exit selct select nsert select") + )); + } +} diff --git a/src/snapshots/osdb__parser__tests__parse_exit.snap b/src/snapshots/osdb__parser__tests__parse_exit.snap new file mode 100644 index 0000000..4ca1f6e --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_exit.snap @@ -0,0 +1,11 @@ +--- +source: src/parser.rs +expression: "parse(file, String::from(\".exit\"))" +--- +Ok( + [ + MetaCommand( + Exit, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_multiple_correct.snap b/src/snapshots/osdb__parser__tests__parse_multiple_correct.snap new file mode 100644 index 0000000..a90d0ae --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_multiple_correct.snap @@ -0,0 +1,23 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\".exit select select insert select\"))" +--- +Ok( + [ + MetaCommand( + Exit, + ), + Statement( + Select, + ), + Statement( + Select, + ), + Statement( + Insert, + ), + Statement( + Select, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_multiple_incorrect.snap b/src/snapshots/osdb__parser__tests__parse_multiple_incorrect.snap new file mode 100644 index 0000000..2e4ba21 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_multiple_incorrect.snap @@ -0,0 +1,68 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\".halp salect selact inset seiect\"))" +--- +Err( + [ + Scan( + ScanError { + location: Location { + file: "", + offset: 0, + length: 5, + }, + kind: UnknownMetaCommand( + ".halp", + ), + }, + ), + Scan( + ScanError { + location: Location { + file: "", + offset: 6, + length: 6, + }, + kind: UnknownKeyword( + "salect", + ), + }, + ), + Scan( + ScanError { + location: Location { + file: "", + offset: 13, + length: 6, + }, + kind: UnknownKeyword( + "selact", + ), + }, + ), + Scan( + ScanError { + location: Location { + file: "", + offset: 20, + length: 5, + }, + kind: UnknownKeyword( + "inset", + ), + }, + ), + Scan( + ScanError { + location: Location { + file: "", + offset: 26, + length: 6, + }, + kind: UnknownKeyword( + "seiect", + ), + }, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_multiple_mixed.snap b/src/snapshots/osdb__parser__tests__parse_multiple_mixed.snap new file mode 100644 index 0000000..9580a02 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_multiple_mixed.snap @@ -0,0 +1,32 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\".exit selct select nsert select\"))" +--- +Err( + [ + Scan( + ScanError { + location: Location { + file: "", + offset: 6, + length: 5, + }, + kind: UnknownKeyword( + "selct", + ), + }, + ), + Scan( + ScanError { + location: Location { + file: "", + offset: 19, + length: 5, + }, + kind: UnknownKeyword( + "nsert", + ), + }, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_correct-2.snap b/src/snapshots/osdb__parser__tests__parse_single_correct-2.snap new file mode 100644 index 0000000..94cc7e1 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_correct-2.snap @@ -0,0 +1,11 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\"select\"))" +--- +Ok( + [ + Statement( + Select, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_correct-3.snap b/src/snapshots/osdb__parser__tests__parse_single_correct-3.snap new file mode 100644 index 0000000..26db6c7 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_correct-3.snap @@ -0,0 +1,11 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\"sElEcT\"))" +--- +Ok( + [ + Statement( + Select, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_correct-4.snap b/src/snapshots/osdb__parser__tests__parse_single_correct-4.snap new file mode 100644 index 0000000..d3ba596 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_correct-4.snap @@ -0,0 +1,11 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\"INSERT\"))" +--- +Ok( + [ + Statement( + Insert, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_correct-5.snap b/src/snapshots/osdb__parser__tests__parse_single_correct-5.snap new file mode 100644 index 0000000..7bc8e93 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_correct-5.snap @@ -0,0 +1,11 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\"InSErT\"))" +--- +Ok( + [ + Statement( + Insert, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_correct.snap b/src/snapshots/osdb__parser__tests__parse_single_correct.snap new file mode 100644 index 0000000..fda989a --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_correct.snap @@ -0,0 +1,11 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\".exit\"))" +--- +Ok( + [ + MetaCommand( + Exit, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_incorrect-2.snap b/src/snapshots/osdb__parser__tests__parse_single_incorrect-2.snap new file mode 100644 index 0000000..4e8a5f1 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_incorrect-2.snap @@ -0,0 +1,20 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\"salect\"))" +--- +Err( + [ + Scan( + ScanError { + location: Location { + file: "", + offset: 0, + length: 6, + }, + kind: UnknownKeyword( + "salect", + ), + }, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_incorrect-3.snap b/src/snapshots/osdb__parser__tests__parse_single_incorrect-3.snap new file mode 100644 index 0000000..6aae7a1 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_incorrect-3.snap @@ -0,0 +1,20 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\"sAlEcT\"))" +--- +Err( + [ + Scan( + ScanError { + location: Location { + file: "", + offset: 0, + length: 6, + }, + kind: UnknownKeyword( + "sAlEcT", + ), + }, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_incorrect-4.snap b/src/snapshots/osdb__parser__tests__parse_single_incorrect-4.snap new file mode 100644 index 0000000..1087e1a --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_incorrect-4.snap @@ -0,0 +1,20 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\"INSART\"))" +--- +Err( + [ + Scan( + ScanError { + location: Location { + file: "", + offset: 0, + length: 6, + }, + kind: UnknownKeyword( + "INSART", + ), + }, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_incorrect-5.snap b/src/snapshots/osdb__parser__tests__parse_single_incorrect-5.snap new file mode 100644 index 0000000..978fd2e --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_incorrect-5.snap @@ -0,0 +1,20 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\"InSArT\"))" +--- +Err( + [ + Scan( + ScanError { + location: Location { + file: "", + offset: 0, + length: 6, + }, + kind: UnknownKeyword( + "InSArT", + ), + }, + ), + ], +) diff --git a/src/snapshots/osdb__parser__tests__parse_single_incorrect.snap b/src/snapshots/osdb__parser__tests__parse_single_incorrect.snap new file mode 100644 index 0000000..9f0ada8 --- /dev/null +++ b/src/snapshots/osdb__parser__tests__parse_single_incorrect.snap @@ -0,0 +1,20 @@ +--- +source: src/parser.rs +expression: "parse(file.clone(), String::from(\".halp\"))" +--- +Err( + [ + Scan( + ScanError { + location: Location { + file: "", + offset: 0, + length: 5, + }, + kind: UnknownMetaCommand( + ".halp", + ), + }, + ), + ], +)