-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlexer.rs
More file actions
86 lines (67 loc) · 1.81 KB
/
lexer.rs
File metadata and controls
86 lines (67 loc) · 1.81 KB
1
2
3
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//! The lexer and associated types
use logos::Logos;
use std::ops::Range;
use crate::{
errors::{ExprErrorS, LexicalError},
span::Spanned,
};
/// Parse source code in to a list of [`Token`].
pub fn lex(source: &str) -> Vec<Result<(usize, Token, usize), ExprErrorS>> {
let lexer: Lexer<'_> = Lexer::new(&source);
let tokens: Vec<Result<(usize, Token, usize), ExprErrorS>> = lexer.collect::<Vec<_>>();
tokens
}
/// Converts a [`String`] source in to a vector of [`Token`]
#[derive(Debug)]
pub struct Lexer<'a> {
inner: logos::Lexer<'a, Token>,
pending: Option<(usize, Token, usize)>,
}
impl<'a> Lexer<'a> {
pub fn new(source: &'a str) -> Self {
Self {
inner: Token::lexer(source),
pending: None,
}
}
}
impl Iterator for Lexer<'_> {
type Item = Result<(usize, Token, usize), ExprErrorS>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(token) = self.pending.take() {
return Some(Ok(token));
}
let token = self.inner.next()?;
{
let Range { start, end } = self.inner.span();
Some(
token
.map(|token| (start, token, end))
.map_err(|(err, err_span)| (err.into(), err_span)),
)
}
}
}
#[derive(Logos, Debug, Clone, PartialEq)]
#[logos(error = Spanned<LexicalError>)]
#[logos(skip r"[ \t\n\f]+")]
pub enum Token {
#[token("(")]
LParan,
#[token(")")]
RParan,
#[token("+")]
Plus,
#[token("-")]
Minus,
#[token("/")]
Slash,
#[token("*")]
Astrisk,
#[regex(r#"[0-9]+(\.[0-9]+)?"#, lex_number)]
Number(f64),
}
fn lex_number(lexer: &mut logos::Lexer<Token>) -> f64 {
let slice = lexer.slice();
slice.parse::<f64>().expect("should be a parsable number")
}