tree-sitter/cli/generate/src/tables.rs

168 lines
4.7 KiB
Rust
Raw Normal View History

use std::collections::BTreeMap;
2024-04-09 13:35:08 -04:00
use super::{
nfa::CharacterSet,
rules::{Alias, Symbol, TokenSet},
};
2024-02-04 01:30:33 -05:00
pub type ProductionInfoId = usize;
pub type ParseStateId = usize;
pub type LexStateId = usize;
2018-12-05 12:50:12 -08:00
use std::hash::BuildHasherDefault;
use indexmap::IndexMap;
use rustc_hash::FxHasher;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2024-02-04 01:30:33 -05:00
pub enum ParseAction {
2018-12-05 12:50:12 -08:00
Accept,
Shift {
state: ParseStateId,
is_repetition: bool,
},
2018-12-05 12:50:12 -08:00
ShiftExtra,
Recover,
Reduce {
symbol: Symbol,
child_count: usize,
dynamic_precedence: i32,
2019-02-12 11:06:18 -08:00
production_id: ProductionInfoId,
2018-12-29 13:57:34 -08:00
},
2018-12-05 12:50:12 -08:00
}
2019-10-21 13:31:49 -07:00
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2024-02-04 01:30:33 -05:00
pub enum GotoAction {
2019-10-21 13:31:49 -07:00
Goto(ParseStateId),
ShiftExtra,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2024-02-04 01:30:33 -05:00
pub struct ParseTableEntry {
pub actions: Vec<ParseAction>,
pub reusable: bool,
2018-12-05 12:50:12 -08:00
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
2024-02-04 01:30:33 -05:00
pub struct ParseState {
pub id: ParseStateId,
pub terminal_entries: IndexMap<Symbol, ParseTableEntry, BuildHasherDefault<FxHasher>>,
pub nonterminal_entries: IndexMap<Symbol, GotoAction, BuildHasherDefault<FxHasher>>,
pub reserved_words: TokenSet,
2018-12-23 10:16:03 -08:00
pub lex_state_id: usize,
pub external_lex_state_id: usize,
pub core_id: usize,
2018-12-05 12:50:12 -08:00
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2024-02-04 01:30:33 -05:00
pub struct FieldLocation {
pub index: usize,
pub inherited: bool,
}
#[derive(Debug, Default, PartialEq, Eq)]
2024-02-04 01:30:33 -05:00
pub struct ProductionInfo {
pub alias_sequence: Vec<Option<Alias>>,
pub field_map: BTreeMap<String, Vec<FieldLocation>>,
}
#[derive(Debug, Default, PartialEq, Eq)]
2024-02-04 01:30:33 -05:00
pub struct ParseTable {
pub states: Vec<ParseState>,
pub symbols: Vec<Symbol>,
2019-02-12 11:06:18 -08:00
pub production_infos: Vec<ProductionInfo>,
pub max_aliased_production_length: usize,
pub external_lex_states: Vec<TokenSet>,
2018-12-05 12:50:12 -08:00
}
2019-06-20 13:01:28 -07:00
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
2024-02-04 01:30:33 -05:00
pub struct AdvanceAction {
pub state: LexStateId,
pub in_main_token: bool,
2018-12-05 12:50:12 -08:00
}
2019-06-20 13:01:28 -07:00
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
2024-02-04 01:30:33 -05:00
pub struct LexState {
2019-01-03 10:31:14 -08:00
pub accept_action: Option<Symbol>,
pub eof_action: Option<AdvanceAction>,
pub advance_actions: Vec<(CharacterSet, AdvanceAction)>,
2018-12-05 12:50:12 -08:00
}
2024-02-04 01:30:33 -05:00
#[derive(Debug, PartialEq, Eq, Default)]
pub struct LexTable {
pub states: Vec<LexState>,
}
impl ParseTableEntry {
2024-09-27 15:42:38 -04:00
#[must_use]
2024-02-04 01:30:33 -05:00
pub const fn new() -> Self {
Self {
reusable: true,
actions: Vec::new(),
}
}
}
2018-12-29 13:57:34 -08:00
impl ParseState {
pub fn is_end_of_non_terminal_extra(&self) -> bool {
self.terminal_entries
.contains_key(&Symbol::end_of_nonterminal_extra())
}
2024-02-04 01:30:33 -05:00
pub fn referenced_states(&self) -> impl Iterator<Item = ParseStateId> + '_ {
2018-12-29 13:57:34 -08:00
self.terminal_entries
.iter()
.flat_map(|(_, entry)| {
entry.actions.iter().filter_map(|action| match action {
ParseAction::Shift { state, .. } => Some(*state),
_ => None,
})
})
2019-10-21 13:31:49 -07:00
.chain(self.nonterminal_entries.iter().filter_map(|(_, action)| {
if let GotoAction::Goto(state) = action {
Some(*state)
} else {
None
}
}))
2018-12-29 13:57:34 -08:00
}
pub fn update_referenced_states<F>(&mut self, mut f: F)
where
2024-02-04 01:30:33 -05:00
F: FnMut(usize, &Self) -> usize,
2018-12-29 13:57:34 -08:00
{
let mut updates = Vec::new();
for (symbol, entry) in &self.terminal_entries {
for (i, action) in entry.actions.iter().enumerate() {
if let ParseAction::Shift { state, .. } = action {
let result = f(*state, self);
if result != *state {
updates.push((*symbol, i, result));
}
}
}
}
2019-10-21 13:31:49 -07:00
for (symbol, action) in &self.nonterminal_entries {
if let GotoAction::Goto(other_state) = action {
let result = f(*other_state, self);
if result != *other_state {
updates.push((*symbol, 0, result));
}
2018-12-29 13:57:34 -08:00
}
}
for (symbol, action_index, new_state) in updates {
if symbol.is_non_terminal() {
2019-10-21 13:31:49 -07:00
self.nonterminal_entries
.insert(symbol, GotoAction::Goto(new_state));
2018-12-29 13:57:34 -08:00
} else {
let entry = self.terminal_entries.get_mut(&symbol).unwrap();
if let ParseAction::Shift { is_repetition, .. } = entry.actions[action_index] {
entry.actions[action_index] = ParseAction::Shift {
state: new_state,
is_repetition,
};
}
}
}
}
}