]> git.huck.website - metaforge.git/commitdiff
parser core
authorHuck Boles <huck@huck.website>
Wed, 3 May 2023 19:13:51 +0000 (14:13 -0500)
committerHuck Boles <huck@huck.website>
Wed, 3 May 2023 19:13:51 +0000 (14:13 -0500)
src/lib.rs
src/main.rs
src/metafile.rs [new file with mode: 0644]
src/parser.rs
src/parser/meta.pest
src/parser/parse.rs [new file with mode: 0644]

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7b33542656ef7ffde6587a46d7e3123b3989e1d9 100644 (file)
@@ -0,0 +1,12 @@
+extern crate pest;
+#[macro_use]
+extern crate pest_derive;
+
+mod metafile;
+mod parser;
+
+pub use metafile::*;
+pub use parser::*;
+
+#[cfg(test)]
+mod tests;
index e7a11a969c037e00a796aafeff6258501ec15e9a..b648bd2ab30b98cbda2b1553148d34f4a4fc9859 100644 (file)
@@ -1,3 +1,7 @@
+extern crate pest;
+#[macro_use]
+extern crate pest_derive;
+
 fn main() {
     println!("Hello, world!");
 }
diff --git a/src/metafile.rs b/src/metafile.rs
new file mode 100644 (file)
index 0000000..f1f3114
--- /dev/null
@@ -0,0 +1,30 @@
+use std::collections::HashMap;
+
+pub struct MetaFile<'a> {
+    pub variables: HashMap<&'a str, &'a str>,
+    pub arrays: HashMap<&'a str, Vec<&'a str>>,
+    pub patterns: HashMap<&'a str, &'a str>,
+    pub source: Vec<Source<'a>>,
+}
+
+impl<'a> MetaFile<'a> {
+    pub fn new() -> MetaFile<'a> {
+        MetaFile {
+            variables: HashMap::new(),
+            arrays: HashMap::new(),
+            patterns: HashMap::new(),
+            source: Vec::new(),
+        }
+    }
+}
+
+pub enum Source<'a> {
+    Str(&'a str),
+    Sub(Substitution<'a>),
+}
+
+pub enum Substitution<'a> {
+    Variable(&'a str),
+    Array(&'a str),
+    Pattern(&'a str),
+}
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4f42021da88b5c57252063d15821881acc0d1f28 100644 (file)
@@ -0,0 +1,3 @@
+mod parse;
+
+pub use parse::*;
index f673b187b250d46161807a3beed5e8e093f55eb5..59ae7115eeaaa7806bec41ade9e80720ea103df7 100644 (file)
@@ -22,7 +22,7 @@ key_chars = @{ (ASCII_ALPHANUMERIC | "_" | ".")* }
 key = @{ key_chars }
 
 value = ${ string | array | "BLANK" | "DEFAULT" }
-assign = _{ key ~ "=" ~ value }
+assign = { key ~ "=" ~ value }
 
 def_block = _{ sigil ~ assign* ~ "}" }
 var_def = { &("$") ~ def_block }
diff --git a/src/parser/parse.rs b/src/parser/parse.rs
new file mode 100644 (file)
index 0000000..f87e9df
--- /dev/null
@@ -0,0 +1,115 @@
+use crate::{MetaFile, Source, Substitution};
+use color_eyre::Result;
+use pest::{
+    iterators::{Pair, Pairs},
+    Parser,
+};
+use std::collections::HashMap;
+
+#[derive(Parser)]
+#[grammar = "parser/meta.pest"]
+pub struct MetaParser;
+
+pub fn parse_file(file: &str) -> Result<MetaFile> {
+    let meta_source = MetaParser::parse(Rule::file, file)?.next().unwrap();
+
+    Ok(parse_pair(meta_source))
+}
+
+pub fn parse_pair(pair: Pair<Rule>) -> MetaFile {
+    let mut meta_file = MetaFile::new();
+
+    if Rule::file == pair.as_rule() {
+        match pair.as_rule() {
+            Rule::source => meta_file.source = parse_source(pair.into_inner()),
+            Rule::var_def => meta_file.variables = parse_defs(pair.into_inner()),
+            Rule::arr_def => meta_file.arrays = parse_array_defs(pair.into_inner()),
+            Rule::pat_def => meta_file.patterns = parse_defs(pair.into_inner()),
+            // anything else is either hidden or children of previous nodes and will be dealt with
+            // in respective parse functions
+            _ => unreachable!(),
+        }
+    }
+
+    meta_file
+}
+
+fn parse_defs<'a>(pairs: Pairs<'a, Rule>) -> HashMap<&'a str, &'a str> {
+    let mut map = HashMap::new();
+    for pair in pairs {
+        if Rule::assign == pair.as_rule() {
+            let (key, val) = parse_assign(pair);
+            map.insert(key, val);
+        }
+    }
+    map
+}
+
+fn parse_array_defs<'a>(pairs: Pairs<'a, Rule>) -> HashMap<&'a str, Vec<&'a str>> {
+    let mut map = HashMap::new();
+    for pair in pairs {
+        if Rule::assign == pair.as_rule() {
+            let (key, val) = parse_assign_array(pair);
+            map.insert(key, val);
+        }
+    }
+    map
+}
+
+fn parse_source<'a>(pairs: Pairs<Rule>) -> Vec<Source> {
+    let mut vec: Vec<Source> = Vec::new();
+
+    for pair in pairs {
+        match pair.as_rule() {
+            Rule::var_sub => vec.push(Source::Sub(Substitution::Variable(pair.as_str()))),
+            Rule::arr_sub => vec.push(Source::Sub(Substitution::Array(pair.as_str()))),
+            Rule::pat_sub => vec.push(Source::Sub(Substitution::Pattern(pair.as_str()))),
+            Rule::char_seq => vec.push(Source::Str(pair.as_str())),
+            // anything that isn't a substitution is a char_seq inside source
+            _ => unreachable!(),
+        }
+    }
+
+    vec
+}
+
+fn parse_assign<'a>(pair: Pair<'a, Rule>) -> (&'a str, &'a str) {
+    let mut key = "";
+    let mut val = "";
+    for pair in pair.into_inner() {
+        if Rule::key == pair.as_rule() {
+            key = pair.as_str();
+        }
+        if Rule::value == pair.as_rule() {
+            val = pair.as_str();
+        }
+    }
+
+    (key, val)
+}
+
+fn parse_assign_array<'a>(pair: Pair<'a, Rule>) -> (&'a str, Vec<&'a str>) {
+    let mut key = "";
+    let mut val: Vec<&str> = Vec::default();
+    for pair in pair.into_inner() {
+        if Rule::key == pair.as_rule() {
+            key = pair.as_str();
+        }
+        if Rule::value == pair.as_rule() {
+            val = parse_array(pair.into_inner());
+        }
+    }
+
+    (key, val)
+}
+
+fn parse_array<'a>(pairs: Pairs<'a, Rule>) -> Vec<&'a str> {
+    let mut vec: Vec<&str> = Vec::default();
+
+    for pair in pairs {
+        if Rule::string == pair.as_rule() {
+            vec.push(pair.as_str());
+        }
+    }
+    vec
+}