Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: grammar and highlighting fixes and improvements #35

Merged
merged 1 commit into from
Feb 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
cmake_minimum_required(VERSION 3.13)

project(tree-sitter-kcl
VERSION "0.1.0"
DESCRIPTION "KCL Configration and policy language"
HOMEPAGE_URL "https://github.com/kcl-lang/tree-sitter-kcl"
LANGUAGES C)

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF)

set(TREE_SITTER_ABI_VERSION 15 CACHE STRING "Tree-sitter ABI version")
if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$")
unset(TREE_SITTER_ABI_VERSION CACHE)
message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer")
endif()

find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI")

add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json
--abi=${TREE_SITTER_ABI_VERSION}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating parser.c")

add_library(tree-sitter-kcl src/parser.c)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c)
target_sources(tree-sitter-kcl PRIVATE src/scanner.c)
endif()
target_include_directories(tree-sitter-kcl
PRIVATE src
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/bindings/c>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

target_compile_definitions(tree-sitter-kcl PRIVATE
$<$<BOOL:${TREE_SITTER_REUSE_ALLOCATOR}>:TREE_SITTER_REUSE_ALLOCATOR>
$<$<CONFIG:Debug>:TREE_SITTER_DEBUG>)

set_target_properties(tree-sitter-kcl
PROPERTIES
C_STANDARD 11
POSITION_INDEPENDENT_CODE ON
SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}"
DEFINE_SYMBOL "")

configure_file(bindings/c/tree-sitter-kcl.pc.in
"${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-kcl.pc" @ONLY)

include(GNUInstallDirs)

install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bindings/c/tree_sitter"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
FILES_MATCHING PATTERN "*.h")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-kcl.pc"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig")
install(TARGETS tree-sitter-kcl
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")

file(GLOB QUERIES queries/*.scm)
install(FILES ${QUERIES}
DESTINATION "${CMAKE_INSTALL_DATADIR}/tree-sitter/queries/kcl")

add_custom_target(ts-test "${TREE_SITTER_CLI}" test
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "tree-sitter test")
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ tree-sitter g

### Testing

Add test suites in [./test/corpus/](./test/corpus/) and run the test command
Add test suites in [./test/corpus/](./test/corpus/) or [./test/highlight/](./test/highlight/) and run the test command

```shell
tree-sitter t -u
Expand Down
36 changes: 17 additions & 19 deletions grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ module.exports = grammar({
$._dedent,
$.string_start,
$._string_content,
$.escape_interpolation,
'${',
$.string_end,

// Mark comments as external tokens so that the external scanner is always
Expand Down Expand Up @@ -296,7 +296,8 @@ module.exports = grammar({
field('name', $.parameter),
optional(seq(
'(',
field('base', $.identifier),
commaSep1(field('base', $.identifier)),
optional(','),
')'
)),
optional(seq(
Expand Down Expand Up @@ -475,17 +476,6 @@ module.exports = grammar({
field('body', $._suite),
),

rule_stmt: $ => seq(
'rule',
field('name', $.identifier),
optional(seq(
'for',
field('protocol', $.identifier),
)),
':',
field('body', $._suite),
),

check_stmt: $ => prec.left(seq(
'check',
':',
Expand Down Expand Up @@ -945,19 +935,28 @@ module.exports = grammar({

string: $ => seq(
$.string_start,
repeat($.string_content),
repeat(choice($.interpolation, $.string_content)),
$.string_end,
),

string_content: $ => prec.right(repeat1(
choice(
$.escape_interpolation,
$.escape_sequence,
$._not_escape_sequence,
$._string_content,
))),

escape_interpolation: _ => token.immediate(/\$\{[^}]*\}/),
interpolation: $ => seq(
'${',
field('expression', $._simple_expr),
optional(field("format_spec", $.format_spec)),
'}',
),

format_spec: $ => seq(
':',
token(prec(1, /[^}\n]+/)),
),

escape_sequence: _ => token.immediate(prec(1, seq(
'\\',
Expand All @@ -968,14 +967,13 @@ module.exports = grammar({
/\d{3}/,
/\r?\n/,
/['"abfrntv\\]/,
/N\{[^}]+\}/,
/N\{[^}]+}/,
/\$/,
),
))),

_not_escape_sequence: _ => token.immediate('\\'),

_string_content: _ => token.immediate(/[^\\{}]+/),

integer: $ => token(choice(
seq(
choice('0x', '0X'),
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@
"node-gyp-build": "^4.8.1"
},
"peerDependencies": {
"tree-sitter": "^0.21.1"
"tree-sitter": "^0.22.4"
},
"peerDependenciesMeta": {
"tree_sitter": {
"optional": true
}
},
"devDependencies": {
"tree-sitter-cli": "^0.23.0",
"prebuildify": "^6.0.1"
"prebuildify": "^6.0.1",
"tree-sitter-cli": "^0.24.7"
},
"tree-sitter": [
{
Expand Down
60 changes: 56 additions & 4 deletions queries/highlights.scm
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
(identifier) @variable

; Reset highlighting in string interpolations
(interpolation) @none

(import_stmt
(dotted_name
(identifier) @namespace))
Expand Down Expand Up @@ -44,10 +47,24 @@

(comment) @comment
(string) @string
(escape_sequence) @escape
(escape_sequence) @string.escape

(schema_stmt
body: (block
.
(string
(string_content) @string.documentation)))

(decorator
(identifier) @attribute)

(call_expr
function: (identifier) @function)

(call_expr
(identifier) @function)
function: (selector_expr
(select_suffix
(identifier) @function)))

[
(integer)
Expand All @@ -57,7 +74,7 @@
[
(true)
(false)
(none)
(none)
(undefined)
] @constant.builtin

Expand All @@ -82,6 +99,19 @@
"type"
] @keyword

[
"("
")"
"["
"]"
"{"
"}"
] @punctuation.bracket

(interpolation
"${" @punctuation.special
"}" @punctuation.special)

[
"+"
"-"
Expand All @@ -103,7 +133,6 @@
"=="
"!="
"@"
; "\\"
"and"
"or"
"not"
Expand All @@ -112,3 +141,26 @@
"="
":"
] @operator

; second argument is a regex in all regex functions with at least two arguments
(call_expr
function: (selector_expr
(identifier) @_regex)
arguments: (argument_list
(_)
.
(string
(string_content) @string.regexp))
(#eq? @_regex "regex"))

; first argument is a regex in 'regex.compile' function
(call_expr
.
function: (selector_expr
(identifier) @_regex
(select_suffix
(identifier) @_fn (#eq? @_fn "compile")))
arguments: (argument_list
(string
(string_content) @string.regexp))
(#eq? @_regex "regex"))
Loading
Loading