-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove token memory allocations allocations from lexer
- Loading branch information
1 parent
8f05e06
commit 186e21c
Showing
12 changed files
with
3,592 additions
and
375 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3,005 changes: 3,005 additions & 0 deletions
3,005
crates/apollo-parser/benches/testdata/alias.graphql
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,131 @@ | ||
use std::str::Chars; | ||
use std::str::CharIndices; | ||
|
||
use crate::Error; | ||
|
||
/// Peekable iterator over a char sequence. | ||
#[derive(Debug, Clone)] | ||
pub(crate) struct Cursor<'a> { | ||
chars: Chars<'a>, | ||
index: usize, | ||
offset: usize, | ||
prev: usize, | ||
source: &'a str, | ||
chars: CharIndices<'a>, | ||
pending: Option<char>, | ||
pub(crate) err: Option<Error>, | ||
} | ||
|
||
impl<'a> Cursor<'a> { | ||
pub(crate) fn new(input: &'a str) -> Cursor<'a> { | ||
Cursor { | ||
chars: input.chars(), | ||
index: 0, | ||
offset: 0, | ||
prev: 0, | ||
pending: None, | ||
source: input, | ||
chars: input.char_indices(), | ||
err: None, | ||
} | ||
} | ||
} | ||
|
||
pub(crate) const EOF_CHAR: char = '\0'; | ||
|
||
impl<'a> Cursor<'a> { | ||
/// Returns nth character relative to the current cursor position. | ||
fn nth_char(&self, n: usize) -> char { | ||
self.chars().nth(n).unwrap_or(EOF_CHAR) | ||
pub(crate) fn index(&self) -> usize { | ||
self.index | ||
} | ||
|
||
fn eof(&self) -> bool { | ||
self.offset == self.source.len() | ||
} | ||
|
||
/// Peeks the next char in input without consuming. | ||
pub(crate) fn first(&self) -> char { | ||
self.nth_char(0) | ||
pub(crate) fn pending(&self) -> bool { | ||
self.pending.is_some() | ||
} | ||
|
||
/// Peeks the second char in input without consuming. | ||
pub(crate) fn second(&self) -> char { | ||
self.nth_char(1) | ||
pub(crate) fn pending_len(&self) -> usize { | ||
self.offset - self.index | ||
} | ||
|
||
/// Moves to the next character. | ||
pub(crate) fn prev_str(&mut self) -> &'a str { | ||
let slice = &self.source[self.index..self.offset]; | ||
|
||
self.index = self.offset; | ||
self.pending = self.source[self.offset..].chars().next(); | ||
|
||
slice | ||
} | ||
|
||
/// Checks if there are chars to consume. | ||
pub(crate) fn is_eof(&self) -> bool { | ||
self.chars.as_str().is_empty() | ||
/// Moves to the next character. | ||
pub(crate) fn current_str(&mut self) -> &'a str { | ||
self.pending = None; | ||
if self.eof() { | ||
return &self.source[self.index..]; | ||
} | ||
let slice = &self.source[self.index..=self.offset]; | ||
|
||
self.index = self.offset; | ||
self.offset = self.offset; | ||
if let Some((pos, next)) = self.chars.next() { | ||
self.index = pos; | ||
self.offset = pos; | ||
self.pending = Some(next); | ||
} | ||
|
||
slice | ||
} | ||
|
||
/// Moves to the next character. | ||
pub(crate) fn bump(&mut self) -> Option<char> { | ||
let c = self.chars.next()?; | ||
if self.pending.is_some() { | ||
return self.pending.take(); | ||
} | ||
|
||
if self.offset == self.source.len() { | ||
return None; | ||
} | ||
|
||
let (pos, c) = self.chars.next()?; | ||
self.prev = self.offset; | ||
self.offset = pos; | ||
|
||
Some(c) | ||
} | ||
|
||
/// Moves to the next character. | ||
pub(crate) fn eatc(&mut self, c: char) -> bool { | ||
if self.pending.is_some() { | ||
panic!("dont call eatc when a character is pending"); | ||
} | ||
|
||
if let Some((pos, c_in)) = self.chars.next() { | ||
self.prev = self.offset; | ||
self.offset = pos; | ||
|
||
if c_in == c { | ||
return true; | ||
} | ||
|
||
self.pending = Some(c_in); | ||
} | ||
|
||
false | ||
} | ||
|
||
/// Get current error object in the cursor. | ||
pub(crate) fn err(&mut self) -> Option<Error> { | ||
self.err.clone() | ||
} | ||
|
||
pub(crate) fn drain(&mut self) -> &'a str{ | ||
self.pending = None; | ||
let start = self.index; | ||
self.index = self.source.len() - 1; | ||
|
||
&self.source[start..=self.index] | ||
} | ||
|
||
/// Add error object to the cursor. | ||
pub(crate) fn add_err(&mut self, err: Error) { | ||
self.err = Some(err) | ||
} | ||
|
||
/// Returns a `Chars` iterator over the remaining characters. | ||
fn chars(&self) -> Chars<'_> { | ||
self.chars.clone() | ||
} | ||
} |
Oops, something went wrong.