use crate::lexer::*;
use crate::maybe_byte::*;
use crate::source::buffer::*;
use crate::str_term::str_types::*;
use crate::DiagnosticMessage;
use crate::{lex_states::*, LexState};
pub(crate) trait ParsePercent {
fn percent_unknown(&mut self, term: &MaybeByte) -> i32;
fn percent_quotation(&mut self, c: &mut MaybeByte, ptok: usize) -> i32;
fn parse_percent(&mut self, space_seen: bool, last_state: LexState) -> i32;
}
impl ParsePercent for Lexer {
fn percent_unknown(&mut self, term: &MaybeByte) -> i32 {
self.buffer.pushback(term);
let len = self.multibyte_char_len(self.buffer.pcur);
if let Some(len) = len {
self.buffer.pcur += len;
self.yyerror1(
DiagnosticMessage::UnknownTypeOfPercentString,
self.current_range().adjust_end(-1),
);
}
Self::END_OF_INPUT
}
fn percent_quotation(&mut self, c: &mut MaybeByte, ptok: usize) -> i32 {
let term: MaybeByte;
let mut paren: Option<u8>;
if c.is_eof() || !c.is_alnum() {
term = c.clone();
if !c.is_ascii() {
return self.percent_unknown(&term);
}
*c = MaybeByte::new('Q');
} else {
term = self.nextc();
if term.is_alnum() {
return self.percent_unknown(&term);
}
}
let mut term = match term.to_option() {
None => {
self.compile_error(
DiagnosticMessage::UnterminatedQuotedString,
self.current_range(),
);
return Self::END_OF_INPUT;
}
Some(term) => term,
};
paren = Some(term);
if term == b'(' {
term = b')';
} else if term == b'[' {
term = b']';
} else if term == b'{' {
term = b'}';
} else if term == b'<' {
term = b'>';
} else {
paren = None
}
self.buffer.ptok = ptok - 1;
match c.to_option() {
Some(b'Q') => {
self.strterm = self.new_strterm(str_dquote, term, paren, None);
Self::tSTRING_BEG
}
Some(b'q') => {
self.strterm = self.new_strterm(str_squote, term, paren, None);
Self::tSTRING_BEG
}
Some(b'W') => {
self.strterm = self.new_strterm(str_dword, term, paren, None);
Self::tWORDS_BEG
}
Some(b'w') => {
self.strterm = self.new_strterm(str_sword, term, paren, None);
Self::tQWORDS_BEG
}
Some(b'I') => {
self.strterm = self.new_strterm(str_dword, term, paren, None);
Self::tSYMBOLS_BEG
}
Some(b'i') => {
self.strterm = self.new_strterm(str_sword, term, paren, None);
Self::tQSYMBOLS_BEG
}
Some(b'x') => {
self.strterm = self.new_strterm(str_xquote, term, paren, None);
Self::tXSTRING_BEG
}
Some(b'r') => {
self.strterm = self.new_strterm(str_regexp, term, paren, None);
Self::tREGEXP_BEG
}
Some(b's') => {
self.strterm = self.new_strterm(str_ssym, term, paren, None);
self.lex_state.set(EXPR_FNAME | EXPR_FITEM);
Self::tSYMBEG
}
_ => {
self.yyerror1(
DiagnosticMessage::UnknownTypeOfPercentString,
self.current_range().adjust_end(-1),
);
Self::END_OF_INPUT
}
}
}
fn parse_percent(&mut self, space_seen: bool, last_state: LexState) -> i32 {
let mut c: MaybeByte;
let ptok = self.buffer.pcur;
if self.lex_state.is_beg() {
c = self.nextc();
return self.percent_quotation(&mut c, ptok);
}
c = self.nextc();
if c == b'=' {
self.set_yylval_id("%=");
self.lex_state.set(EXPR_BEG);
return Self::tOP_ASGN;
}
if self.lex_state.is_spacearg(&c, space_seen)
|| (self.lex_state.is_some(EXPR_FITEM) && c == b's')
{
return self.percent_quotation(&mut c, ptok);
}
self.lex_state.set(if self.lex_state.is_after_operator() {
EXPR_ARG
} else {
EXPR_BEG
});
self.buffer.pushback(&c);
self.warn_balanced(
Self::tPERCENT,
"%%",
"string literal",
&c,
space_seen,
&last_state,
)
}
}