rico 0.1.7

A high-performance Apache Thrift IDL parser that converts Thrift IDL files to JSON AST
Documentation
use crate::ast::FieldType;
use crate::ast::LOC;
use crate::lexer::Token;
use crate::parser::error::ParseError;
use crate::parser::factory::*;
use crate::parser::Parser;

use super::error::ParseErrorKind;

impl<'a> Parser<'a> {
    pub(crate) fn parse_complex_type<F>(
        &mut self,
        create_field_type: F,
    ) -> Result<FieldType, ParseError>
    where
        F: Fn(LOC, &str, FieldType) -> FieldType,
    {
        let start_loc = self.start_pos();
        let slice = self.text().to_owned();

        self.consume(Token::LeftAngle)?;
        let filed_type = self.parse_field_type()?;

        self.consume(Token::RightAngle)?;
        let end_loc = self.get_token_loc();
        Ok(create_field_type(
            LOC {
                start: start_loc,
                end: end_loc.end,
            },
            &slice,
            filed_type,
        ))
    }

    pub(crate) fn parse_list_type(&mut self) -> Result<FieldType, ParseError> {
        self.parse_complex_type(create_list_field_type)
    }

    pub(crate) fn parse_set_type(&mut self) -> Result<FieldType, ParseError> {
        self.parse_complex_type(create_set_field_type)
    }

    pub(crate) fn parse_map_type(&mut self) -> Result<FieldType, ParseError> {
        let start_loc = self.start_pos();
        let slice = self.text().to_owned();

        self.consume(Token::LeftAngle)?;
        let filed_key_type = self.parse_field_type()?;

        self.consume(Token::Comma)?;
        let filed_value_type = self.parse_field_type()?;

        self.consume(Token::RightAngle)?;

        let end_loc = self.get_token_loc();
        Ok(create_map_field_type(
            self.get_token_parent_loc(start_loc, end_loc.end),
            &slice,
            filed_key_type,
            filed_value_type,
        ))
    }

    pub(crate) fn parse_field_type(&mut self) -> Result<FieldType, ParseError> {
        self.parse_field_type_opt(true)
    }

    pub(crate) fn parse_field_type_opt(
        &mut self,
        auto_advance: bool,
    ) -> Result<FieldType, ParseError> {
        if auto_advance {
            self.advance();
        }

        match self.token() {
            Some(token) => match token {
                Token::Binary
                | Token::String
                | Token::Byte
                | Token::I16
                | Token::I32
                | Token::I64
                | Token::Double
                | Token::Bool => Ok(create_keyword_field_type(
                    token,
                    self.get_token_loc(),
                    self.text(),
                )),
                Token::Identifier => Ok(create_identifier_field_type(
                    self.get_token_loc(),
                    self.text(),
                )),
                Token::List => self.parse_list_type(),
                Token::Map => self.parse_map_type(),
                Token::Set => self.parse_set_type(),
                _ => Err(self.error(ParseErrorKind::UnsupportedType)),
            },
            None => Err(self.error(ParseErrorKind::MissingTypeDeclaration)),
        }
    }
}