Struct orecc_front::token_reader::TokenReader
source · pub struct TokenReader {
pub cursor: usize,
/* private fields */
}Expand description
A simple character reader that is useful for creating lexers
Fields§
§cursor: usizeA cursor. Just a byte index, useful for spanning and then codespan_reporting
Implementations§
source§impl TokenReader
impl TokenReader
sourcepub fn new(source: Rc<str>) -> Self
pub fn new(source: Rc<str>) -> Self
Create new TokenReader. Just requires a source as Rc
Examples found in repository?
examples/simple_c_lexer.rs (line 15)
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
pub fn main() {
let args = std::env::args().collect::<Vec<_>>();
if args.len() != 2 {
eprintln!("Usage: cargo run --example simple_c_lexer -- sample.c");
return;
}
let code = std::fs::read_to_string(&args[1]).unwrap();
let mut codebase = Codebase::new();
let key = codebase.add(args[1].clone(), code);
let mut reader = TokenReader::new(codebase.get(key).unwrap().source().clone());
while let Some(char) = reader.next_char() {
if chars::is_digit(char) {
// * Number
println!("Number {}", reader.next_token(chars::is_digit, char));
} else if chars::is_ident_start(char) {
// * Identifier
println!(
"Ident {}",
reader.next_token(chars::is_ident_continue, char)
);
} else if char == '"' {
// * String
let mut string = String::new();
loop {
match reader.next_char() {
// Escape sequences
Some('\\') => match reader.next_char() {
Some('n') => string.push('\n'),
Some(char) => string.push(char),
None => codebase.emit( // Technically won't happen
Diagnostic::error()
.with_message("expected escape code")
.with_labels(vec![Label::primary(
key,
reader.cursor..reader.cursor + 1,
)
.with_message("here")]),
),
},
// Quote
Some('"') => break,
// Char
Some(char) if char != '\n' => string.push(char),
_ => {
codebase.emit(
Diagnostic::error()
.with_message("unterminated string")
.with_labels(vec![Label::primary(
key,
reader.cursor..reader.cursor + 1,
)
.with_message("here")]),
);
break;
}
}
}
println!("String {:?}", string);
} else if ['(', ')', '{', '}', ';'].contains(&char) {
// * Operator
println!("Operator {}", char);
}
}
}sourcepub fn next_char(&mut self) -> Option<char>
pub fn next_char(&mut self) -> Option<char>
Peek a char, return it and move cursor forward
Examples found in repository?
examples/simple_c_lexer.rs (line 16)
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
pub fn main() {
let args = std::env::args().collect::<Vec<_>>();
if args.len() != 2 {
eprintln!("Usage: cargo run --example simple_c_lexer -- sample.c");
return;
}
let code = std::fs::read_to_string(&args[1]).unwrap();
let mut codebase = Codebase::new();
let key = codebase.add(args[1].clone(), code);
let mut reader = TokenReader::new(codebase.get(key).unwrap().source().clone());
while let Some(char) = reader.next_char() {
if chars::is_digit(char) {
// * Number
println!("Number {}", reader.next_token(chars::is_digit, char));
} else if chars::is_ident_start(char) {
// * Identifier
println!(
"Ident {}",
reader.next_token(chars::is_ident_continue, char)
);
} else if char == '"' {
// * String
let mut string = String::new();
loop {
match reader.next_char() {
// Escape sequences
Some('\\') => match reader.next_char() {
Some('n') => string.push('\n'),
Some(char) => string.push(char),
None => codebase.emit( // Technically won't happen
Diagnostic::error()
.with_message("expected escape code")
.with_labels(vec![Label::primary(
key,
reader.cursor..reader.cursor + 1,
)
.with_message("here")]),
),
},
// Quote
Some('"') => break,
// Char
Some(char) if char != '\n' => string.push(char),
_ => {
codebase.emit(
Diagnostic::error()
.with_message("unterminated string")
.with_labels(vec![Label::primary(
key,
reader.cursor..reader.cursor + 1,
)
.with_message("here")]),
);
break;
}
}
}
println!("String {:?}", string);
} else if ['(', ')', '{', '}', ';'].contains(&char) {
// * Operator
println!("Operator {}", char);
}
}
}sourcepub fn next_char_if(&mut self, pred: impl FnOnce(char) -> bool) -> Option<char>
pub fn next_char_if(&mut self, pred: impl FnOnce(char) -> bool) -> Option<char>
Self::next_char() but advances if predicate
sourcepub fn next_token(
&mut self,
pred: impl Fn(char) -> bool,
prefix: char
) -> String
pub fn next_token( &mut self, pred: impl Fn(char) -> bool, prefix: char ) -> String
Takes characters and adds then to the buffer while predicate
Examples found in repository?
examples/simple_c_lexer.rs (line 19)
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
pub fn main() {
let args = std::env::args().collect::<Vec<_>>();
if args.len() != 2 {
eprintln!("Usage: cargo run --example simple_c_lexer -- sample.c");
return;
}
let code = std::fs::read_to_string(&args[1]).unwrap();
let mut codebase = Codebase::new();
let key = codebase.add(args[1].clone(), code);
let mut reader = TokenReader::new(codebase.get(key).unwrap().source().clone());
while let Some(char) = reader.next_char() {
if chars::is_digit(char) {
// * Number
println!("Number {}", reader.next_token(chars::is_digit, char));
} else if chars::is_ident_start(char) {
// * Identifier
println!(
"Ident {}",
reader.next_token(chars::is_ident_continue, char)
);
} else if char == '"' {
// * String
let mut string = String::new();
loop {
match reader.next_char() {
// Escape sequences
Some('\\') => match reader.next_char() {
Some('n') => string.push('\n'),
Some(char) => string.push(char),
None => codebase.emit( // Technically won't happen
Diagnostic::error()
.with_message("expected escape code")
.with_labels(vec![Label::primary(
key,
reader.cursor..reader.cursor + 1,
)
.with_message("here")]),
),
},
// Quote
Some('"') => break,
// Char
Some(char) if char != '\n' => string.push(char),
_ => {
codebase.emit(
Diagnostic::error()
.with_message("unterminated string")
.with_labels(vec![Label::primary(
key,
reader.cursor..reader.cursor + 1,
)
.with_message("here")]),
);
break;
}
}
}
println!("String {:?}", string);
} else if ['(', ')', '{', '}', ';'].contains(&char) {
// * Operator
println!("Operator {}", char);
}
}
}Auto Trait Implementations§
impl RefUnwindSafe for TokenReader
impl !Send for TokenReader
impl !Sync for TokenReader
impl Unpin for TokenReader
impl UnwindSafe for TokenReader
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more