mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-14 13:26:21 +02:00
Modularize Tokenizer's iterator for improved readability (#2053)
While learning Rust and going through the course, I realized the exercise solution readability can be improved by adding Tokenizer helper methods to encapsulate the character collecting logic - which slims down iterator's next() method while enhancing clarity.
This commit is contained in:
parent
3d99e1badf
commit
b6343d0522
@ -57,28 +57,34 @@ enum TokenizerError {
|
|||||||
|
|
||||||
struct Tokenizer<'a>(Peekable<Chars<'a>>);
|
struct Tokenizer<'a>(Peekable<Chars<'a>>);
|
||||||
|
|
||||||
|
impl<'a> Tokenizer<'a> {
|
||||||
|
fn collect_number(&mut self, first_char: char) -> Token {
|
||||||
|
let mut num = String::from(first_char);
|
||||||
|
while let Some(&c @ '0'..='9') = self.0.peek() {
|
||||||
|
num.push(c);
|
||||||
|
self.0.next();
|
||||||
|
}
|
||||||
|
Token::Number(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_identifier(&mut self, first_char: char) -> Token {
|
||||||
|
let mut ident = String::from(first_char);
|
||||||
|
while let Some(&c @ ('a'..='z' | '_' | '0'..='9')) = self.0.peek() {
|
||||||
|
ident.push(c);
|
||||||
|
self.0.next();
|
||||||
|
}
|
||||||
|
Token::Identifier(ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for Tokenizer<'a> {
|
impl<'a> Iterator for Tokenizer<'a> {
|
||||||
type Item = Result<Token, TokenizerError>;
|
type Item = Result<Token, TokenizerError>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Result<Token, TokenizerError>> {
|
fn next(&mut self) -> Option<Result<Token, TokenizerError>> {
|
||||||
let c = self.0.next()?;
|
let c = self.0.next()?;
|
||||||
match c {
|
match c {
|
||||||
'0'..='9' => {
|
'0'..='9' => Some(Ok(self.collect_number(c))),
|
||||||
let mut num = String::from(c);
|
'a'..='z' | '_' => Some(Ok(self.collect_identifier(c))),
|
||||||
while let Some(c @ '0'..='9') = self.0.peek() {
|
|
||||||
num.push(*c);
|
|
||||||
self.0.next();
|
|
||||||
}
|
|
||||||
Some(Ok(Token::Number(num)))
|
|
||||||
}
|
|
||||||
'a'..='z' => {
|
|
||||||
let mut ident = String::from(c);
|
|
||||||
while let Some(c @ ('a'..='z' | '_' | '0'..='9')) = self.0.peek() {
|
|
||||||
ident.push(*c);
|
|
||||||
self.0.next();
|
|
||||||
}
|
|
||||||
Some(Ok(Token::Identifier(ident)))
|
|
||||||
}
|
|
||||||
'+' => Some(Ok(Token::Operator(Op::Add))),
|
'+' => Some(Ok(Token::Operator(Op::Add))),
|
||||||
'-' => Some(Ok(Token::Operator(Op::Sub))),
|
'-' => Some(Ok(Token::Operator(Op::Sub))),
|
||||||
_ => Some(Err(TokenizerError::UnexpectedCharacter(c))),
|
_ => Some(Err(TokenizerError::UnexpectedCharacter(c))),
|
||||||
@ -144,28 +150,34 @@ fn tokenize(input: &str) -> Tokenizer {
|
|||||||
|
|
||||||
struct Tokenizer<'a>(Peekable<Chars<'a>>);
|
struct Tokenizer<'a>(Peekable<Chars<'a>>);
|
||||||
|
|
||||||
|
impl<'a> Tokenizer<'a> {
|
||||||
|
fn collect_number(&mut self, first_char: char) -> Token {
|
||||||
|
let mut num = String::from(first_char);
|
||||||
|
while let Some(&c @ '0'..='9') = self.0.peek() {
|
||||||
|
num.push(c);
|
||||||
|
self.0.next();
|
||||||
|
}
|
||||||
|
Token::Number(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_identifier(&mut self, first_char: char) -> Token {
|
||||||
|
let mut ident = String::from(first_char);
|
||||||
|
while let Some(&c @ ('a'..='z' | '_' | '0'..='9')) = self.0.peek() {
|
||||||
|
ident.push(c);
|
||||||
|
self.0.next();
|
||||||
|
}
|
||||||
|
Token::Identifier(ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for Tokenizer<'a> {
|
impl<'a> Iterator for Tokenizer<'a> {
|
||||||
type Item = Token;
|
type Item = Token;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Token> {
|
fn next(&mut self) -> Option<Token> {
|
||||||
let c = self.0.next()?;
|
let c = self.0.next()?;
|
||||||
match c {
|
match c {
|
||||||
'0'..='9' => {
|
'0'..='9' => Some(self.collect_number(c)),
|
||||||
let mut num = String::from(c);
|
'a'..='z' => Some(self.collect_identifier(c)),
|
||||||
while let Some(c @ '0'..='9') = self.0.peek() {
|
|
||||||
num.push(*c);
|
|
||||||
self.0.next();
|
|
||||||
}
|
|
||||||
Some(Token::Number(num))
|
|
||||||
}
|
|
||||||
'a'..='z' => {
|
|
||||||
let mut ident = String::from(c);
|
|
||||||
while let Some(c @ ('a'..='z' | '_' | '0'..='9')) = self.0.peek() {
|
|
||||||
ident.push(*c);
|
|
||||||
self.0.next();
|
|
||||||
}
|
|
||||||
Some(Token::Identifier(ident))
|
|
||||||
}
|
|
||||||
'+' => Some(Token::Operator(Op::Add)),
|
'+' => Some(Token::Operator(Op::Add)),
|
||||||
'-' => Some(Token::Operator(Op::Sub)),
|
'-' => Some(Token::Operator(Op::Sub)),
|
||||||
_ => panic!("Unexpected character {c}"),
|
_ => panic!("Unexpected character {c}"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user