Skip to content

Commit 08c9b12

Browse files
committed
enh(cpp) simpler struct matching with beforeMatch
Resolves #2736.
1 parent 4257b1e commit 08c9b12

File tree

5 files changed

+43
-21
lines changed

5 files changed

+43
-21
lines changed

src/languages/cpp.js

+6-11
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default function(hljs) {
2121
const DECLTYPE_AUTO_RE = 'decltype\\(auto\\)';
2222
const NAMESPACE_RE = '[a-zA-Z_]\\w*::';
2323
const TEMPLATE_ARGUMENT_RE = '<[^<>]+>';
24-
const FUNCTION_TYPE_RE = '(' +
24+
const FUNCTION_TYPE_RE = '(?!struct)(' +
2525
DECLTYPE_AUTO_RE + '|' +
2626
regex.optional(NAMESPACE_RE) +
2727
'[a-zA-Z_]\\w*' + regex.optional(TEMPLATE_ARGUMENT_RE) +
@@ -233,7 +233,7 @@ export default function(hljs) {
233233
'atomic_bool atomic_char atomic_schar ' +
234234
'atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong ' +
235235
'atomic_ullong new throw return ' +
236-
'and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq',
236+
'and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq struct',
237237
built_in: '_Bool _Complex _Imaginary',
238238
_relevance_hints: COMMON_CPP_HINTS,
239239
literal: 'true false nullptr NULL'
@@ -403,15 +403,10 @@ export default function(hljs) {
403403
keywords: CPP_KEYWORDS
404404
},
405405
{
406-
className: 'class',
407-
beginKeywords: 'enum class struct union',
408-
end: /[{;:<>=]/,
409-
contains: [
410-
{
411-
beginKeywords: "final class struct"
412-
},
413-
hljs.TITLE_MODE
414-
]
406+
beforeMatch: /\b(enum|class|struct|union)\s+/,
407+
keywords: "enum class struct union",
408+
match: /\w+/,
409+
className: "title"
415410
}
416411
])
417412
};

src/lib/exts/before_match.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import * as regex from "../regex.js";
2+
3+
// allow beforeMatch to act as a "qualifier" for the match
4+
// the full match begin must be [beforeMatch][begin]
5+
export const beforeMatchExt = (mode, parent) => {
6+
if (!mode.beforeMatch) return;
7+
// starts conflicts with endsParent which we need to make sure the child
8+
// rule is not matched multiple times
9+
if (mode.starts) throw new Error("beforeMatch cannot be used with starts");
10+
11+
const originalMode = Object.assign({}, mode);
12+
Object.keys(mode).forEach((key) => { delete mode[key]; });
13+
14+
mode.keywords = originalMode.keywords;
15+
mode.begin = regex.concat(originalMode.beforeMatch, regex.lookahead(originalMode.begin));
16+
mode.starts = {
17+
relevance: 0,
18+
contains: [
19+
Object.assign(originalMode, { endsParent: true })
20+
]
21+
};
22+
mode.relevance = 0;
23+
24+
delete originalMode.beforeMatch;
25+
};

src/lib/mode_compiler.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as regex from './regex.js';
22
import { inherit } from './utils.js';
33
import * as EXT from "./compiler_extensions.js";
4+
import { beforeMatchExt } from "./exts/before_match.js";
45
import { compileKeywords } from "./compile_keywords.js";
56
import { MultiClass } from "./ext/multi_class.js";
67

@@ -286,7 +287,8 @@ export function compileLanguage(language, { plugins }) {
286287
// do this early so compiler extensions generally don't have to worry about
287288
// the distinction between match/begin
288289
EXT.compileMatch,
289-
MultiClass
290+
MultiClass,
291+
beforeMatchExt
290292
].forEach(ext => ext(mode, parent));
291293

292294
language.compilerExtensions.forEach(ext => ext(mode, parent));
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
<span class="hljs-keyword">const</span> <span class="hljs-keyword">uint64_t</span> MAX_INT_64;
22

3-
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">position_tag</span>;</span>
3+
<span class="hljs-keyword">struct</span> <span class="hljs-title hljs-title-class">position_tag</span>;
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
<span class="hljs-keyword">template</span> &lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">T</span>&gt;</span> <span class="hljs-comment">// comment</span>
1+
<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">class</span> <span class="hljs-title hljs-title-class">T</span>&gt; <span class="hljs-comment">// comment</span>
22
<span class="hljs-function"><span class="hljs-keyword">auto</span> <span class="hljs-title">foo</span><span class="hljs-params">(T x)</span> </span>{ ... };
33

44
<span class="hljs-keyword">namespace</span> impl {
55
<span class="hljs-keyword">template</span>&lt;<span class="hljs-keyword">typename</span> T&gt;
6-
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">is_streamable</span>&lt;</span>T, std::<span class="hljs-keyword">void_t</span>&lt;<span class="hljs-keyword">decltype</span>(std::declval&lt;std::wostream &amp;&gt;() &lt;&lt; std::declval&lt;T&gt;())&gt;&gt; : std::true_type { };
6+
<span class="hljs-keyword">struct</span> <span class="hljs-title hljs-title-class">is_streamable</span>&lt;T, std::<span class="hljs-keyword">void_t</span>&lt;<span class="hljs-keyword">decltype</span>(std::declval&lt;std::wostream &amp;&gt;() &lt;&lt; std::declval&lt;T&gt;())&gt;&gt; : std::true_type { };
77
}
88

99
<span class="hljs-comment">// Disable overload for already valid operands.</span>
10-
<span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">T</span>, <span class="hljs-keyword">class</span> =</span> std::<span class="hljs-keyword">enable_if_t</span>&lt;!impl::is_streamable_v&lt;<span class="hljs-keyword">const</span> T &amp;&gt; &amp;&amp; std::is_convertible_v&lt;<span class="hljs-keyword">const</span> T &amp;, std::wstring_view&gt;&gt;&gt;
10+
<span class="hljs-keyword">template</span>&lt;<span class="hljs-keyword">class</span> <span class="hljs-title hljs-title-class">T</span>, class = std::<span class="hljs-keyword">enable_if_t</span>&lt;!impl::is_streamable_v&lt;<span class="hljs-keyword">const</span> T &amp;&gt; &amp;&amp; std::is_convertible_v&lt;<span class="hljs-keyword">const</span> T &amp;, std::wstring_view&gt;&gt;&gt;
1111
std::wostream &amp;<span class="hljs-keyword">operator</span> &lt;&lt;(std::wostream &amp;stream, <span class="hljs-keyword">const</span> T &amp;thing)
1212
{
1313
<span class="hljs-keyword">return</span> stream &lt;&lt; <span class="hljs-keyword">static_cast</span>&lt;std::wstring_view&gt;(thing);
1414
}
1515

16-
<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-keyword">struct</span> <span class="hljs-title">DataHolder</span> {</span> };
17-
<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-keyword">class</span> <span class="hljs-title">DataThingy</span> {</span> };
18-
<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Boolean</span> :</span> <span class="hljs-keyword">char</span> {
16+
<span class="hljs-keyword">enum</span> <span class="hljs-title hljs-title-class"><span class="hljs-keyword">struct</span></span> DataHolder { };
17+
<span class="hljs-keyword">enum</span> <span class="hljs-title hljs-title-class"><span class="hljs-keyword">class</span></span> DataThingy { };
18+
<span class="hljs-keyword">enum</span> <span class="hljs-title hljs-title-class"><span class="hljs-keyword">class</span></span> Boolean : <span class="hljs-keyword">char</span> {
1919
True, False, FileNotFound
2020
};
2121

22-
<span class="hljs-class"><span class="hljs-keyword">union</span> <span class="hljs-title">Soy</span>
23-
{</span>
22+
<span class="hljs-keyword">union</span> <span class="hljs-title hljs-title-class">Soy</span>
23+
{
2424
};

0 commit comments

Comments
 (0)