mirror of https://github.com/Wilfred/difftastic/
Update Elixir parser and use crate from crates.io
parent
8f6484cf75
commit
bd9c98050e
@ -1 +0,0 @@
|
||||
../tree-sitter-elixir/queries/highlights.scm
|
||||
@ -1 +0,0 @@
|
||||
tree-sitter-elixir/src
|
||||
@ -1,12 +0,0 @@
|
||||
AlignArrayOfStructures: Left
|
||||
BasedOnStyle: LLVM
|
||||
IndentCaseLabels: true
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 2
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
SeparateDefinitionBlocks: Always
|
||||
SortIncludes: CaseInsensitive
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceBeforeCaseColon: false
|
||||
@ -1,4 +0,0 @@
|
||||
/src/**/* linguist-generated=true
|
||||
/src/scanner.c linguist-generated=false
|
||||
# Exclude test files from language stats
|
||||
/test/**/*.ex linguist-documentation=true
|
||||
@ -1,10 +0,0 @@
|
||||
<!--
|
||||
This repository includes the Tree-sitter parser for Elixir,
|
||||
whereas editor-specific integrations are separate projects.
|
||||
|
||||
If you're running into Tree-sitter related issues in your editor,
|
||||
please report it on the respective repository (likely an editor
|
||||
plugin responsible for Tree-sitter integration).
|
||||
|
||||
For example, when using Neovim, go to https://github.com/nvim-treesitter/nvim-treesitter
|
||||
-->
|
||||
@ -1,44 +0,0 @@
|
||||
name: Generate
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14.x"
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
- name: Generate parser
|
||||
run: |
|
||||
npx tree-sitter generate
|
||||
npx tree-sitter build-wasm
|
||||
- name: Update parser files
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Generate parser
|
||||
file_pattern: src
|
||||
- name: Checkout gh-pages branch to ./gh-pages
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: gh-pages
|
||||
path: ./gh-pages
|
||||
- run: mv *.wasm ./gh-pages
|
||||
- name: Update WASM file on gh-pages branch
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Generate WASM
|
||||
file_pattern: "*.wasm"
|
||||
repository: ./gh-pages
|
||||
@ -1,34 +0,0 @@
|
||||
name: Test
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14.x"
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
- name: Check formatting
|
||||
run: npm run format-check
|
||||
# Ensure the generated parser is up to date
|
||||
- run: npx tree-sitter generate
|
||||
- name: Run Tree-sitter tests
|
||||
run: npx tree-sitter test
|
||||
- name: Run integration tests
|
||||
run: scripts/integration_test.sh
|
||||
@ -1,25 +0,0 @@
|
||||
# Deps
|
||||
/node_modules/
|
||||
|
||||
# Temporary files
|
||||
/tmp/
|
||||
|
||||
# Temporary files generated by Tree-sitter
|
||||
/build/
|
||||
log.html
|
||||
tree-sitter-elixir.wasm
|
||||
|
||||
# Files generated by Cargo
|
||||
/target/
|
||||
Cargo.lock
|
||||
|
||||
# C bindings/binaries
|
||||
/*.a
|
||||
/*.dylib
|
||||
/*.so*
|
||||
*.o
|
||||
/bindings/c/*.h
|
||||
/bindings/c/tree-sitter-*.pc
|
||||
|
||||
# Files generated by Swift
|
||||
/.build/
|
||||
@ -1,9 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [v0.1.0](https://github.com/elixir-lang/tree-sitter-elixir/tree/v0.1.0) (2023-03-14)
|
||||
|
||||
Initial release.
|
||||
@ -1,26 +0,0 @@
|
||||
[package]
|
||||
name = "tree-sitter-elixir"
|
||||
description = "Elixir grammar for the tree-sitter parsing library"
|
||||
version = "0.1.0"
|
||||
keywords = ["incremental", "parsing", "elixir"]
|
||||
categories = ["parsing", "text-editors"]
|
||||
repository = "https://github.com/elixir-lang/tree-sitter-elixir"
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
|
||||
build = "bindings/rust/build.rs"
|
||||
include = [
|
||||
"bindings/rust/*",
|
||||
"grammar.js",
|
||||
"queries/*",
|
||||
"src/*",
|
||||
]
|
||||
|
||||
[lib]
|
||||
path = "bindings/rust/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
tree-sitter = ">= 0.19, < 0.21"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
@ -1,176 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
@ -1,114 +0,0 @@
|
||||
VERSION := 0.19.1
|
||||
|
||||
# Repository
|
||||
SRC_DIR := src
|
||||
|
||||
PARSER_REPO_URL := $(shell git -C $(SRC_DIR) remote get-url origin )
|
||||
|
||||
ifeq (, $(PARSER_NAME))
|
||||
PARSER_NAME := $(shell basename $(PARSER_REPO_URL))
|
||||
PARSER_NAME := $(subst tree-sitter-,,$(PARSER_NAME))
|
||||
PARSER_NAME := $(subst .git,,$(PARSER_NAME))
|
||||
endif
|
||||
|
||||
ifeq (, $(PARSER_URL))
|
||||
PARSER_URL := $(subst :,/,$(PARSER_REPO_URL))
|
||||
PARSER_URL := $(subst git@,https://,$(PARSER_URL))
|
||||
PARSER_URL := $(subst .git,,$(PARSER_URL))
|
||||
endif
|
||||
|
||||
UPPER_PARSER_NAME := $(shell echo $(PARSER_NAME) | tr a-z A-Z )
|
||||
|
||||
# install directory layout
|
||||
PREFIX ?= /usr/local
|
||||
INCLUDEDIR ?= $(PREFIX)/include
|
||||
LIBDIR ?= $(PREFIX)/lib
|
||||
PCLIBDIR ?= $(LIBDIR)/pkgconfig
|
||||
|
||||
# collect C++ sources, and link if necessary
|
||||
CPPSRC := $(wildcard $(SRC_DIR)/*.cc)
|
||||
|
||||
ifeq (, $(CPPSRC))
|
||||
ADDITIONALLIBS :=
|
||||
else
|
||||
ADDITIONALLIBS := -lc++
|
||||
endif
|
||||
|
||||
# collect sources
|
||||
SRC := $(wildcard $(SRC_DIR)/*.c)
|
||||
SRC += $(CPPSRC)
|
||||
OBJ := $(addsuffix .o,$(basename $(SRC)))
|
||||
|
||||
# ABI versioning
|
||||
SONAME_MAJOR := 0
|
||||
SONAME_MINOR := 0
|
||||
|
||||
CFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR)
|
||||
CXXFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR)
|
||||
override CFLAGS += -std=gnu99 -fPIC
|
||||
override CXXFLAGS += -fPIC
|
||||
|
||||
# OS-specific bits
|
||||
ifeq ($(shell uname),Darwin)
|
||||
SOEXT = dylib
|
||||
SOEXTVER_MAJOR = $(SONAME_MAJOR).dylib
|
||||
SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).dylib
|
||||
LINKSHARED := $(LINKSHARED)-dynamiclib -Wl,
|
||||
ifneq ($(ADDITIONALLIBS),)
|
||||
LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS),
|
||||
endif
|
||||
LINKSHARED := $(LINKSHARED)-install_name,$(LIBDIR)/libtree-sitter-$(PARSER_NAME).$(SONAME_MAJOR).dylib,-rpath,@executable_path/../Frameworks
|
||||
else
|
||||
SOEXT = so
|
||||
SOEXTVER_MAJOR = so.$(SONAME_MAJOR)
|
||||
SOEXTVER = so.$(SONAME_MAJOR).$(SONAME_MINOR)
|
||||
LINKSHARED := $(LINKSHARED)-shared -Wl,
|
||||
ifneq ($(ADDITIONALLIBS),)
|
||||
LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS),
|
||||
endif
|
||||
LINKSHARED := $(LINKSHARED)-soname,libtree-sitter-$(PARSER_NAME).so.$(SONAME_MAJOR)
|
||||
endif
|
||||
ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly))
|
||||
PCLIBDIR := $(PREFIX)/libdata/pkgconfig
|
||||
endif
|
||||
|
||||
all: libtree-sitter-$(PARSER_NAME).a libtree-sitter-$(PARSER_NAME).$(SOEXTVER) bindings/c/$(PARSER_NAME).h bindings/c/tree-sitter-$(PARSER_NAME).pc
|
||||
|
||||
libtree-sitter-$(PARSER_NAME).a: $(OBJ)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
libtree-sitter-$(PARSER_NAME).$(SOEXTVER): $(OBJ)
|
||||
$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
|
||||
ln -sf $@ libtree-sitter-$(PARSER_NAME).$(SOEXT)
|
||||
ln -sf $@ libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR)
|
||||
|
||||
bindings/c/$(PARSER_NAME).h:
|
||||
sed -e 's|@UPPER_PARSERNAME@|$(UPPER_PARSER_NAME)|' \
|
||||
-e 's|@PARSERNAME@|$(PARSER_NAME)|' \
|
||||
bindings/c/tree-sitter.h.in > $@
|
||||
|
||||
bindings/c/tree-sitter-$(PARSER_NAME).pc:
|
||||
sed -e 's|@LIBDIR@|$(LIBDIR)|;s|@INCLUDEDIR@|$(INCLUDEDIR)|;s|@VERSION@|$(VERSION)|' \
|
||||
-e 's|=$(PREFIX)|=$${prefix}|' \
|
||||
-e 's|@PREFIX@|$(PREFIX)|' \
|
||||
-e 's|@ADDITIONALLIBS@|$(ADDITIONALLIBS)|' \
|
||||
-e 's|@PARSERNAME@|$(PARSER_NAME)|' \
|
||||
-e 's|@PARSERURL@|$(PARSER_URL)|' \
|
||||
bindings/c/tree-sitter.pc.in > $@
|
||||
|
||||
install: all
|
||||
install -d '$(DESTDIR)$(LIBDIR)'
|
||||
install -m755 libtree-sitter-$(PARSER_NAME).a '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).a
|
||||
install -m755 libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXTVER)
|
||||
ln -sf libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR)
|
||||
ln -sf libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXT)
|
||||
install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter
|
||||
install -m644 bindings/c/$(PARSER_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/
|
||||
install -d '$(DESTDIR)$(PCLIBDIR)'
|
||||
install -m644 bindings/c/tree-sitter-$(PARSER_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) libtree-sitter-$(PARSER_NAME).a libtree-sitter-$(PARSER_NAME).$(SOEXT) libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR) libtree-sitter-$(PARSER_NAME).$(SOEXTVER)
|
||||
rm -f bindings/c/$(PARSER_NAME).h bindings/c/tree-sitter-$(PARSER_NAME).pc
|
||||
|
||||
.PHONY: all install clean
|
||||
@ -1,68 +0,0 @@
|
||||
LEGAL NOTICE INFORMATION
|
||||
------------------------
|
||||
|
||||
All the files in this distribution are copyright to the terms below.
|
||||
|
||||
== All files in src/ except scanner.cc (generated by tree-sitter-cli)
|
||||
|
||||
Copyright (c) 2018-2021 Max Brunsfeld
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
== Some file fragments in test/corpus/
|
||||
|
||||
Copyright (c) 2021 Anantha Kumaran
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
== All other files
|
||||
|
||||
Copyright 2021 The Elixir Team
|
||||
|
||||
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
|
||||
|
||||
https://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.
|
||||
@ -1,41 +0,0 @@
|
||||
// swift-tools-version:5.3
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "TreeSitterElixir",
|
||||
platforms: [.macOS(.v10_13), .iOS(.v11)],
|
||||
products: [
|
||||
.library(name: "TreeSitterElixir", targets: ["TreeSitterElixir"]),
|
||||
],
|
||||
dependencies: [],
|
||||
targets: [
|
||||
.target(name: "TreeSitterElixir",
|
||||
path: ".",
|
||||
exclude: [
|
||||
"binding.gyp",
|
||||
"bindings",
|
||||
"Cargo.toml",
|
||||
"docs",
|
||||
"grammar.js",
|
||||
"LICENSE",
|
||||
"Makefile",
|
||||
"NOTICE",
|
||||
"package.json",
|
||||
"README.md",
|
||||
"scripts",
|
||||
"src/grammar.json",
|
||||
"src/node-types.json",
|
||||
"test",
|
||||
],
|
||||
sources: [
|
||||
"src/parser.c",
|
||||
"src/scanner.c",
|
||||
],
|
||||
resources: [
|
||||
.copy("queries")
|
||||
],
|
||||
publicHeadersPath: "bindings/swift",
|
||||
cSettings: [.headerSearchPath("src")])
|
||||
]
|
||||
)
|
||||
@ -1,11 +0,0 @@
|
||||
# tree-sitter-elixir
|
||||
|
||||
[](https://github.com/elixir-lang/tree-sitter-elixir/actions/workflows/test.yml)
|
||||
|
||||
Elixir grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter).
|
||||
|
||||
Ready for production. Currently used by GitHub itself for source code highlighting and code navigation.
|
||||
|
||||
## Development
|
||||
|
||||
See [the docs](./docs/index.md) for more details.
|
||||
@ -1,19 +0,0 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "tree_sitter_elixir_binding",
|
||||
"include_dirs": [
|
||||
"<!(node -e \"require('nan')\")",
|
||||
"src"
|
||||
],
|
||||
"sources": [
|
||||
"bindings/node/binding.cc",
|
||||
"src/parser.c",
|
||||
"src/scanner.c"
|
||||
],
|
||||
"cflags_c": [
|
||||
"-std=c99",
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
#ifndef TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||
#define TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||
|
||||
#include <tree_sitter/parser.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern TSLanguage *tree_sitter_@PARSERNAME@();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||
@ -1,11 +0,0 @@
|
||||
prefix=@PREFIX@
|
||||
libdir=@LIBDIR@
|
||||
includedir=@INCLUDEDIR@
|
||||
additionallibs=@ADDITIONALLIBS@
|
||||
|
||||
Name: tree-sitter-@PARSERNAME@
|
||||
Description: A tree-sitter grammar for the @PARSERNAME@ programming language.
|
||||
URL: @PARSERURL@
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} ${additionallibs} -ltree-sitter-@PARSERNAME@
|
||||
Cflags: -I${includedir}
|
||||
@ -1,28 +0,0 @@
|
||||
#include "tree_sitter/parser.h"
|
||||
#include <node.h>
|
||||
#include "nan.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
extern "C" TSLanguage * tree_sitter_elixir();
|
||||
|
||||
namespace {
|
||||
|
||||
NAN_METHOD(New) {}
|
||||
|
||||
void Init(Local<Object> exports, Local<Object> module) {
|
||||
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
|
||||
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
|
||||
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
|
||||
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
|
||||
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_elixir());
|
||||
|
||||
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("elixir").ToLocalChecked());
|
||||
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
|
||||
}
|
||||
|
||||
NODE_MODULE(tree_sitter_elixir_binding, Init)
|
||||
|
||||
} // namespace
|
||||
@ -1,19 +0,0 @@
|
||||
try {
|
||||
module.exports = require("../../build/Release/tree_sitter_elixir_binding");
|
||||
} catch (error1) {
|
||||
if (error1.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error1;
|
||||
}
|
||||
try {
|
||||
module.exports = require("../../build/Debug/tree_sitter_elixir_binding");
|
||||
} catch (error2) {
|
||||
if (error2.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error2;
|
||||
}
|
||||
throw error1
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
module.exports.nodeTypeInfo = require("../../src/node-types.json");
|
||||
} catch (_) {}
|
||||
@ -1,19 +0,0 @@
|
||||
fn main() {
|
||||
let src_dir = std::path::Path::new("src");
|
||||
|
||||
let mut c_config = cc::Build::new();
|
||||
c_config.include(src_dir);
|
||||
c_config
|
||||
.flag_if_supported("-Wno-unused-parameter")
|
||||
.flag_if_supported("-Wno-unused-but-set-variable")
|
||||
.flag_if_supported("-Wno-trigraphs");
|
||||
let parser_path = src_dir.join("parser.c");
|
||||
c_config.file(&parser_path);
|
||||
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
|
||||
|
||||
let scanner_path = src_dir.join("scanner.c");
|
||||
c_config.file(&scanner_path);
|
||||
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
|
||||
|
||||
c_config.compile("parser-scanner");
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
//! This crate provides elixir language support for the [tree-sitter][] parsing library.
|
||||
//!
|
||||
//! Typically, you will use the [language][language func] function to add this language to a
|
||||
//! tree-sitter [Parser][], and then use the parser to parse some code:
|
||||
//!
|
||||
//! ```
|
||||
//! let code = "";
|
||||
//! let mut parser = tree_sitter::Parser::new();
|
||||
//! parser.set_language(tree_sitter_elixir::language()).expect("Error loading elixir grammar");
|
||||
//! let tree = parser.parse(code, None).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
|
||||
//! [language func]: fn.language.html
|
||||
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
|
||||
//! [tree-sitter]: https://tree-sitter.github.io/
|
||||
|
||||
use tree_sitter::Language;
|
||||
|
||||
extern "C" {
|
||||
fn tree_sitter_elixir() -> Language;
|
||||
}
|
||||
|
||||
/// Get the tree-sitter [Language][] for this grammar.
|
||||
///
|
||||
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
|
||||
pub fn language() -> Language {
|
||||
unsafe { tree_sitter_elixir() }
|
||||
}
|
||||
|
||||
/// The content of the [`node-types.json`][] file for this grammar.
|
||||
///
|
||||
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
|
||||
pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
|
||||
|
||||
// Uncomment these to include any queries that this grammar contains
|
||||
|
||||
pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
|
||||
// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
|
||||
// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
|
||||
pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_can_load_grammar() {
|
||||
let mut parser = tree_sitter::Parser::new();
|
||||
parser
|
||||
.set_language(super::language())
|
||||
.expect("Error loading elixir language");
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
#ifndef TREE_SITTER_ELIXIR_H_
|
||||
#define TREE_SITTER_ELIXIR_H_
|
||||
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern TSLanguage *tree_sitter_elixir();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_ELIXIR_H_
|
||||
@ -1,60 +0,0 @@
|
||||
# Syntax highlighting
|
||||
|
||||
For detailed introduction see the official guide on [Syntax highlighting](https://tree-sitter.github.io/tree-sitter/syntax-highlighting).
|
||||
|
||||
Briefly speaking, Tree-sitter uses the rules in `queries/highlights.scm` to annotate nodes
|
||||
with specific tokens, then it maps those tokens to formatting style according to user-defined
|
||||
theme.
|
||||
|
||||
To test highlighting using the CLI, you need to create local configuration.
|
||||
|
||||
```shell
|
||||
# Create the config file
|
||||
npx tree-sitter init-config
|
||||
```
|
||||
|
||||
The above command should print out the config location, so that you can further configure it.
|
||||
Open the file and modify `"parser-directories"` to include the parent directory of `tree-sitter-elixir`.
|
||||
Also, you can optionally customize the theme, here's a tiny subset of the One Dark theme:
|
||||
|
||||
```json
|
||||
{
|
||||
"number": {
|
||||
"color": "#61afef",
|
||||
"bold": true
|
||||
},
|
||||
"string": "#98c379",
|
||||
"string.escape": "#56b6c2",
|
||||
"string.special": "#61afef",
|
||||
"string.regexp": "#e06c75",
|
||||
"type": "#e06c75",
|
||||
"comment": {
|
||||
"color": "#5c6370",
|
||||
"italic": true
|
||||
},
|
||||
"punctuation": "#abb2bf",
|
||||
"punctuation.special": "#be5046",
|
||||
"operator": {
|
||||
"color": "#d19a66",
|
||||
"bold": true
|
||||
},
|
||||
"variable": "#abb2bf",
|
||||
"function": "#61afef",
|
||||
"constant": "#61afef",
|
||||
"constant.builtin": {
|
||||
"color": "#e06c75",
|
||||
"bold": true
|
||||
},
|
||||
"keyword": "#c678dd",
|
||||
"attribute": "#e06c75",
|
||||
"embedded": null
|
||||
}
|
||||
```
|
||||
|
||||
With this setup you can test highlighting on files using the Tree-sitter CLI.
|
||||
|
||||
```shell
|
||||
npx tree-sitter highlight tmp/test.ex
|
||||
|
||||
npx tree-sitter highlight test/highlight/**/*.ex
|
||||
```
|
||||
@ -1,21 +0,0 @@
|
||||
# Development notes
|
||||
|
||||
This documentation covers rationale behind some of the design and implementation decisions,
|
||||
as well as basic Tree-sitter tips that are relevant.
|
||||
|
||||
## Pages
|
||||
|
||||
* [Parser](./parser.md)
|
||||
* [Highlighting](./highlighting.md)
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
While this parser is written from scratch, there were previous efforts that made
|
||||
for a helpful reference:
|
||||
|
||||
* [tree-sitter-elixir](https://github.com/ananthakumaran/tree-sitter-elixir) developed
|
||||
by [@ananthakumaran](https://github.com/ananthakumaran)
|
||||
* [tree-sitter-elixir](https://github.com/wingyplus/tree-sitter-elixir) developed
|
||||
by [@wingyplus](https://github.com/wingyplus) and [@Tuxified](https://github.com/Tuxified)
|
||||
|
||||
In particular, some test cases were sourced from [ananthakumaran/tree-sitter-elixir](https://github.com/ananthakumaran/tree-sitter-elixir).
|
||||
@ -1,261 +0,0 @@
|
||||
# Parser
|
||||
|
||||
## The AST
|
||||
|
||||
When it comes to AST Elixir is a rather specific language due to its macro system.
|
||||
From the perspective of our parser, the important implication is that a seemingly
|
||||
invalid code can be a valid syntax when used in a macro (or just put in the `quote`
|
||||
expression). For example:
|
||||
|
||||
```elixir
|
||||
quote do
|
||||
def Bar.foo(x), definitely_not_do: 1
|
||||
%{a}
|
||||
*/2
|
||||
end
|
||||
```
|
||||
|
||||
As opposed to other languages, core constructs like `def`, `if` and `for` are not
|
||||
particularly special either, since they are itself regular functions (or macros rather).
|
||||
As a result, these constructs can be used "improperly" in a quoted expression, as shown above.
|
||||
|
||||
Consequently, to correctly parse all Elixir code, we need the AST to closely match
|
||||
the Elixir AST. See [Elixir / Syntax reference](https://hexdocs.pm/elixir/syntax-reference.html)
|
||||
for more details.
|
||||
|
||||
Whenever possible, we try using a more specific nodes (like binary/unary operator), but only
|
||||
to the extent that doesn't lose on generality. To get a sense of what the AST looks like, have
|
||||
a look at the tests in `test/corpus/`.
|
||||
|
||||
## Getting started with Tree-sitter
|
||||
|
||||
For detailed introduction see the official guide on [Creating parsers](https://tree-sitter.github.io/tree-sitter/creating-parsers).
|
||||
|
||||
Essentially, we define relevant language rules in `grammar.js`, based on which
|
||||
Tree-sitter generates parser code (under `src/`). In some cases, we want to write
|
||||
custom C code for tokenizing specific character sequences (in `src/scanner.c`).
|
||||
|
||||
The grammar rules may often conflict with each other, meaning that the given
|
||||
sequence of tokens has multiple valid interpretations given one _token_ of lookahead.
|
||||
In many conflicts we always want to pick one interpretation over the other and we can
|
||||
do this by assigning different precedence and associativity to relevant rules, which
|
||||
tells the parser which way to go.
|
||||
|
||||
For example given `expression1 * expression2 • *` the next token we _see_ ahead is `*`.
|
||||
The parser needs to decide whether `expression1 * expression2` is a complete binary operator
|
||||
node, or if it should await the next expression and interpret it as `expression1 * (expression2 * expression3)`.
|
||||
Since the `*` operator is left-associative we can use `prec.left` on the corresponding
|
||||
grammar rule, to inform the parser how to resolve this conflict.
|
||||
|
||||
However, in some cases looking at one token ahead isn't enough, in which case we can add
|
||||
the conflicting rules to the `conflicts` list in the grammar. Whenever the parser stumbles
|
||||
upon this conflict it uses its GLR algorithm, basically considering both interpretations
|
||||
until one leads to parsing error. If both paths parse correctly (there's a genuine ambiguity)
|
||||
we can use dynamic precedence (`prec.dynamic`) to decide on the preferred path.
|
||||
|
||||
## Using the CLI
|
||||
|
||||
### tree-sitter
|
||||
|
||||
```shell
|
||||
# See CLI usage
|
||||
npx tree-sitter -h
|
||||
|
||||
# Generate the the parser code based on grammar.js
|
||||
npx tree-sitter generate
|
||||
|
||||
# Run tests
|
||||
npx tree-sitter test
|
||||
npx tree-sitter test --filter "access syntax"
|
||||
|
||||
# Parse a specific file
|
||||
npx tree-sitter parse tmp/test.ex
|
||||
npx tree-sitter parse -x tmp/test.ex
|
||||
|
||||
# Parse codebase to verify syntax coverage
|
||||
npx tree-sitter parse --quiet --stat 'tmp/elixir/**/*.ex*'
|
||||
```
|
||||
|
||||
Whenever you make a change to `grammar.js` remember to run `generate`,
|
||||
before verifying the result. To test custom code, create an Elixir file
|
||||
like `tmp/test.ex` and use `parse` on it. The `-x` flag prints out the
|
||||
source grouped into AST nodes as XML.
|
||||
|
||||
### Additional scripts
|
||||
|
||||
```shell
|
||||
# Format the grammar.js file
|
||||
npm run format
|
||||
|
||||
# Run parser against the given repository
|
||||
scripts/parse_repo.sh elixir-lang/elixir
|
||||
|
||||
# Run parser against a predefined list of popular repositories
|
||||
scripts/integration_test.sh
|
||||
```
|
||||
|
||||
## Implementation notes
|
||||
|
||||
This section covers some of the implementation decisions that have a more
|
||||
elaborated rationale. The individual subsections are referenced in the code.
|
||||
|
||||
### Ref 1. External scanner for quoted content
|
||||
|
||||
We want to scan quoted content as a single token, but it requires lookahead.
|
||||
Specifically the `#` character may no longer be quoted content if followed by `{`.
|
||||
Also, inside heredoc string tokenizing `"` (or `'`) requires lookahead to know
|
||||
if it's already part of the end delimiter or not.
|
||||
|
||||
Since we need to use external scanner, we need to know the delimiter type.
|
||||
One way to achieve this is using external scanner to scan the start delimiter
|
||||
and then storing its type on the parser stack. This approach requires the parser
|
||||
to allocate enough memory upfront and implement serialization/deserialization,
|
||||
which ideally would be avoided. To avoid this, we use a different approach!
|
||||
Instead of having a single `quoted_content` token, we have specific tokens for
|
||||
each quoted content type, such as `_quoted_content_i_single`, `_quoted_content_i_double`.
|
||||
Once the start delimiter is tokenized, we know which quoted content should be
|
||||
tokenized next, and from the token we can infer the end delimiter and whether
|
||||
it supports interpolation. In other words, we extract the information from the
|
||||
parsing state, rather than maintaining custom parser state.
|
||||
|
||||
### Ref 2. External scanner for newlines
|
||||
|
||||
Generally newlines may appear in the middle of expressions and we ignore them
|
||||
as long as the expression is valid, that's why we list newline under extras.
|
||||
|
||||
When a newline follows a complete expression, most of the time it should be
|
||||
treated as terminator. However, there are specific cases where the newline is
|
||||
non-breaking and treated as if it was just a space. This cases are:
|
||||
|
||||
* call followed by newline and a `do end` block
|
||||
* expression followed by newline and a binary operator
|
||||
|
||||
In both cases we want to tokenize the newline as non-breaking, so we use external
|
||||
scanner for lookahead.
|
||||
|
||||
Note that the relevant rules already specify left/right associativity, so if we
|
||||
simply added `optional("\n")` the conflicts would be resolved immediately rather
|
||||
without using GLR.
|
||||
|
||||
Additionally, since comments may appear anywhere and don't change the context,
|
||||
we also tokenize newlines before comments as non-breaking.
|
||||
|
||||
### Ref 3. External scanner for unary + and -
|
||||
|
||||
Plus and minus are either binary or unary operators, depending on the context.
|
||||
Consider the following variants
|
||||
|
||||
```
|
||||
a + b
|
||||
a+b
|
||||
a+ b
|
||||
a +b
|
||||
```
|
||||
|
||||
In the first three expressions `+` is a binary operator, while in the last one
|
||||
`+` is an unary operator referring to local call argument.
|
||||
|
||||
To correctly tokenize all cases we use external scanner to tokenize a special empty
|
||||
token (`_before_unary_operator`) when the spacing matches `a +b`, which forces the
|
||||
parser to pick the unary operator path.
|
||||
|
||||
### Ref 4. External scanner for `not in`
|
||||
|
||||
The `not in` operator may have an arbitrary inline whitespace between `not` and `in`.
|
||||
|
||||
We cannot use a regular expression like `/not[ \t]+in/`, because it would also match
|
||||
in expressions like `a not inn` as the longest matching token.
|
||||
|
||||
A possible solution could be `seq("not", "in")` with dynamic conflict resolution, but
|
||||
then we tokenize two separate tokens. Also to properly handle `a not inn`, we would need
|
||||
keyword extraction, which causes problems in our case (https://github.com/tree-sitter/tree-sitter/issues/1404).
|
||||
|
||||
In the end it's easiest to use external scanner, so that we can skip inline whitespace
|
||||
and ensure token ends after `in`.
|
||||
|
||||
### Ref 5. External scanner for quoted atom start
|
||||
|
||||
For parsing quoted atom `:` we could make the `"` (or `'`) token immediate, however this
|
||||
would require adding immediate rules for single/double quoted content and listing them
|
||||
in relevant places. We could definitely do that, but using external scanner is actually
|
||||
simpler.
|
||||
|
||||
### Ref 6. Identifier pattern
|
||||
|
||||
See [Elixir / Unicode Syntax](https://hexdocs.pm/elixir/unicode-syntax.html) for official
|
||||
notes.
|
||||
|
||||
Tree-sitter already supports unicode properties in regular expressions, however character
|
||||
class subtraction is not supported.
|
||||
|
||||
For the base `<Start>` and `<Continue>` we can use `[\p{ID_Start}]` and `[\p{ID_Continue}]`
|
||||
respectively, since both are supported and according to the
|
||||
[Unicode Annex #31](https://unicode.org/reports/tr31/#Table_Lexical_Classes_for_Identifiers)
|
||||
they match the ranges listed in the Elixir docs.
|
||||
|
||||
For atoms this translates to a clean regular expression.
|
||||
|
||||
For variables however, we want to exclude uppercase (`\p{Lu}`) and titlecase (`\p{Lt}`)
|
||||
categories from `\p{ID_Start}`. As already mentioned, we cannot use group subtraction
|
||||
in the regular expression, so instead we need to create a suitable group of characters
|
||||
on our own.
|
||||
|
||||
After removing the uppercase/titlecase categories from `[\p{ID_Start}]`, we obtain the
|
||||
following group:
|
||||
|
||||
`[\p{Ll}\p{Lm}\p{Lo}\p{Nl}\p{Other_ID_Start}-\p{Pattern_Syntax}-\p{Pattern_White_Space}]`
|
||||
|
||||
At the time of writing the subtracted groups actually only remove a single character:
|
||||
|
||||
```elixir
|
||||
Mix.install([{:unicode_set, "~> 1.1"}])
|
||||
|
||||
Unicode.Set.to_utf8_char(
|
||||
"[[[:Ll:][:Lm:][:Lo:][:Nl:][:Other_ID_Start:]] & [[:Pattern_Syntax:][:Pattern_White_Space:]]]"
|
||||
)
|
||||
#=> {:ok, [11823]}
|
||||
```
|
||||
|
||||
Consequently, by removing the subtraction we allow just one additional (not common) character,
|
||||
which is perfectly acceptable.
|
||||
|
||||
It's important to note that JavaScript regular expressions don't support the `\p{Other_ID_Start}`
|
||||
unicode category. Fortunately this category is a small set of characters introduces for
|
||||
[backward compatibility](https://unicode.org/reports/tr31/#Backward_Compatibility), so we can
|
||||
enumerate it manually:
|
||||
|
||||
```elixir
|
||||
Mix.install([{:unicode_set, "~> 1.1"}])
|
||||
|
||||
Unicode.Set.to_utf8_char("[[[:Other_ID_Start:]] - [[:Pattern_Syntax:][:Pattern_White_Space:]]]")
|
||||
|> elem(1)
|
||||
|> Enum.flat_map(fn
|
||||
n when is_number(n) -> [n]
|
||||
range -> range
|
||||
end)
|
||||
|> Enum.map(&Integer.to_string(&1, 16))
|
||||
#=> ["1885", "1886", "2118", "212E", "309B", "309C"]
|
||||
```
|
||||
|
||||
Finally, we obtain this regular expression group for variable `<Start>`:
|
||||
|
||||
`[\p{Ll}\p{Lm}\p{Lo}\p{Nl}\u1885\u1886\u2118\u212E\u309B\u309C]`
|
||||
|
||||
### Ref 7. Keyword token
|
||||
|
||||
We tokenize the whole keyword sequence like `do: ` as a single token.
|
||||
Ideally we wouldn't include the whitespace, but since we use `token`
|
||||
it gets include. However, this is an intentionally accepted tradeoff,
|
||||
because using `token` significantly simplifies the grammar and avoids
|
||||
conflicts.
|
||||
|
||||
The alternative approach would be to define keyword as `seq(alias(choice(...), $._keyword_literal), $._keyword_end)`,
|
||||
where we list all other tokens that make for for valid keyword literal
|
||||
and use custom scanner for `_keyword_end` to look ahead without tokenizing
|
||||
the whitespace. However, this approach generates a number of conflicts
|
||||
because `:` is tokenized separately and phrases like `fun fun • do` or
|
||||
`fun • {}` are ambiguous (interpretation depends on whether `:` comes next).
|
||||
Resolving some of these conflicts (for instance special keywords like `{}` or `%{}`)
|
||||
requires the use of external scanner. Given the complexities this approach
|
||||
brings to the grammar, and consequently the parser, we stick to the simpler
|
||||
approach.
|
||||
@ -1,918 +0,0 @@
|
||||
const PREC = {
|
||||
// See https://github.com/elixir-lang/elixir/blob/master/lib/elixir/src/elixir_parser.yrl
|
||||
IN_MATCH_OPS: 10,
|
||||
WHEN_OP: 20,
|
||||
TYPE_OP: 30,
|
||||
BAR_OP: 40,
|
||||
ASSOC_OP: 50,
|
||||
CAPTURE_OP: 60,
|
||||
MATCH_OP: 70,
|
||||
OR_OPS: 80,
|
||||
AND_OPS: 90,
|
||||
COMP_OPS: 100,
|
||||
REL_OPS: 110,
|
||||
ARROW_OPS: 120,
|
||||
IN_OPS: 130,
|
||||
XOR_OP: 140,
|
||||
TERNARY_OP: 150,
|
||||
CONCAT_OPS: 160,
|
||||
RANGE_OP: 160,
|
||||
ADD_OPS: 170,
|
||||
MULT_OPS: 180,
|
||||
POWER_OP: 190,
|
||||
UNARY_OPS: 200,
|
||||
ACCESS: 205,
|
||||
DOT_OP: 210,
|
||||
AT_OP: 220,
|
||||
CAPTURE_OPERAND: 235,
|
||||
};
|
||||
|
||||
const IN_MATCH_OPS = ["<-", "\\\\"];
|
||||
const OR_OPS = ["||", "|||", "or"];
|
||||
const AND_OPS = ["&&", "&&&", "and"];
|
||||
const COMP_OPS = ["==", "!=", "=~", "===", "!=="];
|
||||
const REL_OPS = ["<", ">", "<=", ">="];
|
||||
const ARROW_OPS = ["|>", "<<<", ">>>", "<<~", "~>>", "<~", "~>", "<~>", "<|>"];
|
||||
const IN_OPS = ["in", "not in"];
|
||||
const CONCAT_OPS = ["++", "--", "+++", "---", "<>"];
|
||||
const ADD_OPS = ["+", "-"];
|
||||
const MULT_OPS = ["*", "/"];
|
||||
const UNARY_OPS = ["+", "-", "!", "^", "~~~", "not"];
|
||||
|
||||
const ALL_OPS = [
|
||||
["->", "when", "::", "|", "=>", "&", "=", "^^^", "//", "..", "**", ".", "@"],
|
||||
IN_MATCH_OPS,
|
||||
OR_OPS,
|
||||
AND_OPS,
|
||||
COMP_OPS,
|
||||
REL_OPS,
|
||||
ARROW_OPS,
|
||||
IN_OPS,
|
||||
CONCAT_OPS,
|
||||
ADD_OPS,
|
||||
MULT_OPS,
|
||||
UNARY_OPS,
|
||||
].flat();
|
||||
|
||||
// Ignore word literals and "=>" which is not a valid atom
|
||||
const ATOM_OPERATOR_LITERALS = ALL_OPS.filter(
|
||||
(operator) => !/[a-z]/.test(operator) && operator !== "=>"
|
||||
);
|
||||
|
||||
const ATOM_SPECIAL_LITERALS = ["...", "%{}", "{}", "%", "<<>>", "..//"];
|
||||
|
||||
// See Ref 6. in the docs
|
||||
const ATOM_WORD_LITERAL = /[\p{ID_Start}_][\p{ID_Continue}@]*[?!]?/u;
|
||||
|
||||
// Word tokens used directly in the grammar
|
||||
const RESERVED_WORD_TOKENS = [
|
||||
// Operators
|
||||
["and", "in", "not", "or", "when"],
|
||||
// Literals
|
||||
["true", "false", "nil"],
|
||||
// Other
|
||||
["after", "catch", "do", "else", "end", "fn", "rescue"],
|
||||
].flat();
|
||||
|
||||
const DIGITS = /[0-9]+/;
|
||||
const BIN_DIGITS = /[0-1]+/;
|
||||
const OCT_DIGITS = /[0-7]+/;
|
||||
const HEX_DIGITS = /[0-9a-fA-F]+/;
|
||||
|
||||
const NUMBER_DEC = sep1(DIGITS, "_");
|
||||
const NUMBER_BIN = seq("0b", sep1(BIN_DIGITS, "_"));
|
||||
const NUMBER_OCT = seq("0o", sep1(OCT_DIGITS, "_"));
|
||||
const NUMBER_HEX = seq("0x", sep1(HEX_DIGITS, "_"));
|
||||
|
||||
const INTEGER = choice(NUMBER_DEC, NUMBER_BIN, NUMBER_OCT, NUMBER_HEX);
|
||||
|
||||
const FLOAT_SCIENTIFIC_PART = seq(/[eE]/, optional(choice("-", "+")), INTEGER);
|
||||
const FLOAT = seq(NUMBER_DEC, ".", NUMBER_DEC, optional(FLOAT_SCIENTIFIC_PART));
|
||||
|
||||
const NEWLINE = /\r?\n/;
|
||||
|
||||
module.exports = grammar({
|
||||
name: "elixir",
|
||||
|
||||
externals: ($) => [
|
||||
// See Ref 1. in the docs
|
||||
$._quoted_content_i_single,
|
||||
$._quoted_content_i_double,
|
||||
$._quoted_content_i_heredoc_single,
|
||||
$._quoted_content_i_heredoc_double,
|
||||
$._quoted_content_i_parenthesis,
|
||||
$._quoted_content_i_curly,
|
||||
$._quoted_content_i_square,
|
||||
$._quoted_content_i_angle,
|
||||
$._quoted_content_i_bar,
|
||||
$._quoted_content_i_slash,
|
||||
$._quoted_content_single,
|
||||
$._quoted_content_double,
|
||||
$._quoted_content_heredoc_single,
|
||||
$._quoted_content_heredoc_double,
|
||||
$._quoted_content_parenthesis,
|
||||
$._quoted_content_curly,
|
||||
$._quoted_content_square,
|
||||
$._quoted_content_angle,
|
||||
$._quoted_content_bar,
|
||||
$._quoted_content_slash,
|
||||
|
||||
// See Ref 2. in the docs
|
||||
$._newline_before_do,
|
||||
$._newline_before_binary_operator,
|
||||
$._newline_before_comment,
|
||||
|
||||
// See Ref 3. in the docs
|
||||
$._before_unary_op,
|
||||
|
||||
// See Ref 4. in the docs
|
||||
$._not_in,
|
||||
|
||||
// See Ref 5. in the docs
|
||||
$._quoted_atom_start,
|
||||
],
|
||||
|
||||
extras: ($) => [
|
||||
NEWLINE,
|
||||
/[ \t]|\r?\n|\\\r?\n/,
|
||||
$.comment,
|
||||
$._newline_before_comment,
|
||||
// Placing this directly in the binary operator rule leads
|
||||
// to conflicts, but we can place it here without any drawbacks.
|
||||
// If we detect binary operator and the previous line is not a
|
||||
// valid expression, it's a syntax error either way
|
||||
$._newline_before_binary_operator,
|
||||
],
|
||||
|
||||
conflicts: ($) => [
|
||||
// Given `left • *`, `left` identifier can be either:
|
||||
// * expression in `left * right`
|
||||
// * call identifier in `left * / 2`
|
||||
[$._expression, $._local_call_without_parentheses],
|
||||
|
||||
// Given `left • when`, `left` expression can be either:
|
||||
// * binary operator operand in `left when right`
|
||||
// * stab arguments item in `left when right ->`
|
||||
//
|
||||
// Given `arg1, left • when`, `left` expression can be either:
|
||||
// * binary operator operand in `arg1, left when right, arg3`
|
||||
// * stab arguments item in `arg1, left when right ->`
|
||||
[$.binary_operator, $._stab_clause_arguments_without_parentheses],
|
||||
|
||||
// Given `((arg1, arg2 • ,`, `arg3` expression can be either:
|
||||
// * stab parenthesised arguments item in `((arg1, arg2, arg3) ->)`
|
||||
// * stab non-parenthesised arguments item in `((arg1, arg2, arg3 ->))`
|
||||
[
|
||||
$._stab_clause_arguments_without_parentheses,
|
||||
$._stab_clause_arguments_with_parentheses,
|
||||
],
|
||||
|
||||
// Given `(-> • /`, stab can be either:
|
||||
// * stab clause operator in `(-> / / 2)`
|
||||
// * operator identifier in `(-> / 2)`
|
||||
[$.operator_identifier, $.stab_clause],
|
||||
|
||||
// Given `& /`, ampersand can be either:
|
||||
// * capture operator in `& / / 2`
|
||||
// * operator identifier in `& / 1`
|
||||
[$.unary_operator, $.operator_identifier],
|
||||
|
||||
// Given `(arg -> expression • \n`, the newline could be either:
|
||||
// * terminator separating expressions in `(arg -> expression \n expression)`
|
||||
// * terminator separating clauses in `(arg -> expression \n arg -> expression)`
|
||||
[$.body],
|
||||
],
|
||||
|
||||
rules: {
|
||||
source: ($) =>
|
||||
seq(
|
||||
optional($._terminator),
|
||||
optional(
|
||||
seq(sep1($._expression, $._terminator), optional($._terminator))
|
||||
)
|
||||
),
|
||||
|
||||
_terminator: ($) =>
|
||||
// Right precedence, because we want to consume `;` after newlines if present
|
||||
prec.right(choice(seq(repeat(NEWLINE), ";"), repeat1(NEWLINE))),
|
||||
|
||||
_expression: ($) =>
|
||||
choice(
|
||||
$.block,
|
||||
$.identifier,
|
||||
$.alias,
|
||||
$.integer,
|
||||
$.float,
|
||||
$.char,
|
||||
$.boolean,
|
||||
$.nil,
|
||||
$._atom,
|
||||
$.string,
|
||||
$.charlist,
|
||||
$.sigil,
|
||||
$.list,
|
||||
$.tuple,
|
||||
$.bitstring,
|
||||
$.map,
|
||||
$._nullary_operator,
|
||||
$.unary_operator,
|
||||
$.binary_operator,
|
||||
$.dot,
|
||||
$.call,
|
||||
$.access_call,
|
||||
$.anonymous_function
|
||||
),
|
||||
|
||||
block: ($) =>
|
||||
seq(
|
||||
"(",
|
||||
optional($._terminator),
|
||||
optional(
|
||||
choice(
|
||||
sep1(choice($.stab_clause), $._terminator),
|
||||
seq(
|
||||
sep1(choice($._expression), $._terminator),
|
||||
optional($._terminator)
|
||||
)
|
||||
)
|
||||
),
|
||||
")"
|
||||
),
|
||||
|
||||
identifier: ($) =>
|
||||
choice(
|
||||
// See Ref 6. in the docs
|
||||
/[_\p{Ll}\p{Lm}\p{Lo}\p{Nl}\u1885\u1886\u2118\u212E\u309B\u309C][\p{ID_Continue}]*[?!]?/u,
|
||||
"..."
|
||||
),
|
||||
|
||||
alias: ($) => token(sep1(/[A-Z][_a-zA-Z0-9]*/, /\s*\.\s*/)),
|
||||
|
||||
integer: ($) => token(INTEGER),
|
||||
|
||||
float: ($) => token(FLOAT),
|
||||
|
||||
char: ($) => /\?(.|\\.)/,
|
||||
|
||||
boolean: ($) => choice("true", "false"),
|
||||
|
||||
nil: ($) => "nil",
|
||||
|
||||
_atom: ($) => choice($.atom, $.quoted_atom),
|
||||
|
||||
atom: ($) =>
|
||||
token(
|
||||
seq(
|
||||
":",
|
||||
choice(
|
||||
ATOM_WORD_LITERAL,
|
||||
...ATOM_OPERATOR_LITERALS,
|
||||
...ATOM_SPECIAL_LITERALS
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
quoted_atom: ($) =>
|
||||
seq(
|
||||
alias($._quoted_atom_start, ":"),
|
||||
choice($._quoted_i_double, $._quoted_i_single)
|
||||
),
|
||||
|
||||
// Defines $._quoted_content_i_{name} and $._quoted_content_{name} rules,
|
||||
// content with and without interpolation respectively
|
||||
...defineQuoted(`"`, `"`, "double"),
|
||||
...defineQuoted(`'`, `'`, "single"),
|
||||
...defineQuoted(`'''`, `'''`, "heredoc_single"),
|
||||
...defineQuoted(`"""`, `"""`, "heredoc_double"),
|
||||
...defineQuoted(`(`, `)`, "parenthesis"),
|
||||
...defineQuoted(`{`, `}`, "curly"),
|
||||
...defineQuoted(`[`, `]`, "square"),
|
||||
...defineQuoted(`<`, `>`, "angle"),
|
||||
...defineQuoted(`|`, `|`, "bar"),
|
||||
...defineQuoted(`/`, `/`, "slash"),
|
||||
|
||||
string: ($) => choice($._quoted_i_double, $._quoted_i_heredoc_double),
|
||||
|
||||
charlist: ($) => choice($._quoted_i_single, $._quoted_i_heredoc_single),
|
||||
|
||||
interpolation: ($) => seq("#{", optional($._expression), "}"),
|
||||
|
||||
escape_sequence: ($) =>
|
||||
token(
|
||||
seq(
|
||||
"\\",
|
||||
choice(
|
||||
// Single escaped character
|
||||
/[^ux]/,
|
||||
// Hex byte
|
||||
/x[0-9a-fA-F]{1,2}/,
|
||||
/x{[0-9a-fA-F]+}/,
|
||||
// Unicode code point
|
||||
/u{[0-9a-fA-F]+}/,
|
||||
/u[0-9a-fA-F]{4}/
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
sigil: ($) =>
|
||||
seq(
|
||||
"~",
|
||||
choice(
|
||||
seq(
|
||||
alias(token.immediate(/[a-z]/), $.sigil_name),
|
||||
choice(
|
||||
$._quoted_i_double,
|
||||
$._quoted_i_single,
|
||||
$._quoted_i_heredoc_single,
|
||||
$._quoted_i_heredoc_double,
|
||||
$._quoted_i_parenthesis,
|
||||
$._quoted_i_curly,
|
||||
$._quoted_i_square,
|
||||
$._quoted_i_angle,
|
||||
$._quoted_i_bar,
|
||||
$._quoted_i_slash
|
||||
)
|
||||
),
|
||||
seq(
|
||||
alias(token.immediate(/[A-Z]+/), $.sigil_name),
|
||||
choice(
|
||||
$._quoted_double,
|
||||
$._quoted_single,
|
||||
$._quoted_heredoc_single,
|
||||
$._quoted_heredoc_double,
|
||||
$._quoted_parenthesis,
|
||||
$._quoted_curly,
|
||||
$._quoted_square,
|
||||
$._quoted_angle,
|
||||
$._quoted_bar,
|
||||
$._quoted_slash
|
||||
)
|
||||
)
|
||||
),
|
||||
optional(alias(token.immediate(/[a-zA-Z0-9]+/), $.sigil_modifiers))
|
||||
),
|
||||
|
||||
keywords: ($) =>
|
||||
// Right precedence, because we want to consume next items as long
|
||||
// as there is a comma ahead
|
||||
prec.right(sep1($.pair, ",")),
|
||||
|
||||
_keywords_with_trailing_separator: ($) =>
|
||||
seq(sep1($.pair, ","), optional(",")),
|
||||
|
||||
pair: ($) => seq(field("key", $._keyword), field("value", $._expression)),
|
||||
|
||||
_keyword: ($) => choice($.keyword, $.quoted_keyword),
|
||||
|
||||
keyword: ($) =>
|
||||
// See Ref 7. in the docs
|
||||
token(
|
||||
seq(
|
||||
choice(
|
||||
ATOM_WORD_LITERAL,
|
||||
...ATOM_OPERATOR_LITERALS.filter((op) => op !== "::"),
|
||||
...ATOM_SPECIAL_LITERALS
|
||||
),
|
||||
/:\s/
|
||||
)
|
||||
),
|
||||
|
||||
quoted_keyword: ($) =>
|
||||
seq(
|
||||
choice($._quoted_i_double, $._quoted_i_single),
|
||||
token.immediate(/:\s/)
|
||||
),
|
||||
|
||||
list: ($) => seq("[", optional($._items_with_trailing_separator), "]"),
|
||||
|
||||
tuple: ($) => seq("{", optional($._items_with_trailing_separator), "}"),
|
||||
|
||||
bitstring: ($) =>
|
||||
seq("<<", optional($._items_with_trailing_separator), ">>"),
|
||||
|
||||
map: ($) =>
|
||||
// Precedence over tuple
|
||||
prec(
|
||||
1,
|
||||
seq(
|
||||
"%",
|
||||
optional($.struct),
|
||||
"{",
|
||||
optional(alias($._items_with_trailing_separator, $.map_content)),
|
||||
"}"
|
||||
)
|
||||
),
|
||||
|
||||
struct: ($) =>
|
||||
// Left precedence, because if there is a conflict involving `{}`,
|
||||
// we want to treat it as map continuation rather than tuple
|
||||
prec.left(
|
||||
choice(
|
||||
$.alias,
|
||||
$._atom,
|
||||
$.identifier,
|
||||
$.unary_operator,
|
||||
$.dot,
|
||||
alias($._call_with_parentheses, $.call)
|
||||
)
|
||||
),
|
||||
|
||||
_items_with_trailing_separator: ($) =>
|
||||
seq(
|
||||
choice(
|
||||
seq(sep1($._expression, ","), optional(",")),
|
||||
seq(
|
||||
optional(seq(sep1($._expression, ","), ",")),
|
||||
alias($._keywords_with_trailing_separator, $.keywords)
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
_nullary_operator: ($) =>
|
||||
// Nullary operators don't have any child nodes, so we reuse the
|
||||
// operator_identifier node
|
||||
alias(prec(PREC.RANGE_OP, ".."), $.operator_identifier),
|
||||
|
||||
unary_operator: ($) =>
|
||||
choice(
|
||||
unaryOp($, prec, PREC.CAPTURE_OP, "&", $._capture_expression),
|
||||
unaryOp($, prec, PREC.UNARY_OPS, choice(...UNARY_OPS)),
|
||||
unaryOp($, prec, PREC.AT_OP, "@"),
|
||||
// Capture operand like &1 is a special case with higher precedence
|
||||
unaryOp($, prec, PREC.CAPTURE_OPERAND, "&", $.integer)
|
||||
),
|
||||
|
||||
_capture_expression: ($) =>
|
||||
choice(
|
||||
// Note that block expression is not allowed as capture operand,
|
||||
// so we have an explicit sequence with the parentheses and higher
|
||||
// precedence
|
||||
prec(1, seq("(", $._expression, ")")),
|
||||
$._expression
|
||||
),
|
||||
|
||||
binary_operator: ($) =>
|
||||
choice(
|
||||
binaryOp($, prec.left, PREC.IN_MATCH_OPS, choice(...IN_MATCH_OPS)),
|
||||
binaryOp(
|
||||
$,
|
||||
prec.right,
|
||||
PREC.WHEN_OP,
|
||||
"when",
|
||||
$._expression,
|
||||
choice($._expression, $.keywords)
|
||||
),
|
||||
binaryOp($, prec.right, PREC.TYPE_OP, "::"),
|
||||
binaryOp(
|
||||
$,
|
||||
prec.right,
|
||||
PREC.BAR_OP,
|
||||
"|",
|
||||
$._expression,
|
||||
choice($._expression, $.keywords)
|
||||
),
|
||||
binaryOp($, prec.right, PREC.ASSOC_OP, "=>"),
|
||||
binaryOp($, prec.right, PREC.MATCH_OP, "="),
|
||||
binaryOp($, prec.left, PREC.OR_OPS, choice(...OR_OPS)),
|
||||
binaryOp($, prec.left, PREC.AND_OPS, choice(...AND_OPS)),
|
||||
binaryOp($, prec.left, PREC.COMP_OPS, choice(...COMP_OPS)),
|
||||
binaryOp($, prec.left, PREC.REL_OPS, choice(...REL_OPS)),
|
||||
binaryOp($, prec.left, PREC.ARROW_OPS, choice(...ARROW_OPS)),
|
||||
binaryOp(
|
||||
$,
|
||||
prec.left,
|
||||
PREC.IN_OPS,
|
||||
choice("in", alias($._not_in, "not in"))
|
||||
),
|
||||
binaryOp($, prec.left, PREC.XOR_OP, "^^^"),
|
||||
binaryOp($, prec.right, PREC.TERNARY_OP, "//"),
|
||||
binaryOp($, prec.right, PREC.CONCAT_OPS, choice(...CONCAT_OPS)),
|
||||
binaryOp($, prec.right, PREC.RANGE_OP, ".."),
|
||||
binaryOp($, prec.left, PREC.ADD_OPS, choice(...ADD_OPS)),
|
||||
binaryOp($, prec.left, PREC.MULT_OPS, choice(...MULT_OPS)),
|
||||
binaryOp($, prec.left, PREC.POWER_OP, "**"),
|
||||
// Operator with arity
|
||||
binaryOp(
|
||||
$,
|
||||
prec.left,
|
||||
PREC.MULT_OPS,
|
||||
"/",
|
||||
$.operator_identifier,
|
||||
$.integer
|
||||
)
|
||||
),
|
||||
|
||||
operator_identifier: ($) =>
|
||||
// Operators with the following changes:
|
||||
//
|
||||
// * exclude "=>" since it's not a valid operator identifier
|
||||
// * exclude // since it's only valid after ..
|
||||
// * exclude binary "-" and "+" as they are handled as unary below
|
||||
//
|
||||
// For unary operator identifiers we use the same precedence as
|
||||
// operators, so that we get conflicts and resolve them dynamically
|
||||
// (see grammar.conflicts for more details)
|
||||
choice(
|
||||
// Unary operators
|
||||
prec(PREC.CAPTURE_OP, "&"),
|
||||
prec(PREC.UNARY_OPS, choice(...UNARY_OPS)),
|
||||
prec(PREC.AT_OP, "@"),
|
||||
// Binary operators
|
||||
...IN_MATCH_OPS,
|
||||
"when",
|
||||
"::",
|
||||
"|",
|
||||
"=",
|
||||
...OR_OPS,
|
||||
...AND_OPS,
|
||||
...COMP_OPS,
|
||||
...REL_OPS,
|
||||
...ARROW_OPS,
|
||||
"in",
|
||||
alias($._not_in, "not in"),
|
||||
"^^",
|
||||
...CONCAT_OPS,
|
||||
// The range operator has both a binary and a nullary version.
|
||||
// The nullary version is already parsed as operator_identifier,
|
||||
// so it covers this case
|
||||
// ".."
|
||||
...MULT_OPS,
|
||||
"**",
|
||||
"->",
|
||||
"."
|
||||
),
|
||||
|
||||
dot: ($) =>
|
||||
prec(
|
||||
PREC.DOT_OP,
|
||||
seq(
|
||||
field("left", $._expression),
|
||||
field("operator", "."),
|
||||
field("right", choice($.alias, $.tuple))
|
||||
)
|
||||
),
|
||||
|
||||
call: ($) => choice($._call_without_parentheses, $._call_with_parentheses),
|
||||
|
||||
_call_without_parentheses: ($) =>
|
||||
choice(
|
||||
$._local_call_without_parentheses,
|
||||
$._local_call_just_do_block,
|
||||
$._remote_call_without_parentheses
|
||||
),
|
||||
|
||||
_call_with_parentheses: ($) =>
|
||||
choice(
|
||||
$._local_call_with_parentheses,
|
||||
$._remote_call_with_parentheses,
|
||||
$._anonymous_call,
|
||||
$._double_call
|
||||
),
|
||||
|
||||
// Note, calls have left precedence, so that `do end` block sticks to
|
||||
// the outermost call
|
||||
|
||||
_local_call_without_parentheses: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
field("target", $.identifier),
|
||||
alias($._call_arguments_without_parentheses, $.arguments),
|
||||
optional(seq(optional($._newline_before_do), $.do_block))
|
||||
)
|
||||
),
|
||||
|
||||
_local_call_with_parentheses: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
field("target", $.identifier),
|
||||
alias($._call_arguments_with_parentheses_immediate, $.arguments),
|
||||
optional(seq(optional($._newline_before_do), $.do_block))
|
||||
)
|
||||
),
|
||||
|
||||
_local_call_just_do_block: ($) =>
|
||||
// Lower precedence than identifier, because `foo bar do` is `foo(bar) do end`
|
||||
prec(-1, seq(field("target", $.identifier), $.do_block)),
|
||||
|
||||
_remote_call_without_parentheses: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
field("target", alias($._remote_dot, $.dot)),
|
||||
optional(alias($._call_arguments_without_parentheses, $.arguments)),
|
||||
optional(seq(optional($._newline_before_do), $.do_block))
|
||||
)
|
||||
),
|
||||
|
||||
_remote_call_with_parentheses: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
field("target", alias($._remote_dot, $.dot)),
|
||||
alias($._call_arguments_with_parentheses_immediate, $.arguments),
|
||||
optional(seq(optional($._newline_before_do), $.do_block))
|
||||
)
|
||||
),
|
||||
|
||||
_remote_dot: ($) =>
|
||||
prec(
|
||||
PREC.DOT_OP,
|
||||
seq(
|
||||
field("left", $._expression),
|
||||
field("operator", "."),
|
||||
field(
|
||||
"right",
|
||||
choice(
|
||||
$.identifier,
|
||||
alias(choice(...RESERVED_WORD_TOKENS), $.identifier),
|
||||
$.operator_identifier,
|
||||
alias($._quoted_i_double, $.string),
|
||||
alias($._quoted_i_single, $.charlist)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
_anonymous_call: ($) =>
|
||||
seq(
|
||||
field("target", alias($._anonymous_dot, $.dot)),
|
||||
alias($._call_arguments_with_parentheses, $.arguments)
|
||||
),
|
||||
|
||||
_anonymous_dot: ($) =>
|
||||
prec(
|
||||
PREC.DOT_OP,
|
||||
seq(field("left", $._expression), field("operator", "."))
|
||||
),
|
||||
|
||||
_double_call: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
field(
|
||||
"target",
|
||||
alias(
|
||||
choice(
|
||||
$._local_call_with_parentheses,
|
||||
$._remote_call_with_parentheses,
|
||||
$._anonymous_call
|
||||
),
|
||||
$.call
|
||||
)
|
||||
),
|
||||
alias($._call_arguments_with_parentheses, $.arguments),
|
||||
optional(seq(optional($._newline_before_do), $.do_block))
|
||||
)
|
||||
),
|
||||
|
||||
_call_arguments_with_parentheses: ($) =>
|
||||
seq("(", optional($._call_arguments_with_trailing_separator), ")"),
|
||||
|
||||
_call_arguments_with_parentheses_immediate: ($) =>
|
||||
seq(
|
||||
token.immediate("("),
|
||||
optional($._call_arguments_with_trailing_separator),
|
||||
")"
|
||||
),
|
||||
|
||||
_call_arguments_with_trailing_separator: ($) =>
|
||||
choice(
|
||||
seq(
|
||||
sep1($._expression, ","),
|
||||
optional(
|
||||
seq(",", alias($._keywords_with_trailing_separator, $.keywords))
|
||||
)
|
||||
),
|
||||
alias($._keywords_with_trailing_separator, $.keywords)
|
||||
),
|
||||
|
||||
_call_arguments_without_parentheses: ($) =>
|
||||
// In stab clauses a newline can either separate multiple body expressions
|
||||
// or multiple stab clauses, this falls under the $.body conflict. Given a
|
||||
// multiline stab clause with trailing identifier like `1 -> 1 \n x \n 2 -> x`,
|
||||
// there are two matching interpretations:
|
||||
// * `x` as identifier and `2` as stab argument
|
||||
// * `x 2` call as stab argument
|
||||
// Similarly for `Mod.fun` or `mod.fun` the newline should terminate the call.
|
||||
// Consequently, we reject the second interpretation using dynamic precedence
|
||||
prec.dynamic(
|
||||
-1,
|
||||
// Right precedence, because `fun1 fun2 x, y` is `fun1(fun2(x, y))`
|
||||
prec.right(
|
||||
choice(
|
||||
seq(sep1($._expression, ","), optional(seq(",", $.keywords))),
|
||||
$.keywords
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
do_block: ($) =>
|
||||
seq(
|
||||
callKeywordBlock($, "do"),
|
||||
repeat(
|
||||
choice($.after_block, $.rescue_block, $.catch_block, $.else_block)
|
||||
),
|
||||
"end"
|
||||
),
|
||||
|
||||
after_block: ($) => callKeywordBlock($, "after"),
|
||||
rescue_block: ($) => callKeywordBlock($, "rescue"),
|
||||
catch_block: ($) => callKeywordBlock($, "catch"),
|
||||
else_block: ($) => callKeywordBlock($, "else"),
|
||||
|
||||
access_call: ($) =>
|
||||
prec(
|
||||
PREC.ACCESS,
|
||||
seq(
|
||||
field("target", $._expression),
|
||||
token.immediate("["),
|
||||
field("key", $._expression),
|
||||
"]"
|
||||
)
|
||||
),
|
||||
|
||||
stab_clause: ($) =>
|
||||
// Right precedence, because we want to consume body if any
|
||||
prec.right(
|
||||
seq(
|
||||
optional(field("left", $._stab_clause_left)),
|
||||
field("operator", "->"),
|
||||
optional(field("right", $.body))
|
||||
)
|
||||
),
|
||||
|
||||
_stab_clause_left: ($) =>
|
||||
choice(
|
||||
alias($._stab_clause_arguments_with_parentheses, $.arguments),
|
||||
alias(
|
||||
$._stab_clause_arguments_with_parentheses_with_guard,
|
||||
$.binary_operator
|
||||
),
|
||||
alias($._stab_clause_arguments_without_parentheses, $.arguments),
|
||||
alias(
|
||||
$._stab_clause_arguments_without_parentheses_with_guard,
|
||||
$.binary_operator
|
||||
)
|
||||
),
|
||||
|
||||
_stab_clause_arguments_with_parentheses: ($) =>
|
||||
// Precedence over block expression
|
||||
prec(
|
||||
1,
|
||||
seq(
|
||||
"(",
|
||||
optional(
|
||||
choice(
|
||||
seq(
|
||||
// We need the same expression precedence as below, so that we don't
|
||||
// discard this rule in favour of the one below. We use right precedence,
|
||||
// because in this case we can consume expression until the next comma
|
||||
sep1(prec.right(PREC.WHEN_OP, $._expression), ","),
|
||||
optional(seq(",", $.keywords))
|
||||
),
|
||||
$.keywords
|
||||
)
|
||||
),
|
||||
")"
|
||||
)
|
||||
),
|
||||
|
||||
_stab_clause_arguments_without_parentheses: ($) =>
|
||||
// We give the arguments and expression the same precedence as "when"
|
||||
// binary operator, so that we get conflicts and resolve them dynamically
|
||||
// (see the grammar.conflicts for more details)
|
||||
prec(
|
||||
PREC.WHEN_OP,
|
||||
choice(
|
||||
seq(
|
||||
sep1(prec(PREC.WHEN_OP, $._expression), ","),
|
||||
optional(seq(",", $.keywords))
|
||||
),
|
||||
$.keywords
|
||||
)
|
||||
),
|
||||
|
||||
_stab_clause_arguments_with_parentheses_with_guard: ($) =>
|
||||
seq(
|
||||
field(
|
||||
"left",
|
||||
alias($._stab_clause_arguments_with_parentheses, $.arguments)
|
||||
),
|
||||
field("operator", "when"),
|
||||
field("right", $._expression)
|
||||
),
|
||||
|
||||
_stab_clause_arguments_without_parentheses_with_guard: ($) =>
|
||||
// Given `a when b ->`, the left stab operand can be interpreted either
|
||||
// as a single argument item, or as binary operator with arguments on
|
||||
// the left and guard expression on the right. Using dynamic precedence
|
||||
// we favour the latter interpretation during dynamic conflict resolution
|
||||
prec.dynamic(
|
||||
1,
|
||||
seq(
|
||||
field(
|
||||
"left",
|
||||
alias($._stab_clause_arguments_without_parentheses, $.arguments)
|
||||
),
|
||||
field("operator", "when"),
|
||||
field("right", $._expression)
|
||||
)
|
||||
),
|
||||
|
||||
body: ($) =>
|
||||
choice(
|
||||
$._terminator,
|
||||
seq(
|
||||
optional($._terminator),
|
||||
sep1($._expression, $._terminator),
|
||||
optional($._terminator)
|
||||
)
|
||||
),
|
||||
|
||||
anonymous_function: ($) =>
|
||||
seq(
|
||||
"fn",
|
||||
optional($._terminator),
|
||||
sep1($.stab_clause, $._terminator),
|
||||
"end"
|
||||
),
|
||||
|
||||
// A comment may be anywhere, we give it a lower precedence,
|
||||
// so it doesn't intercept interpolation
|
||||
comment: ($) => token(prec(-1, seq("#", /.*/))),
|
||||
},
|
||||
});
|
||||
|
||||
function sep1(rule, separator) {
|
||||
return seq(rule, repeat(seq(separator, rule)));
|
||||
}
|
||||
|
||||
function unaryOp($, assoc, precedence, operator, right = null) {
|
||||
// Expression such as `x + y` falls under the "expression vs local call"
|
||||
// conflict that we already have. By using dynamic precedence we penalize
|
||||
// unary operator, so `x + y` is interpreted as binary operator (unless
|
||||
// _before_unary_op is tokenized and forces unary operator interpretation)
|
||||
return prec.dynamic(
|
||||
-1,
|
||||
assoc(
|
||||
precedence,
|
||||
seq(
|
||||
optional($._before_unary_op),
|
||||
field("operator", operator),
|
||||
field("operand", right || $._expression)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function binaryOp($, assoc, precedence, operator, left = null, right = null) {
|
||||
return assoc(
|
||||
precedence,
|
||||
seq(
|
||||
field("left", left || $._expression),
|
||||
field("operator", operator),
|
||||
field("right", right || $._expression)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function callKeywordBlock($, start) {
|
||||
return seq(
|
||||
start,
|
||||
optional($._terminator),
|
||||
optional(
|
||||
choice(
|
||||
sep1(choice($.stab_clause), $._terminator),
|
||||
seq(sep1(choice($._expression), $._terminator), optional($._terminator))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function defineQuoted(start, end, name) {
|
||||
return {
|
||||
[`_quoted_i_${name}`]: ($) =>
|
||||
seq(
|
||||
field("quoted_start", start),
|
||||
optional(alias($[`_quoted_content_i_${name}`], $.quoted_content)),
|
||||
repeat(
|
||||
seq(
|
||||
choice($.interpolation, $.escape_sequence),
|
||||
optional(alias($[`_quoted_content_i_${name}`], $.quoted_content))
|
||||
)
|
||||
),
|
||||
field("quoted_end", end)
|
||||
),
|
||||
|
||||
[`_quoted_${name}`]: ($) =>
|
||||
seq(
|
||||
field("quoted_start", start),
|
||||
optional(alias($[`_quoted_content_${name}`], $.quoted_content)),
|
||||
repeat(
|
||||
seq(
|
||||
// The end delimiter may be escaped in non-interpolating strings too
|
||||
$.escape_sequence,
|
||||
optional(alias($[`_quoted_content_${name}`], $.quoted_content))
|
||||
)
|
||||
),
|
||||
field("quoted_end", end)
|
||||
),
|
||||
};
|
||||
}
|
||||
@ -1,406 +0,0 @@
|
||||
{
|
||||
"name": "tree-sitter-elixir",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "tree-sitter-elixir",
|
||||
"version": "0.1.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"nan": "^2.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clang-format": "^1.8.0",
|
||||
"prettier": "^2.3.2",
|
||||
"tree-sitter-cli": "^0.20.7"
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/clang-format": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz",
|
||||
"integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"async": "^3.2.3",
|
||||
"glob": "^7.0.0",
|
||||
"resolve": "^1.1.6"
|
||||
},
|
||||
"bin": {
|
||||
"check-clang-format": "bin/check-clang-format.js",
|
||||
"clang-format": "index.js",
|
||||
"git-clang-format": "bin/git-clang-format"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
|
||||
"integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has": "^1.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
|
||||
"integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
|
||||
"integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.11.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"resolve": "bin/resolve"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"tree-sitter": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
|
||||
"dev": true
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"clang-format": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz",
|
||||
"integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "^3.2.3",
|
||||
"glob": "^7.0.0",
|
||||
"resolve": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
|
||||
"integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
|
||||
"integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
|
||||
"integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-core-module": "^2.11.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"dev": true
|
||||
},
|
||||
"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==",
|
||||
"dev": true
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
{
|
||||
"name": "tree-sitter-elixir",
|
||||
"version": "0.1.0",
|
||||
"description": "Elixir grammar for the tree-sitter parsing library",
|
||||
"main": "bindings/node",
|
||||
"keywords": [
|
||||
"parser",
|
||||
"lexer",
|
||||
"elixir",
|
||||
"tree-sitter"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/elixir-lang/tree-sitter-elixir.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tree-sitter test",
|
||||
"format": "prettier --trailing-comma es5 --write grammar.js && clang-format -i src/scanner.c",
|
||||
"format-check": "prettier --trailing-comma es5 --check grammar.js && cat src/scanner.c | clang-format src/scanner.c | diff src/scanner.c -"
|
||||
},
|
||||
"dependencies": {
|
||||
"nan": "^2.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clang-format": "^1.8.0",
|
||||
"prettier": "^2.3.2",
|
||||
"tree-sitter-cli": "^0.20.7"
|
||||
},
|
||||
"tree-sitter": [
|
||||
{
|
||||
"scope": "source.elixir",
|
||||
"file-types": [
|
||||
"ex",
|
||||
"exs"
|
||||
],
|
||||
"injection-regex": "^(ex|elixir)$"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,199 +0,0 @@
|
||||
; Reserved keywords
|
||||
|
||||
["when" "and" "or" "not" "in" "not in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword
|
||||
|
||||
; Operators
|
||||
|
||||
; * doc string
|
||||
(unary_operator
|
||||
operator: "@" @comment.doc
|
||||
operand: (call
|
||||
target: (identifier) @comment.doc.__attribute__
|
||||
(arguments
|
||||
[
|
||||
(string) @comment.doc
|
||||
(charlist) @comment.doc
|
||||
(sigil
|
||||
quoted_start: _ @comment.doc
|
||||
quoted_end: _ @comment.doc) @comment.doc
|
||||
(boolean) @comment.doc
|
||||
]))
|
||||
(#match? @comment.doc.__attribute__ "^(moduledoc|typedoc|doc)$"))
|
||||
|
||||
; * module attribute
|
||||
(unary_operator
|
||||
operator: "@" @attribute
|
||||
operand: [
|
||||
(identifier) @attribute
|
||||
(call
|
||||
target: (identifier) @attribute)
|
||||
(boolean) @attribute
|
||||
(nil) @attribute
|
||||
])
|
||||
|
||||
; * capture operand
|
||||
(unary_operator
|
||||
operator: "&"
|
||||
operand: (integer) @operator)
|
||||
|
||||
(operator_identifier) @operator
|
||||
|
||||
(unary_operator
|
||||
operator: _ @operator)
|
||||
|
||||
(binary_operator
|
||||
operator: _ @operator)
|
||||
|
||||
(dot
|
||||
operator: _ @operator)
|
||||
|
||||
(stab_clause
|
||||
operator: _ @operator)
|
||||
|
||||
; Literals
|
||||
|
||||
[
|
||||
(boolean)
|
||||
(nil)
|
||||
] @constant
|
||||
|
||||
[
|
||||
(integer)
|
||||
(float)
|
||||
] @number
|
||||
|
||||
(alias) @module
|
||||
|
||||
(call
|
||||
target: (dot
|
||||
left: (atom) @module))
|
||||
|
||||
(char) @constant
|
||||
|
||||
; Quoted content
|
||||
|
||||
(interpolation "#{" @punctuation.special "}" @punctuation.special) @embedded
|
||||
|
||||
(escape_sequence) @string.escape
|
||||
|
||||
[
|
||||
(atom)
|
||||
(quoted_atom)
|
||||
(keyword)
|
||||
(quoted_keyword)
|
||||
] @string.special.symbol
|
||||
|
||||
[
|
||||
(string)
|
||||
(charlist)
|
||||
] @string
|
||||
|
||||
; Note that we explicitly target sigil quoted start/end, so they are not overridden by delimiters
|
||||
|
||||
(sigil
|
||||
(sigil_name) @__name__
|
||||
quoted_start: _ @string
|
||||
quoted_end: _ @string
|
||||
(#match? @__name__ "^[sS]$")) @string
|
||||
|
||||
(sigil
|
||||
(sigil_name) @__name__
|
||||
quoted_start: _ @string.regex
|
||||
quoted_end: _ @string.regex
|
||||
(#match? @__name__ "^[rR]$")) @string.regex
|
||||
|
||||
(sigil
|
||||
(sigil_name) @__name__
|
||||
quoted_start: _ @string.special
|
||||
quoted_end: _ @string.special) @string.special
|
||||
|
||||
; Calls
|
||||
|
||||
; * definition keyword
|
||||
(call
|
||||
target: (identifier) @keyword
|
||||
(#match? @keyword "^(def|defdelegate|defexception|defguard|defguardp|defimpl|defmacro|defmacrop|defmodule|defn|defnp|defoverridable|defp|defprotocol|defstruct)$"))
|
||||
|
||||
; * kernel or special forms keyword
|
||||
(call
|
||||
target: (identifier) @keyword
|
||||
(#match? @keyword "^(alias|case|cond|else|for|if|import|quote|raise|receive|require|reraise|super|throw|try|unless|unquote|unquote_splicing|use|with)$"))
|
||||
|
||||
; * function call
|
||||
(call
|
||||
target: [
|
||||
; local
|
||||
(identifier) @function
|
||||
; remote
|
||||
(dot
|
||||
right: (identifier) @function)
|
||||
])
|
||||
|
||||
; * just identifier in function definition
|
||||
(call
|
||||
target: (identifier) @keyword
|
||||
(arguments
|
||||
[
|
||||
(identifier) @function
|
||||
(binary_operator
|
||||
left: (identifier) @function
|
||||
operator: "when")
|
||||
])
|
||||
(#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$"))
|
||||
|
||||
; * pipe into identifier (definition)
|
||||
(call
|
||||
target: (identifier) @keyword
|
||||
(arguments
|
||||
(binary_operator
|
||||
operator: "|>"
|
||||
right: (identifier) @variable))
|
||||
(#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$"))
|
||||
|
||||
; * pipe into identifier (function call)
|
||||
(binary_operator
|
||||
operator: "|>"
|
||||
right: (identifier) @function)
|
||||
|
||||
; Identifiers
|
||||
|
||||
; * special
|
||||
(
|
||||
(identifier) @constant.builtin
|
||||
(#match? @constant.builtin "^(__MODULE__|__DIR__|__ENV__|__CALLER__|__STACKTRACE__)$")
|
||||
)
|
||||
|
||||
; * unused
|
||||
(
|
||||
(identifier) @comment.unused
|
||||
(#match? @comment.unused "^_")
|
||||
)
|
||||
|
||||
; * regular
|
||||
(identifier) @variable
|
||||
|
||||
; Comment
|
||||
|
||||
(comment) @comment
|
||||
|
||||
; Punctuation
|
||||
|
||||
[
|
||||
"%"
|
||||
] @punctuation
|
||||
|
||||
[
|
||||
","
|
||||
";"
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
"<<"
|
||||
">>"
|
||||
] @punctuation.bracket
|
||||
@ -1,7 +0,0 @@
|
||||
; Phoenix HTML template
|
||||
((sigil
|
||||
(sigil_name) @_sigil_name
|
||||
(quoted_content) @injection.content)
|
||||
(#eq? @_sigil_name "H")
|
||||
(#set! injection.language "heex")
|
||||
(#set! injection.combined))
|
||||
@ -1,54 +0,0 @@
|
||||
; Definitions
|
||||
|
||||
; * modules and protocols
|
||||
(call
|
||||
target: (identifier) @ignore
|
||||
(arguments (alias) @name)
|
||||
(#match? @ignore "^(defmodule|defprotocol)$")) @definition.module
|
||||
|
||||
; * functions/macros
|
||||
(call
|
||||
target: (identifier) @ignore
|
||||
(arguments
|
||||
[
|
||||
; zero-arity functions with no parentheses
|
||||
(identifier) @name
|
||||
; regular function clause
|
||||
(call target: (identifier) @name)
|
||||
; function clause with a guard clause
|
||||
(binary_operator
|
||||
left: (call target: (identifier) @name)
|
||||
operator: "when")
|
||||
])
|
||||
(#match? @ignore "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp)$")) @definition.function
|
||||
|
||||
; References
|
||||
|
||||
; ignore calls to kernel/special-forms keywords
|
||||
(call
|
||||
target: (identifier) @ignore
|
||||
(#match? @ignore "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defmodule|defprotocol|defimpl|defstruct|defexception|defoverridable|alias|case|cond|else|for|if|import|quote|raise|receive|require|reraise|super|throw|try|unless|unquote|unquote_splicing|use|with)$"))
|
||||
|
||||
; ignore module attributes
|
||||
(unary_operator
|
||||
operator: "@"
|
||||
operand: (call
|
||||
target: (identifier) @ignore))
|
||||
|
||||
; * function call
|
||||
(call
|
||||
target: [
|
||||
; local
|
||||
(identifier) @name
|
||||
; remote
|
||||
(dot
|
||||
right: (identifier) @name)
|
||||
]) @reference.call
|
||||
|
||||
; * pipe into function call
|
||||
(binary_operator
|
||||
operator: "|>"
|
||||
right: (identifier) @name) @reference.call
|
||||
|
||||
; * modules
|
||||
(alias) @name @reference.module
|
||||
@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
print_usage_and_exit() {
|
||||
echo "Usage: $0"
|
||||
echo ""
|
||||
echo "Runs the parser against a predefined list of popular Elixir repositories"
|
||||
echo ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -ne 0 ]; then
|
||||
print_usage_and_exit
|
||||
fi
|
||||
|
||||
repos="elixir-lang/elixir elixir-lang/ex_doc elixir-plug/plug elixir-ecto/ecto dashbitco/broadway elixir-nx/nx elixir-nx/axon livebook-dev/livebook"
|
||||
|
||||
for repo in $repos; do
|
||||
./scripts/parse_repo.sh $repo
|
||||
done
|
||||
@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
print_usage_and_exit() {
|
||||
echo "Usage: $0 <github-repo>"
|
||||
echo ""
|
||||
echo "Clones the given repository and runs the parser against all Elixir files"
|
||||
echo ""
|
||||
echo "## Examples"
|
||||
echo ""
|
||||
echo " $0 elixir-lang/elixir"
|
||||
echo ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
print_usage_and_exit
|
||||
fi
|
||||
|
||||
gh_repo="$1"
|
||||
|
||||
dir="tmp/gh/${gh_repo//[\/-]/_}"
|
||||
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
mkdir -p "$(dirname "$dir")"
|
||||
git clone --depth 1 "https://github.com/$gh_repo.git" "$dir"
|
||||
fi
|
||||
|
||||
echo "Running parser against $gh_repo"
|
||||
|
||||
npx tree-sitter parse --quiet --stat "$dir/**/*.ex*"
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,636 +0,0 @@
|
||||
#include <tree_sitter/parser.h>
|
||||
|
||||
// See references in grammar.externals
|
||||
enum TokenType {
|
||||
QUOTED_CONTENT_I_SINGLE,
|
||||
QUOTED_CONTENT_I_DOUBLE,
|
||||
QUOTED_CONTENT_I_HEREDOC_SINGLE,
|
||||
QUOTED_CONTENT_I_HEREDOC_DOUBLE,
|
||||
QUOTED_CONTENT_I_PARENTHESIS,
|
||||
QUOTED_CONTENT_I_CURLY,
|
||||
QUOTED_CONTENT_I_SQUARE,
|
||||
QUOTED_CONTENT_I_ANGLE,
|
||||
QUOTED_CONTENT_I_BAR,
|
||||
QUOTED_CONTENT_I_SLASH,
|
||||
QUOTED_CONTENT_SINGLE,
|
||||
QUOTED_CONTENT_DOUBLE,
|
||||
QUOTED_CONTENT_HEREDOC_SINGLE,
|
||||
QUOTED_CONTENT_HEREDOC_DOUBLE,
|
||||
QUOTED_CONTENT_PARENTHESIS,
|
||||
QUOTED_CONTENT_CURLY,
|
||||
QUOTED_CONTENT_SQUARE,
|
||||
QUOTED_CONTENT_ANGLE,
|
||||
QUOTED_CONTENT_BAR,
|
||||
QUOTED_CONTENT_SLASH,
|
||||
|
||||
NEWLINE_BEFORE_DO,
|
||||
NEWLINE_BEFORE_BINARY_OPERATOR,
|
||||
NEWLINE_BEFORE_COMMENT,
|
||||
|
||||
BEFORE_UNARY_OPERATOR,
|
||||
|
||||
NOT_IN,
|
||||
|
||||
QUOTED_ATOM_START
|
||||
};
|
||||
|
||||
static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
|
||||
|
||||
static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
|
||||
|
||||
// Note: some checks require several lexer steps of lookahead
|
||||
// and alter its state, for these we use names check_*
|
||||
|
||||
static inline bool is_whitespace(int32_t c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
|
||||
}
|
||||
|
||||
static inline bool is_inline_whitespace(int32_t c) {
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
static inline bool is_newline(int32_t c) {
|
||||
// Note: this implies \r\n is treated as two line breaks,
|
||||
// but in our case it's fine, since multiple line breaks
|
||||
// make no difference
|
||||
return c == '\n' || c == '\r';
|
||||
}
|
||||
|
||||
static inline bool is_digit(int32_t c) { return '0' <= c && c <= '9'; }
|
||||
|
||||
static inline bool check_keyword_end(TSLexer *lexer) {
|
||||
if (lexer->lookahead == ':') {
|
||||
advance(lexer);
|
||||
return is_whitespace(lexer->lookahead);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool check_operator_end(TSLexer *lexer) {
|
||||
// Keyword
|
||||
if (lexer->lookahead == ':') {
|
||||
return !check_keyword_end(lexer);
|
||||
}
|
||||
while (is_inline_whitespace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
}
|
||||
// Operator identifier with arity
|
||||
if (lexer->lookahead == '/') {
|
||||
advance(lexer);
|
||||
while (is_whitespace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
}
|
||||
if (is_digit(lexer->lookahead)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char token_terminators[] = {
|
||||
// Operator starts
|
||||
'@', '.', '+', '-', '^', '-', '*', '/', '<', '>', '|', '~', '=', '&', '\\',
|
||||
'%',
|
||||
// Delimiters
|
||||
'{', '}', '[', ']', '(', ')', '"', '\'',
|
||||
// Separators
|
||||
',', ';',
|
||||
// Comment
|
||||
'#'};
|
||||
|
||||
const uint8_t token_terminators_length =
|
||||
sizeof(token_terminators) / sizeof(char);
|
||||
|
||||
// Note: this is a heuristic as we only use this to distinguish word
|
||||
// operators and we don't want to include complex Unicode ranges
|
||||
static inline bool is_token_end(int32_t c) {
|
||||
for (uint8_t i = 0; i < token_terminators_length; i++) {
|
||||
if (c == token_terminators[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return is_whitespace(c);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const enum TokenType token_type;
|
||||
const bool supports_interpol;
|
||||
const int32_t end_delimiter;
|
||||
const uint8_t delimiter_length;
|
||||
} QuotedContentInfo;
|
||||
|
||||
const QuotedContentInfo quoted_content_infos[] = {
|
||||
{QUOTED_CONTENT_I_SINGLE, true, '\'', 1},
|
||||
{QUOTED_CONTENT_I_DOUBLE, true, '"', 1},
|
||||
{QUOTED_CONTENT_I_HEREDOC_SINGLE, true, '\'', 3},
|
||||
{QUOTED_CONTENT_I_HEREDOC_DOUBLE, true, '"', 3},
|
||||
{QUOTED_CONTENT_I_PARENTHESIS, true, ')', 1},
|
||||
{QUOTED_CONTENT_I_CURLY, true, '}', 1},
|
||||
{QUOTED_CONTENT_I_SQUARE, true, ']', 1},
|
||||
{QUOTED_CONTENT_I_ANGLE, true, '>', 1},
|
||||
{QUOTED_CONTENT_I_BAR, true, '|', 1},
|
||||
{QUOTED_CONTENT_I_SLASH, true, '/', 1},
|
||||
{QUOTED_CONTENT_SINGLE, false, '\'', 1},
|
||||
{QUOTED_CONTENT_DOUBLE, false, '"', 1},
|
||||
{QUOTED_CONTENT_HEREDOC_SINGLE, false, '\'', 3},
|
||||
{QUOTED_CONTENT_HEREDOC_DOUBLE, false, '"', 3},
|
||||
{QUOTED_CONTENT_PARENTHESIS, false, ')', 1},
|
||||
{QUOTED_CONTENT_CURLY, false, '}', 1},
|
||||
{QUOTED_CONTENT_SQUARE, false, ']', 1},
|
||||
{QUOTED_CONTENT_ANGLE, false, '>', 1},
|
||||
{QUOTED_CONTENT_BAR, false, '|', 1},
|
||||
{QUOTED_CONTENT_SLASH, false, '/', 1},
|
||||
};
|
||||
|
||||
const uint8_t quoted_content_infos_length =
|
||||
sizeof(quoted_content_infos) / sizeof(QuotedContentInfo);
|
||||
|
||||
static inline int8_t find_quoted_token_info(const bool *valid_symbols) {
|
||||
// Quoted tokens are mutually exclusive and only one should be valid
|
||||
// at a time. If multiple are valid it means we parse an arbitrary
|
||||
// code outside quotes, in which case we don't want to tokenize it as
|
||||
// quoted content.
|
||||
if (valid_symbols[QUOTED_CONTENT_I_SINGLE] &&
|
||||
valid_symbols[QUOTED_CONTENT_I_DOUBLE]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < quoted_content_infos_length; i++) {
|
||||
if (valid_symbols[quoted_content_infos[i].token_type]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool scan_quoted_content(TSLexer *lexer, const QuotedContentInfo *info) {
|
||||
lexer->result_symbol = info->token_type;
|
||||
|
||||
bool is_heredoc = (info->delimiter_length == 3);
|
||||
|
||||
for (bool has_content = false; true; has_content = true) {
|
||||
bool newline = false;
|
||||
|
||||
if (is_newline(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
|
||||
has_content = true;
|
||||
newline = true;
|
||||
|
||||
while (is_whitespace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
}
|
||||
}
|
||||
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
if (lexer->lookahead == info->end_delimiter) {
|
||||
uint8_t length = 1;
|
||||
|
||||
while (length < info->delimiter_length) {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == info->end_delimiter) {
|
||||
length++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (length == info->delimiter_length && (!is_heredoc || newline)) {
|
||||
return has_content;
|
||||
}
|
||||
} else {
|
||||
if (lexer->lookahead == '#') {
|
||||
advance(lexer);
|
||||
if (info->supports_interpol && lexer->lookahead == '{') {
|
||||
return has_content;
|
||||
}
|
||||
} else if (lexer->lookahead == '\\') {
|
||||
advance(lexer);
|
||||
if (is_heredoc && lexer->lookahead == '\n') {
|
||||
// We need to know about the newline to correctly recognise
|
||||
// heredoc end delimiter, so we intentionally ignore
|
||||
// escaping
|
||||
} else if (info->supports_interpol ||
|
||||
lexer->lookahead == info->end_delimiter) {
|
||||
return has_content;
|
||||
}
|
||||
} else if (lexer->lookahead == '\0') {
|
||||
// If we reached the end of the file, this means there is no
|
||||
// end delimiter, so the syntax is invalid. In that case we
|
||||
// want to treat all the scanned content as quoted content.
|
||||
return has_content;
|
||||
} else {
|
||||
advance(lexer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool scan_newline(TSLexer *lexer, const bool *valid_symbols) {
|
||||
advance(lexer);
|
||||
|
||||
while (is_whitespace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
// Note we include all the whitespace after newline, so that the
|
||||
// parser doesn't have to go through it again
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
if (lexer->lookahead == '#') {
|
||||
lexer->result_symbol = NEWLINE_BEFORE_COMMENT;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lexer->lookahead == 'd' && valid_symbols[NEWLINE_BEFORE_DO]) {
|
||||
lexer->result_symbol = NEWLINE_BEFORE_DO;
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'o') {
|
||||
advance(lexer);
|
||||
return is_token_end(lexer->lookahead);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (valid_symbols[NEWLINE_BEFORE_BINARY_OPERATOR]) {
|
||||
lexer->result_symbol = NEWLINE_BEFORE_BINARY_OPERATOR;
|
||||
|
||||
// &&, &&&
|
||||
if (lexer->lookahead == '&') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '&') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '&') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
}
|
||||
// =, ==, ===, =~, =>
|
||||
} else if (lexer->lookahead == '=') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '=') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '=') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
} else if (lexer->lookahead == '~') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// ::
|
||||
} else if (lexer->lookahead == ':') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == ':') {
|
||||
advance(lexer);
|
||||
// Ignore ::: atom
|
||||
if (lexer->lookahead == ':')
|
||||
return false;
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// ++, +++
|
||||
} else if (lexer->lookahead == '+') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '+') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '+') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
}
|
||||
// --, ---, ->
|
||||
} else if (lexer->lookahead == '-') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '-') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '-') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
} else if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// <, <=, <-, <>, <~, <~>, <|>, <<<, <<~
|
||||
} else if (lexer->lookahead == '<') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '=' || lexer->lookahead == '-' ||
|
||||
lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else if (lexer->lookahead == '~') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
} else if (lexer->lookahead == '|') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
} else if (lexer->lookahead == '<') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '<' || lexer->lookahead == '~') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// >, >=, >>>
|
||||
} else if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '=') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// ^^^
|
||||
} else if (lexer->lookahead == '^') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '^') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '^') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
}
|
||||
// !=, !==
|
||||
} else if (lexer->lookahead == '!') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '=') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '=') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
}
|
||||
// ~>, ~>>
|
||||
} else if (lexer->lookahead == '~') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
}
|
||||
// |, ||, |||, |>
|
||||
} else if (lexer->lookahead == '|') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '|') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '|') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
} else if (lexer->lookahead == '>') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// *, **
|
||||
} else if (lexer->lookahead == '*') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '*') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// / //
|
||||
} else if (lexer->lookahead == '/') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '/') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// ., ..
|
||||
} else if (lexer->lookahead == '.') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '.') {
|
||||
advance(lexer);
|
||||
// Ignore ... identifier
|
||||
if (lexer->lookahead == '.')
|
||||
return false;
|
||||
return check_operator_end(lexer);
|
||||
} else {
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
// double slash
|
||||
} else if (lexer->lookahead == '\\') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '\\') {
|
||||
advance(lexer);
|
||||
return check_operator_end(lexer);
|
||||
}
|
||||
} else if (lexer->lookahead == 'w') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'h') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'e') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'n') {
|
||||
advance(lexer);
|
||||
return is_token_end(lexer->lookahead) && check_operator_end(lexer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (lexer->lookahead == 'a') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'n') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'd') {
|
||||
advance(lexer);
|
||||
return is_token_end(lexer->lookahead) && check_operator_end(lexer);
|
||||
}
|
||||
}
|
||||
// or
|
||||
} else if (lexer->lookahead == 'o') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'r') {
|
||||
advance(lexer);
|
||||
return is_token_end(lexer->lookahead) && check_operator_end(lexer);
|
||||
}
|
||||
// in
|
||||
} else if (lexer->lookahead == 'i') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'n') {
|
||||
advance(lexer);
|
||||
return is_token_end(lexer->lookahead) && check_operator_end(lexer);
|
||||
}
|
||||
// not in
|
||||
} else if (lexer->lookahead == 'n') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'o') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 't') {
|
||||
advance(lexer);
|
||||
while (is_inline_whitespace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
}
|
||||
if (lexer->lookahead == 'i') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'n') {
|
||||
advance(lexer);
|
||||
return is_token_end(lexer->lookahead) &&
|
||||
check_operator_end(lexer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool scan(TSLexer *lexer, const bool *valid_symbols) {
|
||||
int8_t quoted_content_info_idx = find_quoted_token_info(valid_symbols);
|
||||
|
||||
// Quoted content, which matches any character except for close
|
||||
// delimiters, escapes and interpolations
|
||||
if (quoted_content_info_idx != -1) {
|
||||
const QuotedContentInfo info =
|
||||
quoted_content_infos[quoted_content_info_idx];
|
||||
return scan_quoted_content(lexer, &info);
|
||||
}
|
||||
|
||||
bool skipped_whitespace = false;
|
||||
|
||||
while (is_inline_whitespace(lexer->lookahead)) {
|
||||
skipped_whitespace = true;
|
||||
skip(lexer);
|
||||
}
|
||||
|
||||
// Newline, which is either tokenized as a special newline or ignored
|
||||
if (is_newline(lexer->lookahead) &&
|
||||
(valid_symbols[NEWLINE_BEFORE_DO] ||
|
||||
valid_symbols[NEWLINE_BEFORE_BINARY_OPERATOR] ||
|
||||
valid_symbols[NEWLINE_BEFORE_COMMENT])) {
|
||||
return scan_newline(lexer, valid_symbols);
|
||||
}
|
||||
|
||||
// before unary +
|
||||
if (lexer->lookahead == '+') {
|
||||
if (skipped_whitespace && valid_symbols[BEFORE_UNARY_OPERATOR]) {
|
||||
lexer->mark_end(lexer);
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '+' || lexer->lookahead == ':' ||
|
||||
lexer->lookahead == '/') {
|
||||
return false;
|
||||
}
|
||||
if (is_whitespace(lexer->lookahead)) {
|
||||
return false;
|
||||
}
|
||||
lexer->result_symbol = BEFORE_UNARY_OPERATOR;
|
||||
return true;
|
||||
}
|
||||
// before unary -
|
||||
} else if (lexer->lookahead == '-') {
|
||||
if (skipped_whitespace && valid_symbols[BEFORE_UNARY_OPERATOR]) {
|
||||
lexer->mark_end(lexer);
|
||||
lexer->result_symbol = BEFORE_UNARY_OPERATOR;
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == '-' || lexer->lookahead == '>' ||
|
||||
lexer->lookahead == ':' || lexer->lookahead == '/') {
|
||||
return false;
|
||||
}
|
||||
if (is_whitespace(lexer->lookahead)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// not in
|
||||
} else if (lexer->lookahead == 'n') {
|
||||
if (valid_symbols[NOT_IN]) {
|
||||
lexer->result_symbol = NOT_IN;
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'o') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 't') {
|
||||
advance(lexer);
|
||||
while (is_inline_whitespace(lexer->lookahead)) {
|
||||
advance(lexer);
|
||||
}
|
||||
if (lexer->lookahead == 'i') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead == 'n') {
|
||||
advance(lexer);
|
||||
return is_token_end(lexer->lookahead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// quoted atom start
|
||||
} else if (lexer->lookahead == ':') {
|
||||
if (valid_symbols[QUOTED_ATOM_START]) {
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
lexer->result_symbol = QUOTED_ATOM_START;
|
||||
if (lexer->lookahead == '"' || lexer->lookahead == '\'') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void *tree_sitter_elixir_external_scanner_create() { return NULL; }
|
||||
|
||||
bool tree_sitter_elixir_external_scanner_scan(void *payload, TSLexer *lexer,
|
||||
const bool *valid_symbols) {
|
||||
return scan(lexer, valid_symbols);
|
||||
}
|
||||
|
||||
unsigned tree_sitter_elixir_external_scanner_serialize(void *payload,
|
||||
char *buffer) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tree_sitter_elixir_external_scanner_deserialize(void *payload,
|
||||
const char *buffer,
|
||||
unsigned length) {}
|
||||
|
||||
void tree_sitter_elixir_external_scanner_destroy(void *payload) {}
|
||||
@ -1,224 +0,0 @@
|
||||
#ifndef TREE_SITTER_PARSER_H_
|
||||
#define TREE_SITTER_PARSER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ts_builtin_sym_error ((TSSymbol)-1)
|
||||
#define ts_builtin_sym_end 0
|
||||
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
|
||||
|
||||
typedef uint16_t TSStateId;
|
||||
|
||||
#ifndef TREE_SITTER_API_H_
|
||||
typedef uint16_t TSSymbol;
|
||||
typedef uint16_t TSFieldId;
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
TSFieldId field_id;
|
||||
uint8_t child_index;
|
||||
bool inherited;
|
||||
} TSFieldMapEntry;
|
||||
|
||||
typedef struct {
|
||||
uint16_t index;
|
||||
uint16_t length;
|
||||
} TSFieldMapSlice;
|
||||
|
||||
typedef struct {
|
||||
bool visible;
|
||||
bool named;
|
||||
bool supertype;
|
||||
} TSSymbolMetadata;
|
||||
|
||||
typedef struct TSLexer TSLexer;
|
||||
|
||||
struct TSLexer {
|
||||
int32_t lookahead;
|
||||
TSSymbol result_symbol;
|
||||
void (*advance)(TSLexer *, bool);
|
||||
void (*mark_end)(TSLexer *);
|
||||
uint32_t (*get_column)(TSLexer *);
|
||||
bool (*is_at_included_range_start)(const TSLexer *);
|
||||
bool (*eof)(const TSLexer *);
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
TSParseActionTypeShift,
|
||||
TSParseActionTypeReduce,
|
||||
TSParseActionTypeAccept,
|
||||
TSParseActionTypeRecover,
|
||||
} TSParseActionType;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t type;
|
||||
TSStateId state;
|
||||
bool extra;
|
||||
bool repetition;
|
||||
} shift;
|
||||
struct {
|
||||
uint8_t type;
|
||||
uint8_t child_count;
|
||||
TSSymbol symbol;
|
||||
int16_t dynamic_precedence;
|
||||
uint16_t production_id;
|
||||
} reduce;
|
||||
uint8_t type;
|
||||
} TSParseAction;
|
||||
|
||||
typedef struct {
|
||||
uint16_t lex_state;
|
||||
uint16_t external_lex_state;
|
||||
} TSLexMode;
|
||||
|
||||
typedef union {
|
||||
TSParseAction action;
|
||||
struct {
|
||||
uint8_t count;
|
||||
bool reusable;
|
||||
} entry;
|
||||
} TSParseActionEntry;
|
||||
|
||||
struct TSLanguage {
|
||||
uint32_t version;
|
||||
uint32_t symbol_count;
|
||||
uint32_t alias_count;
|
||||
uint32_t token_count;
|
||||
uint32_t external_token_count;
|
||||
uint32_t state_count;
|
||||
uint32_t large_state_count;
|
||||
uint32_t production_id_count;
|
||||
uint32_t field_count;
|
||||
uint16_t max_alias_sequence_length;
|
||||
const uint16_t *parse_table;
|
||||
const uint16_t *small_parse_table;
|
||||
const uint32_t *small_parse_table_map;
|
||||
const TSParseActionEntry *parse_actions;
|
||||
const char * const *symbol_names;
|
||||
const char * const *field_names;
|
||||
const TSFieldMapSlice *field_map_slices;
|
||||
const TSFieldMapEntry *field_map_entries;
|
||||
const TSSymbolMetadata *symbol_metadata;
|
||||
const TSSymbol *public_symbol_map;
|
||||
const uint16_t *alias_map;
|
||||
const TSSymbol *alias_sequences;
|
||||
const TSLexMode *lex_modes;
|
||||
bool (*lex_fn)(TSLexer *, TSStateId);
|
||||
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
||||
TSSymbol keyword_capture_token;
|
||||
struct {
|
||||
const bool *states;
|
||||
const TSSymbol *symbol_map;
|
||||
void *(*create)(void);
|
||||
void (*destroy)(void *);
|
||||
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
|
||||
unsigned (*serialize)(void *, char *);
|
||||
void (*deserialize)(void *, const char *, unsigned);
|
||||
} external_scanner;
|
||||
const TSStateId *primary_state_ids;
|
||||
};
|
||||
|
||||
/*
|
||||
* Lexer Macros
|
||||
*/
|
||||
|
||||
#define START_LEXER() \
|
||||
bool result = false; \
|
||||
bool skip = false; \
|
||||
bool eof = false; \
|
||||
int32_t lookahead; \
|
||||
goto start; \
|
||||
next_state: \
|
||||
lexer->advance(lexer, skip); \
|
||||
start: \
|
||||
skip = false; \
|
||||
lookahead = lexer->lookahead;
|
||||
|
||||
#define ADVANCE(state_value) \
|
||||
{ \
|
||||
state = state_value; \
|
||||
goto next_state; \
|
||||
}
|
||||
|
||||
#define SKIP(state_value) \
|
||||
{ \
|
||||
skip = true; \
|
||||
state = state_value; \
|
||||
goto next_state; \
|
||||
}
|
||||
|
||||
#define ACCEPT_TOKEN(symbol_value) \
|
||||
result = true; \
|
||||
lexer->result_symbol = symbol_value; \
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
#define END_STATE() return result;
|
||||
|
||||
/*
|
||||
* Parse Table Macros
|
||||
*/
|
||||
|
||||
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
|
||||
|
||||
#define STATE(id) id
|
||||
|
||||
#define ACTIONS(id) id
|
||||
|
||||
#define SHIFT(state_value) \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.state = state_value \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define SHIFT_REPEAT(state_value) \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.state = state_value, \
|
||||
.repetition = true \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define SHIFT_EXTRA() \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.extra = true \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define REDUCE(symbol_val, child_count_val, ...) \
|
||||
{{ \
|
||||
.reduce = { \
|
||||
.type = TSParseActionTypeReduce, \
|
||||
.symbol = symbol_val, \
|
||||
.child_count = child_count_val, \
|
||||
__VA_ARGS__ \
|
||||
}, \
|
||||
}}
|
||||
|
||||
#define RECOVER() \
|
||||
{{ \
|
||||
.type = TSParseActionTypeRecover \
|
||||
}}
|
||||
|
||||
#define ACCEPT_INPUT() \
|
||||
{{ \
|
||||
.type = TSParseActionTypeAccept \
|
||||
}}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_PARSER_H_
|
||||
@ -1,97 +0,0 @@
|
||||
=====================================
|
||||
empty
|
||||
=====================================
|
||||
|
||||
#
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(comment))
|
||||
|
||||
=====================================
|
||||
single line
|
||||
=====================================
|
||||
|
||||
# single comment
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(comment))
|
||||
|
||||
=====================================
|
||||
multiple start symbols
|
||||
=====================================
|
||||
|
||||
### multiple "#"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(comment))
|
||||
|
||||
=====================================
|
||||
many consecutive lines
|
||||
=====================================
|
||||
|
||||
# many
|
||||
# consecutive
|
||||
1
|
||||
# lines
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(comment)
|
||||
(comment)
|
||||
(integer)
|
||||
(comment))
|
||||
|
||||
=====================================
|
||||
in the same line as regular code
|
||||
=====================================
|
||||
|
||||
1 # comment
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(integer)
|
||||
(comment))
|
||||
|
||||
=====================================
|
||||
matches inside a nested structure
|
||||
=====================================
|
||||
|
||||
[ 1 ## inside a list
|
||||
, { 2 # and a tuple, too!
|
||||
, 3 }
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(integer)
|
||||
(comment)
|
||||
(tuple
|
||||
(integer)
|
||||
(comment)
|
||||
(integer))))
|
||||
|
||||
=====================================
|
||||
does not match inside a string
|
||||
=====================================
|
||||
|
||||
"# string"
|
||||
"this is #{interpolation}"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation (identifier))))
|
||||
@ -1,939 +0,0 @@
|
||||
=====================================
|
||||
call without arguments
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
a
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
call with arguments in parentheses
|
||||
=====================================
|
||||
|
||||
fun(a, b) do
|
||||
c
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
call with arguments without parentheses
|
||||
=====================================
|
||||
|
||||
fun a, b do
|
||||
c
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
remote call
|
||||
=====================================
|
||||
|
||||
Mod.fun do
|
||||
a
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
sticks to the outermost call
|
||||
=====================================
|
||||
|
||||
outer_fun inner_fun arg do
|
||||
a
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
newline before do
|
||||
=====================================
|
||||
|
||||
fun x
|
||||
do
|
||||
x
|
||||
end
|
||||
|
||||
fun x
|
||||
# comment
|
||||
do
|
||||
x
|
||||
end
|
||||
|
||||
fun()
|
||||
do
|
||||
x
|
||||
end
|
||||
|
||||
Mod.fun x
|
||||
do
|
||||
x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))
|
||||
(do_block
|
||||
(identifier)))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))
|
||||
(comment)
|
||||
(do_block
|
||||
(identifier)))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments)
|
||||
(do_block
|
||||
(identifier)))
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
stab clause / no arguments
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
() -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments)
|
||||
(body
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / no arguments without parentheses
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
-> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(body
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / one argument
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / many arguments
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x, y, 1 -> :ok
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier)
|
||||
(integer))
|
||||
(body
|
||||
(atom))))))
|
||||
|
||||
=====================================
|
||||
stab clause / arguments in parentheses
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
(x, y) -> :ok
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(body
|
||||
(atom))))))
|
||||
|
||||
=====================================
|
||||
stab clause / many clauses
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
1 -> :yes
|
||||
2 -> :no
|
||||
other -> :maybe
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(atom)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(atom)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(atom))))))
|
||||
|
||||
=====================================
|
||||
stab clause / multiline expression
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x ->
|
||||
y
|
||||
x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / with guard / no arguments
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
() when node() == :nonode@nohost -> true
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments)
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))
|
||||
(atom)))
|
||||
(body
|
||||
(boolean))))))
|
||||
|
||||
=====================================
|
||||
stab clause / with guard / one argument
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x when x == [] -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list)))
|
||||
(body
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / with guard / multiple arguments
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x, y when x == [] -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list)))
|
||||
(body
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / with guard / arguments in parentheses
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
(x, y) when y == [] -> y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list)))
|
||||
(body
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / with guard / multiple guards
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x when x > 10 when x < 5 -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer))))
|
||||
(body
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / edge cases / no stab
|
||||
=====================================
|
||||
|
||||
foo do
|
||||
a when a
|
||||
end
|
||||
|
||||
foo do
|
||||
([])
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(block
|
||||
(list)))))
|
||||
|
||||
=====================================
|
||||
stab clause / edge cases / "when" in arguments
|
||||
=====================================
|
||||
|
||||
foo do
|
||||
a when b, c when d == e -> 1
|
||||
(a, a when b) -> 1
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(body
|
||||
(integer)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(body
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
stab clause / edge cases / block argument
|
||||
=====================================
|
||||
|
||||
foo do
|
||||
(x; y) -> 1
|
||||
((x; y)) -> 1
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(block
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(body
|
||||
(integer)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(block
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(body
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
stab clause / edge cases / operator with lower precedence than "when"
|
||||
=====================================
|
||||
|
||||
foo do
|
||||
x <- y when x -> y
|
||||
end
|
||||
|
||||
foo do
|
||||
(x <- y) when x -> y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(body
|
||||
(identifier)))))
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(identifier))
|
||||
(body
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
stab clause / edge cases / empty
|
||||
=====================================
|
||||
|
||||
fun do->end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause))))
|
||||
|
||||
|
||||
=====================================
|
||||
stab clause / edge cases / trailing call in multiline clause
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
1 ->
|
||||
1
|
||||
x
|
||||
|
||||
1 ->
|
||||
1
|
||||
end
|
||||
|
||||
fun do
|
||||
1 ->
|
||||
1
|
||||
Mod.fun
|
||||
|
||||
1 ->
|
||||
1
|
||||
end
|
||||
|
||||
fun do
|
||||
1 ->
|
||||
1
|
||||
mod.fun
|
||||
|
||||
1 ->
|
||||
1
|
||||
end
|
||||
|
||||
fun do
|
||||
1 ->
|
||||
1
|
||||
|
||||
x 1 ->
|
||||
1
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(integer)
|
||||
(identifier)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(integer)))))
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(integer)
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier)))))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(integer)))))
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(integer)
|
||||
(call
|
||||
(dot
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(integer)))))
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(integer)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(integer))))
|
||||
(body
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
stab clause / edge cases / empty right-hand-side
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x ->
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body)))))
|
||||
|
||||
=====================================
|
||||
pattern matching
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
[h | tail] -> {h, tail}
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(list
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(body
|
||||
(tuple
|
||||
(identifier)
|
||||
(identifier)))))))
|
||||
|
||||
=====================================
|
||||
child blocks / after
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x
|
||||
after
|
||||
y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier)
|
||||
(after_block
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
child blocks / catch
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x
|
||||
catch
|
||||
y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier)
|
||||
(catch_block
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
child blocks / else
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x
|
||||
else
|
||||
y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier)
|
||||
(else_block
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
child blocks / rescue
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x
|
||||
rescue
|
||||
y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier)
|
||||
(rescue_block
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
child blocks / duplicated
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x
|
||||
after
|
||||
y
|
||||
after
|
||||
z
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier)
|
||||
(after_block
|
||||
(identifier))
|
||||
(after_block
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
child blocks / mixed
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x
|
||||
else
|
||||
y
|
||||
after
|
||||
z
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier)
|
||||
(else_block
|
||||
(identifier))
|
||||
(after_block
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
child blocks / stab clause
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x
|
||||
rescue
|
||||
y -> y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier)
|
||||
(rescue_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)))))))
|
||||
|
||||
=====================================
|
||||
child blocks / keyword pattern with child block start token
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x
|
||||
after
|
||||
after
|
||||
after: 1 -> y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(identifier)
|
||||
(after_block)
|
||||
(after_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))
|
||||
(body
|
||||
(identifier)))))))
|
||||
|
||||
=====================================
|
||||
[field names]
|
||||
=====================================
|
||||
|
||||
fun do
|
||||
x -> x
|
||||
x when x == [] -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
target: (identifier)
|
||||
(do_block
|
||||
(stab_clause
|
||||
left: (arguments
|
||||
(identifier))
|
||||
right: (body
|
||||
(identifier)))
|
||||
(stab_clause
|
||||
left: (binary_operator
|
||||
left: (arguments
|
||||
(identifier))
|
||||
right: (binary_operator
|
||||
left: (identifier)
|
||||
right: (list)))
|
||||
right: (body
|
||||
(identifier))))))
|
||||
@ -1,118 +0,0 @@
|
||||
=====================================
|
||||
operator with arity (valid and supported by IEx.Helpers.h)
|
||||
=====================================
|
||||
|
||||
::/2
|
||||
@ / 1
|
||||
& / 1
|
||||
not / 1
|
||||
not in / 2
|
||||
* / 2
|
||||
h +/2
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
stab and slash ambiguity
|
||||
=====================================
|
||||
|
||||
(-> / 2)
|
||||
(-> / / 2)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer)))
|
||||
(block
|
||||
(stab_clause
|
||||
(body
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
unary operator and slash ambiguity
|
||||
=====================================
|
||||
|
||||
& / 2
|
||||
& / / 2
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))))
|
||||
|
||||
=====================================
|
||||
map with identifiers
|
||||
=====================================
|
||||
|
||||
%{a}
|
||||
%{a, b}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(map_content
|
||||
(identifier)))
|
||||
(map
|
||||
(map_content
|
||||
(identifier)
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
def with remote call
|
||||
=====================================
|
||||
|
||||
def Mod.fun(x), do: 1
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier)))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
@ -1,311 +0,0 @@
|
||||
=====================================
|
||||
no arguments
|
||||
=====================================
|
||||
|
||||
fn() -> 1 end
|
||||
fn () -> 1 end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments)
|
||||
(body
|
||||
(integer))))
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments)
|
||||
(body
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
no arguments without parentheses
|
||||
=====================================
|
||||
|
||||
fn -> 1 end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(body
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
one argument
|
||||
=====================================
|
||||
|
||||
fn(x) -> x end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
one argument without parentheses
|
||||
=====================================
|
||||
|
||||
fn x -> x end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
many arguments
|
||||
=====================================
|
||||
|
||||
fn(x, y, z) -> x + y end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier))
|
||||
(body
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
many arguments without parentheses
|
||||
=====================================
|
||||
|
||||
fn x, y -> x + y end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(body
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
multiline body
|
||||
=====================================
|
||||
|
||||
fn x, y ->
|
||||
y
|
||||
x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
many clauses
|
||||
=====================================
|
||||
|
||||
fn
|
||||
1 -> :yes
|
||||
2 -> :no
|
||||
other -> :maybe
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(atom)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(integer))
|
||||
(body
|
||||
(atom)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(atom)))))
|
||||
|
||||
=====================================
|
||||
with guard / no arguments
|
||||
=====================================
|
||||
|
||||
fn
|
||||
() when node() == :nonode@nohost -> true
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments)
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))
|
||||
(atom)))
|
||||
(body
|
||||
(boolean)))))
|
||||
|
||||
=====================================
|
||||
with guard / one argument
|
||||
=====================================
|
||||
|
||||
fn
|
||||
x when x == [] -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list)))
|
||||
(body
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
with guard / multiple arguments
|
||||
=====================================
|
||||
|
||||
fn
|
||||
x, y when x == [] -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list)))
|
||||
(body
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
with guard / arguments in parentheses
|
||||
=====================================
|
||||
|
||||
fn
|
||||
(x, y) when y == [] -> y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list)))
|
||||
(body
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
with guard / multiple guards
|
||||
=====================================
|
||||
|
||||
fn
|
||||
x when x > 10 when x < 5 -> x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer))))
|
||||
(body
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
pattern matching
|
||||
=====================================
|
||||
|
||||
fn
|
||||
[h | tail] -> {h, tail}
|
||||
%{x: x} when x == 1 -> 1
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(anonymous_function
|
||||
(stab_clause
|
||||
(arguments
|
||||
(list
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(body
|
||||
(tuple
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(map
|
||||
(map_content
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(identifier))))))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer)))
|
||||
(body
|
||||
(integer)))))
|
||||
@ -1,230 +0,0 @@
|
||||
=====================================
|
||||
empty
|
||||
=====================================
|
||||
|
||||
()
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block))
|
||||
|
||||
=====================================
|
||||
single expression
|
||||
=====================================
|
||||
|
||||
(1)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
multiple expressions separated by newline
|
||||
=====================================
|
||||
|
||||
(
|
||||
1
|
||||
2
|
||||
)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
multiple expressions separated by semicolon
|
||||
=====================================
|
||||
|
||||
(1;2)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
multiple expressions separated by mixed separators
|
||||
=====================================
|
||||
|
||||
(
|
||||
1
|
||||
|
||||
;
|
||||
|
||||
2
|
||||
)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
leading semicolon
|
||||
=====================================
|
||||
|
||||
(;1;2)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
trailing semicolon
|
||||
=====================================
|
||||
|
||||
(1;2;)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
stab clause / multiple clauses
|
||||
=====================================
|
||||
|
||||
(x -> x; y -> y
|
||||
z -> z)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)))
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
stab clause / multiple arguments
|
||||
=====================================
|
||||
|
||||
(x, y, z -> x)
|
||||
((x, y, z) -> x)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier))
|
||||
(body
|
||||
(identifier))))
|
||||
(block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier))
|
||||
(body
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
stab clause / guard
|
||||
=====================================
|
||||
|
||||
(x, y when x == y -> 1)
|
||||
((x, y when x == y -> 1))
|
||||
((x, y when x == y) -> 1)
|
||||
(x, y when x, z -> 1)
|
||||
((x, y when x, z -> 1))
|
||||
((x, y when x, z) -> 1)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(body
|
||||
(integer))))
|
||||
(block
|
||||
(block
|
||||
(stab_clause
|
||||
(binary_operator
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(body
|
||||
(integer)))))
|
||||
(block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(body
|
||||
(integer))))
|
||||
(block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier))
|
||||
(body
|
||||
(integer))))
|
||||
(block
|
||||
(block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier))
|
||||
(body
|
||||
(integer)))))
|
||||
(block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier))
|
||||
(body
|
||||
(integer)))))
|
||||
@ -1,987 +0,0 @@
|
||||
=====================================
|
||||
local call / no arguments
|
||||
=====================================
|
||||
|
||||
fun()
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments)))
|
||||
|
||||
=====================================
|
||||
local call / arguments in parentheses
|
||||
=====================================
|
||||
|
||||
fun(a)
|
||||
fun([1, 2], option: true, other: 5)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(list
|
||||
(integer)
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(boolean))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
local call / arguments without parentheses
|
||||
=====================================
|
||||
|
||||
fun a
|
||||
fun {}
|
||||
fun [1, 2], option: true, other: 5
|
||||
fun +: 1
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(tuple)))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(list
|
||||
(integer)
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(boolean))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer)))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
local call / arguments without parentheses / multiline
|
||||
=====================================
|
||||
|
||||
fun [1, 2],
|
||||
option: true,
|
||||
other: 5
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(list
|
||||
(integer)
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(boolean))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
local call / nested with parentheses
|
||||
=====================================
|
||||
|
||||
outer_fun(inner_fun(a))
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
local call / nested without parentheses (right associativity)
|
||||
=====================================
|
||||
|
||||
outer_fun inner_fun a, b
|
||||
outer_fun inner_fun do: 1
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))))
|
||||
|
||||
=====================================
|
||||
local call / precedence with operator
|
||||
=====================================
|
||||
|
||||
outer_fun 1 + 1
|
||||
1 + inner_fun 1
|
||||
outer_fun 1 + inner_fun 1
|
||||
fun 1, 2 |> other_fun
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))))
|
||||
(binary_operator
|
||||
(integer)
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(integer))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(integer)
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(integer))))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(integer)
|
||||
(binary_operator
|
||||
(integer)
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
local call / treats nonimmediate parentheses as a block argument
|
||||
=====================================
|
||||
|
||||
fun (x)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(block
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
remote call / no arguments
|
||||
=====================================
|
||||
|
||||
Mod.fun()
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments)))
|
||||
|
||||
=====================================
|
||||
remote call / no arguments without parentheses
|
||||
=====================================
|
||||
|
||||
Mod.fun
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
remote call / arguments in parentheses
|
||||
=====================================
|
||||
|
||||
Mod.fun(a)
|
||||
Mod.fun([1, 2], option: true, other: 5)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(list
|
||||
(integer)
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(boolean))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
remote call / arguments without parentheses
|
||||
=====================================
|
||||
|
||||
Mod.fun a
|
||||
Mod.fun [1, 2], option: true, other: 5
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(list
|
||||
(integer)
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(boolean))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
remote call / nested with parentheses
|
||||
=====================================
|
||||
|
||||
Mod.outer_fun(Mod.inner_fun(a))
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
remote call / nested without parentheses (right associativity)
|
||||
=====================================
|
||||
|
||||
Mod.outer_fun Mod.inner_fun a
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
remote call / precedence with operator
|
||||
=====================================
|
||||
|
||||
Mod.outer_fun 1 + 1
|
||||
1 + Mod.inner_fun 1
|
||||
Mod.outer_fun 1 + Mod.inner_fun 1
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))))
|
||||
(binary_operator
|
||||
(integer)
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(integer))))
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(binary_operator
|
||||
(integer)
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(integer)))))))
|
||||
|
||||
=====================================
|
||||
remote call / treats nonimmediate parentheses as a block argument
|
||||
=====================================
|
||||
|
||||
Mod.fun (x)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(block
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
remote call / multi-level alias
|
||||
=====================================
|
||||
|
||||
Mod1.Mod2.Mod3.fun(a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
remote call / operator
|
||||
=====================================
|
||||
|
||||
Kernel.+(a, b)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(operator_identifier))
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
remote call / quoted function name
|
||||
=====================================
|
||||
|
||||
Mod."fun"(a)
|
||||
Mod.'fun'(a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(string
|
||||
(quoted_content)))
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(charlist
|
||||
(quoted_content)))
|
||||
(arguments
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
remote call / atom literal module
|
||||
=====================================
|
||||
|
||||
:mod.fun(a)
|
||||
:"Elixir.Mod".fun(a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(atom)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(dot
|
||||
(quoted_atom
|
||||
(quoted_content))
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
anonymous call / no arguments
|
||||
=====================================
|
||||
|
||||
fun.()
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(identifier))
|
||||
(arguments)))
|
||||
|
||||
=====================================
|
||||
anonymous call / arguments in parentheses
|
||||
=====================================
|
||||
|
||||
fun.(a)
|
||||
fun.([1, 2], option: true, other: 5)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(dot
|
||||
(identifier))
|
||||
(arguments
|
||||
(list
|
||||
(integer)
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(boolean))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
anonymous call / nested with parentheses
|
||||
=====================================
|
||||
|
||||
outer_fun.(inner_fun.(a))
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(identifier))
|
||||
(arguments
|
||||
(call
|
||||
(dot
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
mixed call types
|
||||
=====================================
|
||||
|
||||
Mod.outer_fun mid_fun inner_fun.(a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(dot
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))))))
|
||||
|
||||
=====================================
|
||||
identifier call
|
||||
=====================================
|
||||
|
||||
mod.fun(a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(identifier)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
nested identifier call
|
||||
=====================================
|
||||
|
||||
map.mod.fun(a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(call
|
||||
(dot
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
reserved word call
|
||||
=====================================
|
||||
|
||||
a.and
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(identifier)
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
range call
|
||||
=====================================
|
||||
|
||||
(1..2).step
|
||||
(1..2//3).step
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(block
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer)))
|
||||
(identifier)))
|
||||
(call
|
||||
(dot
|
||||
(block
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))
|
||||
(integer)))
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
multi-expression block call
|
||||
=====================================
|
||||
|
||||
(
|
||||
x
|
||||
1..2
|
||||
).step
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(block
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer)))
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
map call
|
||||
=====================================
|
||||
|
||||
%{}.field
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(map)
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
struct call
|
||||
=====================================
|
||||
|
||||
%Mod{}.field
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(map
|
||||
(struct
|
||||
(alias)))
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
arbitrary term call
|
||||
=====================================
|
||||
|
||||
1.(1, 2)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(integer))
|
||||
(arguments
|
||||
(integer)
|
||||
(integer))))
|
||||
|
||||
=====================================
|
||||
escaped newline call
|
||||
=====================================
|
||||
|
||||
fun \
|
||||
a
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
keyword list trailing separator
|
||||
=====================================
|
||||
|
||||
fun(option: true, other: 5,)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(boolean))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
newline before dot
|
||||
=====================================
|
||||
|
||||
Mod
|
||||
.fun(a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
newline after dot
|
||||
=====================================
|
||||
|
||||
Mod.
|
||||
fun(a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
access syntax
|
||||
=====================================
|
||||
|
||||
map[key]
|
||||
map[:key]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(access_call
|
||||
(identifier)
|
||||
(identifier))
|
||||
(access_call
|
||||
(identifier)
|
||||
(atom)))
|
||||
|
||||
=====================================
|
||||
access syntax / does not allow whitespace
|
||||
=====================================
|
||||
|
||||
map [key]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(list
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
access syntax / precedence with dot call
|
||||
=====================================
|
||||
|
||||
map.map[:key]
|
||||
map[:mod].fun
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(access_call
|
||||
(call
|
||||
(dot
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(atom))
|
||||
(call
|
||||
(dot
|
||||
(access_call
|
||||
(identifier)
|
||||
(atom))
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
access syntax / precedence with operators
|
||||
=====================================
|
||||
|
||||
-x[:key]
|
||||
@x[:key]
|
||||
&x[:key]
|
||||
&1[:key]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(access_call
|
||||
(identifier)
|
||||
(atom)))
|
||||
(access_call
|
||||
(unary_operator
|
||||
(identifier))
|
||||
(atom))
|
||||
(unary_operator
|
||||
(access_call
|
||||
(identifier)
|
||||
(atom)))
|
||||
(access_call
|
||||
(unary_operator
|
||||
(integer))
|
||||
(atom)))
|
||||
|
||||
=====================================
|
||||
double parenthesised call
|
||||
=====================================
|
||||
|
||||
fun()()
|
||||
fun() ()
|
||||
fun(1)(1)
|
||||
Mod.fun()()
|
||||
fun.()()
|
||||
|
||||
unquote(name)()
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))
|
||||
(arguments))
|
||||
(call
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))
|
||||
(arguments))
|
||||
(call
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(integer)))
|
||||
(arguments
|
||||
(integer)))
|
||||
(call
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments))
|
||||
(arguments))
|
||||
(call
|
||||
(call
|
||||
(dot
|
||||
(identifier))
|
||||
(arguments))
|
||||
(arguments))
|
||||
(call
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(arguments)))
|
||||
|
||||
=====================================
|
||||
[field names]
|
||||
=====================================
|
||||
|
||||
fun()
|
||||
fun a
|
||||
Mod.fun a
|
||||
fun()()
|
||||
fun.()
|
||||
map[key]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
target: (identifier)
|
||||
(arguments))
|
||||
(call
|
||||
target: (identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
target: (dot
|
||||
left: (alias)
|
||||
right: (identifier))
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
target: (call
|
||||
target: (identifier)
|
||||
(arguments))
|
||||
(arguments))
|
||||
(call
|
||||
target: (dot
|
||||
left: (identifier))
|
||||
(arguments))
|
||||
(access_call
|
||||
target: (identifier)
|
||||
key: (identifier)))
|
||||
|
||||
=====================================
|
||||
[error] leading argument separator
|
||||
=====================================
|
||||
|
||||
fun(, a)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(ERROR)
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
[error] trailing argument separator
|
||||
=====================================
|
||||
|
||||
fun(a,)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(ERROR))))
|
||||
@ -1,131 +0,0 @@
|
||||
=====================================
|
||||
anonymous function
|
||||
=====================================
|
||||
|
||||
& &1 + &2
|
||||
&(&1 + &2)
|
||||
&foo(&1, a, &2)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(unary_operator
|
||||
(integer))
|
||||
(unary_operator
|
||||
(integer))))
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(unary_operator
|
||||
(integer))
|
||||
(unary_operator
|
||||
(integer))))
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(unary_operator
|
||||
(integer))
|
||||
(identifier)
|
||||
(unary_operator
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
argument call
|
||||
=====================================
|
||||
|
||||
& &1.some_fun
|
||||
&(&1.some_fun)
|
||||
& &1.(&2)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(dot
|
||||
(unary_operator
|
||||
(integer))
|
||||
(identifier))))
|
||||
(unary_operator
|
||||
(call
|
||||
(dot
|
||||
(unary_operator
|
||||
(integer))
|
||||
(identifier))))
|
||||
(unary_operator
|
||||
(call
|
||||
(dot
|
||||
(unary_operator
|
||||
(integer)))
|
||||
(arguments
|
||||
(unary_operator
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
remote MFA
|
||||
=====================================
|
||||
|
||||
&Mod.fun/1
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier)))
|
||||
(integer))))
|
||||
|
||||
=====================================
|
||||
remote operator MFA
|
||||
=====================================
|
||||
|
||||
&Kernel.>=/2
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(operator_identifier)))
|
||||
(integer))))
|
||||
|
||||
=====================================
|
||||
local MFA
|
||||
=====================================
|
||||
|
||||
&fun/1
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer))))
|
||||
|
||||
=====================================
|
||||
local operator MFA
|
||||
=====================================
|
||||
|
||||
&>=/2
|
||||
&//2
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer)))
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(operator_identifier)
|
||||
(integer))))
|
||||
@ -1,785 +0,0 @@
|
||||
=====================================
|
||||
unary
|
||||
=====================================
|
||||
|
||||
@arg
|
||||
|
||||
+arg
|
||||
-arg
|
||||
!arg
|
||||
^arg
|
||||
not arg
|
||||
~~~arg
|
||||
|
||||
&arg
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier)))
|
||||
|
||||
=====================================
|
||||
binary left associative
|
||||
=====================================
|
||||
|
||||
a ** b ** c
|
||||
|
||||
a * b * c
|
||||
a / b / c
|
||||
|
||||
a + b + c
|
||||
a - b - c
|
||||
|
||||
a ^^^ b ^^^ c
|
||||
|
||||
a in b in c
|
||||
a not in b not in c
|
||||
|
||||
a |> b |> c
|
||||
a <<< b <<< c
|
||||
a >>> b >>> c
|
||||
a <<~ b <<~ c
|
||||
a ~>> b ~>> c
|
||||
a <~ b <~ c
|
||||
a ~> b ~> c
|
||||
a <~> b <~> c
|
||||
a <|> b <|> c
|
||||
|
||||
a < b < c
|
||||
a > b > c
|
||||
a <= b <= c
|
||||
a >= b >= c
|
||||
|
||||
a == b == c
|
||||
a != b != c
|
||||
a =~ b =~ c
|
||||
a === b === c
|
||||
a !== b !== c
|
||||
|
||||
a && b && c
|
||||
a &&& b &&& c
|
||||
a and b and c
|
||||
|
||||
a || b || c
|
||||
a ||| b ||| c
|
||||
a or b or c
|
||||
|
||||
a <- b <- c
|
||||
a \\ b \\ c
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier)))
|
||||
|
||||
=====================================
|
||||
binary right associative
|
||||
=====================================
|
||||
|
||||
a ++ b ++ c
|
||||
a -- b -- c
|
||||
a +++ b +++ c
|
||||
a --- b --- c
|
||||
a .. b .. c
|
||||
a <> b <> c
|
||||
|
||||
a = b = c
|
||||
|
||||
a | b | c
|
||||
|
||||
a :: b :: c
|
||||
|
||||
a when b when c
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier)))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier))))
|
||||
|
||||
=====================================
|
||||
precedence on the same level falls back to associativity
|
||||
=====================================
|
||||
|
||||
a * b / c
|
||||
a + b - c
|
||||
a in b not in c
|
||||
a <<< b >>> c
|
||||
a < b > c
|
||||
a == b != c
|
||||
a &&& b && c
|
||||
a ||| b || c
|
||||
a <- b \\ c
|
||||
|
||||
a ++ b -- c
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (binary_operator (identifier) (identifier)) (identifier))
|
||||
(binary_operator (identifier) (binary_operator (identifier) (identifier))))
|
||||
|
||||
=====================================
|
||||
precedence on different levels
|
||||
=====================================
|
||||
|
||||
& @ a - b
|
||||
a -- b + c
|
||||
a - b ++ c
|
||||
a = b <<< c
|
||||
|
||||
a + b * c - d
|
||||
a ** b + c ** d
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(unary_operator
|
||||
(identifier))
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
precedence determined by parentheses
|
||||
=====================================
|
||||
|
||||
(& a) - b
|
||||
|
||||
(a + b) * (c - d)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(block
|
||||
(unary_operator
|
||||
(identifier)))
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(block
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(block
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
"not in" spacing
|
||||
=====================================
|
||||
|
||||
a not in b
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))
|
||||
|
||||
=====================================
|
||||
"not in" boundary
|
||||
=====================================
|
||||
|
||||
fun not inARG
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(unary_operator
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
multiline / unary
|
||||
=====================================
|
||||
|
||||
@
|
||||
arg
|
||||
|
||||
+
|
||||
arg
|
||||
|
||||
-
|
||||
arg
|
||||
|
||||
!
|
||||
arg
|
||||
|
||||
^
|
||||
arg
|
||||
|
||||
not
|
||||
arg
|
||||
|
||||
~~~
|
||||
arg
|
||||
|
||||
&
|
||||
arg
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier))
|
||||
(unary_operator (identifier)))
|
||||
|
||||
=====================================
|
||||
multiline / binary
|
||||
=====================================
|
||||
|
||||
a
|
||||
**
|
||||
b
|
||||
|
||||
a
|
||||
*
|
||||
b
|
||||
|
||||
a
|
||||
/
|
||||
b
|
||||
|
||||
a
|
||||
++
|
||||
b
|
||||
|
||||
a
|
||||
--
|
||||
b
|
||||
|
||||
a
|
||||
+++
|
||||
b
|
||||
|
||||
a
|
||||
---
|
||||
b
|
||||
|
||||
a
|
||||
..
|
||||
b
|
||||
|
||||
a
|
||||
<>
|
||||
b
|
||||
|
||||
|
||||
a
|
||||
^^^
|
||||
b
|
||||
|
||||
a
|
||||
in
|
||||
b
|
||||
|
||||
a
|
||||
not in
|
||||
b
|
||||
|
||||
a
|
||||
|>
|
||||
b
|
||||
|
||||
a
|
||||
<<<
|
||||
b
|
||||
|
||||
a
|
||||
>>>
|
||||
b
|
||||
|
||||
a
|
||||
<<~
|
||||
b
|
||||
|
||||
a
|
||||
~>>
|
||||
b
|
||||
|
||||
a
|
||||
<~
|
||||
b
|
||||
|
||||
a
|
||||
~>
|
||||
b
|
||||
|
||||
a
|
||||
<~>
|
||||
b
|
||||
|
||||
a
|
||||
<|>
|
||||
b
|
||||
|
||||
a
|
||||
<
|
||||
b
|
||||
|
||||
a
|
||||
>
|
||||
b
|
||||
|
||||
a
|
||||
<=
|
||||
b
|
||||
|
||||
a
|
||||
>=
|
||||
b
|
||||
|
||||
a
|
||||
==
|
||||
b
|
||||
|
||||
a
|
||||
!=
|
||||
b
|
||||
|
||||
a
|
||||
=~
|
||||
b
|
||||
|
||||
a
|
||||
===
|
||||
b
|
||||
|
||||
a
|
||||
!==
|
||||
b
|
||||
|
||||
a
|
||||
&&
|
||||
b
|
||||
|
||||
a
|
||||
&&&
|
||||
b
|
||||
|
||||
a
|
||||
and
|
||||
b
|
||||
|
||||
a
|
||||
||
|
||||
b
|
||||
|
||||
a
|
||||
|||
|
||||
b
|
||||
|
||||
a
|
||||
or
|
||||
b
|
||||
|
||||
a
|
||||
=
|
||||
b
|
||||
|
||||
a
|
||||
|
|
||||
b
|
||||
|
||||
a
|
||||
::
|
||||
b
|
||||
|
||||
a
|
||||
when
|
||||
b
|
||||
|
||||
a
|
||||
<-
|
||||
b
|
||||
|
||||
a
|
||||
\\
|
||||
b
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier))
|
||||
(binary_operator (identifier) (identifier)))
|
||||
|
||||
=====================================
|
||||
multiline / unary over binary
|
||||
=====================================
|
||||
|
||||
a
|
||||
+
|
||||
b
|
||||
|
||||
a
|
||||
-
|
||||
b
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(identifier)
|
||||
(unary_operator
|
||||
(identifier))
|
||||
(identifier)
|
||||
(unary_operator
|
||||
(identifier)))
|
||||
|
||||
=====================================
|
||||
multiline / right operands
|
||||
=====================================
|
||||
|
||||
x
|
||||
not in
|
||||
[y]
|
||||
|
||||
x
|
||||
not in[y]
|
||||
|
||||
:a
|
||||
++:b
|
||||
|
||||
:a++
|
||||
:b
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(atom)
|
||||
(atom))
|
||||
(binary_operator
|
||||
(atom)
|
||||
(atom)))
|
||||
|
||||
=====================================
|
||||
multiline / unary over binary (precedence)
|
||||
=====================================
|
||||
|
||||
x
|
||||
-
|
||||
y
|
||||
|
||||
x
|
||||
+
|
||||
y
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(identifier)
|
||||
(unary_operator
|
||||
(identifier))
|
||||
(identifier)
|
||||
(unary_operator
|
||||
(identifier)))
|
||||
|
||||
=====================================
|
||||
plus minus
|
||||
=====================================
|
||||
|
||||
x+y
|
||||
x + y
|
||||
x+ y
|
||||
|
||||
x +y
|
||||
x +y +z
|
||||
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(unary_operator
|
||||
(identifier))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(unary_operator
|
||||
(identifier))))))))
|
||||
|
||||
=====================================
|
||||
nullary range
|
||||
=====================================
|
||||
|
||||
..
|
||||
Enum.to_list(..)
|
||||
not ..
|
||||
range = ..
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(operator_identifier)
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(operator_identifier)))
|
||||
(unary_operator
|
||||
(operator_identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(operator_identifier)))
|
||||
|
||||
=====================================
|
||||
stepped range
|
||||
=====================================
|
||||
|
||||
1 .. 2 // 3
|
||||
1..2//3
|
||||
0..1//-1
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))
|
||||
(integer))
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))
|
||||
(integer))
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))
|
||||
(unary_operator
|
||||
(integer))))
|
||||
|
||||
=====================================
|
||||
stepped range / multiline
|
||||
=====================================
|
||||
|
||||
1..2
|
||||
// 4
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
stepped ranges / blocks
|
||||
=====================================
|
||||
|
||||
foo do end..bar do end//baz do end
|
||||
1..(2//3)
|
||||
(1..2)//3
|
||||
(1..2)//(3)
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(do_block))
|
||||
(call
|
||||
(identifier)
|
||||
(do_block)))
|
||||
(call
|
||||
(identifier)
|
||||
(do_block)))
|
||||
(binary_operator
|
||||
(integer)
|
||||
(block
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))))
|
||||
(binary_operator
|
||||
(block
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer)))
|
||||
(integer))
|
||||
(binary_operator
|
||||
(block
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer)))
|
||||
(block
|
||||
(integer))))
|
||||
|
||||
=====================================
|
||||
[field names]
|
||||
=====================================
|
||||
|
||||
a + b
|
||||
@a
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(binary_operator
|
||||
left: (identifier)
|
||||
right: (identifier))
|
||||
(unary_operator
|
||||
operand: (identifier)))
|
||||
@ -1,270 +0,0 @@
|
||||
=====================================
|
||||
simple literal
|
||||
=====================================
|
||||
|
||||
~s(content)
|
||||
~r{content}
|
||||
~w[content]
|
||||
~a<content>
|
||||
~b"content"
|
||||
~c'content'
|
||||
~d|content|
|
||||
~e/content/
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil (sigil_name) (quoted_content))
|
||||
(sigil (sigil_name) (quoted_content))
|
||||
(sigil (sigil_name) (quoted_content))
|
||||
(sigil (sigil_name) (quoted_content))
|
||||
(sigil (sigil_name) (quoted_content))
|
||||
(sigil (sigil_name) (quoted_content))
|
||||
(sigil (sigil_name) (quoted_content))
|
||||
(sigil (sigil_name) (quoted_content)))
|
||||
|
||||
|
||||
=====================================
|
||||
multiple lines
|
||||
=====================================
|
||||
|
||||
~s"line 1
|
||||
line 2"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
interpolation
|
||||
=====================================
|
||||
|
||||
~s"hey #{name}!"
|
||||
~r/hey #{
|
||||
name
|
||||
}!/
|
||||
~w{##{name}#}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
nested interpolation
|
||||
=====================================
|
||||
|
||||
~s{this is #{~s{number #{1}}}!}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(integer))))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
escape sequence
|
||||
=====================================
|
||||
|
||||
~s{_\}_\n_\t_\r_\e_\\_\1_\x3f_\u0065\u0301_}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
escaped interpolation
|
||||
=====================================
|
||||
|
||||
~s/\#{1}/
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
upper sigil / no interpolation
|
||||
=====================================
|
||||
|
||||
~S"hey #{name}!"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
upper sigil / no escape sequence
|
||||
=====================================
|
||||
|
||||
~S"\n"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
upper sigil / escape terminator
|
||||
=====================================
|
||||
|
||||
~S"content \" content"
|
||||
~S{content \} content}
|
||||
~S/content \/ content/
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content))
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content))
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
upper sigil / multiple characters
|
||||
=====================================
|
||||
|
||||
~MAT"1 2"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc delimiter
|
||||
=====================================
|
||||
|
||||
~s"""
|
||||
text
|
||||
with "quotes"
|
||||
"""
|
||||
|
||||
~s'''
|
||||
text
|
||||
with 'quotes'
|
||||
'''
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content))
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
modifiers
|
||||
=====================================
|
||||
|
||||
~r/left|right/i
|
||||
~r/left|right/iUx
|
||||
~r/left|right/0
|
||||
~r/left|right/u8
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(sigil_modifiers))
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(sigil_modifiers))
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(sigil_modifiers))
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(quoted_content)
|
||||
(sigil_modifiers)))
|
||||
|
||||
=====================================
|
||||
[error] accepts only a single character
|
||||
=====================================
|
||||
|
||||
~mysigil"content"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(sigil
|
||||
(sigil_name)
|
||||
(ERROR)
|
||||
(quoted_content)))
|
||||
@ -1,392 +0,0 @@
|
||||
=====================================
|
||||
def / no arguments
|
||||
=====================================
|
||||
|
||||
def fun() do
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments)))
|
||||
(do_block)))
|
||||
|
||||
=====================================
|
||||
def / no arguments without parentheses
|
||||
=====================================
|
||||
|
||||
def fun do
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))
|
||||
(do_block)))
|
||||
|
||||
=====================================
|
||||
def / one argument
|
||||
=====================================
|
||||
|
||||
def fun(x) do
|
||||
x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
def / one argument without parentheses
|
||||
=====================================
|
||||
|
||||
def fun x do
|
||||
x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
def / many arguments
|
||||
=====================================
|
||||
|
||||
def fun(x, y) do
|
||||
x + y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(do_block
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
def / many arguments without parentheses
|
||||
=====================================
|
||||
|
||||
def fun x, y do
|
||||
x + y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(do_block
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
def / default arguments
|
||||
=====================================
|
||||
|
||||
def fun x, y \\ 1 do
|
||||
x + y
|
||||
end
|
||||
|
||||
def fun(x, y \\ 1) do
|
||||
x + y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer)))))
|
||||
(do_block
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer)))))
|
||||
(do_block
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
def / keyword do block
|
||||
=====================================
|
||||
|
||||
def fun(), do: 1
|
||||
def fun(x), do: x
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer)))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
def / pattern matching
|
||||
=====================================
|
||||
|
||||
def fun([{x, y} | tail]) do
|
||||
x + y
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(list
|
||||
(binary_operator
|
||||
(tuple
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier))))))
|
||||
(do_block
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
def / with guard
|
||||
=====================================
|
||||
|
||||
def fun(x) when x == 1 do
|
||||
x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer))))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
def / with guard / multiple guards
|
||||
=====================================
|
||||
|
||||
def fun(x) when x > 10 when x < 5 do
|
||||
x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer)))))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
defp
|
||||
=====================================
|
||||
|
||||
defp fun(x) do
|
||||
x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))
|
||||
(do_block
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
defmacro
|
||||
=====================================
|
||||
|
||||
defmacro fun(x) do
|
||||
quote do
|
||||
[unquote(x)]
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))
|
||||
(do_block
|
||||
(call
|
||||
(identifier)
|
||||
(do_block
|
||||
(list
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))))))))
|
||||
|
||||
=====================================
|
||||
defguard
|
||||
=====================================
|
||||
|
||||
defguard is_even(term) when is_integer(term) and rem(term, 2) == 0
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(integer)))
|
||||
(integer)))))))
|
||||
|
||||
=====================================
|
||||
def in macro
|
||||
=====================================
|
||||
|
||||
def unquote(name)(unquote_splicing(args)) do
|
||||
unquote(compiled)
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))))
|
||||
(do_block
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))))
|
||||
@ -1,132 +0,0 @@
|
||||
=====================================
|
||||
for / enumerable
|
||||
=====================================
|
||||
|
||||
for n <- [1, 2], do: n * 2
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list
|
||||
(integer)
|
||||
(integer)))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer)))))))
|
||||
|
||||
=====================================
|
||||
for / enumerable / with options and block
|
||||
=====================================
|
||||
|
||||
for line <- IO.stream(), into: IO.stream() do
|
||||
String.upcase(line)
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments)))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments)))))
|
||||
(do_block
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
for / binary
|
||||
=====================================
|
||||
|
||||
for <<c <- " hello world ">>, c != ?\s, into: "", do: <<c>>
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(string
|
||||
(quoted_content))))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(char))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(string))
|
||||
(pair
|
||||
(keyword)
|
||||
(bitstring
|
||||
(identifier)))))))
|
||||
|
||||
=====================================
|
||||
for / reduce
|
||||
=====================================
|
||||
|
||||
for x <- [1, 2, 1], reduce: %{} do
|
||||
acc -> Map.update(acc, x, 1, & &1 + 1)
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(list
|
||||
(integer)
|
||||
(integer)
|
||||
(integer)))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(map))))
|
||||
(do_block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier)
|
||||
(integer)
|
||||
(unary_operator
|
||||
(binary_operator
|
||||
(unary_operator
|
||||
(integer))
|
||||
(integer))))))))))
|
||||
@ -1,138 +0,0 @@
|
||||
=====================================
|
||||
empty module definition
|
||||
=====================================
|
||||
|
||||
defmodule Mod do
|
||||
end
|
||||
|
||||
defmodule Mod.Child do
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(alias))
|
||||
(do_block))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(alias))
|
||||
(do_block)))
|
||||
|
||||
=====================================
|
||||
module definition with atom literal
|
||||
=====================================
|
||||
|
||||
defmodule :mod do
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(atom))
|
||||
(do_block)))
|
||||
|
||||
=====================================
|
||||
full module definition
|
||||
=====================================
|
||||
|
||||
defmodule Mod do
|
||||
@moduledoc """
|
||||
Example module
|
||||
"""
|
||||
|
||||
use UseMod
|
||||
|
||||
@attribute 1
|
||||
|
||||
@doc """
|
||||
Example function
|
||||
"""
|
||||
@spec func(integer) :: integer
|
||||
def func(x) when is_integer(x) do
|
||||
priv(x) + priv(x)
|
||||
end
|
||||
|
||||
defp priv(x), do: x * x
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(alias))
|
||||
(do_block
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(string
|
||||
(quoted_content)))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(alias)))
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(integer))))
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(string
|
||||
(quoted_content)))))
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(identifier)))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))))
|
||||
(do_block
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier))))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier)))))))))
|
||||
@ -1,245 +0,0 @@
|
||||
=====================================
|
||||
without type parentheses
|
||||
=====================================
|
||||
|
||||
@spec fun(atom, integer, keyword) :: string
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
with type parentheses
|
||||
=====================================
|
||||
|
||||
@spec fun(atom(), integer(), keyword()) :: string()
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))))
|
||||
(call
|
||||
(identifier)
|
||||
(arguments)))))))
|
||||
|
||||
=====================================
|
||||
with literals
|
||||
=====================================
|
||||
|
||||
@spec fun(%{key: atom}) :: {:ok, atom} | {:error, binary}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(map
|
||||
(map_content
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(identifier)))))))
|
||||
(binary_operator
|
||||
(tuple
|
||||
(atom)
|
||||
(identifier))
|
||||
(tuple
|
||||
(atom)
|
||||
(identifier))))))))
|
||||
|
||||
=====================================
|
||||
with function reference
|
||||
=====================================
|
||||
|
||||
@spec fun((-> atom), (atom -> integer)) :: integer
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(block
|
||||
(stab_clause
|
||||
(body
|
||||
(identifier))))
|
||||
(block
|
||||
(stab_clause
|
||||
(arguments
|
||||
(identifier))
|
||||
(body
|
||||
(identifier))))))
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
with remote type
|
||||
=====================================
|
||||
|
||||
@spec fun(Keyword.t()) :: String.t()
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments))))
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments)))))))
|
||||
|
||||
=====================================
|
||||
with type guard
|
||||
=====================================
|
||||
|
||||
@spec fun(arg1, arg2) :: {arg1, arg2} when arg1: atom, arg2: integer
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(tuple
|
||||
(identifier)
|
||||
(identifier)))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(identifier))
|
||||
(pair
|
||||
(keyword)
|
||||
(identifier))))))))
|
||||
|
||||
=====================================
|
||||
with named arguments
|
||||
=====================================
|
||||
|
||||
@spec days_since_epoch(year :: integer, month :: integer, day :: integer) :: integer
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(identifier))))))
|
||||
|
||||
=====================================
|
||||
nonempty list
|
||||
=====================================
|
||||
|
||||
@spec fun() :: [integer, ...]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))
|
||||
(list
|
||||
(identifier)
|
||||
(identifier)))))))
|
||||
|
||||
=====================================
|
||||
[error] type guard cannot end with keyword separator
|
||||
=====================================
|
||||
|
||||
@spec fun(arg) :: arg when arg: atom,
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(unary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))
|
||||
(identifier))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(identifier)))))))
|
||||
(ERROR))
|
||||
@ -1,32 +0,0 @@
|
||||
=====================================
|
||||
separates expressions in the same line
|
||||
=====================================
|
||||
|
||||
1 ; 1
|
||||
|
||||
---
|
||||
|
||||
(source (integer) (integer))
|
||||
|
||||
=====================================
|
||||
trailing
|
||||
=====================================
|
||||
|
||||
1;
|
||||
2;
|
||||
|
||||
---
|
||||
|
||||
(source (integer) (integer))
|
||||
|
||||
=====================================
|
||||
with comment
|
||||
=====================================
|
||||
|
||||
1 ; # comment
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(integer)
|
||||
(comment))
|
||||
@ -1,84 +0,0 @@
|
||||
=====================================
|
||||
single part
|
||||
=====================================
|
||||
|
||||
Mod
|
||||
AZ_az_19_
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(alias)
|
||||
(alias))
|
||||
|
||||
=====================================
|
||||
multiple parts
|
||||
=====================================
|
||||
|
||||
Mod.Child
|
||||
Mod.Child.Child
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(alias)
|
||||
(alias))
|
||||
|
||||
=====================================
|
||||
spacing
|
||||
=====================================
|
||||
|
||||
Mod . Child
|
||||
|
||||
Mod
|
||||
.
|
||||
Child
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(alias)
|
||||
(alias))
|
||||
|
||||
=====================================
|
||||
qualified tuples
|
||||
=====================================
|
||||
|
||||
Mod.{Child1, Child2}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(dot
|
||||
(alias)
|
||||
(tuple
|
||||
(alias)
|
||||
(alias))))
|
||||
|
||||
=====================================
|
||||
dot on identifier
|
||||
=====================================
|
||||
|
||||
name.Mod
|
||||
name.Mod.Child
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(dot
|
||||
(identifier)
|
||||
(alias))
|
||||
(dot
|
||||
(identifier)
|
||||
(alias)))
|
||||
|
||||
=====================================
|
||||
dot on special identifier
|
||||
=====================================
|
||||
|
||||
__MODULE__.Child
|
||||
|
||||
(source
|
||||
(dot
|
||||
(identifier)
|
||||
(alias)))
|
||||
@ -1,84 +0,0 @@
|
||||
=====================================
|
||||
simple literal
|
||||
=====================================
|
||||
|
||||
:atom
|
||||
:_az_AZ_19_
|
||||
:nonode@nohost
|
||||
:bang!
|
||||
:question?
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(atom)
|
||||
(atom)
|
||||
(atom)
|
||||
(atom)
|
||||
(atom))
|
||||
|
||||
=====================================
|
||||
operators
|
||||
=====================================
|
||||
|
||||
[:~~~, :~>>, :~>, :|||, :||, :|>, :|, :>>>, :>=, :>, :=~, :===, :==, :=, :<~>, :<~, :<|>, :<>, :<=, :<<~, :<<<, :<-, :<, :+++, :++, :+, :^^^, :^, :&&&, :&&, :&, :\\, :/, :**, :*, :@, :.., :., :!==, :!=, :!, :::, :->, :---, :--, :-]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom) (atom)))
|
||||
|
||||
=====================================
|
||||
special operator-like atoms
|
||||
=====================================
|
||||
|
||||
[:..., :%{}, :{}, :%, :<<>>, :..//]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(atom)
|
||||
(atom)
|
||||
(atom)
|
||||
(atom)
|
||||
(atom)
|
||||
(atom)))
|
||||
|
||||
=====================================
|
||||
quoted atom
|
||||
=====================================
|
||||
|
||||
:"atom ?? !! ' \n"
|
||||
:'atom ?? !! " \n'
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(quoted_atom
|
||||
(quoted_content)
|
||||
(escape_sequence))
|
||||
(quoted_atom
|
||||
(quoted_content)
|
||||
(escape_sequence)))
|
||||
|
||||
=====================================
|
||||
interpolation
|
||||
=====================================
|
||||
|
||||
:"hey #{name}!"
|
||||
:'hey #{name}!'
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(quoted_atom
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(quoted_atom
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content)))
|
||||
@ -1,192 +0,0 @@
|
||||
=====================================
|
||||
single item
|
||||
=====================================
|
||||
|
||||
<<>>
|
||||
<<10>>
|
||||
<<10.0>>
|
||||
<<"string">>
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(bitstring)
|
||||
(bitstring
|
||||
(integer))
|
||||
(bitstring
|
||||
(float))
|
||||
(bitstring
|
||||
(string
|
||||
(quoted_content))))
|
||||
|
||||
=====================================
|
||||
multiple items
|
||||
=====================================
|
||||
|
||||
<<
|
||||
10,
|
||||
10.0,
|
||||
"string"
|
||||
>>
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(bitstring
|
||||
(integer)
|
||||
(float)
|
||||
(string
|
||||
(quoted_content))))
|
||||
|
||||
=====================================
|
||||
size modifiers
|
||||
=====================================
|
||||
|
||||
<<10::4>>
|
||||
<<10::size(4)>>
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer)))
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(integer)
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
multiple modifiers
|
||||
=====================================
|
||||
|
||||
<<"string"::utf8-big>>
|
||||
<<"string"::utf16-big>>
|
||||
<<"string"::utf32-big>>
|
||||
<<10::32-little-unsigned>>
|
||||
<<10::integer-signed-big>>
|
||||
<<10.10::float-signed-native>>
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(integer)
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(integer)
|
||||
(identifier))
|
||||
(identifier))))
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(integer)
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier))))
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(float)
|
||||
(binary_operator
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(identifier))
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
multiple components with modifiers
|
||||
=====================================
|
||||
|
||||
<<10::8-native, "string", 3.14::float, a::8, b::binary-size(known_size)>>
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(integer)
|
||||
(binary_operator
|
||||
(integer)
|
||||
(identifier)))
|
||||
(string
|
||||
(quoted_content))
|
||||
(binary_operator
|
||||
(float)
|
||||
(identifier))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))))))
|
||||
|
||||
=====================================
|
||||
spacing
|
||||
=====================================
|
||||
|
||||
<<
|
||||
10 :: 8-native,
|
||||
b :: binary - size(known_size)
|
||||
>>
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(bitstring
|
||||
(binary_operator
|
||||
(integer)
|
||||
(binary_operator
|
||||
(integer)
|
||||
(identifier)))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(call
|
||||
(identifier)
|
||||
(arguments
|
||||
(identifier)))))))
|
||||
|
||||
=====================================
|
||||
trailing separator
|
||||
=====================================
|
||||
|
||||
<<1,>>
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(bitstring
|
||||
(integer)))
|
||||
@ -1,12 +0,0 @@
|
||||
=====================================
|
||||
simple literal
|
||||
=====================================
|
||||
|
||||
true
|
||||
false
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(boolean)
|
||||
(boolean))
|
||||
@ -1,55 +0,0 @@
|
||||
=====================================
|
||||
regular character
|
||||
=====================================
|
||||
|
||||
?a
|
||||
?Z
|
||||
?0
|
||||
?9
|
||||
?_
|
||||
??
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(char)
|
||||
(char)
|
||||
(char)
|
||||
(char)
|
||||
(char)
|
||||
(char))
|
||||
|
||||
=====================================
|
||||
escaped character
|
||||
=====================================
|
||||
|
||||
?\n
|
||||
?\t
|
||||
?\s
|
||||
?\\
|
||||
?\a
|
||||
?\b
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(char)
|
||||
(char)
|
||||
(char)
|
||||
(char)
|
||||
(char)
|
||||
(char))
|
||||
|
||||
=====================================
|
||||
list of char literals
|
||||
=====================================
|
||||
|
||||
[?a, ?b, ?c]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(char)
|
||||
(char)
|
||||
(char)))
|
||||
@ -1,214 +0,0 @@
|
||||
=====================================
|
||||
single line
|
||||
=====================================
|
||||
|
||||
'Hello, 123!'
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
multiple lines
|
||||
=====================================
|
||||
|
||||
'line 1
|
||||
line 2'
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
interpolation
|
||||
=====================================
|
||||
|
||||
'hey #{name}!'
|
||||
'hey #{
|
||||
name
|
||||
}!'
|
||||
'##{name}#'
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
nested interpolation
|
||||
=====================================
|
||||
|
||||
'this is #{'number #{1}'}!'
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(integer))))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
escape sequence
|
||||
=====================================
|
||||
|
||||
'_\'_\n_\t_\r_\e_\\_\1_\x3f_\u0065\u0301_'
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
escaped interpolation
|
||||
=====================================
|
||||
|
||||
'\#{1}'
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / charlist
|
||||
=====================================
|
||||
|
||||
'''
|
||||
text
|
||||
with 'quotes'
|
||||
'''
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / interpolation
|
||||
=====================================
|
||||
|
||||
'''
|
||||
hey #{name}!
|
||||
'''
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / nested interpolation
|
||||
=====================================
|
||||
|
||||
'''
|
||||
this is #{
|
||||
'''
|
||||
number #{1}
|
||||
'''
|
||||
}!
|
||||
'''
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(integer))
|
||||
(quoted_content)))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / escaped delimiter
|
||||
=====================================
|
||||
|
||||
'''
|
||||
\'''
|
||||
'''
|
||||
|
||||
'''
|
||||
\'\'\'
|
||||
'''
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content))
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / escaped interpolation
|
||||
=====================================
|
||||
|
||||
'''
|
||||
\#{1}
|
||||
'''
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
@ -1,48 +0,0 @@
|
||||
=====================================
|
||||
simple literal
|
||||
=====================================
|
||||
|
||||
1234567890.1234567890
|
||||
-1234567890.1234567890
|
||||
-1_234_567_890.123_456_789_0
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(float)
|
||||
(unary_operator
|
||||
(float))
|
||||
(unary_operator
|
||||
(float)))
|
||||
|
||||
=====================================
|
||||
scientific notation
|
||||
=====================================
|
||||
|
||||
1.0e6
|
||||
1.0e+6
|
||||
1.0e-6
|
||||
-1.0e6
|
||||
-1.0e+6
|
||||
-1.0e-6
|
||||
1.0E6
|
||||
1.0E+6
|
||||
1.0E-6
|
||||
1_234_567_890.123_456_789_0e1_234_567_890
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(float)
|
||||
(float)
|
||||
(float)
|
||||
(unary_operator
|
||||
(float))
|
||||
(unary_operator
|
||||
(float))
|
||||
(unary_operator
|
||||
(float))
|
||||
(float)
|
||||
(float)
|
||||
(float)
|
||||
(float))
|
||||
@ -1,65 +0,0 @@
|
||||
=====================================
|
||||
decimal
|
||||
=====================================
|
||||
|
||||
1234567890
|
||||
-1234567890
|
||||
1_234_567_890
|
||||
019
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(integer)
|
||||
(unary_operator
|
||||
(integer))
|
||||
(integer)
|
||||
(integer))
|
||||
|
||||
=====================================
|
||||
binary
|
||||
=====================================
|
||||
|
||||
0b0101011
|
||||
-0b0101011
|
||||
0b0_10_10_11
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(integer)
|
||||
(unary_operator
|
||||
(integer))
|
||||
(integer))
|
||||
|
||||
=====================================
|
||||
octal
|
||||
=====================================
|
||||
|
||||
0o1234567
|
||||
-0o1234567
|
||||
0o1_23_45_67
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(integer)
|
||||
(unary_operator
|
||||
(integer))
|
||||
(integer))
|
||||
|
||||
=====================================
|
||||
hexadecimal
|
||||
=====================================
|
||||
|
||||
0x123456789abcdefABCDEF
|
||||
-0x123456789abcdefABCDEF
|
||||
0x123456789_abcdef_ABCDEF
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(integer)
|
||||
(unary_operator
|
||||
(integer))
|
||||
(integer))
|
||||
@ -1,234 +0,0 @@
|
||||
=====================================
|
||||
simple literal
|
||||
=====================================
|
||||
|
||||
[a: 1, a_b@12?: 2, A_B@12!: 3, Mod: 4, __struct__: 5]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
trailing separator
|
||||
=====================================
|
||||
|
||||
[a: 1,]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
with leading items
|
||||
=====================================
|
||||
|
||||
[1, {:c, 1}, a: 1, b: 2]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(integer)
|
||||
(tuple
|
||||
(atom)
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
operator key
|
||||
=====================================
|
||||
|
||||
[~~~: 1, ==: 2, >: 3]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
special atom key
|
||||
=====================================
|
||||
|
||||
[...: 1, %{}: 2, {}: 3, %: 4, <<>>: 5, ..//: 6]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
reserved token key
|
||||
=====================================
|
||||
|
||||
[not: 1, and: 2]
|
||||
[nil: 1, true: 2]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
quoted key
|
||||
=====================================
|
||||
|
||||
[
|
||||
"key1 ?? !! ' \n": 1,
|
||||
'key2 ?? !! " \n': 2
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
(quoted_keyword
|
||||
(quoted_content)
|
||||
(escape_sequence))
|
||||
(integer))
|
||||
(pair
|
||||
(quoted_keyword
|
||||
(quoted_content)
|
||||
(escape_sequence))
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
key interpolation
|
||||
=====================================
|
||||
|
||||
[
|
||||
"hey #{name}!": 1,
|
||||
'hey #{name}!': 2
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
(quoted_keyword
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(integer))
|
||||
(pair
|
||||
(quoted_keyword
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
[field names]
|
||||
=====================================
|
||||
|
||||
[a: 1, b: 2]
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(keywords
|
||||
(pair
|
||||
key: (keyword)
|
||||
value: (integer))
|
||||
(pair
|
||||
key: (keyword)
|
||||
value: (integer)))))
|
||||
|
||||
=====================================
|
||||
[error] with trailing items
|
||||
=====================================
|
||||
|
||||
[a: 1, b: 2, 1 => 1]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(ERROR
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer))))
|
||||
@ -1,88 +0,0 @@
|
||||
=====================================
|
||||
simple literal
|
||||
=====================================
|
||||
|
||||
[]
|
||||
[a]
|
||||
[A]
|
||||
[1]
|
||||
[1, 2]
|
||||
[1,2]
|
||||
[ 1 , 2 ]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list)
|
||||
(list
|
||||
(identifier))
|
||||
(list
|
||||
(alias))
|
||||
(list
|
||||
(integer))
|
||||
(list
|
||||
(integer)
|
||||
(integer))
|
||||
(list
|
||||
(integer)
|
||||
(integer))
|
||||
(list
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
nested
|
||||
=====================================
|
||||
|
||||
[[1], 1]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(list
|
||||
(integer))
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
trailing separator
|
||||
=====================================
|
||||
|
||||
[1,]
|
||||
[1,2,]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(integer))
|
||||
(list
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
[error] missing element
|
||||
=====================================
|
||||
|
||||
[, 1]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(ERROR)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
[error] missing separator
|
||||
=====================================
|
||||
|
||||
[1 2]
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(list
|
||||
(integer)
|
||||
(ERROR
|
||||
(integer))))
|
||||
@ -1,166 +0,0 @@
|
||||
=====================================
|
||||
empty
|
||||
=====================================
|
||||
|
||||
%{}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map))
|
||||
|
||||
=====================================
|
||||
from keywords
|
||||
=====================================
|
||||
|
||||
%{a: 1, b: 2}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(map_content
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
from arrow entries
|
||||
=====================================
|
||||
|
||||
%{:a => 1, "b" => 2, c => 3}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(map_content
|
||||
(binary_operator
|
||||
(atom)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(integer))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
from both arrow entries and keywords
|
||||
=====================================
|
||||
|
||||
%{"a" => 1, b: 2, c: 3}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(map_content
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
trailing separator
|
||||
=====================================
|
||||
|
||||
%{"a" => 1,}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(map_content
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
update syntax
|
||||
=====================================
|
||||
|
||||
%{user | name: "Jane", email: "jane@example.com"}
|
||||
%{user | "name" => "Jane"}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(map_content
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(string
|
||||
(quoted_content)))
|
||||
(pair
|
||||
(keyword)
|
||||
(string
|
||||
(quoted_content)))))))
|
||||
(map
|
||||
(map_content
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))))))
|
||||
|
||||
=====================================
|
||||
[error] ordering
|
||||
=====================================
|
||||
|
||||
%{b: 2, c: 3, 1 => 1}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(ERROR
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))
|
||||
(map_content
|
||||
(binary_operator
|
||||
(integer)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
[error] missing separator
|
||||
=====================================
|
||||
|
||||
%{"a" => 1 "b" => 2}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(map_content
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(ERROR (integer))
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(integer))))))
|
||||
@ -1,10 +0,0 @@
|
||||
=====================================
|
||||
simple literal
|
||||
=====================================
|
||||
|
||||
nil
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(nil))
|
||||
@ -1,278 +0,0 @@
|
||||
=====================================
|
||||
empty
|
||||
=====================================
|
||||
|
||||
""
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string))
|
||||
|
||||
=====================================
|
||||
single line
|
||||
=====================================
|
||||
|
||||
"Hello, 123!"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
multiple lines
|
||||
=====================================
|
||||
|
||||
"line 1
|
||||
line 2"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
interpolation
|
||||
=====================================
|
||||
|
||||
"hey #{name}!"
|
||||
"hey #{
|
||||
name
|
||||
}!"
|
||||
"##{name}#"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
nested interpolation
|
||||
=====================================
|
||||
|
||||
"this is #{"number #{1}"}!"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(integer))))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
empty interpolation
|
||||
=====================================
|
||||
|
||||
"#{}"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(interpolation)))
|
||||
|
||||
=====================================
|
||||
escape sequence
|
||||
=====================================
|
||||
|
||||
"_\"_\n_\t_\r_\e_\\_\1_\x3f_\u0065\u0301_"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
escaped interpolation
|
||||
=====================================
|
||||
|
||||
"\#{1}"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / string
|
||||
=====================================
|
||||
|
||||
"""
|
||||
text
|
||||
with "quotes"
|
||||
"""
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / interpolation
|
||||
=====================================
|
||||
|
||||
"""
|
||||
hey #{name}!
|
||||
"""
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(identifier))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / nested interpolation
|
||||
=====================================
|
||||
|
||||
"""
|
||||
this is #{
|
||||
"""
|
||||
number #{1}
|
||||
"""
|
||||
}!
|
||||
"""
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(string
|
||||
(quoted_content)
|
||||
(interpolation
|
||||
(integer))
|
||||
(quoted_content)))
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / delimiter in the middle
|
||||
=====================================
|
||||
|
||||
"""
|
||||
hey """
|
||||
"""
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / escaped newline (ignored)
|
||||
=====================================
|
||||
|
||||
"""
|
||||
hey \
|
||||
"""
|
||||
|
||||
"""
|
||||
hey \
|
||||
"""
|
||||
|
||||
"""
|
||||
hey \
|
||||
there
|
||||
"""
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / escaped delimiter
|
||||
=====================================
|
||||
|
||||
"""
|
||||
\"""
|
||||
"""
|
||||
|
||||
"""
|
||||
\"\"\"
|
||||
"""
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
heredoc / escaped interpolation
|
||||
=====================================
|
||||
|
||||
"""
|
||||
\#{1}
|
||||
"""
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
@ -1,239 +0,0 @@
|
||||
=====================================
|
||||
empty
|
||||
=====================================
|
||||
|
||||
%User{}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(alias))))
|
||||
|
||||
=====================================
|
||||
from keywords
|
||||
=====================================
|
||||
|
||||
%User{a: 1, b: 2}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(alias))
|
||||
(map_content
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
from arrow entries
|
||||
=====================================
|
||||
|
||||
%User{:a => 1, "b" => 2, c => 3}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(alias))
|
||||
(map_content
|
||||
(binary_operator
|
||||
(atom)
|
||||
(integer))
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(integer))
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
from both arrow entries and keywords
|
||||
=====================================
|
||||
|
||||
%User{"a" => 1, b: 2, c: 3}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(alias))
|
||||
(map_content
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(integer))
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))
|
||||
(pair
|
||||
(keyword)
|
||||
(integer))))))
|
||||
|
||||
=====================================
|
||||
trailing separator
|
||||
=====================================
|
||||
|
||||
%User{"a" => 1,}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(alias))
|
||||
(map_content
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(integer)))))
|
||||
|
||||
=====================================
|
||||
update syntax
|
||||
=====================================
|
||||
|
||||
%User{user | name: "Jane", email: "jane@example.com"}
|
||||
%User{user | "name" => "Jane"}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct (alias))
|
||||
(map_content
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(keywords
|
||||
(pair
|
||||
(keyword)
|
||||
(string
|
||||
(quoted_content)))
|
||||
(pair
|
||||
(keyword)
|
||||
(string
|
||||
(quoted_content)))))))
|
||||
(map
|
||||
(struct
|
||||
(alias))
|
||||
(map_content
|
||||
(binary_operator
|
||||
(identifier)
|
||||
(binary_operator
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))))))
|
||||
|
||||
=====================================
|
||||
unused struct identifier
|
||||
=====================================
|
||||
|
||||
%_{}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
matching struct identifier
|
||||
=====================================
|
||||
|
||||
%name{}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(identifier))))
|
||||
|
||||
=====================================
|
||||
pinned struct identifier
|
||||
=====================================
|
||||
|
||||
%^name{}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(unary_operator
|
||||
(identifier)))))
|
||||
|
||||
=====================================
|
||||
with special identifier
|
||||
=====================================
|
||||
|
||||
%__MODULE__{}
|
||||
%__MODULE__.Child{}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(identifier)))
|
||||
(map
|
||||
(struct
|
||||
(dot
|
||||
(identifier)
|
||||
(alias)))))
|
||||
|
||||
=====================================
|
||||
with atom
|
||||
=====================================
|
||||
|
||||
%:"Elixir.Mod"{}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(quoted_atom
|
||||
(quoted_content)))))
|
||||
|
||||
=====================================
|
||||
with call
|
||||
=====================================
|
||||
|
||||
%fun(){}
|
||||
%Mod.fun(){}
|
||||
%fun.(){}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(map
|
||||
(struct
|
||||
(call
|
||||
(identifier)
|
||||
(arguments))))
|
||||
(map
|
||||
(struct
|
||||
(call
|
||||
(dot
|
||||
(alias)
|
||||
(identifier))
|
||||
(arguments))))
|
||||
(map
|
||||
(struct
|
||||
(call
|
||||
(dot
|
||||
(identifier))
|
||||
(arguments)))))
|
||||
@ -1,82 +0,0 @@
|
||||
=====================================
|
||||
simple literal
|
||||
=====================================
|
||||
|
||||
{}
|
||||
{1}
|
||||
{1, 2}
|
||||
{1,2}
|
||||
{ 1 , 2 }
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(tuple)
|
||||
(tuple
|
||||
(integer))
|
||||
(tuple
|
||||
(integer)
|
||||
(integer))
|
||||
(tuple
|
||||
(integer)
|
||||
(integer))
|
||||
(tuple
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
nested
|
||||
=====================================
|
||||
|
||||
{{1}, 1}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(tuple
|
||||
(tuple
|
||||
(integer))
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
trailing separator
|
||||
=====================================
|
||||
|
||||
{1,}
|
||||
{1,2,}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(tuple
|
||||
(integer))
|
||||
(tuple
|
||||
(integer)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
[error] missing element
|
||||
=====================================
|
||||
|
||||
{, 1}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(tuple
|
||||
(ERROR)
|
||||
(integer)))
|
||||
|
||||
=====================================
|
||||
[error] missing separator
|
||||
=====================================
|
||||
|
||||
{1 2}
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(tuple
|
||||
(integer)
|
||||
(ERROR
|
||||
(integer))))
|
||||
@ -1,109 +0,0 @@
|
||||
=====================================
|
||||
atom
|
||||
=====================================
|
||||
|
||||
:time_μs
|
||||
:"£"
|
||||
:'£'
|
||||
:こんにちは世界
|
||||
:Ólá
|
||||
:olá
|
||||
:Olá
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(atom)
|
||||
(quoted_atom
|
||||
(quoted_content))
|
||||
(quoted_atom
|
||||
(quoted_content))
|
||||
(atom)
|
||||
(atom)
|
||||
(atom)
|
||||
(atom))
|
||||
|
||||
=====================================
|
||||
string
|
||||
=====================================
|
||||
|
||||
"time_μs"
|
||||
"£"
|
||||
"こんにちは世界"
|
||||
"Ólá"
|
||||
"olá"
|
||||
"Olá"
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
charlist
|
||||
=====================================
|
||||
|
||||
'time_μs'
|
||||
'£'
|
||||
'こんにちは世界'
|
||||
'Ólá'
|
||||
'olá'
|
||||
'Olá'
|
||||
---
|
||||
|
||||
(source
|
||||
(charlist
|
||||
(quoted_content))
|
||||
(charlist
|
||||
(quoted_content))
|
||||
(charlist
|
||||
(quoted_content))
|
||||
(charlist
|
||||
(quoted_content))
|
||||
(charlist
|
||||
(quoted_content))
|
||||
(charlist
|
||||
(quoted_content)))
|
||||
|
||||
=====================================
|
||||
char
|
||||
=====================================
|
||||
|
||||
?ł
|
||||
?μ
|
||||
?£
|
||||
?こ
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(char)
|
||||
(char)
|
||||
(char)
|
||||
(char))
|
||||
|
||||
=====================================
|
||||
variable
|
||||
=====================================
|
||||
|
||||
time_μs
|
||||
こんにちは世界
|
||||
olá
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier))
|
||||
@ -1,63 +0,0 @@
|
||||
=====================================
|
||||
regular
|
||||
=====================================
|
||||
|
||||
snake_case
|
||||
camelCase
|
||||
az_AZ_19
|
||||
bang!
|
||||
question?
|
||||
doctest
|
||||
not1
|
||||
notfalse
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier))
|
||||
|
||||
=====================================
|
||||
unused
|
||||
=====================================
|
||||
|
||||
_
|
||||
_number
|
||||
__TEST__
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(identifier)
|
||||
(identifier)
|
||||
(identifier))
|
||||
|
||||
=====================================
|
||||
three dots identifier
|
||||
=====================================
|
||||
|
||||
...
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(identifier))
|
||||
|
||||
=====================================
|
||||
special identifier
|
||||
=====================================
|
||||
|
||||
__MODULE__
|
||||
__DIR__
|
||||
|
||||
---
|
||||
|
||||
(source
|
||||
(identifier)
|
||||
(identifier))
|
||||
@ -1,72 +0,0 @@
|
||||
fn x, y, z ->
|
||||
# <- keyword
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
fn(a, b, c) ->
|
||||
# <- keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
&(x + y - z * a / &1 + b + div(&2, c))
|
||||
#<- operator
|
||||
#^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ operator
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
end
|
||||
end
|
||||
|
||||
fn ->
|
||||
# <- keyword
|
||||
# ^ operator
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
&Set.put(&1, &2)
|
||||
# <- operator
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ punctuation.delimiter
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
|
||||
&( Set.put(&1, &1) )
|
||||
#<- operator
|
||||
#^ punctuation.bracket
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ punctuation.delimiter
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
@ -1,90 +0,0 @@
|
||||
Path.expand("..", __DIR__)
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ string
|
||||
# ^ punctuation.delimiter
|
||||
# ^ constant.builtin
|
||||
# ^ punctuation.bracket
|
||||
|
||||
func.(1)
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
|
||||
arg |> func
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ function
|
||||
|
||||
func 1
|
||||
# ^ function
|
||||
# ^ number
|
||||
|
||||
hd([1,2])
|
||||
# <- function
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
|
||||
Kernel.spawn(fn -> :ok end)
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ keyword
|
||||
# ^ operator
|
||||
# ^ string.special.symbol
|
||||
# ^ keyword
|
||||
# ^ punctuation.bracket
|
||||
|
||||
IO.ANSI.black
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
|
||||
Kernel.-(number)
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
|
||||
Enum.map([1, 2], fn x ->
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
x * 2
|
||||
# <- variable
|
||||
# ^ operator
|
||||
# ^ number
|
||||
end)
|
||||
# <- keyword
|
||||
# ^ punctuation.bracket
|
||||
|
||||
:erlang.abs(-1)
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
@ -1,200 +0,0 @@
|
||||
<<1, 2, 3>>
|
||||
# <- punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
|
||||
<< header :: size(8), data :: binary >>
|
||||
# <- punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
|
||||
<<"hello"::binary, c :: utf8, x::[4, unit(2)]>> = "hello™1"
|
||||
# <- punctuation.bracket
|
||||
# ^ string
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ string
|
||||
|
||||
[1, :a, 'hello'] ++ [2, 3]
|
||||
# <- punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
|
||||
[:head | [?t, ?a]]
|
||||
# <- punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ constant
|
||||
# ^ punctuation.delimiter
|
||||
# ^ constant
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
|
||||
{:one, 2.0, "three"}
|
||||
# <- punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.delimiter
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string
|
||||
# ^ punctuation.bracket
|
||||
|
||||
[option: "value", key: :word]
|
||||
# <- punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ string
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
|
||||
[++: "operator", ~~~: :&&&]
|
||||
# <- punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ string
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
|
||||
[...: 1, <<>>: 2, %{}: 3, %: 4, {}: 5]
|
||||
# <- punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
|
||||
["this is an atom too": 1, "so is #{1} this": 2]
|
||||
# <- punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.special
|
||||
# ^ number
|
||||
# ^ punctuation.special
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
|
||||
%{shortcut: "syntax"}
|
||||
#<- punctuation
|
||||
#^ punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ string
|
||||
# ^ punctuation.bracket
|
||||
|
||||
%{map | "update" => "me"}
|
||||
#<- punctuation
|
||||
#^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ string
|
||||
# ^ operator
|
||||
# ^ string
|
||||
# ^ punctuation.bracket
|
||||
|
||||
%{ 12 => 13, :weird => ['thing'] }
|
||||
#<- punctuation
|
||||
#^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ string
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
|
||||
%Long.Module.Name{name: "Silly"}
|
||||
# <- punctuation
|
||||
# ^ module
|
||||
# ^ module
|
||||
# ^ punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ string
|
||||
# ^ punctuation.bracket
|
||||
|
||||
%Long.Module.Name{s | height: {192, :cm}}
|
||||
# <- punctuation
|
||||
# ^ module
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
|
||||
".. #{%Long.Module.Name{s | height: {192, :cm}}} .."
|
||||
# ^ string
|
||||
# ^ punctuation.special
|
||||
# ^ punctuation
|
||||
# ^ module
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.special
|
||||
# ^ string
|
||||
@ -1,15 +0,0 @@
|
||||
abc_123
|
||||
# ^ variable
|
||||
|
||||
_018OP
|
||||
# ^ comment.unused
|
||||
|
||||
A__0
|
||||
# ^ module
|
||||
|
||||
__MODULE__ ; __STACKTRACE__
|
||||
# ^ constant.builtin
|
||||
# ^ constant.builtin
|
||||
|
||||
__OTHER__
|
||||
# ^ comment.unused
|
||||
@ -1,175 +0,0 @@
|
||||
for x <- 1..10, x < 5, do: {x, x}
|
||||
# <- keyword
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
|
||||
for << <<r::4, g::4, b::4, a::size(4)>> <- pixels >> do
|
||||
# <- keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ keyword
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
if :this do
|
||||
# <- keyword
|
||||
# ^ string.special.symbol
|
||||
# ^ keyword
|
||||
:that
|
||||
# ^ string.special.symbol
|
||||
else
|
||||
# <- keyword
|
||||
:otherwise
|
||||
# ^ string.special.symbol
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
receive do
|
||||
# ^ keyword
|
||||
# ^ keyword
|
||||
{:EXIT, _} -> :done
|
||||
# <- punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.delimiter
|
||||
# ^ comment.unused
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ string.special.symbol
|
||||
{ ^pid, :_ } -> nil
|
||||
# <- punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ constant
|
||||
after 100 -> :no_luck
|
||||
# ^ keyword
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ string.special.symbol
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
case __ENV__.line do
|
||||
# ^ keyword
|
||||
# ^ constant.builtin
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ keyword
|
||||
x when is_integer(x) -> x
|
||||
# <- variable
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
x when x in 1..12 -> -x
|
||||
# <- variable
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
# ^ keyword
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
cond do
|
||||
# <- keyword
|
||||
# ^ keyword
|
||||
false -> "too bad"
|
||||
# ^ constant
|
||||
# ^ operator
|
||||
# ^ string
|
||||
4 > 5 -> "oops"
|
||||
# <- number
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ string
|
||||
true -> nil
|
||||
# ^ constant
|
||||
# ^ operator
|
||||
# ^ constant
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
raise RuntimeError, message: "This is not an error"
|
||||
# ^ keyword
|
||||
# ^ module
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ string
|
||||
|
||||
import Kernel, except: [spawn: 1, +: 2, /: 2, Unless: 2]
|
||||
# ^ keyword
|
||||
# ^ module
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
|
||||
alias Long.Module.Name, as: N0men123_and4
|
||||
# ^ keyword
|
||||
# ^ module
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ module
|
||||
|
||||
use Bitwise
|
||||
# ^ keyword
|
||||
# ^ module
|
||||
@ -1,173 +0,0 @@
|
||||
1234 ; 01234
|
||||
# ^ number
|
||||
# ^ punctuation.delimiter
|
||||
# ^ number
|
||||
|
||||
1.23 ; 1.23e10 ; 1.23e-10
|
||||
# ^ number
|
||||
# ^ number
|
||||
# ^ number
|
||||
|
||||
0xab ; 0o171 ; 0b01001
|
||||
# ^ number
|
||||
# ^ number
|
||||
# ^ number
|
||||
|
||||
100_000_000 ; 0b1111_0000
|
||||
# ^ number
|
||||
# ^ number
|
||||
|
||||
?a ; ?1 ; ?\n ; ?\s ; ?\c ; ? ; ?,
|
||||
# <- constant
|
||||
# ^ constant
|
||||
# ^ constant
|
||||
# ^ constant
|
||||
# ^ constant
|
||||
# ^ constant
|
||||
# ^ constant
|
||||
# ^ constant
|
||||
|
||||
true ; false ; nil
|
||||
# ^ constant
|
||||
# ^ constant
|
||||
# ^ constant
|
||||
|
||||
:this ; :that
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
|
||||
:'complex atom'
|
||||
# ^ string.special.symbol
|
||||
|
||||
:"with' \" 'quotes \u0301"
|
||||
# ^ string.special.symbol
|
||||
# ^ string.escape
|
||||
# ^ string.escape
|
||||
# ^ string.special.symbol
|
||||
# ^ string.escape
|
||||
# ^ string.escape
|
||||
|
||||
:"with #{1 + 1} interpol"
|
||||
# ^ punctuation.special
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ punctuation.special
|
||||
|
||||
:... ; :<<>> ; :%{} ; :% ; :{}
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
|
||||
:++ ; :-- ; :* ; :~~~ ; :::
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
|
||||
:% ; :. ; :<-
|
||||
# <- string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
# ^ string.special.symbol
|
||||
|
||||
"simple string"
|
||||
# ^ string
|
||||
# ^ string
|
||||
|
||||
"with \x{ff} code"
|
||||
# ^ string
|
||||
# ^ string.escape
|
||||
# ^ string.escape
|
||||
# ^ string
|
||||
|
||||
"with \7 \016 \t \\s"
|
||||
# ^ string
|
||||
# ^ string.escape
|
||||
# ^ string.escape
|
||||
# ^ string
|
||||
# ^ string.escape
|
||||
# ^ string
|
||||
# ^ string.escape
|
||||
# ^ string
|
||||
|
||||
"with #{inspect "inner"} interpolation"
|
||||
# ^ string
|
||||
# ^ punctuation.special
|
||||
# ^ function
|
||||
# ^ string
|
||||
# ^ punctuation.special
|
||||
# ^ string
|
||||
|
||||
"Multiline
|
||||
string"
|
||||
# <- string
|
||||
# ^ string
|
||||
|
||||
"""
|
||||
Heredoc
|
||||
"""
|
||||
# ^ string
|
||||
|
||||
'charlist'
|
||||
# ^ string
|
||||
|
||||
~s(string sigil #{1})
|
||||
# <- string
|
||||
# ^ string
|
||||
# ^ string
|
||||
# ^ number
|
||||
|
||||
~S/string #{1}/
|
||||
# ^ string
|
||||
|
||||
~r/x?/iu
|
||||
# <- string.regex
|
||||
# ^ string.regex
|
||||
# ^ string.regex
|
||||
|
||||
~R{noescapes\}[a-z]*}
|
||||
# ^ string.regex
|
||||
# ^ string.escape
|
||||
# ^ string.regex
|
||||
|
||||
~w(hello #{ ["has" <> "123", '\c\d', "\123 interpol" | []] } world)s
|
||||
#<- string.special
|
||||
# ^ string.special
|
||||
# ^ punctuation.special
|
||||
# ^ punctuation.bracket
|
||||
# ^ string
|
||||
# ^ operator
|
||||
# ^ string
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string
|
||||
# ^ string.escape
|
||||
# ^ string.escape
|
||||
# ^ string
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string
|
||||
# ^ string.escape
|
||||
# ^ string
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.special
|
||||
# ^ string.special
|
||||
|
||||
~w/yoo \\ \/ =)/
|
||||
# ^ string.special
|
||||
# ^ string.escape
|
||||
# ^ string.escape
|
||||
# ^ string.special
|
||||
|
||||
~W/yoo \\ \/ =)/
|
||||
# ^ string.special
|
||||
# ^ string.special
|
||||
# ^ string.escape
|
||||
# ^ string.special
|
||||
|
||||
~D/2020-01-01/d
|
||||
# ^ string.special
|
||||
@ -1,319 +0,0 @@
|
||||
defmodule Long.Module.Name do
|
||||
# ^ keyword
|
||||
# ^ module
|
||||
# ^ module
|
||||
# ^ keyword
|
||||
|
||||
@moduledoc "Simple doc"
|
||||
# <- comment.doc
|
||||
# ^ comment.doc.__attribute__
|
||||
# ^ comment.doc
|
||||
|
||||
@moduledoc false
|
||||
# <- comment.doc
|
||||
# ^ comment.doc.__attribute__
|
||||
# ^ comment.doc
|
||||
|
||||
@moduledoc """
|
||||
Heredoc doc
|
||||
"""
|
||||
# ^ comment.doc
|
||||
|
||||
@moduledoc ~S'''
|
||||
Sigil doc
|
||||
'''
|
||||
# ^ comment.doc
|
||||
|
||||
@moduledoc "With #{1} interpolation"
|
||||
# ^ punctuation.special
|
||||
# ^ number
|
||||
# ^ punctuation.special
|
||||
|
||||
@typedoc "Type doc"
|
||||
# <- comment.doc
|
||||
|
||||
@doc "Type doc"
|
||||
# <- comment.doc
|
||||
|
||||
@doc """
|
||||
Multiline docstring
|
||||
"with quotes"
|
||||
and #{ inspect %{"interpolation" => "in" <> "action"} }
|
||||
now with #{ {:a, 'tuple'} }
|
||||
and #{ inspect {
|
||||
:tuple,
|
||||
%{ with: "nested #{ inspect %{ :interpolation => %{} } }" }
|
||||
} }
|
||||
"""
|
||||
# <- comment.doc
|
||||
|
||||
@spec func(type, integer()) :: :ok | :fail
|
||||
# <- attribute
|
||||
# ^ attribute
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ string.special.symbol
|
||||
# ^ operator
|
||||
# ^ string.special.symbol
|
||||
|
||||
defstruct items: []
|
||||
# ^ keyword
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
|
||||
defexception [:message]
|
||||
# ^ keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
|
||||
@type item :: String.t()
|
||||
# <- attribute
|
||||
# ^ attribute
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
|
||||
@attr "value"
|
||||
# <- attribute
|
||||
# ^ attribute
|
||||
# ^ string
|
||||
|
||||
@true
|
||||
# ^ attribute
|
||||
|
||||
@nil
|
||||
# ^ attribute
|
||||
|
||||
def f, do: nil
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def f(x), do: x
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ variable
|
||||
|
||||
def f(10), do: nil
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def f(a, b \\ []), do: nil
|
||||
# <- keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def __before_compile__(_) do
|
||||
# <- keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ comment.unused
|
||||
# ^ punctuation.bracket
|
||||
# ^ keyword
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
def with_guard(x) when x == 1 do: nil
|
||||
# <- keyword
|
||||
# ^ function
|
||||
# ^ variable
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ keyword
|
||||
# <- keyword
|
||||
|
||||
def with_guard when is_integer(1), do: nil
|
||||
# <- keyword
|
||||
# ^ function
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ number
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def x + y, do: nil
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def x |> y, do: nil
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def x and y, do: nil
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def unquote(f)(x), do: nil
|
||||
# ^ keyword
|
||||
# ^ keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def unquote(name)(unquote_splicing(args)), do: nil
|
||||
# ^ keyword
|
||||
# ^ keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ constant
|
||||
|
||||
def(test(x), do: x)
|
||||
# ^ keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
|
||||
defguard is_something(one), do: one != nil
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ constant
|
||||
|
||||
defdelegate empty?(list), to: Enum
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ module
|
||||
|
||||
defmacro meta_function(name) do
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
# ^ keyword
|
||||
quote do
|
||||
# ^ keyword
|
||||
# ^ keyword
|
||||
def unquote(:"#{name}_foo")() do
|
||||
# ^ keyword
|
||||
# ^ keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.special
|
||||
# ^ variable
|
||||
# ^ punctuation.special
|
||||
# ^ string.special.symbol
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ punctuation.bracket
|
||||
# ^ keyword
|
||||
unquote("yessir")
|
||||
# ^ keyword
|
||||
# ^ punctuation.bracket
|
||||
# ^ string
|
||||
# ^ punctuation.bracket
|
||||
end
|
||||
# <- keyword
|
||||
end
|
||||
# <- keyword
|
||||
end
|
||||
# <- keyword
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
defprotocol Useless do
|
||||
# ^ keyword
|
||||
# ^ module
|
||||
# ^ keyword
|
||||
def func(this)
|
||||
# ^ keyword
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
end
|
||||
# <- keyword
|
||||
|
||||
defimpl Useless, for: Atom do
|
||||
# ^ keyword
|
||||
# ^ module
|
||||
# ^ punctuation.delimiter
|
||||
# ^ string.special.symbol
|
||||
# ^ module
|
||||
# ^ keyword
|
||||
end
|
||||
# <- keyword
|
||||
@ -1,89 +0,0 @@
|
||||
a in b
|
||||
# <- variable
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
|
||||
a not in b
|
||||
# <- variable
|
||||
# ^ keyword
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
|
||||
a not in b
|
||||
# <- variable
|
||||
# ^ keyword
|
||||
# ^ keyword
|
||||
# ^ variable
|
||||
|
||||
a ~>> b = bind(a, b)
|
||||
# <- variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ punctuation.bracket
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
|
||||
a ~> b
|
||||
# ^ operator
|
||||
|
||||
a + b
|
||||
# ^ operator
|
||||
|
||||
... == !x && y || z
|
||||
# <- variable
|
||||
# ^ operator
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
|
||||
x = 1 + 2.0 * 3
|
||||
# <- variable
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ number
|
||||
# ^ operator
|
||||
# ^ number
|
||||
|
||||
y = true and false
|
||||
# <- variable
|
||||
# ^ operator
|
||||
# ^ constant
|
||||
# ^ keyword
|
||||
# ^ constant
|
||||
|
||||
{ ^z, a } = {true, x}
|
||||
# <- punctuation.bracket
|
||||
# ^ operator
|
||||
# ^ variable
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ operator
|
||||
# ^ punctuation.bracket
|
||||
# ^ constant
|
||||
# ^ punctuation.delimiter
|
||||
# ^ variable
|
||||
# ^ punctuation.bracket
|
||||
|
||||
"hello" |> String.upcase |> String.downcase()
|
||||
# ^ string
|
||||
# ^ operator
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
# ^ operator
|
||||
# ^ module
|
||||
# ^ operator
|
||||
# ^ function
|
||||
|
||||
range = ..
|
||||
# <- variable
|
||||
# ^ operator
|
||||
# ^ operator
|
||||
@ -1,31 +0,0 @@
|
||||
defmodule Foo.Bar.Baz do
|
||||
# ^ definition.module
|
||||
# ^ definition.module
|
||||
# ^ definition.module
|
||||
|
||||
def init(arg) do
|
||||
# ^ definition.function
|
||||
state =
|
||||
arg
|
||||
|> map(&(&1 * 2))
|
||||
# ^ reference.call
|
||||
|> map(&(&1 + 1))
|
||||
# ^ reference.call
|
||||
|
||||
{:ok, arg}
|
||||
end
|
||||
|
||||
def map(list, fun, acc \\ [])
|
||||
# ^ definition.function
|
||||
|
||||
def map([head | rest], fun, acc) do
|
||||
# ^ definition.function
|
||||
map(rest, fun, [fun.(head) | acc])
|
||||
# <- reference.call
|
||||
end
|
||||
|
||||
def map([], _fun, acc), do: Enum.reverse(acc)
|
||||
# ^ definition.function
|
||||
# ^ reference.module
|
||||
# ^ reference.call
|
||||
end
|
||||
@ -1,21 +0,0 @@
|
||||
defprotocol Countable do
|
||||
# ^ definition.module
|
||||
def count(data)
|
||||
# ^ definition.function
|
||||
end
|
||||
|
||||
defimpl Countable, for: Binary do
|
||||
# ^ reference.module
|
||||
# ^ reference.module
|
||||
def count(binary), do: byte_size(binary)
|
||||
# ^ definition.function
|
||||
# ^ reference.call
|
||||
end
|
||||
|
||||
defimpl Countable, for: List do
|
||||
# ^ reference.module
|
||||
# ^ reference.module
|
||||
def count(list), do: length(list)
|
||||
# ^ definition.function
|
||||
# ^ reference.call
|
||||
end
|
||||
Loading…
Reference in New Issue