Skip to content

Commit

Permalink
Implement basic cut operator
Browse files Browse the repository at this point in the history
  • Loading branch information
DasLixou committed Apr 30, 2024
1 parent ffcead2 commit ba45c47
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 91 deletions.
4 changes: 2 additions & 2 deletions peg-macros/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl<'a> LeftRecursionVisitor<'a> {

LiteralExpr(_) | PatternExpr(_) | MethodExpr(_, _) | FailExpr(_) | MarkerExpr(_) => false,

PositionExpr => true,
PositionExpr | CutExpr => true,
}
}
}
Expand Down Expand Up @@ -273,7 +273,7 @@ impl<'a> LoopNullabilityVisitor<'a> {
}

LiteralExpr(_) | PatternExpr(_) | MethodExpr(_, _) | FailExpr(_) | MarkerExpr(_) => false,
PositionExpr => true,
PositionExpr | CutExpr => true,
}
}
}
1 change: 1 addition & 0 deletions peg-macros/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ pub enum Expr {
levels: Vec<PrecedenceLevel>,
},
MarkerExpr(bool),
CutExpr,
}

impl Expr {
Expand Down
303 changes: 215 additions & 88 deletions peg-macros/grammar.rs

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion peg-macros/grammar.rustpeg
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ rule labeled() -> TaggedExpr
{ TaggedExpr{ name: label, expr: expression } }

rule suffixed() -> SpannedExpr
= e:prefixed() sp:sp() "?" { OptionalExpr(Box::new(e)).at(sp) }
= sp:sp() "~>" { CutExpr.at(sp) }
/ e:prefixed() sp:sp() "?" { OptionalExpr(Box::new(e)).at(sp) }
/ e:prefixed() sp:sp() "**" count:repeatcount() sep:primary() { Repeat { inner: Box::new(e), bound: count, sep: Some(Box::new(sep)) }.at(sp) }
/ e:prefixed() sp:sp() "++" sep:primary() { Repeat { inner: Box::new(e), bound: BoundedRepeat::Plus, sep: Some(Box::new(sep)) }.at(sp )}
/ e:prefixed() sp:sp() "*" count:repeatcount() { Repeat { inner: Box::new(e), bound: count, sep: None }.at(sp) }
Expand Down
7 changes: 7 additions & 0 deletions peg-macros/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ fn ordered_choice(span: Span, mut rs: impl DoubleEndedIterator<Item = TokenStrea
let __choice_res = #preferred;
match __choice_res {
::peg::RuleResult::Matched(__pos, __value) => ::peg::RuleResult::Matched(__pos, __value),
::peg::RuleResult::Failed if __err_state.is_cut => ::peg::RuleResult::Failed,
::peg::RuleResult::Failed => #fallback
}
}}
Expand Down Expand Up @@ -1017,5 +1018,11 @@ fn compile_expr(context: &Context, e: &SpannedExpr, result_used: bool) -> TokenS
MarkerExpr { .. } => {
report_error(span, "`@` is only allowed in `precedence!{}`".to_string())
}
CutExpr => {
quote_spanned!{ span => {
__err_state.is_cut = true;
::peg::RuleResult::Matched(__pos, __pos)
}}
}
}
}
4 changes: 4 additions & 0 deletions peg-runtime/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ pub struct ErrorState {
/// Non-zero => yes, to support nested blocks.
pub suppress_fail: usize,

/// Are we cut from other choices?
pub is_cut: bool,

/// Are we reparsing after a failure? If so, compute and store expected set of all alternative expectations
/// when we are at offset `max_err_pos`.
pub reparsing_on_error: bool,
Expand All @@ -92,6 +95,7 @@ impl ErrorState {
ErrorState {
max_err_pos: initial_pos,
suppress_fail: 0,
is_cut: false,
reparsing_on_error: false,
expected: ExpectedSet {
expected: BTreeSet::new(),
Expand Down
16 changes: 16 additions & 0 deletions tests/run-pass/cut.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
extern crate peg;

peg::parser!( grammar test_grammar() for str {
pub rule cut() -> Option<&'input str>
= "a" ending:$("a") {Some(ending)}
/ "a" ~> ending:$("b") {Some(ending)}
/ "a" ending:$("c") {Some(ending)}
});

use self::test_grammar::*;

fn main() {
assert_eq!(cut("aa"), Ok(Some("a")));
assert_eq!(cut("ab"), Ok(Some("b")));
assert!(cut("ac").is_err());
}

0 comments on commit ba45c47

Please sign in to comment.