mirror of
https://github.com/Noratrieb/mono-fmt.git
synced 2026-01-16 16:25:07 +01:00
finish trying to write the new perser
This commit is contained in:
parent
34155bcd48
commit
a96b97f5de
4 changed files with 142 additions and 27 deletions
|
|
@ -65,9 +65,9 @@ impl std::fmt::Debug for FmtPart {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Literal(arg0) => f.debug_tuple("Literal").field(arg0).finish(),
|
Self::Literal(arg0) => f.debug_tuple("Literal").field(arg0).finish(),
|
||||||
Self::Debug(arg0) => f.debug_tuple("Debug").finish(),
|
Self::Debug(_) => f.debug_tuple("Debug").finish(),
|
||||||
Self::Display(arg0) => f.debug_tuple("Display").finish(),
|
Self::Display(_) => f.debug_tuple("Display").finish(),
|
||||||
Self::Advanced(arg0, arg1) => f.debug_tuple("Advanced").field(arg0).finish(),
|
Self::Advanced(arg0, _) => f.debug_tuple("Advanced").field(arg0).finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +234,9 @@ impl ToTokens for FmtPart {
|
||||||
pub fn format_args(tokens: TokenStream) -> TokenStream {
|
pub fn format_args(tokens: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(tokens as Input);
|
let input = parse_macro_input!(tokens as Input);
|
||||||
|
|
||||||
parser::FmtSpecParser::new(&mut input.format_str.chars().peekable()).parse();
|
if false {
|
||||||
|
parser::FmtSpecParser::new(&mut input.format_str.chars().peekable()).parse().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let formatter = Formatter {
|
let formatter = Formatter {
|
||||||
string: input.format_str.chars().peekable(),
|
string: input.format_str.chars().peekable(),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,27 @@
|
||||||
use std::{iter::Peekable, str::Chars};
|
use std::{iter::Peekable, str::Chars};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Default)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Alignment {
|
||||||
|
Left,
|
||||||
|
Center,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Alignment {
|
||||||
|
fn from_char(char: char) -> Result<Self, ()> {
|
||||||
|
match char {
|
||||||
|
'<' => Ok(Self::Left),
|
||||||
|
'^' => Ok(Self::Center),
|
||||||
|
'>' => Ok(Self::Right),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Align {
|
pub struct Align {
|
||||||
amount: usize,
|
kind: Alignment,
|
||||||
char: Option<char>,
|
fill: Option<char>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Default)]
|
#[derive(Debug, PartialEq, Default)]
|
||||||
|
|
@ -24,6 +42,12 @@ pub enum FmtType {
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum Precision {
|
||||||
|
Num(usize),
|
||||||
|
Asterisk,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Default)]
|
#[derive(Debug, PartialEq, Default)]
|
||||||
pub struct FmtSpec {
|
pub struct FmtSpec {
|
||||||
arg: Argument,
|
arg: Argument,
|
||||||
|
|
@ -32,12 +56,13 @@ pub struct FmtSpec {
|
||||||
alternate: bool,
|
alternate: bool,
|
||||||
zero: bool,
|
zero: bool,
|
||||||
width: Option<usize>,
|
width: Option<usize>,
|
||||||
precision: Option<usize>,
|
precision: Option<Precision>,
|
||||||
kind: FmtType,
|
kind: FmtType,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FmtSpecParser<'a> {
|
pub struct FmtSpecParser<'a> {
|
||||||
chars: &'a mut Peekable<Chars<'a>>,
|
chars: &'a mut Peekable<Chars<'a>>,
|
||||||
|
/// The last state of the parser.
|
||||||
state: State,
|
state: State,
|
||||||
argument: FmtSpec,
|
argument: FmtSpec,
|
||||||
}
|
}
|
||||||
|
|
@ -47,13 +72,12 @@ enum State {
|
||||||
Initial,
|
Initial,
|
||||||
Argument,
|
Argument,
|
||||||
// : here
|
// : here
|
||||||
Fill,
|
|
||||||
Align,
|
Align,
|
||||||
Sign,
|
Sign,
|
||||||
|
Alternate,
|
||||||
Zero,
|
Zero,
|
||||||
Width,
|
Width,
|
||||||
Precision,
|
Precision,
|
||||||
Type,
|
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,21 +113,33 @@ impl<'a> FmtSpecParser<'a> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eat_until(&mut self, char: char) -> Option<String> {
|
fn expect(&mut self, char: char) -> Result<(), ()> {
|
||||||
|
if !self.eat(char) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eat_until(&mut self, should_stop: impl Fn(char) -> bool) -> Option<String> {
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
let mut has_char = false;
|
let mut has_char = false;
|
||||||
while self.peek() != Some(char) {
|
// let_chains would be neat here
|
||||||
self.next();
|
while self.peek().is_some() && !should_stop(self.peek().unwrap()) {
|
||||||
string.push(char);
|
let next = self.next().unwrap();
|
||||||
|
string.push(next);
|
||||||
has_char = true;
|
has_char = true;
|
||||||
}
|
}
|
||||||
has_char.then_some(string)
|
has_char.then_some(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eat_until_match(&mut self, char: char) -> Option<String> {
|
||||||
|
self.eat_until(|c| c == char)
|
||||||
|
}
|
||||||
|
|
||||||
fn step(&mut self) -> Result<(), ()> {
|
fn step(&mut self) -> Result<(), ()> {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::Initial => {
|
State::Initial => {
|
||||||
let argument = if let Some(arg) = self.eat_until(':') {
|
let argument = if let Some(arg) = self.eat_until_match(':') {
|
||||||
if let Ok(num) = arg.parse() {
|
if let Ok(num) = arg.parse() {
|
||||||
Argument::PositionalExplicit(num)
|
Argument::PositionalExplicit(num)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -119,18 +155,94 @@ impl<'a> FmtSpecParser<'a> {
|
||||||
if !self.eat(':') {
|
if !self.eat(':') {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
State::Argument => todo!(),
|
State::Argument => match self.next().ok_or(())? {
|
||||||
State::Fill => todo!(),
|
c @ ('>' | '^' | '<') => {
|
||||||
State::Align => todo!(),
|
self.argument.align = Some(Align {
|
||||||
State::Sign => todo!(),
|
kind: Alignment::from_char(c)?,
|
||||||
State::Zero => todo!(),
|
fill: None,
|
||||||
State::Width => todo!(),
|
});
|
||||||
State::Precision => todo!(),
|
self.state = State::Align;
|
||||||
State::Type => todo!(),
|
}
|
||||||
|
other => {
|
||||||
|
if let Some(c @ ('>' | '^' | '<')) = self.peek() {
|
||||||
|
self.argument.align = Some(Align {
|
||||||
|
kind: Alignment::from_char(c).unwrap(),
|
||||||
|
fill: Some(other),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state = State::Align;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State::Align => {
|
||||||
|
if let Some(c @ ('+' | '-')) = self.peek() {
|
||||||
|
self.next();
|
||||||
|
self.argument.sign = Some(c);
|
||||||
|
}
|
||||||
|
self.state = State::Sign;
|
||||||
|
}
|
||||||
|
State::Sign => {
|
||||||
|
if self.eat('#') {
|
||||||
|
self.argument.alternate = true;
|
||||||
|
}
|
||||||
|
self.state = State::Alternate;
|
||||||
|
}
|
||||||
|
State::Alternate => {
|
||||||
|
if self.eat('0') {
|
||||||
|
self.argument.zero = true;
|
||||||
|
}
|
||||||
|
self.state = State::Zero;
|
||||||
|
}
|
||||||
|
State::Zero => {
|
||||||
|
if let Some(width) = self.eat_until(|c| !c.is_ascii_digit()) {
|
||||||
|
let width = width.parse().map_err(|_| ())?;
|
||||||
|
self.argument.width = Some(width);
|
||||||
|
}
|
||||||
|
self.state = State::Width;
|
||||||
|
}
|
||||||
|
State::Width => {
|
||||||
|
if self.eat('.') {
|
||||||
|
if let Some(precision) = self.eat_until(|c| c != '*' && !c.is_ascii_digit()) {
|
||||||
|
let precision = if precision == "*" {
|
||||||
|
Precision::Asterisk
|
||||||
|
} else {
|
||||||
|
Precision::Num(precision.parse().map_err(|_| ())?)
|
||||||
|
};
|
||||||
|
self.argument.precision = Some(precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.state = State::Precision;
|
||||||
|
}
|
||||||
|
State::Precision => match self.next() {
|
||||||
|
Some('?') => {
|
||||||
|
self.argument.kind = FmtType::Debug;
|
||||||
|
self.expect('}')?;
|
||||||
|
}
|
||||||
|
Some('x') => {
|
||||||
|
self.expect('?')?;
|
||||||
|
self.argument.kind = FmtType::LowerHex;
|
||||||
|
self.expect('}')?;
|
||||||
|
}
|
||||||
|
Some('X') => {
|
||||||
|
self.expect('?')?;
|
||||||
|
self.argument.kind = FmtType::UpperHex;
|
||||||
|
self.expect('}')?;
|
||||||
|
}
|
||||||
|
Some('}') | None => {}
|
||||||
|
Some(other) => {
|
||||||
|
if let Some(kind) = self.eat_until(|c| c == '}') {
|
||||||
|
self.argument.kind = FmtType::Other(format!("{other}{kind}"));
|
||||||
|
self.expect('}')?;
|
||||||
|
} else {
|
||||||
|
self.argument.kind = FmtType::Default;
|
||||||
|
self.expect('}')?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
State::Done => unreachable!(),
|
State::Done => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ pub fn ConstWidthArg<T, const WIDTH: usize>(value: T) -> ConstWidthArg<T, WIDTH>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Display, const WIDTH: usize> Arguments for ConstWidthArg<T, WIDTH> {
|
impl<T: Display, const WIDTH: usize> Arguments for ConstWidthArg<T, WIDTH> {
|
||||||
fn fmt<W: Write, O: FmtOpts>(&self, f: &mut Formatter<W, O>) -> Result {
|
fn fmt<W: Write, O: FmtOpts>(&self, _: &mut Formatter<W, O>) -> Result {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
// for the test macro expansion
|
// for the test macro expansion
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate self as mono_fmt;
|
extern crate self as mono_fmt;
|
||||||
|
|
@ -7,7 +9,6 @@ mod opts;
|
||||||
mod write;
|
mod write;
|
||||||
|
|
||||||
pub use mono_fmt_macro::format_args;
|
pub use mono_fmt_macro::format_args;
|
||||||
use opts::{WithAlternate, WithCenterAlign, WithFill, WithLeftAlign, WithRightAlign, WithWidth};
|
|
||||||
|
|
||||||
pub use crate::args::Arguments;
|
pub use crate::args::Arguments;
|
||||||
pub use crate::opts::FmtOpts;
|
pub use crate::opts::FmtOpts;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue