use super::errors::ParserError;
use super::errors::ErrorKind;
use super::stream::ParserStream;
use super::parser::Result;
pub trait FTLParserStream<I> {
fn peek_line_ws(&mut self);
fn skip_ws_lines(&mut self);
fn skip_line_ws(&mut self);
fn expect_char(&mut self, ch: char) -> Result<()>;
fn take_char_if(&mut self, ch: char) -> bool;
fn take_char<F>(&mut self, f: F) -> Option<char>
where
F: Fn(char) -> bool;
fn is_id_start(&mut self) -> bool;
fn is_peek_next_line_indented(&mut self) -> bool;
fn is_peek_next_line_variant_start(&mut self) -> bool;
fn is_peek_next_line_attribute_start(&mut self) -> bool;
fn is_peek_next_line_pattern(&mut self) -> bool;
fn is_peek_next_line_tag_start(&mut self) -> bool;
fn skip_to_next_entry_start(&mut self);
fn take_id_start(&mut self) -> Result<char>;
fn take_id_char(&mut self) -> Option<char>;
fn take_symb_char(&mut self) -> Option<char>;
fn take_digit(&mut self) -> Option<char>;
}
impl<I> FTLParserStream<I> for ParserStream<I>
where
I: Iterator<Item = char>,
{
fn peek_line_ws(&mut self) {
while let Some(ch) = self.current_peek() {
if ch != ' ' && ch != '\t' {
break;
}
self.peek();
}
}
fn skip_ws_lines(&mut self) {
loop {
self.peek_line_ws();
if self.current_peek() == Some('\n') {
self.skip_to_peek();
self.next();
} else {
self.reset_peek();
break;
}
}
}
fn skip_line_ws(&mut self) {
while self.ch == Some(' ') || self.ch == Some('\t') {
self.next();
}
}
fn expect_char(&mut self, ch: char) -> Result<()> {
if self.ch == Some(ch) {
self.next();
return Ok(());
}
error!(ErrorKind::ExpectedToken { token: ch })
}
fn take_char_if(&mut self, ch: char) -> bool {
if self.ch == Some(ch) {
self.next();
return true;
}
false
}
fn take_char<F>(&mut self, f: F) -> Option<char>
where
F: Fn(char) -> bool,
{
if let Some(ch) = self.ch {
if f(ch) {
self.next();
return Some(ch);
}
}
None
}
fn is_id_start(&mut self) -> bool {
if let Some(ch) = self.ch {
return match ch {
'a'...'z' | 'A'...'Z' | '_' => true,
_ => false,
};
}
false
}
fn is_peek_next_line_indented(&mut self) -> bool {
if !self.current_peek_is('\n') {
return false;
}
self.peek();
if self.current_peek_is(' ') {
self.reset_peek();
return true;
}
self.reset_peek();
false
}
fn is_peek_next_line_variant_start(&mut self) -> bool {
if !self.current_peek_is('\n') {
return false;
}
self.peek();
let ptr = self.get_peek_index();
self.peek_line_ws();
if self.get_peek_index() - ptr == 0 {
self.reset_peek();
return false;
}
if self.current_peek_is('*') {
self.peek();
}
if self.current_peek_is('[') && !self.peek_char_is('[') {
self.reset_peek();
return true;
}
self.reset_peek();
false
}
fn is_peek_next_line_attribute_start(&mut self) -> bool {
if !self.current_peek_is('\n') {
return false;
}
self.peek();
let ptr = self.get_peek_index();
self.peek_line_ws();
if self.get_peek_index() - ptr == 0 {
self.reset_peek();
return false;
}
if self.current_peek_is('.') {
self.reset_peek();
return true;
}
self.reset_peek();
false
}
fn is_peek_next_line_pattern(&mut self) -> bool {
if !self.current_peek_is('\n') {
return false;
}
self.peek();
let ptr = self.get_peek_index();
self.peek_line_ws();
if self.get_peek_index() - ptr == 0 {
self.reset_peek();
return false;
}
if self.current_peek_is('}') || self.current_peek_is('.') ||
self.current_peek_is('#') || self.current_peek_is('[') ||
self.current_peek_is('*')
{
self.reset_peek();
return false;
}
self.reset_peek();
true
}
fn is_peek_next_line_tag_start(&mut self) -> bool {
if !self.current_peek_is('\n') {
return false;
}
self.peek();
let ptr = self.get_peek_index();
self.peek_line_ws();
if self.get_peek_index() - ptr == 0 {
self.reset_peek();
return false;
}
if self.current_peek_is('#') {
self.reset_peek();
return true;
}
self.reset_peek();
false
}
fn skip_to_next_entry_start(&mut self) {
while let Some(_) = self.next() {
if self.current_is('\n') && !self.peek_char_is('\n') &&
(self.next() == None || self.is_id_start() || self.current_is('/') ||
self.current_is('[') || self.peek_char_is('/') ||
self.peek_char_is('['))
{
break;
}
}
}
fn take_id_start(&mut self) -> Result<char> {
let closure = |x| match x {
'a'...'z' | 'A'...'Z' | '_' => true,
_ => false,
};
match self.take_char(closure) {
Some(ch) => Ok(ch),
None => {
error!(ErrorKind::ExpectedCharRange {
range: String::from("'a'...'z' | 'A'...'Z' | '_'"),
})
}
}
}
fn take_id_char(&mut self) -> Option<char> {
let closure = |x| match x {
'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => true,
_ => false,
};
match self.take_char(closure) {
Some(ch) => Some(ch),
None => None,
}
}
fn take_symb_char(&mut self) -> Option<char> {
let closure = |x| match x {
'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' | ' ' => true,
_ => false,
};
match self.take_char(closure) {
Some(ch) => Some(ch),
None => None,
}
}
fn take_digit(&mut self) -> Option<char> {
let closure = |x| match x {
'0'...'9' => true,
_ => false,
};
match self.take_char(closure) {
Some(ch) => Some(ch),
None => None,
}
}
}