Skip to main content

tzcompile/source/
records.rs

1//! Lexical records: the output of the lexer, before any semantic interpretation.
2//!
3//! A tzdata source file is line-oriented. After comment stripping and field splitting,
4//! each non-blank line becomes a [`Line`] holding its 1-based number and the [`Field`]s on
5//! it. Keeping the column of each field lets diagnostics point precisely at the offending
6//! token rather than just the line.
7
8/// One whitespace-delimited (or quoted) field, with the byte column it started at.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Field {
11    /// The field's content with surrounding quotes removed and escapes resolved.
12    pub text: String,
13    /// 0-based byte column of the field's first character on the original line.
14    pub col: usize,
15}
16
17impl Field {
18    pub fn new(text: impl Into<String>, col: usize) -> Self {
19        Field {
20            text: text.into(),
21            col,
22        }
23    }
24}
25
26/// A single logical source line that contained at least one field.
27#[derive(Debug, Clone)]
28pub struct Line {
29    /// 1-based line number in the source file.
30    pub number: usize,
31    pub fields: Vec<Field>,
32}
33
34impl Line {
35    /// The first field's text, if any — the record keyword for a fresh line (`Rule`,
36    /// `Zone`, `Link`), or the first column of a zone continuation line.
37    pub fn keyword(&self) -> Option<&str> {
38        self.fields.first().map(|f| f.text.as_str())
39    }
40}