Skip to main content

rantlr_core/
token.rs

1use serde::Serialize;
2
3use crate::span::Span;
4
5/// Reserved words in the `.gr` surface language.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Keyword {
8    Grammar,
9    Rule,
10    Token,
11    Match,
12    Repeat,
13    Optional,
14    Example,
15    Input,
16    Expect,
17    Skip,
18    Import,
19    Fragment,
20}
21
22impl Keyword {
23    pub fn as_str(self) -> &'static str {
24        match self {
25            Self::Grammar => "grammar",
26            Self::Rule => "rule",
27            Self::Token => "token",
28            Self::Match => "match",
29            Self::Repeat => "repeat",
30            Self::Optional => "optional",
31            Self::Example => "example",
32            Self::Input => "input",
33            Self::Expect => "expect",
34            Self::Skip => "skip",
35            Self::Import => "import",
36            Self::Fragment => "fragment",
37        }
38    }
39
40    pub fn from_ident(ident: &str) -> Option<Self> {
41        Some(match ident {
42            "grammar" => Self::Grammar,
43            "rule" => Self::Rule,
44            "token" => Self::Token,
45            "match" => Self::Match,
46            "repeat" => Self::Repeat,
47            "optional" => Self::Optional,
48            "example" => Self::Example,
49            "input" => Self::Input,
50            "expect" => Self::Expect,
51            "skip" => Self::Skip,
52            "import" => Self::Import,
53            "fragment" => Self::Fragment,
54            _ => return None,
55        })
56    }
57}
58
59/// Built-in lexical types available in `token Name = <Builtin>;`.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
61#[serde(rename_all = "PascalCase")]
62pub enum BuiltinType {
63    Email,
64    Url,
65    DateTime,
66    QuotedString,
67    Number,
68}
69
70impl BuiltinType {
71    pub fn as_str(self) -> &'static str {
72        match self {
73            Self::Email => "Email",
74            Self::Url => "Url",
75            Self::DateTime => "DateTime",
76            Self::QuotedString => "QuotedString",
77            Self::Number => "Number",
78        }
79    }
80
81    pub fn from_ident(ident: &str) -> Option<Self> {
82        Some(match ident {
83            "Email" => Self::Email,
84            "Url" => Self::Url,
85            "DateTime" => Self::DateTime,
86            "QuotedString" => Self::QuotedString,
87            "Number" => Self::Number,
88            _ => return None,
89        })
90    }
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub enum TokenKind {
95    /// End of input sentinel.
96    Eof,
97
98    Keyword(Keyword),
99    Builtin(BuiltinType),
100
101    /// Rule / token / grammar names (`expr`, `JsonMini`, …).
102    Ident(String),
103
104    /// Double-quoted string with escapes (`"import"`, `"{"`).
105    String(String),
106    /// Backtick raw string for example inputs (`` `{"a":1}` ``).
107    RawString(String),
108
109    /// Integer literal (e.g. range bounds in `repeat(0..)`).
110    Integer(u64),
111
112    // Punctuation / operators
113    LBrace,   // {
114    RBrace,   // }
115    LParen,   // (
116    RParen,   // )
117    LBracket, // [
118    RBracket, // ]
119    Pipe,     // |
120    Comma,    // ,
121    Semi,     // ;
122    Colon,    // :
123    Eq,       // =
124    DotDot,   // ..
125    Arrow,    // ->
126}
127
128impl TokenKind {
129    pub fn is_eof(&self) -> bool {
130        matches!(self, Self::Eof)
131    }
132}
133
134#[derive(Debug, Clone, PartialEq, Eq)]
135pub struct Token {
136    pub kind: TokenKind,
137    pub span: Span,
138}
139
140impl Token {
141    pub fn new(kind: TokenKind, span: Span) -> Self {
142        Self { kind, span }
143    }
144}