diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index b8753d58..e77bc17b 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -143,6 +143,7 @@
 | svelte | ✓ |  |  | `svelteserver` |
 | sway | ✓ | ✓ | ✓ | `forc` |
 | swift | ✓ |  |  | `sourcekit-lsp` |
+| t32 | ✓ |  |  |  |
 | tablegen | ✓ | ✓ | ✓ |  |
 | task | ✓ |  |  |  |
 | tfvars | ✓ |  | ✓ | `terraform-ls` |
diff --git a/languages.toml b/languages.toml
index 373a8be0..28669c55 100644
--- a/languages.toml
+++ b/languages.toml
@@ -2605,3 +2605,16 @@ indent = { tab-width = 3, unit = "   " }
 [[grammar]]
 name = "forth"
 source = { git = "https://github.com/alexanderbrevig/tree-sitter-forth", rev = "c6fae50a17763af827604627c0fa9e4604aaac0b" }
+
+[[language]]
+name = "t32"
+scope = "source.t32"
+injection-regex = "t32"
+file-types = ["cmm", "t32"]
+roots = []
+comment-token = ";"
+indent = { tab-width = 2, unit = "  " }
+
+[[grammar]]
+name = "t32"
+source = { git = "https://codeberg.org/xasc/tree-sitter-t32", rev = "1dd98248b01e4a3933c1b85b58bab0875e2ba437" }
diff --git a/runtime/queries/t32/highlights.scm b/runtime/queries/t32/highlights.scm
new file mode 100644
index 00000000..c3bba814
--- /dev/null
+++ b/runtime/queries/t32/highlights.scm
@@ -0,0 +1,145 @@
+[
+  "="
+  "^^"
+  "||"
+  "&&"
+  "+"
+  "-"
+  "*"
+  "/"
+  "%"
+  "|"
+  "^"
+  "=="
+  "!="
+  ">"
+  ">="
+  "<="
+  "<"
+  "<<"
+  ">>"
+  ".."
+  "--"
+  "++"
+  "+"
+  "-"
+  "~"
+  "!"
+  "&"
+  "->"
+  "*"
+] @operator
+
+[
+ "("
+ ")"
+ "{"
+ "}"
+ "["
+ "]"
+] @punctuation.bracket
+
+[
+  ","
+  "."
+  ";"
+] @punctuation.delimiter
+
+; Constants
+[
+  (access_class)
+  (address)
+  (bitmask)
+  (file_handle)
+  (frequency)
+  (time)
+] @constant.builtin
+
+[
+  (float)
+  (percentage)
+] @constant.numeric.float
+
+(integer) @constant.numeric.integer
+
+(character) @constant.character
+
+; Strings
+(string) @string
+
+(path) @string.special.path
+
+(symbol) @string.special.symbol
+
+; Returns
+(
+  (command_expression
+    command: (identifier) @keyword.return)
+  (#match? @keyword.return "^[eE][nN][dD]([dD][oO])?$")
+)
+(
+  (command_expression
+    command: (identifier) @keyword.return)
+  (#match? @keyword.return "^[rR][eE][tT][uU][rR][nN]$")
+)
+
+; Subroutine calls
+(subroutine_call_expression
+  command: (identifier) @keyword
+  subroutine: (identifier) @function)
+
+; Subroutine blocks
+(subroutine_block
+  command: (identifier) @keyword
+  subroutine: (identifier) @function)
+
+(labeled_expression
+  label: (identifier) @function
+  (block))
+
+; Parameter declarations
+(parameter_declaration
+  command: (identifier) @keyword
+  (identifier)? @constant.builtin
+  macro: (macro) @variable.parameter)
+
+; Variables, constants and labels
+(macro) @variable
+(internal_c_variable) @variable
+
+(
+  (command_expression
+    command: (identifier) @keyword
+    arguments: (argument_list . (identifier) @label))
+  (#match? @keyword "^[gG][oO][tT][oO]$")
+)
+(labeled_expression
+  label: (identifier) @label)
+
+(
+ (argument_list (identifier) @constant.builtin)
+ (#match? @constant.builtin "^[%/][a-zA-Z][a-zA-Z0-9.]*$")
+)
+(argument_list
+  (identifier) @constant)
+
+; Commands
+(command_expression command: (identifier) @keyword)
+(macro_definition command: (identifier) @keyword)
+
+; Control flow
+(if_block
+  command: (identifier) @keyword.control.conditional.if)
+(else_block
+  command: (identifier) @keyword.control.control.else)
+
+(while_block
+  command: (identifier) @keyword.control.repeat.while)
+(repeat_block
+  command: (identifier) @keyword.control.loop)
+
+(call_expression
+  function: (identifier) @function)
+
+(type_identifier) @type
+(comment) @comment
diff --git a/runtime/queries/t32/injections.scm b/runtime/queries/t32/injections.scm
new file mode 100644
index 00000000..2f0e58eb
--- /dev/null
+++ b/runtime/queries/t32/injections.scm
@@ -0,0 +1,2 @@
+((comment) @injection.content
+  (#set! injection.language "comment"))