Skip to content

Commit 71949f3

Browse files
committed
libfmt_macros: resolve all implicit refs while parsing
1 parent 4a12a70 commit 71949f3

File tree

1 file changed

+46
-11
lines changed

1 file changed

+46
-11
lines changed

src/libfmt_macros/lib.rs

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ pub struct Parser<'a> {
144144
cur: iter::Peekable<str::CharIndices<'a>>,
145145
/// Error messages accumulated during parsing
146146
pub errors: Vec<string::String>,
147+
/// Current position of implicit positional argument pointer
148+
curarg: usize,
147149
}
148150

149151
impl<'a> Iterator for Parser<'a> {
@@ -186,6 +188,7 @@ impl<'a> Parser<'a> {
186188
input: s,
187189
cur: s.char_indices().peekable(),
188190
errors: vec![],
191+
curarg: 0,
189192
}
190193
}
191194

@@ -259,9 +262,41 @@ impl<'a> Parser<'a> {
259262
/// Parses an Argument structure, or what's contained within braces inside
260263
/// the format string
261264
fn argument(&mut self) -> Argument<'a> {
265+
let mut pos = self.position();
266+
let mut format = self.format();
267+
268+
// Resolve CountIsNextParam's into absolute references.
269+
// Current argument's position must be known so this is done after
270+
// format parsing.
271+
// Curiously, currently {:.*} for named arguments is implemented,
272+
// and it consumes a positional arg slot just like a positional {:.*}
273+
// does. The current behavior is reproduced to prevent any
274+
// incompatibilities.
275+
match format.precision {
276+
CountIsNextParam => {
277+
// eat the current implicit arg
278+
let i = self.curarg;
279+
self.curarg += 1;
280+
format.precision = CountIsParam(i);
281+
}
282+
_ => {}
283+
}
284+
285+
// Resolve ArgumentNext's into absolute references.
286+
// This must come after count resolution because we may consume one
287+
// more arg if precision is CountIsNextParam.
288+
match pos {
289+
ArgumentNext => {
290+
let i = self.curarg;
291+
self.curarg += 1;
292+
pos = ArgumentIs(i);
293+
}
294+
_ => {}
295+
}
296+
262297
Argument {
263-
position: self.position(),
264-
format: self.format(),
298+
position: pos,
299+
format: format,
265300
}
266301
}
267302

@@ -487,7 +522,7 @@ mod tests {
487522
fn format_nothing() {
488523
same("{}",
489524
&[NextArgument(Argument {
490-
position: ArgumentNext,
525+
position: ArgumentIs(0),
491526
format: fmtdflt(),
492527
})]);
493528
}
@@ -565,7 +600,7 @@ mod tests {
565600
fn format_counts() {
566601
same("{:10s}",
567602
&[NextArgument(Argument {
568-
position: ArgumentNext,
603+
position: ArgumentIs(0),
569604
format: FormatSpec {
570605
fill: None,
571606
align: AlignUnknown,
@@ -577,7 +612,7 @@ mod tests {
577612
})]);
578613
same("{:10$.10s}",
579614
&[NextArgument(Argument {
580-
position: ArgumentNext,
615+
position: ArgumentIs(0),
581616
format: FormatSpec {
582617
fill: None,
583618
align: AlignUnknown,
@@ -589,19 +624,19 @@ mod tests {
589624
})]);
590625
same("{:.*s}",
591626
&[NextArgument(Argument {
592-
position: ArgumentNext,
627+
position: ArgumentIs(1),
593628
format: FormatSpec {
594629
fill: None,
595630
align: AlignUnknown,
596631
flags: 0,
597-
precision: CountIsNextParam,
632+
precision: CountIsParam(0),
598633
width: CountImplied,
599634
ty: "s",
600635
},
601636
})]);
602637
same("{:.10$s}",
603638
&[NextArgument(Argument {
604-
position: ArgumentNext,
639+
position: ArgumentIs(0),
605640
format: FormatSpec {
606641
fill: None,
607642
align: AlignUnknown,
@@ -613,7 +648,7 @@ mod tests {
613648
})]);
614649
same("{:a$.b$s}",
615650
&[NextArgument(Argument {
616-
position: ArgumentNext,
651+
position: ArgumentIs(0),
617652
format: FormatSpec {
618653
fill: None,
619654
align: AlignUnknown,
@@ -628,7 +663,7 @@ mod tests {
628663
fn format_flags() {
629664
same("{:-}",
630665
&[NextArgument(Argument {
631-
position: ArgumentNext,
666+
position: ArgumentIs(0),
632667
format: FormatSpec {
633668
fill: None,
634669
align: AlignUnknown,
@@ -640,7 +675,7 @@ mod tests {
640675
})]);
641676
same("{:+#}",
642677
&[NextArgument(Argument {
643-
position: ArgumentNext,
678+
position: ArgumentIs(0),
644679
format: FormatSpec {
645680
fill: None,
646681
align: AlignUnknown,

0 commit comments

Comments
 (0)