Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a less fragile Parser API. #114

Merged
merged 8 commits into from
May 14, 2019
7 changes: 7 additions & 0 deletions macros/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,11 @@ testcases![
A("abab") => "1:1-1:5",
A("aba") => "1:1-1:4",
A("b") => r#"1:1: error: expected ["a"]"#;

nested_or {
A = x:"x" { a:"a" | b:"b" };
}:
// FIXME(eddyb) figure out why the output is not `... => A {...}`.
A("xa") => "\
1:1-1:3 => ";
];
48 changes: 18 additions & 30 deletions src/generate/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,7 @@ impl Continuation<'_> {
fn to_inline(&mut self) -> &mut Src {
if let Code::Label(ref label) = self.code {
self.code = Code::Inline(quote!(
c.code = #label;
p.threads.spawn(c, _range);
p.spawn(#label);
));
}

Expand Down Expand Up @@ -584,7 +583,8 @@ macro_rules! thunk {
}

fn pop_saved<F: ContFn>(f: impl FnOnce(Src) -> Thunk<F>) -> Thunk<impl ContFn> {
f(quote!(c.saved.unwrap()))
thunk!(let saved = p.take_saved();)
+ f(quote!(saved))
+ Thunk::new(|mut cont| {
if let Some(&None) = cont.nested_frames.last() {
*cont.nested_frames.last_mut().unwrap() =
Expand All @@ -599,8 +599,8 @@ fn pop_saved<F: ContFn>(f: impl FnOnce(Src) -> Thunk<F>) -> Thunk<impl ContFn> {
})
}

fn push_saved(saved: Src) -> Thunk<impl ContFn> {
thunk!(c.saved = Some(#saved);)
fn push_saved(parse_node_kind: ParseNodeKind) -> Thunk<impl ContFn> {
thunk!(p.save(#parse_node_kind);)
+ Thunk::new(move |mut cont| {
if let Some((ret_label, outer_fn_label)) = cont.nested_frames.pop().unwrap() {
let inner_fn_label = mem::replace(cont.fn_code_label, outer_fn_label);
Expand All @@ -627,15 +627,14 @@ fn call(callee: Rc<CodeLabel>) -> Thunk<impl ContFn> {
Thunk::new(move |mut cont| {
let label = cont.to_label().clone();
cont.code = Code::Inline(quote!(
c.code = #label;
p.call(Call { callee: #callee, range: _range }, c);
p.call(#callee, #label);
));
cont
})
}

fn ret() -> Thunk<impl ContFn> {
thunk!(p.ret(c, _range);)
thunk!(p.ret();)
+ Thunk::new(|mut cont| {
assert!(cont.to_inline().is_empty());
cont
Expand Down Expand Up @@ -749,7 +748,7 @@ fn reify_as(label: Rc<CodeLabel>) -> Thunk<impl ContFn> {
}

fn forest_add_choice(parse_node_kind: &ParseNodeKind, choice: ParseNodeKind) -> Thunk<impl ContFn> {
thunk!(p.forest_add_choice(#parse_node_kind, c.fn_input.subtract_suffix(_range), #choice);)
thunk!(p.forest_add_choice(#parse_node_kind, #choice);)
}

fn concat_and_forest_add(
Expand All @@ -758,18 +757,12 @@ fn concat_and_forest_add(
right: Thunk<impl ContFn>,
parse_node_kind: ParseNodeKind,
) -> Thunk<impl ContFn> {
thunk!(assert_eq!(_range.start(), c.fn_input.start());)
+ left
+ push_saved(quote!(ParseNode {
kind: #left_parse_node_kind,
range: c.fn_input.subtract_suffix(_range),
}))
left + push_saved(left_parse_node_kind)
+ right
+ pop_saved(move |saved| {
thunk!(p.forest_add_split(
#parse_node_kind,
c.fn_input.subtract_suffix(_range),
#saved.range.len(),
#saved,
);)
})
}
Expand Down Expand Up @@ -799,7 +792,7 @@ impl<Pat: Ord + Hash + RustInputPat> RuleGenerateMethods<Pat> for Rule<Pat> {
(Rule::Empty, _) => cont,
(Rule::Eat(pat), _) => {
let pat = pat.rust_matcher();
check(quote!(let Some(_range) = p.input_consume_left(_range, &(#pat)))).apply(cont)
check(quote!(let Some(mut p) = p.input_consume_left(&(#pat)))).apply(cont)
}
(Rule::Call(r), _) => call(Rc::new(CodeLabel::NamedRule(r.clone()))).apply(cont),
(Rule::Concat([left, right]), None) => {
Expand All @@ -817,12 +810,11 @@ impl<Pat: Ord + Hash + RustInputPat> RuleGenerateMethods<Pat> for Rule<Pat> {
))
.apply(cont),
(Rule::Or(cases), Some((rc_self, rules))) => {
(thunk!(assert_eq!(_range.start(), c.fn_input.start());)
+ parallel(ThunkIter(cases.iter().map(|rule| {
let parse_node_kind = rule.parse_node_kind(rules);
rule.generate_parse(Some((rule, rules)))
+ forest_add_choice(&rc_self.parse_node_kind(rules), parse_node_kind)
}))))
(parallel(ThunkIter(cases.iter().map(|rule| {
let parse_node_kind = rule.parse_node_kind(rules);
rule.generate_parse(Some((rule, rules)))
+ forest_add_choice(&rc_self.parse_node_kind(rules), parse_node_kind)
}))))
.apply(cont)
}
(Rule::Opt(rule), _) => {
Expand Down Expand Up @@ -1395,12 +1387,8 @@ where
quote!(impl<I> gll::runtime::CodeStep<I> for _C
where I: gll::runtime::Input<Slice = #rust_slice_ty>,
{
fn step<'i>(
p: &mut gll::runtime::Parser<'i, _C, I>,
mut c: gll::runtime::Continuation<'i, _C>,
_range: gll::runtime::Range<'i>,
) {
match c.code {
fn step<'i>(self, mut p: gll::runtime::Parser<'_, 'i, _C, I>) {
match self {
#(#code_label_arms)*
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/generate/templates/imports.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use gll::runtime::{
nd::Arrow, traverse, Call, CodeLabel, Continuation, ParseNode, ParseNodeKind, ParseNodeShape,
Range,
nd::Arrow, traverse, CodeLabel, ParseNode, ParseNodeKind, ParseNodeShape, Range,
};
use std::any;
use std::fmt;
Expand Down
Loading