]> git.proxmox.com Git - rustc.git/blobdiff - src/libfmt_macros/lib.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / libfmt_macros / lib.rs
index 07d26cddfdb87ee818d762a511fb5a35040afdd0..e7d401f0929fe1910ec87bc256cbe1d3715d49e1 100644 (file)
@@ -80,8 +80,6 @@ pub struct FormatSpec<'a> {
 /// Enum describing where an argument for a format can be located.
 #[derive(Copy, Clone, PartialEq)]
 pub enum Position<'a> {
-    /// The argument will be in the next position. This is the default.
-    ArgumentNext,
     /// The argument is located at a specific index.
     ArgumentIs(usize),
     /// The argument has a name.
@@ -127,8 +125,6 @@ pub enum Count<'a> {
     CountIsName(&'a str),
     /// The count is specified by the argument at the given index.
     CountIsParam(usize),
-    /// The count is specified by the next parameter.
-    CountIsNextParam,
     /// The count is implied and cannot be explicitly specified.
     CountImplied,
 }
@@ -144,6 +140,8 @@ pub struct Parser<'a> {
     cur: iter::Peekable<str::CharIndices<'a>>,
     /// Error messages accumulated during parsing
     pub errors: Vec<string::String>,
+    /// Current position of implicit positional argument pointer
+    curarg: usize,
 }
 
 impl<'a> Iterator for Parser<'a> {
@@ -186,6 +184,7 @@ impl<'a> Parser<'a> {
             input: s,
             cur: s.char_indices().peekable(),
             errors: vec![],
+            curarg: 0,
         }
     }
 
@@ -259,21 +258,40 @@ impl<'a> Parser<'a> {
     /// Parses an Argument structure, or what's contained within braces inside
     /// the format string
     fn argument(&mut self) -> Argument<'a> {
+        let pos = self.position();
+        let format = self.format();
+
+        // Resolve position after parsing format spec.
+        let pos = match pos {
+            Some(position) => position,
+            None => {
+                let i = self.curarg;
+                self.curarg += 1;
+                ArgumentIs(i)
+            }
+        };
+
         Argument {
-            position: self.position(),
-            format: self.format(),
+            position: pos,
+            format: format,
         }
     }
 
     /// Parses a positional argument for a format. This could either be an
     /// integer index of an argument, a named argument, or a blank string.
-    fn position(&mut self) -> Position<'a> {
+    /// Returns `Some(parsed_position)` if the position is not implicitly
+    /// consuming a macro argument, `None` if it's the case.
+    fn position(&mut self) -> Option<Position<'a>> {
         if let Some(i) = self.integer() {
-            ArgumentIs(i)
+            Some(ArgumentIs(i))
         } else {
             match self.cur.peek() {
-                Some(&(_, c)) if c.is_alphabetic() => ArgumentNamed(self.word()),
-                _ => ArgumentNext,
+                Some(&(_, c)) if c.is_alphabetic() => Some(ArgumentNamed(self.word())),
+
+                // This is an `ArgumentNext`.
+                // Record the fact and do the resolution after parsing the
+                // format spec, to make things like `{:.*}` work.
+                _ => None,
             }
         }
     }
@@ -340,7 +358,11 @@ impl<'a> Parser<'a> {
         }
         if self.consume('.') {
             if self.consume('*') {
-                spec.precision = CountIsNextParam;
+                // Resolve `CountIsNextParam`.
+                // We can do this immediately as `position` is resolved later.
+                let i = self.curarg;
+                self.curarg += 1;
+                spec.precision = CountIsParam(i);
             } else {
                 spec.precision = self.count();
             }
@@ -487,7 +509,7 @@ mod tests {
     fn format_nothing() {
         same("{}",
              &[NextArgument(Argument {
-                   position: ArgumentNext,
+                   position: ArgumentIs(0),
                    format: fmtdflt(),
                })]);
     }
@@ -565,7 +587,7 @@ mod tests {
     fn format_counts() {
         same("{:10s}",
              &[NextArgument(Argument {
-                   position: ArgumentNext,
+                   position: ArgumentIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -577,7 +599,7 @@ mod tests {
                })]);
         same("{:10$.10s}",
              &[NextArgument(Argument {
-                   position: ArgumentNext,
+                   position: ArgumentIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -589,19 +611,19 @@ mod tests {
                })]);
         same("{:.*s}",
              &[NextArgument(Argument {
-                   position: ArgumentNext,
+                   position: ArgumentIs(1),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
                        flags: 0,
-                       precision: CountIsNextParam,
+                       precision: CountIsParam(0),
                        width: CountImplied,
                        ty: "s",
                    },
                })]);
         same("{:.10$s}",
              &[NextArgument(Argument {
-                   position: ArgumentNext,
+                   position: ArgumentIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -613,7 +635,7 @@ mod tests {
                })]);
         same("{:a$.b$s}",
              &[NextArgument(Argument {
-                   position: ArgumentNext,
+                   position: ArgumentIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -628,7 +650,7 @@ mod tests {
     fn format_flags() {
         same("{:-}",
              &[NextArgument(Argument {
-                   position: ArgumentNext,
+                   position: ArgumentIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,
@@ -640,7 +662,7 @@ mod tests {
                })]);
         same("{:+#}",
              &[NextArgument(Argument {
-                   position: ArgumentNext,
+                   position: ArgumentIs(0),
                    format: FormatSpec {
                        fill: None,
                        align: AlignUnknown,