|
@@ -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
|
+}
|