@gram-data/tree-sitter-gram 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,30 +8,29 @@ test("can load grammar", () => {
8
8
  assert.doesNotThrow(() => parser.setLanguage(require(".")));
9
9
  });
10
10
 
11
- test("annotation node kinds: identified_annotation and property_annotation", () => {
11
+ test("parses a simple node pattern", () => {
12
12
  const Parser = require("tree-sitter");
13
13
  const GramLang = require(".");
14
14
  const parser = new Parser();
15
15
  parser.setLanguage(GramLang);
16
16
 
17
- const annotated = (root) => root.child(0) ?? null;
17
+ const tree = parser.parse("(a)");
18
+ const pattern = tree.rootNode.child(0);
19
+ assert(pattern, "root should have a pattern child");
18
20
 
19
- const withIdentified = parser.parse("@@p (a)");
20
- const ap1 = annotated(withIdentified.rootNode);
21
- assert(ap1?.type === "annotated_pattern", "root should have annotated_pattern child");
22
- const annotations1 = ap1.childForFieldName("annotations");
23
- assert(annotations1, "annotations node should exist");
24
- const first1 = annotations1.child(0);
25
- assert.strictEqual(first1?.type, "identified_annotation", "@@ form should be identified_annotation");
26
- assert(first1?.childForFieldName("identifier"), "identified_annotation should have identifier field");
21
+ // Find the symbol 'a' in the pattern
22
+ function findSymbol(node, text) {
23
+ if (node.isNamed && node.type === "symbol" && node.text === text) {
24
+ return node;
25
+ }
26
+ for (let i = 0; i < node.childCount; i++) {
27
+ const result = findSymbol(node.child(i), text);
28
+ if (result) return result;
29
+ }
30
+ return null;
31
+ }
27
32
 
28
- const withProperty = parser.parse("@x(1) ()");
29
- const ap2 = annotated(withProperty.rootNode);
30
- assert(ap2?.type === "annotated_pattern", "root should have annotated_pattern child");
31
- const annotations2 = ap2.childForFieldName("annotations");
32
- assert(annotations2, "annotations node should exist");
33
- const first2 = annotations2.child(0);
34
- assert.strictEqual(first2?.type, "property_annotation", "@ form should be property_annotation");
35
- assert(first2?.childForFieldName("key"), "property_annotation should have key field");
36
- assert(first2?.childForFieldName("value"), "property_annotation should have value field");
33
+ const symbol = findSymbol(pattern, "a");
34
+ assert(symbol, "pattern should contain symbol 'a'");
35
+ assert.strictEqual(symbol.type, "symbol");
37
36
  });
@@ -0,0 +1,20 @@
1
+ [package]
2
+ name = "gram_zed_extension"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ license = "MIT"
6
+ publish = false
7
+ repository = "https://github.com/gram-data/tree-sitter-gram"
8
+ build = "build.rs"
9
+
10
+ [lib]
11
+ path = "src/lib.rs"
12
+ crate-type = ["cdylib"]
13
+
14
+ [dependencies]
15
+ zed_extension_api = "0.7"
16
+
17
+ # Standalone workspace root so this crate is not treated as a stray member of the
18
+ # repository workspace (see root `Cargo.toml` `[workspace]`).
19
+ [workspace]
20
+ members = ["."]
@@ -5,6 +5,7 @@ A [Zed](https://zed.dev) extension providing syntax highlighting and language su
5
5
  ## Features
6
6
 
7
7
  - **Syntax Highlighting**: Full syntax highlighting for all Gram constructs including subjects, nodes, relationships, and data types
8
+ - **Language server**: When [`gram-lsp`](../../tools/lsp/) is on your `PATH`, Zed starts it for `.gram` files (diagnostics, hover, definitions, references, completions)
8
9
  - **Subject Pattern Matching**: Automatic matching for `()`, `[]`, and `{}`
9
10
  - **File Type Detection**: Automatic recognition of `.gram` files
10
11
  - **Smart Indentation**: Proper indentation handling for nested structures
@@ -40,7 +41,7 @@ Then restart Zed.
40
41
 
41
42
  ## Usage
42
43
 
43
- Once installed, the extension automatically provides syntax highlighting for any file with a `.gram` extension.
44
+ Once installed, the extension provides syntax highlighting for `.gram` files. With `gram-lsp` installed and on `PATH`, Zed also attaches the language server automatically.
44
45
 
45
46
  ### Example Gram Syntax
46
47
 
@@ -108,14 +109,25 @@ To work on this extension:
108
109
  - Select the `editors/zed` directory
109
110
  - Restart Zed
110
111
 
111
- 3. Make changes to the extension files
112
- 4. Restart Zed to see changes
112
+ 3. Build the Wasm extension once after Rust changes (Zed loads the cdylib):
113
+
114
+ ```bash
115
+ rustup target add wasm32-wasip1
116
+ cd editors/zed && cargo check --target wasm32-wasip1
117
+ ```
118
+
119
+ 4. Make changes to the extension files
120
+ 5. Restart Zed to see changes
113
121
 
114
122
  ### Extension Structure
115
123
 
116
124
  ```
117
125
  editors/zed/
118
- ├── extension.toml # Extension metadata; points at grammar repo (repository + rev)
126
+ ├── Cargo.toml # Wasm extension crate (zed_extension_api)
127
+ ├── build.rs # Embeds `extension.toml` version for release asset lookup
128
+ ├── Cargo.lock
129
+ ├── src/lib.rs # `language_server_command`: PATH, then GitHub release download
130
+ ├── extension.toml # Extension metadata; grammar repo + `[language_servers.gram-lsp]`
119
131
  ├── languages/
120
132
  │ └── gram/
121
133
  │ ├── config.toml # Zed language config (brackets, suffixes, etc.)
@@ -144,6 +156,12 @@ After either command, `extension.toml` is updated in place. For local dev you ty
144
156
 
145
157
  **If Zed shows an old version (e.g. 0.1.11) after installing the dev extension:** Zed may be using a cached clone of the grammar (at an old rev) or an older copy of the extension. Try: (1) Uninstall the Gram extension from Zed’s Extensions panel. (2) Delete the grammar cache: remove `editors/zed/grammars/` if it exists (Zed recreates it when needed). (3) Run `npm run zed:dev` again so `extension.toml` has the current version and rev. (4) In Zed, run “Install Dev Extension” and select `editors/zed` again. Restart Zed and recheck the extension version.
146
158
 
159
+ ### Bundled `gram-lsp` (GitHub Releases)
160
+
161
+ Zed extensions ship a **Wasm** adapter only; native `gram-lsp` binaries cannot be embedded in that bundle. Instead, when `gram-lsp` is **not** on `PATH`, the extension downloads a platform archive from **this repo’s GitHub Release** whose tag is **`v` + `version` from `extension.toml`** (for example `v0.3.5` for `version = "0.3.5"`).
162
+
163
+ Maintainers: pushing a **`v*`** tag runs **`.github/workflows/gram-lsp-release-assets.yml`**, which builds `gram-lsp` for common targets and uploads `gram-lsp-{target}.tar.gz` to the matching GitHub Release. Filenames must stay in sync with `editors/zed/src/lib.rs`. Keep `extension.toml`’s `version` aligned with the tag you ship to the Zed extension registry (for example tag `v0.3.5` and `version = "0.3.5"`) so installs download the intended binaries.
164
+
147
165
  ## Contributing
148
166
 
149
167
  Contributions are welcome! Please see the main [repository](https://github.com/gram-data/tree-sitter-gram) for contribution guidelines.
@@ -156,7 +174,7 @@ To improve syntax highlighting and editor behavior:
156
174
 
157
175
  ## License
158
176
 
159
- This extension is part of the tree-sitter-gram project and is licensed under the ISC License. See the main repository's [LICENSE](../../LICENSE) file for details.
177
+ This extension is part of the tree-sitter-gram project and is licensed under the MIT License. See the main repository's [LICENSE](../../LICENSE) file for details.
160
178
 
161
179
  ## Learn More
162
180
 
@@ -0,0 +1,26 @@
1
+ //! Expose `extension.toml`'s `version = "…"` as `env!("GRAM_EXT_VERSION")` for release lookups.
2
+
3
+ use std::env;
4
+ use std::fs;
5
+ use std::path::PathBuf;
6
+
7
+ fn main() {
8
+ let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
9
+ let ext_toml = manifest_dir.join("extension.toml");
10
+ println!("cargo:rerun-if-changed={}", ext_toml.display());
11
+
12
+ let content = fs::read_to_string(&ext_toml).unwrap_or_else(|e| panic!("read {}: {e}", ext_toml.display()));
13
+ let version = parse_version(&content)
14
+ .unwrap_or_else(|| panic!("{}: missing `version = \"…\"` line", ext_toml.display()));
15
+ println!("cargo:rustc-env=GRAM_EXT_VERSION={version}");
16
+ }
17
+
18
+ fn parse_version(toml: &str) -> Option<String> {
19
+ for line in toml.lines() {
20
+ let line = line.trim();
21
+ if let Some(rest) = line.strip_prefix("version = \"") {
22
+ return rest.split('"').next().map(str::to_string);
23
+ }
24
+ }
25
+ None
26
+ }
@@ -1,11 +1,16 @@
1
1
  id = "gram"
2
2
  name = "Gram Language Support"
3
- version = "0.3.4"
3
+ version = "0.3.6"
4
4
  schema_version = 1
5
5
  authors = ["Gram Data Contributors"]
6
6
  description = "Support for Gram notation - composable data patterns"
7
7
 
8
+ capabilities = [
9
+ { kind = "process:exec", command = "*", args = ["stdio"] },
10
+ { kind = "download_file", host = "github.com", path = ["gram-data", "tree-sitter-gram", "**"] },
11
+ ]
12
+
8
13
  # path = "grammars/tree-sitter-gram"
9
14
  [grammars.gram]
10
15
  repository = "https://github.com/gram-data/tree-sitter-gram"
11
- rev = "7aee4c203a5c6ea48660ae6d8af849ed90317bed"
16
+ rev = "184b524f4a0653bee3a07c44907dc266d698cb6e"
@@ -12,5 +12,5 @@ word_characters = ["_"]
12
12
  [prettier]
13
13
  allowed = false
14
14
 
15
- # [language_servers]
16
- # Add language server configuration here if you develop one for Gram
15
+ # Language servers are declared in extension.toml (`[language_servers.gram-lsp]`)
16
+ # and started from `src/lib.rs`. Per-server options go in Zed settings.json under `lsp`.
@@ -21,30 +21,48 @@
21
21
  ; Reference identifier: pattern_reference (FR-001)
22
22
  (pattern_reference identifier: (_) @variable)
23
23
 
24
- ; Definition-like identifiers (FR-001): @type
24
+ ; Symbols and identifiers (generic; definition/reference/tag captured above)
25
+ (symbol) @variable
26
+
27
+ ; Definition-like identifiers and labels (FR-001): @type
28
+ ; These must come AFTER generic symbol rule to take priority
29
+
30
+ ; Labels (symbols and quoted names in labels nodes)
31
+ (labels (symbol) @type)
32
+ (labels (quoted_name) @type)
33
+
34
+ ; Annotation identifiers and labels
35
+ (identified_annotation identifier: (_) @type)
36
+ (identified_annotation labels: (labels (symbol) @type))
37
+ (identified_annotation labels: (labels (quoted_name) @type))
38
+
39
+ ; Subject, node, and relationship pattern definitions (FR-001): @type
25
40
  ; subject/node subject is _subject (use wildcard _ as it may be hidden in some runtimes)
26
41
  (subject_pattern subject: (_ identifier: (_) @type))
27
42
  (subject_pattern subject: (_ labels: (labels (symbol) @type)))
43
+ (subject_pattern subject: (_ labels: (labels (quoted_name) @type)))
28
44
  (node_pattern subject: (_ identifier: (_) @type))
29
45
  (node_pattern subject: (_ labels: (labels (symbol) @type)))
46
+ (node_pattern subject: (_ labels: (labels (quoted_name) @type)))
30
47
  (relationship_pattern left: (node_pattern subject: (_ identifier: (_) @type)))
31
48
  (relationship_pattern left: (node_pattern subject: (_ labels: (labels (symbol) @type))))
49
+ (relationship_pattern left: (node_pattern subject: (_ labels: (labels (quoted_name) @type))))
32
50
  (relationship_pattern right: (node_pattern subject: (_ identifier: (_) @type)))
33
51
  (relationship_pattern right: (node_pattern subject: (_ labels: (labels (symbol) @type))))
52
+ (relationship_pattern right: (node_pattern subject: (_ labels: (labels (quoted_name) @type))))
34
53
  ; Arrow kind: subject is inside optional brackets on the arrow
35
54
  (relationship_pattern kind: (right_arrow subject: (_ identifier: (_) @type)))
36
55
  (relationship_pattern kind: (right_arrow subject: (_ labels: (labels (symbol) @type))))
56
+ (relationship_pattern kind: (right_arrow subject: (_ labels: (labels (quoted_name) @type))))
37
57
  (relationship_pattern kind: (left_arrow subject: (_ identifier: (_) @type)))
38
58
  (relationship_pattern kind: (left_arrow subject: (_ labels: (labels (symbol) @type))))
59
+ (relationship_pattern kind: (left_arrow subject: (_ labels: (labels (quoted_name) @type))))
39
60
  (relationship_pattern kind: (undirected_arrow subject: (_ identifier: (_) @type)))
40
61
  (relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (symbol) @type))))
62
+ (relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (quoted_name) @type))))
41
63
  (relationship_pattern kind: (bidirectional_arrow subject: (_ identifier: (_) @type)))
42
64
  (relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (symbol) @type))))
43
- (identified_annotation identifier: (_) @type)
44
- (identified_annotation labels: (labels (symbol) @type))
45
-
46
- ; Symbols and identifiers (generic; definition/reference/tag captured above)
47
- (symbol) @variable
65
+ (relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (quoted_name) @type))))
48
66
 
49
67
  ; Keywords and operators
50
68
  [
@@ -71,11 +89,11 @@
71
89
 
72
90
  ; Field names in records and maps
73
91
  (record_property key: (symbol) @property)
74
- (record_property key: (string_literal) @property)
75
- (record_property key: (integer) @property)
92
+ (record_property key: (quoted_name) @property)
93
+ (record_property key: (double_quoted_name) @property)
76
94
  (map_entry key: (symbol) @property)
77
- (map_entry key: (string_literal) @property)
78
- (map_entry key: (integer) @property)
95
+ (map_entry key: (quoted_name) @property)
96
+ (map_entry key: (double_quoted_name) @property)
79
97
 
80
98
  ; Annotation keys (property-style) and headers (identified/label-style)
81
99
  (property_annotation key: (symbol) @attribute)
@@ -7,22 +7,31 @@
7
7
  ; Definitions: identifiers that define a pattern or annotation
8
8
  (subject_pattern subject: (_ identifier: (_) @local.definition))
9
9
  (subject_pattern subject: (_ labels: (labels (symbol) @local.definition)))
10
+ (subject_pattern subject: (_ labels: (labels (quoted_name) @local.definition)))
10
11
  (node_pattern subject: (_ identifier: (_) @local.definition))
11
12
  (node_pattern subject: (_ labels: (labels (symbol) @local.definition)))
13
+ (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition)))
12
14
  (relationship_pattern left: (node_pattern subject: (_ identifier: (_) @local.definition)))
13
15
  (relationship_pattern left: (node_pattern subject: (_ labels: (labels (symbol) @local.definition))))
16
+ (relationship_pattern left: (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition))))
14
17
  (relationship_pattern right: (node_pattern subject: (_ identifier: (_) @local.definition)))
15
18
  (relationship_pattern right: (node_pattern subject: (_ labels: (labels (symbol) @local.definition))))
19
+ (relationship_pattern right: (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition))))
16
20
  (relationship_pattern kind: (right_arrow subject: (_ identifier: (_) @local.definition)))
17
21
  (relationship_pattern kind: (right_arrow subject: (_ labels: (labels (symbol) @local.definition))))
22
+ (relationship_pattern kind: (right_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
18
23
  (relationship_pattern kind: (left_arrow subject: (_ identifier: (_) @local.definition)))
19
24
  (relationship_pattern kind: (left_arrow subject: (_ labels: (labels (symbol) @local.definition))))
25
+ (relationship_pattern kind: (left_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
20
26
  (relationship_pattern kind: (undirected_arrow subject: (_ identifier: (_) @local.definition)))
21
27
  (relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (symbol) @local.definition))))
28
+ (relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
22
29
  (relationship_pattern kind: (bidirectional_arrow subject: (_ identifier: (_) @local.definition)))
23
30
  (relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (symbol) @local.definition))))
31
+ (relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
24
32
  (identified_annotation identifier: (_) @local.definition)
25
33
  (identified_annotation labels: (labels (symbol) @local.definition))
34
+ (identified_annotation labels: (labels (quoted_name) @local.definition))
26
35
 
27
36
  ; References: pattern_reference identifier
28
37
  (pattern_reference identifier: (_) @local.reference)
@@ -0,0 +1,156 @@
1
+ //! Zed extension host glue: starts `gram-lsp` from `PATH` or downloads a release asset.
2
+
3
+ use zed_extension_api::{
4
+ self as zed,
5
+ github_release_by_tag_name,
6
+ set_language_server_installation_status,
7
+ Architecture, Command, DownloadedFileType, Extension, LanguageServerId,
8
+ LanguageServerInstallationStatus, Os, Result, Worktree, current_platform, download_file,
9
+ make_file_executable,
10
+ };
11
+
12
+ const GRAM_REPO: &str = "gram-data/tree-sitter-gram";
13
+
14
+ struct GramExtension {
15
+ /// Relative path (under the extension work dir) or absolute path from `which`.
16
+ cached_binary: Option<String>,
17
+ }
18
+
19
+ impl GramExtension {
20
+ fn rust_target_triple() -> Result<&'static str> {
21
+ match current_platform() {
22
+ (Os::Mac, Architecture::Aarch64) => Ok("aarch64-apple-darwin"),
23
+ (Os::Mac, Architecture::X8664) => Ok("x86_64-apple-darwin"),
24
+ (Os::Linux, Architecture::Aarch64) => Ok("aarch64-unknown-linux-gnu"),
25
+ (Os::Linux, Architecture::X8664) => Ok("x86_64-unknown-linux-gnu"),
26
+ (Os::Windows, Architecture::Aarch64) => Ok("aarch64-pc-windows-msvc"),
27
+ (Os::Windows, Architecture::X8664) => Ok("x86_64-pc-windows-msvc"),
28
+ (Os::Linux, Architecture::X86) | (Os::Windows, Architecture::X86) => Err(
29
+ "gram-lsp: 32-bit platforms are not supported; install gram-lsp on PATH manually"
30
+ .into(),
31
+ ),
32
+ (Os::Mac, Architecture::X86) => Err(
33
+ "gram-lsp: unexpected macOS x86 architecture; install gram-lsp on PATH manually"
34
+ .into(),
35
+ ),
36
+ }
37
+ }
38
+
39
+ fn gram_lsp_bin_name(os: Os) -> &'static str {
40
+ match os {
41
+ Os::Windows => "gram-lsp.exe",
42
+ Os::Mac | Os::Linux => "gram-lsp",
43
+ }
44
+ }
45
+
46
+ fn ensure_downloaded(
47
+ &mut self,
48
+ language_server_id: &LanguageServerId,
49
+ ) -> Result<String> {
50
+ let version = env!("GRAM_EXT_VERSION");
51
+ let extract_dir = format!("gram-lsp-{version}");
52
+ let (os, _) = current_platform();
53
+ let bin_name = Self::gram_lsp_bin_name(os);
54
+ let relative_binary = format!("{extract_dir}/{bin_name}");
55
+
56
+ let triple = Self::rust_target_triple()?;
57
+ let asset_name = format!("gram-lsp-{triple}.tar.gz");
58
+ let tag = format!("v{version}");
59
+
60
+ set_language_server_installation_status(
61
+ language_server_id,
62
+ &LanguageServerInstallationStatus::Downloading,
63
+ );
64
+
65
+ let release = match github_release_by_tag_name(GRAM_REPO, &tag) {
66
+ Ok(r) => r,
67
+ Err(e) => {
68
+ let detail = format!(
69
+ "GitHub release {tag}: {e}. Install `gram-lsp` on PATH or publish release assets (see .github/workflows/gram-lsp-release-assets.yml)."
70
+ );
71
+ set_language_server_installation_status(
72
+ language_server_id,
73
+ &LanguageServerInstallationStatus::Failed(detail.clone()),
74
+ );
75
+ return Err(format!("gram-lsp: no GitHub release for {tag}: {e}"));
76
+ }
77
+ };
78
+
79
+ let asset = match release.assets.iter().find(|a| a.name == asset_name) {
80
+ Some(a) => a,
81
+ None => {
82
+ let msg = format!(
83
+ "gram-lsp: release {tag} has no asset {asset_name}. Build with the gram-lsp-release-assets workflow."
84
+ );
85
+ set_language_server_installation_status(
86
+ language_server_id,
87
+ &LanguageServerInstallationStatus::Failed(msg.clone()),
88
+ );
89
+ return Err(msg);
90
+ }
91
+ };
92
+
93
+ if let Err(e) = download_file(
94
+ &asset.download_url,
95
+ &extract_dir,
96
+ DownloadedFileType::GzipTar,
97
+ ) {
98
+ set_language_server_installation_status(
99
+ language_server_id,
100
+ &LanguageServerInstallationStatus::Failed(e.clone()),
101
+ );
102
+ return Err(format!("gram-lsp: download failed: {e}"));
103
+ }
104
+
105
+ if let Err(e) = make_file_executable(&relative_binary) {
106
+ set_language_server_installation_status(
107
+ language_server_id,
108
+ &LanguageServerInstallationStatus::Failed(e.clone()),
109
+ );
110
+ return Err(format!("gram-lsp: chmod failed: {e}"));
111
+ }
112
+
113
+ set_language_server_installation_status(
114
+ language_server_id,
115
+ &LanguageServerInstallationStatus::None,
116
+ );
117
+
118
+ self.cached_binary = Some(relative_binary.clone());
119
+ Ok(relative_binary)
120
+ }
121
+ }
122
+
123
+ impl Extension for GramExtension {
124
+ fn new() -> Self {
125
+ Self {
126
+ cached_binary: None,
127
+ }
128
+ }
129
+
130
+ fn language_server_command(
131
+ &mut self,
132
+ language_server_id: &LanguageServerId,
133
+ worktree: &Worktree,
134
+ ) -> Result<Command> {
135
+ if language_server_id.as_ref() != "gram-lsp" {
136
+ return Err(format!(
137
+ "unsupported language server id: {}",
138
+ language_server_id.as_ref()
139
+ ));
140
+ }
141
+
142
+ if let Some(path) = &self.cached_binary {
143
+ return Ok(Command::new(path).arg("stdio"));
144
+ }
145
+
146
+ if let Some(path) = worktree.which("gram-lsp") {
147
+ self.cached_binary = Some(path.clone());
148
+ return Ok(Command::new(path).arg("stdio"));
149
+ }
150
+
151
+ let path = self.ensure_downloaded(language_server_id)?;
152
+ Ok(Command::new(path).arg("stdio"))
153
+ }
154
+ }
155
+
156
+ zed::register_extension!(GramExtension);
package/grammar.js CHANGED
@@ -69,7 +69,7 @@ module.exports = grammar({
69
69
 
70
70
  pattern_reference: ($) => field("identifier", $._identifier),
71
71
 
72
- _identifier: ($) => choice($.symbol, $.string_literal, $.integer),
72
+ _identifier: ($) => choice($.symbol, $.quoted_name, $.integer),
73
73
 
74
74
  _subject: ($) =>
75
75
  choice(
@@ -114,13 +114,13 @@ module.exports = grammar({
114
114
 
115
115
  labels: ($) => repeat1($._label),
116
116
 
117
- _label: ($) => seq(choice(":", "::"), $.symbol),
117
+ _label: ($) => seq(choice(":", "::"), choice($.symbol, $.quoted_name)),
118
118
 
119
119
  record: ($) => seq("{", commaSep($.record_property), "}"),
120
120
 
121
121
  record_property: ($) =>
122
122
  seq(
123
- field("key", $._identifier),
123
+ field("key", $._key_name),
124
124
  choice(":", "::"),
125
125
  field("value", $._value),
126
126
  ),
@@ -128,7 +128,7 @@ module.exports = grammar({
128
128
  map: ($) => seq("{", commaSep($.map_entry), "}"),
129
129
 
130
130
  map_entry: ($) =>
131
- seq(field("key", $._identifier), ":", field("value", $._scalar_value)),
131
+ seq(field("key", $._key_name), ":", field("value", $._scalar_value)),
132
132
 
133
133
  symbol: ($) => token(/[a-zA-Z_][0-9a-zA-Z_.\-@]*/),
134
134
 
@@ -174,6 +174,15 @@ module.exports = grammar({
174
174
  return token(measurement);
175
175
  },
176
176
 
177
+ quoted_name: ($) =>
178
+ delimit_string(alias($._backticked_text, $.string_content), "`"),
179
+
180
+ double_quoted_name: ($) =>
181
+ delimit_string(alias($._double_quoted_text, $.string_content), '"'),
182
+
183
+ _key_name: ($) =>
184
+ choice($.symbol, $.quoted_name, $.double_quoted_name),
185
+
177
186
  string_literal: ($) =>
178
187
  choice(
179
188
  $._single_quoted_string,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gram-data/tree-sitter-gram",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "subject-oriented notation for structured data",
5
5
  "homepage": "https://gram-data.github.io",
6
6
  "repository": {
@@ -21,30 +21,48 @@
21
21
  ; Reference identifier: pattern_reference (FR-001)
22
22
  (pattern_reference identifier: (_) @variable)
23
23
 
24
- ; Definition-like identifiers (FR-001): @type
24
+ ; Symbols and identifiers (generic; definition/reference/tag captured above)
25
+ (symbol) @variable
26
+
27
+ ; Definition-like identifiers and labels (FR-001): @type
28
+ ; These must come AFTER generic symbol rule to take priority
29
+
30
+ ; Labels (symbols and quoted names in labels nodes)
31
+ (labels (symbol) @type)
32
+ (labels (quoted_name) @type)
33
+
34
+ ; Annotation identifiers and labels
35
+ (identified_annotation identifier: (_) @type)
36
+ (identified_annotation labels: (labels (symbol) @type))
37
+ (identified_annotation labels: (labels (quoted_name) @type))
38
+
39
+ ; Subject, node, and relationship pattern definitions (FR-001): @type
25
40
  ; subject/node subject is _subject (use wildcard _ as it may be hidden in some runtimes)
26
41
  (subject_pattern subject: (_ identifier: (_) @type))
27
42
  (subject_pattern subject: (_ labels: (labels (symbol) @type)))
43
+ (subject_pattern subject: (_ labels: (labels (quoted_name) @type)))
28
44
  (node_pattern subject: (_ identifier: (_) @type))
29
45
  (node_pattern subject: (_ labels: (labels (symbol) @type)))
46
+ (node_pattern subject: (_ labels: (labels (quoted_name) @type)))
30
47
  (relationship_pattern left: (node_pattern subject: (_ identifier: (_) @type)))
31
48
  (relationship_pattern left: (node_pattern subject: (_ labels: (labels (symbol) @type))))
49
+ (relationship_pattern left: (node_pattern subject: (_ labels: (labels (quoted_name) @type))))
32
50
  (relationship_pattern right: (node_pattern subject: (_ identifier: (_) @type)))
33
51
  (relationship_pattern right: (node_pattern subject: (_ labels: (labels (symbol) @type))))
52
+ (relationship_pattern right: (node_pattern subject: (_ labels: (labels (quoted_name) @type))))
34
53
  ; Arrow kind: subject is inside optional brackets on the arrow
35
54
  (relationship_pattern kind: (right_arrow subject: (_ identifier: (_) @type)))
36
55
  (relationship_pattern kind: (right_arrow subject: (_ labels: (labels (symbol) @type))))
56
+ (relationship_pattern kind: (right_arrow subject: (_ labels: (labels (quoted_name) @type))))
37
57
  (relationship_pattern kind: (left_arrow subject: (_ identifier: (_) @type)))
38
58
  (relationship_pattern kind: (left_arrow subject: (_ labels: (labels (symbol) @type))))
59
+ (relationship_pattern kind: (left_arrow subject: (_ labels: (labels (quoted_name) @type))))
39
60
  (relationship_pattern kind: (undirected_arrow subject: (_ identifier: (_) @type)))
40
61
  (relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (symbol) @type))))
62
+ (relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (quoted_name) @type))))
41
63
  (relationship_pattern kind: (bidirectional_arrow subject: (_ identifier: (_) @type)))
42
64
  (relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (symbol) @type))))
43
- (identified_annotation identifier: (_) @type)
44
- (identified_annotation labels: (labels (symbol) @type))
45
-
46
- ; Symbols and identifiers (generic; definition/reference/tag captured above)
47
- (symbol) @variable
65
+ (relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (quoted_name) @type))))
48
66
 
49
67
  ; Keywords and operators
50
68
  [
@@ -71,11 +89,11 @@
71
89
 
72
90
  ; Field names in records and maps
73
91
  (record_property key: (symbol) @property)
74
- (record_property key: (string_literal) @property)
75
- (record_property key: (integer) @property)
92
+ (record_property key: (quoted_name) @property)
93
+ (record_property key: (double_quoted_name) @property)
76
94
  (map_entry key: (symbol) @property)
77
- (map_entry key: (string_literal) @property)
78
- (map_entry key: (integer) @property)
95
+ (map_entry key: (quoted_name) @property)
96
+ (map_entry key: (double_quoted_name) @property)
79
97
 
80
98
  ; Annotation keys (property-style) and headers (identified/label-style)
81
99
  (property_annotation key: (symbol) @attribute)
@@ -7,22 +7,31 @@
7
7
  ; Definitions: identifiers that define a pattern or annotation
8
8
  (subject_pattern subject: (_ identifier: (_) @local.definition))
9
9
  (subject_pattern subject: (_ labels: (labels (symbol) @local.definition)))
10
+ (subject_pattern subject: (_ labels: (labels (quoted_name) @local.definition)))
10
11
  (node_pattern subject: (_ identifier: (_) @local.definition))
11
12
  (node_pattern subject: (_ labels: (labels (symbol) @local.definition)))
13
+ (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition)))
12
14
  (relationship_pattern left: (node_pattern subject: (_ identifier: (_) @local.definition)))
13
15
  (relationship_pattern left: (node_pattern subject: (_ labels: (labels (symbol) @local.definition))))
16
+ (relationship_pattern left: (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition))))
14
17
  (relationship_pattern right: (node_pattern subject: (_ identifier: (_) @local.definition)))
15
18
  (relationship_pattern right: (node_pattern subject: (_ labels: (labels (symbol) @local.definition))))
19
+ (relationship_pattern right: (node_pattern subject: (_ labels: (labels (quoted_name) @local.definition))))
16
20
  (relationship_pattern kind: (right_arrow subject: (_ identifier: (_) @local.definition)))
17
21
  (relationship_pattern kind: (right_arrow subject: (_ labels: (labels (symbol) @local.definition))))
22
+ (relationship_pattern kind: (right_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
18
23
  (relationship_pattern kind: (left_arrow subject: (_ identifier: (_) @local.definition)))
19
24
  (relationship_pattern kind: (left_arrow subject: (_ labels: (labels (symbol) @local.definition))))
25
+ (relationship_pattern kind: (left_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
20
26
  (relationship_pattern kind: (undirected_arrow subject: (_ identifier: (_) @local.definition)))
21
27
  (relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (symbol) @local.definition))))
28
+ (relationship_pattern kind: (undirected_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
22
29
  (relationship_pattern kind: (bidirectional_arrow subject: (_ identifier: (_) @local.definition)))
23
30
  (relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (symbol) @local.definition))))
31
+ (relationship_pattern kind: (bidirectional_arrow subject: (_ labels: (labels (quoted_name) @local.definition))))
24
32
  (identified_annotation identifier: (_) @local.definition)
25
33
  (identified_annotation labels: (labels (symbol) @local.definition))
34
+ (identified_annotation labels: (labels (quoted_name) @local.definition))
26
35
 
27
36
  ; References: pattern_reference identifier
28
37
  (pattern_reference identifier: (_) @local.reference)