Skip to main content

harn_lexer/
token.rs

1use std::fmt;
2
3/// A segment of an interpolated string.
4#[derive(Debug, Clone, PartialEq)]
5pub enum StringSegment {
6    Literal(String),
7    Expression(String),
8}
9
10impl fmt::Display for StringSegment {
11    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12        match self {
13            StringSegment::Literal(s) => write!(f, "{s}"),
14            StringSegment::Expression(e) => write!(f, "${{{e}}}"),
15        }
16    }
17}
18
19/// Source location for error reporting.
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub struct Span {
22    /// Byte offset from start of source (inclusive).
23    pub start: usize,
24    /// Byte offset from start of source (exclusive).
25    pub end: usize,
26    /// 1-based line number of start position.
27    pub line: usize,
28    /// 1-based column number of start position.
29    pub column: usize,
30}
31
32impl Span {
33    pub fn with_offsets(start: usize, end: usize, line: usize, column: usize) -> Self {
34        Self {
35            start,
36            end,
37            line,
38            column,
39        }
40    }
41
42    /// Create a span covering two spans (from start of `a` to end of `b`).
43    pub fn merge(a: Span, b: Span) -> Span {
44        Span {
45            start: a.start,
46            end: b.end,
47            line: a.line,
48            column: a.column,
49        }
50    }
51
52    /// A dummy span for synthetic/generated nodes.
53    pub fn dummy() -> Self {
54        Self {
55            start: 0,
56            end: 0,
57            line: 0,
58            column: 0,
59        }
60    }
61}
62
63impl fmt::Display for Span {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        write!(f, "{}:{}", self.line, self.column)
66    }
67}
68
69/// Token kinds produced by the lexer.
70#[derive(Debug, Clone, PartialEq)]
71pub enum TokenKind {
72    // Keywords
73    Pipeline,
74    Extends,
75    Override,
76    Let,
77    Var,
78    If,
79    Else,
80    For,
81    In,
82    Match,
83    Retry,
84    Parallel,
85    ParallelMap,
86    Return,
87    Import,
88    True,
89    False,
90    Nil,
91    Try,
92    Catch,
93    Throw,
94    Fn,
95    Spawn,
96    While,
97    TypeKw,
98    Enum,
99    Struct,
100    Interface,
101    Pub,
102    From,
103    Thru,
104    Upto,
105    Guard,
106    Ask,
107    Deadline,
108    Yield,
109    Mutex,
110    Break,
111    Continue,
112
113    // Literals
114    Identifier(String),
115    StringLiteral(String),
116    InterpolatedString(Vec<StringSegment>),
117    IntLiteral(i64),
118    FloatLiteral(f64),
119    /// Duration literal in milliseconds: 500ms, 5s, 30m, 2h
120    DurationLiteral(u64),
121
122    // Two-character operators
123    Eq,            // ==
124    Neq,           // !=
125    And,           // &&
126    Or,            // ||
127    Pipe,          // |>
128    NilCoal,       // ??
129    QuestionDot,   // ?.
130    Arrow,         // ->
131    Lte,           // <=
132    Gte,           // >=
133    PlusAssign,    // +=
134    MinusAssign,   // -=
135    StarAssign,    // *=
136    SlashAssign,   // /=
137    PercentAssign, // %=
138
139    // Single-character operators
140    Assign,   // =
141    Not,      // !
142    Dot,      // .
143    Plus,     // +
144    Minus,    // -
145    Star,     // *
146    Slash,    // /
147    Percent,  // %
148    Lt,       // <
149    Gt,       // >
150    Question, // ?
151    Bar,      // |  (for union types)
152
153    // Delimiters
154    LBrace,    // {
155    RBrace,    // }
156    LParen,    // (
157    RParen,    // )
158    LBracket,  // [
159    RBracket,  // ]
160    Comma,     // ,
161    Colon,     // :
162    Semicolon, // ;
163
164    // Comments
165    LineComment(String),  // // text
166    BlockComment(String), // /* text */
167
168    // Special
169    Newline,
170    Eof,
171}
172
173impl fmt::Display for TokenKind {
174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175        match self {
176            TokenKind::Pipeline => write!(f, "pipeline"),
177            TokenKind::Extends => write!(f, "extends"),
178            TokenKind::Override => write!(f, "override"),
179            TokenKind::Let => write!(f, "let"),
180            TokenKind::Var => write!(f, "var"),
181            TokenKind::If => write!(f, "if"),
182            TokenKind::Else => write!(f, "else"),
183            TokenKind::For => write!(f, "for"),
184            TokenKind::In => write!(f, "in"),
185            TokenKind::Match => write!(f, "match"),
186            TokenKind::Retry => write!(f, "retry"),
187            TokenKind::Parallel => write!(f, "parallel"),
188            TokenKind::ParallelMap => write!(f, "parallel_map"),
189            TokenKind::Return => write!(f, "return"),
190            TokenKind::Import => write!(f, "import"),
191            TokenKind::True => write!(f, "true"),
192            TokenKind::False => write!(f, "false"),
193            TokenKind::Nil => write!(f, "nil"),
194            TokenKind::Try => write!(f, "try"),
195            TokenKind::Catch => write!(f, "catch"),
196            TokenKind::Throw => write!(f, "throw"),
197            TokenKind::Fn => write!(f, "fn"),
198            TokenKind::Spawn => write!(f, "spawn"),
199            TokenKind::While => write!(f, "while"),
200            TokenKind::TypeKw => write!(f, "type"),
201            TokenKind::Enum => write!(f, "enum"),
202            TokenKind::Struct => write!(f, "struct"),
203            TokenKind::Interface => write!(f, "interface"),
204            TokenKind::Pub => write!(f, "pub"),
205            TokenKind::From => write!(f, "from"),
206            TokenKind::Thru => write!(f, "thru"),
207            TokenKind::Upto => write!(f, "upto"),
208            TokenKind::Guard => write!(f, "guard"),
209            TokenKind::Ask => write!(f, "ask"),
210            TokenKind::Deadline => write!(f, "deadline"),
211            TokenKind::Yield => write!(f, "yield"),
212            TokenKind::Mutex => write!(f, "mutex"),
213            TokenKind::Break => write!(f, "break"),
214            TokenKind::Continue => write!(f, "continue"),
215            TokenKind::Identifier(s) => write!(f, "id({s})"),
216            TokenKind::StringLiteral(s) => write!(f, "str({s})"),
217            TokenKind::InterpolatedString(_) => write!(f, "istr(...)"),
218            TokenKind::IntLiteral(n) => write!(f, "int({n})"),
219            TokenKind::FloatLiteral(n) => write!(f, "float({n})"),
220            TokenKind::DurationLiteral(ms) => write!(f, "duration({ms}ms)"),
221            TokenKind::Eq => write!(f, "=="),
222            TokenKind::Neq => write!(f, "!="),
223            TokenKind::And => write!(f, "&&"),
224            TokenKind::Or => write!(f, "||"),
225            TokenKind::Pipe => write!(f, "|>"),
226            TokenKind::NilCoal => write!(f, "??"),
227            TokenKind::QuestionDot => write!(f, "?."),
228            TokenKind::Arrow => write!(f, "->"),
229            TokenKind::Lte => write!(f, "<="),
230            TokenKind::Gte => write!(f, ">="),
231            TokenKind::PlusAssign => write!(f, "+="),
232            TokenKind::MinusAssign => write!(f, "-="),
233            TokenKind::StarAssign => write!(f, "*="),
234            TokenKind::SlashAssign => write!(f, "/="),
235            TokenKind::PercentAssign => write!(f, "%="),
236            TokenKind::Assign => write!(f, "="),
237            TokenKind::Not => write!(f, "!"),
238            TokenKind::Dot => write!(f, "."),
239            TokenKind::Plus => write!(f, "+"),
240            TokenKind::Minus => write!(f, "-"),
241            TokenKind::Star => write!(f, "*"),
242            TokenKind::Slash => write!(f, "/"),
243            TokenKind::Percent => write!(f, "%"),
244            TokenKind::Lt => write!(f, "<"),
245            TokenKind::Gt => write!(f, ">"),
246            TokenKind::Question => write!(f, "?"),
247            TokenKind::Bar => write!(f, "|"),
248            TokenKind::LBrace => write!(f, "{{"),
249            TokenKind::RBrace => write!(f, "}}"),
250            TokenKind::LParen => write!(f, "("),
251            TokenKind::RParen => write!(f, ")"),
252            TokenKind::LBracket => write!(f, "["),
253            TokenKind::RBracket => write!(f, "]"),
254            TokenKind::Comma => write!(f, ","),
255            TokenKind::Colon => write!(f, ":"),
256            TokenKind::Semicolon => write!(f, ";"),
257            TokenKind::LineComment(s) => write!(f, "// {s}"),
258            TokenKind::BlockComment(s) => write!(f, "/* {s} */"),
259            TokenKind::Newline => write!(f, "\\n"),
260            TokenKind::Eof => write!(f, "EOF"),
261        }
262    }
263}
264
265/// A token with its kind and source location.
266#[derive(Debug, Clone, PartialEq)]
267pub struct Token {
268    pub kind: TokenKind,
269    pub span: Span,
270}
271
272impl Token {
273    pub fn with_span(kind: TokenKind, span: Span) -> Self {
274        Self { kind, span }
275    }
276}