summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs22
-rw-r--r--src/path.lalrpop38
-rw-r--r--src/path.rs27
-rw-r--r--src/path/parser.lalrpop82
4 files changed, 113 insertions, 56 deletions
diff --git a/src/main.rs b/src/main.rs
index d499ad9..2a5234f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,3 @@
-pub mod error;
-
 use error::Error;
 use std::io;
 use std::io::prelude::*;
@@ -7,29 +5,17 @@ use std::io::prelude::*;
 #[macro_use] extern crate lalrpop_util;
 
 lalrpop_mod!(pub commandline);
-lalrpop_mod!(pub path);
+pub mod error;
+pub mod path;
 
 
 pub type Result<T> = std::result::Result<T, Error>;
 
-
 pub enum Input {
     String(String),
     End,
 }
 
-pub struct GenericPath {
-    absolute: bool,
-    directory: bool,
-    components: Vec<GenericPathComponent>,
-}
-
-pub enum GenericPathComponent {
-    CurrentDirectory,
-    ParentDirectory,
-    Entry(String),
-}
-
 
 fn main() -> Result<()> {
     std::process::exit(match repl() {
@@ -87,12 +73,12 @@ fn execute(input: &str) -> Result<()> {
     match invocation.as_slice() {
       ["paths", path_list, ..] => {
         println!("{:?}", path_list);
-        match path::PathListParser::new().parse(path_list) {
+        match path::parser::PathListParser::new().parse(path_list) {
           Ok(parsed_paths) => {
             println!("paths '{:?}'", parsed_paths);
           },
           Err(_) => {
-            match path::PathListAllowingEmptyPathsParser::new()
+            match path::parser::PathListAllowingEmptyPathsParser::new()
               .parse(path_list)
             {
               Ok(parsed) => {
diff --git a/src/path.lalrpop b/src/path.lalrpop
deleted file mode 100644
index 099b217..0000000
--- a/src/path.lalrpop
+++ /dev/null
@@ -1,38 +0,0 @@
-grammar;
-
-pub PathList: Vec<&'input str> = {
-  => {
-    Vec::new()
-  },
-  <mut left:(<Path> COLON)*> <right:Path> => {
-    left.push(right);
-    left
-  },
-};
-
-pub PathListAllowingEmptyPaths: Vec<&'input str> = {
-  => vec![""],
-  Path => vec![<>],
-  <mut left:PathListAllowingEmptyPaths> COLON => {
-    left.push("");
-    left
-  },
-  <mut left:PathListAllowingEmptyPaths> COLON <right:Path> => {
-    left.push(right);
-    left
-  },
-}
-
-pub Path: &'input str = {
-  <PATH_COMPONENT>,
-}
-
-// Whitespace is not allowed.
-match {
-  r"[^z:/]+" => PATH_COMPONENT,
-
-  r"/" => SLASH,
-
-  ":" => COLON,
-}
-
diff --git a/src/path.rs b/src/path.rs
new file mode 100644
index 0000000..bfb5719
--- /dev/null
+++ b/src/path.rs
@@ -0,0 +1,27 @@
+lalrpop_mod!(pub parser, "/path/parser.rs");
+
+
+#[derive(Debug)]
+pub struct DirectoryName(String);
+
+#[derive(Debug)]
+pub struct FileName(String);
+
+#[derive(Debug)]
+pub struct AbsoluteDirectoryPath {
+  components: Vec<DirectoryName>,
+}
+
+#[derive(Debug)]
+pub enum GenericPathComponent {
+  FileOrDirectoryName(String),
+  CurrentDirectory,
+  ParentDirectory,
+}
+
+#[derive(Debug)]
+pub struct GenericPath {
+  components: Vec<GenericPathComponent>,
+  starts_with_slash: bool,
+  ends_with_slash: bool,
+}
diff --git a/src/path/parser.lalrpop b/src/path/parser.lalrpop
new file mode 100644
index 0000000..0b3be9a
--- /dev/null
+++ b/src/path/parser.lalrpop
@@ -0,0 +1,82 @@
+grammar;
+
+use crate::path::GenericPath;
+use crate::path::GenericPathComponent;
+
+pub PathList: Vec<GenericPath> = {
+  => {
+    Vec::new()
+  },
+  <mut left:(<PathNoColons> COLON)*> <right:PathNoColons> => {
+    left.push(right);
+    left
+  },
+};
+
+pub PathListAllowingEmptyPaths: Vec<GenericPath> = {
+  => vec![GenericPath {
+    components: Vec::new(),
+    starts_with_slash: false,
+    ends_with_slash: false,
+  }],
+  PathNoColons => vec![<>],
+  <mut left:PathListAllowingEmptyPaths> COLON => {
+    left.push(GenericPath {
+      components: Vec::new(),
+      starts_with_slash: false,
+      ends_with_slash: false,
+    });
+    left
+  },
+  <mut left:PathListAllowingEmptyPaths> COLON <right:PathNoColons> => {
+    left.push(right);
+    left
+  },
+}
+
+pub PathNoColons: GenericPath = {
+  SLASH => GenericPath {
+    components: Vec::new(),
+    starts_with_slash: true,
+    ends_with_slash: true,
+  },
+  <PathNoColons2> => GenericPath {
+    components: <>,
+    starts_with_slash: false,
+    ends_with_slash: false,
+  },
+  <PathNoColons2> SLASH => GenericPath {
+    components: <>,
+    starts_with_slash: false,
+    ends_with_slash: true,
+  },
+  SLASH <PathNoColons2> => GenericPath {
+    components: <>,
+    starts_with_slash: true,
+    ends_with_slash: false,
+  },
+  SLASH <PathNoColons2> SLASH => GenericPath {
+    components: <>,
+    starts_with_slash: true,
+    ends_with_slash: true,
+  },
+}
+
+PathNoColons2: Vec<GenericPathComponent> = {
+  <PATH_COMPONENT_NO_COLONS> =>
+      vec![GenericPathComponent::FileOrDirectoryName(<>.to_string())],
+  <mut left:PathNoColons2> SLASH <right:PATH_COMPONENT_NO_COLONS> => {
+    left.push(GenericPathComponent::FileOrDirectoryName(right.to_string()));
+    left
+  }
+}
+
+// Whitespace is not allowed.
+match {
+  r"[^z:/]+" => PATH_COMPONENT_NO_COLONS,
+
+  r"/" => SLASH,
+
+  ":" => COLON,
+}
+