Add flag for logging the item set associated with a certain parse state

This commit is contained in:
Max Brunsfeld 2019-01-04 15:26:48 -08:00
parent a0e65018ba
commit 3a727af264
5 changed files with 66 additions and 29 deletions

View file

@ -39,6 +39,7 @@ struct ParseTableBuilder<'a> {
parse_state_queue: VecDeque<ParseStateQueueEntry>,
parse_table: ParseTable,
following_tokens: Vec<LookaheadSet>,
state_ids_to_log: Vec<ParseStateId>,
}
impl<'a> ParseTableBuilder<'a> {
@ -64,29 +65,26 @@ impl<'a> ParseTableBuilder<'a> {
);
while let Some(entry) = self.parse_state_queue.pop_front() {
// info!(
// "state: {}, item set: {}",
// entry.state_id,
// super::item::ParseItemSetDisplay(
// &self.item_sets_by_state_id[entry.state_id],
// self.syntax_grammar,
// self.lexical_grammar,
// )
// );
let item_set = self
.item_set_builder
.transitive_closure(&self.item_sets_by_state_id[entry.state_id]);
// info!(
// "state: {}, closed item set: {}",
// entry.state_id,
// super::item::ParseItemSetDisplay(
// &item_set,
// self.syntax_grammar,
// self.lexical_grammar,
// )
// );
if self.state_ids_to_log.contains(&entry.state_id) {
eprintln!(
"state: {}\n\ninitial item set:\n\n{}closed item set:\n\n{}",
entry.state_id,
super::item::ParseItemSetDisplay(
&self.item_sets_by_state_id[entry.state_id],
self.syntax_grammar,
self.lexical_grammar,
),
super::item::ParseItemSetDisplay(
&item_set,
self.syntax_grammar,
self.lexical_grammar,
)
);
}
self.add_actions(
entry.preceding_symbols,
@ -553,6 +551,7 @@ impl<'a> ParseTableBuilder<'a> {
)
.unwrap();
}
write!(&mut msg, "\n").unwrap();
}
for item in &conflicting_items {
@ -560,7 +559,7 @@ impl<'a> ParseTableBuilder<'a> {
resolution_count += 1;
write!(
&mut msg,
" {}: Specify a higher precedence in `{}` than in the other rules.\n",
" {}: Specify a higher precedence in `{}` than in the other rules.\n",
resolution_count,
self.symbol_name(&Symbol::non_terminal(item.variable_index as usize))
)
@ -571,7 +570,7 @@ impl<'a> ParseTableBuilder<'a> {
resolution_count += 1;
write!(
&mut msg,
" {}: Add a conflict for these rules: ",
" {}: Add a conflict for these rules: ",
resolution_count
)
.unwrap();
@ -714,10 +713,12 @@ pub(crate) fn build_parse_table(
syntax_grammar: &SyntaxGrammar,
lexical_grammar: &LexicalGrammar,
inlines: &InlinedProductionMap,
state_ids_to_log: Vec<usize>,
) -> Result<(ParseTable, Vec<LookaheadSet>)> {
ParseTableBuilder {
syntax_grammar,
lexical_grammar,
state_ids_to_log,
item_set_builder: ParseItemSetBuilder::new(syntax_grammar, lexical_grammar, inlines),
state_ids_by_item_set: HashMap::new(),
item_sets_by_state_id: Vec::new(),

View file

@ -45,7 +45,7 @@ pub(crate) struct ParseItemSet<'a> {
pub(crate) struct ParseItemDisplay<'a>(
pub &'a ParseItem<'a>,
pub &'a SyntaxGrammar,
pub &'a LexicalGrammar
pub &'a LexicalGrammar,
);
pub(crate) struct LookaheadSetDisplay<'a>(&'a LookaheadSet, &'a SyntaxGrammar, &'a LexicalGrammar);
@ -252,6 +252,13 @@ impl<'a> fmt::Display for ParseItemDisplay<'a> {
for (i, step) in self.0.production.steps.iter().enumerate() {
if i == self.0.step_index as usize {
write!(f, "")?;
if step.precedence != 0 || step.associativity.is_some() {
write!(
f,
" (prec {:?} assoc {:?})",
step.precedence, step.associativity
)?;
}
}
write!(f, " ")?;
@ -274,6 +281,15 @@ impl<'a> fmt::Display for ParseItemDisplay<'a> {
if self.0.is_done() {
write!(f, "")?;
if let Some(step) = self.0.production.steps.last() {
if step.precedence != 0 || step.associativity.is_some() {
write!(
f,
" (prec {:?} assoc {:?})",
step.precedence, step.associativity
)?;
}
}
}
Ok(())

View file

@ -24,9 +24,10 @@ pub(crate) fn build_tables(
simple_aliases: &AliasMap,
inlines: &InlinedProductionMap,
minimize: bool,
state_ids_to_log: Vec<usize>,
) -> Result<(ParseTable, LexTable, LexTable, Option<Symbol>)> {
let (mut parse_table, following_tokens) =
build_parse_table(syntax_grammar, lexical_grammar, inlines)?;
build_parse_table(syntax_grammar, lexical_grammar, inlines, state_ids_to_log)?;
let token_conflict_map = TokenConflictMap::new(lexical_grammar, following_tokens);
let coincident_token_index = CoincidentTokenIndex::new(&parse_table, lexical_grammar);
let keywords = identify_keywords(

View file

@ -1,18 +1,24 @@
use crate::build_tables::build_tables;
use crate::error::Result;
use crate::parse_grammar::parse_grammar;
use crate::prepare_grammar::prepare_grammar;
use crate::build_tables::build_tables;
use crate::render::render_c_code;
pub fn generate_parser_for_grammar(input: &str, minimize: bool) -> Result<String> {
pub fn generate_parser_for_grammar(
input: &str,
minimize: bool,
state_ids_to_log: Vec<usize>,
) -> Result<String> {
let input_grammar = parse_grammar(input)?;
let (syntax_grammar, lexical_grammar, inlines, simple_aliases) = prepare_grammar(&input_grammar)?;
let (syntax_grammar, lexical_grammar, inlines, simple_aliases) =
prepare_grammar(&input_grammar)?;
let (parse_table, main_lex_table, keyword_lex_table, keyword_capture_token) = build_tables(
&syntax_grammar,
&lexical_grammar,
&simple_aliases,
&inlines,
minimize
minimize,
state_ids_to_log,
)?;
let c_code = render_c_code(
&input_grammar.name,
@ -22,7 +28,7 @@ pub fn generate_parser_for_grammar(input: &str, minimize: bool) -> Result<String
keyword_capture_token,
syntax_grammar,
lexical_grammar,
simple_aliases
simple_aliases,
);
Ok(c_code)
}

View file

@ -12,6 +12,7 @@ use std::env;
use std::io::Write;
use std::path::PathBuf;
use std::process::{exit, Command, Stdio};
use std::usize;
mod build_tables;
mod error;
@ -41,6 +42,11 @@ fn run() -> error::Result<()> {
SubCommand::with_name("generate")
.about("Generate a parser")
.arg(Arg::with_name("log").long("log"))
.arg(
Arg::with_name("state-ids-to-log")
.long("log-state")
.takes_value(true),
)
.arg(Arg::with_name("no-minimize").long("no-minimize")),
)
.subcommand(
@ -63,10 +69,17 @@ fn run() -> error::Result<()> {
}
let minimize = !matches.is_present("no-minimize");
let state_ids_to_log = matches
.values_of("state-ids-to-log")
.map_or(Vec::new(), |ids| {
ids.filter_map(|id| usize::from_str_radix(id, 10).ok())
.collect()
});
let mut grammar_path = env::current_dir().expect("Failed to read CWD");
grammar_path.push("grammar.js");
let grammar_json = load_js_grammar_file(grammar_path);
let code = generate::generate_parser_for_grammar(&grammar_json, minimize)?;
let code =
generate::generate_parser_for_grammar(&grammar_json, minimize, state_ids_to_log)?;
println!("{}", code);
}