diff --git a/Cargo.lock b/Cargo.lock index 7180d30..b468ae7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,8 +111,14 @@ name = "cuentitos" version = "0.3.0" dependencies = [ "clap", + "cuentitos-common", + "cuentitos-parser", ] +[[package]] +name = "cuentitos-common" +version = "0.3.0" + [[package]] name = "cuentitos-compat" version = "0.3.0" @@ -122,6 +128,13 @@ dependencies = [ "glob", ] +[[package]] +name = "cuentitos-parser" +version = "0.3.0" +dependencies = [ + "cuentitos-common", +] + [[package]] name = "glob" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index c9acfb7..63dad86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,8 @@ resolver = "2" members = [ "cli", + "common", "compat", + "parser", ] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index f7f2284..b0a7f96 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -7,3 +7,5 @@ edition = "2021" [dependencies] clap = { version = "4.5.23", features = ["derive"] } +cuentitos-common = { path = "../common" } +cuentitos-parser = { path = "../parser" } diff --git a/cli/src/main.rs b/cli/src/main.rs index 8c04aec..67daa8f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,3 +1,4 @@ +use std::fs::File; use std::path::PathBuf; use clap::{Parser, Subcommand}; /// Simple program to greet a person @@ -24,9 +25,17 @@ fn main() { let cli = Args::parse(); match cli.command { - Commands::Run { script_path: _, input_string: _ } => { - println!("This is a single line"); - println!("END"); + Commands::Run { script_path, input_string } => { + + // Read the script file + let script = std::fs::read_to_string(script_path).unwrap(); + + // Parse it + let database = cuentitos_parser::parse(&script).unwrap(); + println!("{:?}", database); + + // println!("This is a single line"); + // println!("END"); // println!("Running script: {:?}", script_path); // if let Some(input) = input_string { // println!("Input string: {}", input); diff --git a/common/Cargo.toml b/common/Cargo.toml new file mode 100644 index 0000000..96b263c --- /dev/null +++ b/common/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "cuentitos-common" +version = "0.3.0" +edition = "2021" + +[dependencies] diff --git a/common/src/lib.rs b/common/src/lib.rs new file mode 100644 index 0000000..6499353 --- /dev/null +++ b/common/src/lib.rs @@ -0,0 +1,12 @@ +pub type StringId = usize; + +#[derive(Debug, Clone)] +pub enum Block { + String(StringId) +} + +#[derive(Debug, Default, Clone)] +pub struct Database { + pub blocks: Vec, + pub strings: Vec +} diff --git a/docs/architecture/000004-parser.md b/docs/architecture/000004-parser.md new file mode 100644 index 0000000..792b26e --- /dev/null +++ b/docs/architecture/000004-parser.md @@ -0,0 +1,37 @@ +# Parser + +### Submitters + +- Fran Tufro + +## Change Log + +- 2025-01-20 - [First Draft of ADR created](https://github.com/hiddenpeopleclub/cuentitos/pull/52). + +## Context + +Cuentitos needs a fast and efficient parser to define the language grammar and +generate the necessary structures to be executed at runtime. + +In version 0.2 we used PEST, a parser generator for Rust that allowed us to +define the language grammar and generate a parser that was responsible for +transforming the source code into a data structure that we could easily translate +into Rust code. + +The main problem with PEST is that it was not easy to modify and extend the +language grammar, and it was not easy to maintain. + +Thinking about the possibility of extending the language in the future through +plugins, it is necessary that the parser be easy to extend and maintain. + +## Proposed Design + +I will start by implementing a very simple parser: it will go line by line +through the script, and asking a list of possible classes if they can parse the +line. If a class can parse the line, the class is responsible for parsing it and +returning an object that represents the line. + +## Decision + +## Other Related ADRs + diff --git a/parser/Cargo.toml b/parser/Cargo.toml new file mode 100644 index 0000000..bcbc5b4 --- /dev/null +++ b/parser/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cuentitos-parser" +version = "0.3.0" +edition = "2021" + +[dependencies] +cuentitos-common = { path = "../common" } diff --git a/parser/src/lib.rs b/parser/src/lib.rs new file mode 100644 index 0000000..ad33a71 --- /dev/null +++ b/parser/src/lib.rs @@ -0,0 +1,12 @@ +use cuentitos_common::*; + +mod parser; +use parser::*; + +mod line_parser; + + +pub fn parse(script: &str) -> Result { + let mut parser = Parser::default(); + parser.parse(script) +} diff --git a/parser/src/line_parser/mod.rs b/parser/src/line_parser/mod.rs new file mode 100644 index 0000000..5a49818 --- /dev/null +++ b/parser/src/line_parser/mod.rs @@ -0,0 +1,23 @@ +use cuentitos_common::Block; +use crate::ParseError; + +pub struct Line<'a> { + pub parsed: bool, + pub text: &'a str, +} + + +#[derive(Debug)] +pub struct LineParserResult { + pub block: Block, + pub string: String, +} + +pub fn parse(line: Line) -> Result { + Ok( + LineParserResult { + block: Block::String(1), + string: String::from(line.text), + } + ) +} diff --git a/parser/src/parser.rs b/parser/src/parser.rs new file mode 100644 index 0000000..f43ef7f --- /dev/null +++ b/parser/src/parser.rs @@ -0,0 +1,40 @@ +use crate::line_parser; +use cuentitos_common::*; + +#[derive(Debug, Default)] +pub struct Parser; + +#[derive(Debug)] +#[derive(Clone)] +pub enum ParseError { + UnexpectedToken, + UnexpectedEndOfFile, +} + + + +impl Parser { + pub fn parse(&mut self, script: A) -> Result + where A: AsRef + { + let mut database = Database::default(); + + let script = script.as_ref(); + + // iterate through each line + for line in script.lines() { + let line = line_parser::Line { parsed: false, text: line }; + let result = line_parser::parse(line); + + match result { + Ok(result) => { + database.blocks.push(Block::String(database.strings.len())); + database.strings.push(result.string); + }, + Err(_) => panic!("Error parsing line"), + } + } + + Ok(database) + } +}