use range::Range;
use read_token::ReadToken;
use std::sync::Arc;
use super::{
ParseResult,
};
use {
DebugId,
MetaData,
ParseError,
};
use tokenizer::{ read_data, TokenizerState };
#[derive(Clone, Debug, PartialEq)]
pub struct Tag {
pub text: Arc<String>,
pub not: bool,
pub inverted: bool,
pub property: Option<Arc<String>>,
pub debug_id: DebugId,
}
impl Tag {
pub fn parse(
&self,
tokens: &mut Vec<Range<MetaData>>,
state: &TokenizerState,
read_token: &ReadToken
) -> ParseResult<TokenizerState> {
if let Some(range) = read_token.tag(&self.text) {
if self.not {
Err(range.wrap(
ParseError::DidNotExpectTag(self.text.clone(),
self.debug_id)))
} else {
match &self.property {
&Some(ref name) => {
Ok((range, read_data(
tokens,
range.wrap(
MetaData::Bool(name.clone(), !self.inverted)),
&state
), None))
}
_ => {
Ok((range, state.clone(), None))
}
}
}
} else {
if self.not {
match &self.property {
&Some(ref name) => {
let range = read_token.start();
Ok((range, read_data(
tokens,
range.wrap(
MetaData::Bool(name.clone(), !self.inverted)),
&state
), None))
}
_ => {
Ok((read_token.start(), state.clone(), None))
}
}
} else {
Err(read_token.start().wrap(
ParseError::ExpectedTag(self.text.clone(),
self.debug_id)))
}
}
}
}
#[cfg(test)]
mod tests {
use all::*;
use all::tokenizer::*;
use meta_rules::Tag;
use std::sync::Arc;
use range::Range;
use read_token::ReadToken;
#[test]
fn expected_token() {
let text = ")";
let start_parenthesis = Tag {
debug_id: 0,
text: Arc::new("(".into()),
not: false,
inverted: false,
property: None
};
let mut tokens = vec![];
let s = TokenizerState::new();
let res = start_parenthesis.parse(&mut tokens, &s,
&ReadToken::new(&text, 0));
assert_eq!(res, Err(Range::new(0, 0).wrap(
ParseError::ExpectedTag(Arc::new("(".into()), 0))));
}
#[test]
fn did_not_expect_token() {
let text = ")";
let start_parenthesis = Tag {
debug_id: 0,
text: Arc::new(")".into()),
not: true,
inverted: false,
property: None
};
let mut tokens = vec![];
let s = TokenizerState::new();
let res = start_parenthesis.parse(&mut tokens, &s,
&ReadToken::new(&text, 0));
assert_eq!(res, Err(Range::new(0, 1).wrap(
ParseError::DidNotExpectTag(Arc::new(")".into()), 0))));
}
#[test]
fn successful() {
let text = "fn foo()";
let fn_ = Tag {
debug_id: 0,
text: Arc::new("fn ".into()),
not: false,
inverted: false,
property: None
};
let mut tokens = vec![];
let s = TokenizerState::new();
let res = fn_.parse(&mut tokens, &s, &ReadToken::new(&text, 0));
assert_eq!(res, Ok((Range::new(0, 3), s, None)));
assert_eq!(tokens.len(), 0);
let mut tokens = vec![];
let has_arguments: Arc<String> = Arc::new("has_arguments".into());
let start_parenthesis = Tag {
debug_id: 0,
text: Arc::new("(".into()),
not: false,
inverted: false,
property: Some(has_arguments.clone())
};
let s = TokenizerState::new();
let res = start_parenthesis.parse(&mut tokens, &s,
&ReadToken::new(&text[6..], 6));
assert_eq!(res, Ok((Range::new(6, 1), TokenizerState(1), None)));
assert_eq!(tokens.len(), 1);
assert_eq!(&tokens[0].data, &MetaData::Bool(has_arguments.clone(), true));
let mut tokens = vec![];
let has_arguments: Arc<String> = Arc::new("has_no_arguments".into());
let start_parenthesis = Tag {
debug_id: 0,
text: Arc::new("(".into()),
not: false,
inverted: true,
property: Some(has_arguments.clone())
};
let s = TokenizerState::new();
let res = start_parenthesis.parse(&mut tokens, &s,
&ReadToken::new(&text[6..], 6));
assert_eq!(res, Ok((Range::new(6, 1), TokenizerState(1), None)));
assert_eq!(tokens.len(), 1);
assert_eq!(&tokens[0].data, &MetaData::Bool(has_arguments.clone(), false));
}
}