Merge commit '7aa24fe8616072fc1a659f72d5b60bd8c01fb5cc'

syntax_id
Wilfred Hughes 2023-08-08 23:00:30 +07:00
commit db8797d6c2
19 changed files with 35463 additions and 25932 deletions

@ -1,5 +1,9 @@
## 0.50 (unreleased)
### Parsing
Updated Erlang parser.
### Display
Tweaked the colours on the file header, to make metadata less

@ -1,3 +1,8 @@
1.0.0 (September 26, 2022)
0.1.0 (June 16, 2023)
* Add support for OTP 26 constructs
* maybe
* map comprehension
0.0.1 (September 26, 2022)
* Initial Release

@ -5,7 +5,7 @@ edition = "2018"
keywords = ["incremental", "parsing", "erlang"]
license = "MIT"
name = "tree-sitter-erlang"
version = "0.0.1"
version = "0.1.0"
build = "bindings/rust/build.rs"
include = [
@ -19,7 +19,7 @@ include = [
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = "0.20.9"
tree-sitter = "0.20.10"
[build-dependencies]
cc = "1.0.73"
cc = "1.0.79"

@ -10,6 +10,12 @@ fmt:
test: gen
$(TREE_SITTER) test
.PHONY: test-highlight
test-highlight:
# Note: test-highlight uses a filter for non-existent corpus
# tests, so only highlights run. And does not gen.
$(TREE_SITTER) test-highlight
.PHONY: update
update: gen
$(TREE_SITTER) test -- --update

@ -1,3 +1,19 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
module.exports = require("../../build/Release/tree_sitter_erlang_binding");
} catch (error1) {

@ -1,3 +1,19 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Note: If this file does not exist, it is generated by `tree-sitter generate`.
fn main() {

@ -1,3 +1,19 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Note: If this file does not exist, it is generated by `tree-sitter generate`.
//! This crate provides erlang language support for the [tree-sitter][] parsing library.

@ -1,5 +1,5 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -37,6 +37,8 @@ const PREC = {
REMOTE: 1,
BIT_EXPR: 2,
COND_MATCH: 81, // `?=` in maybe expr. Should has lowest priority https://www.erlang.org/eeps/eep-0049#operator-priority
// In macro def, prefer expressions, if type and expr would parse
DYN_CR_CLAUSES: 1,
DYN_FUNCTION_CLAUSES: 2,
@ -101,6 +103,10 @@ module.exports = grammar({
$._expr,
$._expr_max,
$._catch_pat,
$._deprecated_details,
$._deprecated_fun_arity,
$._desc,
$._string_like
],
@ -140,6 +146,7 @@ module.exports = grammar({
$.optional_callbacks_attribute,
$.compile_options_attribute,
$.file_attribute,
$.deprecated_attribute,
$.record_decl,
$.type_alias,
$.opaque,
@ -263,6 +270,58 @@ module.exports = grammar({
field("original_line", $.integer),
')', '.'),
deprecated_attribute: $ => seq(
'-',
atom_const('deprecated'),
'(',
field("attr", $._deprecated_details),
')',
'.'
),
_deprecated_details: $ => choice(
$.deprecated_module,
$.deprecated_fa,
$.deprecated_fas,
),
deprecated_module: $ => field("module", $.atom),
deprecated_fas: $ => seq(
'[',
sepBy1(',', field("fa", $.deprecated_fa)),
']',
),
deprecated_fa: $ => seq(
'{',
field("fun", $.atom),
',',
field("arity", $._deprecated_fun_arity),
field("desc", optional($.deprecation_desc)),
'}',
),
deprecation_desc: $ => seq(',', field("desc", $._desc)),
_desc: $ => choice(
field("atom", $.atom),
field("comment", $.multi_string),
),
multi_string: $ => prec.right(field("elems", repeat1($._string_like))),
_string_like: $ => choice(
$.string,
$._macro_body_expr
),
_deprecated_fun_arity: $ => choice(
$.integer,
$.deprecated_wildcard,
),
deprecated_wildcard: $ => "'_'",
type_alias: $ => seq('-', atom_const('type'), $._type_def, '.'),
opaque: $ => seq('-', atom_const('opaque'), $._type_def, '.'),
@ -367,6 +426,7 @@ module.exports = grammar({
$._record_expr,
$.remote,
$._expr_max,
$.cond_match_expr,
),
dotdotdot: $ => '...',
@ -379,6 +439,12 @@ module.exports = grammar({
'=',
field("rhs", prec.right($._expr)),
)),
cond_match_expr: $ =>
prec.right(PREC.COND_MATCH, seq(
field("lhs", $._expr),
'?=',
field("rhs", prec.right($._expr)),
)),
binary_op_expr: $ => choice(
prec.right(PREC.BANG, seq(
field("lhs", $._expr),
@ -435,6 +501,7 @@ module.exports = grammar({
$.binary,
$.list_comprehension,
$.binary_comprehension,
$.map_comprehension,
$.tuple,
$.paren_expr,
$.block_expr,
@ -443,6 +510,7 @@ module.exports = grammar({
$.receive_expr,
$._fun_expr,
$.try_expr,
$.maybe_expr,
),
remote: $ => prec.right(PREC.REMOTE, seq(field("module", $.remote_module), field("fun", $._expr_max))),
@ -512,6 +580,13 @@ module.exports = grammar({
field("lc_exprs", $.lc_exprs),
'>>'
),
map_comprehension: $ => seq(
'#',
'{',
field("expr", $.map_field),
field("lc_exprs", $.lc_exprs),
'}',
),
lc_exprs: $ => seq('||', sepBy1(',', field("exprs", $._lc_expr))),
@ -519,6 +594,7 @@ module.exports = grammar({
$._expr,
$.generator,
$.b_generator,
$.map_generator,
),
generator: $ => seq(
@ -531,6 +607,11 @@ module.exports = grammar({
'<=',
field("rhs", $._expr),
),
map_generator: $ => seq(
field("lhs", $.map_field),
'<-',
field("rhs", $._expr),
),
tuple: $ => seq(
'{',
@ -793,6 +874,13 @@ module.exports = grammar({
)),
),
maybe_expr: $ => choice(
seq('maybe', sepBy1(',', field("exprs", $._expr)), 'end'),
seq('maybe', sepBy1(',', field("exprs", $._expr)), $._maybe_else_clause),
),
_maybe_else_clause: $ => seq('else', optional($._cr_clauses), 'end'),
_macro_def_replacement: $ => choice(
prec.dynamic(PREC.DYN_EXPR, $._expr),
prec.dynamic(PREC.DYN_FUNCTION_CLAUSES, $.replacement_function_clauses),

@ -1,7 +1,7 @@
{
"name": "tree-sitter-erlang",
"version": "0.0.0",
"lockfileVersion": 2,
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
@ -11,18 +11,18 @@
"dependencies": {
"nan": "^2.14.1",
"prettier": "^2.2.1",
"tree-sitter-cli": "^0.20.7"
"tree-sitter-cli": "^0.20.8"
}
},
"node_modules/nan": {
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
"integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA=="
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ=="
},
"node_modules/prettier": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"bin": {
"prettier": "bin-prettier.js"
},
@ -34,30 +34,13 @@
}
},
"node_modules/tree-sitter-cli": {
"version": "0.20.7",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.7.tgz",
"integrity": "sha512-MHABT8oCPr4D0fatsPo6ATQ9H4h9vHpPRjlxkxJs80tpfAEKGn6A1zU3eqfCKBcgmfZDe9CiL3rKOGMzYHwA3w==",
"version": "0.20.8",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.8.tgz",
"integrity": "sha512-XjTcS3wdTy/2cc/ptMLc/WRyOLECRYcMTrSWyhZnj1oGSOWbHLTklgsgRICU3cPfb0vy+oZCC33M43u6R1HSCA==",
"hasInstallScript": true,
"bin": {
"tree-sitter": "cli.js"
}
}
},
"dependencies": {
"nan": {
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
"integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA=="
},
"prettier": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g=="
},
"tree-sitter-cli": {
"version": "0.20.7",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.7.tgz",
"integrity": "sha512-MHABT8oCPr4D0fatsPo6ATQ9H4h9vHpPRjlxkxJs80tpfAEKGn6A1zU3eqfCKBcgmfZDe9CiL3rKOGMzYHwA3w=="
}
}
}

@ -4,6 +4,7 @@
"description": "Tree Sitter grammar for Erlang",
"scripts": {
"test": "tree-sitter test",
"test-highlight": "tree-sitter test -f does-not-exist",
"generate": "tree-sitter generate",
"parse": "tree-sitter parse"
},
@ -12,7 +13,20 @@
"dependencies": {
"nan": "^2.14.1",
"prettier": "^2.2.1",
"tree-sitter-cli": "^0.20.7"
"tree-sitter-cli": "^0.20.8"
},
"main": "bindings/node"
"main": "bindings/node",
"tree-sitter": [
{
"scope": "source.erlang",
"file-types": [
"erl",
"hrl",
"app.src",
"app",
"escript",
"rebar.config"
]
}
]
}

@ -0,0 +1,228 @@
;; Copyright (c) Facebook, Inc. and its affiliates.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
;; You may obtain a copy of the License at
;;
;; http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.
;; ---------------------------------------------------------------------
;; Based initially on the contents of https://github.com/WhatsApp/tree-sitter-erlang/issues/2 by @Wilfred
;; and https://github.com/the-mikedavis/tree-sitter-erlang/blob/main/queries/highlights.scm
;;
;; The tests are also based on those in
;; https://github.com/the-mikedavis/tree-sitter-erlang/tree/main/test/highlight
;;
;; First match wins in this file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Attributes
;; module attribute
(module_attribute
name: (atom) @module)
;; behaviour
(behaviour_attribute name: (atom) @module)
;; export
;; Import attribute
(import_attribute
module: (atom) @module)
;; export_type
;; optional_callbacks
;; compile
(compile_options_attribute
options: (tuple
expr: (atom)
expr: (list
exprs: (binary_op_expr
lhs: (atom)
rhs: (integer)))))
;; file attribute
;; record
(record_decl name: (atom) @type)
(record_decl name: (macro_call_expr name: (var) @constant))
(record_field name: (atom) @property)
;; type alias
;; opaque
;; Spec attribute
(spec fun: (atom) @function)
(spec
module: (module name: (atom) @module)
fun: (atom) @function)
;; callback
(callback fun: (atom) @function)
;; wild attribute
(wild_attribute name: (attr_name name: (atom) @keyword))
;; fun decl
;; include/include_lib
;; ifdef/ifndef
(pp_ifdef name: (_) @keyword.directive)
(pp_ifndef name: (_) @keyword.directive)
;; define
(pp_define
lhs: (macro_lhs
name: (_) @keyword.directive
args: (var_args args: (var))))
(pp_define
lhs: (macro_lhs
name: (var) @constant))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions
(fa fun: (atom) @function)
(type_name name: (atom) @function)
(call expr: (atom) @function)
(function_clause name: (atom) @function)
(internal_fun fun: (atom) @function)
;; This is a fudge, we should check that the operator is '/'
;; But our grammar does not (currently) provide it
(binary_op_expr lhs: (atom) @function rhs: (integer))
;; Others
(remote_module module: (atom) @module)
(remote fun: (atom) @function)
(macro_call_expr name: (var) @keyword.directive args: (_) )
(macro_call_expr name: (var) @constant)
(macro_call_expr name: (atom) @keyword.directive)
(record_field_name name: (atom) @property)
(record_name name: (atom) @type)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Reserved words
[ "after"
"and"
"band"
"begin"
"behavior"
"behaviour"
"bnot"
"bor"
"bsl"
"bsr"
"bxor"
"callback"
"case"
"catch"
"compile"
"define"
"div"
"elif"
"else"
"end"
"endif"
"export"
"export_type"
"file"
"fun"
"if"
"ifdef"
"ifndef"
"import"
"include"
"include_lib"
"module"
"of"
"opaque"
"optional_callbacks"
"or"
"receive"
"record"
"spec"
"try"
"type"
"undef"
"unit"
"when"
"xor"] @keyword
["andalso" "orelse"] @keyword.operator
;; Punctuation
["," "." ";"] @punctuation.delimiter
["(" ")" "{" "}" "[" "]" "<<" ">>"] @punctuation.bracket
;; Operators
["!"
"->"
"<-"
"#"
"::"
"|"
":"
"="
"||"
"+"
"-"
"bnot"
"not"
"/"
"*"
"div"
"rem"
"band"
"and"
"+"
"-"
"bor"
"bxor"
"bsl"
"bsr"
"or"
"xor"
"++"
"--"
"=="
"/="
"=<"
"<"
">="
">"
"=:="
"=/="
] @operator
;;; Comments
((var) @comment.discard
(#match? @comment.discard "^_"))
(dotdotdot) @comment.discard
(comment) @comment
;; Primitive types
(string) @string
(char) @constant
(integer) @number
(var) @variable
(atom) @string.special.symbol

@ -48,6 +48,10 @@
"type": "SYMBOL",
"name": "file_attribute"
},
{
"type": "SYMBOL",
"name": "deprecated_attribute"
},
{
"type": "SYMBOL",
"name": "record_decl"
@ -1228,6 +1232,256 @@
}
]
},
"deprecated_attribute": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "-"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "deprecated"
},
{
"type": "ALIAS",
"content": {
"type": "STRING",
"value": "'deprecated'"
},
"named": false,
"value": "deprecated"
}
]
},
{
"type": "STRING",
"value": "("
},
{
"type": "FIELD",
"name": "attr",
"content": {
"type": "SYMBOL",
"name": "_deprecated_details"
}
},
{
"type": "STRING",
"value": ")"
},
{
"type": "STRING",
"value": "."
}
]
},
"_deprecated_details": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "deprecated_module"
},
{
"type": "SYMBOL",
"name": "deprecated_fa"
},
{
"type": "SYMBOL",
"name": "deprecated_fas"
}
]
},
"deprecated_module": {
"type": "FIELD",
"name": "module",
"content": {
"type": "SYMBOL",
"name": "atom"
}
},
"deprecated_fas": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "["
},
{
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "fa",
"content": {
"type": "SYMBOL",
"name": "deprecated_fa"
}
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "FIELD",
"name": "fa",
"content": {
"type": "SYMBOL",
"name": "deprecated_fa"
}
}
]
}
}
]
},
{
"type": "STRING",
"value": "]"
}
]
},
"deprecated_fa": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{
"type": "FIELD",
"name": "fun",
"content": {
"type": "SYMBOL",
"name": "atom"
}
},
{
"type": "STRING",
"value": ","
},
{
"type": "FIELD",
"name": "arity",
"content": {
"type": "SYMBOL",
"name": "_deprecated_fun_arity"
}
},
{
"type": "FIELD",
"name": "desc",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "deprecation_desc"
},
{
"type": "BLANK"
}
]
}
},
{
"type": "STRING",
"value": "}"
}
]
},
"deprecation_desc": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "FIELD",
"name": "desc",
"content": {
"type": "SYMBOL",
"name": "_desc"
}
}
]
},
"_desc": {
"type": "CHOICE",
"members": [
{
"type": "FIELD",
"name": "atom",
"content": {
"type": "SYMBOL",
"name": "atom"
}
},
{
"type": "FIELD",
"name": "comment",
"content": {
"type": "SYMBOL",
"name": "multi_string"
}
}
]
},
"multi_string": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "FIELD",
"name": "elems",
"content": {
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "_string_like"
}
}
}
},
"_string_like": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "string"
},
{
"type": "SYMBOL",
"name": "_macro_body_expr"
}
]
},
"_deprecated_fun_arity": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "integer"
},
{
"type": "SYMBOL",
"name": "deprecated_wildcard"
}
]
},
"deprecated_wildcard": {
"type": "STRING",
"value": "'_'"
},
"type_alias": {
"type": "SEQ",
"members": [
@ -2166,6 +2420,10 @@
{
"type": "SYMBOL",
"name": "_expr_max"
},
{
"type": "SYMBOL",
"name": "cond_match_expr"
}
]
},
@ -2227,6 +2485,39 @@
]
}
},
"cond_match_expr": {
"type": "PREC_RIGHT",
"value": 81,
"content": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "lhs",
"content": {
"type": "SYMBOL",
"name": "_expr"
}
},
{
"type": "STRING",
"value": "?="
},
{
"type": "FIELD",
"name": "rhs",
"content": {
"type": "PREC_RIGHT",
"value": 0,
"content": {
"type": "SYMBOL",
"name": "_expr"
}
}
}
]
}
},
"binary_op_expr": {
"type": "CHOICE",
"members": [
@ -2507,6 +2798,10 @@
"type": "SYMBOL",
"name": "binary_comprehension"
},
{
"type": "SYMBOL",
"name": "map_comprehension"
},
{
"type": "SYMBOL",
"name": "tuple"
@ -2538,6 +2833,10 @@
{
"type": "SYMBOL",
"name": "try_expr"
},
{
"type": "SYMBOL",
"name": "maybe_expr"
}
]
},
@ -3039,6 +3338,39 @@
}
]
},
"map_comprehension": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "#"
},
{
"type": "STRING",
"value": "{"
},
{
"type": "FIELD",
"name": "expr",
"content": {
"type": "SYMBOL",
"name": "map_field"
}
},
{
"type": "FIELD",
"name": "lc_exprs",
"content": {
"type": "SYMBOL",
"name": "lc_exprs"
}
},
{
"type": "STRING",
"value": "}"
}
]
},
"lc_exprs": {
"type": "SEQ",
"members": [
@ -3095,6 +3427,10 @@
{
"type": "SYMBOL",
"name": "b_generator"
},
{
"type": "SYMBOL",
"name": "map_generator"
}
]
},
@ -3148,6 +3484,31 @@
}
]
},
"map_generator": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "lhs",
"content": {
"type": "SYMBOL",
"name": "map_field"
}
},
{
"type": "STRING",
"value": "<-"
},
{
"type": "FIELD",
"name": "rhs",
"content": {
"type": "SYMBOL",
"name": "_expr"
}
}
]
},
"tuple": {
"type": "SEQ",
"members": [
@ -4737,6 +5098,128 @@
}
]
},
"maybe_expr": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "maybe"
},
{
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "exprs",
"content": {
"type": "SYMBOL",
"name": "_expr"
}
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "FIELD",
"name": "exprs",
"content": {
"type": "SYMBOL",
"name": "_expr"
}
}
]
}
}
]
},
{
"type": "STRING",
"value": "end"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "maybe"
},
{
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "exprs",
"content": {
"type": "SYMBOL",
"name": "_expr"
}
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "FIELD",
"name": "exprs",
"content": {
"type": "SYMBOL",
"name": "_expr"
}
}
]
}
}
]
},
{
"type": "SYMBOL",
"name": "_maybe_else_clause"
}
]
}
]
},
"_maybe_else_clause": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "else"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_cr_clauses"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "end"
}
]
},
"_macro_def_replacement": {
"type": "CHOICE",
"members": [
@ -5664,7 +6147,11 @@
"_record_expr_base",
"_expr",
"_expr_max",
"_catch_pat"
"_catch_pat",
"_deprecated_details",
"_deprecated_fun_arity",
"_desc",
"_string_like"
],
"@generated": true
}

@ -115,6 +115,52 @@
}
]
},
{
"type": "_deprecated_details",
"named": true,
"subtypes": [
{
"type": "deprecated_fa",
"named": true
},
{
"type": "deprecated_fas",
"named": true
},
{
"type": "deprecated_module",
"named": true
}
]
},
{
"type": "_deprecated_fun_arity",
"named": true,
"subtypes": [
{
"type": "deprecated_wildcard",
"named": true
},
{
"type": "integer",
"named": true
}
]
},
{
"type": "_desc",
"named": true,
"subtypes": [
{
"type": "atom",
"named": true
},
{
"type": "multi_string",
"named": true
}
]
},
{
"type": "_expr",
"named": true,
@ -139,6 +185,10 @@
"type": "catch_expr",
"named": true
},
{
"type": "cond_match_expr",
"named": true
},
{
"type": "dotdotdot",
"named": true
@ -265,6 +315,14 @@
"type": "macro_string",
"named": true
},
{
"type": "map_comprehension",
"named": true
},
{
"type": "maybe_expr",
"named": true
},
{
"type": "paren_expr",
"named": true
@ -311,6 +369,10 @@
"type": "compile_options_attribute",
"named": true
},
{
"type": "deprecated_attribute",
"named": true
},
{
"type": "export_attribute",
"named": true
@ -404,6 +466,10 @@
{
"type": "generator",
"named": true
},
{
"type": "map_generator",
"named": true
}
]
},
@ -559,6 +625,24 @@
}
]
},
{
"type": "_string_like",
"named": true,
"subtypes": [
{
"type": "macro_call_expr",
"named": true
},
{
"type": "macro_string",
"named": true
},
{
"type": "string",
"named": true
}
]
},
{
"type": "ann_type",
"named": true,
@ -1075,6 +1159,32 @@
}
}
},
{
"type": "cond_match_expr",
"named": true,
"fields": {
"lhs": {
"multiple": false,
"required": true,
"types": [
{
"type": "_expr",
"named": true
}
]
},
"rhs": {
"multiple": false,
"required": true,
"types": [
{
"type": "_expr",
"named": true
}
]
}
}
},
{
"type": "cr_clause",
"named": true,
@ -1111,6 +1221,106 @@
}
}
},
{
"type": "deprecated_attribute",
"named": true,
"fields": {
"attr": {
"multiple": false,
"required": true,
"types": [
{
"type": "_deprecated_details",
"named": true
}
]
}
}
},
{
"type": "deprecated_fa",
"named": true,
"fields": {
"arity": {
"multiple": false,
"required": true,
"types": [
{
"type": "_deprecated_fun_arity",
"named": true
}
]
},
"desc": {
"multiple": false,
"required": false,
"types": [
{
"type": "deprecation_desc",
"named": true
}
]
},
"fun": {
"multiple": false,
"required": true,
"types": [
{
"type": "atom",
"named": true
}
]
}
}
},
{
"type": "deprecated_fas",
"named": true,
"fields": {
"fa": {
"multiple": true,
"required": true,
"types": [
{
"type": "deprecated_fa",
"named": true
}
]
}
}
},
{
"type": "deprecated_module",
"named": true,
"fields": {
"module": {
"multiple": false,
"required": true,
"types": [
{
"type": "atom",
"named": true
}
]
}
}
},
{
"type": "deprecation_desc",
"named": true,
"fields": {
"desc": {
"multiple": false,
"required": true,
"types": [
{
"type": "_desc",
"named": true
}
]
}
}
},
{
"type": "export_attribute",
"named": true,
@ -1749,6 +1959,32 @@
}
}
},
{
"type": "map_comprehension",
"named": true,
"fields": {
"expr": {
"multiple": false,
"required": true,
"types": [
{
"type": "map_field",
"named": true
}
]
},
"lc_exprs": {
"multiple": false,
"required": true,
"types": [
{
"type": "lc_exprs",
"named": true
}
]
}
}
},
{
"type": "map_expr",
"named": true,
@ -1817,6 +2053,32 @@
}
}
},
{
"type": "map_generator",
"named": true,
"fields": {
"lhs": {
"multiple": false,
"required": true,
"types": [
{
"type": "map_field",
"named": true
}
]
},
"rhs": {
"multiple": false,
"required": true,
"types": [
{
"type": "_expr",
"named": true
}
]
}
}
},
{
"type": "match_expr",
"named": true,
@ -1843,6 +2105,32 @@
}
}
},
{
"type": "maybe_expr",
"named": true,
"fields": {
"clauses": {
"multiple": true,
"required": false,
"types": [
{
"type": "_cr_clause_or_macro",
"named": true
}
]
},
"exprs": {
"multiple": true,
"required": true,
"types": [
{
"type": "_expr",
"named": true
}
]
}
}
},
{
"type": "module",
"named": true,
@ -1875,6 +2163,22 @@
}
}
},
{
"type": "multi_string",
"named": true,
"fields": {
"elems": {
"multiple": true,
"required": true,
"types": [
{
"type": "_string_like",
"named": true
}
]
}
}
},
{
"type": "opaque",
"named": true,
@ -2973,6 +3277,10 @@
"type": "?",
"named": false
},
{
"type": "?=",
"named": false
},
{
"type": "[",
"named": false
@ -3061,6 +3369,14 @@
"type": "define",
"named": false
},
{
"type": "deprecated",
"named": false
},
{
"type": "deprecated_wildcard",
"named": true
},
{
"type": "div",
"named": false
@ -3133,6 +3449,10 @@
"type": "integer",
"named": true
},
{
"type": "maybe",
"named": false
},
{
"type": "module",
"named": false

File diff suppressed because it is too large Load Diff

@ -34,6 +34,161 @@ behaviour attribute
(behaviour_attribute
(atom)))
================================================================================
deprecated attribute with arity
================================================================================
-deprecated({f,1}).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_fa
(atom)
(integer))))
================================================================================
deprecated attribute with arity wildcard
================================================================================
-deprecated({f,'_'}).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_fa
(atom)
(deprecated_wildcard))))
================================================================================
deprecated module attribute
================================================================================
-deprecated(module).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_module
(atom))))
================================================================================
deprecated '_', '_' attribute
================================================================================
-deprecated({'_','_'}).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_fa
(atom)
(deprecated_wildcard))))
================================================================================
deprecated function/arity/desc attribute
================================================================================
-deprecated({f,1,"Use g/1 instead"}).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_fa
(atom)
(integer)
(deprecation_desc
(multi_string
(string))))))
================================================================================
deprecated '_', '_', atom attribute
================================================================================
-deprecated({'_','_',eventually}).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_fa
(atom)
(deprecated_wildcard)
(deprecation_desc
(atom)))))
================================================================================
deprecated list attribute with func, arity and atom desc
================================================================================
-deprecated([{g,1,next_version}]).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_fas
(deprecated_fa
(atom)
(integer)
(deprecation_desc
(atom))))))
================================================================================
deprecated list attribute
================================================================================
-deprecated([{foo,'_',next}, {bar,1,"desc"}, {baz, 2}, {'_', '_', "all"}]).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_fas
(deprecated_fa
(atom)
(deprecated_wildcard)
(deprecation_desc
(atom)))
(deprecated_fa
(atom)
(integer)
(deprecation_desc
(multi_string
(string))))
(deprecated_fa
(atom)
(integer))
(deprecated_fa
(atom)
(deprecated_wildcard)
(deprecation_desc
(multi_string
(string)))))))
================================================================================
deprecated multi-string description
================================================================================
-deprecated({new, 1, "str1" "str2"}).
--------------------------------------------------------------------------------
(source_file
(deprecated_attribute
(deprecated_fa
(atom)
(integer)
(deprecation_desc
(multi_string
(string)
(string))))))
================================================================================
include attribute
================================================================================

@ -465,17 +465,17 @@ f() ->
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(match_expr
(var)
(binary_op_expr
(integer)
(var)))))))
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(match_expr
(var)
(binary_op_expr
(integer)
(var)))))))
================================================================================
fun
@ -485,18 +485,18 @@ fun
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(anonymous_fun
(fun_clause
(expr_args
(var))
(clause_body
(var))))))))
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(anonymous_fun
(fun_clause
(expr_args
(var))
(clause_body
(var))))))))
================================================================================
named fun
@ -506,16 +506,271 @@ named fun
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(anonymous_fun
(fun_clause
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(anonymous_fun
(fun_clause
(var)
(expr_args
(var))
(clause_body
(var))))))))
================================================================================
maybe
================================================================================
f() ->
maybe
{ok, A} ?= a(),
true = A >= 0,
{ok, B} ?= b(),
A + B
end.
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(maybe_expr
(cond_match_expr
(tuple
(atom)
(var))
(call
(atom)
(expr_args)))
(match_expr
(atom)
(binary_op_expr
(var)
(integer)))
(cond_match_expr
(tuple
(atom)
(var))
(call
(atom)
(expr_args)))
(binary_op_expr
(var)
(var)))))))
================================================================================
maybe else
================================================================================
f() ->
maybe
{ok, A} ?= a(),
true = A >= 0,
A
else
Err when Err /= warn -> error;
false -> error
end.
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(maybe_expr
(cond_match_expr
(tuple
(atom)
(var))
(call
(atom)
(expr_args)))
(match_expr
(atom)
(binary_op_expr
(var)
(integer)))
(var)
(cr_clause
(var)
(guard
(guard_clause
(binary_op_expr
(var)
(atom))))
(clause_body
(atom)))
(cr_clause
(atom)
(clause_body
(atom))))))))
================================================================================
simple map comprehension
================================================================================
f() ->
#{K => V || K := V <- #{1 => 2, 3 => 4}}.
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(map_comprehension
(map_field
(var)
(var))
(lc_exprs
(map_generator
(map_field
(var)
(expr_args
(var))
(map_expr
(map_field
(integer)
(integer))
(map_field
(integer)
(integer))))))))))
================================================================================
simple map comprehension with filter
================================================================================
f() ->
#{K => V || K := V <- #{1 => 2, 3 => 4}, K>1}.
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(map_comprehension
(map_field
(var)
(var))
(lc_exprs
(map_generator
(map_field
(var)
(var))
(map_expr
(map_field
(integer)
(integer))
(map_field
(integer)
(integer))))
(binary_op_expr
(var)
(integer))))))))
================================================================================
map comprehension with list generator
================================================================================
f() ->
#{K => K + 1 || K <- [1, 2, 3], K>1}.
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(map_comprehension
(map_field
(var)
(binary_op_expr
(var)
(integer)))
(lc_exprs
(generator
(var)
(list
(integer)
(integer)
(integer)))
(binary_op_expr
(var)
(integer))))))))
================================================================================
map comprehension with binary generator
================================================================================
f() ->
#{K => V || <<K, V>> <= <<1, 2, 3, 4>>, K>1}.
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(map_comprehension
(map_field
(var)
(var))
(lc_exprs
(b_generator
(binary
(bin_element
(var))
(clause_body
(var))))))))
(bin_element
(var)))
(binary
(bin_element
(integer))
(bin_element
(integer))
(bin_element
(integer))
(bin_element
(integer))))
(binary_op_expr
(var)
(integer))))))))
================================================================================
list comprehension with map generator
================================================================================
f() ->
[{K, V} || K := V <- #{1 => 2, 3 => 4}, K>1].
--------------------------------------------------------------------------------
(source_file
(fun_decl
(function_clause
(atom)
(expr_args)
(clause_body
(list_comprehension
(tuple
(var)
(var))
(lc_exprs
(map_generator
(map_field
(var)
(var))
(map_expr
(map_field
(integer)
(integer))
(map_field
(integer)
(integer))))
(binary_op_expr
(var)
(integer))))))))

@ -0,0 +1,189 @@
%% Copyright (c) Facebook, Inc. and its affiliates.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%% ---------------------------------------------------------------------
%% Based on
%% https://github.com/the-mikedavis/tree-sitter-erlang/blob/main/test/highlight/attributes.erl
-module(attributes).
% ^ keyword
% ^ punctuation.bracket
% ^ module
% ^ punctuation.bracket
% ^ punctuation.delimiter
-module('lru').
% ^ keyword
% ^ module
-export([a_func/1,another_func/2]).
% ^ keyword
% ^ punctuation.bracket
% ^ function
% ^ operator
% ^ number
% ^ function
-export_type([a_type/1,another_type/2]).
% ^ keyword
% ^ punctuation.bracket
% ^ function
% ^ operator
% ^ number
% ^ function
-import(lists, [sort/1,map/2]).
% ^ keyword
% ^ module
% ^ function
% ^ operator
% ^ number
-type t() :: integer()
% ^ keyword
% ^ function
% ^ operator
% ^ function
| 0
% ^ operator
% ^ number
| 0..1
% ^ operator
% ^ number
% ^ number
| $a..$b
% ^ operator
% ^ constant
% ^ constant
| [non_neg_integer(), ...]
% ^ operator
% ^ punctuation.bracket
% ^ function
% ^ comment.discard
| #{mfa() => atom()}.
% ^ operator
% ^ operator
% ^ punctuation.bracket
-opaque o() :: integer().
% ^ keyword
% ^ function
% ^ operator
% ^ function
-spec ok_this(Term) -> {ok, Term} when Term :: any().
% ^ keyword
% ^ function
% ^ variable
% ^ operator
% ^ punctuation.bracket
% ^ string.special.symbol
% ^ punctuation.delimiter
% ^ variable
% ^ keyword
% ^ variable
% ^ operator
% ^ function
-spec erlang:ok() -> ok.
% ^ module
% ^ function
% ^ string.special.symbol
-ifdef(debug).
% ^ keyword
% ^ keyword.directive
-ifdef(TEST).
% ^ keyword
% ^ keyword.directive
-define(LOG(X), io:format("~80~n", [X])).
% ^ keyword
% ^ keyword.directive
% ^ variable
% ^ module
% ^ function
% ^ string
% ^ variable
-define(SUB_PASS_TIMES, compile__sub_pass_times).
% ^ keyword
% ^ constant
% ^ string.special.symbol
-elif true.
% ^ keyword
-else.
% ^ keyword
-define(LOG(X), ok).
% ^ keyword
% ^ keyword.directive
% ^ variable
% ^ string.special.symbol
-endif.
% ^ keyword
-record(person, {name,
% ^ keyword
% ^ type
% ^ property
email_address="",
% ^ property
% ^ string
ssn :: string(),
% ^ property
phone=1 :: integer()}).
% ^ property
-record(?MODULE, {name}).
% ^ constant
% ^ property
-compile({no_auto_import,[min/2]}).
% ^ keyword
% % ^ string.special.symbol
% ^ function
-include("file.hrl").
% ^ keyword
-file("myfile.erl", 3).
% ^ keyword
-callback name(Arguments) -> Result.
% ^ keyword
% ^ function
-optional_callbacks([a_callback/3]).
% ^ keyword
% ^ function
-ifndef(TEST).
% ^ keyword
% ^ keyword.directive
-behaviour(gen_server).
% ^ keyword
% ^ module
-behavior(gen_server).
% ^ keyword
% ^ module
-dialyzer({nowarn_function, [compile/1]}).
% ^ keyword
% ^ string.special.symbol
% ^ function
-record(garbage_collection, {}).
%% ^ keyword
%% ^ type

File diff suppressed because it is too large Load Diff

@ -0,0 +1,32 @@
%% Copyright (c) Facebook, Inc. and its affiliates.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%% ---------------------------------------------------------------------
foo() ->
?assertMatch({ok, _}, start()),
%% ^ keyword.directive
?_assertEqual(a, a),
%% ^ keyword.directive
State#state.config#config.pid
%% ^ variable
%% ^ operator
%% ^ type
%% ^ punctuation.delimiter
%% ^ property
%% ^ operator
%% ^ type
%% ^ property
.