Use Symbol for named arguments in fmt_macros

This commit is contained in:
Mark Rousskov
2019-06-03 20:47:42 -06:00
parent 7795b155e0
commit dc13072b7b
7 changed files with 79 additions and 61 deletions

View File

@@ -24,6 +24,8 @@ use std::str;
use std::string;
use std::iter;
use syntax_pos::Symbol;
/// A piece is a portion of the format string which represents the next part
/// to emit. These are emitted as a stream by the `Parser` class.
#[derive(Copy, Clone, PartialEq)]
@@ -39,7 +41,7 @@ pub enum Piece<'a> {
#[derive(Copy, Clone, PartialEq)]
pub struct Argument<'a> {
/// Where to find this argument
pub position: Position<'a>,
pub position: Position,
/// How to format the argument
pub format: FormatSpec<'a>,
}
@@ -54,9 +56,9 @@ pub struct FormatSpec<'a> {
/// Packed version of various flags provided
pub flags: u32,
/// The integer precision to use
pub precision: Count<'a>,
pub precision: Count,
/// The string width requested for the resulting format
pub width: Count<'a>,
pub width: Count,
/// The descriptor string representing the name of the format desired for
/// this argument, this can be empty or any number of characters, although
/// it is required to be one word.
@@ -65,16 +67,16 @@ pub struct FormatSpec<'a> {
/// Enum describing where an argument for a format can be located.
#[derive(Copy, Clone, PartialEq)]
pub enum Position<'a> {
pub enum Position {
/// The argument is implied to be located at an index
ArgumentImplicitlyIs(usize),
/// The argument is located at a specific index given in the format
ArgumentIs(usize),
/// The argument has a name.
ArgumentNamed(&'a str),
ArgumentNamed(Symbol),
}
impl Position<'_> {
impl Position {
pub fn index(&self) -> Option<usize> {
match self {
ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
@@ -119,11 +121,11 @@ pub enum Flag {
/// A count is used for the precision and width parameters of an integer, and
/// can reference either an argument or a literal integer.
#[derive(Copy, Clone, PartialEq)]
pub enum Count<'a> {
pub enum Count {
/// The count is specified explicitly.
CountIs(usize),
/// The count is specified by the argument with the given name.
CountIsName(&'a str),
CountIsName(Symbol),
/// The count is specified by the argument at the given index.
CountIsParam(usize),
/// The count is implied and cannot be explicitly specified.
@@ -431,12 +433,14 @@ impl<'a> Parser<'a> {
/// integer index of an argument, a named argument, or a blank string.
/// 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>> {
fn position(&mut self) -> Option<Position> {
if let Some(i) = self.integer() {
Some(ArgumentIs(i))
} else {
match self.cur.peek() {
Some(&(_, c)) if c.is_alphabetic() => Some(ArgumentNamed(self.word())),
Some(&(_, c)) if c.is_alphabetic() => {
Some(ArgumentNamed(Symbol::intern(self.word())))
}
Some(&(pos, c)) if c == '_' => {
let invalid_name = self.string(pos);
self.err_with_note(format!("invalid argument name `{}`", invalid_name),
@@ -444,7 +448,7 @@ impl<'a> Parser<'a> {
"argument names cannot start with an underscore",
self.to_span_index(pos),
self.to_span_index(pos + invalid_name.len()));
Some(ArgumentNamed(invalid_name))
Some(ArgumentNamed(Symbol::intern(invalid_name)))
},
// This is an `ArgumentNext`.
@@ -552,7 +556,7 @@ impl<'a> Parser<'a> {
/// Parses a Count parameter at the current position. This does not check
/// for 'CountIsNextParam' because that is only used in precision, not
/// width.
fn count(&mut self) -> Count<'a> {
fn count(&mut self) -> Count {
if let Some(i) = self.integer() {
if self.consume('$') {
CountIsParam(i)
@@ -566,7 +570,7 @@ impl<'a> Parser<'a> {
self.cur = tmp;
CountImplied
} else if self.consume('$') {
CountIsName(word)
CountIsName(Symbol::intern(word))
} else {
self.cur = tmp;
CountImplied
@@ -756,6 +760,8 @@ mod tests {
}
#[test]
fn format_counts() {
use syntax_pos::{GLOBALS, Globals, edition};
GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || {
same("{:10s}",
&[NextArgument(Argument {
position: ArgumentImplicitlyIs(0),
@@ -811,11 +817,12 @@ mod tests {
fill: None,
align: AlignUnknown,
flags: 0,
precision: CountIsName("b"),
width: CountIsName("a"),
precision: CountIsName(Symbol::intern("b")),
width: CountIsName(Symbol::intern("a")),
ty: "s",
},
})]);
});
}
#[test]
fn format_flags() {