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