diff --git a/utils/textmate/README.md b/utils/textmate/README.md index 6d67f11343ff..bf37ae6c8883 100644 --- a/utils/textmate/README.md +++ b/utils/textmate/README.md @@ -49,9 +49,11 @@ utils/textmate/render_sample.py utils/textmate/Samples/*.carbon ``` The colors are a palette built for this grammar rather than an editor's theme. -Each family of related scopes gets one color, and bold and italic distinguish -the scopes within a family, so every scope the grammar emits renders differently -and a change to what the grammar scopes is visible in the image. Unscoped text +Each family of related scopes gets one color, and bold, italic, and underline +distinguish the scopes within a family. Every scope the grammar picks from +context renders differently, so a change to what the grammar scopes is visible +in the image. Scopes that follow from the spelling alone, such as a bracket's +shape, can share a rendering, since the text already shows them. Unscoped text is dimmer than any scope's color, so text the grammar misses stands out. A scope -with no entry of its own takes its family's color and style, so give a new scope -an entry to keep every scope distinct. +with no entry of its own takes its family's color and style, so give a new +context-dependent scope an entry of its own. diff --git a/utils/textmate/Samples/choices.svg b/utils/textmate/Samples/choices.svg index bfdc725f5f3c..f80db658477f 100644 --- a/utils/textmate/Samples/choices.svg +++ b/utils/textmate/Samples/choices.svg @@ -5,9 +5,9 @@ 2 // Exceptions. See /LICENSE for license information. 3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 -5 choice SomeChoice(T: type) { -6 Val1, -7 Val2(a: i32, b: array(T, 5), t: T), -8 Val3 -9 } +5 choice SomeChoice(T: type) { +6 Val1, +7 Val2(a: i32, b: array(T, 5), t: T), +8 Val3 +9 } diff --git a/utils/textmate/Samples/comments.carbon b/utils/textmate/Samples/comments.carbon index e089e9cc197b..bc2295b69dba 100644 --- a/utils/textmate/Samples/comments.carbon +++ b/utils/textmate/Samples/comments.carbon @@ -8,6 +8,8 @@ //@dump-sem-ir-begin //@dump-sem-ir-end //@include-in-dumps + //@include-in-dumps +//@dump-sem-ir-begin with trailing text is an ordinary comment //@dump-sem-ir- //no whitespace after double slash /* invalid comment pattern. */ diff --git a/utils/textmate/Samples/comments.svg b/utils/textmate/Samples/comments.svg index 5929b28e802f..272c9fda15f2 100644 --- a/utils/textmate/Samples/comments.svg +++ b/utils/textmate/Samples/comments.svg @@ -1,4 +1,4 @@ - + 1 // Part of the Carbon Language project, under the Apache License v2.0 with LLVM @@ -11,10 +11,12 @@ 8 //@dump-sem-ir-begin 9 //@dump-sem-ir-end 10 //@include-in-dumps -11 //@dump-sem-ir- -12 //no whitespace after double slash -13 /* invalid comment pattern. */ -14 /// invalid comment pattern. -15 class C; // Comment after a statement/expression/declaration. -16 var x: i32 = 1;// Trailing, with no space before the introducer. +11 //@include-in-dumps +12 //@dump-sem-ir-begin with trailing text is an ordinary comment +13 //@dump-sem-ir- +14 //no whitespace after double slash +15 /* invalid comment pattern. */ +16 /// invalid comment pattern. +17 class C; // Comment after a statement/expression/declaration. +18 var x: i32 = 1;// Trailing, with no space before the introducer. diff --git a/utils/textmate/Samples/customs.svg b/utils/textmate/Samples/customs.svg index 94e20e063c82..2436592fbca2 100644 --- a/utils/textmate/Samples/customs.svg +++ b/utils/textmate/Samples/customs.svg @@ -6,10 +6,10 @@ 3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 5 package SomePackage; - 6 Core SomeCore; + 6 Core SomeCore; 7 - 8 import SomePackage; + 8 import SomePackage; 9 -10 CallFunction(a, b, c.d); +10 CallFunction(a, b, c.d); 11 unidentified; diff --git a/utils/textmate/Samples/functions_variables.carbon b/utils/textmate/Samples/functions_variables.carbon index 1054a90b015a..c180c26e1b81 100644 --- a/utils/textmate/Samples/functions_variables.carbon +++ b/utils/textmate/Samples/functions_variables.carbon @@ -28,6 +28,7 @@ generic a: T = b; a: A in some_list; var a: T; let b: T; +let unused c: T = d; binding: T; generic binding: T; var @@ -50,3 +51,17 @@ r#class r#if r#i32 var r#var: i32 = r#class; + +// --- member access through a pointer + +p->field; +p->Method(a); +p->0; +(*p).field; +t.0.1; +q.value()->size(); + +// --- builtin function definitions + +fn Add(a: i32, b: i32) -> i32 = "int.sadd"; +fn Bits(n: IntLiteral) -> type = "int.make_type_signed"; diff --git a/utils/textmate/Samples/functions_variables.svg b/utils/textmate/Samples/functions_variables.svg index f17f1a65c3b7..3732439c78ed 100644 --- a/utils/textmate/Samples/functions_variables.svg +++ b/utils/textmate/Samples/functions_variables.svg @@ -1,56 +1,71 @@ - + 1 // Part of the Carbon Language project, under the Apache License v2.0 with LLVM 2 // Exceptions. See /LICENSE for license information. 3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 - 5 fn F; - 6 fn F1(); - 7 fn Func(a: i32, b: A); - 8 fn Generic[T: type, U: I](a: T, b: U) -> U; - 9 fn Lambda(a: i32) -> i32 => return a + 5; + 5 fn F; + 6 fn F1(); + 7 fn Func(a: i32, b: A); + 8 fn Generic[T: type, U: I](a: T, b: U) -> U; + 9 fn Lambda(a: i32) -> i32 => return a + 5; 10 fn 11 -12 MultiLine[ -13 A: type, -14 B: C1, -15 C: C2 -16 ](a: A(B, C), -17 b: B, -18 c: i32); -19 fn Invalid#+?Name(); -20 x.(I.F)(); +12 MultiLine[ +13 A: type, +14 B: C1, +15 C: C2 +16 ](a: A(B, C), +17 b: B, +18 c: i32); +19 fn Invalid#+?Name(); +20 x.(I.F)(); 21 -22 a: A; -23 a: A = (b as A); -24 a: i32; -25 a: array(A, 5); -26 generic a: type; -27 generic a: T = b; -28 a: A in some_list; +22 a: A; +23 a: A = (b as A); +24 a: i32; +25 a: array(A, 5); +26 generic a: type; +27 generic a: T = b; +28 a: A in some_list; 29 var a: T; -30 let b: T; -31 binding: T; -32 generic binding: T; -33 var -34 multiline: T; -35 -36 fn F(ref a: A, const ref b: B); -37 fn F() -> T; -38 fn F() -> T.U { return val; } -39 fn F() -> i32 => return val; -40 -41 // --- lambdas and positional parameters -42 -43 var explicit: auto = fn (x: i32) -> i32 { return x + 1; }; -44 var expression: auto = fn (x: i32) => x + 1; -45 var positional: auto = fn { Print($0, $1, $42); }; -46 -47 // --- raw identifiers -48 -49 r#class -50 r#if -51 r#i32 -52 var r#var: i32 = r#class; +30 let b: T; +31 let unused c: T = d; +32 binding: T; +33 generic binding: T; +34 var +35 multiline: T; +36 +37 fn F(ref a: A, const ref b: B); +38 fn F() -> T; +39 fn F() -> T.U { return val; } +40 fn F() -> i32 => return val; +41 +42 // --- lambdas and positional parameters +43 +44 var explicit: auto = fn (x: i32) -> i32 { return x + 1; }; +45 var expression: auto = fn (x: i32) => x + 1; +46 var positional: auto = fn { Print($0, $1, $42); }; +47 +48 // --- raw identifiers +49 +50 r#class +51 r#if +52 r#i32 +53 var r#var: i32 = r#class; +54 +55 // --- member access through a pointer +56 +57 p->field; +58 p->Method(a); +59 p->0; +60 (*p).field; +61 t.0.1; +62 q.value()->size(); +63 +64 // --- builtin function definitions +65 +66 fn Add(a: i32, b: i32) -> i32 = "int.sadd"; +67 fn Bits(n: IntLiteral) -> type = "int.make_type_signed"; diff --git a/utils/textmate/Samples/interop.svg b/utils/textmate/Samples/interop.svg index 99238f7277f1..c9ebd87e530e 100644 --- a/utils/textmate/Samples/interop.svg +++ b/utils/textmate/Samples/interop.svg @@ -9,25 +9,25 @@ 6 // grammar highlights them as C++; these renderings come from the Carbon grammar 7 // alone, so that content shows plain. 8 - 9 package Sample library "interop"; + 9 package Sample library "interop"; 10 -11 import Cpp library "<cstdio>"; -12 import Cpp library "<string_view>"; +11 import Cpp library "<cstdio>"; +12 import Cpp library "<string_view>"; 13 -14 import Cpp inline '''c++ +14 import Cpp inline '''c++ 15 int FromImport() { return 1; } 16 '''; 17 -18 import Cpp inline "int OneLiner() { return 2; }"; +18 import Cpp inline "int OneLiner() { return 2; }"; 19 20 inline Cpp ''' 21 int FromBlock() { return 3; } 22 '''; 23 -24 fn Uses() { -25 var value: Cpp.int = 1 as Cpp.int; -26 var widened: Cpp.size_t = value as Cpp.size_t; -27 var back: i32 = value unsafe as i32; -28 Cpp.printf("%d\n", value); -29 } +24 fn Uses() { +25 var value: Cpp.int = 1 as Cpp.int; +26 var widened: Cpp.size_t = value as Cpp.size_t; +27 var back: i32 = value unsafe as i32; +28 Cpp.printf("%d\n", value); +29 } diff --git a/utils/textmate/Samples/keywords.svg b/utils/textmate/Samples/keywords.svg index b5827092c65a..ff4de3982413 100644 --- a/utils/textmate/Samples/keywords.svg +++ b/utils/textmate/Samples/keywords.svg @@ -8,8 +8,8 @@ 5 // --- operators 6 7 >>= <=> <<= ->? &= ^= := :? == => != >= >> <= <> << <- -= -> -- %= |= += ++ /= - 8 *= ~= & @ ^ : = ! > < - % . | + ? / * ~ \ - 9 and as impls in like not or typeof where + 8 *= ~= & @ ^ : = ! > < - % . | + ? / * ~ \ + 9 and as impls in like not or typeof where 10 11 // --- special-keywords 12 @@ -18,7 +18,7 @@ 15 16 // --- introducer-keywords 17 -18 adapt alias choice class constraint fn import inline interface let library +18 adapt alias choice class constraint fn import inline interface let library 19 match_first namespace observe require var 20 base 21 export @@ -31,7 +31,7 @@ 28 private protected ref runtime static template unsafe unused val virtual 29 base class 30 default -31 export import +31 export import 32 impl fn 33 impl library 34 impl package @@ -40,8 +40,8 @@ 37 38 destroy each expand forall form friend 39 fn destroy -40 ...expand -41 .base +40 ...expand +41 .base 42 43 // --- self-keywords 44 diff --git a/utils/textmate/Samples/literals.carbon b/utils/textmate/Samples/literals.carbon index 382f52b7b63d..447f7a4ab889 100644 --- a/utils/textmate/Samples/literals.carbon +++ b/utils/textmate/Samples/literals.carbon @@ -14,6 +14,12 @@ '''py Block literal with a file type indicator. ''' +'''sql // A trailing comment on the introducer line. + SELECT 1; +''' +''' // A comment with no file type indicator. + Text. +''' #"a raw \n literal, where \#n is the escape"# ##"nested "# stays inside, and \##n is the escape"## @@ -27,6 +33,7 @@ 'a' '\n' '\0' '\u{1F600}' '\x70' +"\x4F is an escape, \x4f is not" '' 'abcde' diff --git a/utils/textmate/Samples/literals.svg b/utils/textmate/Samples/literals.svg index 8dbfcbe77eab..5ecfdbe91a41 100644 --- a/utils/textmate/Samples/literals.svg +++ b/utils/textmate/Samples/literals.svg @@ -1,4 +1,4 @@ - + 1 // Part of the Carbon Language project, under the Apache License v2.0 with LLVM @@ -17,56 +17,63 @@ 14 '''py 15 Block literal with a file type indicator. 16 ''' -17 -18 #"a raw \n literal, where \#n is the escape"# -19 ##"nested "# stays inside, and \##n is the escape"## -20 #''' -21 A raw block literal. -22 '''# +17 '''sql // A trailing comment on the introducer line. +18 SELECT 1; +19 ''' +20 ''' // A comment with no file type indicator. +21 Text. +22 ''' 23 -24 "unterminated -25 -26 // --- characters -27 -28 'a' '\n' '\0' '\u{1F600}' -29 '\x70' -30 '' -31 'abcde' -32 -33 // --- true-false -34 -35 true false -36 -37 // --- type-literals -38 -39 array auto bool char str type -40 i8 i16 i32 i64 i128 i10 -41 u8 u16 u32 u64 u128 u11 -42 f8 f16 f32 f64 f128 f12 +24 #"a raw \n literal, where \#n is the escape"# +25 ##"nested "# stays inside, and \##n is the escape"## +26 #''' +27 A raw block literal. +28 '''# +29 +30 "unterminated +31 +32 // --- characters +33 +34 'a' '\n' '\0' '\u{1F600}' +35 '\x70' +36 "\x4F is an escape, \x4f is not" +37 '' +38 'abcde' +39 +40 // --- true-false +41 +42 true false 43 -44 // --- numbers +44 // --- type-literals 45 -46 12345 6789 00012345 -47 -48 1234.56789 -49 0.875 -50 0.3e5 -51 1e5 -52 .123 -53 .1e3 +46 array auto bool char str type +47 i8 i16 i32 i64 i128 i10 +48 u8 u16 u32 u64 u128 u11 +49 f8 f16 f32 f64 f128 f12 +50 +51 // --- numbers +52 +53 12345 6789 00012345 54 -55 0o755 -56 0o_17 -57 0o8 -58 -59 0b1011_0010 -60 0b_010 -61 0b2345 -62 0B011 -63 -64 0x2AE5 -65 0x_F109 -66 0xD8_E2.5F_7Bp8 -67 0xabcdef.abcdef -68 0XA85CE +55 1234.56789 +56 0.875 +57 0.3e5 +58 1e5 +59 .123 +60 .1e3 +61 +62 0o755 +63 0o_17 +64 0o8 +65 +66 0b1011_0010 +67 0b_010 +68 0b2345 +69 0B011 +70 +71 0x2AE5 +72 0x_F109 +73 0xD8_E2.5F_7Bp8 +74 0xabcdef.abcdef +75 0XA85CE diff --git a/utils/textmate/Samples/main.svg b/utils/textmate/Samples/main.svg index a536895d7ead..d3534c9d1092 100644 --- a/utils/textmate/Samples/main.svg +++ b/utils/textmate/Samples/main.svg @@ -9,42 +9,42 @@ 6 7 package Carbon; 8 - 9 interface HasValueParam(T: type, V: T) { -10 fn Go(self) -> T; -11 } + 9 interface HasValueParam(T: type, V: T) { +10 fn Go(self) -> T; +11 } 12 -13 impl () as HasValueParam(i32, 5) { -14 fn Go(self) -> i32 { return 42; } -15 } +13 impl () as HasValueParam(i32, 5) { +14 fn Go(self) -> i32 { return 42; } +15 } 16 -17 class Point { -18 fn Origin() -> Self { -19 return {.x = 0, .y = 0}; -20 } +17 class Point { +18 fn Origin() -> Self { +19 return {.x = 0, .y = 0}; +20 } 21 22 var x: i32; 23 var y: i32; -24 } +24 } 25 -26 fn Procedure() -> i32 { +26 fn Procedure() -> i32 { 27 returned var zoop: i32 = 0; -28 while (DoSomeJob()) { +28 while (DoSomeJob()) { 29 zoop += 1; -30 } +30 } 31 32 return var; -33 } +33 } 34 -35 fn Main() -> i32 { +35 fn Main() -> i32 { 36 let str = "Hello world"; -37 let hex = 0xABCDEF1234567890; -38 let bin = 0b0000111001010010; +37 let hex = 0xABCDEF1234567890; +38 let bin = 0b0000111001010010; 39 let dec = 123456789012345678; 40 -41 let big: Core.Int(1024) = 1234; -42 let aaa: auto = "Carbon"; -43 let view: str = "Carbon"; +41 let big: Core.Int(1024) = 1234; +42 let aaa: auto = "Carbon"; +43 let view: str = "Carbon"; 44 -45 return Procedure(); -46 } +45 return Procedure(); +46 } diff --git a/utils/textmate/Samples/types.carbon b/utils/textmate/Samples/types.carbon index d2e46b08042a..b5def909c003 100644 --- a/utils/textmate/Samples/types.carbon +++ b/utils/textmate/Samples/types.carbon @@ -30,6 +30,7 @@ interface I; impl C as (I(A, B, C.(D.E(F, G)).H)) {} impl C as I where .A = (B where .Self = {}) {} impl C as I where .A = {} and .B = C {} +impl forall [T: I where .A = i32] T as J where .B = T.A {} impl Self as I; impl as I; @@ -39,3 +40,40 @@ constraint Constraint { require impls I; extern require impls I; } + +namespace N; + +class N.C1 { + fn N.C1.Make() -> Self; +} +alias N.A = N.C1; +fn N.C1.Other(); +class Outer(T: type).Inner(U: type) {} +fn Outer(T: type).Inner(U: type).F[self: Self](x: T) -> U; +fn N.Base(N.T).Member() {} +interface N.I2; +constraint N.C2 {} + +class C6 { + fn destroy(ref self); +} +fn C6.destroy(ref self) {} + +var p: C6* = &c6; +var q: typeof(p) = p; +var r: typeof(Make(p, (q))).Pointee = *p; + +// --- the same names in type and expression positions + +var o: Optional(Slice(i32)) = Optional(Slice(i32)).None(); +let origin: Point = Point.Origin(); +let t: type = Point; +var c: Core.Int(64) = x as Core.Int(64); +var v: Cpp.std.vector(i32) = Make(i32, Vector(Point)); +var s: {.x: i32, .y: Point} = {.x = 1, .y = p}; +var tup: (i32, Point) = (1, p); +fn Pick[T: Hashable & Eq where .Key = i32](t: T) -> T.Key; +fn Iter() -> Vector(T).Iterator; +if (T == Point and x impls Hashable) {} +alias lower = i32; +var l: lower = a * b; diff --git a/utils/textmate/Samples/types.svg b/utils/textmate/Samples/types.svg index bb2c9c1e38bc..ba77584ddde7 100644 --- a/utils/textmate/Samples/types.svg +++ b/utils/textmate/Samples/types.svg @@ -1,45 +1,83 @@ - + 1 // Part of the Carbon Language project, under the Apache License v2.0 with LLVM 2 // Exceptions. See /LICENSE for license information. 3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 - 5 class C1; - 6 class C2(T1: type, T2: C1) {} - 7 class C3 { - 8 extend base: C1; - 9 } + 5 class C1; + 6 class C2(T1: type, T2: C1) {} + 7 class C3 { + 8 extend base: C1; + 9 } 10 class -11 (C4( -12 (T1: type), -13 T2: -14 (A.(B(E, F(G)).C) -15 .D))) ; +11 (C4( +12 (T1: type), +13 T2: +14 (A.(B(E, F(G)).C) +15 .D))) ; 16 -17 class C5 { -18 impl as I; -19 extend impl as I; -20 } +17 class C5 { +18 impl as I; +19 extend impl as I; +20 } 21 -22 alias a1 = C1; +22 alias a1 = C1; 23 alias a2 = i32; 24 25 adapt SomeClass; -26 adapt {.a: SomeClass, .b: i32}; +26 adapt {.a: SomeClass, .b: i32}; 27 adapt i32; 28 29 interface I; -30 impl C as (I(A, B, C.(D.E(F, G)).H)) {} -31 impl C as I where .A = (B where .Self = {}) {} -32 impl C as I where .A = {} and .B = C {} -33 impl Self as I; -34 impl as I; -35 -36 constraint Constraint { -37 require T impls I; -38 require Self impls I; -39 require impls I; -40 extern require impls I; -41 } +30 impl C as (I(A, B, C.(D.E(F, G)).H)) {} +31 impl C as I where .A = (B where .Self = {}) {} +32 impl C as I where .A = {} and .B = C {} +33 impl forall [T: I where .A = i32] T as J where .B = T.A {} +34 impl Self as I; +35 impl as I; +36 +37 constraint Constraint { +38 require T impls I; +39 require Self impls I; +40 require impls I; +41 extern require impls I; +42 } +43 +44 namespace N; +45 +46 class N.C1 { +47 fn N.C1.Make() -> Self; +48 } +49 alias N.A = N.C1; +50 fn N.C1.Other(); +51 class Outer(T: type).Inner(U: type) {} +52 fn Outer(T: type).Inner(U: type).F[self: Self](x: T) -> U; +53 fn N.Base(N.T).Member() {} +54 interface N.I2; +55 constraint N.C2 {} +56 +57 class C6 { +58 fn destroy(ref self); +59 } +60 fn C6.destroy(ref self) {} +61 +62 var p: C6* = &c6; +63 var q: typeof(p) = p; +64 var r: typeof(Make(p, (q))).Pointee = *p; +65 +66 // --- the same names in type and expression positions +67 +68 var o: Optional(Slice(i32)) = Optional(Slice(i32)).None(); +69 let origin: Point = Point.Origin(); +70 let t: type = Point; +71 var c: Core.Int(64) = x as Core.Int(64); +72 var v: Cpp.std.vector(i32) = Make(i32, Vector(Point)); +73 var s: {.x: i32, .y: Point} = {.x = 1, .y = p}; +74 var tup: (i32, Point) = (1, p); +75 fn Pick[T: Hashable & Eq where .Key = i32](t: T) -> T.Key; +76 fn Iter() -> Vector(T).Iterator; +77 if (T == Point and x impls Hashable) {} +78 alias lower = i32; +79 var l: lower = a * b; diff --git a/utils/textmate/Syntaxes/carbon.tmLanguage b/utils/textmate/Syntaxes/carbon.tmLanguage index f68fa1fbbec8..ab1ea0fd5658 100644 --- a/utils/textmate/Syntaxes/carbon.tmLanguage +++ b/utils/textmate/Syntaxes/carbon.tmLanguage @@ -39,10 +39,26 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. include #strings + + include + #builtin-functions + + + include + #choice-definitions + include #declarations + + include + #inheritance + + + include + #type-annotation + include #keywords @@ -70,6 +86,376 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. repository + bindings + + patterns + + + captures + + 1 + + name + punctuation.definition.raw-identifier.carbon + + 2 + + name + variable.parameter.carbon + + + comment + Parameter bindings (`name: Type` when not preceded by `let` or `var`), with `variable.parameter` nested inside `variable.other`. + match + (?<!\.)(?<!->)\b(r#)?([A-Za-z_][A-Za-z0-9_]*)(?=\s*:(?![=!?])) + name + variable.other.carbon + + + + builtin-functions + + patterns + + + begin + \b(fn)\b(?=[^"/;]*=\s*") + beginCaptures + + 1 + + name + storage.type.carbon + + + comment + A builtin function declaration (`fn ... = "..."`), scoping the string contents as `support.function.builtin`. + end + (?=;)|$ + patterns + + + captures + + 1 + + name + keyword.operator.carbon + + 2 + + name + string.quoted.double.carbon + + 3 + + name + punctuation.definition.string.begin.carbon + + 4 + + name + support.function.builtin.carbon + + 5 + + name + punctuation.definition.string.end.carbon + + + match + (=)\s*((")([^"\\\n]*)(")) + + + include + #declarations + + + include + #comments + + + include + #strings + + + include + #type-annotation + + + include + #keywords + + + include + #literals + + + include + #numbers + + + include + #operators + + + include + #identifiers + + + include + #punctuation + + + + + + choice-definitions + + patterns + + + begin + \b(choice)\b + beginCaptures + + 1 + + name + storage.type.carbon + + + comment + A `choice` declaration, scoping names in its body as enum members and closing immediately if there is no body. + end + (?<=\})|(?=[^\s({]) + patterns + + + begin + (?<=\bchoice)\s+(?=(?:r#)?[A-Za-z_]) + end + ((?:r#)?[A-Za-z_][A-Za-z0-9_]*)\b(?!\s*(?:\[[^\[\]]*\]\s*)?(?:\([^()]*(?:\([^()]*(?:\([^()]*\)[^()]*)*\)[^()]*)*\)\s*)?\.)|(?=[^\sA-Za-z_])|$ + endCaptures + + 1 + + name + entity.name.type.carbon + + + patterns + + + include + #declared-name-qualifier + + + + + include + #comments + + + begin + \( + beginCaptures + + 0 + + name + punctuation.section.parens.begin.bracket.round.carbon + + + comment + Choice parameters. + end + (\))|$ + endCaptures + + 1 + + name + punctuation.section.parens.end.bracket.round.carbon + + + patterns + + + include + #choice-parameters + + + + + begin + \{ + beginCaptures + + 0 + + name + punctuation.section.block.begin.bracket.curly.carbon + + + comment + Choice body. + end + (\})|(?=[;=]) + endCaptures + + 1 + + name + punctuation.section.block.end.bracket.curly.carbon + + + patterns + + + include + #comments + + + begin + \( + beginCaptures + + 0 + + name + punctuation.section.parens.begin.bracket.round.carbon + + + comment + Alternative parameters. + end + (\))|$ + endCaptures + + 1 + + name + punctuation.section.parens.end.bracket.round.carbon + + + patterns + + + include + #choice-parameters + + + + + begin + \[ + beginCaptures + + 0 + + name + punctuation.section.brackets.begin.bracket.square.carbon + + + comment + Invalid implicit parameter list on an alternative, matched so its contents are not scoped as enum members. + end + (\])|$ + endCaptures + + 1 + + name + punctuation.section.brackets.end.bracket.square.carbon + + + patterns + + + include + #choice-parameters + + + + + include + #keywords + + + include + #literals + + + match + \b(?:r#)?[A-Za-z_][A-Za-z0-9_]*\b + name + variable.other.enummember.carbon + + + include + #numbers + + + include + #operators + + + include + #punctuation + + + + + + + + choice-parameters + + patterns + + + include + #comments + + + include + #strings + + + include + #inheritance + + + include + #type-annotation + + + include + #keywords + + + include + #literals + + + include + #numbers + + + include + #operators + + + include + #identifiers + + + include + #punctuation + + + comments patterns @@ -80,20 +466,23 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. 1 name - punctuation.definition.comment.carbon + comment.line.double-slash.carbon 2 + + name + punctuation.definition.comment.carbon + + 3 name keyword.other.directive.carbon comment - Toolchain directives, which are comments the driver acts on. + Toolchain directives. The comment scope sits on a capture rather than on the rule, to leave the leading indentation outside it. match - (//)(@(?:dump-sem-ir-(?:begin|end)|include-in-dumps))\b.*$ - name - comment.line.double-slash.carbon + ^\s*((//)(@(?:dump-sem-ir-(?:begin|end)|include-in-dumps)))$ captures @@ -117,13 +506,13 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. begin - \b(?:(import)\s+(Cpp)\s+(inline)|(inline)\s+(Cpp))\s*(''')([^\s'\"#]*) + \b(?:(import)\s+(Cpp)\s+(inline)|(inline)\s+(Cpp))\s*(''')([^\s'\"#]*)(?:[ \t]*((//)(?:[ \t][^\n]*)?)$)? beginCaptures 1 name - storage.type.carbon + keyword.control.import.carbon 2 @@ -155,6 +544,16 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. name entity.name.tag.language.carbon + 8 + + name + comment.line.double-slash.carbon + + 9 + + name + punctuation.definition.comment.carbon + comment Inline C++, block form. @@ -172,7 +571,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. 2 name - punctuation.terminator.carbon + punctuation.terminator.statement.carbon patterns @@ -191,7 +590,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. 1 name - storage.type.carbon + keyword.control.import.carbon 2 @@ -235,7 +634,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. 2 name - punctuation.terminator.carbon + punctuation.terminator.statement.carbon patterns @@ -253,23 +652,78 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. patterns - captures + begin + (?<=\bfn)\s+(?=(?:r#)?[A-Za-z_]) + comment + The name a function declaration declares, after any qualifiers, or the `destroy` keyword. + end + (?:(destroy)|((?:r#)?[A-Za-z_][A-Za-z0-9_]*))\b(?!\s*(?:\[[^\[\]]*\]\s*)?(?:\([^()]*(?:\([^()]*(?:\([^()]*\)[^()]*)*\)[^()]*)*\)\s*)?\.)|(?=[^\sA-Za-z_])|$ + endCaptures 1 name - storage.type.carbon + keyword.other.carbon 2 name - entity.name.function.carbon + entity.name.function.definition.carbon + patterns + + + include + #declared-name-qualifier + + + + + begin + (?<=\bclass)\s+(?=(?:r#)?[A-Za-z_]) comment - Function declarations, including lambdas with a name. `destroy` is a keyword naming a destructor, not a name. - match - \b(fn)\s+(?!destroy\b)((?:r#)?[A-Za-z_][A-Za-z0-9_]*) + The name a class declaration declares, given `entity.name.type.class` for themes that color classes apart from other types. + end + ((?:r#)?[A-Za-z_][A-Za-z0-9_]*)\b(?!\s*(?:\[[^\[\]]*\]\s*)?(?:\([^()]*(?:\([^()]*(?:\([^()]*\)[^()]*)*\)[^()]*)*\)\s*)?\.)|(?=[^\sA-Za-z_])|$ + endCaptures + + 1 + + name + entity.name.type.class.carbon + + + patterns + + + include + #declared-name-qualifier + + + + + begin + (?:(?<=\balias)|(?<=\bconstraint)|(?<=\binterface))\s+(?=(?:r#)?[A-Za-z_]) + comment + The name the other nominal type declarations declare. + end + ((?:r#)?[A-Za-z_][A-Za-z0-9_]*)\b(?!\s*(?:\[[^\[\]]*\]\s*)?(?:\([^()]*(?:\([^()]*(?:\([^()]*\)[^()]*)*\)[^()]*)*\)\s*)?\.)|(?=[^\sA-Za-z_])|$ + endCaptures + + 1 + + name + entity.name.type.carbon + + + patterns + + + include + #declared-name-qualifier + + captures @@ -282,13 +736,69 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. 2 name - entity.name.type.carbon + storage.modifier.carbon + + 3 + + name + punctuation.definition.raw-identifier.carbon + + 4 + + name + variable.other.constant.carbon comment - Nominal type declarations. + `let` and `var` bindings, with optional modifiers before the name. `_` and `self` are left to `#literals`. match - \b(alias|choice|class|constraint|interface)\s+((?:r#)?[A-Za-z_][A-Za-z0-9_]*) + \b(let)\s+((?:(?:generic|ref|template|unused|var)\s+)*)(?!_\s*:)(r#)?([A-Za-z_][A-Za-z0-9_]*)(?=\s*:(?![=!?])) + + + captures + + 1 + + name + storage.type.carbon + + 2 + + name + storage.modifier.carbon + + 3 + + name + punctuation.definition.raw-identifier.carbon + + 4 + + name + variable.other.carbon + + + match + \b(var)\s+((?:(?:generic|ref|template|unused)\s+)*)(?!(?:_|self)\s*:)(r#)?([A-Za-z_][A-Za-z0-9_]*)(?=\s*:(?![=!?])) + + + captures + + 1 + + name + keyword.control.import.carbon + + 2 + + name + entity.name.namespace.carbon + + + comment + Package, namespace, and import names, excluding keywords (`library`, `inline`) and `Core` and `Cpp`. + match + \b(import)\s+(?!(?:library|inline|Core|Cpp)\b)((?:r#)?[A-Za-z_][A-Za-z0-9_]*) captures @@ -304,10 +814,125 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. entity.name.namespace.carbon - comment - Package, namespace, and import names. `library` and `inline` are keywords that may follow `import`, not names. match - \b(package|namespace|import)\s+(?!(?:library|inline)\b)((?:r#)?[A-Za-z_][A-Za-z0-9_]*) + \b(package|namespace)\s+(?!(?:library|Core|Cpp)\b)((?:r#)?[A-Za-z_][A-Za-z0-9_]*) + + + captures + + 1 + + name + storage.type.carbon + + 2 + + name + string.quoted.double.carbon + + 3 + + name + punctuation.definition.string.begin.carbon + + 4 + + name + entity.name.namespace.library.carbon + + 5 + + name + punctuation.definition.string.end.carbon + + + comment + A library name, written as a string, with `entity.name.namespace.library` nested inside the string scope. + match + \b(library)\s+((")((?:\\.|[^"\\\n])*)(")) + + + + declared-name-qualifier + + patterns + + + begin + (((?:r#)?[A-Za-z_][A-Za-z0-9_]*))\b(?=\s*(?:\[[^\[\]]*\]\s*)?(?:\([^()]*(?:\([^()]*(?:\([^()]*\)[^()]*)*\)[^()]*)*\)\s*)?\.) + beginCaptures + + 1 + + name + entity.name.type.carbon + + 2 + + name + entity.name.scope-resolution.carbon + + + comment + One qualifier on a declared name, such as `N.` or `Base(T: type).`, matched when followed by `.` after any parameter lists. `entity.name.scope-resolution` is nested inside `entity.name.type` so themes without a scope-resolution rule fall back to the type color. + end + (\.) + endCaptures + + 1 + + name + punctuation.separator.dot-access.carbon + + + patterns + + + include + #type-body + + + + + + expression-parens + + patterns + + + begin + \( + beginCaptures + + 0 + + name + punctuation.section.parens.begin.bracket.round.carbon + + + comment + Parentheses nested in an expression that sits inside a type, so that only the matching `)` ends the expression. + end + (\))|$ + endCaptures + + 1 + + name + punctuation.section.parens.end.bracket.round.carbon + + + patterns + + + include + #expression-parens + + + include + $self + + @@ -316,23 +941,8 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. patterns - captures - - 1 - - name - punctuation.definition.raw-identifier.carbon - - 2 - - name - entity.name.type.carbon - - - comment - Raw identifiers, which suppress keyword meaning. - match - \b(r#)([A-Z][A-Za-z0-9_]*) + include + #bindings captures @@ -342,54 +952,309 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. name punctuation.definition.raw-identifier.carbon - 2 - - name - variable.other.carbon - + comment + Raw identifiers. match - \b(r#)([a-z_][A-Za-z0-9_]*) + \b(r#)([A-Za-z_][A-Za-z0-9_]*) + name + variable.other.carbon comment - An identifier applied to an argument list is a call. + Member function call. + match + (?:(?<=\.)|(?<=\->))[A-Za-z_][A-Za-z0-9_]*(?=\s*\() + name + entity.name.function.member.carbon + + + comment + Member access via `.` or `->`. + match + (?:(?<=\.)|(?<=\->))[A-Za-z_][A-Za-z0-9_]*\b + name + variable.other.property.carbon + + + comment + Function call. match \b[A-Za-z_][A-Za-z0-9_]*(?=\s*\() name - entity.name.function.carbon + entity.name.function.call.carbon - comment - UpperCamel names a type. match - \b[A-Z][A-Za-z0-9_]*\b - name - entity.name.type.carbon - - - comment - lower_snake names a value. - match - \b[a-z_][A-Za-z0-9_]*\b + \b[A-Za-z_][A-Za-z0-9_]*\b name variable.other.carbon + impls-clause + + patterns + + + begin + \b(impls)\b + beginCaptures + + 1 + + name + keyword.operator.expression.impls.carbon + + + end + (?=[,;={}\)\]]|[-+/%!<>|^~?@\\]|//|\b(?:in|and|or|not|as|impls)\b|$) + name + meta.inheritance-clause.carbon + patterns + + + include + #inheritance-body + + + + + + inheritance + + patterns + + + begin + \b(impl)\b(?!\s*(?:adapt|alias|base|choice|class|constraint|export|fn|impl|import|interface|let|library|match_first|namespace|observe|package|require|var)\b) + beginCaptures + + 1 + + name + storage.type.carbon + + + comment + An `impl` declaration (when `impl` does not precede another declaration keyword), scoping the type before `as` with `#type-body` and the interface after `as` with `#inheritance-body`. + end + (?=[;{]|$) + name + meta.type.annotation.carbon + patterns + + + begin + \b(as)\b + beginCaptures + + 1 + + name + keyword.operator.expression.as.carbon + + + end + (?=[,;={}\)\]]|[-+/%!<>|^~?@\\]|//|\b(?:in|and|or|not|as|impls)\b|$) + name + meta.inheritance-clause.carbon + patterns + + + include + #inheritance-body + + + + + include + #type-body + + + + + begin + (?<!\.)\b(base)\s*(:)(?![=!?]) + beginCaptures + + 1 + + name + storage.type.carbon + + 2 + + name + keyword.operator.type.annotation.carbon + + + comment + A `base:` declaration, excluding `.base` member access and `base class`. + end + (?=[,;={}\)\]]|[-+/%!<>|^~?@\\]|//|\b(?:in|and|or|not|as|impls)\b|$) + name + meta.inheritance-clause.carbon + patterns + + + include + #inheritance-body + + + + + include + #impls-clause + + + + inheritance-body + + patterns + + + begin + (?<=[A-Za-z0-9_\]])\( + beginCaptures + + 0 + + name + punctuation.section.parens.begin.bracket.round.carbon + + + comment + Only the interface itself is scoped as `entity.other.inherited-class`; its argument list switches to expression scoping. + end + (\))|$ + endCaptures + + 1 + + name + punctuation.section.parens.end.bracket.round.carbon + + + patterns + + + include + #expression-parens + + + include + $self + + + + + begin + \( + beginCaptures + + 0 + + name + punctuation.section.parens.begin.bracket.round.carbon + + + comment + Grouping parentheses around an interface name stay in `#inheritance-body`. + end + (\))|$ + endCaptures + + 1 + + name + punctuation.section.parens.end.bracket.round.carbon + + + patterns + + + include + #inheritance-body + + + + + begin + \b(where)\b + beginCaptures + + 1 + + name + keyword.other.where.carbon + + + comment + A `where` clause switches to expression scoping and ends at a `)` or `]` it did not open. + end + (?=[;{}\)\]]|$) + patterns + + + include + #expression-parens + + + include + $self + + + + + include + #keywords + + + include + #literals + + + comment + The final identifier of the interface or base class name; any preceding qualifiers fall through to `#type-body`. + match + \b(?:r#)?[A-Za-z_][A-Za-z0-9_]*\b(?!\s*\.) + name + entity.other.inherited-class.carbon + + + include + #type-body + + + keywords patterns + comment + `.base` member access, matched before `base` as an introducer. match - \b(adapt|alias|choice|class|constraint|fn|import|inline|interface|let|library|match_first|namespace|observe|require|var)\b + (?<=\.)\b(base)\b + name + keyword.other.base.carbon + + + match + \b(import)\b + name + keyword.control.import.carbon + + + match + \b(adapt|alias|choice|class|constraint|fn|inline|interface|let|library|match_first|namespace|observe|require|var)\b name storage.type.carbon comment - `base` introduces a base class declaration unless it modifies one. + `base` as an introducer (not `base class`). match \b(base)\b(?!\s*class\b) name @@ -403,13 +1268,13 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - \b(impl)\b(?!\s*(fn|library|package)\b) + \b(impl)\b(?!\s*(adapt|alias|base|choice|class|constraint|export|fn|impl|import|interface|let|library|match_first|namespace|observe|package|require|var)\b) name storage.type.carbon comment - `package` is an introducer unless it begins a qualified name. + `package` as an introducer (not `package.`). match \b(package)\b(?!\.) name @@ -423,7 +1288,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. comment - `default` is a declaration modifier unless it opens a match arm. + `default` as a modifier (not `default =>`). match \b(default)\b(?!\s*=>) name @@ -443,7 +1308,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - \b(impl)\b(?=\s*(fn|library|package)\b) + \b(impl)\b(?=\s*(adapt|alias|base|choice|class|constraint|export|fn|impl|import|interface|let|library|match_first|namespace|observe|package|require|var)\b) name storage.modifier.carbon @@ -455,7 +1320,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. comment - `default` is a match arm here, and a declaration modifier elsewhere. + `default` in a `match` clause. match \b(default)\b(?=\s*=>) name @@ -463,21 +1328,57 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - \b(and|as|impls|in|like|not|or|typeof|where)\b + \b(and|or)\b name keyword.control.carbon match - \b(destroy|each|expand|forall|form|friend)\b + \b(not)\b name - keyword.other.carbon + keyword.operator.expression.not.carbon comment - `.base` names the base class subobject. + Fallback when not matched by `#type-annotation` or `#inheritance`. match - (?<=\.)\b(base)\b + \b(as)\b + name + keyword.operator.expression.as.carbon + + + match + \b(impls)\b + name + keyword.operator.expression.impls.carbon + + + match + \b(in)\b + name + keyword.operator.expression.in.carbon + + + match + \b(like)\b + name + keyword.operator.expression.like.carbon + + + match + \b(typeof)\b + name + keyword.operator.expression.typeof.carbon + + + match + \b(where)\b + name + keyword.other.where.carbon + + + match + \b(destroy|each|expand|forall|form|friend)\b name keyword.other.carbon @@ -503,7 +1404,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. comment - Language-provided package roots. + Built-in package names. match \b(Core|Cpp)\b name @@ -511,7 +1412,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. comment - `package` as a qualified-name root names the current package. + `package` as a qualifier. match \b(package)\b(?=\.) name @@ -525,17 +1426,23 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - \b(array|auto|bool|char|str|type)\b + \b(array|auto|type)\b name support.type.builtin.carbon + + match + \b(bool|char|str)\b + name + support.type.primitive.carbon + comment - Integer and float type literals. The lexer accepts any width, so this must not be restricted to the common ones. + Integer and floating-point type literals. match \b[iuf][1-9][0-9]*\b name - support.type.builtin.carbon + support.type.primitive.carbon @@ -544,26 +1451,72 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. patterns + captures + + 1 + + name + keyword.other.unit.hexadecimal.carbon + + + comment + Each numeric rule matches a full alphanumeric word starting with a digit so a malformed suffix is not split into an identifier. Real literals exclude a leading `.` or `->` so tuple access like `t.0.1` is not matched as a real. match - \b0x[_0-9A-Fa-f]*(?:\.[_0-9A-Fa-f]*)?(?:[pP][-+]?[0-9]+)? + (?<!\.)(?<!->)\b(0x)[_0-9A-Za-z]*\.[0-9A-Za-z][_0-9A-Za-z]*(?:(?<=[a-z])[-+][0-9A-Za-z][_0-9A-Za-z]*)? name constant.numeric.hex.carbon + captures + + 1 + + name + keyword.other.unit.hexadecimal.carbon + + match - \b0o[_0-7]* + \b(0x)[_0-9A-Za-z]* + name + constant.numeric.hex.carbon + + + captures + + 1 + + name + keyword.other.unit.octal.carbon + + + match + \b(0o)[_0-9A-Za-z]* name constant.numeric.octal.carbon + captures + + 1 + + name + keyword.other.unit.binary.carbon + + match - \b0b[_01]* + \b(0b)[_0-9A-Za-z]* name constant.numeric.binary.carbon match - \b[0-9][_0-9]*(?:\.[_0-9]+)?(?:[eE][-+]?[0-9]+)? + (?<!\.)(?<!->)\b[0-9][_0-9A-Za-z]*\.[0-9A-Za-z][_0-9A-Za-z]*(?:(?<=[a-z])[-+][0-9A-Za-z][_0-9A-Za-z]*)? + name + constant.numeric.decimal.carbon + + + match + \b[0-9][_0-9A-Za-z]* name constant.numeric.decimal.carbon @@ -583,7 +1536,51 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - (\->\?|>>=|<=>|<<=|\&=|\^=|:=|:\?|==|=>|!=|>=|>>|<=|<>|<<|<\-|\-=|\->|\-\-|%=|\|=|\+=|\+\+|/=|\*=|\~=|\&|@|\^|:|=|!|>|<|\-|%|\.|\||\+|\?|/|\*|\~|\\) + :! + name + keyword.operator.type.annotation.symbolic.carbon + + + match + :\? + name + keyword.operator.type.annotation.form.carbon + + + match + :(?![=!?]) + name + keyword.operator.type.annotation.carbon + + + comment + `->` directly after an operand is pointer member access rather than a return type arrow. + match + (?<=[A-Za-z0-9_)\]}])\->(?!\?) + name + punctuation.separator.pointer-access.carbon + + + match + \->\? + name + keyword.operator.function-result.form.carbon + + + match + \->(?!\?) + name + keyword.operator.function-result.carbon + + + match + => + name + keyword.operator.arrow.fat.carbon + + + match + <=>|<<=|>>=|==|!=|<=|>=|<<|>>|\+\+|--|\+=|-=|\*=|/=|%=|&=|\|=|\^=|~=|:=|<-|<>|[-+*/%&|^~!<>=@?\\] name keyword.operator.carbon @@ -593,17 +1590,59 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. patterns + + match + \( + name + punctuation.section.parens.begin.bracket.round.carbon + + + match + \) + name + punctuation.section.parens.end.bracket.round.carbon + + + match + \{ + name + punctuation.section.block.begin.bracket.curly.carbon + + + match + \} + name + punctuation.section.block.end.bracket.curly.carbon + + + match + \[ + name + punctuation.section.brackets.begin.bracket.square.carbon + + + match + \] + name + punctuation.section.brackets.end.bracket.square.carbon + + + match + \. + name + punctuation.separator.dot-access.carbon + match , name - punctuation.separator.carbon + punctuation.separator.comma.carbon match ; name - punctuation.terminator.carbon + punctuation.terminator.statement.carbon @@ -613,7 +1652,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - \\(?:[tnr0'\"\\]|x[0-9A-Fa-f]{2}|u\{[0-9A-Fa-f]+\}) + \\(?:[tnr0'\"\\]|x[0-9A-F]{2}|u\{[0-9A-F]+\}) name constant.character.escape.carbon @@ -625,7 +1664,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - \\#(?:[tnr0'\"\\]|x[0-9A-Fa-f]{2}|u\{[0-9A-Fa-f]+\}) + \\#(?:[tnr0'\"\\]|x[0-9A-F]{2}|u\{[0-9A-F]+\}) name constant.character.escape.carbon @@ -637,7 +1676,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - \\##(?:[tnr0'\"\\]|x[0-9A-Fa-f]{2}|u\{[0-9A-Fa-f]+\}) + \\##(?:[tnr0'\"\\]|x[0-9A-F]{2}|u\{[0-9A-F]+\}) name constant.character.escape.carbon @@ -649,7 +1688,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. match - \\#{3,}(?:[tnr0'\"\\]|x[0-9A-Fa-f]{2}|u\{[0-9A-Fa-f]+\}) + \\#{3,}(?:[tnr0'\"\\]|x[0-9A-F]{2}|u\{[0-9A-F]+\}) name constant.character.escape.carbon @@ -661,7 +1700,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. begin - (#{3,})(''')([^\s'\"#]*) + (#{3,})(''')([^\s'\"#]*)(?:[ \t]*((//)(?:[ \t][^\n]*)?)$)? beginCaptures 1 @@ -679,6 +1718,16 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. name entity.name.tag.language.carbon + 4 + + name + comment.line.double-slash.carbon + + 5 + + name + punctuation.definition.comment.carbon + comment Block string literal, with an optional file type indicator, raw at `###` level. @@ -704,7 +1753,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. begin - (##)(''')([^\s'\"#]*) + (##)(''')([^\s'\"#]*)(?:[ \t]*((//)(?:[ \t][^\n]*)?)$)? beginCaptures 1 @@ -722,6 +1771,16 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. name entity.name.tag.language.carbon + 4 + + name + comment.line.double-slash.carbon + + 5 + + name + punctuation.definition.comment.carbon + comment Block string literal, with an optional file type indicator, raw at `##` level. @@ -747,7 +1806,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. begin - (#)(''')([^\s'\"#]*) + (#)(''')([^\s'\"#]*)(?:[ \t]*((//)(?:[ \t][^\n]*)?)$)? beginCaptures 1 @@ -765,6 +1824,16 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. name entity.name.tag.language.carbon + 4 + + name + comment.line.double-slash.carbon + + 5 + + name + punctuation.definition.comment.carbon + comment Block string literal, with an optional file type indicator, raw at `#` level. @@ -790,7 +1859,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. begin - (''')([^\s'\"#]*) + (''')([^\s'\"#]*)(?:[ \t]*((//)(?:[ \t][^\n]*)?)$)? beginCaptures 1 @@ -803,6 +1872,16 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. name entity.name.tag.language.carbon + 3 + + name + comment.line.double-slash.carbon + + 4 + + name + punctuation.definition.comment.carbon + comment Block string literal, with an optional file type indicator. @@ -828,7 +1907,7 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. begin - (""")([^\s'\"#]*) + (""")([^\s'\"#]*)(?:[ \t]*((//)(?:[ \t][^\n]*)?)$)? beginCaptures 1 @@ -841,6 +1920,16 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. name entity.name.tag.language.carbon + 3 + + name + comment.line.double-slash.carbon + + 4 + + name + punctuation.definition.comment.carbon + comment A `"""` block is always an error, but highlighting it as a block string keeps the rest of the file readable. @@ -1046,6 +2135,285 @@ THIS FILE IS AUTOGENERATED FROM carbon.tmLanguage.json. DO NOT EDIT. + type-annotation + + patterns + + + begin + (:!)|(:\?)|(:(?![=!?]))|((?<![A-Za-z0-9_)\]}])\->\?)|((?<![A-Za-z0-9_)\]}])\->(?!\?))|\b(as)\b|\b(adapt)\b|\b(require)\b + beginCaptures + + 1 + + name + keyword.operator.type.annotation.symbolic.carbon + + 2 + + name + keyword.operator.type.annotation.form.carbon + + 3 + + name + keyword.operator.type.annotation.carbon + + 4 + + name + keyword.operator.function-result.form.carbon + + 5 + + name + keyword.operator.function-result.carbon + + 6 + + name + keyword.operator.expression.as.carbon + + 7 + + name + storage.type.carbon + + 8 + + name + storage.type.carbon + + + comment + A type expression, from the token that introduces it to the first token that cannot continue one. + end + (?=[,;={}\)\]]|[-+/%!<>|^~?@\\]|//|\b(?:in|and|or|not|as|impls)\b|$) + name + meta.type.annotation.carbon + patterns + + + include + #type-body + + + + + + type-body + + patterns + + + begin + \( + beginCaptures + + 0 + + name + punctuation.section.parens.begin.bracket.round.carbon + + + comment + Argument and grouping parentheses, which nest rather than ending the type. + end + (\))|$ + endCaptures + + 1 + + name + punctuation.section.parens.end.bracket.round.carbon + + + patterns + + + include + #type-body + + + + + begin + \[ + beginCaptures + + 0 + + name + punctuation.section.brackets.begin.bracket.square.carbon + + + end + (\])|$ + endCaptures + + 1 + + name + punctuation.section.brackets.end.bracket.square.carbon + + + patterns + + + include + #type-body + + + + + begin + \bwhere\b + beginCaptures + + 0 + + name + keyword.other.where.carbon + + + comment + A `where` clause switches to expression scoping so `=` does not end the enclosing type as an initializer, and ends at a `)` or `]` it did not open. + end + (?=[;{}\)\]]|$) + patterns + + + include + #expression-parens + + + include + $self + + + + + include + #impls-clause + + + include + #comments + + + include + #strings + + + begin + \b(typeof)\s*(\() + beginCaptures + + 1 + + name + keyword.operator.expression.typeof.carbon + + 2 + + name + punctuation.section.parens.begin.bracket.round.carbon + + + comment + `typeof` takes an expression operand, switching out of `#type-body`. + end + (\))|$ + endCaptures + + 1 + + name + punctuation.section.parens.end.bracket.round.carbon + + + patterns + + + include + #expression-parens + + + include + $self + + + + + include + #keywords + + + include + #literals + + + include + #numbers + + + comment + Pointer `*`, written directly after the pointee type. + match + (?<=[A-Za-z0-9_)\]*])\*(?!=) + name + keyword.operator.type.pointer.carbon + + + include + #operators + + + include + #bindings + + + captures + + 1 + + name + entity.name.scope-resolution.carbon + + + comment + A qualifier in a type, which `#declared-name-qualifier` scopes the same way on a declared name. + match + (?:(?<=[A-Za-z0-9_)\]]\.)|(?<!\.))\b((?:r#)?[A-Za-z_][A-Za-z0-9_]*)\b(?=\s*(?:\[[^\[\]]*\]\s*)?(?:\([^()]*(?:\([^()]*(?:\([^()]*\)[^()]*)*\)[^()]*)*\)\s*)?\.) + name + entity.name.type.carbon + + + captures + + 1 + + name + punctuation.definition.raw-identifier.carbon + + + comment + Unqualified names and qualified member names in a type context. A `.` with no preceding qualifier (such as a struct field `.x`) is left to `#identifiers`. + match + (?:(?<=[A-Za-z0-9_)\]]\.)|(?<!\.))\b(r#)?[A-Za-z_][A-Za-z0-9_]*\b + name + entity.name.type.carbon + + + include + #identifiers + + + include + #punctuation + + + scopeName source.carbon diff --git a/utils/textmate/render_sample.py b/utils/textmate/render_sample.py index e815365fd63a..cdb79be58814 100755 --- a/utils/textmate/render_sample.py +++ b/utils/textmate/render_sample.py @@ -36,10 +36,12 @@ _GRAMMAR_PATH = ( ) # A theme built for this grammar rather than taken from an editor. Each family -# of related scopes gets one color, and bold and italic distinguish the scopes -# within a family, so every scope the grammar emits renders differently and a -# change to what it scopes is visible in the rendering. A scope with no entry of -# its own takes its family's. The colors are Catppuccin Mocha's. +# of related scopes gets one color, and bold, italic, and underline distinguish +# the scopes within a family. Every scope the grammar picks from context renders +# differently, so a change to what it scopes is visible in the rendering. Scopes +# that follow from the spelling alone, such as a bracket's shape, can share a +# rendering, since the text already shows them. A scope with no entry of its own +# takes its family's. The colors are Catppuccin Mocha's. _COLORS = { "comment": "#7f849c", "punctuation.definition.comment": "#7f849c", @@ -53,10 +55,17 @@ _COLORS = { "entity.name.type": "#f9e2af", "support.type": "#f9e2af", "support.class": "#f9e2af", + "entity.other.inherited-class": "#f9e2af", "entity.name.namespace": "#f5e0dc", + "entity.name.scope-resolution": "#f5e0dc", "entity.name.tag": "#f5e0dc", "entity.name.function": "#89b4fa", + "support.function": "#89b4fa", "variable": "#cdd6f4", + # Members of something else: a field or other member read through `.` or + # `->`, and a choice's alternatives. + "variable.other.property": "#eba0ac", + "variable.other.enummember": "#eba0ac", "string": "#a6e3a1", "constant.character.escape": "#f5c2e7", "constant.numeric": "#fab387", @@ -76,14 +85,25 @@ _STYLES = { "storage.modifier": "italic", "constant.language": "bold", "keyword.other": "italic", + "keyword.operator.type.pointer": "bold", "punctuation.terminator": "bold", "punctuation.definition.string": "italic", "punctuation.definition.raw-identifier": "bold italic", "support.type": "italic", "support.class": "bold", + "entity.name.type.class": "bold italic", + "entity.other.inherited-class": "underline", + "entity.name.namespace.library": "bold", + "entity.name.scope-resolution": "bold italic", "entity.name.tag": "italic", + "entity.name.function.definition": "bold", + "entity.name.function.member": "italic", + "support.function": "bold italic", "variable.parameter": "italic", "variable.language": "bold", + "variable.other.constant": "bold italic", + "variable.other.property": "italic", + "variable.other.enummember": "bold", "string.quoted.single": "italic", "string.quoted.triple": "bold", "constant.character.escape": "", diff --git a/utils/textmate/tmlanguage.py b/utils/textmate/tmlanguage.py index 3cdcfe5657cc..6b6649032c33 100644 --- a/utils/textmate/tmlanguage.py +++ b/utils/textmate/tmlanguage.py @@ -234,30 +234,42 @@ def _append_capture_tokens( group's text takes on top of `scopes`; group `"0"` is the whole match. The tokens tile the match with no gaps: text not covered by a listed group is still appended, under `scopes` alone. + + Groups nest, so the scopes do too: text inside `((//)(@x))` carries the + scope of group 1 and then the scope of whichever of 2 and 3 covers it. + Enclosing groups have the lower number, which is what puts them lower in + the stack. """ if not captures: _append_token(tokens, linenum, match.start(), match.end(), scopes) return - pos = match.start() + spans = [] for group in range((match.re.groups or 0) + 1): spec = captures.get(str(group)) - # Skip a group the grammar does not name, one that did not - # participate in the match (`start` is then -1), and one that lies - # behind text already appended, since tokens come out in order. - if spec is None or match.start(group) < pos: + start, end = match.span(group) + # Skip a group the grammar does not name, one that did not participate + # in the match, whose `start` is then -1, and one that matched empty. + if spec is None or start < 0 or start == end: continue - if match.start(group) == match.end(group): - continue - _append_token(tokens, linenum, pos, match.start(group), scopes) + spans.append((start, end, spec["name"])) + edges = sorted( + {match.start(), match.end()}.union( + point for start, end, _ in spans for point in (start, end) + ) + ) + for start, end in zip(edges, edges[1:]): _append_token( tokens, linenum, - match.start(group), - match.end(group), - scopes + [spec["name"]], + start, + end, + scopes + + [ + name + for span_start, span_end, name in spans + if span_start <= start and end <= span_end + ], ) - pos = match.end(group) - _append_token(tokens, linenum, pos, match.end(), scopes) def _push_scope( diff --git a/utils/vscode/carbon.tmLanguage.json b/utils/vscode/carbon.tmLanguage.json index 6b1ff9918ccd..2d58b7ed493d 100644 --- a/utils/vscode/carbon.tmLanguage.json +++ b/utils/vscode/carbon.tmLanguage.json @@ -10,7 +10,11 @@ { "include": "#comments" }, { "include": "#cpp-inline" }, { "include": "#strings" }, + { "include": "#builtin-functions" }, + { "include": "#choice-definitions" }, { "include": "#declarations" }, + { "include": "#inheritance" }, + { "include": "#type-annotation" }, { "include": "#keywords" }, { "include": "#literals" }, { "include": "#numbers" }, @@ -22,12 +26,12 @@ "comments": { "patterns": [ { - "comment": "Toolchain directives, which are comments the driver acts on.", - "name": "comment.line.double-slash.carbon", - "match": "(//)(@(?:dump-sem-ir-(?:begin|end)|include-in-dumps))\\b.*$", + "comment": "Toolchain directives. The comment scope sits on a capture rather than on the rule, to leave the leading indentation outside it.", + "match": "^\\s*((//)(@(?:dump-sem-ir-(?:begin|end)|include-in-dumps)))$", "captures": { - "1": { "name": "punctuation.definition.comment.carbon" }, - "2": { "name": "keyword.other.directive.carbon" } + "1": { "name": "comment.line.double-slash.carbon" }, + "2": { "name": "punctuation.definition.comment.carbon" }, + "3": { "name": "keyword.other.directive.carbon" } } }, { @@ -43,20 +47,22 @@ "patterns": [ { "comment": "Inline C++, block form.", - "begin": "\\b(?:(import)\\s+(Cpp)\\s+(inline)|(inline)\\s+(Cpp))\\s*(''')([^\\s'\\\"#]*)", + "begin": "\\b(?:(import)\\s+(Cpp)\\s+(inline)|(inline)\\s+(Cpp))\\s*(''')([^\\s'\\\"#]*)(?:[ \\t]*((//)(?:[ \\t][^\\n]*)?)$)?", "end": "(''')\\s*(;)?", "beginCaptures": { - "1": { "name": "storage.type.carbon" }, + "1": { "name": "keyword.control.import.carbon" }, "2": { "name": "support.class.carbon" }, "3": { "name": "storage.type.carbon" }, "4": { "name": "storage.type.carbon" }, "5": { "name": "support.class.carbon" }, "6": { "name": "punctuation.definition.string.begin.carbon" }, - "7": { "name": "entity.name.tag.language.carbon" } + "7": { "name": "entity.name.tag.language.carbon" }, + "8": { "name": "comment.line.double-slash.carbon" }, + "9": { "name": "punctuation.definition.comment.carbon" } }, "endCaptures": { "1": { "name": "punctuation.definition.string.end.carbon" }, - "2": { "name": "punctuation.terminator.carbon" } + "2": { "name": "punctuation.terminator.statement.carbon" } }, "contentName": "meta.embedded.block.cpp", "patterns": [{ "include": "source.cpp" }] @@ -66,7 +72,7 @@ "begin": "\\b(?:(import)\\s+(Cpp)\\s+(inline)|(inline)\\s+(Cpp))\\s*(\")", "end": "(\")\\s*(;)?", "beginCaptures": { - "1": { "name": "storage.type.carbon" }, + "1": { "name": "keyword.control.import.carbon" }, "2": { "name": "support.class.carbon" }, "3": { "name": "storage.type.carbon" }, "4": { "name": "storage.type.carbon" }, @@ -75,7 +81,7 @@ }, "endCaptures": { "1": { "name": "punctuation.definition.string.end.carbon" }, - "2": { "name": "punctuation.terminator.carbon" } + "2": { "name": "punctuation.terminator.statement.carbon" } }, "contentName": "meta.embedded.inline.cpp", "patterns": [{ "include": "source.cpp" }] @@ -87,12 +93,14 @@ { "comment": "Block string literal, with an optional file type indicator, raw at `###` level.", "name": "string.quoted.triple.carbon", - "begin": "(#{3,})(''')([^\\s'\\\"#]*)", + "begin": "(#{3,})(''')([^\\s'\\\"#]*)(?:[ \\t]*((//)(?:[ \\t][^\\n]*)?)$)?", "end": "(''')\\1", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.carbon" }, "2": { "name": "punctuation.definition.string.begin.carbon" }, - "3": { "name": "entity.name.tag.language.carbon" } + "3": { "name": "entity.name.tag.language.carbon" }, + "4": { "name": "comment.line.double-slash.carbon" }, + "5": { "name": "punctuation.definition.comment.carbon" } }, "endCaptures": { "1": { "name": "punctuation.definition.string.end.carbon" } @@ -102,12 +110,14 @@ { "comment": "Block string literal, with an optional file type indicator, raw at `##` level.", "name": "string.quoted.triple.carbon", - "begin": "(##)(''')([^\\s'\\\"#]*)", + "begin": "(##)(''')([^\\s'\\\"#]*)(?:[ \\t]*((//)(?:[ \\t][^\\n]*)?)$)?", "end": "('''##)", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.carbon" }, "2": { "name": "punctuation.definition.string.begin.carbon" }, - "3": { "name": "entity.name.tag.language.carbon" } + "3": { "name": "entity.name.tag.language.carbon" }, + "4": { "name": "comment.line.double-slash.carbon" }, + "5": { "name": "punctuation.definition.comment.carbon" } }, "endCaptures": { "1": { "name": "punctuation.definition.string.end.carbon" } @@ -117,12 +127,14 @@ { "comment": "Block string literal, with an optional file type indicator, raw at `#` level.", "name": "string.quoted.triple.carbon", - "begin": "(#)(''')([^\\s'\\\"#]*)", + "begin": "(#)(''')([^\\s'\\\"#]*)(?:[ \\t]*((//)(?:[ \\t][^\\n]*)?)$)?", "end": "('''#)", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.carbon" }, "2": { "name": "punctuation.definition.string.begin.carbon" }, - "3": { "name": "entity.name.tag.language.carbon" } + "3": { "name": "entity.name.tag.language.carbon" }, + "4": { "name": "comment.line.double-slash.carbon" }, + "5": { "name": "punctuation.definition.comment.carbon" } }, "endCaptures": { "1": { "name": "punctuation.definition.string.end.carbon" } @@ -132,11 +144,13 @@ { "comment": "Block string literal, with an optional file type indicator.", "name": "string.quoted.triple.carbon", - "begin": "(''')([^\\s'\\\"#]*)", + "begin": "(''')([^\\s'\\\"#]*)(?:[ \\t]*((//)(?:[ \\t][^\\n]*)?)$)?", "end": "(''')", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.carbon" }, - "2": { "name": "entity.name.tag.language.carbon" } + "2": { "name": "entity.name.tag.language.carbon" }, + "3": { "name": "comment.line.double-slash.carbon" }, + "4": { "name": "punctuation.definition.comment.carbon" } }, "endCaptures": { "1": { "name": "punctuation.definition.string.end.carbon" } @@ -146,11 +160,13 @@ { "comment": "A `\"\"\"` block is always an error, but highlighting it as a block string keeps the rest of the file readable.", "name": "string.quoted.triple.carbon", - "begin": "(\"\"\")([^\\s'\\\"#]*)", + "begin": "(\"\"\")([^\\s'\\\"#]*)(?:[ \\t]*((//)(?:[ \\t][^\\n]*)?)$)?", "end": "(\"\"\")", "beginCaptures": { "1": { "name": "punctuation.definition.string.begin.carbon" }, - "2": { "name": "entity.name.tag.language.carbon" } + "2": { "name": "entity.name.tag.language.carbon" }, + "3": { "name": "comment.line.double-slash.carbon" }, + "4": { "name": "punctuation.definition.comment.carbon" } }, "endCaptures": { "1": { "name": "punctuation.definition.string.end.carbon" } @@ -231,7 +247,7 @@ "patterns": [ { "name": "constant.character.escape.carbon", - "match": "\\\\(?:[tnr0'\\\"\\\\]|x[0-9A-Fa-f]{2}|u\\{[0-9A-Fa-f]+\\})" + "match": "\\\\(?:[tnr0'\\\"\\\\]|x[0-9A-F]{2}|u\\{[0-9A-F]+\\})" } ] }, @@ -239,7 +255,7 @@ "patterns": [ { "name": "constant.character.escape.carbon", - "match": "\\\\#(?:[tnr0'\\\"\\\\]|x[0-9A-Fa-f]{2}|u\\{[0-9A-Fa-f]+\\})" + "match": "\\\\#(?:[tnr0'\\\"\\\\]|x[0-9A-F]{2}|u\\{[0-9A-F]+\\})" } ] }, @@ -247,7 +263,7 @@ "patterns": [ { "name": "constant.character.escape.carbon", - "match": "\\\\##(?:[tnr0'\\\"\\\\]|x[0-9A-Fa-f]{2}|u\\{[0-9A-Fa-f]+\\})" + "match": "\\\\##(?:[tnr0'\\\"\\\\]|x[0-9A-F]{2}|u\\{[0-9A-F]+\\})" } ] }, @@ -255,46 +271,383 @@ "patterns": [ { "name": "constant.character.escape.carbon", - "match": "\\\\#{3,}(?:[tnr0'\\\"\\\\]|x[0-9A-Fa-f]{2}|u\\{[0-9A-Fa-f]+\\})" + "match": "\\\\#{3,}(?:[tnr0'\\\"\\\\]|x[0-9A-F]{2}|u\\{[0-9A-F]+\\})" + } + ] + }, + "builtin-functions": { + "patterns": [ + { + "comment": "A builtin function declaration (`fn ... = \"...\"`), scoping the string contents as `support.function.builtin`.", + "begin": "\\b(fn)\\b(?=[^\"/;]*=\\s*\")", + "beginCaptures": { + "1": { "name": "storage.type.carbon" } + }, + "end": "(?=;)|$", + "patterns": [ + { + "match": "(=)\\s*((\")([^\"\\\\\\n]*)(\"))", + "captures": { + "1": { "name": "keyword.operator.carbon" }, + "2": { "name": "string.quoted.double.carbon" }, + "3": { "name": "punctuation.definition.string.begin.carbon" }, + "4": { "name": "support.function.builtin.carbon" }, + "5": { "name": "punctuation.definition.string.end.carbon" } + } + }, + { "include": "#declarations" }, + { "include": "#comments" }, + { "include": "#strings" }, + { "include": "#type-annotation" }, + { "include": "#keywords" }, + { "include": "#literals" }, + { "include": "#numbers" }, + { "include": "#operators" }, + { "include": "#identifiers" }, + { "include": "#punctuation" } + ] } ] }, "declarations": { "patterns": [ { - "comment": "Function declarations, including lambdas with a name. `destroy` is a keyword naming a destructor, not a name.", - "match": "\\b(fn)\\s+(?!destroy\\b)((?:r#)?[A-Za-z_][A-Za-z0-9_]*)", + "comment": "The name a function declaration declares, after any qualifiers, or the `destroy` keyword.", + "begin": "(?<=\\bfn)\\s+(?=(?:r#)?[A-Za-z_])", + "end": "(?:(destroy)|((?:r#)?[A-Za-z_][A-Za-z0-9_]*))\\b(?!\\s*(?:\\[[^\\[\\]]*\\]\\s*)?(?:\\([^()]*(?:\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*)?\\.)|(?=[^\\sA-Za-z_])|$", + "endCaptures": { + "1": { "name": "keyword.other.carbon" }, + "2": { "name": "entity.name.function.definition.carbon" } + }, + "patterns": [{ "include": "#declared-name-qualifier" }] + }, + { + "comment": "The name a class declaration declares, given `entity.name.type.class` for themes that color classes apart from other types.", + "begin": "(?<=\\bclass)\\s+(?=(?:r#)?[A-Za-z_])", + "end": "((?:r#)?[A-Za-z_][A-Za-z0-9_]*)\\b(?!\\s*(?:\\[[^\\[\\]]*\\]\\s*)?(?:\\([^()]*(?:\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*)?\\.)|(?=[^\\sA-Za-z_])|$", + "endCaptures": { + "1": { "name": "entity.name.type.class.carbon" } + }, + "patterns": [{ "include": "#declared-name-qualifier" }] + }, + { + "comment": "The name the other nominal type declarations declare.", + "begin": "(?:(?<=\\balias)|(?<=\\bconstraint)|(?<=\\binterface))\\s+(?=(?:r#)?[A-Za-z_])", + "end": "((?:r#)?[A-Za-z_][A-Za-z0-9_]*)\\b(?!\\s*(?:\\[[^\\[\\]]*\\]\\s*)?(?:\\([^()]*(?:\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*)?\\.)|(?=[^\\sA-Za-z_])|$", + "endCaptures": { + "1": { "name": "entity.name.type.carbon" } + }, + "patterns": [{ "include": "#declared-name-qualifier" }] + }, + { + "comment": "`let` and `var` bindings, with optional modifiers before the name. `_` and `self` are left to `#literals`.", + "match": "\\b(let)\\s+((?:(?:generic|ref|template|unused|var)\\s+)*)(?!_\\s*:)(r#)?([A-Za-z_][A-Za-z0-9_]*)(?=\\s*:(?![=!?]))", "captures": { "1": { "name": "storage.type.carbon" }, - "2": { "name": "entity.name.function.carbon" } + "2": { "name": "storage.modifier.carbon" }, + "3": { "name": "punctuation.definition.raw-identifier.carbon" }, + "4": { "name": "variable.other.constant.carbon" } } }, { - "comment": "Nominal type declarations.", - "match": "\\b(alias|choice|class|constraint|interface)\\s+((?:r#)?[A-Za-z_][A-Za-z0-9_]*)", + "match": "\\b(var)\\s+((?:(?:generic|ref|template|unused)\\s+)*)(?!(?:_|self)\\s*:)(r#)?([A-Za-z_][A-Za-z0-9_]*)(?=\\s*:(?![=!?]))", "captures": { "1": { "name": "storage.type.carbon" }, - "2": { "name": "entity.name.type.carbon" } + "2": { "name": "storage.modifier.carbon" }, + "3": { "name": "punctuation.definition.raw-identifier.carbon" }, + "4": { "name": "variable.other.carbon" } } }, { - "comment": "Package, namespace, and import names. `library` and `inline` are keywords that may follow `import`, not names.", - "match": "\\b(package|namespace|import)\\s+(?!(?:library|inline)\\b)((?:r#)?[A-Za-z_][A-Za-z0-9_]*)", + "comment": "Package, namespace, and import names, excluding keywords (`library`, `inline`) and `Core` and `Cpp`.", + "match": "\\b(import)\\s+(?!(?:library|inline|Core|Cpp)\\b)((?:r#)?[A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.import.carbon" }, + "2": { "name": "entity.name.namespace.carbon" } + } + }, + { + "match": "\\b(package|namespace)\\s+(?!(?:library|Core|Cpp)\\b)((?:r#)?[A-Za-z_][A-Za-z0-9_]*)", "captures": { "1": { "name": "storage.type.carbon" }, "2": { "name": "entity.name.namespace.carbon" } } + }, + { + "comment": "A library name, written as a string, with `entity.name.namespace.library` nested inside the string scope.", + "match": "\\b(library)\\s+((\")((?:\\\\.|[^\"\\\\\\n])*)(\"))", + "captures": { + "1": { "name": "storage.type.carbon" }, + "2": { "name": "string.quoted.double.carbon" }, + "3": { "name": "punctuation.definition.string.begin.carbon" }, + "4": { "name": "entity.name.namespace.library.carbon" }, + "5": { "name": "punctuation.definition.string.end.carbon" } + } } ] }, + "declared-name-qualifier": { + "patterns": [ + { + "comment": "One qualifier on a declared name, such as `N.` or `Base(T: type).`, matched when followed by `.` after any parameter lists. `entity.name.scope-resolution` is nested inside `entity.name.type` so themes without a scope-resolution rule fall back to the type color.", + "begin": "(((?:r#)?[A-Za-z_][A-Za-z0-9_]*))\\b(?=\\s*(?:\\[[^\\[\\]]*\\]\\s*)?(?:\\([^()]*(?:\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*)?\\.)", + "beginCaptures": { + "1": { "name": "entity.name.type.carbon" }, + "2": { "name": "entity.name.scope-resolution.carbon" } + }, + "end": "(\\.)", + "endCaptures": { + "1": { "name": "punctuation.separator.dot-access.carbon" } + }, + "patterns": [{ "include": "#type-body" }] + } + ] + }, + "type-annotation": { + "patterns": [ + { + "comment": "A type expression, from the token that introduces it to the first token that cannot continue one.", + "name": "meta.type.annotation.carbon", + "begin": "(:!)|(:\\?)|(:(?![=!?]))|((?\\?)|((?(?!\\?))|\\b(as)\\b|\\b(adapt)\\b|\\b(require)\\b", + "beginCaptures": { + "1": { "name": "keyword.operator.type.annotation.symbolic.carbon" }, + "2": { "name": "keyword.operator.type.annotation.form.carbon" }, + "3": { "name": "keyword.operator.type.annotation.carbon" }, + "4": { "name": "keyword.operator.function-result.form.carbon" }, + "5": { "name": "keyword.operator.function-result.carbon" }, + "6": { "name": "keyword.operator.expression.as.carbon" }, + "7": { "name": "storage.type.carbon" }, + "8": { "name": "storage.type.carbon" } + }, + "end": "(?=[,;={}\\)\\]]|[-+/%!<>|^~?@\\\\]|//|\\b(?:in|and|or|not|as|impls)\\b|$)", + "patterns": [{ "include": "#type-body" }] + } + ] + }, + "type-body": { + "patterns": [ + { + "comment": "Argument and grouping parentheses, which nest rather than ending the type.", + "begin": "\\(", + "end": "(\\))|$", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.carbon" + } + }, + "patterns": [{ "include": "#type-body" }] + }, + { + "begin": "\\[", + "end": "(\\])|$", + "beginCaptures": { + "0": { + "name": "punctuation.section.brackets.begin.bracket.square.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.brackets.end.bracket.square.carbon" + } + }, + "patterns": [{ "include": "#type-body" }] + }, + { + "comment": "A `where` clause switches to expression scoping so `=` does not end the enclosing type as an initializer, and ends at a `)` or `]` it did not open.", + "begin": "\\bwhere\\b", + "beginCaptures": { + "0": { "name": "keyword.other.where.carbon" } + }, + "end": "(?=[;{}\\)\\]]|$)", + "patterns": [ + { "include": "#expression-parens" }, + { "include": "$self" } + ] + }, + { "include": "#impls-clause" }, + { "include": "#comments" }, + { "include": "#strings" }, + { + "comment": "`typeof` takes an expression operand, switching out of `#type-body`.", + "begin": "\\b(typeof)\\s*(\\()", + "end": "(\\))|$", + "beginCaptures": { + "1": { "name": "keyword.operator.expression.typeof.carbon" }, + "2": { + "name": "punctuation.section.parens.begin.bracket.round.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.carbon" + } + }, + "patterns": [ + { "include": "#expression-parens" }, + { "include": "$self" } + ] + }, + { "include": "#keywords" }, + { "include": "#literals" }, + { "include": "#numbers" }, + { + "comment": "Pointer `*`, written directly after the pointee type.", + "name": "keyword.operator.type.pointer.carbon", + "match": "(?<=[A-Za-z0-9_)\\]*])\\*(?!=)" + }, + { "include": "#operators" }, + { "include": "#bindings" }, + { + "comment": "A qualifier in a type, which `#declared-name-qualifier` scopes the same way on a declared name.", + "name": "entity.name.type.carbon", + "match": "(?:(?<=[A-Za-z0-9_)\\]]\\.)|(?|^~?@\\\\]|//|\\b(?:in|and|or|not|as|impls)\\b|$)", + "patterns": [{ "include": "#inheritance-body" }] + }, + { "include": "#type-body" } + ], + "name": "meta.type.annotation.carbon" + }, + { + "comment": "A `base:` declaration, excluding `.base` member access and `base class`.", + "name": "meta.inheritance-clause.carbon", + "begin": "(?|^~?@\\\\]|//|\\b(?:in|and|or|not|as|impls)\\b|$)", + "patterns": [{ "include": "#inheritance-body" }] + }, + { "include": "#impls-clause" } + ] + }, + "impls-clause": { + "patterns": [ + { + "name": "meta.inheritance-clause.carbon", + "begin": "\\b(impls)\\b", + "beginCaptures": { + "1": { "name": "keyword.operator.expression.impls.carbon" } + }, + "end": "(?=[,;={}\\)\\]]|[-+/%!<>|^~?@\\\\]|//|\\b(?:in|and|or|not|as|impls)\\b|$)", + "patterns": [{ "include": "#inheritance-body" }] + } + ] + }, + "inheritance-body": { + "patterns": [ + { + "comment": "Only the interface itself is scoped as `entity.other.inherited-class`; its argument list switches to expression scoping.", + "begin": "(?<=[A-Za-z0-9_\\]])\\(", + "end": "(\\))|$", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.carbon" + } + }, + "patterns": [ + { "include": "#expression-parens" }, + { "include": "$self" } + ] + }, + { + "comment": "Grouping parentheses around an interface name stay in `#inheritance-body`.", + "begin": "\\(", + "end": "(\\))|$", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.carbon" + } + }, + "patterns": [{ "include": "#inheritance-body" }] + }, + { + "comment": "A `where` clause switches to expression scoping and ends at a `)` or `]` it did not open.", + "begin": "\\b(where)\\b", + "beginCaptures": { + "1": { "name": "keyword.other.where.carbon" } + }, + "end": "(?=[;{}\\)\\]]|$)", + "patterns": [ + { "include": "#expression-parens" }, + { "include": "$self" } + ] + }, + { "include": "#keywords" }, + { "include": "#literals" }, + { + "comment": "The final identifier of the interface or base class name; any preceding qualifiers fall through to `#type-body`.", + "name": "entity.other.inherited-class.carbon", + "match": "\\b(?:r#)?[A-Za-z_][A-Za-z0-9_]*\\b(?!\\s*\\.)" + }, + { "include": "#type-body" } + ] + }, "keywords": { "patterns": [ { - "name": "storage.type.carbon", - "match": "\\b(adapt|alias|choice|class|constraint|fn|import|inline|interface|let|library|match_first|namespace|observe|require|var)\\b" + "comment": "`.base` member access, matched before `base` as an introducer.", + "name": "keyword.other.base.carbon", + "match": "(?<=\\.)\\b(base)\\b" }, { - "comment": "`base` introduces a base class declaration unless it modifies one.", + "name": "keyword.control.import.carbon", + "match": "\\b(import)\\b" + }, + { + "name": "storage.type.carbon", + "match": "\\b(adapt|alias|choice|class|constraint|fn|inline|interface|let|library|match_first|namespace|observe|require|var)\\b" + }, + { + "comment": "`base` as an introducer (not `base class`).", "name": "storage.type.carbon", "match": "\\b(base)\\b(?!\\s*class\\b)" }, @@ -304,10 +657,10 @@ }, { "name": "storage.type.carbon", - "match": "\\b(impl)\\b(?!\\s*(fn|library|package)\\b)" + "match": "\\b(impl)\\b(?!\\s*(adapt|alias|base|choice|class|constraint|export|fn|impl|import|interface|let|library|match_first|namespace|observe|package|require|var)\\b)" }, { - "comment": "`package` is an introducer unless it begins a qualified name.", + "comment": "`package` as an introducer (not `package.`).", "name": "storage.type.carbon", "match": "\\b(package)\\b(?!\\.)" }, @@ -316,7 +669,7 @@ "match": "\\b(abstract|const|eval|extend|extern|final|generic|musteval|override|partial|private|protected|ref|runtime|static|template|unsafe|unused|val|virtual)\\b" }, { - "comment": "`default` is a declaration modifier unless it opens a match arm.", + "comment": "`default` as a modifier (not `default =>`).", "name": "storage.modifier.carbon", "match": "\\b(default)\\b(?!\\s*=>)" }, @@ -330,29 +683,50 @@ }, { "name": "storage.modifier.carbon", - "match": "\\b(impl)\\b(?=\\s*(fn|library|package)\\b)" + "match": "\\b(impl)\\b(?=\\s*(adapt|alias|base|choice|class|constraint|export|fn|impl|import|interface|let|library|match_first|namespace|observe|package|require|var)\\b)" }, { "name": "keyword.control.carbon", "match": "\\b(break|case|continue|else|for|if|match|return|returned|then|while)\\b" }, { - "comment": "`default` is a match arm here, and a declaration modifier elsewhere.", + "comment": "`default` in a `match` clause.", "name": "keyword.control.carbon", "match": "\\b(default)\\b(?=\\s*=>)" }, { "name": "keyword.control.carbon", - "match": "\\b(and|as|impls|in|like|not|or|typeof|where)\\b" + "match": "\\b(and|or)\\b" }, + { + "name": "keyword.operator.expression.not.carbon", + "match": "\\b(not)\\b" + }, + { + "comment": "Fallback when not matched by `#type-annotation` or `#inheritance`.", + "name": "keyword.operator.expression.as.carbon", + "match": "\\b(as)\\b" + }, + { + "name": "keyword.operator.expression.impls.carbon", + "match": "\\b(impls)\\b" + }, + { + "name": "keyword.operator.expression.in.carbon", + "match": "\\b(in)\\b" + }, + { + "name": "keyword.operator.expression.like.carbon", + "match": "\\b(like)\\b" + }, + { + "name": "keyword.operator.expression.typeof.carbon", + "match": "\\b(typeof)\\b" + }, + { "name": "keyword.other.where.carbon", "match": "\\b(where)\\b" }, { "name": "keyword.other.carbon", "match": "\\b(destroy|each|expand|forall|form|friend)\\b" - }, - { - "comment": "`.base` names the base class subobject.", - "name": "keyword.other.carbon", - "match": "(?<=\\.)\\b(base)\\b" } ] }, @@ -365,23 +739,27 @@ "match": "\\b(_)\\b" }, { - "comment": "Language-provided package roots.", + "comment": "Built-in package names.", "name": "support.class.carbon", "match": "\\b(Core|Cpp)\\b" }, { - "comment": "`package` as a qualified-name root names the current package.", + "comment": "`package` as a qualifier.", "name": "variable.language.carbon", "match": "\\b(package)\\b(?=\\.)" }, { "name": "constant.language.carbon", "match": "\\b(true|false)\\b" }, { "name": "support.type.builtin.carbon", - "match": "\\b(array|auto|bool|char|str|type)\\b" + "match": "\\b(array|auto|type)\\b" }, { - "comment": "Integer and float type literals. The lexer accepts any width, so this must not be restricted to the common ones.", - "name": "support.type.builtin.carbon", + "name": "support.type.primitive.carbon", + "match": "\\b(bool|char|str)\\b" + }, + { + "comment": "Integer and floating-point type literals.", + "name": "support.type.primitive.carbon", "match": "\\b[iuf][1-9][0-9]*\\b" } ] @@ -389,14 +767,41 @@ "numbers": { "patterns": [ { + "comment": "Each numeric rule matches a full alphanumeric word starting with a digit so a malformed suffix is not split into an identifier. Real literals exclude a leading `.` or `->` so tuple access like `t.0.1` is not matched as a real.", "name": "constant.numeric.hex.carbon", - "match": "\\b0x[_0-9A-Fa-f]*(?:\\.[_0-9A-Fa-f]*)?(?:[pP][-+]?[0-9]+)?" + "match": "(?)\\b(0x)[_0-9A-Za-z]*\\.[0-9A-Za-z][_0-9A-Za-z]*(?:(?<=[a-z])[-+][0-9A-Za-z][_0-9A-Za-z]*)?", + "captures": { + "1": { "name": "keyword.other.unit.hexadecimal.carbon" } + } + }, + { + "name": "constant.numeric.hex.carbon", + "match": "\\b(0x)[_0-9A-Za-z]*", + "captures": { + "1": { "name": "keyword.other.unit.hexadecimal.carbon" } + } + }, + { + "name": "constant.numeric.octal.carbon", + "match": "\\b(0o)[_0-9A-Za-z]*", + "captures": { + "1": { "name": "keyword.other.unit.octal.carbon" } + } + }, + { + "name": "constant.numeric.binary.carbon", + "match": "\\b(0b)[_0-9A-Za-z]*", + "captures": { + "1": { "name": "keyword.other.unit.binary.carbon" } + } }, - { "name": "constant.numeric.octal.carbon", "match": "\\b0o[_0-7]*" }, - { "name": "constant.numeric.binary.carbon", "match": "\\b0b[_01]*" }, { "name": "constant.numeric.decimal.carbon", - "match": "\\b[0-9][_0-9]*(?:\\.[_0-9]+)?(?:[eE][-+]?[0-9]+)?" + "match": "(?)\\b[0-9][_0-9A-Za-z]*\\.[0-9A-Za-z][_0-9A-Za-z]*(?:(?<=[a-z])[-+][0-9A-Za-z][_0-9A-Za-z]*)?" + }, + { + "name": "constant.numeric.decimal.carbon", + "match": "\\b[0-9][_0-9A-Za-z]*" }, { "comment": "Positional parameter, as used in lambdas.", @@ -407,50 +812,247 @@ }, "operators": { "patterns": [ + { + "name": "keyword.operator.type.annotation.symbolic.carbon", + "match": ":!" + }, + { + "name": "keyword.operator.type.annotation.form.carbon", + "match": ":\\?" + }, + { + "name": "keyword.operator.type.annotation.carbon", + "match": ":(?![=!?])" + }, + { + "comment": "`->` directly after an operand is pointer member access rather than a return type arrow.", + "name": "punctuation.separator.pointer-access.carbon", + "match": "(?<=[A-Za-z0-9_)\\]}])\\->(?!\\?)" + }, + { + "name": "keyword.operator.function-result.form.carbon", + "match": "\\->\\?" + }, + { + "name": "keyword.operator.function-result.carbon", + "match": "\\->(?!\\?)" + }, + { "name": "keyword.operator.arrow.fat.carbon", "match": "=>" }, { "name": "keyword.operator.carbon", - "match": "(\\->\\?|>>=|<=>|<<=|\\&=|\\^=|:=|:\\?|==|=>|!=|>=|>>|<=|<>|<<|<\\-|\\-=|\\->|\\-\\-|%=|\\|=|\\+=|\\+\\+|/=|\\*=|\\~=|\\&|@|\\^|:|=|!|>|<|\\-|%|\\.|\\||\\+|\\?|/|\\*|\\~|\\\\)" + "match": "<=>|<<=|>>=|==|!=|<=|>=|<<|>>|\\+\\+|--|\\+=|-=|\\*=|/=|%=|&=|\\|=|\\^=|~=|:=|<-|<>|[-+*/%&|^~!<>=@?\\\\]" } ] }, "identifiers": { "patterns": [ + { "include": "#bindings" }, { - "comment": "Raw identifiers, which suppress keyword meaning.", - "match": "\\b(r#)([A-Z][A-Za-z0-9_]*)", + "comment": "Raw identifiers.", + "name": "variable.other.carbon", + "match": "\\b(r#)([A-Za-z_][A-Za-z0-9_]*)", "captures": { - "1": { "name": "punctuation.definition.raw-identifier.carbon" }, - "2": { "name": "entity.name.type.carbon" } + "1": { "name": "punctuation.definition.raw-identifier.carbon" } } }, { - "match": "\\b(r#)([a-z_][A-Za-z0-9_]*)", - "captures": { - "1": { "name": "punctuation.definition.raw-identifier.carbon" }, - "2": { "name": "variable.other.carbon" } - } + "comment": "Member function call.", + "name": "entity.name.function.member.carbon", + "match": "(?:(?<=\\.)|(?<=\\->))[A-Za-z_][A-Za-z0-9_]*(?=\\s*\\()" }, { - "comment": "An identifier applied to an argument list is a call.", - "name": "entity.name.function.carbon", + "comment": "Member access via `.` or `->`.", + "name": "variable.other.property.carbon", + "match": "(?:(?<=\\.)|(?<=\\->))[A-Za-z_][A-Za-z0-9_]*\\b" + }, + { + "comment": "Function call.", + "name": "entity.name.function.call.carbon", "match": "\\b[A-Za-z_][A-Za-z0-9_]*(?=\\s*\\()" }, { - "comment": "UpperCamel names a type.", - "name": "entity.name.type.carbon", - "match": "\\b[A-Z][A-Za-z0-9_]*\\b" - }, - { - "comment": "lower_snake names a value.", "name": "variable.other.carbon", - "match": "\\b[a-z_][A-Za-z0-9_]*\\b" + "match": "\\b[A-Za-z_][A-Za-z0-9_]*\\b" } ] }, "punctuation": { "patterns": [ - { "name": "punctuation.separator.carbon", "match": "," }, - { "name": "punctuation.terminator.carbon", "match": ";" } + { + "name": "punctuation.section.parens.begin.bracket.round.carbon", + "match": "\\(" + }, + { + "name": "punctuation.section.parens.end.bracket.round.carbon", + "match": "\\)" + }, + { + "name": "punctuation.section.block.begin.bracket.curly.carbon", + "match": "\\{" + }, + { + "name": "punctuation.section.block.end.bracket.curly.carbon", + "match": "\\}" + }, + { + "name": "punctuation.section.brackets.begin.bracket.square.carbon", + "match": "\\[" + }, + { + "name": "punctuation.section.brackets.end.bracket.square.carbon", + "match": "\\]" + }, + { "name": "punctuation.separator.dot-access.carbon", "match": "\\." }, + { "name": "punctuation.separator.comma.carbon", "match": "," }, + { "name": "punctuation.terminator.statement.carbon", "match": ";" } + ] + }, + "choice-definitions": { + "patterns": [ + { + "comment": "A `choice` declaration, scoping names in its body as enum members and closing immediately if there is no body.", + "begin": "\\b(choice)\\b", + "beginCaptures": { + "1": { "name": "storage.type.carbon" } + }, + "end": "(?<=\\})|(?=[^\\s({])", + "patterns": [ + { + "begin": "(?<=\\bchoice)\\s+(?=(?:r#)?[A-Za-z_])", + "end": "((?:r#)?[A-Za-z_][A-Za-z0-9_]*)\\b(?!\\s*(?:\\[[^\\[\\]]*\\]\\s*)?(?:\\([^()]*(?:\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*)?\\.)|(?=[^\\sA-Za-z_])|$", + "endCaptures": { + "1": { "name": "entity.name.type.carbon" } + }, + "patterns": [{ "include": "#declared-name-qualifier" }] + }, + { "include": "#comments" }, + { + "comment": "Choice parameters.", + "begin": "\\(", + "end": "(\\))|$", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.carbon" + } + }, + "patterns": [{ "include": "#choice-parameters" }] + }, + { + "comment": "Choice body.", + "begin": "\\{", + "end": "(\\})|(?=[;=])", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.bracket.curly.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.bracket.curly.carbon" + } + }, + "patterns": [ + { "include": "#comments" }, + { + "comment": "Alternative parameters.", + "begin": "\\(", + "end": "(\\))|$", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.carbon" + } + }, + "patterns": [{ "include": "#choice-parameters" }] + }, + { + "comment": "Invalid implicit parameter list on an alternative, matched so its contents are not scoped as enum members.", + "begin": "\\[", + "end": "(\\])|$", + "beginCaptures": { + "0": { + "name": "punctuation.section.brackets.begin.bracket.square.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.brackets.end.bracket.square.carbon" + } + }, + "patterns": [{ "include": "#choice-parameters" }] + }, + { "include": "#keywords" }, + { "include": "#literals" }, + { + "name": "variable.other.enummember.carbon", + "match": "\\b(?:r#)?[A-Za-z_][A-Za-z0-9_]*\\b" + }, + { "include": "#numbers" }, + { "include": "#operators" }, + { "include": "#punctuation" } + ] + } + ] + } + ] + }, + "choice-parameters": { + "patterns": [ + { "include": "#comments" }, + { "include": "#strings" }, + { "include": "#inheritance" }, + { "include": "#type-annotation" }, + { "include": "#keywords" }, + { "include": "#literals" }, + { "include": "#numbers" }, + { "include": "#operators" }, + { "include": "#identifiers" }, + { "include": "#punctuation" } + ] + }, + "bindings": { + "patterns": [ + { + "comment": "Parameter bindings (`name: Type` when not preceded by `let` or `var`), with `variable.parameter` nested inside `variable.other`.", + "name": "variable.other.carbon", + "match": "(?)\\b(r#)?([A-Za-z_][A-Za-z0-9_]*)(?=\\s*:(?![=!?]))", + "captures": { + "1": { "name": "punctuation.definition.raw-identifier.carbon" }, + "2": { "name": "variable.parameter.carbon" } + } + } + ] + }, + "expression-parens": { + "patterns": [ + { + "comment": "Parentheses nested in an expression that sits inside a type, so that only the matching `)` ends the expression.", + "begin": "\\(", + "end": "(\\))|$", + "beginCaptures": { + "0": { + "name": "punctuation.section.parens.begin.bracket.round.carbon" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.section.parens.end.bracket.round.carbon" + } + }, + "patterns": [ + { "include": "#expression-parens" }, + { "include": "$self" } + ] + } ] } }