Compare commits

...

14 commits

Author SHA1 Message Date
Bruno BELANYI cc84a43055 Release 0.2.0
All checks were successful
ci/woodpecker/push/check Pipeline was successful
2024-04-13 17:11:41 +01:00
Bruno BELANYI 0ca28eb2e9 Add indentation tests 2024-04-13 17:07:43 +01:00
Bruno BELANYI f8f328fa17 Add indentation queries 2024-04-13 17:07:37 +01:00
Bruno BELANYI 9ee889d7ad Make 'punctuation' highlight test more exhaustive 2024-04-13 17:07:29 +01:00
Bruno BELANYI 9889191245 Fix indentation in test files 2024-04-13 17:07:23 +01:00
Bruno BELANYI 6bd28f2b6b Add NeoVim test runner
For the queries that can't be tested with `tree-sitter` itself.
2024-04-13 17:07:16 +01:00
Bruno BELANYI 9e9fde6c77 Add 'comment' injection 2024-04-13 16:01:26 +01:00
Bruno BELANYI 615bb266cc Add folding query 2024-04-13 16:01:26 +01:00
Bruno BELANYI 9457caf3a2 Fix typo in a comment 2024-04-11 18:44:13 +01:00
Bruno BELANYI adec624d74 Tweak comment parsing
This is taken verbatim from tree-sitter-c [1], just in case :-).

[1]: https://github.com/tree-sitter/tree-sitter-c
2024-04-11 18:38:14 +01:00
Bruno BELANYI b62fc19da9 Make comments a single node in the grammar
This looks to be a *strong* idiom in tree-sitter parsers.
2024-04-11 18:36:20 +01:00
Bruno BELANYI aa8472e73f Add test for literals 2024-04-11 18:08:40 +01:00
Bruno BELANYI 508ea00920 Add missing 'PHONY' target 2024-04-11 18:01:32 +01:00
Bruno BELANYI dc1d139d35 Fix 'PHONY' target name 2024-04-11 18:00:12 +01:00
23 changed files with 1433 additions and 1190 deletions

View file

@ -1,7 +1,7 @@
[package]
name = "tree-sitter-bp"
description = "Blueprint grammar for the tree-sitter parsing library"
version = "0.1.0"
version = "0.2.0"
keywords = ["incremental", "parsing", "android", "blueprint"]
categories = ["parsing", "text-editors"]
repository = "https://git.belanyi.fr/ambroisie/tree-sitter-bp"

View file

@ -1,15 +1,18 @@
.PHONE: all
.PHONY: all
all:
tree-sitter generate
.PHONE: test
.PHONY: test
test: all
tree-sitter test --apply-all-captures
nvim-test-runner
.PHONE: update-tests
.PHONY: update-tests
update-tests: all
tree-sitter test -u --apply-all-captures
nvim-test-runner
.PHONY: playground
playground:
nix shell pkgs#emscripten --command tree-sitter build-wasm
tree-sitter playground

View file

@ -37,6 +37,7 @@
}:
let
inherit (flake-utils.lib) eachDefaultSystem;
inherit (nixpkgs) lib;
in
eachDefaultSystem
(system:
@ -46,6 +47,25 @@
overlays = [ self.overlays.default ];
};
nvim-test-runner = pkgs.writeShellApplication {
name = "nvim-test-runner";
runtimeInputs = with pkgs; [
highlight-assertions
neovim
];
text = ''
export NVIM_PLENARY='${pkgs.vimPlugins.plenary-nvim}'
export NVIM_TREESITTER='${pkgs.vimPlugins.nvim-treesitter}'
export NVIM_TREESITTER_TEXTOBJECTS='${pkgs.vimPlugins.nvim-treesitter-textobjects}'
export NVIM_TREESITTER_PARSER='${pkgs.vimPlugins.nvim-treesitter.grammarToPlugin self.packages.${system}.tree-sitter-bp}'
nvim --headless --noplugin -u ${scripts/minimal_init.lua} \
-c "PlenaryBustedDirectory test/ { minimal_init = '${./scripts/minimal_init.lua}' }"
'';
};
bump-version = pkgs.writeShellScriptBin "bump-version" ''
set -eu
@ -90,6 +110,13 @@
enable = true;
};
nvim-test-runner = {
enable = true;
name = "nvim tests";
entry = "${lib.getExe nvim-test-runner}";
pass_filenames = false;
};
tree-sitter = {
enable = true;
name = "tree-sitter tests";
@ -112,6 +139,7 @@
nativeBuildInputs = with pkgs; [
bump-version
nodejs
nvim-test-runner
# FIXME: waiting on #301336
# (tree-sitter.override { webUISupport = true; })
tree-sitter

View file

@ -11,8 +11,7 @@ module.exports = grammar({
extras: ($) => [
/\s+/,
$.line_comment,
$.block_comment,
$.comment,
],
rules: {
@ -23,9 +22,10 @@ module.exports = grammar({
$.module,
),
line_comment: (_) => seq("//", /[^\n]*/),
block_comment: (_) => seq("/*", /[^*]*\*+([^/*][^*]*\*+)*/, '/'),
comment: (_) => choice(
seq("//", /(\\+(.|\r?\n)|[^\\\n])*/),
seq("/*", /[^*]*\*+([^/*][^*]*\*+)*/, "/"),
),
// Definitions {{{

View file

@ -1,6 +1,6 @@
{
"name": "tree-sitter-bp",
"version": "0.1.0",
"version": "0.2.0",
"description": "Blueprint grammar for tree-sitter",
"main": "bindings/node",
"keywords": [

8
queries/folds.scm Normal file
View file

@ -0,0 +1,8 @@
[
(list_expression)
(map_expression)
(module)
(select_expression)
] @fold
; vim: sw=2 foldmethod=marker

View file

@ -1,7 +1,4 @@
[
(line_comment)
(block_comment)
] @comment
(comment) @comment
; Operators {{{
(operator) @operator

27
queries/indents.scm Normal file
View file

@ -0,0 +1,27 @@
; Expressions {{{
(list_expression) @indent.begin
(list_expression
"]" @indent.branch)
(map_expression) @indent.begin
(map_expression
"}" @indent.branch)
(select_expression) @indent.begin
(select_expression
")" @indent.branch)
(select_cases) @indent.begin
(select_cases
"}" @indent.branch)
; }}}
; Declarations {{{
(module) @indent.begin
(module
")" @indent.branch)
(module
"}" @indent.branch)
; }}}
; vim: sw=2 foldmethod=marker

4
queries/injections.scm Normal file
View file

@ -0,0 +1,4 @@
((comment) @injection.content
(#set! injection.language "comment"))
; vim: sw=2 foldmethod=marker

View file

@ -0,0 +1 @@
../../../queries

40
scripts/minimal_init.lua Normal file
View file

@ -0,0 +1,40 @@
vim.opt.runtimepath:append(vim.env.NVIM_PLENARY)
vim.opt.runtimepath:append(vim.env.NVIM_TREESITTER)
vim.opt.runtimepath:append(vim.env.NVIM_TREESITTER_TEXTOBJECTS)
vim.opt.runtimepath:append(vim.env.NVIM_TREESITTER_PARSER)
vim.cmd.runtime({ "plugin/plenary.vim", bang = true })
vim.cmd.runtime({ "plugin/nvim-treesitter.lua", bang = true })
vim.cmd.runtime({ "plugin/nvim-treesitter-textobjects.lua", bang = true })
local Path = require("plenary.path")
local project_root = Path:new(".") -- FIXME: relies on current working directory
vim.filetype.add({
extension = {
bp = "bp",
},
})
vim.o.swapfile = false
vim.bo.swapfile = false
local parser_config = require("nvim-treesitter.parsers").get_parser_configs()
parser_config.bp = {
install_info = {
url = project_root.filename,
files = {"src/parser.c"},
},
}
require("nvim-treesitter.configs").setup({
indent = { enable = true },
highlight = { enable = true },
})
-- We need a hierarchy of `queries/bp/*.scm` in the runtimepath, otherwise
-- `nvim-treesitter` doesn't enable some of its features (e.g: folding).
-- The dummy plugin has a symlink following that format for our queries.
local dummy_plugin_path = project_root / "scripts" / "dummy_plugin"
vim.opt.runtimepath:append(dummy_plugin_path.filename)

57
src/grammar.json generated
View file

@ -21,33 +21,38 @@
}
]
},
"line_comment": {
"type": "SEQ",
"comment": {
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "//"
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "//"
},
{
"type": "PATTERN",
"value": "(\\\\+(.|\\r?\\n)|[^\\\\\\n])*"
}
]
},
{
"type": "PATTERN",
"value": "[^\\n]*"
}
]
},
"block_comment": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "/*"
},
{
"type": "PATTERN",
"value": "[^*]*\\*+([^/*][^*]*\\*+)*"
},
{
"type": "STRING",
"value": "/"
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "/*"
},
{
"type": "PATTERN",
"value": "[^*]*\\*+([^/*][^*]*\\*+)*"
},
{
"type": "STRING",
"value": "/"
}
]
}
]
},
@ -956,11 +961,7 @@
},
{
"type": "SYMBOL",
"name": "line_comment"
},
{
"type": "SYMBOL",
"name": "block_comment"
"name": "comment"
}
],
"conflicts": [],

9
src/node-types.json generated
View file

@ -168,12 +168,12 @@
}
},
{
"type": "block_comment",
"type": "boolean_literal",
"named": true,
"fields": {}
},
{
"type": "boolean_literal",
"type": "comment",
"named": true,
"fields": {}
},
@ -259,11 +259,6 @@
]
}
},
{
"type": "line_comment",
"named": true,
"fields": {}
},
{
"type": "list_expression",
"named": true,

2124
src/parser.c generated

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ Empty comment
--------------------------------------------------------------------------------
(source_file
(line_comment))
(comment))
================================================================================
Single comment
@ -18,7 +18,7 @@ Single comment
--------------------------------------------------------------------------------
(source_file
(line_comment))
(comment))
================================================================================
Multiple comments
@ -30,8 +30,8 @@ Multiple comments
--------------------------------------------------------------------------------
(source_file
(line_comment)
(line_comment))
(comment)
(comment))
================================================================================
Empty block comment
@ -42,7 +42,7 @@ Empty block comment
--------------------------------------------------------------------------------
(source_file
(block_comment))
(comment))
================================================================================
Whitespace block comment
@ -53,7 +53,7 @@ Whitespace block comment
--------------------------------------------------------------------------------
(source_file
(block_comment))
(comment))
================================================================================
Block comment
@ -64,7 +64,7 @@ Block comment
--------------------------------------------------------------------------------
(source_file
(block_comment))
(comment))
================================================================================
Block comment with slashes
@ -75,7 +75,7 @@ Block comment with slashes
--------------------------------------------------------------------------------
(source_file
(block_comment))
(comment))
================================================================================
Block comment with asterisks
@ -86,7 +86,7 @@ Block comment with asterisks
--------------------------------------------------------------------------------
(source_file
(block_comment))
(comment))
================================================================================
Block comment (multiline)
@ -103,7 +103,7 @@ Block comment (multiline)
--------------------------------------------------------------------------------
(source_file
(block_comment))
(comment))
================================================================================
Block comment is not recursive
@ -114,7 +114,7 @@ Block comment is not recursive
--------------------------------------------------------------------------------
(source_file
(block_comment))
(comment))
================================================================================
Unterminated comment

134
test/corpus/literals.txt Normal file
View file

@ -0,0 +1,134 @@
================================================================================
Booelan literal
================================================================================
foo = true
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(boolean_literal)))
================================================================================
Integer literal
================================================================================
foo = 42
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(integer_literal)))
================================================================================
String literal
================================================================================
foo = "Hello World!"
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(interpreted_string_literal)))
================================================================================
String literal special character escapes
================================================================================
foo = "Hello\nWorld!"
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(interpreted_string_literal
(escape_sequence))))
================================================================================
String literal octal
================================================================================
foo = "Hello World\041"
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(interpreted_string_literal
(escape_sequence))))
================================================================================
String literal hex
================================================================================
foo = "Hello World\x21"
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(interpreted_string_literal
(escape_sequence))))
================================================================================
String literal character escapes
================================================================================
foo = "Hello\\\"World\""
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(interpreted_string_literal
(escape_sequence)
(escape_sequence)
(escape_sequence))))
================================================================================
Unterminated string literal
================================================================================
foo = "
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(interpreted_string_literal
(MISSING """))))
================================================================================
String literal unterminated escape
================================================================================
foo = "\"
--------------------------------------------------------------------------------
(source_file
(assignment
(identifier)
(operator)
(interpreted_string_literal
(escape_sequence)
(MISSING """))))

View file

@ -1,10 +1,9 @@
/* This is comment */
/* <- comment
^ comment
^ comment
*/
/* This is a comment */
// <- comment
// ^ comment
// ^ comment
// And another comment
/* <- comment
^ comment
^ comment
*/
// <- comment
// ^ comment
// ^ comment

View file

@ -4,16 +4,16 @@ foo {}
foo ()
// <- function.call
foo {
// <- function.call
some_module {
// ^ function.call
field: 12,
// <- variable.parameter
another_field: 27,
// <- variable.parameter
}
foo (
// <- function.call
some_module (
// ^ function.call
field = 42,
// <- variable.parameter
done = false,

View file

@ -1,6 +1,6 @@
foo {
field: {
// <- variable.parameter
some_field: {
// ^ variable.parameter
key: 42,
// <- property
},

View file

@ -3,13 +3,24 @@ foo (
bar = [
//^ punctuation.bracket
{
// <- punctuation.bracket
key: "value",
// ^ punctuation.delimiter
// ^ punctuation.delimiter
another: {},
// ^ punctuation.bracket
// ^ punctuation.bracket
},
// <- punctuation.bracket
]
],
// <- punctuation.bracket
baz = {
//^ punctuation.bracket
key: [],
// ^ punctuation.delimiter
// ^ punctuation.bracket
// ^ punctuation.bracket
// ^ punctuation.delimiter
},
// <- punctuation.bracket
)
// <- punctuation.bracket

View file

@ -0,0 +1,22 @@
foo = 1 + 2
foo = [
1,
2,
3,
]
foo = {
foo: [
"bar",
],
},
foo = {
foo: [
"bar",
{
key: "value",
},
],
},

28
test/indent/select.bp Normal file
View file

@ -0,0 +1,28 @@
foo = select(variant("VARIANT"), {
"x86": "my_x86",
"x86_64": [
"x86",
"x64",
],
"arm": {
some: "aarch",
value: "aarch64",
},
default: 0,
})
foo = select(
variant("VARIANT"),
{
"x86": "my_x86",
"x86_64": [
"x86",
"x64",
],
"arm": {
some: "aarch",
value: "aarch64",
},
default: 0,
}
)

47
test/indent_spec.lua Normal file
View file

@ -0,0 +1,47 @@
package.path = package.path .. ";" .. vim.env.NVIM_TREESITTER .. "/?.lua"
local Runner = require("tests.indent.common").Runner
-- FIXME: path to root
local runner = Runner:new(it, ".", {
tabstop = 4,
shiftwidth = 4,
softtabstop = 0,
expandtab = true,
})
describe("indent Blueprint:", function()
describe("whole file:", function()
runner:whole_file("test/highlight/", {
expected_failures = {
-- NOTE: none for now
},
})
runner:whole_file("test/indent/", {
expected_failures = {
-- NOTE: none for now
},
})
end)
describe("new line:", function()
runner:new_line("test/indent/expressions.bp", { on_line = 2, text = "foo = 42", indent = 0 }, "variable declaration")
runner:new_line("test/indent/expressions.bp", { on_line = 4, text = "0,", indent = 4 }, "list element")
runner:new_line("test/indent/expressions.bp", { on_line = 6, text = "]", indent = 0 }, "list closing delimiter")
runner:new_line("test/indent/expressions.bp", { on_line = 9, text = "key: 42", indent = 4 }, "map property")
runner:new_line("test/indent/expressions.bp", { on_line = 12, text = "key: 42", indent = 4 }, "map property, trailing")
runner:new_line("test/indent/expressions.bp", { on_line = 9, text = "}", indent = 0 }, "map closing delimiter")
runner:new_line("test/indent/expressions.bp", { on_line = 11, text = "]", indent = 4 }, "nested list closing delimiter")
runner:new_line("test/indent/expressions.bp", { on_line = 18, text = "key: 42", indent = 12 }, "nested map property")
runner:new_line("test/indent/expressions.bp", { on_line = 19, text = "key: 42", indent = 12 }, "nested map property, trailing")
runner:new_line("test/indent/select.bp", { on_line = 1, text = '"case": "value"', indent = 4 }, "select case")
runner:new_line("test/indent/select.bp", { on_line = 1, text = 'default: "value"', indent = 4 }, "default case")
runner:new_line("test/indent/select.bp", { on_line = 11, text = '"case": "value"', indent = 4 }, "select case, trailing")
runner:new_line("test/indent/select.bp", { on_line = 11, text = 'default: "value"', indent = 4 }, "default case, trailing")
runner:new_line("test/indent/select.bp", { on_line = 16, text = '"case": "value"', indent = 8 }, "select case, alternate formatting")
runner:new_line("test/indent/select.bp", { on_line = 16, text = 'default: "value"', indent = 8 }, "default case, alternate formatting")
runner:new_line("test/indent/select.bp", { on_line = 26, text = '"case": "value"', indent = 8 }, "select case, trailing, alternate formattingg")
runner:new_line("test/indent/select.bp", { on_line = 26, text = 'default: "value"', indent = 8 }, "default case, trailing, alternate formattingn")
end)
end)