lexer peekable

This commit is contained in:
Noah Hellman 2022-12-11 09:25:35 +01:00
parent 13850978c1
commit 3c5093f4db
2 changed files with 23 additions and 16 deletions

View file

@ -66,7 +66,7 @@ pub struct Parser<'s> {
events: std::collections::VecDeque<Event>, events: std::collections::VecDeque<Event>,
span: Span, span: Span,
lexer: std::iter::Peekable<lex::Lexer<'s>>, lexer: lex::Lexer<'s>,
verbatim: Option<(Container, usize)>, verbatim: Option<(Container, usize)>,
last: bool, last: bool,
@ -79,7 +79,7 @@ impl<'s> Parser<'s> {
events: std::collections::VecDeque::new(), events: std::collections::VecDeque::new(),
span: Span::new(0, 0), span: Span::new(0, 0),
lexer: lex::Lexer::new("").peekable(), lexer: lex::Lexer::new(""),
verbatim: None, verbatim: None,
last: false, last: false,
@ -87,7 +87,7 @@ impl<'s> Parser<'s> {
} }
pub fn parse(&mut self, src: &'s str, last: bool) { pub fn parse(&mut self, src: &'s str, last: bool) {
self.lexer = lex::Lexer::new(src).peekable(); self.lexer = lex::Lexer::new(src);
if last { if last {
assert!(!self.last); assert!(!self.last);
} }

View file

@ -99,26 +99,33 @@ impl<'s> Lexer<'s> {
} }
} }
fn peek(&mut self) -> char { pub fn peek(&mut self) -> Option<&Token> {
if self.next.is_none() {
self.next = self.token();
}
self.next.as_ref()
}
fn peek_char(&mut self) -> char {
self.chars.clone().next().unwrap_or(EOF) self.chars.clone().next().unwrap_or(EOF)
} }
fn eat(&mut self) -> Option<char> { fn eat_char(&mut self) -> Option<char> {
let c = self.chars.next(); let c = self.chars.next();
self.len += c.map_or(0, char::len_utf8); self.len += c.map_or(0, char::len_utf8);
c c
} }
fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) {
while predicate(self.peek()) { while predicate(self.peek_char()) {
self.eat(); self.eat_char();
} }
} }
fn token(&mut self) -> Option<Token> { fn token(&mut self) -> Option<Token> {
self.len = 0; self.len = 0;
let first = self.eat()?; let first = self.eat_char()?;
let escape = self.escape; let escape = self.escape;
@ -128,14 +135,14 @@ impl<'s> Lexer<'s> {
&& matches!(first, '\t' | ' ') && matches!(first, '\t' | ' ')
&& self.chars.clone().find(|c| !matches!(c, ' ' | '\t')) == Some('\n') => && self.chars.clone().find(|c| !matches!(c, ' ' | '\t')) == Some('\n') =>
{ {
while self.eat() != Some('\n') {} while self.eat_char() != Some('\n') {}
Hardbreak Hardbreak
} }
_ if escape && first == ' ' => Nbsp, _ if escape && first == ' ' => Nbsp,
_ if escape => Text, _ if escape => Text,
'\\' => { '\\' => {
let next = self.peek(); let next = self.peek_char();
if next.is_whitespace() || next.is_ascii_punctuation() { if next.is_whitespace() || next.is_ascii_punctuation() {
self.escape = true; self.escape = true;
Escape Escape
@ -155,7 +162,7 @@ impl<'s> Lexer<'s> {
'[' => Open(Bracket), '[' => Open(Bracket),
']' => Close(Bracket), ']' => Close(Bracket),
'{' => { '{' => {
let explicit = match self.peek() { let explicit = match self.peek_char() {
'*' => Some(Open(BraceAsterisk)), '*' => Some(Open(BraceAsterisk)),
'^' => Some(Open(BraceCaret)), '^' => Some(Open(BraceCaret)),
'=' => Some(Open(BraceEqual)), '=' => Some(Open(BraceEqual)),
@ -166,7 +173,7 @@ impl<'s> Lexer<'s> {
_ => None, _ => None,
}; };
if let Some(exp) = explicit { if let Some(exp) = explicit {
self.eat(); self.eat_char();
exp exp
} else { } else {
Open(Brace) Open(Brace)
@ -180,8 +187,8 @@ impl<'s> Lexer<'s> {
'~' => self.maybe_eat_close_brace(Tilde, BraceTilde), '~' => self.maybe_eat_close_brace(Tilde, BraceTilde),
'_' => self.maybe_eat_close_brace(Underscore, BraceUnderscore), '_' => self.maybe_eat_close_brace(Underscore, BraceUnderscore),
'-' => { '-' => {
if self.peek() == '}' { if self.peek_char() == '}' {
self.eat(); self.eat_char();
Close(BraceHyphen) Close(BraceHyphen)
} else { } else {
self.eat_seq(Hyphen) self.eat_seq(Hyphen)
@ -226,8 +233,8 @@ impl<'s> Lexer<'s> {
} }
fn maybe_eat_close_brace(&mut self, s: Symbol, d: Delimiter) -> Kind { fn maybe_eat_close_brace(&mut self, s: Symbol, d: Delimiter) -> Kind {
if self.peek() == '}' { if self.peek_char() == '}' {
self.eat(); self.eat_char();
Close(d) Close(d)
} else { } else {
Sym(s) Sym(s)