jsonpath/src/parser/tokenizer.rs

381 lines
11 KiB
Rust
Raw Normal View History

2019-03-14 22:30:42 +09:00
use std::result::Result;
2018-12-26 14:45:31 +09:00
2019-03-14 22:30:42 +09:00
use super::path_reader::{PathReader, ReaderError};
2018-12-26 14:45:31 +09:00
2019-06-25 18:58:25 +09:00
pub const ABSOLUTE: &str = "$";
pub const DOT: &str = ".";
pub const AT: &str = "@";
pub const OPEN_ARRAY: &str = "[";
pub const CLOSE_ARRAY: &str = "]";
pub const ASTERISK: &str = "*";
pub const QUESTION: &str = "?";
pub const COMMA: &str = ",";
pub const SPLIT: &str = ":";
pub const OPEN_PARENTHESIS: &str = "(";
pub const CLOSE_PARENTHESIS: &str = ")";
pub const KEY: &str = "Key";
pub const DOUBLE_QUOTE: &str = "\"";
pub const SINGLE_QUOTE: &str = "'";
pub const EQUAL: &str = "==";
pub const GREATER_OR_EQUAL: &str = ">=";
pub const GREATER: &str = ">";
pub const LITTLE: &str = "<";
pub const LITTLE_OR_EQUAL: &str = "<=";
pub const NOT_EQUAL: &str = "!=";
pub const AND: &str = "&&";
pub const OR: &str = "||";
pub const WHITESPACE: &str = " ";
2018-12-26 14:45:31 +09:00
const CH_DOLLA: char = '$';
const CH_DOT: char = '.';
const CH_ASTERISK: char = '*';
const CH_LARRAY: char = '[';
const CH_RARRAY: char = ']';
const CH_LPAREN: char = '(';
const CH_RPAREN: char = ')';
const CH_AT: char = '@';
const CH_QUESTION: char = '?';
const CH_COMMA: char = ',';
const CH_SEMICOLON: char = ':';
const CH_EQUAL: char = '=';
const CH_AMPERSAND: char = '&';
const CH_PIPE: char = '|';
const CH_LITTLE: char = '<';
const CH_GREATER: char = '>';
const CH_EXCLAMATION: char = '!';
2019-06-17 15:42:46 +09:00
const CH_SINGLE_QUOTE: char = '\'';
const CH_DOUBLE_QUOTE: char = '"';
2018-12-26 14:45:31 +09:00
2018-12-27 23:46:15 +09:00
#[derive(Debug, Clone, PartialEq)]
pub enum TokenError {
Eof,
Position(usize),
}
fn to_token_error(read_err: ReaderError) -> TokenError {
match read_err {
2019-06-19 11:34:47 +09:00
ReaderError::Eof => TokenError::Eof,
2018-12-27 23:46:15 +09:00
}
}
#[derive(Debug, PartialEq)]
2018-12-26 14:45:31 +09:00
pub enum Token {
Absolute(usize),
2018-12-27 23:46:15 +09:00
Dot(usize),
2018-12-26 14:45:31 +09:00
At(usize),
OpenArray(usize),
CloseArray(usize),
Asterisk(usize),
Question(usize),
Comma(usize),
Split(usize),
OpenParenthesis(usize),
CloseParenthesis(usize),
2019-03-11 17:35:15 +09:00
Key(usize, String),
DoubleQuoted(usize, String),
SingleQuoted(usize, String),
2018-12-26 14:45:31 +09:00
Equal(usize),
GreaterOrEqual(usize),
Greater(usize),
Little(usize),
LittleOrEqual(usize),
NotEqual(usize),
And(usize),
Or(usize),
2018-12-27 23:46:15 +09:00
Whitespace(usize, usize),
2018-12-26 14:45:31 +09:00
}
impl Token {
2018-12-27 23:46:15 +09:00
pub fn partial_eq(&self, other: Token) -> bool {
self.to_simple() == other.to_simple()
2018-12-26 14:45:31 +09:00
}
pub fn simple_eq(&self, str_token: &str) -> bool {
self.to_simple() == str_token
}
2019-06-26 15:07:49 +09:00
#[cfg_attr(tarpaulin, skip)]
2018-12-27 23:46:15 +09:00
fn to_simple(&self) -> &'static str {
2018-12-26 14:45:31 +09:00
match self {
Token::Absolute(_) => ABSOLUTE,
2018-12-27 23:46:15 +09:00
Token::Dot(_) => DOT,
2018-12-26 14:45:31 +09:00
Token::At(_) => AT,
Token::OpenArray(_) => OPEN_ARRAY,
Token::CloseArray(_) => CLOSE_ARRAY,
Token::Asterisk(_) => ASTERISK,
Token::Question(_) => QUESTION,
Token::Comma(_) => COMMA,
Token::Split(_) => SPLIT,
2018-12-27 23:46:15 +09:00
Token::OpenParenthesis(_) => OPEN_PARENTHESIS,
Token::CloseParenthesis(_) => CLOSE_PARENTHESIS,
2018-12-26 14:45:31 +09:00
Token::Key(_, _) => KEY,
2019-06-18 11:46:24 +09:00
Token::DoubleQuoted(_, _) => DOUBLE_QUOTE,
Token::SingleQuoted(_, _) => SINGLE_QUOTE,
2018-12-26 14:45:31 +09:00
Token::Equal(_) => EQUAL,
Token::GreaterOrEqual(_) => GREATER_OR_EQUAL,
Token::Greater(_) => GREATER,
Token::Little(_) => LITTLE,
Token::LittleOrEqual(_) => LITTLE_OR_EQUAL,
Token::NotEqual(_) => NOT_EQUAL,
Token::And(_) => AND,
Token::Or(_) => OR,
2019-06-19 11:34:47 +09:00
Token::Whitespace(_, _) => WHITESPACE,
2018-12-26 14:45:31 +09:00
}
}
}
fn simple_matched_token(ch: char, pos: usize) -> Option<Token> {
match ch {
CH_DOLLA => Some(Token::Absolute(pos)),
2018-12-27 23:46:15 +09:00
CH_DOT => Some(Token::Dot(pos)),
2018-12-26 14:45:31 +09:00
CH_ASTERISK => Some(Token::Asterisk(pos)),
CH_LARRAY => Some(Token::OpenArray(pos)),
CH_RARRAY => Some(Token::CloseArray(pos)),
CH_LPAREN => Some(Token::OpenParenthesis(pos)),
CH_RPAREN => Some(Token::CloseParenthesis(pos)),
CH_AT => Some(Token::At(pos)),
CH_QUESTION => Some(Token::Question(pos)),
CH_COMMA => Some(Token::Comma(pos)),
CH_SEMICOLON => Some(Token::Split(pos)),
2019-06-19 11:34:47 +09:00
_ => None,
2018-12-26 14:45:31 +09:00
}
}
pub struct Tokenizer<'a> {
input: PathReader<'a>,
}
impl<'a> Tokenizer<'a> {
pub fn new(input: &'a str) -> Self {
2019-06-17 15:42:46 +09:00
trace!("input: {}", input);
2018-12-26 14:45:31 +09:00
Tokenizer {
input: PathReader::new(input),
}
}
2019-06-17 15:42:46 +09:00
fn quote(&mut self, ch: char) -> Result<String, TokenError> {
2019-06-19 11:34:47 +09:00
let (_, mut val) = self
.input
.take_while(|c| *c != ch)
.map_err(to_token_error)?;
2019-06-17 15:42:46 +09:00
if let Some('\\') = val.chars().last() {
self.input.next_char().map_err(to_token_error)?;
let _ = val.pop();
2019-06-25 22:42:21 +09:00
let (_, val_remain) = self
2019-06-19 11:34:47 +09:00
.input
.take_while(|c| *c != ch)
.map_err(to_token_error)?;
2019-06-17 15:42:46 +09:00
self.input.next_char().map_err(to_token_error)?;
val.push(ch);
val.push_str(val_remain.as_str());
} else {
self.input.next_char().map_err(to_token_error)?;
}
Ok(val)
}
fn single_quote(&mut self, pos: usize, ch: char) -> Result<Token, TokenError> {
let val = self.quote(ch)?;
2019-03-11 17:35:15 +09:00
Ok(Token::SingleQuoted(pos, val))
2018-12-26 14:45:31 +09:00
}
2019-06-17 15:42:46 +09:00
fn double_quote(&mut self, pos: usize, ch: char) -> Result<Token, TokenError> {
let val = self.quote(ch)?;
2019-03-11 17:35:15 +09:00
Ok(Token::DoubleQuoted(pos, val))
2018-12-26 14:45:31 +09:00
}
2019-03-14 22:30:42 +09:00
fn equal(&mut self, pos: usize, _: char) -> Result<Token, TokenError> {
2018-12-27 23:46:15 +09:00
let (_, ch) = self.input.peek_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
match ch {
CH_EQUAL => {
2018-12-27 23:46:15 +09:00
self.input.next_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
Ok(Token::Equal(pos))
}
2019-06-19 11:34:47 +09:00
_ => Err(TokenError::Position(pos)),
2018-12-26 14:45:31 +09:00
}
}
2019-03-14 22:30:42 +09:00
fn not_equal(&mut self, pos: usize, _: char) -> Result<Token, TokenError> {
2018-12-27 23:46:15 +09:00
let (_, ch) = self.input.peek_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
match ch {
CH_EQUAL => {
2018-12-27 23:46:15 +09:00
self.input.next_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
Ok(Token::NotEqual(pos))
}
2019-06-19 11:34:47 +09:00
_ => Err(TokenError::Position(pos)),
2018-12-26 14:45:31 +09:00
}
}
2019-03-14 22:30:42 +09:00
fn little(&mut self, pos: usize, _: char) -> Result<Token, TokenError> {
2018-12-27 23:46:15 +09:00
let (_, ch) = self.input.peek_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
match ch {
CH_EQUAL => {
2018-12-27 23:46:15 +09:00
self.input.next_char().map_err(to_token_error)?;
Ok(Token::LittleOrEqual(pos))
2018-12-26 14:45:31 +09:00
}
2018-12-27 23:46:15 +09:00
_ => Ok(Token::Little(pos)),
2018-12-26 14:45:31 +09:00
}
}
2019-03-14 22:30:42 +09:00
fn greater(&mut self, pos: usize, _: char) -> Result<Token, TokenError> {
2018-12-27 23:46:15 +09:00
let (_, ch) = self.input.peek_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
match ch {
CH_EQUAL => {
2018-12-27 23:46:15 +09:00
self.input.next_char().map_err(to_token_error)?;
Ok(Token::GreaterOrEqual(pos))
2018-12-26 14:45:31 +09:00
}
2018-12-27 23:46:15 +09:00
_ => Ok(Token::Greater(pos)),
2018-12-26 14:45:31 +09:00
}
}
2019-03-14 22:30:42 +09:00
fn and(&mut self, pos: usize, _: char) -> Result<Token, TokenError> {
2018-12-27 23:46:15 +09:00
let (_, ch) = self.input.peek_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
match ch {
CH_AMPERSAND => {
2018-12-27 23:46:15 +09:00
let _ = self.input.next_char().map_err(to_token_error);
2018-12-26 14:45:31 +09:00
Ok(Token::And(pos))
}
2019-06-19 11:34:47 +09:00
_ => Err(TokenError::Position(pos)),
2018-12-26 14:45:31 +09:00
}
}
2019-03-14 22:30:42 +09:00
fn or(&mut self, pos: usize, _: char) -> Result<Token, TokenError> {
2018-12-27 23:46:15 +09:00
let (_, ch) = self.input.peek_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
match ch {
CH_PIPE => {
2018-12-27 23:46:15 +09:00
self.input.next_char().map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
Ok(Token::Or(pos))
}
2019-06-19 11:34:47 +09:00
_ => Err(TokenError::Position(pos)),
2018-12-26 14:45:31 +09:00
}
}
2019-03-14 22:30:42 +09:00
fn whitespace(&mut self, pos: usize, _: char) -> Result<Token, TokenError> {
2019-06-19 11:34:47 +09:00
let (_, vec) = self
.input
.take_while(|c| c.is_whitespace())
.map_err(to_token_error)?;
2018-12-27 23:46:15 +09:00
Ok(Token::Whitespace(pos, vec.len()))
2018-12-26 14:45:31 +09:00
}
2019-03-14 22:30:42 +09:00
fn other(&mut self, pos: usize, ch: char) -> Result<Token, TokenError> {
2019-06-19 11:34:47 +09:00
let fun = |c: &char| match simple_matched_token(*c, pos) {
Some(_) => false,
_ if c == &CH_LITTLE
|| c == &CH_GREATER
|| c == &CH_EQUAL
|| c == &CH_AMPERSAND
|| c == &CH_PIPE
|| c == &CH_EXCLAMATION =>
{
false
2018-12-26 14:45:31 +09:00
}
2019-06-19 11:34:47 +09:00
_ => !c.is_whitespace(),
2018-12-26 14:45:31 +09:00
};
2018-12-27 23:46:15 +09:00
let (_, mut vec) = self.input.take_while(fun).map_err(to_token_error)?;
2018-12-26 14:45:31 +09:00
vec.insert(0, ch);
Ok(Token::Key(pos, vec))
}
2019-03-14 22:30:42 +09:00
pub fn next_token(&mut self) -> Result<Token, TokenError> {
2018-12-27 23:46:15 +09:00
let (pos, ch) = self.input.next_char().map_err(to_token_error)?;
match simple_matched_token(ch, pos) {
2018-12-26 14:45:31 +09:00
Some(t) => Ok(t),
2019-06-19 11:34:47 +09:00
None => match ch {
CH_SINGLE_QUOTE => self.single_quote(pos, ch),
CH_DOUBLE_QUOTE => self.double_quote(pos, ch),
CH_EQUAL => self.equal(pos, ch),
CH_GREATER => self.greater(pos, ch),
CH_LITTLE => self.little(pos, ch),
CH_AMPERSAND => self.and(pos, ch),
CH_PIPE => self.or(pos, ch),
CH_EXCLAMATION => self.not_equal(pos, ch),
_ if ch.is_whitespace() => self.whitespace(pos, ch),
_ => self.other(pos, ch),
},
2018-12-26 14:45:31 +09:00
}
2018-12-27 23:46:15 +09:00
}
2018-12-26 14:45:31 +09:00
2018-12-27 23:46:15 +09:00
fn current_pos(&self) -> usize {
self.input.current_pos()
2018-12-26 14:45:31 +09:00
}
}
2019-06-03 18:45:26 +09:00
pub struct TokenReader<'a> {
2018-12-27 23:46:15 +09:00
origin_input: &'a str,
err: TokenError,
err_pos: usize,
tokens: Vec<(usize, Token)>,
curr_pos: Option<usize>,
}
2019-06-03 18:45:26 +09:00
impl<'a> TokenReader<'a> {
2018-12-27 23:46:15 +09:00
pub fn new(input: &'a str) -> Self {
let mut tokenizer = Tokenizer::new(input);
let mut tokens = vec![];
loop {
match tokenizer.next_token() {
Ok(t) => {
tokens.insert(0, (tokenizer.current_pos(), t));
}
Err(e) => {
2019-06-03 18:45:26 +09:00
return TokenReader {
2019-06-25 18:58:25 +09:00
origin_input: input,
2019-02-22 00:22:30 +09:00
err: e,
err_pos: tokenizer.current_pos(),
tokens,
curr_pos: None,
};
2018-12-27 23:46:15 +09:00
}
}
}
}
2018-12-26 14:45:31 +09:00
pub fn peek_is(&self, simple_token: &str) -> bool {
match self.peek_token() {
Ok(t) => t.simple_eq(simple_token),
2019-06-19 11:34:47 +09:00
_ => false,
}
}
2019-03-14 22:30:42 +09:00
pub fn peek_token(&self) -> Result<&Token, TokenError> {
2018-12-27 23:46:15 +09:00
match self.tokens.last() {
Some((_, t)) => {
trace!("%{:?}", t);
Ok(t)
}
_ => {
trace!("%{:?}", self.err);
Err(self.err.clone())
}
}
}
2019-03-14 22:30:42 +09:00
pub fn next_token(&mut self) -> Result<Token, TokenError> {
2018-12-27 23:46:15 +09:00
match self.tokens.pop() {
Some((pos, t)) => {
self.curr_pos = Some(pos);
trace!("@{:?}", t);
Ok(t)
}
_ => {
trace!("@{:?}", self.err);
Err(self.err.clone())
}
}
}
pub fn err_msg_with_pos(&self, pos: usize) -> String {
2019-06-19 15:09:42 +09:00
format!("{}\n{}", self.origin_input, "^".repeat(pos))
2018-12-27 23:46:15 +09:00
}
pub fn err_msg(&self) -> String {
match self.curr_pos {
2019-06-19 11:34:47 +09:00
Some(pos) => self.err_msg_with_pos(pos),
_ => self.err_msg_with_pos(self.err_pos),
2018-12-26 14:45:31 +09:00
}
}
2019-06-19 11:34:47 +09:00
}