Add flag for logging the item set associated with a certain parse state
This commit is contained in:
parent
a0e65018ba
commit
3a727af264
5 changed files with 66 additions and 29 deletions
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
15
src/main.rs
15
src/main.rs
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue