metrale_grammar/grammar/lexer_token.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2//
3// EBNF token type definitions. Split out of `lexer.rs` to keep each
4// file under the 250-line cap. Port of `EBNFLexer::TokenType` and
5// `EBNFLexer::Token` from xgrammar `cpp/grammar_parser.h`.
6
7/// EBNF token kinds. Port of `EBNFLexer::TokenType`.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum TokenType {
10 /// Name on the left of `::=`, e.g. `root`.
11 RuleName,
12 /// A reference to a rule, or a macro name (e.g. `TagDispatch`).
13 Identifier,
14 /// A `"..."` string literal.
15 StringLiteral,
16 /// `true` / `false`.
17 BooleanLiteral,
18 /// An integer literal.
19 IntegerLiteral,
20 /// `(`
21 LParen,
22 /// `)`
23 RParen,
24 /// `{`
25 LBrace,
26 /// `}`
27 RBrace,
28 /// `|`
29 Pipe,
30 /// `,`
31 Comma,
32 /// End of input.
33 EndOfFile,
34 /// `::=`
35 Assign,
36 /// `=`
37 Equal,
38 /// `*`
39 Star,
40 /// `+`
41 Plus,
42 /// `?`
43 Question,
44 /// `[`
45 LBracket,
46 /// `]`
47 RBracket,
48 /// `-` inside a character class.
49 Dash,
50 /// `^` inside a character class.
51 Caret,
52 /// A single (possibly escaped) character inside a character class.
53 CharInCharClass,
54 /// A regex-style escape with special meaning inside a class (`\d`…).
55 EscapeInCharClass,
56 /// `(=` — opens a lookahead assertion.
57 LookaheadLParen,
58}
59
60/// The processed value carried by a [`Token`].
61#[derive(Debug, Clone, PartialEq)]
62pub enum TokenValue {
63 /// No processed value.
64 None,
65 /// String value (string literals; identifier names; class escapes).
66 Str(String),
67 /// Integer value (integer literals).
68 Int(i64),
69 /// Boolean value (`true`/`false`).
70 Bool(bool),
71 /// Codepoint value (a character inside a character class).
72 Codepoint(i32),
73}
74
75/// A single lexer token. Port of `EBNFLexer::Token`.
76#[derive(Debug, Clone, PartialEq)]
77pub struct Token {
78 /// The token kind.
79 pub ty: TokenType,
80 /// Original source text of the token.
81 pub lexeme: String,
82 /// Processed value.
83 pub value: TokenValue,
84 /// 1-based source line.
85 pub line: i32,
86 /// 1-based source column.
87 pub column: i32,
88}
89
90/// A lexer error with source position.
91#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
92#[error("EBNF lexer error at line {line}, column {column}: {msg}")]
93pub struct LexError {
94 /// 1-based source line.
95 pub line: i32,
96 /// 1-based source column.
97 pub column: i32,
98 /// Human-readable error message.
99 pub msg: String,
100}