use std::borrow::Cow::Borrowed;
use std::borrow::{Borrow, Cow};
use std::cell::Cell;
use std::rc::Rc;
use crate::atn_simulator::LexerATNSimulatorManager;
use crate::char_stream::CharStream;
use crate::error_listener::{ConsoleErrorListener, ErrorListener};
use crate::errors::ANTLRError;
use crate::int_stream::IntStream;
use crate::lexer_atn_simulator::{ILexerATNSimulator, LexerATNSimulator};
use crate::Arena;
use crate::recognizer::{Actions, Recognizer};
use crate::rule_context::{EmptyNodeKind, EmptyRuleNode};
use crate::token::TOKEN_INVALID_TYPE;
use crate::token_factory::TokenFactory;
use crate::token_source::TokenSource;
use std::ops::{Deref, DerefMut};
pub trait Lexer<'input, 'arena, Input, TF>:
TokenSource<'input, 'arena, TF> + Recognizer<'input, 'arena, TF::Tok>
where
'input: 'arena,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
fn input(&mut self) -> &mut Input;
fn set_channel(&mut self, v: i32);
fn push_mode(&mut self, m: usize);
fn pop_mode(&mut self) -> Option<usize>;
fn set_type(&mut self, t: i32);
fn set_mode(&mut self, m: usize);
fn more(&mut self);
fn skip(&mut self);
#[doc(hidden)]
fn reset(&mut self);
#[doc(hidden)]
fn get_interpreter(&self) -> Option<&'arena LexerATNSimulator<'arena>>;
}
pub trait LexerRecog<'input, 'arena, TF, R>:
Actions<'input, 'arena, R, TF::Tok> + Sized + 'static
where
'input: 'arena,
TF: TokenFactory<'input, 'arena> + 'arena,
R: Recognizer<'input, 'arena, TF::Tok>,
{
fn before_emit(_lexer: &mut R) {}
fn get_rule_names(&self) -> &'static [&'static str];
fn get_literal_names(&self) -> &[Option<&str>];
fn get_symbolic_names(&self) -> &[Option<&str>];
fn get_grammar_file_name(&self) -> &'static str;
fn get_atn_simulator_man(&self) -> &'static LexerATNSimulatorManager;
}
#[allow(missing_docs)]
pub struct BaseLexer<'input, 'arena, Ext, Input, TF>
where
'input: 'arena,
Ext: LexerRecog<'input, 'arena, TF, Self> + 'static,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
pub interpreter: Option<LexerATNSimulator<'arena>>,
pub input: Option<Input>,
recog: Ext,
factory: TF,
error_listeners: Vec<Box<dyn ErrorListener<'input, 'arena, Self, TF::Tok>>>,
pub token_start_char_index: isize,
pub token_start_line: u32,
pub token_start_column: i32,
current_pos: Rc<LexerPosition>,
pub token_type: i32,
pub token: Option<&'arena mut TF::Tok>,
hit_eof: bool,
pub channel: i32,
pub mode_stack: Vec<usize>,
pub mode: usize,
pub text: Option<String>,
}
#[derive(Debug)]
pub(crate) struct LexerPosition {
pub(crate) line: Cell<u32>,
pub(crate) char_position_in_line: Cell<i32>,
}
impl<'input, 'arena, Ext, Input, TF> Deref for BaseLexer<'input, 'arena, Ext, Input, TF>
where
Ext: LexerRecog<'input, 'arena, TF, Self> + 'static,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
type Target = Ext;
fn deref(&self) -> &Self::Target {
&self.recog
}
}
impl<'input, 'arena, Ext, Input, TF> DerefMut for BaseLexer<'input, 'arena, Ext, Input, TF>
where
Ext: LexerRecog<'input, 'arena, TF, Self> + 'static,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.recog
}
}
impl<'input, 'arena, Ext, Input, TF> Recognizer<'input, 'arena, TF::Tok>
for BaseLexer<'input, 'arena, Ext, Input, TF>
where
'input: 'arena,
Ext: LexerRecog<'input, 'arena, TF, Self> + 'static,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
type Node = EmptyNodeKind;
fn sempred(
&mut self,
localctx: Option<&'arena EmptyRuleNode<'input, 'arena, TF::Tok>>,
rule_index: i32,
action_index: i32,
) -> bool {
Ext::sempred(localctx, rule_index, action_index, self)
}
fn action(
&mut self,
localctx: Option<&'arena EmptyRuleNode<'input, 'arena, TF::Tok>>,
rule_index: i32,
action_index: i32,
) {
Ext::action(localctx, rule_index, action_index, self)
}
}
pub const LEXER_DEFAULT_MODE: usize = 0;
pub const LEXER_MORE: i32 = -2;
pub const LEXER_SKIP: i32 = -3;
#[doc(inline)]
pub use super::token::TOKEN_DEFAULT_CHANNEL as LEXER_DEFAULT_TOKEN_CHANNEL;
#[doc(inline)]
pub use super::token::TOKEN_HIDDEN_CHANNEL as LEXER_HIDDEN;
pub(crate) const LEXER_MIN_CHAR_VALUE: i32 = 0x0000;
pub(crate) const LEXER_MAX_CHAR_VALUE: i32 = 0x10FFFF;
impl<'input, 'arena, Ext, Input, TF> BaseLexer<'input, 'arena, Ext, Input, TF>
where
'input: 'arena,
Ext: LexerRecog<'input, 'arena, TF, Self> + 'static,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
fn emit_token(&mut self, token: &'arena mut TF::Tok) {
self.token = Some(token);
}
fn emit(&mut self) {
Ext::before_emit(self);
let stop = self.get_char_index() - 1;
let token = self.factory.create(
Some(self.input.as_mut().unwrap()),
self.token_type,
self.text.take(),
self.channel,
self.token_start_char_index,
stop,
self.token_start_line,
self.token_start_column,
);
self.emit_token(token);
}
fn emit_eof(&mut self) {
let token = self.factory.create(
None::<&mut Input>,
super::int_stream::EOF,
None,
LEXER_DEFAULT_TOKEN_CHANNEL,
self.get_char_index(),
self.get_char_index() - 1,
self.get_line(),
self.get_char_position_in_line(),
);
self.emit_token(token)
}
pub fn get_char_index(&self) -> isize {
self.input.as_ref().unwrap().index()
}
pub fn get_text<'a>(&'a self) -> Cow<'a, str>
where
'input: 'a,
{
self.text
.as_ref()
.map(|it| Borrowed(it.borrow()))
.unwrap_or_else(|| {
self.input
.as_ref()
.unwrap()
.get_text(self.token_start_char_index, self.get_char_index() - 1)
})
}
pub fn set_text(&mut self, _text: impl Into<String>) {
self.text = Some(_text.into());
}
pub fn add_error_listener(
&mut self,
listener: Box<dyn ErrorListener<'input, 'arena, Self, TF::Tok>>,
) {
self.error_listeners.push(listener);
}
pub fn remove_error_listeners(&mut self) {
self.error_listeners.clear();
}
pub fn new_base_lexer(input: Input, recog: Ext, arena: &'arena Arena) -> Self {
let factory = TF::new(arena);
let atn_manager = recog.get_atn_simulator_man();
let interpreter = LexerATNSimulator::new(atn_manager.get_simulator(arena));
let mut lexer = Self {
interpreter: Some(interpreter),
input: Some(input),
recog,
factory,
error_listeners: vec![Box::new(ConsoleErrorListener {})],
token_start_char_index: 0,
token_start_line: 0,
token_start_column: 0,
current_pos: Rc::new(LexerPosition {
line: Cell::new(1),
char_position_in_line: Cell::new(0),
}),
token_type: super::token::TOKEN_INVALID_TYPE,
text: None,
token: None,
hit_eof: false,
channel: super::token::TOKEN_DEFAULT_CHANNEL,
mode_stack: Vec::new(),
mode: self::LEXER_DEFAULT_MODE,
};
let pos = lexer.current_pos.clone();
lexer.interpreter.as_mut().unwrap().current_pos = pos;
lexer
}
pub fn get_interpreter_mut(&mut self) -> &mut LexerATNSimulator<'arena> {
self.interpreter.as_mut().unwrap()
}
}
impl<'input, 'arena, L, Input, TF> TokenSource<'input, 'arena, TF>
for BaseLexer<'input, 'arena, L, Input, TF>
where
'input: 'arena,
L: LexerRecog<'input, 'arena, TF, Self> + 'static,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
#[inline]
#[allow(unused_labels)]
fn next_token(&mut self) -> &'arena mut TF::Tok {
assert!(self.input.is_some());
let _marker = self.input().mark();
'outer: loop {
if self.hit_eof {
self.emit_eof();
break;
}
self.token = None;
self.channel = LEXER_DEFAULT_TOKEN_CHANNEL;
self.token_start_column = self
.interpreter
.as_ref()
.unwrap()
.get_char_position_in_line();
self.token_start_line = self.interpreter.as_ref().unwrap().get_line();
self.text = None;
let index = self.input().index();
self.token_start_char_index = index;
'inner: loop {
self.token_type = TOKEN_INVALID_TYPE;
let mut interpreter = self.interpreter.take().unwrap();
let result = interpreter.match_token(self.mode, self);
self.interpreter = Some(interpreter);
let ttype = result.unwrap_or_else(|err| {
notify_listeners(self, &err);
self.interpreter
.as_mut()
.unwrap()
.recover(err, self.input.as_mut().unwrap());
LEXER_SKIP
});
if self.input().la(1) == super::int_stream::EOF {
self.hit_eof = true;
}
if self.token_type == TOKEN_INVALID_TYPE {
self.token_type = ttype;
}
if self.token_type == LEXER_SKIP {
continue 'outer;
}
if self.token_type != LEXER_MORE {
break;
}
}
if self.token.is_none() {
self.emit();
break;
}
}
self.input().release(_marker);
self.token.take().unwrap()
}
fn get_line(&self) -> u32 {
self.current_pos.line.get()
}
fn get_char_position_in_line(&self) -> i32 {
self.current_pos.char_position_in_line.get()
}
fn get_input_stream(&mut self) -> Option<&mut dyn IntStream> {
self.input.as_mut().map(|x| x as _)
}
fn get_source_name(&self) -> String {
self.input
.as_ref()
.map(|it| it.get_source_name())
.unwrap_or("<none>".to_string())
}
fn get_token_factory(&self) -> &TF {
&self.factory
}
fn get_dfa_string(&self) -> String {
self.get_interpreter()
.unwrap()
.get_dfa_for_mode(LEXER_DEFAULT_MODE)
.to_lexer_string()
}
}
#[cold]
#[inline(never)]
fn notify_listeners<'input, 'arena, L, Input, TF>(
lexer: &mut BaseLexer<'input, 'arena, L, Input, TF>,
e: &ANTLRError,
) where
'input: 'arena,
L: LexerRecog<'input, 'arena, TF, BaseLexer<'input, 'arena, L, Input, TF>> + 'static,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
let inner = lexer
.input
.as_ref()
.unwrap()
.get_text(lexer.token_start_char_index, lexer.get_char_index());
let text = format!("token recognition error at: '{}'", inner);
for listener in lexer.error_listeners.iter() {
listener.syntax_error(
lexer,
None,
lexer.token_start_line,
lexer.token_start_column,
&text,
Some(e),
)
}
}
impl<'input, 'arena, L, Input, TF> Lexer<'input, 'arena, Input, TF>
for BaseLexer<'input, 'arena, L, Input, TF>
where
'input: 'arena,
L: LexerRecog<'input, 'arena, TF, Self> + 'static,
Input: CharStream<'input>,
TF: TokenFactory<'input, 'arena> + 'arena,
{
fn input(&mut self) -> &mut Input {
self.input.as_mut().unwrap()
}
fn set_channel(&mut self, v: i32) {
self.channel = v;
}
fn push_mode(&mut self, m: usize) {
self.mode_stack.push(self.mode);
self.mode = m;
}
fn pop_mode(&mut self) -> Option<usize> {
self.mode_stack.pop().inspect(|&mode| {
self.mode = mode;
})
}
fn set_type(&mut self, t: i32) {
self.token_type = t;
}
fn set_mode(&mut self, m: usize) {
self.mode = m;
}
fn more(&mut self) {
self.set_type(LEXER_MORE)
}
fn skip(&mut self) {
self.set_type(LEXER_SKIP)
}
fn reset(&mut self) {
unimplemented!()
}
fn get_interpreter(&self) -> Option<&'arena LexerATNSimulator<'arena>> {
unsafe { std::mem::transmute(self.interpreter.as_ref()) }
}
}