v0.2: Pico-8 Lua dialect grammar and language

Reorganize into grammars/<name>/ subdirs ( Zed's [grammars.*] supports
a `path` field, so both grammars ship from this repo without a sibling-
repo split ). Vendor tree-sitter-lua as the fork base for tree-sitter-
pico8-lua; upstream MIT license preserved at grammars/pico-8-lua/
UPSTREAM-LICENSE.md.

Dialect features added: != as ~= alias, \ integer divide, ^^ binary xor,
>>> / <<> / >>< shifts and rotates, compound-assignment statements,
memory peek prefixes @ % $ (% coexists with binary modulo), single-line
`if (cond) stmt [else stmt]` and `while (cond) stmt`, statement-level
print shorthand ?, and `#include path` directives. Identifier rule no
longer accepts ! ? @ $ ( upstream did ).

Pico-8 Lua language ( languages/pico-8-lua/, suffix .p8lua ) ships
highlights with the full ~110 PICO-8 builtins as @function.builtin.
The cart injection now hands __lua__ bodies to pico-8-lua, so .p8 carts
and bare .p8lua files share the dialect-aware grammar. Examples updated
to exercise the dialect end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-01 12:50:41 -07:00
parent 04a92fc16e
commit 39d77a8cae
32 changed files with 32503 additions and 120 deletions
+215
View File
@@ -0,0 +1,215 @@
; --- Keywords ---
"return" @keyword.return
[
"goto"
"in"
"local"
] @keyword
(label_statement) @label
(break_statement) @keyword
(do_statement
["do" "end"] @keyword)
(while_statement
["while" "do" "end"] @keyword.repeat)
(shorthand_while_statement
"while" @keyword.repeat)
(repeat_statement
["repeat" "until"] @keyword.repeat)
(if_statement
["if" "elseif" "else" "then" "end"] @keyword.conditional)
(elseif_statement
["elseif" "then" "end"] @keyword.conditional)
(else_statement
["else" "end"] @keyword.conditional)
(shorthand_if_statement
["if" "else"] @keyword.conditional)
(for_statement
["for" "do" "end"] @keyword.repeat)
(function_declaration
["function" "end"] @keyword.function)
(function_definition
["function" "end"] @keyword.function)
; --- PICO-8 dialect: print shorthand and #include ---
(print_shorthand_statement
directive: "?" @function.builtin)
(include_statement
directive: _ @keyword.directive)
(include_statement
path: (include_path) @string.special.path)
; --- Operators ---
(binary_expression
operator: _ @operator)
(unary_expression
operator: _ @operator)
(compound_assignment_statement
operator: _ @operator)
"=" @operator
[
"and"
"not"
"or"
] @keyword.operator
; --- Punctuation ---
[
";"
":"
","
"."
] @punctuation.delimiter
[
"("
")"
"["
"]"
"{"
"}"
] @punctuation.bracket
; --- Variables and constants ---
(identifier) @variable
(variable_list
(attribute
"<" @punctuation.bracket
(identifier) @attribute
">" @punctuation.bracket))
((identifier) @constant
(#match? @constant "^[A-Z][A-Z_0-9]*$"))
(vararg_expression) @constant
(nil) @constant.builtin
[
(false)
(true)
] @boolean
; PICO-8 callback hooks — recognized by name regardless of definition site.
((identifier) @function.builtin
(#any-of? @function.builtin
"_init" "_update" "_update60" "_draw"))
; --- Tables ---
(field
name: (identifier) @property)
(dot_index_expression
field: (identifier) @property)
(table_constructor
["{" "}"] @constructor)
; --- Functions ---
(parameters
(identifier) @variable.parameter)
(function_declaration
name: [
(identifier) @function
(dot_index_expression
field: (identifier) @function)
])
(function_declaration
name: (method_index_expression
method: (identifier) @function.method))
(assignment_statement
(variable_list
.
name: [
(identifier) @function
(dot_index_expression
field: (identifier) @function)
])
(expression_list
.
value: (function_definition)))
(table_constructor
(field
name: (identifier) @function
value: (function_definition)))
(function_call
name: [
(identifier) @function.call
(dot_index_expression
field: (identifier) @function.call)
(method_index_expression
method: (identifier) @function.method.call)
])
; --- PICO-8 builtin globals ---
(function_call
(identifier) @function.builtin
(#any-of? @function.builtin
; system
"load" "save" "ls" "run" "stop" "assert" "reset" "info" "flip" "printh"
"time" "t" "stat" "extcmd" "holdframe" "_set_fps"
; graphics
"clip" "pset" "pget" "sget" "sset" "fget" "fset" "print" "cursor"
"color" "cls" "camera" "circ" "circfill" "oval" "ovalfill" "line"
"rect" "rectfill" "rrect" "rrectfill" "pal" "palt" "spr" "sspr" "fillp"
; tables
"add" "del" "deli" "count" "all" "foreach" "pairs" "ipairs" "next"
; input
"btn" "btnp"
; audio
"sfx" "music"
; map
"mget" "mset" "map" "tline"
; memory
"peek" "poke" "peek2" "poke2" "peek4" "poke4" "memcpy" "reload"
"cstore" "memset"
; math
"max" "min" "mid" "flr" "ceil" "cos" "sin" "atan2" "sqrt" "abs"
"rnd" "srand"
; bitwise (named forms — operator forms covered by @operator)
"band" "bor" "bxor" "bnot" "shl" "shr" "lshr" "rotl" "rotr"
; custom menu
"menuitem"
; strings / conversion
"tostr" "tonum" "chr" "ord" "sub" "split" "type"
; cart data
"cartdata" "dget" "dset"
; metatables
"setmetatable" "getmetatable" "rawset" "rawget" "rawequal" "rawlen"
; coroutines
"cocreate" "coresume" "costatus" "yield"
; error
"error" "pcall" "xpcall"))
; --- Misc ---
(comment) @comment
(hash_bang_line) @comment.documentation
(number) @number
(string) @string
(escape_sequence) @string.escape