1"""
2 pygments.lexers.rust
3 ~~~~~~~~~~~~~~~~~~~~
4
5 Lexers for the Rust language.
6
7 :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
10
11from pygments.lexer import RegexLexer, include, bygroups, words, default
12from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
13 Number, Punctuation, Whitespace
14
15__all__ = ['RustLexer']
16
17
18class RustLexer(RegexLexer):
19 """
20 Lexer for the Rust programming language (version 1.47).
21 """
22 name = 'Rust'
23 url = 'https://www.rust-lang.org/'
24 filenames = ['*.rs', '*.rs.in']
25 aliases = ['rust', 'rs']
26 mimetypes = ['text/rust', 'text/x-rust']
27 version_added = '1.6'
28
29 keyword_types = (words((
30 'u8', 'u16', 'u32', 'u64', 'u128', 'i8', 'i16', 'i32', 'i64', 'i128',
31 'usize', 'isize', 'f32', 'f64', 'char', 'str', 'bool',
32 ), suffix=r'\b'), Keyword.Type)
33
34 builtin_funcs_types = (words((
35 'Copy', 'Send', 'Sized', 'Sync', 'Unpin',
36 'Drop', 'Fn', 'FnMut', 'FnOnce', 'drop',
37 'Box', 'ToOwned', 'Clone',
38 'PartialEq', 'PartialOrd', 'Eq', 'Ord',
39 'AsRef', 'AsMut', 'Into', 'From', 'Default',
40 'Iterator', 'Extend', 'IntoIterator', 'DoubleEndedIterator',
41 'ExactSizeIterator',
42 'Option', 'Some', 'None',
43 'Result', 'Ok', 'Err',
44 'String', 'ToString', 'Vec',
45 ), suffix=r'\b'), Name.Builtin)
46
47 builtin_macros = (words((
48 'asm', 'assert', 'assert_eq', 'assert_ne', 'cfg', 'column',
49 'compile_error', 'concat', 'concat_idents', 'dbg', 'debug_assert',
50 'debug_assert_eq', 'debug_assert_ne', 'env', 'eprint', 'eprintln',
51 'file', 'format', 'format_args', 'format_args_nl', 'global_asm',
52 'include', 'include_bytes', 'include_str',
53 'is_aarch64_feature_detected',
54 'is_arm_feature_detected',
55 'is_mips64_feature_detected',
56 'is_mips_feature_detected',
57 'is_powerpc64_feature_detected',
58 'is_powerpc_feature_detected',
59 'is_x86_feature_detected',
60 'line', 'llvm_asm', 'log_syntax', 'macro_rules', 'matches',
61 'module_path', 'option_env', 'panic', 'print', 'println', 'stringify',
62 'thread_local', 'todo', 'trace_macros', 'unimplemented', 'unreachable',
63 'vec', 'write', 'writeln',
64 ), suffix=r'!'), Name.Function.Magic)
65
66 tokens = {
67 'root': [
68 # rust allows a file to start with a shebang, but if the first line
69 # starts with #![ then it's not a shebang but a crate attribute.
70 (r'#![^[\r\n].*$', Comment.Preproc),
71 default('base'),
72 ],
73 'base': [
74 # Whitespace and Comments
75 (r'\n', Whitespace),
76 (r'\s+', Whitespace),
77 (r'//!.*?\n', String.Doc),
78 (r'///(\n|[^/].*?\n)', String.Doc),
79 (r'//(.*?)\n', Comment.Single),
80 (r'/\*\*(\n|[^/*])', String.Doc, 'doccomment'),
81 (r'/\*!', String.Doc, 'doccomment'),
82 (r'/\*', Comment.Multiline, 'comment'),
83
84 # Macro parameters
85 (r"""\$([a-zA-Z_]\w*|\(,?|\),?|,?)""", Comment.Preproc),
86 # Keywords
87 (words(('as', 'async', 'await', 'box', 'const', 'crate', 'dyn',
88 'else', 'extern', 'for', 'if', 'impl', 'in', 'loop',
89 'match', 'move', 'mut', 'pub', 'ref', 'return', 'static',
90 'super', 'trait', 'unsafe', 'use', 'where', 'while'),
91 suffix=r'\b'), Keyword),
92 (words(('abstract', 'become', 'do', 'final', 'macro', 'override',
93 'priv', 'typeof', 'try', 'unsized', 'virtual', 'yield'),
94 suffix=r'\b'), Keyword.Reserved),
95 (r'(true|false)\b', Keyword.Constant),
96 (r'self\b', Name.Builtin.Pseudo),
97 (r'mod\b', Keyword, 'modname'),
98 (r'let\b', Keyword.Declaration),
99 (r'fn\b', Keyword, 'funcname'),
100 (r'(struct|enum|type|union)\b', Keyword, 'typename'),
101 (r'(default)(\s+)(type|fn)\b', bygroups(Keyword, Whitespace, Keyword)),
102 keyword_types,
103 (r'[sS]elf\b', Name.Builtin.Pseudo),
104 # Prelude (taken from Rust's src/libstd/prelude.rs)
105 builtin_funcs_types,
106 builtin_macros,
107 # Path separators, so types don't catch them.
108 (r'::\b', Punctuation),
109 # Types in positions.
110 (r'(?::|->)', Punctuation, 'typename'),
111 # Labels
112 (r'(break|continue)(\b\s*)(\'[A-Za-z_]\w*)?',
113 bygroups(Keyword, Text.Whitespace, Name.Label)),
114
115 # Character literals
116 (r"""'(\\['"\\nrt]|\\x[0-7][0-9a-fA-F]|\\0"""
117 r"""|\\u\{[0-9a-fA-F]{1,6}\}|.)'""",
118 String.Char),
119 (r"""b'(\\['"\\nrt]|\\x[0-9a-fA-F]{2}|\\0"""
120 r"""|\\u\{[0-9a-fA-F]{1,6}\}|.)'""",
121 String.Char),
122
123 # Binary literals
124 (r'0b[01_]+', Number.Bin, 'number_lit'),
125 # Octal literals
126 (r'0o[0-7_]+', Number.Oct, 'number_lit'),
127 # Hexadecimal literals
128 (r'0[xX][0-9a-fA-F_]+', Number.Hex, 'number_lit'),
129 # Decimal literals
130 (r'[0-9][0-9_]*(\.[0-9_]+[eE][+\-]?[0-9_]+|'
131 r'\.[0-9_]*(?!\.)|[eE][+\-]?[0-9_]+)', Number.Float,
132 'number_lit'),
133 (r'[0-9][0-9_]*', Number.Integer, 'number_lit'),
134
135 # String literals
136 (r'b"', String, 'bytestring'),
137 (r'"', String, 'string'),
138 (r'(?s)b?r(#*)".*?"\1', String),
139
140 # Lifetime names
141 (r"'", Operator, 'lifetime'),
142
143 # Operators and Punctuation
144 (r'\.\.=?', Operator),
145 (r'[{}()\[\],.;]', Punctuation),
146 (r'[+\-*/%&|<>^!~@=:?]', Operator),
147
148 # Identifiers
149 (r'[a-zA-Z_]\w*', Name),
150 # Raw identifiers
151 (r'r#[a-zA-Z_]\w*', Name),
152
153 # Attributes
154 (r'#!?\[', Comment.Preproc, 'attribute['),
155
156 # Misc
157 # Lone hashes: not used in Rust syntax, but allowed in macro
158 # arguments, most famously for quote::quote!()
159 (r'#', Punctuation),
160 ],
161 'comment': [
162 (r'[^*/]+', Comment.Multiline),
163 (r'/\*', Comment.Multiline, '#push'),
164 (r'\*/', Comment.Multiline, '#pop'),
165 (r'[*/]', Comment.Multiline),
166 ],
167 'doccomment': [
168 (r'[^*/]+', String.Doc),
169 (r'/\*', String.Doc, '#push'),
170 (r'\*/', String.Doc, '#pop'),
171 (r'[*/]', String.Doc),
172 ],
173 'modname': [
174 (r'\s+', Whitespace),
175 (r'[a-zA-Z_]\w*', Name.Namespace, '#pop'),
176 default('#pop'),
177 ],
178 'funcname': [
179 (r'\s+', Whitespace),
180 (r'[a-zA-Z_]\w*', Name.Function, '#pop'),
181 default('#pop'),
182 ],
183 'typename': [
184 (r'\s+', Whitespace),
185 (r'&', Keyword.Pseudo),
186 (r"'", Operator, 'lifetime'),
187 builtin_funcs_types,
188 keyword_types,
189 (r'[a-zA-Z_]\w*', Name.Class, '#pop'),
190 default('#pop'),
191 ],
192 'lifetime': [
193 (r"(static|_)", Name.Builtin),
194 (r"[a-zA-Z_]+\w*", Name.Attribute),
195 default('#pop'),
196 ],
197 'number_lit': [
198 (r'[ui](8|16|32|64|size)', Keyword, '#pop'),
199 (r'f(32|64)', Keyword, '#pop'),
200 default('#pop'),
201 ],
202 'string': [
203 (r'"', String, '#pop'),
204 (r"""\\['"\\nrt]|\\x[0-7][0-9a-fA-F]|\\0"""
205 r"""|\\u\{[0-9a-fA-F]{1,6}\}""", String.Escape),
206 (r'[^\\"]+', String),
207 (r'\\', String),
208 ],
209 'bytestring': [
210 (r"""\\x[89a-fA-F][0-9a-fA-F]""", String.Escape),
211 include('string'),
212 ],
213 'attribute_common': [
214 (r'"', String, 'string'),
215 (r'\[', Comment.Preproc, 'attribute['),
216 ],
217 'attribute[': [
218 include('attribute_common'),
219 (r'\]', Comment.Preproc, '#pop'),
220 (r'[^"\]\[]+', Comment.Preproc),
221 ],
222 }