json_pop/
lex.rs

1use crate::error::CompilationError;
2use logos::Logos;
3use std::fmt;
4use std::ops::Range;
5
6#[derive(Logos, Debug, PartialEq, Copy, Clone)]
7pub enum Token<'a> {
8    #[regex("[ \r\n\t]+", logos::skip)]
9    #[error]
10    Error,
11
12    #[token("true")]
13    True,
14
15    #[token("false")]
16    False,
17
18    #[token("null")]
19    Null,
20
21    #[token(":")]
22    Colon,
23
24    #[token(",")]
25    Comma,
26
27    #[token("{")]
28    LBrace,
29
30    #[token("}")]
31    RBrace,
32
33    #[token("[")]
34    LBrack,
35
36    #[token("]")]
37    RBrack,
38
39    /* The last 2 could use some cleaning up,
40       In particular matching Number as a regex... turning it into a string,
41       and then doing an entire pass over the string, rather than converting
42       numbers as digits match is a likely improvement.
43    */
44    #[regex(r#"-?([0-9]|([1-9][0-9]*))((\.[0-9]+)?)([eE][+-]?[0-9]+)?"#, |lex| lex.slice())]
45    Number(&'a str),
46
47    #[regex(r#""([ -!#-\[\]-\x{10ffff}]|([\\](["\\/bfnrt]|[u][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]])))*""#)]
48    String(&'a str),
49    #[regex(r#""([ -!#-\[\]-\x{10ffff}]|([\\](["\\/bfnrt]|[u][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]])))*"#)]
50    MissingEndQuote(&'a str),
51}
52
53impl<'a> Token<'a> {
54    pub fn to_lalr_triple(
55        (t, r): (Token<'a>, Range<usize>),
56    ) -> Result<(usize, Token, usize), CompilationError> {
57        if t == Token::Error {
58            Err(CompilationError::LexicalError { range: r })
59        } else {
60            Ok((r.start, t, r.end))
61        }
62    }
63}
64
65impl<'a> fmt::Display for Token<'a> {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        write!(f, "{:#?}", self)
68    }
69}