summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorQrius <[email protected]>2024-09-26 00:11:05 +0200
committerQrius <[email protected]>2024-09-26 00:11:05 +0200
commit99205d6a5635dc8cb1a9d7429e6b6d0880518cb9 (patch)
treeb6fb81830c1795cc115a0b13863123604df5bb5d /src
parent3b35f97b07d3a6b439544097fe36628619f95d4f (diff)
downloadskaldpress-99205d6a5635dc8cb1a9d7429e6b6d0880518cb9.tar.gz
skaldpress-99205d6a5635dc8cb1a9d7429e6b6d0880518cb9.zip
Clean up things a bit
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs2
-rw-r--r--src/macro_processor/macro_processor.rs130
-rw-r--r--src/macro_processor/main.rs4
-rw-r--r--src/skaldpress/main.rs18
-rw-r--r--src/skaldpress/mod.rs1
5 files changed, 105 insertions, 50 deletions
diff --git a/src/lib.rs b/src/lib.rs
index d81aca7..7898aa2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,2 +1,2 @@
-pub mod skaldpress;
pub mod macro_processor;
+pub mod skaldpress;
diff --git a/src/macro_processor/macro_processor.rs b/src/macro_processor/macro_processor.rs
index 0d931f9..4a46a62 100644
--- a/src/macro_processor/macro_processor.rs
+++ b/src/macro_processor/macro_processor.rs
@@ -38,15 +38,7 @@ macro_rules! highlight_debug {
};
}
-pub enum MacroType {
- Function(fn(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String),
- String(String)
-}
-
-pub struct MacroProcessor {
- macros: HashMap<String, MacroType>,
-}
-
+/// Builtin for defining a new macro
fn smp_builtin_define(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String {
if args.len() < 1 {
return macro_name.to_string();
@@ -61,6 +53,7 @@ fn smp_builtin_define(smp: &mut MacroProcessor, macro_name: &str, args: &mut [St
String::new()
}
+/// If macro is defined, return second argument, else return third argument if provided
fn smp_builtin_ifdef(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String {
if args.len() < 2 {
return macro_name.to_string();
@@ -76,6 +69,7 @@ fn smp_builtin_ifdef(smp: &mut MacroProcessor, macro_name: &str, args: &mut [Str
String::new()
}
+/// If macro is not defined, return second argument, else return third argument if provided
fn smp_builtin_ifndef(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String {
if args.len() < 2 {
return macro_name.to_string();
@@ -91,6 +85,7 @@ fn smp_builtin_ifndef(smp: &mut MacroProcessor, macro_name: &str, args: &mut [St
String::new()
}
+/// If arguments are equal, return third argument, else return fourth argument if provided
fn smp_builtin_ifeq(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String {
if args.len() < 3 {
return macro_name.to_string();
@@ -106,6 +101,7 @@ fn smp_builtin_ifeq(smp: &mut MacroProcessor, macro_name: &str, args: &mut [Stri
String::new()
}
+/// If arguments are not equal, return third argument, else return fourth argument if provided
fn smp_builtin_ifneq(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String {
if args.len() < 3 {
return macro_name.to_string();
@@ -121,6 +117,7 @@ fn smp_builtin_ifneq(smp: &mut MacroProcessor, macro_name: &str, args: &mut [Str
return String::new();
}
+/// Include a new file, and process it normally. There is no loop protection here!
fn smp_builtin_include(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String {
if args.len() < 1 {
return macro_name.to_string();
@@ -130,18 +127,16 @@ fn smp_builtin_include(smp: &mut MacroProcessor, macro_name: &str, args: &mut [S
return smp.process_input(&input_file);
}
+/// Simply execute argument as shell command
fn smp_builtin_shell(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String {
if args.len() < 1 {
return macro_name.to_string();
}
let arg0 = smp.process_input(&args[0]);
- let res = Command::new("sh")
- .arg("-c")
- .arg(arg0)
- .output();
+ let res = Command::new("sh").arg("-c").arg(arg0).output();
match res {
Ok(output) => String::from_utf8(output.stdout).expect("SMP1"),
- Err(_) => String::new()
+ Err(_) => String::new(),
}
}
@@ -155,16 +150,38 @@ fn smp_builtin_expr(smp: &mut MacroProcessor, macro_name: &str, args: &mut [Stri
*arg = smp.process_input(&arg);
}
- let res = Command::new("expr")
- .args(args)
- .output();
+ let res = Command::new("expr").args(args).output();
match res {
Ok(output) => String::from_utf8(output.stdout).expect("SMP1"),
- Err(_) => String::new()
+ Err(_) => String::new(),
}
}
+/// Types of macros, this is to make it easy to store both functions and strings
+pub enum MacroType {
+ /// When expanded, the associated function will be expanded
+ Function(fn(smp: &mut MacroProcessor, macro_name: &str, args: &mut [String]) -> String),
+ /// Will be expanded in-place to the String
+ String(String),
+}
+
+/// Possible parser states
+#[derive(Debug, PartialEq)]
+enum ParserState {
+ Normal,
+ InMacro,
+ InMacroArgs,
+}
+
+/// Defines a MacroProcessor object, with it's associated state
+/// the state mostly includes the defined macros
+pub struct MacroProcessor {
+ /// All currently defined macros in this MacroProcessor
+ macros: HashMap<String, MacroType>,
+}
+
impl MacroProcessor {
+
pub fn new() -> Self {
let mut smp = Self {
macros: HashMap::new(),
@@ -173,28 +190,64 @@ impl MacroProcessor {
smp
}
+ /// Bootstrapping-function for defining all builtins,
+ /// the same way all other macros might be defined
fn define_builtins(&mut self) {
- self.define_macro_fn(String::from("define"), MacroType::Function(smp_builtin_define));
- self.define_macro_fn(String::from("ifdef"), MacroType::Function(smp_builtin_ifdef));
- self.define_macro_fn(String::from("ifndef"), MacroType::Function(smp_builtin_ifndef));
+ self.define_macro_fn(
+ String::from("define"),
+ MacroType::Function(smp_builtin_define),
+ );
+ self.define_macro_fn(
+ String::from("ifdef"),
+ MacroType::Function(smp_builtin_ifdef),
+ );
+ self.define_macro_fn(
+ String::from("ifndef"),
+ MacroType::Function(smp_builtin_ifndef),
+ );
self.define_macro_fn(String::from("ifeq"), MacroType::Function(smp_builtin_ifeq));
- self.define_macro_fn(String::from("ifneq"), MacroType::Function(smp_builtin_ifneq));
- self.define_macro_fn(String::from("include"), MacroType::Function(smp_builtin_include));
- self.define_macro_fn(String::from("shell"), MacroType::Function(smp_builtin_shell));
+ self.define_macro_fn(
+ String::from("ifneq"),
+ MacroType::Function(smp_builtin_ifneq),
+ );
+ self.define_macro_fn(
+ String::from("include"),
+ MacroType::Function(smp_builtin_include),
+ );
+ self.define_macro_fn(
+ String::from("shell"),
+ MacroType::Function(smp_builtin_shell),
+ );
self.define_macro_fn(String::from("expr"), MacroType::Function(smp_builtin_expr));
- // TODO
// format('Result id %d', 3282)
}
+ /// Define a new macro as a string that will be expanded in-place
+ ///
+ /// # Arguments
+ ///
+ /// * `name` - The name of the new macro
+ /// * `body` - The body of the new macro, this will be expanded when macro is executed
pub fn define_macro(&mut self, name: String, body: String) {
self.macros.insert(name, MacroType::String(body));
}
+ /// Define a new macro as any MacroType
+ ///
+ /// # Arguments
+ ///
+ /// * `name` - The name of the new macro
+ /// * `macro_expansion` - The MacroType struct to use.
pub fn define_macro_fn(&mut self, name: String, macro_expansion: MacroType) {
self.macros.insert(name, macro_expansion);
}
-
+
/// This expands a macro definition, and it executes builtin functions, like define
+ ///
+ /// # Arguments
+ ///
+ /// * `macro_name` - Name of macro to expand if it exists
+ /// * `args` - List of arguments parsed along with macro invokation (empty list if no arguments were parsed)
fn expand_macro(&mut self, macro_name: &str, args: &mut [String]) -> String {
let Some(macro_body) = self.macros.get(macro_name) else {
return format!("{}", macro_name);
@@ -203,18 +256,32 @@ impl MacroProcessor {
match macro_body {
MacroType::String(body) => {
let mut expanded = body.clone();
+ // The expanded macro, should _probably_ be expanded again
+ // The below is a okay _idea_, but I am not sure if I want to have this syntax for
+ // functions defined in normal smp code
for (i, arg) in args.iter().enumerate() {
let placeholder = format!("${}", i + 1);
expanded = expanded.replace(&placeholder, arg);
}
return expanded;
- },
+ }
MacroType::Function(func) => {
return func(self, macro_name, args);
- },
+ }
}
}
+ /// Do macro processing of a input string
+ ///
+ /// This is the main function used for processing a input string,
+ /// will return the processed string.
+ /// Will be called recursively if needed.
+ /// Subsequent calls will keep the state from the previous call.
+ /// This includes macro definitions.
+ ///
+ /// # Arguments
+ ///
+ /// * `input` - The text to process
pub fn process_input(&mut self, input: &str) -> String {
let mut output = String::new();
let mut state = ParserState::Normal;
@@ -296,10 +363,3 @@ impl MacroProcessor {
output
}
}
-
-#[derive(Debug, PartialEq)]
-enum ParserState {
- Normal,
- InMacro,
- InMacroArgs,
-}
diff --git a/src/macro_processor/main.rs b/src/macro_processor/main.rs
index 5575aa6..247fc85 100644
--- a/src/macro_processor/main.rs
+++ b/src/macro_processor/main.rs
@@ -1,11 +1,11 @@
+use skaldpress::macro_processor::MacroProcessor;
use std::env;
use std::fs;
-use skaldpress::macro_processor::MacroProcessor;
fn main() {
let args: Vec<String> = env::args().collect();
let input_file = fs::read_to_string(&args[1]).expect("Failed to read input file");
-
+
let mut macro_processor = MacroProcessor::new();
let final_output = macro_processor.process_input(&input_file);
println!("{}", final_output);
diff --git a/src/skaldpress/main.rs b/src/skaldpress/main.rs
index de6088f..56abf70 100644
--- a/src/skaldpress/main.rs
+++ b/src/skaldpress/main.rs
@@ -92,17 +92,13 @@ fn compile_file(file_path: &Path) -> Result<String, Box<dyn std::error::Error>>
return Ok(file_content);
};
- let template_file = format!(
- "{}{}.html",
- TEMPLATES_DIR,
- template
- );
+ let template_file = format!("{}{}.html", TEMPLATES_DIR, template);
//println!(
// "Processing template {} for content file {:?}",
// template_file, file_path
//);
let template = fs::read_to_string(template_file).expect("Failed to read template");
-
+
let mut macro_processor = MacroProcessor::new();
for (key, value) in map {
macro_processor.define_macro(format!("METADATA_{}", key), value.to_string());
@@ -114,7 +110,9 @@ fn compile_file(file_path: &Path) -> Result<String, Box<dyn std::error::Error>>
}
fn compile_file_and_write(source_file_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
- let dest_file_path = Path::new(BUILD_DIR).join(source_file_path.strip_prefix(CONTENT_DIR).expect("SP14")).with_extension("html");
+ let dest_file_path = Path::new(BUILD_DIR)
+ .join(source_file_path.strip_prefix(CONTENT_DIR).expect("SP14"))
+ .with_extension("html");
std::fs::create_dir_all(&dest_file_path.parent().expect("SP19")).expect("SP10");
@@ -130,16 +128,12 @@ fn compile_files_in_directory(directory: &Path) {
let metadata = fs::metadata(&path).expect("SP6");
if metadata.is_file() {
- println!(
- "Compiling {:#?}",
- path.as_path()
- );
+ println!("Compiling {:#?}", path.as_path());
compile_file_and_write(path.as_path()).expect("SP12");
} else if metadata.is_dir() {
compile_files_in_directory(path.as_path());
}
}
-
}
fn main() {
diff --git a/src/skaldpress/mod.rs b/src/skaldpress/mod.rs
index e69de29..8b13789 100644
--- a/src/skaldpress/mod.rs
+++ b/src/skaldpress/mod.rs
@@ -0,0 +1 @@
+