fluffos/tools/lpc-syntax/lpc.tmLanguage.json
Yucong Sun e2e21f4e50
lpc-syntax: move the VS Code extension out to fluffos/fluffos-vscode (#1282)
* docs: point VS Code extension README at the fluffos-vscode packaging repo

Packaged .vsix releases now come from fluffos/fluffos-vscode, which pins
a fluffos commit via submodule and builds this directory from that pin.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXqX4Kf55ArA39suS9cdCv

* lpc-syntax: move the VS Code extension out to fluffos/fluffos-vscode

The extension source (extension.js, manifest, language configuration)
now lives in the fluffos/fluffos-vscode repo, which pins a fluffos
commit via submodule and syncs this directory's outputs -- the
tokenizer/formatter/linter, lpc-grammar.json, and the TextMate grammar
-- into the packaged extension at build time. tools/lpc-syntax/ keeps
only the grammar-driven engine those builds consume.

- delete tools/lpc-syntax/vscode/ (extension code, generated lib copies)
- generate_ebnf.py: emit_vscode_assets -> emit_tm_language, writing
  lpc.tmLanguage.json at the tools root next to lpc-grammar.json; the
  lib-copy machinery is gone (the other repo syncs the sources directly)
- fix nondeterministic regen: the function-call reserved-word alternation
  sorted a set union with key=len only, so same-length ordering followed
  the per-process string-hash seed; tie-break alphabetically (verified
  identical output under PYTHONHASHSEED=0/1/42)
- test.mjs: retarget tmLanguage checks to the new path; the
  extension-local checks (lib-copy identity, extension.js wiring,
  language-configuration) moved to fluffos-vscode's scripts/test.mjs
- docs: tools/lpc-syntax/README.md, AGENTS.md paragraph 11, docs/lpc/formatter.md

grammar.ebnf and lpc-grammar.json regenerate byte-identical (bison
3.8.2); the moved tmLanguage differs from the old committed copy only in
the same-length tie order inside the function-call lookahead, which is
order-independent for matching.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXqX4Kf55ArA39suS9cdCv

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:44:50 -07:00

211 lines
5.1 KiB
JSON

{
"$comment": "GENERATED from lpc-grammar.json by generate_ebnf.py (CMake target generate_ebnf) -- do not edit by hand.",
"name": "LPC",
"scopeName": "source.lpc",
"fileTypes": [
"lpc"
],
"patterns": [
{
"include": "#comments"
},
{
"include": "#preprocessor"
},
{
"include": "#textblock"
},
{
"include": "#template"
},
{
"include": "#strings"
},
{
"include": "#chars"
},
{
"include": "#numbers"
},
{
"include": "#functional"
},
{
"include": "#class-keyword"
},
{
"include": "#keywords"
},
{
"include": "#types"
},
{
"include": "#modifiers"
},
{
"include": "#dollar-params"
},
{
"include": "#function-call"
},
{
"include": "#operators"
}
],
"repository": {
"comments": {
"patterns": [
{
"name": "comment.line.double-slash.lpc",
"match": "//.*$"
},
{
"name": "comment.block.lpc",
"begin": "/\\*",
"end": "\\*/"
}
]
},
"preprocessor": {
"name": "meta.preprocessor.lpc",
"begin": "^\\s*(#\\s*[A-Za-z_]*)",
"beginCaptures": {
"1": {
"name": "keyword.control.directive.lpc"
}
},
"end": "(?<!\\\\)$",
"patterns": [
{
"include": "#comments"
},
{
"include": "#strings"
},
{
"name": "string.quoted.other.include.lpc",
"match": "<[^>\\n]*>"
},
{
"include": "#numbers"
},
{
"name": "constant.character.escape.line-continuation.lpc",
"match": "\\\\$"
}
]
},
"textblock": {
"name": "string.unquoted.textblock.lpc",
"begin": "(@@?)([A-Za-z_][A-Za-z0-9_]*)$",
"beginCaptures": {
"1": {
"name": "keyword.operator.textblock.lpc"
},
"2": {
"name": "constant.other.terminator.lpc"
}
},
"end": "^\\2(?![A-Za-z0-9_])",
"endCaptures": {
"0": {
"name": "constant.other.terminator.lpc"
}
}
},
"template": {
"name": "string.interpolated.lpc",
"begin": "`",
"end": "`",
"patterns": [
{
"name": "constant.character.escape.lpc",
"match": "\\\\."
},
{
"name": "meta.embedded.interpolation.lpc",
"begin": "\\$\\{",
"end": "\\}",
"beginCaptures": {
"0": {
"name": "punctuation.section.interpolation.begin.lpc"
}
},
"endCaptures": {
"0": {
"name": "punctuation.section.interpolation.end.lpc"
}
},
"patterns": [
{
"include": "$self"
}
]
}
]
},
"strings": {
"name": "string.quoted.double.lpc",
"begin": "\"",
"end": "\"",
"patterns": [
{
"name": "constant.character.escape.lpc",
"match": "\\\\."
}
]
},
"chars": {
"name": "constant.character.lpc",
"match": "'(\\\\.|[^'\\\\])'"
},
"numbers": {
"name": "constant.numeric.lpc",
"match": "\\b(0[xX][0-9A-Fa-f_]+|0[bB][01_]+|[0-9][0-9_]*(\\.(?!\\.)[0-9_]*)?([eE][+-]?[0-9][0-9_]*)?)"
},
"functional": {
"patterns": [
{
"name": "keyword.operator.functional.lpc",
"match": "\\(:"
},
{
"name": "keyword.operator.functional.lpc",
"match": ":\\)"
}
]
},
"class-keyword": {
"name": "storage.type.class.lpc",
"match": "\\b(struct|class)\\b"
},
"keywords": {
"name": "keyword.control.lpc",
"match": "\\b(time_expression|parse_command|__TREE__|continue|default|foreach|inherit|return|sscanf|switch|array|break|catch|while|case|efun|else|for|new|ref|do|if|in)\\b"
},
"types": {
"name": "storage.type.lpc",
"match": "\\b(function|mapping|buffer|object|string|float|mixed|void|int)\\b"
},
"modifiers": {
"name": "storage.modifier.lpc",
"match": "\\b(protected|private|varargs|nomask|nosave|public|static)\\b"
},
"dollar-params": {
"name": "variable.parameter.positional.lpc",
"match": "\\$[0-9]+"
},
"function-call": {
"match": "\\b(?!(?:time_expression|parse_command|protected|__TREE__|continue|function|default|foreach|inherit|mapping|private|varargs|buffer|nomask|nosave|object|public|return|sscanf|static|string|struct|switch|array|break|catch|class|float|mixed|while|case|efun|else|void|for|int|new|ref|do|if|in)\\b)([A-Za-z_][A-Za-z0-9_]*)\\s*(?=\\()",
"captures": {
"1": {
"name": "entity.name.function.lpc"
}
}
},
"operators": {
"name": "keyword.operator.lpc",
"match": "\\&\\&=|\\.\\.\\.|<<=|>>=|\\?\\?=|\\|\\|=|!=|%=|\\&\\&|\\&=|\\(:|\\*=|\\+\\+|\\+=|\\-\\-|\\-=|\\->|\\.\\.|\\.\\?|/=|:\\)|::|<<|<=|==|>=|>>|\\?\\.|\\?\\?|\\^=|\\|=|\\|\\||=|>"
}
}
}