tree-sitter-ucode 0.2.0 → 0.3.0

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.
package/README.md CHANGED
@@ -7,7 +7,12 @@ Two grammars are provided:
7
7
  | Grammar | Scope | File types |
8
8
  |---------|-------|------------|
9
9
  | `ucode` | `source.uc` | `.uc` |
10
- | `ucode_tmpl` | `source.uc.tmpl` | `.uc.tmpl`, `.utpl` |
10
+ | `ucode_tmpl` | `source.uc.tmpl` | `.uc` (template files — detected by content) |
11
+
12
+ Both grammars use the `.uc` extension. Template files are distinguished from plain
13
+ code files by content: any `.uc` file whose first tag opener (`{%`, `{{`, or `{#`)
14
+ appears at the start of a line is automatically parsed by `ucode_tmpl`. Plain code
15
+ files fall back to `ucode`. See [File-type detection](#file-type-detection) below.
11
16
 
12
17
  ## Ucode vs JavaScript
13
18
 
@@ -55,10 +60,18 @@ npm test # runs tree-sitter test for ucode and ucode_tmpl
55
60
  To filter by corpus file name:
56
61
 
57
62
  ```sh
58
- npx tree-sitter test --file-name control_flow
63
+ npx tree-sitter test --lib-path ucode.so --lang-name ucode --file-name control_flow
59
64
  npx tree-sitter test -p tmpl --file-name template
60
65
  ```
61
66
 
67
+ ## File-type detection
68
+
69
+ Both grammars claim the `.uc` extension. Tools that respect `content-regex` in
70
+ `tree-sitter.json` (including the tree-sitter CLI ≥ 0.24) automatically route
71
+ template files to `ucode_tmpl` when a tag opener appears at the start of a line.
72
+ Editors that manage their own filetype dispatch (Neovim, Helix) need an explicit
73
+ rule — see the editor sections below.
74
+
62
75
  ## Use in Neovim (nvim-treesitter)
63
76
 
64
77
  Add to your nvim-treesitter config (e.g. `~/.config/nvim/lua/plugins/treesitter.lua`):
@@ -85,15 +98,26 @@ parser_config.ucode_tmpl = {
85
98
  }
86
99
  ```
87
100
 
88
- Associate `.uc` and `.uc.tmpl` files with the right filetypes:
101
+ Associate `.uc` files with the right filetype. Since nvim-treesitter does not
102
+ use `content-regex`, the mapping must be done with a `BufRead` autocmd or a
103
+ filetype function that inspects the file content:
89
104
 
90
105
  ```lua
91
106
  vim.filetype.add({
92
107
  extension = {
93
- uc = "ucode",
94
- utpl = "ucode_tmpl",
108
+ uc = function(path)
109
+ -- Files whose first tag opener is at the start of a line are templates
110
+ local f = io.open(path, "r")
111
+ if f then
112
+ local content = f:read("*a")
113
+ f:close()
114
+ if content:find("^%s*{[%%{#]", 1, false) or content:find("\n%s*{[%%{#]") then
115
+ return "ucode_tmpl"
116
+ end
117
+ end
118
+ return "ucode"
119
+ end,
95
120
  },
96
- pattern = { [".*%.uc%.tmpl"] = "ucode_tmpl" },
97
121
  })
98
122
  ```
99
123
 
@@ -103,32 +127,38 @@ Add to `~/.config/helix/languages.toml`:
103
127
 
104
128
  ```toml
105
129
  [[language]]
106
- name = "ucode"
107
- scope = "source.uc"
108
- file-types = ["uc"]
130
+ name = "ucode"
131
+ scope = "source.uc"
132
+ file-types = [{ glob = "*.uc" }]
109
133
  comment-token = "//"
110
- indent = { tab-width = 2, unit = " " }
111
- grammar = "ucode"
134
+ indent = { tab-width = 2, unit = " " }
135
+ grammar = "ucode"
112
136
 
113
137
  [[language]]
114
- name = "ucode-tmpl"
115
- scope = "source.uc.tmpl"
116
- file-types = ["uc.tmpl", "utpl"]
117
- grammar = "ucode_tmpl"
138
+ name = "ucode-tmpl"
139
+ scope = "source.uc.tmpl"
140
+ comment-token = "{#"
141
+ indent = { tab-width = 2, unit = " " }
142
+ grammar = "ucode_tmpl"
118
143
 
119
144
  [[grammar]]
120
145
  name = "ucode"
121
- source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "main" }
146
+ source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.3.0" }
122
147
 
123
148
  [[grammar]]
124
149
  name = "ucode_tmpl"
125
- source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "main", subpath = "tmpl" }
150
+ source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.3.0", subpath = "tmpl" }
126
151
  ```
127
152
 
128
- ## Template files (.uc.tmpl / .utpl)
153
+ Helix does not support content-based filetype detection. To open a `.uc`
154
+ template file as `ucode-tmpl`, use `:set-language ucode-tmpl` in command mode,
155
+ or configure a file-specific override via a `.helix/languages.toml` in your
156
+ project.
157
+
158
+ ## Template files
129
159
 
130
- Template files mix raw text with code tags. The `ucode_tmpl` grammar produces
131
- a document tree; editors use language injection to apply ucode highlighting
160
+ Template files mix raw text with code tags. The `ucode_tmpl` grammar produces a
161
+ `document` tree; editors use language injection to apply ucode highlighting
132
162
  inside the code and expression tags.
133
163
 
134
164
  | Tag | Purpose |
@@ -141,7 +171,17 @@ inside the code and expression tags.
141
171
  | `{%+ ... %}` | Statement block — suppress `lstrip_blocks` stripping |
142
172
  | `{#- ... -#}` | Comment — strip whitespace on both sides |
143
173
 
144
- Opener and closer markers are independent: any opener variant may be combined with any closer variant. `{%-` / `{{-` / `{#-` strip the preceding raw text; `-%}` / `-}}` / `-#}` strip the following raw text. `{%+` suppresses `lstrip_blocks` stripping and may be combined with `-%}` (e.g. `{%+ ... -%}`).
174
+ Opener and closer markers are independent: any opener variant may be combined
175
+ with any closer variant. `{%-` / `{{-` / `{#-` strip the preceding raw text;
176
+ `-%}` / `-}}` / `-#}` strip the following raw text. `{%+` suppresses
177
+ `lstrip_blocks` stripping and may be combined with `-%}`.
178
+
179
+ **EOF-implicit close**: a `{%` statement tag that reaches end-of-file without
180
+ an explicit `%}` is treated as implicitly closed. This supports the common
181
+ OpenWrt pattern of a file that opens one `{%` block at the top and contains
182
+ only ucode code, with no closing `%}`. The parse tree shows an `(eof_close)`
183
+ node in the `close` field. Expression (`{{`) and comment (`{#`) tags still
184
+ require explicit closers.
145
185
 
146
186
  Example:
147
187
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-sitter-ucode",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Ucode grammar for tree-sitter",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "devDependencies": {
37
37
  "prebuildify": "^6.0.1",
38
- "tree-sitter-cli": "^0.26.0"
38
+ "tree-sitter-cli": "0.26.9"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "tree-sitter": "^0.22.0"
@@ -48,7 +48,7 @@
48
48
  "scripts": {
49
49
  "install": "node-gyp-build",
50
50
  "build": "tree-sitter generate && tree-sitter generate tmpl/grammar.js --output tmpl/src && node-gyp-build && tree-sitter build --output ucode.so . && tree-sitter build --output ucode_tmpl.so ./tmpl",
51
- "test": "tree-sitter test && tree-sitter test -p tmpl",
51
+ "test": "node scripts/run-tests.js",
52
52
  "prestart": "tree-sitter build --wasm",
53
53
  "start": "tree-sitter playground"
54
54
  }
@@ -0,0 +1,38 @@
1
+ ; Fold queries for ucode.
2
+ ; Each captured node becomes a collapsible fold region.
3
+
4
+ ; -------------------------------------------------------------------------
5
+ ; Brace-delimited blocks
6
+ ;
7
+ ; statement_block covers brace-body function_declaration, function_expression,
8
+ ; and arrow_function bodies — the signature line stays visible because the
9
+ ; fold starts at '{', not at the 'function' keyword.
10
+ ; -------------------------------------------------------------------------
11
+
12
+ [
13
+ (statement_block)
14
+ (switch_body)
15
+ (object)
16
+ (array)
17
+ ] @fold
18
+
19
+ ; -------------------------------------------------------------------------
20
+ ; Alternative (colon/endif) syntax — fold the entire construct
21
+ ; -------------------------------------------------------------------------
22
+
23
+ [
24
+ (if_alt_statement)
25
+ (for_alt_statement)
26
+ (for_in_alt_statement)
27
+ (while_alt_statement)
28
+ ] @fold
29
+
30
+ ; -------------------------------------------------------------------------
31
+ ; Colon-body function declaration (function f(): ... endfunction)
32
+ ;
33
+ ; Brace-body function declarations are folded via (statement_block) above.
34
+ ; The colon form has no statement_block, so we fold the whole declaration.
35
+ ; We filter on "endfunction" so this pattern only matches the colon form.
36
+ ; -------------------------------------------------------------------------
37
+
38
+ (function_declaration "endfunction") @fold
@@ -119,6 +119,12 @@
119
119
  ["import" "export"] @keyword.import
120
120
  ["as" "from"] @keyword.import
121
121
 
122
+ ; 'default' in export context is a module keyword, not a conditional.
123
+ ; These patterns are more specific than the generic ["switch" "case" "default"]
124
+ ; below, so they take priority for 'default' tokens inside export constructs.
125
+ (export_statement "default" @keyword.import)
126
+ (export_specifier "default" @keyword.import)
127
+
122
128
  ; -------------------------------------------------------------------------
123
129
  ; Keywords — storage / operators
124
130
  ; -------------------------------------------------------------------------
@@ -0,0 +1,63 @@
1
+ ; Indentation queries for ucode.
2
+ ; Capture names follow the nvim-treesitter standard.
3
+
4
+ ; -------------------------------------------------------------------------
5
+ ; Brace-delimited constructs — increase indent inside
6
+ ; -------------------------------------------------------------------------
7
+
8
+ [
9
+ (statement_block)
10
+ (switch_body)
11
+ (object)
12
+ (array)
13
+ (arguments)
14
+ (formal_parameters)
15
+ ] @indent.begin
16
+
17
+ ; Closing delimiters — decrease indent
18
+ [
19
+ "}"
20
+ "]"
21
+ ")"
22
+ ] @indent.end
23
+
24
+ ; -------------------------------------------------------------------------
25
+ ; Alternative (colon/endif) syntax
26
+ ; -------------------------------------------------------------------------
27
+
28
+ ; The ':' after the condition opens the body
29
+ (if_alt_statement ":" @indent.begin)
30
+ (elif_clause ":" @indent.begin)
31
+ (for_alt_statement ":" @indent.begin)
32
+ (for_in_alt_statement ":" @indent.begin)
33
+ (while_alt_statement ":" @indent.begin)
34
+ (function_declaration ":" @indent.begin)
35
+
36
+ ; Closing keywords close the body
37
+ [
38
+ "endif"
39
+ "endfor"
40
+ "endwhile"
41
+ "endfunction"
42
+ ] @indent.end
43
+
44
+ ; -------------------------------------------------------------------------
45
+ ; Branch keywords (else/elif) — dedent keyword, indent following body
46
+ ; -------------------------------------------------------------------------
47
+
48
+ (else_clause "else") @indent.branch
49
+ (else_alt_clause "else") @indent.branch
50
+ (elif_clause "elif") @indent.branch
51
+
52
+ ; else_alt_clause has no ':' delimiter (grammar: 'else' repeat(statement)),
53
+ ; so @indent.branch alone only dedents the 'else' keyword — it does not
54
+ ; open an indent scope for the body. Add @indent.begin on the whole node
55
+ ; so the body statements are indented one level relative to 'else'.
56
+ (else_alt_clause) @indent.begin
57
+
58
+ ; -------------------------------------------------------------------------
59
+ ; Switch
60
+ ; -------------------------------------------------------------------------
61
+
62
+ (switch_case "case") @indent.branch
63
+ (switch_default "default") @indent.branch
@@ -0,0 +1,84 @@
1
+ ; Text-object queries for nvim-treesitter-textobjects.
2
+ ; Provides @function, @parameter, @conditional, @loop, @call, and @block
3
+ ; text objects for ucode source files.
4
+
5
+ ; -------------------------------------------------------------------------
6
+ ; Functions
7
+ ; -------------------------------------------------------------------------
8
+
9
+ ; Brace-body function declaration
10
+ (function_declaration
11
+ body: (statement_block) @function.inner) @function.outer
12
+
13
+ ; Colon-body function declaration — outer only; no block node to target for inner
14
+ (function_declaration "endfunction") @function.outer
15
+
16
+ (function_expression
17
+ body: (statement_block) @function.inner) @function.outer
18
+
19
+ (arrow_function
20
+ body: (statement_block) @function.inner) @function.outer
21
+
22
+ ; Arrow function with expression body (no braces).
23
+ ; Uses the 'expression' supertype so all expression forms are matched
24
+ ; without an explicit enumeration — including update_expression (x => x++),
25
+ ; assignment_expression (x => y = 1), and any type added to the grammar later.
26
+ (arrow_function
27
+ body: (expression) @function.inner) @function.outer
28
+
29
+ ; -------------------------------------------------------------------------
30
+ ; Parameters
31
+ ;
32
+ ; @parameter.inner — the parameter node itself
33
+ ; @parameter.outer — same node; nvim-treesitter-textobjects extends the
34
+ ; selection to absorb adjacent ',' delimiters automatically when the
35
+ ; capture name ends in .outer
36
+ ; -------------------------------------------------------------------------
37
+
38
+ (formal_parameters (_) @parameter.inner)
39
+ (formal_parameters (_) @parameter.outer)
40
+
41
+ ; -------------------------------------------------------------------------
42
+ ; Conditionals
43
+ ; -------------------------------------------------------------------------
44
+
45
+ (if_statement
46
+ consequence: (statement_block) @conditional.inner) @conditional.outer
47
+
48
+ (if_alt_statement) @conditional.outer
49
+
50
+ ; -------------------------------------------------------------------------
51
+ ; Loops
52
+ ; -------------------------------------------------------------------------
53
+
54
+ (for_statement
55
+ body: (statement_block) @loop.inner) @loop.outer
56
+
57
+ (for_in_statement
58
+ body: (statement_block) @loop.inner) @loop.outer
59
+
60
+ (while_statement
61
+ body: (statement_block) @loop.inner) @loop.outer
62
+
63
+ (for_alt_statement) @loop.outer
64
+ (for_in_alt_statement) @loop.outer
65
+ (while_alt_statement) @loop.outer
66
+
67
+ ; -------------------------------------------------------------------------
68
+ ; Calls
69
+ ; -------------------------------------------------------------------------
70
+
71
+ (call_expression
72
+ arguments: (arguments) @call.inner) @call.outer
73
+
74
+ ; -------------------------------------------------------------------------
75
+ ; Blocks
76
+ ;
77
+ ; @block.outer — the full statement_block including braces
78
+ ; @block.inner — named children only; nvim-treesitter-textobjects selects
79
+ ; from the first to the last captured child, covering the block interior
80
+ ; without needing the deprecated #make-range! predicate
81
+ ; -------------------------------------------------------------------------
82
+
83
+ (statement_block) @block.outer
84
+ (statement_block (_) @block.inner)
package/src/parser.c CHANGED
@@ -32491,7 +32491,7 @@ TS_PUBLIC const TSLanguage *tree_sitter_ucode(void) {
32491
32491
  .max_reserved_word_set_size = 28,
32492
32492
  .metadata = {
32493
32493
  .major_version = 0,
32494
- .minor_version = 2,
32494
+ .minor_version = 3,
32495
32495
  .patch_version = 0,
32496
32496
  },
32497
32497
  };
package/tmpl/grammar.js CHANGED
@@ -33,6 +33,7 @@ module.exports = grammar({
33
33
  $._stmt_code, // content between {% ... %} (before the closer)
34
34
  $._expr_code, // content between {{ ... }} (before the closer)
35
35
  $._comment_body, // content between {# ... #} (before the closer)
36
+ $.eof_close, // emitted at EOF when inside a statement tag (implicit close)
36
37
  ],
37
38
 
38
39
  // The template scanner handles all whitespace explicitly; no implicit extras.
@@ -49,7 +50,7 @@ module.exports = grammar({
49
50
  statement_tag: $ => seq(
50
51
  field('open', choice('{%-', '{%+', '{%')),
51
52
  field('code', optional(alias($._stmt_code, $.code))),
52
- field('close', choice('-%}', '%}')),
53
+ field('close', choice('-%}', '%}', $.eof_close)),
53
54
  ),
54
55
 
55
56
  expression_tag: $ => seq(
@@ -0,0 +1,4 @@
1
+ ; Fold queries for ucode_tmpl.
2
+ ; Folds are not meaningful at the template document level since each tag is
3
+ ; typically one or a few lines. Folding inside code blocks is handled by the
4
+ ; injected ucode grammar.
@@ -0,0 +1,5 @@
1
+ ; Indentation queries for ucode_tmpl.
2
+ ; Raw text between tags is not indented by the template engine, so there are
3
+ ; no template-level indent rules. Code inside statement_tag and expression_tag
4
+ ; is parsed via language injection (see injections.scm) and indented according
5
+ ; to the injected ucode grammar's indents.scm.
@@ -89,6 +89,10 @@
89
89
  {
90
90
  "type": "STRING",
91
91
  "value": "%}"
92
+ },
93
+ {
94
+ "type": "SYMBOL",
95
+ "name": "eof_close"
92
96
  }
93
97
  ]
94
98
  }
@@ -235,6 +239,10 @@
235
239
  {
236
240
  "type": "SYMBOL",
237
241
  "name": "_comment_body"
242
+ },
243
+ {
244
+ "type": "SYMBOL",
245
+ "name": "eof_close"
238
246
  }
239
247
  ],
240
248
  "inline": [],
@@ -130,6 +130,10 @@
130
130
  {
131
131
  "type": "-%}",
132
132
  "named": false
133
+ },
134
+ {
135
+ "type": "eof_close",
136
+ "named": true
133
137
  }
134
138
  ]
135
139
  },
@@ -191,6 +195,10 @@
191
195
  "type": "comment_content",
192
196
  "named": true
193
197
  },
198
+ {
199
+ "type": "eof_close",
200
+ "named": true
201
+ },
194
202
  {
195
203
  "type": "raw_text",
196
204
  "named": true
package/tmpl/src/parser.c CHANGED
@@ -9,10 +9,10 @@
9
9
  #define LANGUAGE_VERSION 15
10
10
  #define STATE_COUNT 17
11
11
  #define LARGE_STATE_COUNT 4
12
- #define SYMBOL_COUNT 23
12
+ #define SYMBOL_COUNT 24
13
13
  #define ALIAS_COUNT 0
14
- #define TOKEN_COUNT 18
15
- #define EXTERNAL_TOKEN_COUNT 4
14
+ #define TOKEN_COUNT 19
15
+ #define EXTERNAL_TOKEN_COUNT 5
16
16
  #define FIELD_COUNT 4
17
17
  #define MAX_ALIAS_SEQUENCE_LENGTH 3
18
18
  #define MAX_RESERVED_WORD_SET_SIZE 0
@@ -37,11 +37,12 @@ enum ts_symbol_identifiers {
37
37
  sym__stmt_code = 15,
38
38
  sym__expr_code = 16,
39
39
  sym__comment_body = 17,
40
- sym_document = 18,
41
- sym_statement_tag = 19,
42
- sym_expression_tag = 20,
43
- sym_comment_tag = 21,
44
- aux_sym_document_repeat1 = 22,
40
+ sym_eof_close = 18,
41
+ sym_document = 19,
42
+ sym_statement_tag = 20,
43
+ sym_expression_tag = 21,
44
+ sym_comment_tag = 22,
45
+ aux_sym_document_repeat1 = 23,
45
46
  };
46
47
 
47
48
  static const char * const ts_symbol_names[] = {
@@ -63,6 +64,7 @@ static const char * const ts_symbol_names[] = {
63
64
  [sym__stmt_code] = "code",
64
65
  [sym__expr_code] = "code",
65
66
  [sym__comment_body] = "comment_content",
67
+ [sym_eof_close] = "eof_close",
66
68
  [sym_document] = "document",
67
69
  [sym_statement_tag] = "statement_tag",
68
70
  [sym_expression_tag] = "expression_tag",
@@ -89,6 +91,7 @@ static const TSSymbol ts_symbol_map[] = {
89
91
  [sym__stmt_code] = sym__stmt_code,
90
92
  [sym__expr_code] = sym__stmt_code,
91
93
  [sym__comment_body] = sym__comment_body,
94
+ [sym_eof_close] = sym_eof_close,
92
95
  [sym_document] = sym_document,
93
96
  [sym_statement_tag] = sym_statement_tag,
94
97
  [sym_expression_tag] = sym_expression_tag,
@@ -169,6 +172,10 @@ static const TSSymbolMetadata ts_symbol_metadata[] = {
169
172
  .visible = true,
170
173
  .named = true,
171
174
  },
175
+ [sym_eof_close] = {
176
+ .visible = true,
177
+ .named = true,
178
+ },
172
179
  [sym_document] = {
173
180
  .visible = true,
174
181
  .named = true,
@@ -359,7 +366,7 @@ static const TSLexerMode ts_lex_modes[STATE_COUNT] = {
359
366
  [10] = {.lex_state = 0, .external_lex_state = 3},
360
367
  [11] = {.lex_state = 0, .external_lex_state = 4},
361
368
  [12] = {.lex_state = 0, .external_lex_state = 5},
362
- [13] = {.lex_state = 0},
369
+ [13] = {.lex_state = 0, .external_lex_state = 6},
363
370
  [14] = {.lex_state = 0},
364
371
  [15] = {.lex_state = 0},
365
372
  [16] = {.lex_state = 0},
@@ -385,6 +392,7 @@ static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = {
385
392
  [sym__stmt_code] = ACTIONS(1),
386
393
  [sym__expr_code] = ACTIONS(1),
387
394
  [sym__comment_body] = ACTIONS(1),
395
+ [sym_eof_close] = ACTIONS(1),
388
396
  },
389
397
  [STATE(1)] = {
390
398
  [sym_document] = STATE(16),
@@ -510,34 +518,36 @@ static const uint16_t ts_small_parse_table[] = {
510
518
  [84] = 2,
511
519
  ACTIONS(72), 1,
512
520
  sym__stmt_code,
513
- ACTIONS(70), 2,
521
+ ACTIONS(70), 3,
522
+ sym_eof_close,
514
523
  anon_sym_DASH_PERCENT_RBRACE,
515
524
  anon_sym_PERCENT_RBRACE,
516
- [92] = 2,
525
+ [93] = 2,
517
526
  ACTIONS(76), 1,
518
527
  sym__expr_code,
519
528
  ACTIONS(74), 2,
520
529
  anon_sym_DASH_RBRACE_RBRACE,
521
530
  anon_sym_RBRACE_RBRACE,
522
- [100] = 2,
531
+ [101] = 2,
523
532
  ACTIONS(80), 1,
524
533
  sym__comment_body,
525
534
  ACTIONS(78), 2,
526
535
  anon_sym_DASH_POUND_RBRACE,
527
536
  anon_sym_POUND_RBRACE,
528
- [108] = 1,
529
- ACTIONS(82), 2,
537
+ [109] = 1,
538
+ ACTIONS(82), 3,
539
+ sym_eof_close,
530
540
  anon_sym_DASH_PERCENT_RBRACE,
531
541
  anon_sym_PERCENT_RBRACE,
532
- [113] = 1,
542
+ [115] = 1,
533
543
  ACTIONS(84), 2,
534
544
  anon_sym_DASH_RBRACE_RBRACE,
535
545
  anon_sym_RBRACE_RBRACE,
536
- [118] = 1,
546
+ [120] = 1,
537
547
  ACTIONS(86), 2,
538
548
  anon_sym_DASH_POUND_RBRACE,
539
549
  anon_sym_POUND_RBRACE,
540
- [123] = 1,
550
+ [125] = 1,
541
551
  ACTIONS(88), 1,
542
552
  ts_builtin_sym_end,
543
553
  };
@@ -550,12 +560,12 @@ static const uint32_t ts_small_parse_table_map[] = {
550
560
  [SMALL_STATE(8)] = 56,
551
561
  [SMALL_STATE(9)] = 70,
552
562
  [SMALL_STATE(10)] = 84,
553
- [SMALL_STATE(11)] = 92,
554
- [SMALL_STATE(12)] = 100,
555
- [SMALL_STATE(13)] = 108,
556
- [SMALL_STATE(14)] = 113,
557
- [SMALL_STATE(15)] = 118,
558
- [SMALL_STATE(16)] = 123,
563
+ [SMALL_STATE(11)] = 93,
564
+ [SMALL_STATE(12)] = 101,
565
+ [SMALL_STATE(13)] = 109,
566
+ [SMALL_STATE(14)] = 115,
567
+ [SMALL_STATE(15)] = 120,
568
+ [SMALL_STATE(16)] = 125,
559
569
  };
560
570
 
561
571
  static const TSParseActionEntry ts_parse_actions[] = {
@@ -608,6 +618,7 @@ enum ts_external_scanner_symbol_identifiers {
608
618
  ts_external_token__stmt_code = 1,
609
619
  ts_external_token__expr_code = 2,
610
620
  ts_external_token__comment_body = 3,
621
+ ts_external_token_eof_close = 4,
611
622
  };
612
623
 
613
624
  static const TSSymbol ts_external_scanner_symbol_map[EXTERNAL_TOKEN_COUNT] = {
@@ -615,20 +626,23 @@ static const TSSymbol ts_external_scanner_symbol_map[EXTERNAL_TOKEN_COUNT] = {
615
626
  [ts_external_token__stmt_code] = sym__stmt_code,
616
627
  [ts_external_token__expr_code] = sym__expr_code,
617
628
  [ts_external_token__comment_body] = sym__comment_body,
629
+ [ts_external_token_eof_close] = sym_eof_close,
618
630
  };
619
631
 
620
- static const bool ts_external_scanner_states[6][EXTERNAL_TOKEN_COUNT] = {
632
+ static const bool ts_external_scanner_states[7][EXTERNAL_TOKEN_COUNT] = {
621
633
  [1] = {
622
634
  [ts_external_token__raw_text] = true,
623
635
  [ts_external_token__stmt_code] = true,
624
636
  [ts_external_token__expr_code] = true,
625
637
  [ts_external_token__comment_body] = true,
638
+ [ts_external_token_eof_close] = true,
626
639
  },
627
640
  [2] = {
628
641
  [ts_external_token__raw_text] = true,
629
642
  },
630
643
  [3] = {
631
644
  [ts_external_token__stmt_code] = true,
645
+ [ts_external_token_eof_close] = true,
632
646
  },
633
647
  [4] = {
634
648
  [ts_external_token__expr_code] = true,
@@ -636,6 +650,9 @@ static const bool ts_external_scanner_states[6][EXTERNAL_TOKEN_COUNT] = {
636
650
  [5] = {
637
651
  [ts_external_token__comment_body] = true,
638
652
  },
653
+ [6] = {
654
+ [ts_external_token_eof_close] = true,
655
+ },
639
656
  };
640
657
 
641
658
  #ifdef __cplusplus
@@ -696,7 +713,7 @@ TS_PUBLIC const TSLanguage *tree_sitter_ucode_tmpl(void) {
696
713
  .max_reserved_word_set_size = 0,
697
714
  .metadata = {
698
715
  .major_version = 0,
699
- .minor_version = 2,
716
+ .minor_version = 3,
700
717
  .patch_version = 0,
701
718
  },
702
719
  };
@@ -6,6 +6,7 @@ enum TokenType {
6
6
  STMT_CODE,
7
7
  EXPR_CODE,
8
8
  COMMENT_BODY,
9
+ EOF_CLOSE,
9
10
  };
10
11
 
11
12
  void *tree_sitter_ucode_tmpl_external_scanner_create(void) { return NULL; }
@@ -160,6 +161,10 @@ bool tree_sitter_ucode_tmpl_external_scanner_scan(
160
161
  ) {
161
162
  (void)payload;
162
163
 
164
+ if (valid_symbols[EOF_CLOSE] && lexer->lookahead == '\0') {
165
+ lexer->result_symbol = EOF_CLOSE;
166
+ return true;
167
+ }
163
168
  if (valid_symbols[RAW_TEXT]) return scan_raw_text(lexer);
164
169
  if (valid_symbols[STMT_CODE]) return scan_stmt_code(lexer);
165
170
  if (valid_symbols[EXPR_CODE]) return scan_expr_code(lexer);
Binary file
Binary file
package/tree-sitter.json CHANGED
@@ -1,33 +1,15 @@
1
1
  {
2
2
  "grammars": [
3
- {
4
- "name": "ucode",
5
- "camelcase": "Ucode",
6
- "scope": "source.uc",
7
- "path": ".",
8
- "file-types": [
9
- "uc"
10
- ],
11
- "highlights": [
12
- "queries/highlights.scm"
13
- ],
14
- "locals": [
15
- "queries/locals.scm"
16
- ],
17
- "tags": [
18
- "queries/tags.scm"
19
- ],
20
- "injection-regex": "^ucode$"
21
- },
22
3
  {
23
4
  "name": "ucode_tmpl",
24
5
  "camelcase": "UcodeTmpl",
25
6
  "scope": "source.uc.tmpl",
26
7
  "path": "./tmpl",
27
8
  "file-types": [
28
- "uc.tmpl",
9
+ "uc",
29
10
  "utpl"
30
11
  ],
12
+ "content-regex": "(?m)^\\s*\\{[%{#]",
31
13
  "highlights": [
32
14
  "tmpl/queries/highlights.scm"
33
15
  ],
@@ -38,10 +20,29 @@
38
20
  "tmpl/queries/injections.scm"
39
21
  ],
40
22
  "injection-regex": "^ucode_tmpl$"
23
+ },
24
+ {
25
+ "name": "ucode",
26
+ "camelcase": "Ucode",
27
+ "scope": "source.uc",
28
+ "path": ".",
29
+ "file-types": [
30
+ "uc"
31
+ ],
32
+ "highlights": [
33
+ "queries/highlights.scm"
34
+ ],
35
+ "locals": [
36
+ "queries/locals.scm"
37
+ ],
38
+ "tags": [
39
+ "queries/tags.scm"
40
+ ],
41
+ "injection-regex": "^ucode$"
41
42
  }
42
43
  ],
43
44
  "metadata": {
44
- "version": "0.2.0",
45
+ "version": "0.3.0",
45
46
  "license": "MIT",
46
47
  "description": "Ucode grammar for tree-sitter",
47
48
  "links": {