tree-sitter-ucode 0.2.0 → 0.4.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 +49 -58
- package/grammar.js +214 -28
- package/markup/grammar.js +1057 -0
- package/markup/queries/folds.scm +20 -0
- package/markup/queries/highlights.scm +38 -0
- package/markup/queries/indents.scm +51 -0
- package/markup/queries/injections.scm +40 -0
- package/markup/queries/locals.scm +107 -0
- package/markup/queries/tags.scm +65 -0
- package/markup/queries/textobjects.scm +56 -0
- package/markup/src/grammar.json +5786 -0
- package/markup/src/node-types.json +3211 -0
- package/markup/src/parser.c +134461 -0
- package/markup/src/scanner.c +22 -0
- package/package.json +8 -7
- package/prebuilds/darwin-arm64/tree-sitter-ucode.node +0 -0
- package/prebuilds/linux-arm64/tree-sitter-ucode.node +0 -0
- package/prebuilds/linux-x64/tree-sitter-ucode.node +0 -0
- package/prebuilds/win32-x64/tree-sitter-ucode.node +0 -0
- package/queries/folds.scm +38 -0
- package/queries/highlights.scm +6 -0
- package/queries/indents.scm +63 -0
- package/queries/locals.scm +1 -0
- package/queries/textobjects.scm +84 -0
- package/scripts/generate-markup-grammar.js +93 -0
- package/src/grammar.json +1069 -226
- package/src/node-types.json +662 -8
- package/src/parser.c +106401 -25117
- package/src/scanner.c +16 -193
- package/src/scanner_impl.h +494 -0
- package/tree-sitter-ucode.wasm +0 -0
- package/tree-sitter-ucode_markup.wasm +0 -0
- package/tree-sitter.json +24 -12
- package/tmpl/grammar.js +0 -67
- package/tmpl/queries/highlights.scm +0 -23
- package/tmpl/queries/injections.scm +0 -8
- package/tmpl/queries/locals.scm +0 -3
- package/tmpl/src/grammar.json +0 -243
- package/tmpl/src/node-types.json +0 -230
- package/tmpl/src/parser.c +0 -707
- package/tmpl/src/scanner.c +0 -169
- package/tree-sitter-ucode_tmpl.wasm +0 -0
- /package/{tmpl → markup}/src/tree_sitter/alloc.h +0 -0
- /package/{tmpl → markup}/src/tree_sitter/array.h +0 -0
- /package/{tmpl → markup}/src/tree_sitter/parser.h +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* External scanner for the ucode_markup grammar.
|
|
3
|
+
*
|
|
4
|
+
* All implementation lives in src/scanner_impl.h (static functions). This
|
|
5
|
+
* file only exports the five tree_sitter_ucode_markup_external_scanner_*
|
|
6
|
+
* entry points — no ucode_* symbols leak into this shared library.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#include "../../src/scanner_impl.h"
|
|
10
|
+
|
|
11
|
+
void *tree_sitter_ucode_markup_external_scanner_create(void) { return NULL; }
|
|
12
|
+
void tree_sitter_ucode_markup_external_scanner_destroy(void *p) { (void)p; }
|
|
13
|
+
unsigned tree_sitter_ucode_markup_external_scanner_serialize(void *p, char *b) { (void)p; (void)b; return 0; }
|
|
14
|
+
void tree_sitter_ucode_markup_external_scanner_deserialize(void *p, const char *b, unsigned n) {
|
|
15
|
+
(void)p; (void)b; (void)n;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
bool tree_sitter_ucode_markup_external_scanner_scan(
|
|
19
|
+
void *payload, TSLexer *lexer, const bool *valid_symbols
|
|
20
|
+
) {
|
|
21
|
+
return ucode_scanner_scan(payload, lexer, valid_symbols);
|
|
22
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tree-sitter-ucode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Ucode grammar for tree-sitter",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,9 +24,10 @@
|
|
|
24
24
|
"bindings/node/*",
|
|
25
25
|
"queries/*",
|
|
26
26
|
"src/**",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
27
|
+
"markup/grammar.js",
|
|
28
|
+
"markup/src/**",
|
|
29
|
+
"markup/queries/*",
|
|
30
|
+
"scripts/generate-markup-grammar.js",
|
|
30
31
|
"*.wasm"
|
|
31
32
|
],
|
|
32
33
|
"dependencies": {
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"prebuildify": "^6.0.1",
|
|
38
|
-
"tree-sitter-cli": "
|
|
39
|
+
"tree-sitter-cli": "0.26.9"
|
|
39
40
|
},
|
|
40
41
|
"peerDependencies": {
|
|
41
42
|
"tree-sitter": "^0.22.0"
|
|
@@ -47,8 +48,8 @@
|
|
|
47
48
|
},
|
|
48
49
|
"scripts": {
|
|
49
50
|
"install": "node-gyp-build",
|
|
50
|
-
"build": "tree-sitter generate && tree-sitter generate
|
|
51
|
-
"test": "
|
|
51
|
+
"build": "node scripts/generate-markup-grammar.js && tree-sitter generate && tree-sitter generate markup/grammar.js --output markup/src && node-gyp-build && tree-sitter build --output ucode.so . && tree-sitter build --output ucode_markup.so ./markup",
|
|
52
|
+
"test": "node scripts/run-tests.js",
|
|
52
53
|
"prestart": "tree-sitter build --wasm",
|
|
53
54
|
"start": "tree-sitter playground"
|
|
54
55
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
package/queries/highlights.scm
CHANGED
|
@@ -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
|
package/queries/locals.scm
CHANGED
|
@@ -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)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Generate markup/grammar.js from grammar.js.
|
|
4
|
+
*
|
|
5
|
+
* The main grammar has `program` as the first (start) rule so that `.uc`
|
|
6
|
+
* files work. For `.uc.tmpl` files we need `markup` to be the
|
|
7
|
+
* start rule. This script produces markup/grammar.js by:
|
|
8
|
+
*
|
|
9
|
+
* 1. Changing the grammar name from 'ucode' to 'ucode_markup'
|
|
10
|
+
* 2. Swapping the `markup` and `program` rule definitions so `markup`
|
|
11
|
+
* appears first (tree-sitter uses the first rule as the start rule)
|
|
12
|
+
*
|
|
13
|
+
* The generated file is checked in and rebuilt whenever grammar.js changes.
|
|
14
|
+
* Run via `npm run generate-markup` or as part of `npm run build`.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
const srcPath = path.resolve(__dirname, '..', 'grammar.js');
|
|
23
|
+
const dstPath = path.resolve(__dirname, '..', 'markup', 'grammar.js');
|
|
24
|
+
|
|
25
|
+
let src = fs.readFileSync(srcPath, 'utf8');
|
|
26
|
+
|
|
27
|
+
// 1. Rename the grammar
|
|
28
|
+
src = src.replace(/name:\s*'ucode'/, "name: 'ucode_markup'");
|
|
29
|
+
|
|
30
|
+
// 2. Locate the `program` and `markup` rule definitions inside `rules: { ... }`.
|
|
31
|
+
// Each top-level rule starts with "\n <ident>: $ =>".
|
|
32
|
+
// We need to swap the two so `markup` comes first.
|
|
33
|
+
|
|
34
|
+
// Find the position of each rule's leading newline+spaces
|
|
35
|
+
const programMatch = src.match(/\n program: \$/);
|
|
36
|
+
const markupMatch = src.match(/\n markup: \$/);
|
|
37
|
+
|
|
38
|
+
if (!programMatch || !markupMatch) {
|
|
39
|
+
console.error('Could not locate program or markup rule in grammar.js');
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const programIdx = src.indexOf('\n program: $');
|
|
44
|
+
const markupIdx = src.indexOf('\n markup: $');
|
|
45
|
+
|
|
46
|
+
if (programIdx === markupIdx) {
|
|
47
|
+
console.error('program and markup are at the same position?');
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Determine which comes first in the file
|
|
52
|
+
const firstIdx = Math.min(programIdx, markupIdx);
|
|
53
|
+
const secondIdx = Math.max(programIdx, markupIdx);
|
|
54
|
+
|
|
55
|
+
// Extract each rule: from its start up to the start of the next rule (or end-of-rules).
|
|
56
|
+
// A top-level rule starts at "\n <ident>: $" and ends just before the next "\n <ident>: $".
|
|
57
|
+
// We need the SPANS of the two rules to swap them.
|
|
58
|
+
|
|
59
|
+
function findNextRuleStart(text, from) {
|
|
60
|
+
// Match "\n <word>: $ =>" — the arrow function syntax uniquely identifies
|
|
61
|
+
// rule definitions vs. object properties at the same indentation level.
|
|
62
|
+
const re = /\n \w+: \$ =>/g;
|
|
63
|
+
re.lastIndex = from + 1; // skip the current match
|
|
64
|
+
const m = re.exec(text);
|
|
65
|
+
return m ? m.index : text.length;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const firstEnd = findNextRuleStart(src, firstIdx);
|
|
69
|
+
const secondEnd = findNextRuleStart(src, secondIdx);
|
|
70
|
+
|
|
71
|
+
const firstRule = src.slice(firstIdx, firstEnd);
|
|
72
|
+
const secondRule = src.slice(secondIdx, secondEnd);
|
|
73
|
+
|
|
74
|
+
// Reconstruct: everything before firstIdx, then the rule that was second,
|
|
75
|
+
// then everything between the two rules, then the rule that was first,
|
|
76
|
+
// then everything after secondEnd.
|
|
77
|
+
const between = src.slice(firstEnd, secondIdx);
|
|
78
|
+
|
|
79
|
+
const swapped =
|
|
80
|
+
src.slice(0, firstIdx) +
|
|
81
|
+
secondRule +
|
|
82
|
+
between +
|
|
83
|
+
firstRule +
|
|
84
|
+
src.slice(secondEnd);
|
|
85
|
+
|
|
86
|
+
// 3. Add a header comment noting this is generated
|
|
87
|
+
const header = '// GENERATED by scripts/generate-markup-grammar.js — do not edit by hand.\n';
|
|
88
|
+
const output = header + swapped;
|
|
89
|
+
|
|
90
|
+
fs.mkdirSync(path.dirname(dstPath), { recursive: true });
|
|
91
|
+
fs.writeFileSync(dstPath, output, 'utf8');
|
|
92
|
+
|
|
93
|
+
console.log(`Wrote ${path.relative(process.cwd(), dstPath)}`);
|