Skip to content
225 changes: 225 additions & 0 deletions assets/highlighting-tests/zig.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
// Single-line comment
/// Documentation comment.

// Imports
const std = @import("std");
const builtin = @import("builtin");

// Constants and variables
const answer: i32 = 42;
const pi = 3.14159;
var counter: usize = 0;
pub const name = "Zig";

// Integer literals
const decimal = 123;
const binary = 0b1010_0101;
const octal = 0o755;
const hex = 0xDEAD_BEEF;
const separated = 1_000_000;

// Floating-point literals
const float = 3.14;
const exponent = 1.5e-3;
const hex_float = 0x1.8p1;
const hex_fraction = 0xAB.CD;
const hex_exponent = 0x1P+4;
const separated_float = 1_000.125_000E+2;
const separated_hex_float = 0x1234_5678.9ABC_CDEFp-10;

// Character and string literals
const char = 'a';
const newline = '\n';
const unicode = '\u{1F600}';
const string = "escapes: \" \\ \n \t";

// Multiline string
const multiline =
\\first line
\\
\\second line
\\"quotes", // comments, @builtins, and 123 are literal text
;
const inline_multiline = \\starts on the declaration line
;

// Identifiers
const @"quoted identifier" = 123;
const snake_case = true;
const @"if" = @"quoted identifier";
const @"escaped \"quote\"" = "// not a comment";
const _123 = 123;
const u8_count = 8;
const iffy = false;

// Operators
const arithmetic = 1 + 2 * 3 - 4 / 2 % 2;
const comparison = a == b and c != d or e >= f;
const bitwise = x & y | z ^ w;
const shifts = value << 2 >> 1;
const wrapping = a +% b;
const saturating = a +| b;

// Struct
const Point = struct {
x: i32,
y: i32,

pub fn init(x: i32, y: i32) Point {
return .{ .x = x, .y = y };
}
};

const origin = Point{
.x = 0,
.y = 0,
};

// Enum
const Color = enum {
red,
green,
blue,
};

// Tagged union
const Value = union(enum) {
integer: i64,
float: f64,
boolean: bool,
};

// Arrays, slices, tuples
const array = [_]u8{ 1, 2, 3, 4 };
const slice = array[1..3];
const open_slice = array[1..];
const hex_slice = array[0x1..0x3];
const tuple = .{ 42, true, "hello" };

// Pointers
var value: i32 = 42;
const ptr: *i32 = &value;
const many_ptr: [*]i32 = undefined;
const sentinel_ptr: [*:0]const u8 = undefined;

// Functions
fn add(a: i32, b: i32) i32 {
return a + b;
}

fn generic(comptime T: type, value: T) T {
return value;
}

fn inferred(argument: anytype) @TypeOf(argument) {
return argument;
}

extern fn cFunction(argument: c_int, pointer: *anyopaque) c_longdouble;

const CTypes = .{ c_char, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong, c_longdouble };

const BitFields = packed struct {
empty: u0,
small: i7,
wide: u256,
};

// If / else
fn classify(x: i32) i32 {
if (x > 10) {
return 1;
} else if (x == 10) {
return 0;
} else {
return -1;
}
}

// While / for / labels
fn loops() void {
var i: usize = 0;

while (i < 10) : (i += 1) {
if (i == 5) continue;
if (i == 8) break;
}

for (array, 0..) |item, index| {
_ = item;
_ = index;
}

outer: for (array) |item| {
if (item == 3) break :outer;
}
}

// Switch
fn describe(value: Value) void {
switch (value) {
.integer => |x| _ = x,
.float => |x| _ = x,
.boolean => |x| _ = x,
}
}

fn inRange(number: u8) bool {
return switch (number) {
1...3 => true,
else => false,
};
}

// Optionals
fn optional(value: ?i32) i32 {
return value orelse 0;
}

// Errors
const MyError = error{
NotFound,
InvalidValue,
};

fn mightFail() MyError!i32 {
return error.NotFound;
}

fn handleError() !void {
const result = try mightFail();
_ = result;

_ = mightFail() catch 42;
}

// Defer
fn cleanup() void {
defer std.debug.print("done\n", .{});
}

// Comptime / builtins
const type_of_value = @TypeOf(value);
const size_of_point = @sizeOf(Point);
const alignment = @alignOf(Point);
const field_name = @tagName(Color.red);

// Builtin-heavy expression
const converted = @intCast(@as(u64, 42));
const bits = @bitCast(@as(u32, 0x3F800000));

// Extern / export / calling convention
extern fn external_function(x: i32) i32;

export fn exported_function(x: i32) callconv(.c) i32 {
return x;
}

// Tests
test "basic arithmetic" {
try std.testing.expect(add(1, 2) == 3);
}

test "optional" {
try std.testing.expect(optional(null) == 0);
}
42 changes: 42 additions & 0 deletions crates/lsh/definitions/zig.lsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#[display_name = "Zig"]
#[path = "**/*.zig"]
#[path = "**/*.zon"]
pub fn zig() {
until /$/ {
yield other;

if /\/\/.*/ {
yield comment;
} else if /\\\\.*/ {
yield string;
} else if /'/ {
single_quote_string();
} else if /"/ {
double_quote_string();
} else if /(?:break|catch|continue|defer|else|errdefer|for|if|nosuspend|orelse|resume|return|suspend|switch|try|while)\>/ {
yield keyword.control;
} else if /(?:addrspace|align|allowzero|and|asm|callconv|comptime|const|enum|export|extern|fn|inline|linksection|noalias|noinline|opaque|or|packed|pub|struct|test|threadlocal|union|unreachable|var|volatile)\>/ {
yield keyword.other;
} else if /(?:true|false|null|undefined)\>/ {
yield constant.language;
} else if /(?:anyerror|anyframe|anyopaque|anytype|bool|comptime_float|comptime_int|error|f16|f32|f64|f80|f128|[iu](?:\d+|size)|noreturn|type|void)\>/ {
yield storage.type;
} else if /c_(?:char|short|ushort|int|uint|longdouble|longlong|long|ulonglong|ulong)\>/ {
yield storage.type;
} else if /(?i:0x[\da-f_]+(?:\.[\da-f_]+)?(?:p[+-]?[\d_]+)?|0b[01_]+|0o[0-7_]+|\d[\d_]*(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?)/ {
if /\w+/ {
// Invalid numeric literal
} else {
yield constant.numeric;
}
} else if /@[a-zA-Z_]\w*/ {
yield method;
} else if /(\w+)\s*\(/ {
yield $1 as method;
} else if /\w+/ {
// Gobble word chars to align the next iteration on a word boundary.
}

yield other;
}
}
Loading