/* lexer/src/lib.rs * Eryn Wells */ mod chars; mod error; mod states; mod token; pub use error::Error; pub use token::{Lex, Token}; use std::iter::Peekable; use states::*; pub type Result = std::result::Result; pub struct Lexer where T: Iterator { input: Peekable, line: usize, offset: usize, } impl Lexer where T: Iterator { pub fn new(input: T) -> Lexer { Lexer { input: input.peekable(), line: 0, offset: 0 } } } impl Lexer where T: Iterator { fn handle_whitespace(&mut self, c: char) { if c == '\n' { self.line += 1; self.offset = 0; } else { self.offset += 1; } } } impl Iterator for Lexer where T: Iterator { type Item = Result; fn next(&mut self) -> Option { let mut buffer = String::new(); let mut state: Box = Box::new(states::Begin{}); let mut out: Option = None; loop { let peek = self.input.peek().map(char::clone); println!("lexing {:?} in state {:?}, buffer = {:?}", peek, state, buffer); match peek { // TODO: Give the current state a chance to react. None => match state.none() { Ok(None) => break, Ok(Some(token)) => { out = Some(Ok(Lex::new(token, &buffer, self.line, self.offset))); break; }, Err(msg) => panic!("{}", msg) }, Some(c) => { let result = state.lex(c); match result { StateResult::Continue => { buffer.push(c); self.input.next(); }, StateResult::Advance { to } => { buffer.push(c); self.input.next(); state = to; }, StateResult::Emit(token, resume) => { if resume == Resume::AtNext { buffer.push(c); self.input.next(); } out = Some(Ok(Lex::new(token, &buffer, self.line, self.offset))); break; }, StateResult::Fail { msg } => { panic!("{}", msg); } } } } } out } }