feat: improve tree-sitter syntax highlighting with named nodes
- Add aliases for keywords (VAR_INPUT, BEGIN, IF, etc.) as named nodes - Add aliases for built-in types (INT, BOOL, STRING, etc.) as type_builtin - Add aliases for constants (TRUE, FALSE) - Add aliases for operators (AND, OR, NOT, MOD) - Add prefix node for # variable prefix highlighting - Highlight FB instance names in calls - Highlight FB parameter names as properties - Update README with detailed syntax highlighting features - Update .gitignore for *.wasm files
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
*.o
|
*.o
|
||||||
*.so
|
*.so
|
||||||
|
*.wasm
|
||||||
*.log
|
*.log
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -33,11 +33,15 @@ A comprehensive Neovim/LazyVim plugin providing **Language Server Protocol (LSP)
|
|||||||
|
|
||||||
### Syntax Highlighting
|
### Syntax Highlighting
|
||||||
- Full SCL syntax support via tree-sitter
|
- Full SCL syntax support via tree-sitter
|
||||||
- ORGANIZATION_BLOCK, FUNCTION_BLOCK, FUNCTION definitions
|
- Block definitions: ORGANIZATION_BLOCK, FUNCTION_BLOCK, FUNCTION
|
||||||
- Variable declarations (VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT, VAR_TEMP, etc.)
|
- Variable sections: VAR_INPUT, VAR_OUTPUT, VAR_IN_OUT, VAR_TEMP, VAR_CONSTANT
|
||||||
- Control structures (IF/THEN/ELSE, CASE, FOR, WHILE, REPEAT)
|
- Control structures: IF/THEN/ELSIF/ELSE/END_IF, CASE/OF/END_CASE, FOR/TO/BY/DO/END_FOR, WHILE/END_WHILE, REPEAT/UNTIL/END_REPEAT
|
||||||
- Code regions and comments
|
- Built-in data types: BOOL, INT, DINT, REAL, STRING, TIME, etc.
|
||||||
- All SCL data types and operators
|
- Function block instances highlighted in calls
|
||||||
|
- FB parameter names (IN, PT, CU, etc.) highlighted as properties
|
||||||
|
- `#` prefix for local variables highlighted
|
||||||
|
- Operators: AND, OR, NOT, XOR, MOD
|
||||||
|
- Comments: line (`//`), block (`(* *)`), C-style (`/* */`)
|
||||||
|
|
||||||
### Additional Features
|
### Additional Features
|
||||||
| Feature | Description |
|
| Feature | Description |
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
M.FUNCTIONS = {
|
||||||
|
ADD = true,
|
||||||
|
SUB = true,
|
||||||
|
MUL = true,
|
||||||
|
DIV = true,
|
||||||
|
MIN = true,
|
||||||
|
MAX = true,
|
||||||
|
LIMIT = true,
|
||||||
|
MOVE = true,
|
||||||
|
CONVERT = true,
|
||||||
|
ROUND = true,
|
||||||
|
TRUNC = true,
|
||||||
|
CEIL = true,
|
||||||
|
FLOOR = true,
|
||||||
|
SQR = true,
|
||||||
|
SQRT = true,
|
||||||
|
SIN = true,
|
||||||
|
COS = true,
|
||||||
|
TAN = true,
|
||||||
|
ASIN = true,
|
||||||
|
ACOS = true,
|
||||||
|
ATAN = true,
|
||||||
|
LEN = true,
|
||||||
|
CONCAT = true,
|
||||||
|
LEFT = true,
|
||||||
|
RIGHT = true,
|
||||||
|
MID = true,
|
||||||
|
AND = true,
|
||||||
|
OR = true,
|
||||||
|
XOR = true,
|
||||||
|
SHL = true,
|
||||||
|
SHR = true,
|
||||||
|
ROL = true,
|
||||||
|
ROR = true,
|
||||||
|
BCD_I = true,
|
||||||
|
I_BCD = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
M.FUNCTION_BLOCKS = {
|
||||||
|
TON = true,
|
||||||
|
TOF = true,
|
||||||
|
TP = true,
|
||||||
|
TONR = true,
|
||||||
|
CTU = true,
|
||||||
|
CTD = true,
|
||||||
|
CTUD = true,
|
||||||
|
IEC_TIMER = true,
|
||||||
|
IEC_TON = true,
|
||||||
|
IEC_TOF = true,
|
||||||
|
IEC_TP = true,
|
||||||
|
IEC_COUNTER = true,
|
||||||
|
IEC_CTU = true,
|
||||||
|
IEC_CTD = true,
|
||||||
|
IEC_CTUD = true,
|
||||||
|
R_TRIG = true,
|
||||||
|
F_TRIG = true,
|
||||||
|
SR = true,
|
||||||
|
RS = true,
|
||||||
|
SCHEDULE = true,
|
||||||
|
BPM = true,
|
||||||
|
LOG = true,
|
||||||
|
DATALOG = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
M.PARAMETERS = {
|
||||||
|
TON = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
TOF = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
TP = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
TONR = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" }, { name = "R", type = "BOOL" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
CTU = { inputs = { { name = "CU", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
CTD = { inputs = { { name = "CD", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
CTUD = { inputs = { { name = "CU", type = "BOOL" }, { name = "CD", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "QU", type = "BOOL" }, { name = "QD", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
R_TRIG = { inputs = { { name = "CLK", type = "BOOL" } }, outputs = { { name = "Q", type = "BOOL" } } },
|
||||||
|
F_TRIG = { inputs = { { name = "CLK", type = "BOOL" } }, outputs = { { name = "Q", type = "BOOL" } } },
|
||||||
|
SR = { inputs = { { name = "S", type = "BOOL" }, { name = "R1", type = "BOOL" } }, outputs = { { name = "Q1", type = "BOOL" } } },
|
||||||
|
RS = { inputs = { { name = "S1", type = "BOOL" }, { name = "R", type = "BOOL" } }, outputs = { { name = "Q1", type = "BOOL" } } },
|
||||||
|
IEC_TIMER = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
IEC_TON = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
IEC_TOF = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
IEC_TP = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
|
||||||
|
IEC_COUNTER = { inputs = { { name = "CU", type = "BOOL" }, { name = "CD", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "QU", type = "BOOL" }, { name = "QD", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
IEC_CTU = { inputs = { { name = "CU", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
IEC_CTD = { inputs = { { name = "CD", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
IEC_CTUD = { inputs = { { name = "CU", type = "BOOL" }, { name = "CD", type = "BOOL" }, { name = "R", type = "BOOL" }, { name = "LD", type = "BOOL" }, { name = "PV", type = "INT" } }, outputs = { { name = "QU", type = "BOOL" }, { name = "QD", type = "BOOL" }, { name = "CV", type = "INT" } } },
|
||||||
|
ADD = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SUB = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MUL = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
DIV = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MIN = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MAX = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
LIMIT = { inputs = { { name = "MN" }, { name = "IN" }, { name = "MX" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MOVE = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
CONVERT = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ROUND = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
TRUNC = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
CEIL = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
FLOOR = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SQR = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SQRT = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SIN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
COS = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
TAN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ASIN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ACOS = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ATAN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
LEN = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
CONCAT = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
LEFT = { inputs = { { name = "IN" }, { name = "L" } }, outputs = { { name = "OUT" } } },
|
||||||
|
RIGHT = { inputs = { { name = "IN" }, { name = "L" } }, outputs = { { name = "OUT" } } },
|
||||||
|
MID = { inputs = { { name = "IN" }, { name = "L" }, { name = "P" } }, outputs = { { name = "OUT" } } },
|
||||||
|
AND = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
OR = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
XOR = { inputs = { { name = "IN1" }, { name = "IN2" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SHL = { inputs = { { name = "IN" }, { name = "N" } }, outputs = { { name = "OUT" } } },
|
||||||
|
SHR = { inputs = { { name = "IN" }, { name = "N" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ROL = { inputs = { { name = "IN" }, { name = "N" } }, outputs = { { name = "OUT" } } },
|
||||||
|
ROR = { inputs = { { name = "IN" }, { name = "N" } }, outputs = { { name = "OUT" } } },
|
||||||
|
BCD_I = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
I_BCD = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
|
||||||
|
}
|
||||||
|
|
||||||
|
function M.get_parameters(name)
|
||||||
|
return M.PARAMETERS[name:upper()]
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.is_known_function_block(name)
|
||||||
|
return M.FUNCTION_BLOCKS[name:upper()] or false
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.is_known_function(name)
|
||||||
|
return M.FUNCTIONS[name:upper()] or false
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
+31
-14
@@ -6,24 +6,41 @@ local M = {}
|
|||||||
function M.setup(opts)
|
function M.setup(opts)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
|
|
||||||
|
-- Add plugin to runtime path
|
||||||
|
vim.opt.runtimepath:prepend(vim.fn.stdpath("data") .. "/lazy/scl_lsp")
|
||||||
|
|
||||||
M.create_commands()
|
M.create_commands()
|
||||||
|
|
||||||
-- Treesitter parser config
|
-- Treesitter setup for Neovim 0.11+
|
||||||
local has_ts, ts = pcall(require, "nvim-treesitter.parsers")
|
local function setup_treesitter()
|
||||||
if has_ts and ts.get_parser_configs then
|
local lang = vim.treesitter.language
|
||||||
local ok, parser_config = pcall(ts.get_parser_configs)
|
local parser_path = "/home/lazar/dev/scl_lsp/src/parser.so"
|
||||||
if ok and parser_config then
|
|
||||||
parser_config.scl = {
|
-- Register the SCL language
|
||||||
install_info = {
|
lang.add("scl", {
|
||||||
files = { "src/parser.c" },
|
path = parser_path,
|
||||||
generate_requires_npm = false,
|
filetype = "scl",
|
||||||
requires_generate_from_grammar = false,
|
})
|
||||||
},
|
|
||||||
filetype = "scl",
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pcall(setup_treesitter)
|
||||||
|
|
||||||
|
-- Install queries
|
||||||
|
local queries_src = "/home/lazar/dev/scl_lsp/queries/highlights.scm"
|
||||||
|
local queries_dest = vim.fn.stdpath("data") .. "/site/queries/scl/highlights.scm"
|
||||||
|
if vim.fn.filereadable(queries_src) == 1 then
|
||||||
|
vim.fn.mkdir(vim.fn.stdpath("data") .. "/site/queries/scl", "p")
|
||||||
|
vim.fn.writefile(vim.fn.readfile(queries_src), queries_dest)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Enable treesitter manually for SCL files - bypass LazyVim
|
||||||
|
vim.api.nvim_create_autocmd("FileType", {
|
||||||
|
pattern = "scl",
|
||||||
|
callback = function(args)
|
||||||
|
vim.treesitter.start(args.buf, "scl")
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
-- Register blink.cmp source
|
-- Register blink.cmp source
|
||||||
if opts.cmp then
|
if opts.cmp then
|
||||||
local function try_register()
|
local function try_register()
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
local function get_builtin_interface(var_type)
|
||||||
|
local builtin = require("scl.builtin_instructions")
|
||||||
|
local clean_type = var_type:gsub('"', ''):gsub("#", ""):upper()
|
||||||
|
local params_info = builtin.get_parameters(clean_type)
|
||||||
|
if params_info then
|
||||||
|
return {
|
||||||
|
inputs = params_info.inputs or {},
|
||||||
|
outputs = params_info.outputs or {},
|
||||||
|
inouts = {},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local function get_fb_interface(var_type)
|
local function get_fb_interface(var_type)
|
||||||
local fb_parser = require("scl.fb_parser")
|
local fb_parser = require("scl.fb_parser")
|
||||||
local clean_type = var_type:gsub('"', '')
|
local clean_type = var_type:gsub('"', '')
|
||||||
@@ -49,44 +63,69 @@ function M.fill_multiline_params()
|
|||||||
local line_before_cursor = line:sub(1, col)
|
local line_before_cursor = line:sub(1, col)
|
||||||
|
|
||||||
local known_vars = get_known_variables(bufnr)
|
local known_vars = get_known_variables(bufnr)
|
||||||
|
local builtin = require("scl.builtin_instructions")
|
||||||
|
|
||||||
local fb_name = nil
|
local fb_name = nil
|
||||||
local fb_prefix = ""
|
local fb_prefix = ""
|
||||||
|
local is_builtin_function = false
|
||||||
|
|
||||||
local prefix, var_name = line_before_cursor:match("(#?)([%w_]+)%s*%(%s*$")
|
local prefix, var_name = line_before_cursor:match("(#?)([%w_]+)%s*%(%s*$")
|
||||||
if var_name and known_vars[var_name] then
|
if var_name then
|
||||||
fb_prefix = prefix or ""
|
if known_vars[var_name] then
|
||||||
fb_name = var_name
|
|
||||||
end
|
|
||||||
|
|
||||||
if not fb_name then
|
|
||||||
prefix, var_name = line_before_cursor:match("(#?)([%w_]+)%s*%([^)]-,%s*$")
|
|
||||||
if var_name and known_vars[var_name] then
|
|
||||||
fb_prefix = prefix or ""
|
fb_prefix = prefix or ""
|
||||||
fb_name = var_name
|
fb_name = var_name
|
||||||
|
elseif builtin.is_known_function(var_name) then
|
||||||
|
fb_prefix = prefix or ""
|
||||||
|
fb_name = var_name
|
||||||
|
is_builtin_function = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not fb_name then
|
if not fb_name then
|
||||||
vim.notify("No FB instance found before cursor", vim.log.levels.WARN)
|
prefix, var_name = line_before_cursor:match("(#?)([%w_]+)%s*%([^)]-,%s*$")
|
||||||
|
if var_name then
|
||||||
|
if known_vars[var_name] then
|
||||||
|
fb_prefix = prefix or ""
|
||||||
|
fb_name = var_name
|
||||||
|
elseif builtin.is_known_function(var_name) then
|
||||||
|
fb_prefix = prefix or ""
|
||||||
|
fb_name = var_name
|
||||||
|
is_builtin_function = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not fb_name then
|
||||||
|
vim.notify("No FB instance or known function found before cursor", vim.log.levels.WARN)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local var_type = get_variable_type(fb_name, bufnr)
|
local fb_interface = nil
|
||||||
if not var_type then
|
|
||||||
vim.notify("Cannot find type for: " .. fb_name, vim.log.levels.WARN)
|
if is_builtin_function then
|
||||||
return
|
fb_interface = get_builtin_interface(fb_name)
|
||||||
|
else
|
||||||
|
local var_type = get_variable_type(fb_name, bufnr)
|
||||||
|
if not var_type then
|
||||||
|
vim.notify("Cannot find type for: " .. fb_name, vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local clean_type = var_type:gsub('"', '')
|
||||||
|
|
||||||
|
fb_interface = get_builtin_interface(clean_type)
|
||||||
|
|
||||||
|
if not fb_interface then
|
||||||
|
if not is_fb_type(clean_type) then
|
||||||
|
vim.notify(clean_type .. " is not an FB/Function type", vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
fb_interface = get_fb_interface(clean_type)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local clean_type = var_type:gsub('"', '')
|
|
||||||
if not is_fb_type(clean_type) then
|
|
||||||
vim.notify(clean_type .. " is not an FB/Function type", vim.log.levels.WARN)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local fb_interface = get_fb_interface(clean_type)
|
|
||||||
if not fb_interface then
|
if not fb_interface then
|
||||||
vim.notify("Cannot get interface for: " .. clean_type, vim.log.levels.WARN)
|
vim.notify("Cannot get interface for: " .. (clean_type or fb_name), vim.log.levels.WARN)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -102,7 +141,7 @@ function M.fill_multiline_params()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if #params == 0 then
|
if #params == 0 then
|
||||||
vim.notify("No parameters found for: " .. clean_type, vim.log.levels.WARN)
|
vim.notify("No parameters found for: " .. (clean_type or fb_name), vim.log.levels.WARN)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+56
-191
@@ -1,211 +1,76 @@
|
|||||||
; Comprehensive SCL highlight queries for Neovim
|
; SCL highlights
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Comments
|
|
||||||
; ============================================
|
|
||||||
(line_comment) @comment
|
(line_comment) @comment
|
||||||
(block_comment) @comment
|
(block_comment) @comment
|
||||||
(c_style_comment) @comment
|
(c_style_comment) @comment
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Literals
|
|
||||||
; ============================================
|
|
||||||
(number) @number
|
(number) @number
|
||||||
(hex_number) @number
|
(hex_number) @number
|
||||||
(string) @string
|
(string) @string
|
||||||
(time_value) @number
|
(time_value) @number
|
||||||
|
|
||||||
; ============================================
|
(prefix) @punctuation.special
|
||||||
; Constants
|
|
||||||
; ============================================
|
|
||||||
(
|
|
||||||
(identifier) @constant.builtin
|
|
||||||
(#match? @constant.builtin "^(TRUE|FALSE|TRUE#|FALSE#)$")
|
|
||||||
)
|
|
||||||
(
|
|
||||||
(type) @type.builtin
|
|
||||||
(#match? @type.builtin "^(TRUE|FALSE)$")
|
|
||||||
)
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Identifiers
|
|
||||||
; ============================================
|
|
||||||
(identifier) @variable
|
(identifier) @variable
|
||||||
(prefixed_identifier) @variable
|
|
||||||
|
|
||||||
; ============================================
|
; FB instance calls - highlight instance name as type
|
||||||
; Types - Basic
|
(fb_call
|
||||||
; ============================================
|
instance: (prefixed_identifier
|
||||||
(
|
(identifier) @type))
|
||||||
(type) @type.builtin
|
(fb_call
|
||||||
(#match? @type.builtin "^(BOOL|Bool|INT|Int|DINT|DInt|SINT|SInt|USINT|USInt|UINT|UInt|WORD|Word|DWORD|DWord|BYTE|Byte|REAL|Real|LREAL|LReal|TIME|Time|TOD|Tod|DT|Dt|String|STRING|CHAR|Char|WSTRING|WString)$")
|
instance: (identifier) @type)
|
||||||
)
|
|
||||||
|
|
||||||
; Types - User defined (quoted strings like "UDT_Type")
|
; FB parameter names (IN :=, PT :=, etc.)
|
||||||
(type
|
(fb_parameter
|
||||||
(string) @type
|
|
||||||
)
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Keywords - Block definitions
|
|
||||||
; ============================================
|
|
||||||
"ORGANIZATION_BLOCK" @keyword
|
|
||||||
"FUNCTION_BLOCK" @keyword
|
|
||||||
"FUNCTION" @keyword
|
|
||||||
"END_ORGANIZATION_BLOCK" @keyword
|
|
||||||
"END_FUNCTION_BLOCK" @keyword
|
|
||||||
"END_FUNCTION" @keyword
|
|
||||||
"BEGIN" @keyword
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Keywords - Variable sections
|
|
||||||
; ============================================
|
|
||||||
"VAR_INPUT" @keyword
|
|
||||||
"VAR_OUTPUT" @keyword
|
|
||||||
"VAR_IN_OUT" @keyword
|
|
||||||
"VAR" @keyword
|
|
||||||
"VAR_TEMP" @keyword
|
|
||||||
"VAR_CONSTANT" @keyword
|
|
||||||
"END_VAR" @keyword
|
|
||||||
"CONSTANT" @keyword
|
|
||||||
"RETAIN" @keyword
|
|
||||||
"NON_RETAIN" @keyword
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Keywords - Control flow
|
|
||||||
; ============================================
|
|
||||||
"IF" @conditional
|
|
||||||
"THEN" @conditional
|
|
||||||
"ELSIF" @conditional
|
|
||||||
"ELSE" @conditional
|
|
||||||
"END_IF" @conditional
|
|
||||||
"CASE" @conditional
|
|
||||||
"OF" @conditional
|
|
||||||
"END_CASE" @conditional
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Keywords - Loops
|
|
||||||
; ============================================
|
|
||||||
"FOR" @repeat
|
|
||||||
"TO" @repeat
|
|
||||||
"BY" @repeat
|
|
||||||
"DO" @repeat
|
|
||||||
"END_FOR" @repeat
|
|
||||||
"WHILE" @repeat
|
|
||||||
"END_WHILE" @repeat
|
|
||||||
"REPEAT" @repeat
|
|
||||||
"UNTIL" @repeat
|
|
||||||
"END_REPEAT" @repeat
|
|
||||||
"EXIT" @keyword
|
|
||||||
"CONTINUE" @keyword
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Keywords - Regions
|
|
||||||
; ============================================
|
|
||||||
"REGION" @namespace
|
|
||||||
"END_REGION" @namespace
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Keywords - Other
|
|
||||||
; ============================================
|
|
||||||
"TITLE" @keyword
|
|
||||||
"VERSION" @keyword
|
|
||||||
"ARRAY" @keyword
|
|
||||||
"OF" @keyword
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Fields
|
|
||||||
; ============================================
|
|
||||||
(block
|
|
||||||
name: (string) @namespace)
|
|
||||||
|
|
||||||
(block
|
|
||||||
name: (identifier) @namespace)
|
|
||||||
|
|
||||||
(var_item
|
|
||||||
name: (identifier) @property)
|
name: (identifier) @property)
|
||||||
|
|
||||||
|
; Function call names
|
||||||
|
(function_call
|
||||||
|
(identifier) @function)
|
||||||
|
|
||||||
|
; Variable declarations
|
||||||
(var_item
|
(var_item
|
||||||
type: (type) @type)
|
name: (identifier) @variable)
|
||||||
|
|
||||||
; ============================================
|
; Type references in declarations
|
||||||
; Functions and function calls
|
(type
|
||||||
; ============================================
|
(identifier) @type)
|
||||||
(function_call
|
|
||||||
(identifier) @function.call)
|
|
||||||
|
|
||||||
(function_call
|
(type_builtin) @type.builtin
|
||||||
(string) @function.call)
|
|
||||||
|
|
||||||
(parameter
|
(keyword) @keyword
|
||||||
(identifier) @parameter)
|
(constant) @constant.builtin
|
||||||
|
(operator) @operator
|
||||||
|
|
||||||
; ============================================
|
(assignment) @operator
|
||||||
; Array access
|
(binary_expression) @operator
|
||||||
; ============================================
|
(unary_expression) @operator
|
||||||
(array_access
|
|
||||||
"[" @punctuation.bracket
|
|
||||||
"]" @punctuation.bracket)
|
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Field access
|
|
||||||
; ============================================
|
|
||||||
(field_access
|
(field_access
|
||||||
"." @punctuation.delimiter)
|
"."
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Attribute lists
|
|
||||||
; ============================================
|
|
||||||
(attribute_list
|
|
||||||
"{" @punctuation.bracket
|
|
||||||
"}" @punctuation.bracket)
|
|
||||||
|
|
||||||
(attribute_list
|
|
||||||
"," @punctuation.delimiter)
|
|
||||||
|
|
||||||
(attribute_list
|
|
||||||
";" @punctuation.delimiter)
|
|
||||||
|
|
||||||
(attribute
|
|
||||||
(identifier) @property)
|
(identifier) @property)
|
||||||
|
|
||||||
; ============================================
|
(array_access) @property
|
||||||
; Operators - Logical
|
|
||||||
; ============================================
|
|
||||||
"AND" @operator
|
|
||||||
"OR" @operator
|
|
||||||
"XOR" @operator
|
|
||||||
"NOT" @operator
|
|
||||||
|
|
||||||
; ============================================
|
(attribute_list) @attribute
|
||||||
; Operators - Comparison
|
(attribute) @attribute
|
||||||
; ============================================
|
(attribute_value) @string
|
||||||
"=" @operator
|
|
||||||
"<>" @operator
|
|
||||||
"<" @operator
|
|
||||||
">" @operator
|
|
||||||
"<=" @operator
|
|
||||||
">=" @operator
|
|
||||||
|
|
||||||
; ============================================
|
(var_item) @property
|
||||||
; Operators - Arithmetic
|
|
||||||
; ============================================
|
|
||||||
"+" @operator
|
|
||||||
"-" @operator
|
|
||||||
"*" @operator
|
|
||||||
"/" @operator
|
|
||||||
"MOD" @operator
|
|
||||||
"**" @operator
|
|
||||||
|
|
||||||
; ============================================
|
(function_call) @function.call
|
||||||
; Operators - Assignment
|
(fb_call) @function.call
|
||||||
; ============================================
|
|
||||||
":=" @operator
|
(if_statement) @conditional
|
||||||
"=>" @operator
|
(elsif_clause) @conditional
|
||||||
|
(else_clause) @conditional
|
||||||
|
(case_statement) @conditional
|
||||||
|
(case_item) @conditional
|
||||||
|
|
||||||
|
(for_statement) @repeat
|
||||||
|
(while_statement) @repeat
|
||||||
|
(repeat_statement) @repeat
|
||||||
|
|
||||||
; ============================================
|
|
||||||
; Punctuation
|
|
||||||
; ============================================
|
|
||||||
";" @punctuation.delimiter
|
";" @punctuation.delimiter
|
||||||
":" @punctuation.delimiter
|
":" @punctuation.delimiter
|
||||||
"," @punctuation.delimiter
|
"," @punctuation.delimiter
|
||||||
@@ -214,17 +79,17 @@
|
|||||||
"[" @punctuation.bracket
|
"[" @punctuation.bracket
|
||||||
"]" @punctuation.bracket
|
"]" @punctuation.bracket
|
||||||
"." @punctuation.delimiter
|
"." @punctuation.delimiter
|
||||||
".." @punctuation.delimiter
|
|
||||||
"#" @punctuation.special
|
|
||||||
|
|
||||||
; ============================================
|
":=" @operator
|
||||||
; Binary and unary expressions
|
"=>" @operator
|
||||||
; ============================================
|
"=" @operator
|
||||||
(binary_expression) @operator
|
"<>" @operator
|
||||||
(unary_expression) @operator
|
"<" @operator
|
||||||
|
">" @operator
|
||||||
|
"<=" @operator
|
||||||
|
">=" @operator
|
||||||
|
|
||||||
; ============================================
|
"+" @operator
|
||||||
; Range expressions
|
"-" @operator
|
||||||
; ============================================
|
"*" @operator
|
||||||
(range
|
"/" @operator
|
||||||
".." @punctuation.delimiter)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user