Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 35 additions & 7 deletions lrpar/src/lib/ctbuilder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,7 @@ where
let run_parser = match self.yacckind.unwrap() {
YaccKind::Original(YaccOriginalActionKind::GenericParseTree) => {
quote! {
::lrpar::RTParserBuilder::new(&grm, &stable)
::lrpar::RTParserBuilder::new(grm, stable)
.recoverer(#recoverer)
.parse_map(
lexer,
Expand All @@ -1104,7 +1104,7 @@ where
}
YaccKind::Original(YaccOriginalActionKind::NoAction) => {
quote! {
::lrpar::RTParserBuilder::new(&grm, &stable)
::lrpar::RTParserBuilder::new(grm, stable)
.recoverer(#recoverer)
.parse_map(lexer, &|_| (), &|_, _| ()).1
}
Expand Down Expand Up @@ -1145,7 +1145,7 @@ where
#action_fn_parse_param_ty
) -> #actionskind #type_generics
> = ::std::vec![#(&#wrappers,)*];
match ::lrpar::RTParserBuilder::new(&grm, &stable)
match ::lrpar::RTParserBuilder::new(grm, stable)
.recoverer(#recoverer)
.parse_actions(lexer, &actions, #action_fn_parse_param) {
(Some(#actionskind::#action_ident(x)), y) => (Some(x), y),
Expand Down Expand Up @@ -1205,14 +1205,24 @@ where
const __GRM_DATA: &[u8] = &[#(#grm_data,)*];
const __STABLE_DATA: &[u8] = &[#(#stable_data,)*];

fn __lrpar_parser_data() -> &'static ::lrpar::ParserData<#storaget> {
static DATA: ::std::sync::OnceLock<::lrpar::ParserData<#storaget>>
= ::std::sync::OnceLock::new();
DATA.get_or_init(
|| ::lrpar::ctbuilder::_reconstitute(__GRM_DATA, __STABLE_DATA)
)
}

#[allow(dead_code)]
pub fn parse #generics (
lexer: &'lexer dyn ::lrpar::NonStreamingLexer<'input, #lexertypest>,
#parse_fn_parse_param
) -> #parse_fn_return_ty
#where_clause
{
let (grm, stable) = ::lrpar::ctbuilder::_reconstitute(__GRM_DATA, __STABLE_DATA);
let __data = __lrpar_parser_data();
let grm = __data.grm();
let stable = __data.stable();
#run_parser
}
})
Expand Down Expand Up @@ -1601,16 +1611,34 @@ where
}
}

/// Bundles `YaccGrammar` + `StateTable` so that generated parsers can hold
/// them in a `OnceLock` without naming `lrtable` directly.
#[doc(hidden)]
pub struct ParserData<StorageT: Eq + Hash> {
grm: YaccGrammar<StorageT>,
stable: StateTable<StorageT>,
}

impl<StorageT: Eq + Hash> ParserData<StorageT> {
pub fn grm(&self) -> &YaccGrammar<StorageT> {
&self.grm
}

pub fn stable(&self) -> &StateTable<StorageT> {
&self.stable
}
}

/// This function is called by generated files; it exists so that generated files don't require a
/// direct dependency on bincode.
#[doc(hidden)]
pub fn _reconstitute<StorageT: Decode<()> + Hash + PrimInt + Unsigned + 'static>(
pub fn _reconstitute<StorageT: Decode<()> + Eq + Hash + PrimInt + Unsigned + 'static>(
grm_buf: &[u8],
stable_buf: &[u8],
) -> (YaccGrammar<StorageT>, StateTable<StorageT>) {
) -> ParserData<StorageT> {
let (grm, _) = decode_from_slice(grm_buf, bincode::config::standard()).unwrap();
let (stable, _) = decode_from_slice(stable_buf, bincode::config::standard()).unwrap();
(grm, stable)
ParserData { grm, stable }
}

/// An interface to the result of [CTParserBuilder::build()].
Expand Down
2 changes: 1 addition & 1 deletion lrpar/src/lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ pub mod parser;
pub mod test_utils;

pub use crate::{
ctbuilder::{CTParser, CTParserBuilder, RustEdition, Visibility},
ctbuilder::{CTParser, CTParserBuilder, ParserData, RustEdition, Visibility},
lex_api::{LexError, Lexeme, Lexer, LexerTypes, NonStreamingLexer},
parser::{LexParseError, ParseError, ParseRepair, RTParserBuilder, RecoveryKind},
};
Expand Down
28 changes: 11 additions & 17 deletions lrpar/src/lib/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub(super) struct Parser<
{
rcvry_kind: RecoveryKind,
pub(super) grm: &'a YaccGrammar<StorageT>,
pub(super) token_cost: Box<TokenCostFn<'a, StorageT>>,
pub(super) token_cost: TokenCostFn<'a, StorageT>,
pub(super) stable: &'a StateTable<StorageT>,
lexer: &'b dyn NonStreamingLexer<'input, LexerTypesT>,
// In the long term, we should remove the `lexemes` field entirely, as the `NonStreamingLexer` API is
Expand Down Expand Up @@ -176,7 +176,7 @@ where
let psr = Parser {
rcvry_kind,
grm,
token_cost: Box::new(token_cost),
token_cost,
stable,
lexer,
lexemes,
Expand Down Expand Up @@ -274,7 +274,7 @@ where
let psr = Parser {
rcvry_kind,
grm,
token_cost: Box::new(token_cost),
token_cost,
stable,
lexer,
lexemes,
Expand Down Expand Up @@ -970,13 +970,10 @@ where
fterm: &dyn Fn(LexerTypesT::LexemeT) -> Node,
fnonterm: &dyn Fn(RIdx<StorageT>, Vec<Node>) -> Node,
) -> (Option<Node>, Vec<LexParseError<StorageT, LexerTypesT>>) {
let mut lexemes = vec![];
for e in lexer.iter().collect::<Vec<_>>() {
match e {
Ok(l) => lexemes.push(l),
Err(e) => return (None, vec![e.into()]),
}
}
let lexemes = match lexer.iter().collect() {
Ok(lexemes) => lexemes,
Err(e) => return (None, vec![e.into()]),
};
Parser::<
StorageT,
LexerTypesT,
Expand Down Expand Up @@ -1019,13 +1016,10 @@ where
actions: &'a [ActionFn<'a, 'b, 'input, StorageT, LexerTypesT, ActionT, ParamT>],
param: ParamT,
) -> (Option<ActionT>, Vec<LexParseError<StorageT, LexerTypesT>>) {
let mut lexemes = vec![];
for e in lexer.iter().collect::<Vec<_>>() {
match e {
Ok(l) => lexemes.push(l),
Err(e) => return (None, vec![e.into()]),
}
}
let lexemes = match lexer.iter().collect() {
Ok(lexemes) => lexemes,
Err(e) => return (None, vec![e.into()]),
};
Parser::parse_actions(
self.recoverer,
self.grm,
Expand Down