Browse Source

Parse select statements

main
Dylan Baker 3 years ago
parent
commit
2fdff907dd
4 changed files with 117 additions and 8 deletions
  1. 35
    6
      src/error.rs
  2. 1
    0
      src/lib.rs
  3. 79
    0
      src/parser.rs
  4. 2
    2
      src/token.rs

+ 35
- 6
src/error.rs View File

@@ -5,6 +5,14 @@ pub struct LexerError {
5 5
     message: String,
6 6
 }
7 7
 
8
+impl LexerError {
9
+    pub fn new(message: &str) -> Self {
10
+        Self {
11
+            message: message.to_string(),
12
+        }
13
+    }
14
+}
15
+
8 16
 impl Display for LexerError {
9 17
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10 18
         write!(f, "{}", &self.message)
@@ -13,14 +21,35 @@ impl Display for LexerError {
13 21
 
14 22
 impl Error for LexerError {}
15 23
 
16
-// impl Into<std::io::Error> for LexerError {
17
-//     fn into(self) -> std::io::Error {
18
-//         std::io::Error::new(std::io::ErrorKind::InvalidInput, self.message)
19
-//     }
20
-// }
21
-
22 24
 impl From<LexerError> for std::io::Error {
23 25
     fn from(e: LexerError) -> Self {
24 26
         Self::new(std::io::ErrorKind::InvalidInput, e.message)
25 27
     }
26 28
 }
29
+
30
+#[derive(Debug, PartialEq)]
31
+pub struct ParserError {
32
+    message: String,
33
+}
34
+
35
+impl ParserError {
36
+    pub fn new(message: &str) -> Self {
37
+        Self {
38
+            message: message.to_string(),
39
+        }
40
+    }
41
+}
42
+
43
+impl Display for ParserError {
44
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45
+        write!(f, "{}", &self.message)
46
+    }
47
+}
48
+
49
+impl Error for ParserError {}
50
+
51
+impl From<ParserError> for std::io::Error {
52
+    fn from(e: ParserError) -> Self {
53
+        Self::new(std::io::ErrorKind::InvalidInput, e.message)
54
+    }
55
+}

+ 1
- 0
src/lib.rs View File

@@ -1,3 +1,4 @@
1 1
 pub mod error;
2 2
 pub mod lexer;
3
+pub mod parser;
3 4
 pub mod token;

+ 79
- 0
src/parser.rs View File

@@ -0,0 +1,79 @@
1
+use std::slice::Iter;
2
+
3
+use crate::error::ParserError;
4
+use crate::token::{Token, TokenType};
5
+
6
+#[derive(Debug, PartialEq)]
7
+pub struct Select {
8
+    pub fields: Vec<Field>,
9
+    pub source: Identifier,
10
+}
11
+
12
+#[derive(Debug, PartialEq)]
13
+pub struct Identifier {
14
+    pub name: String,
15
+}
16
+
17
+#[derive(Debug, PartialEq)]
18
+pub enum Field {
19
+    Star,
20
+}
21
+
22
+impl Identifier {
23
+    pub fn new(name: &str) -> Self {
24
+        Self {
25
+            name: name.to_string(),
26
+        }
27
+    }
28
+}
29
+
30
+pub fn parse(tokens: Vec<Token>) -> Result<Select, ParserError> {
31
+    select_expression(&mut tokens.iter())
32
+}
33
+
34
+fn select_expression(tokens: &mut Iter<Token>) -> Result<Select, ParserError> {
35
+    eat(tokens, TokenType::Select)?;
36
+    let fields = eat(tokens, TokenType::Star).and_then(|_| Ok(vec![Field::Star]))?;
37
+    eat(tokens, TokenType::From)?;
38
+    let source = eat(tokens, TokenType::Identfiier).and_then(|t| Ok(Identifier::new(&t.value)))?;
39
+
40
+    Ok(Select { fields, source })
41
+}
42
+
43
+fn eat<'a>(tokens: &'a mut Iter<Token>, token_type: TokenType) -> Result<&'a Token, ParserError> {
44
+    match tokens.next() {
45
+        Some(token) => {
46
+            if token.token_type == token_type {
47
+                Ok(token)
48
+            } else {
49
+                Err(ParserError::new(&format!(
50
+                    "Expected {} but got {}",
51
+                    token_type, token.token_type
52
+                )))
53
+            }
54
+        }
55
+        None => Err(ParserError::new("Unexpected end of tokens")),
56
+    }
57
+}
58
+
59
+#[cfg(test)]
60
+mod tests {
61
+    use super::*;
62
+    use crate::lexer::scan;
63
+
64
+    fn _parse(input: &str) -> Result<Select, ParserError> {
65
+        let tokens = scan(input).unwrap();
66
+        parse(tokens)
67
+    }
68
+
69
+    #[test]
70
+    fn it_parses_a_simple_select() {
71
+        assert_eq!(
72
+            _parse("SELECT * FROM index").unwrap(),
73
+            Select {
74
+                fields: vec![Field::Star],
75
+                source: Identifier::new("index")
76
+            },
77
+        )
78
+    }
79
+}

+ 2
- 2
src/token.rs View File

@@ -1,7 +1,7 @@
1 1
 #[derive(Debug, PartialEq)]
2 2
 pub struct Token {
3
-    token_type: TokenType,
4
-    value: String,
3
+    pub token_type: TokenType,
4
+    pub value: String,
5 5
 }
6 6
 
7 7
 impl Token {

Loading…
Cancel
Save