Check for EOF (aka input.next() -> None) and emit what we have before finishing forever
This commit is contained in:
parent
5fe10fe002
commit
28e5814101
1 changed files with 18 additions and 9 deletions
|
@ -12,6 +12,7 @@ enum Resume { Here, AtNext }
|
|||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
enum IterationResult {
|
||||
Finish,
|
||||
Continue,
|
||||
Emit(Token, Resume),
|
||||
Error(String),
|
||||
|
@ -40,31 +41,39 @@ impl<T> Iterator for Lexer<T> where T: Iterator<Item=char> {
|
|||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut buffer = String::new();
|
||||
while let Some(peek) = self.input.peek().map(char::clone) {
|
||||
loop {
|
||||
let peek = self.input.peek().map(char::clone);
|
||||
let result = if buffer.is_empty() {
|
||||
match peek {
|
||||
'(' => self.emit(Token::LeftParen, Resume::AtNext),
|
||||
')' => self.emit(Token::RightParen, Resume::AtNext),
|
||||
c if c.is_whitespace() => IterationResult::Continue,
|
||||
c if c.is_alphabetic() => {
|
||||
Some('(') => self.emit(Token::LeftParen, Resume::AtNext),
|
||||
Some(')') => self.emit(Token::RightParen, Resume::AtNext),
|
||||
Some(c) if c.is_whitespace() => IterationResult::Continue,
|
||||
Some(c) if c.is_alphabetic() => {
|
||||
buffer.push(c);
|
||||
IterationResult::Continue
|
||||
},
|
||||
c => self.fail(format!("Invalid character: {}", c)),
|
||||
Some(c) => self.fail(format!("Invalid character: {}", c)),
|
||||
// We found EOF and there's no pending string, so just finish.
|
||||
None => IterationResult::Finish,
|
||||
}
|
||||
}
|
||||
else {
|
||||
match peek {
|
||||
c if c.is_alphabetic() => {
|
||||
Some(c) if c.is_alphabetic() => {
|
||||
buffer.push(c);
|
||||
IterationResult::Continue
|
||||
}
|
||||
c if c == '(' || c == ')' || c.is_whitespace() =>
|
||||
Some(c) if c == '(' || c == ')' || c.is_whitespace() =>
|
||||
self.emit(Token::Id(buffer.clone()), Resume::Here),
|
||||
c => self.fail(format!("Invalid character: {}", c)),
|
||||
Some(c) => self.fail(format!("Invalid character: {}", c)),
|
||||
// Found EOF. Emit what we have and finish.
|
||||
// Note: the Resume argument doesn't matter in this case since the input
|
||||
// iterator will always be None from here on.
|
||||
None => self.emit(Token::Id(buffer.clone()), Resume::Here),
|
||||
}
|
||||
};
|
||||
match result {
|
||||
IterationResult::Finish => break,
|
||||
IterationResult::Continue => self.input.next(),
|
||||
IterationResult::Emit(token, resume) => {
|
||||
if resume == Resume::AtNext {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue