use std::hash::Hash;
use crate::{atn_config_set::ConfigSet, dfa::DFAStateStore, lexer::Lexer};
pub(crate) const LEXER_ACTION_TYPE_CHANNEL: i32 = 0;
pub(crate) const LEXER_ACTION_TYPE_CUSTOM: i32 = 1;
pub(crate) const LEXER_ACTION_TYPE_MODE: i32 = 2;
pub(crate) const LEXER_ACTION_TYPE_MORE: i32 = 3;
pub(crate) const LEXER_ACTION_TYPE_POP_MODE: i32 = 4;
pub(crate) const LEXER_ACTION_TYPE_PUSH_MODE: i32 = 5;
pub(crate) const LEXER_ACTION_TYPE_SKIP: i32 = 6;
pub(crate) const LEXER_ACTION_TYPE_TYPE: i32 = 7;
#[allow(clippy::enum_variant_names)]
#[derive(Clone, Default, Eq, PartialEq, Debug, Hash)]
pub(crate) enum LexerAction<'ephemeral> {
Channel(i32),
Custom {
rule_index: i32,
action_index: i32,
},
Mode(i32),
More,
PopMode,
PushMode(i32),
#[default]
Skip,
Type(i32),
IndexedCustom(&'ephemeral LexerIndexedCustomAction<'ephemeral>),
}
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
pub(crate) struct LexerIndexedCustomAction<'ephemeral> {
pub(crate) offset: isize,
pub(crate) action: LexerAction<'ephemeral>,
}
impl<'ephemeral> LexerAction<'ephemeral> {
pub fn is_position_dependent(&self) -> bool {
matches!(
self,
LexerAction::Custom { .. } | LexerAction::IndexedCustom { .. }
)
}
pub(crate) fn execute<'input, 'arena, Input, TF, L>(&self, lexer: &mut L)
where
'input: 'arena,
L: Lexer<'input, 'arena, Input, TF>,
Input: crate::char_stream::CharStream<'input>,
TF: crate::token_factory::TokenFactory<'input, 'arena> + 'arena,
{
match self {
&LexerAction::Channel(channel) => lexer.set_channel(channel),
&LexerAction::Custom {
rule_index,
action_index,
} => {
lexer.action(None, rule_index, action_index);
}
&LexerAction::Mode(mode) => lexer.set_mode(mode as usize),
&LexerAction::More => lexer.more(),
&LexerAction::PopMode => {
lexer.pop_mode();
}
&LexerAction::PushMode(mode) => lexer.push_mode(mode as usize),
&LexerAction::Skip => lexer.skip(),
&LexerAction::Type(ty) => lexer.set_type(ty),
LexerAction::IndexedCustom(action) => action.action.execute(lexer),
}
}
pub(crate) fn promote<'sim, CS>(&self, dfa: &DFAStateStore<'sim, CS>) -> LexerAction<'sim>
where
CS: ConfigSet<'sim> + 'sim,
{
match self {
LexerAction::IndexedCustom(action)
if dfa.contains_lexer_indexed_custom_action(action) =>
{
unsafe { std::mem::transmute::<Self, LexerAction<'sim>>(self.clone()) }
}
LexerAction::IndexedCustom(action) => {
LexerAction::IndexedCustom(dfa.alloc_lexer_indexed_custom_action(|| {
LexerIndexedCustomAction {
offset: action.offset,
action: action.action.promote(dfa),
}
}))
}
_ => unsafe { std::mem::transmute::<Self, LexerAction<'sim>>(self.clone()) },
}
}
}