From fe6a69a6266fed74508fd73345ca151cc312f795 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 20 Jun 2019 13:01:28 -0700 Subject: [PATCH] Sort lex states --- .../generate/build_tables/build_lex_table.rs | 33 +++++++++++++++++++ cli/src/generate/tables.rs | 4 +-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/cli/src/generate/build_tables/build_lex_table.rs b/cli/src/generate/build_tables/build_lex_table.rs index 1985badd..96e6cfea 100644 --- a/cli/src/generate/build_tables/build_lex_table.rs +++ b/cli/src/generate/build_tables/build_lex_table.rs @@ -8,6 +8,7 @@ use crate::generate::tables::{AdvanceAction, LexState, LexTable, ParseStateId, P use log::info; use std::collections::hash_map::Entry; use std::collections::{BTreeMap, HashMap, VecDeque}; +use std::mem; pub(crate) fn build_lex_table( parse_table: &mut ParseTable, @@ -79,6 +80,7 @@ pub(crate) fn build_lex_table( if minimize { minimize_lex_table(&mut table, parse_table); + sort_states(&mut table, parse_table); } (table, keyword_lex_table) @@ -327,3 +329,34 @@ fn minimize_lex_table(table: &mut LexTable, parse_table: &mut ParseTable) { result }); } + +fn sort_states(table: &mut LexTable, parse_table: &mut ParseTable) { + // Get a mapping of old state index -> new_state_index + let mut old_ids_by_new_id = (0..table.states.len()).collect::>(); + &old_ids_by_new_id[1..].sort_unstable_by_key(|id| &table.states[*id]); + + // Get the inverse mapping + let mut new_ids_by_old_id = vec![0; old_ids_by_new_id.len()]; + for (id, old_id) in old_ids_by_new_id.iter().enumerate() { + new_ids_by_old_id[*old_id] = id; + } + + // Reorder the parse states and update their references to reflect + // the new ordering. + table.states = old_ids_by_new_id + .iter() + .map(|old_id| { + let mut state = LexState::default(); + mem::swap(&mut state, &mut table.states[*old_id]); + for (_, advance_action) in state.advance_actions.iter_mut() { + advance_action.state = new_ids_by_old_id[advance_action.state]; + } + state + }) + .collect(); + + // Update the parse table's lex state references + for state in parse_table.states.iter_mut() { + state.lex_state_id = new_ids_by_old_id[state.lex_state_id]; + } +} diff --git a/cli/src/generate/tables.rs b/cli/src/generate/tables.rs index e04c4ae2..f7d96556 100644 --- a/cli/src/generate/tables.rs +++ b/cli/src/generate/tables.rs @@ -61,13 +61,13 @@ pub(crate) struct ParseTable { pub max_aliased_production_length: usize, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub(crate) struct AdvanceAction { pub state: LexStateId, pub in_main_token: bool, } -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] pub(crate) struct LexState { pub advance_actions: Vec<(CharacterSet, AdvanceAction)>, pub accept_action: Option,