Skip to main content

microcad_lang_parse/parser/
parse_context.rs

1// Copyright © 2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Parse context for parsing specific types.
5
6use microcad_lang_base::{ComputedHash, Hashed, LineIndex, Span, SrcRef, Url};
7
8/// Context for parsing.
9#[derive(Debug)]
10pub enum ParseContext<'source> {
11    /// Parse a single element from a string
12    Element(Hashed<&'source str>),
13    /// Parse a source code snippet from a url and a string.
14    Source {
15        /// The source url
16        url: Url,
17        /// Line index
18        line_index: LineIndex,
19        /// A line offset (e.g. used when source is parsed from markdown code snippets).
20        line_offset: u32,
21        /// The source code to be parsed.
22        code: Hashed<&'source str>,
23    },
24}
25
26impl<'source> ParseContext<'source> {
27    /// Create a new parse context for a source code.
28    pub fn new(source: &'source str) -> Self {
29        Self::Element(Hashed::new(source))
30    }
31
32    /// Add a URL to the parse context.
33    pub fn with_url(self, url: Url) -> Self {
34        match self {
35            Self::Source {
36                line_index,
37                line_offset,
38                code,
39                ..
40            } => Self::Source {
41                url,
42                code,
43                line_index,
44                line_offset,
45            },
46            Self::Element(code) => Self::Source {
47                line_index: LineIndex::new(&code),
48                url,
49                code,
50                line_offset: 0,
51            },
52        }
53    }
54
55    /// Add a line offset the parse context.
56    pub fn with_line_offset(self, line_offset: u32) -> Self {
57        match self {
58            Self::Source {
59                url,
60                line_index,
61                code: source,
62                ..
63            } => Self::Source {
64                url,
65                code: source,
66                line_index,
67                line_offset,
68            },
69            Self::Element(source) => Self::Source {
70                line_index: LineIndex::new(&source),
71                url: microcad_lang_base::virtual_url(&format!("source_{}", source.computed_hash())),
72                code: source,
73                line_offset,
74            },
75        }
76    }
77
78    /// Create a source code reference from a span.
79    pub fn src_ref(&self, span: &Span) -> SrcRef {
80        match self {
81            Self::Source {
82                line_index,
83                line_offset,
84                code: source,
85                ..
86            } => line_index
87                .src_ref(source.value(), span, source.computed_hash())
88                .with_line_offset(*line_offset),
89            Self::Element(source) => {
90                SrcRef::new(span.clone(), Default::default(), source.computed_hash())
91            }
92        }
93    }
94}
95
96impl<'source> From<&'source microcad_lang_base::Source> for ParseContext<'source> {
97    fn from(source: &'source microcad_lang_base::Source) -> Self {
98        Self::Source {
99            url: source.url.clone(),
100            line_index: LineIndex::new(&source.code),
101            line_offset: source.line_offset,
102            code: Hashed::new(source.code.value()),
103        }
104    }
105}