oak_core/lexer/
scan_comment.rs

1use crate::{SyntaxKind, Token};
2use std::range::Range;
3
4/// Configuration for comment scanning
5#[derive(Debug, Clone)]
6pub struct CommentLine {
7    /// Single-line comment markers (e.g., ["//", "#", ";"])
8    pub line_markers: &'static [&'static str],
9}
10
11/// Configuration for block comment scanning
12#[derive(Debug, Clone)]
13pub struct CommentBlock {
14    /// Block comment start/end pairs (e.g., [("/*", "*/"), ("<!--", "-->")])
15    pub block_markers: &'static [(&'static str, &'static str)],
16    /// Whether block comments can be nested
17    pub nested_blocks: bool,
18}
19
20impl Default for CommentLine {
21    fn default() -> Self {
22        Self { line_markers: &["//"] }
23    }
24}
25
26impl Default for CommentBlock {
27    fn default() -> Self {
28        Self { block_markers: &[("/*", "*/")], nested_blocks: false }
29    }
30}
31
32impl CommentLine {
33    /// Scan for a line comment at the given position
34    ///
35    /// # Arguments
36    ///
37    /// * `view` - The text view to scan
38    /// * `start` - The starting byte position
39    /// * `kind` - The token kind to assign to the comment
40    ///
41    /// # Returns
42    ///
43    /// A token if a line comment is found, `None` otherwise
44    pub fn scan<K: SyntaxKind>(&self, view: &str, start: usize, kind: K) -> Option<Token<K>> {
45        for marker in self.line_markers {
46            if view.starts_with(marker) {
47                return Some(Token { kind, span: Range { start, end: start + marker.len() } });
48            }
49        }
50        None
51    }
52}
53
54impl CommentBlock {
55    /// Scan for a block comment at the given position
56    ///
57    /// # Arguments
58    ///
59    /// * `view` - The text view to scan
60    /// * `start` - The starting byte position
61    /// * `kind` - The token kind to assign to the comment
62    ///
63    /// # Returns
64    ///
65    /// A token if a block comment is found, `None` otherwise
66    pub fn scan<K: SyntaxKind>(&self, view: &str, start: usize, kind: K) -> Option<Token<K>> {
67        for (start_marker, end_marker) in self.block_markers {
68            if view.starts_with(start_marker) {
69                let end_index = view[start + start_marker.len()..].find(end_marker);
70                if let Some(end_index) = end_index {
71                    return Some(Token {
72                        kind,
73                        span: Range { start, end: start + start_marker.len() + end_index + end_marker.len() },
74                    });
75                }
76            }
77        }
78        None
79    }
80}