123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- use std::{iter::Peekable, slice::Iter};
-
- use crate::error::KappeError;
- use crate::token::{Token, TokenType};
-
- #[derive(Debug, PartialEq)]
- pub struct Select {
- pub fields: Vec<Field>,
- pub source: Identifier,
- }
-
- #[derive(Debug, PartialEq)]
- pub struct Identifier {
- pub name: String,
- }
-
- #[derive(Debug, PartialEq)]
- pub enum Field {
- Named(String),
- Star,
- }
-
- impl Identifier {
- pub fn new(name: &str) -> Self {
- Self {
- name: name.to_string(),
- }
- }
- }
-
- pub fn parse(tokens: Vec<Token>) -> Result<Select, KappeError> {
- parse_select_expression(&mut tokens.iter().peekable())
- }
-
- fn parse_select_expression(tokens: &mut Peekable<Iter<Token>>) -> Result<Select, KappeError> {
- eat(tokens, TokenType::Select)?;
- let fields = parse_fields(tokens)?;
- eat(tokens, TokenType::From)?;
- let source = eat(tokens, TokenType::Identfiier).and_then(|t| Ok(Identifier::new(&t.value)))?;
-
- Ok(Select { fields, source })
- }
-
- fn parse_fields(tokens: &mut Peekable<Iter<Token>>) -> Result<Vec<Field>, KappeError> {
- if current_token_is(tokens, TokenType::Star) {
- eat(tokens, TokenType::Star).and_then(|_| Ok(vec![Field::Star]))
- } else {
- let mut fields: Vec<Field> = vec![];
-
- loop {
- let field = eat(tokens, TokenType::Identfiier)?;
- fields.push(Field::Named(field.value.clone()));
-
- if current_token_is(tokens, TokenType::Comma) {
- eat(tokens, TokenType::Comma)?;
- } else {
- break;
- }
- }
-
- Ok(fields)
- }
- }
-
- fn current_token_is(tokens: &mut Peekable<Iter<Token>>, token_type: TokenType) -> bool {
- match tokens.peek() {
- Some(t) => t.token_type == token_type,
- None => false,
- }
- }
-
- fn eat<'a>(
- tokens: &'a mut Peekable<Iter<Token>>,
- token_type: TokenType,
- ) -> Result<&'a Token, KappeError> {
- match tokens.next() {
- Some(token) => {
- if token.token_type == token_type {
- Ok(token)
- } else {
- Err(KappeError::new(&format!(
- "Expected {} but got {}",
- token_type, token.token_type
- )))
- }
- }
- None => Err(KappeError::new("Unexpected end of tokens")),
- }
- }
-
- #[cfg(test)]
- mod tests {
- use super::*;
- use crate::lexer::scan;
-
- fn _parse(input: &str) -> Result<Select, KappeError> {
- let tokens = scan(input).unwrap();
- parse(tokens)
- }
-
- #[test]
- fn it_parses_a_simple_select() {
- assert_eq!(
- _parse("SELECT * FROM index").unwrap(),
- Select {
- fields: vec![Field::Star],
- source: Identifier::new("index")
- },
- )
- }
-
- #[test]
- fn it_parses_a_select_with_field() {
- assert_eq!(
- _parse("SELECT field FROM index").unwrap(),
- Select {
- fields: vec![Field::Named("field".to_string())],
- source: Identifier::new("index")
- },
- )
- }
-
- #[test]
- fn it_parses_a_select_with_multiple_fields() {
- assert_eq!(
- _parse("SELECT field_one, field_two FROM index").unwrap(),
- Select {
- fields: vec![
- Field::Named("field_one".to_string()),
- Field::Named("field_two".to_string())
- ],
- source: Identifier::new("index")
- },
- )
- }
- }
|