highlighter_core/
language.rs

1use regex::Error;
2
3use crate::lexer::LexerContext;
4
5/// The scope of a token.
6#[derive(Clone, Copy, Debug, PartialEq)]
7pub enum Scope {
8    /// A comment token, such as:
9    /// 
10    /// ```
11    /// // Hello, world!
12    /// /* Hello, world! */
13    /// ```
14    /// ```html
15    /// <!-- Hello, world! -->
16    /// ```
17    Comment,
18
19    /// A numeric constant token.
20    /// 
21    /// ```
22    /// 1234;
23    /// 1.3f32;
24    /// 0x42;
25    /// ```
26    ConstantNumber,
27
28    /// A character constant token.
29    /// 
30    /// ```
31    /// 'A';
32    /// ```
33    ConstantChar,
34
35    /// A language constant token.
36    /// 
37    /// ```
38    /// true;
39    /// false;
40    /// ```
41    /// 
42    /// ```c
43    /// nullptr
44    /// ```
45    /// 
46    /// ```lua
47    /// nil
48    /// ```
49    ConstantLanguage,
50
51    /// Any other constant.
52    ConstantOther,
53
54    /// A function name token.
55    /// 
56    /// ```c
57    /// main();
58    /// ```
59    NameFunction,
60
61    /// A type name token.
62    /// 
63    /// ```c
64    /// typedef struct Name {
65    ///     int member;
66    /// } Name;
67    /// ```
68    NameType,
69
70    /// The name of a tag.
71    /// 
72    /// ```html
73    /// <name></name>
74    /// ```
75    NameTag,
76
77    /// The name of a tag.
78    /// 
79    /// ```markdown
80    /// ## Header
81    /// ```
82    /// 
83    /// ```latex
84    /// \chapter{Chapter}
85    /// ```
86    NameSection,
87
88    /// An invalid token.
89    Invalid,
90
91    /// A deprecated case.
92    Deprecated,
93
94    /// A storage type keyword, such as `class`, `function` or `var`.
95    /// 
96    /// ```c++
97    /// class MyClass {
98    /// public:
99    ///     // ...
100    /// }
101    /// ```
102    /// 
103    /// ```
104    /// fn main() {
105    ///     println!("Hello, world!");
106    /// }
107    /// ```
108    StorageType,
109
110    /// A storage modifier keyword, such as `static`, `mut`, `final`, etc.
111    StorageModifier,
112
113    /// A quoted string token.
114    StringQuoted,
115
116    /// A string that is evaluated, such as JavaScript template strings.
117    StringEvaluated,
118
119    /// A regex string.
120    /// 
121    /// ```js
122    /// /([a-zA-Z])+/g
123    /// ```
124    StringRegex,
125
126    /// Any other kind of string.
127    StringOther,
128
129    /// A function provided by the language or standard library.
130    SupportFunction,
131
132    /// A type (class, struct, etc.) provided by the language or standard library.
133    SupportType,
134
135    /// A constant provided by the language or standard library.
136    SupportConstant,
137
138    /// A variable provided by the language or standard library.
139    SupportVar,
140
141    /// Any other supporting value.
142    SupportOther,
143
144    /// A variable declared as a function parameter.
145    VariableParameter,
146
147    /// A special variable such as `super` or `this`.
148    VariableLanguage,
149
150    /// Any other variable names.
151    VariableOther,
152
153    /// A controlling keyword, such as `if`, `break`, `return`, `while`, etc.
154    KeywordControl,
155
156    /// An operator keyword, such as `instanceof`, `as`, `instance`, `or`, etc.
157    KeywordOperator,
158
159    /// An other keyword.
160    KeywordOther,
161
162    /// No scope matches this token.
163    None,
164}
165
166impl Scope {
167    /// Converts the [`Scope`]'s name to a snake case string.
168    pub fn snake_case(&self) -> &str {
169        match self {
170            Self::Comment => "comment",
171            Self::ConstantNumber => "constant_number",
172            Self::ConstantChar => "constant_char",
173            Self::ConstantLanguage => "constant_language",
174            Self::ConstantOther => "constant_other",
175            Self::NameFunction => "name_function",
176            Self::NameType => "name_type",
177            Self::NameTag => "name_tag",
178            Self::NameSection => "name_section",
179            Self::Invalid => "invalid",
180            Self::Deprecated => "deprecated",
181            Self::StorageType => "storage_type",
182            Self::StorageModifier => "storage_modifier",
183            Self::StringQuoted => "string_quoted",
184            Self::StringEvaluated => "string_evaluated",
185            Self::StringRegex => "string_regex",
186            Self::StringOther => "string_other",
187            Self::SupportFunction => "support_function",
188            Self::SupportType => "support_type",
189            Self::SupportConstant => "support_constant",
190            Self::SupportVar => "support_var",
191            Self::SupportOther => "support_other",
192            Self::VariableParameter => "variable_parameter",
193            Self::VariableLanguage => "variable_language",
194            Self::VariableOther => "variable_other",
195            Self::KeywordControl => "keyword_control",
196            Self::KeywordOperator => "keyword_operator",
197            Self::KeywordOther => "keyword_other",
198            Self::None => "none",
199        }
200    }
201
202    /// Converts the [`Scope`]'s name to a kebab case string.
203    pub fn kebab_case(&self) -> &str {
204        match self {
205            Self::Comment => "comment",
206            Self::ConstantNumber => "constant-number",
207            Self::ConstantChar => "constant-char",
208            Self::ConstantLanguage => "constant-language",
209            Self::ConstantOther => "constant-other",
210            Self::NameFunction => "name-function",
211            Self::NameType => "name-type",
212            Self::NameTag => "name-tag",
213            Self::NameSection => "name-section",
214            Self::Invalid => "invalid",
215            Self::Deprecated => "deprecated",
216            Self::StorageType => "storage-type",
217            Self::StorageModifier => "storage-modifier",
218            Self::StringQuoted => "string-quoted",
219            Self::StringEvaluated => "string-evaluated",
220            Self::StringRegex => "string-regex",
221            Self::StringOther => "string-other",
222            Self::SupportFunction => "support-function",
223            Self::SupportType => "support-type",
224            Self::SupportConstant => "support-constant",
225            Self::SupportVar => "support-var",
226            Self::SupportOther => "support-other",
227            Self::VariableParameter => "variable-parameter",
228            Self::VariableLanguage => "variable-language",
229            Self::VariableOther => "variable-other",
230            Self::KeywordControl => "keyword-control",
231            Self::KeywordOperator => "keyword-operator",
232            Self::KeywordOther => "keyword-other",
233            Self::None => "none",
234        }
235    }
236}
237
238/// A language implementation for Highlighter.
239pub trait Language {
240
241    /// Returns the name of the programming language.
242    fn name(&self) -> String;
243
244    /// Returns all of the aliases of the programming language.
245    /// 
246    /// For example:
247    /// ```
248    /// vec!["js".to_owned(), "javascript".to_owned(), "jscript".to_owned(), "es".to_owned(), "ecmascript".to_owned()];
249    /// ```
250    fn names(&self) -> Vec<String> {
251        vec![self.name()]
252    }
253
254    /// Initializes the programming language.
255    fn init(&self, x: &mut LexerContext) -> Result<(), Error>;
256}