From 8758d582f60079bbb903dd7e9082e7fdbc1ef963 Mon Sep 17 00:00:00 2001 From: Jamie Shorten Date: Thu, 19 Mar 2026 20:43:09 +0000 Subject: [PATCH] feat: add Concerto modelling language parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add tree-sitter parser and queries for the Concerto Modelling Language (.cto files) by the Accord Project. Concerto is a schema language for defining data models used in smart legal contracts and business networks. Queries: - highlights.scm — full syntax highlighting - folds.scm — code folding for declaration bodies and block comments - locals.scm — scope, definition, and reference tracking - indents.scm — auto-indentation for declaration bodies Grammar source: https://github.com/accordproject/concerto-tree-sitter Language spec: https://concerto.accordproject.org Note: Neovim does not yet detect .cto files natively. Users need to add: vim.filetype.add({ extension = { cto = 'concerto' } }) --- SUPPORTED_LANGUAGES.md | 1 + lua/nvim-treesitter/parsers.lua | 8 + runtime/queries/concerto/folds.scm | 14 ++ runtime/queries/concerto/highlights.scm | 231 ++++++++++++++++++++++++ runtime/queries/concerto/indents.scm | 15 ++ runtime/queries/concerto/locals.scm | 85 +++++++++ 6 files changed, 354 insertions(+) create mode 100644 runtime/queries/concerto/folds.scm create mode 100644 runtime/queries/concerto/highlights.scm create mode 100644 runtime/queries/concerto/indents.scm create mode 100644 runtime/queries/concerto/locals.scm diff --git a/SUPPORTED_LANGUAGES.md b/SUPPORTED_LANGUAGES.md index 978a4b8ed..5311de423 100644 --- a/SUPPORTED_LANGUAGES.md +++ b/SUPPORTED_LANGUAGES.md @@ -42,6 +42,7 @@ Language | Tier | Queries | Maintainer [cmake](https://github.com/uyha/tree-sitter-cmake) | unstable | `HFIJ ` | @uyha [comment](https://github.com/stsewd/tree-sitter-comment) | unstable | `H    ` | @stsewd [commonlisp](https://github.com/tree-sitter-grammars/tree-sitter-commonlisp) | unstable | `HF JL` | @theHamsta +[concerto](https://github.com/accordproject/concerto-tree-sitter) | unmaintained | `HFI L` | @jamieshorten [cooklang](https://github.com/addcninblue/tree-sitter-cooklang) | unstable | `H  J ` | @addcninblue [corn](https://github.com/jakestanger/tree-sitter-corn) | unstable | `HFIJL` | @jakestanger [cpon](https://github.com/tree-sitter-grammars/tree-sitter-cpon) | unstable | `HFIJL` | @amaanq diff --git a/lua/nvim-treesitter/parsers.lua b/lua/nvim-treesitter/parsers.lua index c09bdfe32..de7ccb0dc 100644 --- a/lua/nvim-treesitter/parsers.lua +++ b/lua/nvim-treesitter/parsers.lua @@ -243,6 +243,14 @@ return { maintainers = { '@stsewd' }, tier = 2, }, + concerto = { + install_info = { + revision = '77ae6b9e09a58ac4c94fe36760df7e8d26ab5aca', + url = 'https://github.com/accordproject/concerto-tree-sitter', + }, + maintainers = { '@jamieshorten' }, + tier = 3, + }, commonlisp = { install_info = { revision = '32323509b3d9fe96607d151c2da2c9009eb13a2f', diff --git a/runtime/queries/concerto/folds.scm b/runtime/queries/concerto/folds.scm new file mode 100644 index 000000000..1ad7cfbbf --- /dev/null +++ b/runtime/queries/concerto/folds.scm @@ -0,0 +1,14 @@ +; Concerto Language - Fold Queries +; ================================= +; Fold declaration bodies +(class_body) @fold + +(enum_body) @fold + +(map_body) @fold + +; Fold block comments +(block_comment) @fold + +; Fold decorator argument lists +(decorator_arguments) @fold diff --git a/runtime/queries/concerto/highlights.scm b/runtime/queries/concerto/highlights.scm new file mode 100644 index 000000000..5ec0de290 --- /dev/null +++ b/runtime/queries/concerto/highlights.scm @@ -0,0 +1,231 @@ +; Concerto Language - Syntax Highlighting Queries +; ================================================= +; Keywords +; -------- +; Declaration keywords +[ + "concept" + "asset" + "participant" + "transaction" + "event" + "enum" + "scalar" + "map" +] @keyword.type + +[ + "namespace" + "import" + "from" +] @keyword.import + +"extends" @keyword + +"abstract" @keyword.modifier + +[ + "identified" + "by" +] @keyword + +"optional" @keyword.modifier + +[ + "concerto" + "version" +] @keyword + +"default" @keyword + +[ + "regex" + "range" + "length" +] @keyword + +"as" @keyword + +; Primitive type keywords +[ + "String" + "Boolean" + "DateTime" + "Integer" + "Long" + "Double" +] @type.builtin + +(primitive_type) @type.builtin + +; Boolean literals +(boolean_literal) @boolean + +; Comments +; -------- +(line_comment) @comment + +(block_comment) @comment + +; Strings +; ------- +(string_literal) @string + +(escape_sequence) @string.escape + +; Numbers +; ------- +(signed_integer) @number + +(signed_real) @number + +(signed_number) @number + +; Regex +; ----- +(regex_literal) @string.regexp + +; Decorators +; ---------- +(decorator + "@" @attribute + name: (identifier) @attribute) + +; Namespace and imports +; -------------------- +(namespace_path) @module + +(import_path) @module + +(uri) @string.special + +; Version +; ------- +(concerto_version + (string_literal) @string.special) + +; Type identifiers (in type position) +; ----------------------------------- +(concept_declaration + name: (type_identifier) @type) + +(asset_declaration + name: (type_identifier) @type) + +(participant_declaration + name: (type_identifier) @type) + +(transaction_declaration + name: (type_identifier) @type) + +(event_declaration + name: (type_identifier) @type) + +(enum_declaration + name: (type_identifier) @type) + +(scalar_declaration + name: (type_identifier) @type) + +(map_declaration + name: (type_identifier) @type) + +(extends_clause + (type_identifier) @type) + +; Field type references +(object_field + type: (type_identifier) @type) + +(relationship_field + type: (type_identifier) @type) + +; Map type references +(map_key_type + type: (type_identifier) @type) + +(map_value_property + type: (type_identifier) @type) + +(map_value_relationship + type: (type_identifier) @type) + +; Decorator identifier references +(decorator_identifier_ref + (type_identifier) @type) + +; Import type name +(import_single + type: (identifier) @type) + +(type_list_item + (identifier) @type) + +(aliased_type + original: (identifier) @type + alias: (identifier) @type) + +; Field/property names +; -------------------- +(string_field + name: (identifier) @property) + +(boolean_field + name: (identifier) @property) + +(datetime_field + name: (identifier) @property) + +(integer_field + name: (identifier) @property) + +(long_field + name: (identifier) @property) + +(double_field + name: (identifier) @property) + +(object_field + name: (identifier) @property) + +(relationship_field + name: (identifier) @property) + +(enum_property + name: (identifier) @property) + +; Identified by field name +(identified_by + field: (identifier) @property) + +; Relationship arrow +"-->" @operator + +; Property indicator +"o" @punctuation.special + +; Array indicator +(array_indicator) @punctuation.bracket + +; Wildcards in imports +"*" @operator + +; Delimiters +; ---------- +"{" @punctuation.bracket + +"}" @punctuation.bracket + +"(" @punctuation.bracket + +")" @punctuation.bracket + +"[" @punctuation.bracket + +"]" @punctuation.bracket + +"," @punctuation.delimiter + +"." @punctuation.delimiter + +"=" @operator diff --git a/runtime/queries/concerto/indents.scm b/runtime/queries/concerto/indents.scm new file mode 100644 index 000000000..106fbcec2 --- /dev/null +++ b/runtime/queries/concerto/indents.scm @@ -0,0 +1,15 @@ +; Concerto Language - Indent Queries +; =================================== +; Indent inside declaration bodies +[ + (class_body) + (enum_body) + (map_body) + (decorator_arguments) +] @indent.begin + +; Outdent at closing braces +[ + "}" + ")" +] @indent.end diff --git a/runtime/queries/concerto/locals.scm b/runtime/queries/concerto/locals.scm new file mode 100644 index 000000000..222565a3b --- /dev/null +++ b/runtime/queries/concerto/locals.scm @@ -0,0 +1,85 @@ +; Concerto Language - Locals Queries +; =================================== +; Scopes +; ------ +; Each declaration body creates a new scope +(concept_declaration) @local.scope + +(asset_declaration) @local.scope + +(participant_declaration) @local.scope + +(transaction_declaration) @local.scope + +(event_declaration) @local.scope + +(enum_declaration) @local.scope + +(map_declaration) @local.scope + +; Definitions +; ----------- +; Type declarations define types +(concept_declaration + name: (type_identifier) @local.definition) + +(asset_declaration + name: (type_identifier) @local.definition) + +(participant_declaration + name: (type_identifier) @local.definition) + +(transaction_declaration + name: (type_identifier) @local.definition) + +(event_declaration + name: (type_identifier) @local.definition) + +(enum_declaration + name: (type_identifier) @local.definition) + +(scalar_declaration + name: (type_identifier) @local.definition) + +(map_declaration + name: (type_identifier) @local.definition) + +; Property declarations define properties +(string_field + name: (identifier) @local.definition) + +(boolean_field + name: (identifier) @local.definition) + +(datetime_field + name: (identifier) @local.definition) + +(integer_field + name: (identifier) @local.definition) + +(long_field + name: (identifier) @local.definition) + +(double_field + name: (identifier) @local.definition) + +(object_field + name: (identifier) @local.definition) + +(relationship_field + name: (identifier) @local.definition) + +(enum_property + name: (identifier) @local.definition) + +; References +; ---------- +; Type references +(extends_clause + (type_identifier) @local.reference) + +(object_field + type: (type_identifier) @local.reference) + +(relationship_field + type: (type_identifier) @local.reference)