Skip to content
This repository was archived by the owner on Apr 2, 2026. It is now read-only.

Commit cacbd20

Browse files
committed
Implement the None associativity
The infix functions need to return an InfixResult to represent the case when parsing is ambigious due to no associtivity. The parse function will now also return an error if an infix parser inside it's loop return an ambigious result. In order to correctly determinate if an infix parse is ambigious, the operator must be parsed before the associativity is checked. Otherwise a "probe" call by the vector implementaion might return the Ambigious error even if this operator is not present.
1 parent d3595ae commit cacbd20

2 files changed

Lines changed: 62 additions & 41 deletions

File tree

src/pratt.rs

Lines changed: 59 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@
8787
8888
use super::*;
8989

90+
/// The result of calling [`Operator::do_parse_infix`]
91+
pub enum InfixResult<T, E> {
92+
/// Input was parsed
93+
Ok(T),
94+
/// Input could not be parsed
95+
Err(E),
96+
/// Input could not be parsed, because it was ambigious
97+
Ambigious(E),
98+
}
99+
90100
macro_rules! op_check_and_emit {
91101
() => {
92102
#[inline(always)]
@@ -163,7 +173,7 @@ macro_rules! op_check_and_emit {
163173
lhs: (),
164174
min_power: u32,
165175
f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Check, O>,
166-
) -> Result<(), ()> {
176+
) -> InfixResult<(), ()> {
167177
self.do_parse_infix::<Check>(inp, pre_expr, pre_op, lhs, min_power, &f)
168178
}
169179
#[inline(always)]
@@ -180,7 +190,7 @@ macro_rules! op_check_and_emit {
180190
lhs: O,
181191
min_power: u32,
182192
f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Emit, O>,
183-
) -> Result<O, O> {
193+
) -> InfixResult<O, O> {
184194
self.do_parse_infix::<Emit>(inp, pre_expr, pre_op, lhs, min_power, &f)
185195
}
186196
};
@@ -245,11 +255,11 @@ where
245255
lhs: M::Output<O>,
246256
_min_power: u32,
247257
_f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<M, O>,
248-
) -> Result<M::Output<O>, M::Output<O>>
258+
) -> InfixResult<M::Output<O>, M::Output<O>>
249259
where
250260
Self: Sized,
251261
{
252-
Err(lhs)
262+
InfixResult::Err(lhs)
253263
}
254264

255265
#[doc(hidden)]
@@ -293,7 +303,7 @@ where
293303
lhs: (),
294304
min_power: u32,
295305
f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Check, O>,
296-
) -> Result<(), ()>;
306+
) -> InfixResult<(), ()>;
297307
#[doc(hidden)]
298308
fn do_parse_infix_emit<'parse>(
299309
&self,
@@ -303,7 +313,7 @@ where
303313
lhs: O,
304314
min_power: u32,
305315
f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Emit, O>,
306-
) -> Result<O, O>;
316+
) -> InfixResult<O, O>;
307317
}
308318

309319
/// A boxed pratt parser operator. See [`Operator`].
@@ -357,7 +367,7 @@ where
357367
lhs: M::Output<O>,
358368
min_power: u32,
359369
f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<M, O>,
360-
) -> Result<M::Output<O>, M::Output<O>>
370+
) -> InfixResult<M::Output<O>, M::Output<O>>
361371
where
362372
Self: Sized,
363373
{
@@ -415,7 +425,7 @@ where
415425
lhs: (),
416426
min_power: u32,
417427
f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Check, O>,
418-
) -> Result<(), ()> {
428+
) -> InfixResult<(), ()> {
419429
self.0
420430
.do_parse_infix_check(inp, pre_expr, pre_op, lhs, min_power, &f)
421431
}
@@ -428,7 +438,7 @@ where
428438
lhs: O,
429439
min_power: u32,
430440
f: &dyn Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Emit, O>,
431-
) -> Result<O, O> {
441+
) -> InfixResult<O, O> {
432442
self.0
433443
.do_parse_infix_emit(inp, pre_expr, pre_op, lhs, min_power, &f)
434444
}
@@ -560,32 +570,38 @@ where
560570
lhs: M::Output<O>,
561571
min_power: u32,
562572
f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<M, O>,
563-
) -> Result<M::Output<O>, M::Output<O>>
573+
) -> InfixResult<M::Output<O>, M::Output<O>>
564574
where
565575
Self: Sized,
566576
{
567-
if self.associativity.left_power() >= min_power {
568-
match self.op_parser.go::<M>(inp) {
569-
Ok(op) => match f(inp, self.associativity.right_power()) {
570-
Ok(rhs) => Ok(M::combine(
571-
M::combine(lhs, rhs, |lhs, rhs| (lhs, rhs)),
572-
op,
573-
|(lhs, rhs), op| {
574-
(self.fold)(lhs, op, rhs, &mut MapExtra::new(pre_expr, inp))
575-
},
576-
)),
577-
Err(()) => {
578-
inp.rewind(pre_op.clone());
579-
Err(lhs)
577+
match self.op_parser.go::<M>(inp) {
578+
Ok(op) => {
579+
if self.associativity.left_power() > min_power {
580+
match f(inp, self.associativity.right_power()) {
581+
Ok(rhs) => InfixResult::Ok(M::combine(
582+
M::combine(lhs, rhs, |lhs, rhs| (lhs, rhs)),
583+
op,
584+
|(lhs, rhs), op| {
585+
(self.fold)(lhs, op, rhs, &mut MapExtra::new(pre_expr, inp))
586+
},
587+
)),
588+
Err(()) => {
589+
inp.rewind(pre_op.clone());
590+
InfixResult::Err(lhs)
591+
}
580592
}
581-
},
582-
Err(()) => {
593+
} else if self.associativity.left_power() == min_power {
583594
inp.rewind(pre_op.clone());
584-
Err(lhs)
595+
InfixResult::Ambigious(lhs)
596+
} else {
597+
inp.rewind(pre_op.clone());
598+
InfixResult::Err(lhs)
585599
}
586600
}
587-
} else {
588-
Err(lhs)
601+
Err(()) => {
602+
inp.rewind(pre_op.clone());
603+
InfixResult::Err(lhs)
604+
}
589605
}
590606
}
591607

@@ -834,18 +850,19 @@ macro_rules! impl_operator_for_tuple {
834850
mut lhs: M::Output<O>,
835851
min_power: u32,
836852
f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<M, O>,
837-
) -> Result<M::Output<O>, M::Output<O>>
853+
) -> InfixResult<M::Output<O>, M::Output<O>>
838854
where
839855
Self: Sized,
840856
{
841857
let ($($X,)*) = self;
842858
$(
843859
match $X.do_parse_infix::<M>(inp, pre_expr, pre_op, lhs, min_power, f) {
844-
Ok(out) => return Ok(out),
845-
Err(out) => lhs = out,
860+
InfixResult::Ok(out) => return InfixResult::Ok(out),
861+
InfixResult::Err(out) => lhs = out,
862+
InfixResult::Ambigious(out) => return InfixResult::Ambigious(out),
846863
}
847864
)*
848-
Err(lhs)
865+
InfixResult::Err(lhs)
849866
}
850867

851868
op_check_and_emit!();
@@ -910,17 +927,18 @@ where
910927
mut lhs: M::Output<O>,
911928
min_power: u32,
912929
f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<M, O>,
913-
) -> Result<M::Output<O>, M::Output<O>>
930+
) -> InfixResult<M::Output<O>, M::Output<O>>
914931
where
915932
Self: Sized,
916933
{
917934
for op in self {
918935
match op.do_parse_infix::<M>(inp, pre_expr, pre_op, lhs, min_power, f) {
919-
Ok(out) => return Ok(out),
920-
Err(out) => lhs = out,
936+
InfixResult::Ok(out) => return InfixResult::Ok(out),
937+
InfixResult::Err(out) => lhs = out,
938+
InfixResult::Ambigious(out) => return InfixResult::Ambigious(out),
921939
}
922940
}
923-
Err(lhs)
941+
InfixResult::Err(lhs)
924942
}
925943

926944
op_check_and_emit!();
@@ -977,11 +995,14 @@ impl<'src, Atom, Ops> Pratt<Atom, Ops> {
977995
recursive::recurse(|| self.pratt_go::<M, _, _, _>(inp, min_power))
978996
},
979997
) {
980-
Ok(out) => {
998+
InfixResult::Ok(out) => {
981999
lhs = out;
9821000
continue;
9831001
}
984-
Err(out) => lhs = out,
1002+
InfixResult::Err(out) => lhs = out,
1003+
InfixResult::Ambigious(out) => {
1004+
return Err(());
1005+
}
9851006
}
9861007

9871008
inp.rewind(pre_op);

src/private.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub trait Mode {
109109
lhs: Self::Output<O>,
110110
min_power: u32,
111111
f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Self, O>,
112-
) -> Result<Self::Output<O>, Self::Output<O>>
112+
) -> pratt::InfixResult::<Self::Output<O>, Self::Output<O>>
113113
where
114114
Op: pratt::Operator<'src, I, O, E>,
115115
I: Input<'src>,
@@ -229,7 +229,7 @@ impl Mode for Emit {
229229
lhs: Self::Output<O>,
230230
min_power: u32,
231231
f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Self, O>,
232-
) -> Result<Self::Output<O>, Self::Output<O>>
232+
) -> pratt::InfixResult::<Self::Output<O>, Self::Output<O>>
233233
where
234234
Op: pratt::Operator<'src, I, O, E>,
235235
I: Input<'src>,
@@ -340,7 +340,7 @@ impl Mode for Check {
340340
lhs: Self::Output<O>,
341341
min_power: u32,
342342
f: &impl Fn(&mut InputRef<'src, 'parse, I, E>, u32) -> PResult<Self, O>,
343-
) -> Result<Self::Output<O>, Self::Output<O>>
343+
) -> pratt::InfixResult::<Self::Output<O>, Self::Output<O>>
344344
where
345345
Op: pratt::Operator<'src, I, O, E>,
346346
I: Input<'src>,

0 commit comments

Comments
 (0)