summary refs log tree commit diff stats
path: root/src/tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tree.rs')
-rw-r--r--src/tree.rs169
1 files changed, 103 insertions, 66 deletions
diff --git a/src/tree.rs b/src/tree.rs
index 71243be..ae408a8 100644
--- a/src/tree.rs
+++ b/src/tree.rs
@@ -6,100 +6,137 @@
 //! Command syntax tree.
 
 use ::std::borrow::Cow;
+use ::std::collections::HashMap;
+use ::std::collections::HashSet;
+use ::std::hash::Hash;
+use ::std::sync::Arc;
 
 use crate::Command;
 use crate::args::{ArgumentType, ArgumentTypeAny};
 use crate::strcursor::StringReader;
-// FIXME
+// FIXME move
 use crate::args::CommandContext;
 
 /// The kind of node.
-enum NodeKind<S, E> {
+enum NodeKind<'a, Source, Error> {
     /// Root node.
     Root,
     /// Literal node.
     Literal {
         /// The literal of the node.
-        literal: Cow<'static, str>,
+        literal: Cow<'a, str>,
     },
     /// Argument node.
     Argument {
         /// The label of the node.
-        label: Cow<'static, str>,
+        label: Cow<'a, str>,
         /// The argument type.
-        arg: Box<dyn ArgumentTypeAny<S, E>>,
+        arg: Arc<dyn ArgumentTypeAny<Source, Error>>,
     },
 }
 
-/// A node in the syntax tree.
-pub struct CommandNode<T, S, E> {
+impl<'a, Source, Error> Clone for NodeKind<'a, Source, Error> {
+    fn clone(&self) -> Self {
+        match self {
+            &Self::Root => Self::Root,
+            &Self::Literal {
+                ref literal,
+            } => Self::Literal {
+                literal: Cow::clone(literal),
+            },
+            &Self::Argument {
+                ref label,
+                ref arg,
+            } => Self::Argument {
+                label: Cow::clone(label),
+                arg: Arc::clone(arg),
+            },
+        }
+    }
+}
+
+/// A node of the command parse graph.
+pub struct CommandNode<'a, Type, Source, Error> {
     /// The command to run for this node.
-    command: Option<Command<T, S, E>>,
+    command: Option<Command<Type, Source, Error>>,
     /// Nodes.
-    nodes: (),
+    nodes: HashMap<Cow<'a, str>, Cow<'a, CommandNode<'a, Type, Source, Error>>>,
     /// Literal nodes.
-    literals: (),
+    literals: HashSet<Cow<'a, str>>,
     /// Argument nodes.
-    arguments: (),
+    arguments: HashSet<Cow<'a, str>>,
     /// The kind of node.
-    kind: NodeKind<S, E>,
+    kind: NodeKind<'a, Source, Error>,
 }
 
-impl<T, S, E> CommandNode<T, S, E> {
-    /// Creates a new root node.
-    pub fn root() -> Self {
-        CommandNode {
-            command: None,
-            nodes: (),
-            literals: (),
-            arguments: (),
-            kind: NodeKind::Root,
-        }
-    }
-
-    /// Creates a new literal node.
-    pub fn literal(
-        word: Cow<'static, str>,
-        command: Option<Command<T, S, E>>,
-    ) -> Self {
-        CommandNode {
-            command: command,
-            nodes: (),
-            literals: (),
-            arguments: (),
-            kind: NodeKind::Literal {
-                literal: word,
-            },
+impl<'a, Type, Source, Error> Clone for CommandNode<'a, Type, Source, Error> {
+    fn clone(&self) -> Self {
+        Self {
+            command: self.command.clone(),
+            nodes: self.nodes.clone(),
+            literals: self.literals.clone(),
+            arguments: self.arguments.clone(),
+            kind: self.kind.clone(),
         }
     }
+}
 
-    /// Creates a new argument node.
-    pub fn argument<A: ArgumentType<S, E> + 'static + Send + Sync>(
-        name: Cow<'static, str>,
-        command: Option<Command<T, S, E>>,
-        argument: A,
-    ) -> Self {
-        CommandNode {
-            command: command,
-            nodes: (),
-            literals: (),
-            arguments: (),
-            kind: NodeKind::Argument {
-                label: name,
-                arg: Box::new(argument),
-            },
-        }
-    }
 
-    /// Returns the name of this node.
-    ///
-    /// For literal nodes, this is the literal itself. For argument nodes, this
-    /// is the name of the argument.
-    pub fn get_name(&self) -> &str {
-        match self.kind {
-            NodeKind::Root => "",
-            NodeKind::Literal { ref literal, .. } => literal,
-            NodeKind::Argument { ref label, .. } => label,
-        }
-    }
-}
+//impl<T, S, E> CommandNode<T, S, E> {
+//    /// Creates a new root node.
+//    pub fn root() -> Self {
+//        CommandNode {
+//            command: None,
+//            nodes: (),
+//            literals: (),
+//            arguments: (),
+//            kind: NodeKind::Root,
+//        }
+//    }
+//
+//    /// Creates a new literal node.
+//    pub fn literal(
+//        word: Cow<'static, str>,
+//        command: Option<Command<T, S, E>>,
+//    ) -> Self {
+//        CommandNode {
+//            command: command,
+//            nodes: (),
+//            literals: (),
+//            arguments: (),
+//            kind: NodeKind::Literal {
+//                literal: word,
+//            },
+//        }
+//    }
+//
+//    /// Creates a new argument node.
+//    pub fn argument<A: ArgumentType<S, E> + 'static + Send + Sync + Eq + Hash>(
+//        name: Cow<'static, str>,
+//        command: Option<Command<T, S, E>>,
+//        argument: A,
+//    ) -> Self {
+//        CommandNode {
+//            command: command,
+//            nodes: (),
+//            literals: (),
+//            arguments: (),
+//            kind: NodeKind::Argument {
+//                label: name,
+//                arg: Box::new(argument),
+//            },
+//        }
+//    }
+//
+//    /// Returns the name of this node.
+//    ///
+//    /// For literal nodes, this is the literal itself. For argument nodes, this
+//    /// is the name of the argument.
+//    pub fn get_name(&self) -> &str {
+//        match self.kind {
+//            NodeKind::Root => "",
+//            NodeKind::Literal { ref literal, .. } => literal,
+//            NodeKind::Argument { ref label, .. } => label,
+//        }
+//    }
+//}