diff --git a/src/ast.rs b/src/ast.rs
new file mode 100644
index 0000000..5a20bbc
--- /dev/null
+++ b/src/ast.rs
@@ -0,0 +1,123 @@
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
+
+#[derive(Debug)]
+pub enum Command {
+    Simple {
+        assignments: Vec<(String, Word)>,
+        command_word: Word,
+        redirections: Vec<Redirection>
+    },
+    Pipeline(Vec<Command>),
+    Sequence(Vec<Command>),
+    ShortCircuitConjection(Vec<Command>),
+    ShortCircuitDisjunction(Vec<Command>),
+    Negation(Command),
+    While {
+        condition: Command,
+        loop_body: Command
+    },
+    For {
+        varname: String,
+        sequence: Word,
+        loop_body: Command
+    }
+    If {
+        condition: Command,
+        then_branch: Command,
+        else_branch: Command
+    },
+    Case {
+        expr: Word,
+        cases: Vec<(Word, Command)>
+    },
+    Function {
+        name: String,
+        body: Command
+    }
+}
+
+/*
+ * We are all luminous beings.
+ * Why then, do we not appear before each
+ * other radiant in our illumination ?
+ */
+
+/*
+ * Bewteen the idea
+ * And the reality
+ * Between the motion
+ * And the act
+ * Falls the Shadow
+ * (T.S. Eliot)
+ */
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
+
+#[derive(Debug)]
+pub struct Word {
+    pub segments: Vec<WordSegment>
+}
+
+#[derive(Debug)]
+pub enum WordSegment {
+    FieldSeparator,
+    Tilde(String),
+    Literal(String),
+    Parameter(String, ParameterFormat),
+    Subshell(Command),
+    DoubleQuote(Word),
+}
+
+#[derive(Debug)]
+pub enum ParameterFormat {
+    Normal,
+    Length,
+    Default(Word),
+    Assign(Word),
+    Error(Word),
+    Alt(Word),
+    Sub(ParamSubSide, ParamSubMode, Word),
+}
+
+#[derive(Debug)]
+pub enum ParamSubMode {
+    Shortest, Longest
+}
+
+#[derive(Debug)]
+pub enum ParamSubSide {
+    Prefix, Suffix
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
+
+#[derive(Debug)]
+pub struct Redirection {
+    redirection_type: RedirectionType,
+    fd: u64,
+    target: Word
+}
+
+#[derive(Debug)]
+pub enum RedirectionType {
+    File(FileRedirectionType),
+    Dup(DupRedirectionType),
+    Heredoc // '<<'
+}
+
+#[derive(Debug)]
+pub enum FileRedirectionType {
+    In,         // '<'
+    InOut,      // '<>'
+    Out,        // '>'
+    OutReplace, // '>|'
+    OutAppend,  // '>|'
+}
+
+#[derive(Debug)]
+pub enum DupRedirectionType {
+    In,  // '<&'
+    Out  // '>&'
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
diff --git a/src/env.rs b/src/env.rs
new file mode 100644
index 0000000..091e68d
--- /dev/null
+++ b/src/env.rs
@@ -0,0 +1,9 @@
+use std::collections::HashMap;
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
+
+struct Environment {
+    variables: HashMap<String, String>
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
diff --git a/src/expand.rs b/src/expand.rs
new file mode 100644
index 0000000..412fc5f
--- /dev/null
+++ b/src/expand.rs
@@ -0,0 +1,44 @@
+use crate::ast::*;
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
+
+impl Word {
+    pub fn (&mut self, env: &Environment) {
+        for x in self.0.iter_mut() {
+            x.expand_tilde();
+            match x {
+                Word::Tilde => Word::Literal( env.get_home() ),
+                other => other,
+            }
+        }
+    }
+
+    pub fn expand(&self) -> Vec<String> {
+        let mut fields = Vec::new();
+
+        for seg in self.segments.iter() {
+            //
+        }
+
+        fields
+    }
+
+    pub fn split_field(&mut self) {
+        
+    }
+}
+
+impl WordSegment {
+    pub fn split_field(&self) -> Word {
+        
+        match self {
+            
+        }
+    }
+
+    pub fn expand(&self) -> Word {
+        match 
+    }
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
diff --git a/src/main.rs b/src/main.rs
index 5533bc1..d6025bd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,11 @@ use {
     tiny_ansi::TinyAnsi
 };
 
+mod ast;
+mod env;
+mod parse;
+//mod expand;
+
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
 
 pub fn get_type_str(cmd: &str, item: &str) -> Option<String> {
@@ -31,7 +36,19 @@ fn main() {
     let mut dict = TypeDict::new();
 
     let stdin = std::io::stdin();
-    for pipeline in std::io::BufReader::new(stdin).lines() {        
+    for line in std::io::BufReader::new(stdin).lines() {
+        if let Ok(line) = line {
+            let mut lex = parse::WordLexer::from( line.chars() );
+            for word in lex {
+                eprintln!("word-segment: {:?}", word);
+            }
+        }
+    }
+
+    return;
+
+    let stdin = std::io::stdin();
+    for pipeline in std::io::BufReader::new(stdin).lines() {
         let mut last_cmd = String::new();
         let mut last_stdout_type : Option<TypeTerm> = None;
 
diff --git a/src/parse.rs b/src/parse.rs
new file mode 100644
index 0000000..9a54df4
--- /dev/null
+++ b/src/parse.rs
@@ -0,0 +1,130 @@
+use {
+    crate::ast::*,
+    std::iter::{Peekable, FromIterator},
+};
+
+pub struct WordLexer<It>
+where It: Iterator<Item = char> {
+    chars: Peekable<It>
+}
+
+impl<It> From<It> for WordLexer<It>
+where It: Iterator<Item = char> {
+    fn from(iter: It) -> Self {
+        WordLexer {
+            chars: iter.into_iter().peekable()
+        }
+    }
+}
+
+#[derive(Debug)]
+pub enum LexError {
+    UnexpectedEnd(char)
+}
+
+impl<It> WordLexer<It>
+where It: Iterator<Item = char> {
+    fn collect_until(&mut self, close: char) -> Result<String, LexError> {
+        let mut val = String::new();
+        while let Some(c) = self.chars.peek().cloned() {
+            if c == close {
+                return Ok(val)
+            } else {
+                self.chars.next();
+                val.push(c);
+            }
+        }
+
+        if close.is_whitespace() {
+            Ok(val)
+        } else {
+            Err(LexError::UnexpectedEnd(close))
+        }
+    }
+}
+
+impl<It> Iterator for WordLexer<It>
+where It: Iterator<Item = char> {
+    type Item = Result<WordSegment, LexError>;
+
+    fn next(&mut self) -> Option<Result<WordSegment, LexError>> {
+        match self.chars.peek().cloned() {
+            Some('~') => {
+                self.chars.next();
+                match self.collect_until(' ') {
+                    Ok(s) => Some(Ok(WordSegment::Tilde(s))),
+                    Err(e) => Some(Err(e))
+                }
+            }
+            Some('"') => {
+                self.chars.next();
+                match self.collect_until('"') {
+                    Ok(s) => {
+                        self.chars.next();
+
+                        let word = Word {
+                            segments: WordLexer { chars: s.chars().peekable() }
+                            .scan((), |_, x| x.ok())
+                                .collect::<Vec<_>>()
+                        };
+
+                        Some(Ok(WordSegment::DoubleQuote(word)))
+                    },
+                    Err(e) => Some(Err(e))
+                }
+            },
+            Some('\'') => {
+                self.chars.next();
+                match self.collect_until('\'') {
+                    Ok(s) => {
+                        self.chars.next();
+                        Some(Ok(WordSegment::Literal(s)))
+                    },
+                    Err(e) => Some(Err(e))
+                }
+            },
+            Some('$') => {
+                self.chars.next();
+                match self.chars.peek() {
+                    Some('{') => {
+                        self.chars.next();
+                        match self.collect_until('}') {
+                            Ok(s) => {
+                                self.chars.next();
+                                Some(Ok(WordSegment::Variable(s)))
+                            }
+                            Err(e) => Some(Err(e))
+                        }
+                    }
+                    _ => {
+                        match self.collect_until(' ') {
+                            Ok(s) => {
+                                Some(Ok(WordSegment::Variable(s)))
+                            }
+                            Err(e) => Some(Err(e))
+                        }
+                    }
+                }
+            }
+            Some(c) => {
+                while let Some(c) = self.chars.peek() {
+                    if c.is_whitespace() {
+                        self.chars.next();
+                    } else {
+                        return match self.collect_until(' ') {
+                            Ok(s) => {
+                                Some(Ok(WordSegment::Literal(s)))
+                            }
+                            Err(e) => Some(Err(e))
+                        };
+                    }
+                }
+                None
+            }
+            None => {
+                None
+            }
+        }
+    }
+}
+