Merge commit '4b0e4a3891337514126ec72c7af394c0ff2cf48c'

pull/48/head
Wilfred Hughes 2021-10-02 12:17:06 +07:00
commit d355c3ceb0
16 changed files with 6765 additions and 3240 deletions

@ -1,2 +1,3 @@
node_modules
build
target

@ -1,6 +1,24 @@
# v1.2 (unreleased)
# v1.3 (unreleased)
No changes yet.
Don't error on quoted forms that look like function definitions (such
as `'(defun foo)`).
# v1.2
Added some basic syntax highlighting support ("queries" in tree-sitter
terms).
Function definitions are now handled separately from other
s-expressions. Added highlighting and tags table queries for function
definitions.
Macros are also handled separately to other s-expressions. They are
treated the same as functions for highlighting and tags tables.
Special forms are now parsed and highlighted separately from
s-expressions.
Added highlighting for `nil` and `t`.
# v1.1

@ -1,7 +1,7 @@
[package]
name = "tree-sitter-elisp"
description = "elisp grammar for the tree-sitter parsing library"
version = "0.0.1"
version = "1.3.0"
keywords = ["incremental", "parsing", "elisp"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-elisp"

@ -10,12 +10,12 @@ Syntax supported:
* Quoting and unquoting (`'`, `#'`, `` ` ``, `,`, `,@`)
* Some special read syntax (`$#`, `##`, `#("foo" 1 2 x)`)
* Bytecode literals (`#[1 2 3 4]`)
* Special forms (`let` etc)
* Comments
Currently unsupported:
* Autoload cookies
* Special forms (e.g. `let`, currently treated as symbols)
* Definitions (e.g. `defun`, `defvar`, `defmacro`)
## Limitations
@ -28,6 +28,12 @@ Currently tree-sitter-elisp treats everything as an s-expression. This
is accurate, but makes this package less useful for generating a
summary of file contents, or for syntax highlighting.
Emacs itself has more information that it can use. Emacs will
highlight macro calls based on which macros are defined in the current
instance. Some elisp packages also offer custom highlighting logic,
such as `dash-fontify-mode` in
[dash.el](https://github.com/magnars/dash.el).
## Developing
Check out the repo, then use `npm` to install dependencies.
@ -71,7 +77,7 @@ However, there is a growing ecosystem of tools built on top of
tree-sitter, such as GitHub. This project should allow them to support
emacs lisp too.
## References
## Related Projects
[tree-sitter-clojure](https://github.com/sogaiu/tree-sitter-clojure)
is another tree-sitter package for the lisp family. It's a useful

@ -1,4 +1,4 @@
const COMMENT = token(/;.*\n?/);
const COMMENT = token(/;.*/);
const STRING = token(
seq('"', repeat(choice(/[^"\\]/, seq("\\", /(.|\n)/))), '"')
@ -51,6 +51,9 @@ module.exports = grammar({
_sexp: ($) =>
choice(
$.special_form,
$.function_definition,
$.macro_definition,
$.list,
$.vector,
$.hash_table,
@ -62,6 +65,67 @@ module.exports = grammar({
$.unquote
),
special_form: ($) =>
seq(
"(",
choice(
"and",
"catch",
"cond",
"condition-case",
"defconst",
"defvar",
"function",
"if",
"interactive",
"lambda",
"let",
"let*",
"or",
"prog1",
"prog2",
"progn",
"quote",
"save-current-buffer",
"save-excursion",
"save-restriction",
"setq",
"setq-default",
"unwind-protect",
"while"
),
repeat($._sexp),
")"
),
function_definition: ($) =>
prec(
1,
seq(
"(",
choice("defun", "defsubst"),
field("name", $.symbol),
optional(field("parameters", $._sexp)),
optional(field("docstring", $.string)),
repeat($._sexp),
")"
)
),
macro_definition: ($) =>
prec(
1,
seq(
"(",
"defmacro",
field("name", $.symbol),
optional(field("parameters", $._sexp)),
optional(field("docstring", $.string)),
repeat($._sexp),
")"
)
),
_atom: ($) =>
choice(
$.float,
@ -93,7 +157,21 @@ module.exports = grammar({
),
string: ($) => STRING,
byte_compiled_file_name: ($) => BYTE_COMPILED_FILE_NAME,
symbol: ($) => choice(ESCAPED_READER_SYMBOL, SYMBOL, INTERNED_EMPTY_STRING),
symbol: ($) =>
choice(
// Match nil and t separately so we can highlight them.
"nil",
"t",
// We need to define these as separate tokens so we can handle
// e.g '(defun) as a sexp. Without these, we just try
// function_definition and produce a parse failure.
"defun",
"defsubst",
"defmacro",
ESCAPED_READER_SYMBOL,
SYMBOL,
INTERNED_EMPTY_STRING
),
quote: ($) => seq(choice("#'", "'", "`"), $._sexp),
unquote_splice: ($) => seq(",@", $._sexp),

@ -1,6 +1,6 @@
{
"name": "tree-sitter-elisp",
"version": "1.2.0",
"version": "1.3.0",
"description": "tree-sitter grammar for Emacs Lisp",
"main": "bindings/node",
"keywords": [
@ -9,6 +9,7 @@
],
"scripts": {
"generate": "tree-sitter generate",
"highlight": "tree-sitter highlight",
"parse": "tree-sitter parse",
"test": "tree-sitter test"
},

@ -0,0 +1,72 @@
;; Special forms
[
"and"
"catch"
"cond"
"condition-case"
"defconst"
"defvar"
"function"
"if"
"interactive"
"lambda"
"let"
"let*"
"or"
"prog1"
"prog2"
"progn"
"quote"
"save-current-buffer"
"save-excursion"
"save-restriction"
"setq"
"setq-default"
"unwind-protect"
"while"
] @keyword
;; Function definitions
[
"defun"
"defsubst"
] @keyword
(function_definition name: (symbol) @function)
(function_definition parameters: (list (symbol) @variable.parameter))
(function_definition docstring: (string) @comment)
;; Highlight macro definitions the same way as function definitions.
"defmacro" @keyword
(macro_definition name: (symbol) @function)
(macro_definition parameters: (list (symbol) @variable.parameter))
(macro_definition docstring: (string) @comment)
(comment) @comment
(integer) @number
(float) @number
(char) @number
(string) @string
[
"("
")"
"#["
"["
"]"
] @punctuation.bracket
[
"`"
"#'"
"'"
","
",@"
] @operator
;; Highlight nil and t as constants, unlike other symbols
[
"nil"
"t"
] @constant.builtin

@ -0,0 +1,5 @@
;; defun/defsubst
(function_definition name: (symbol) @name) @definition.function
;; Treat macros as function definitions for the sake of TAGS.
(macro_definition name: (symbol) @name) @definition.function

@ -11,6 +11,18 @@
"_sexp": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "special_form"
},
{
"type": "SYMBOL",
"name": "function_definition"
},
{
"type": "SYMBOL",
"name": "macro_definition"
},
{
"type": "SYMBOL",
"name": "list"
@ -49,6 +61,272 @@
}
]
},
"special_form": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "and"
},
{
"type": "STRING",
"value": "catch"
},
{
"type": "STRING",
"value": "cond"
},
{
"type": "STRING",
"value": "condition-case"
},
{
"type": "STRING",
"value": "defconst"
},
{
"type": "STRING",
"value": "defvar"
},
{
"type": "STRING",
"value": "function"
},
{
"type": "STRING",
"value": "if"
},
{
"type": "STRING",
"value": "interactive"
},
{
"type": "STRING",
"value": "lambda"
},
{
"type": "STRING",
"value": "let"
},
{
"type": "STRING",
"value": "let*"
},
{
"type": "STRING",
"value": "or"
},
{
"type": "STRING",
"value": "prog1"
},
{
"type": "STRING",
"value": "prog2"
},
{
"type": "STRING",
"value": "progn"
},
{
"type": "STRING",
"value": "quote"
},
{
"type": "STRING",
"value": "save-current-buffer"
},
{
"type": "STRING",
"value": "save-excursion"
},
{
"type": "STRING",
"value": "save-restriction"
},
{
"type": "STRING",
"value": "setq"
},
{
"type": "STRING",
"value": "setq-default"
},
{
"type": "STRING",
"value": "unwind-protect"
},
{
"type": "STRING",
"value": "while"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "_sexp"
}
},
{
"type": "STRING",
"value": ")"
}
]
},
"function_definition": {
"type": "PREC",
"value": 1,
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "defun"
},
{
"type": "STRING",
"value": "defsubst"
}
]
},
{
"type": "FIELD",
"name": "name",
"content": {
"type": "SYMBOL",
"name": "symbol"
}
},
{
"type": "CHOICE",
"members": [
{
"type": "FIELD",
"name": "parameters",
"content": {
"type": "SYMBOL",
"name": "_sexp"
}
},
{
"type": "BLANK"
}
]
},
{
"type": "CHOICE",
"members": [
{
"type": "FIELD",
"name": "docstring",
"content": {
"type": "SYMBOL",
"name": "string"
}
},
{
"type": "BLANK"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "_sexp"
}
},
{
"type": "STRING",
"value": ")"
}
]
}
},
"macro_definition": {
"type": "PREC",
"value": 1,
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "STRING",
"value": "defmacro"
},
{
"type": "FIELD",
"name": "name",
"content": {
"type": "SYMBOL",
"name": "symbol"
}
},
{
"type": "CHOICE",
"members": [
{
"type": "FIELD",
"name": "parameters",
"content": {
"type": "SYMBOL",
"name": "_sexp"
}
},
{
"type": "BLANK"
}
]
},
{
"type": "CHOICE",
"members": [
{
"type": "FIELD",
"name": "docstring",
"content": {
"type": "SYMBOL",
"name": "string"
}
},
{
"type": "BLANK"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "_sexp"
}
},
{
"type": "STRING",
"value": ")"
}
]
}
},
"_atom": {
"type": "CHOICE",
"members": [
@ -249,6 +527,26 @@
"symbol": {
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "nil"
},
{
"type": "STRING",
"value": "t"
},
{
"type": "STRING",
"value": "defun"
},
{
"type": "STRING",
"value": "defsubst"
},
{
"type": "STRING",
"value": "defmacro"
},
{
"type": "TOKEN",
"content": {
@ -444,7 +742,7 @@
"type": "TOKEN",
"content": {
"type": "PATTERN",
"value": ";.*\\n?"
"value": ";.*"
}
}
},

@ -23,6 +23,10 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -35,10 +39,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -76,6 +88,180 @@
"named": true,
"fields": {}
},
{
"type": "function_definition",
"named": true,
"fields": {
"docstring": {
"multiple": false,
"required": false,
"types": [
{
"type": "string",
"named": true
}
]
},
"name": {
"multiple": false,
"required": true,
"types": [
{
"type": "symbol",
"named": true
}
]
},
"parameters": {
"multiple": false,
"required": false,
"types": [
{
"type": "byte_compiled_file_name",
"named": true
},
{
"type": "bytecode",
"named": true
},
{
"type": "char",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_text_properties",
"named": true
},
{
"type": "symbol",
"named": true
},
{
"type": "unquote",
"named": true
},
{
"type": "unquote_splice",
"named": true
},
{
"type": "vector",
"named": true
}
]
}
},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "byte_compiled_file_name",
"named": true
},
{
"type": "bytecode",
"named": true
},
{
"type": "char",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_text_properties",
"named": true
},
{
"type": "symbol",
"named": true
},
{
"type": "unquote",
"named": true
},
{
"type": "unquote_splice",
"named": true
},
{
"type": "vector",
"named": true
}
]
}
},
{
"type": "hash_table",
"named": true,
@ -100,6 +286,10 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -112,10 +302,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -172,6 +370,184 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_text_properties",
"named": true
},
{
"type": "symbol",
"named": true
},
{
"type": "unquote",
"named": true
},
{
"type": "unquote_splice",
"named": true
},
{
"type": "vector",
"named": true
}
]
}
},
{
"type": "macro_definition",
"named": true,
"fields": {
"docstring": {
"multiple": false,
"required": false,
"types": [
{
"type": "string",
"named": true
}
]
},
"name": {
"multiple": false,
"required": true,
"types": [
{
"type": "symbol",
"named": true
}
]
},
"parameters": {
"multiple": false,
"required": false,
"types": [
{
"type": "byte_compiled_file_name",
"named": true
},
{
"type": "bytecode",
"named": true
},
{
"type": "char",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_text_properties",
"named": true
},
{
"type": "symbol",
"named": true
},
{
"type": "unquote",
"named": true
},
{
"type": "unquote_splice",
"named": true
},
{
"type": "vector",
"named": true
}
]
}
},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "byte_compiled_file_name",
"named": true
},
{
"type": "bytecode",
"named": true
},
{
"type": "char",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -184,10 +560,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -239,6 +623,10 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -251,10 +639,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -306,6 +702,89 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_text_properties",
"named": true
},
{
"type": "symbol",
"named": true
},
{
"type": "unquote",
"named": true
},
{
"type": "unquote_splice",
"named": true
},
{
"type": "vector",
"named": true
}
]
}
},
{
"type": "special_form",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "byte_compiled_file_name",
"named": true
},
{
"type": "bytecode",
"named": true
},
{
"type": "char",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -318,10 +797,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -373,6 +860,10 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -385,10 +876,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -445,6 +944,10 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -457,10 +960,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -512,6 +1023,10 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -524,10 +1039,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -579,6 +1102,10 @@
"type": "float",
"named": true
},
{
"type": "function_definition",
"named": true
},
{
"type": "hash_table",
"named": true
@ -591,10 +1118,18 @@
"type": "list",
"named": true
},
{
"type": "macro_definition",
"named": true
},
{
"type": "quote",
"named": true
},
{
"type": "special_form",
"named": true
},
{
"type": "string",
"named": true
@ -674,16 +1209,132 @@
"type": "`",
"named": false
},
{
"type": "and",
"named": false
},
{
"type": "byte_compiled_file_name",
"named": true
},
{
"type": "catch",
"named": false
},
{
"type": "comment",
"named": true
},
{
"type": "cond",
"named": false
},
{
"type": "condition-case",
"named": false
},
{
"type": "defconst",
"named": false
},
{
"type": "defmacro",
"named": false
},
{
"type": "defsubst",
"named": false
},
{
"type": "defun",
"named": false
},
{
"type": "defvar",
"named": false
},
{
"type": "function",
"named": false
},
{
"type": "if",
"named": false
},
{
"type": "interactive",
"named": false
},
{
"type": "lambda",
"named": false
},
{
"type": "let",
"named": false
},
{
"type": "let*",
"named": false
},
{
"type": "nil",
"named": false
},
{
"type": "or",
"named": false
},
{
"type": "prog1",
"named": false
},
{
"type": "prog2",
"named": false
},
{
"type": "progn",
"named": false
},
{
"type": "quote",
"named": false
},
{
"type": "save-current-buffer",
"named": false
},
{
"type": "save-excursion",
"named": false
},
{
"type": "save-restriction",
"named": false
},
{
"type": "setq",
"named": false
},
{
"type": "setq-default",
"named": false
},
{
"type": "string",
"named": true
},
{
"type": "t",
"named": false
},
{
"type": "unwind-protect",
"named": false
},
{
"type": "while",
"named": false
}
]

File diff suppressed because it is too large Load Diff

@ -0,0 +1,54 @@
================================================================================
Function definition
================================================================================
(defun foo (x &optional y)
"stuff"
x)
(defsubst bar () nil)
(defun no-args nil 123)
`(defun ,x () ,@body)
'(defun 1)
'(defun)
'(defun foo)
--------------------------------------------------------------------------------
(source_file
(function_definition
(symbol)
(list
(symbol)
(symbol)
(symbol))
(string)
(symbol))
(function_definition
(symbol)
(list)
(symbol))
(function_definition
(symbol)
(symbol)
(integer))
(quote
(list
(symbol)
(unquote
(symbol))
(list)
(unquote_splice
(symbol))))
(quote
(list
(symbol)
(integer)))
(quote
(list
(symbol)))
(quote
(function_definition
(symbol))))

@ -0,0 +1,19 @@
================================================================================
Macro definition
================================================================================
(defmacro foo (x &optional y)
"stuff"
x)
--------------------------------------------------------------------------------
(source_file
(macro_definition
(symbol)
(list
(symbol)
(symbol)
(symbol))
(string)
(symbol)))

@ -0,0 +1,17 @@
================================================================================
Special forms
================================================================================
(if x 1 2)
(while x y)
--------------------------------------------------------------------------------
(source_file
(special_form
(symbol)
(integer)
(integer))
(special_form
(symbol)
(symbol)))

@ -25,6 +25,7 @@ _
foo-★
1+
\1
nil
--------------------------------------------------------------------------------
@ -51,4 +52,5 @@ foo-★
(symbol)
(symbol)
(symbol)
(symbol)
(symbol))

@ -0,0 +1,7 @@
(defun foo (x)
;; ^ keyword
;; ^ function
;; ^ variable.parameter
"stuff"
;; ^ comment
x)