mirror of https://github.com/Wilfred/difftastic/
Initial commit
fbshipit-source-id: ba4d26ff8ff932e614e343d0c8cac90abf5f2776pull/454/head
commit
a8b8b0e16c
@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report unexpected parsing results
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
The following piece of code is valid but it is parsed incorrectly:
|
||||
|
||||
```javascript
|
||||
|
||||
```
|
||||
|
||||
Here's a link to the TypeScript Playground showing that the snippet above is valid JavaScript or TypeScript:
|
||||
<!-- Please check your code at https://www.typescriptlang.org/play
|
||||
and paste the URL below. -->
|
||||
|
||||
<!-- Please run `tree-sitter parse YOUR_FILE` and show us the output. -->
|
||||
The output of `tree-sitter parse` is the following:
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
<!-- If there is no `ERROR` or `MISSING` node in the output above,
|
||||
explain what you were expecting: -->
|
||||
|
||||
<!-- Name of the broken/missing feature, link to official
|
||||
documentation, and any other relevant info is appreciated: -->
|
||||
@ -0,0 +1,13 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
The tree-sitter-erlang project is an Erlang parser only.
|
||||
How can we improve it?
|
||||
-->
|
||||
@ -0,0 +1,22 @@
|
||||
name: Build/test
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- "**"
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
@ -0,0 +1,11 @@
|
||||
*.wasm
|
||||
node_modules
|
||||
build
|
||||
examples
|
||||
*.log
|
||||
|
||||
# Output of running `npm run parse -- --debug-graph foo.erl`
|
||||
log.html
|
||||
|
||||
# Input to the parse test
|
||||
foo.erl
|
||||
@ -0,0 +1,10 @@
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"bracketSameLine": true,
|
||||
"bracketSpacing": false,
|
||||
"requirePragma": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"tabWidth": 4,
|
||||
"indentSize": 4
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
1.0.0 (September 26, 2022)
|
||||
|
||||
* Initial Release
|
||||
@ -0,0 +1,80 @@
|
||||
# Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to make participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all project spaces, and it also applies when
|
||||
an individual is representing the project or its community in public spaces.
|
||||
Examples of representing a project or community include using an official
|
||||
project e-mail address, posting via an official social media account, or acting
|
||||
as an appointed representative at an online or offline event. Representation of
|
||||
a project may be further defined and clarified by project maintainers.
|
||||
|
||||
This Code of Conduct also applies outside the project spaces when there is a
|
||||
reasonable belief that an individual's behavior may have a negative impact on
|
||||
the project or its community.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at <opensource-conduct@fb.com>. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
@ -0,0 +1,35 @@
|
||||
# Contributing to tree-sitter-erlang
|
||||
|
||||
We want to make contributing to this project as easy and transparent as possible.
|
||||
|
||||
## Our Development Process
|
||||
|
||||
tree-sitter-erlang is currently developed in Meta's internal repositories and then exported
|
||||
out to GitHub by a Meta team member; however, we invite you to submit pull
|
||||
requests as described below.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
We actively welcome your pull requests.
|
||||
|
||||
1. Fork the repo and create your branch from `main`.
|
||||
2. If you've added code that should be tested, add tests.
|
||||
3. Ensure the test suite passes.
|
||||
4. If you haven't already, complete the Contributor License Agreement ("CLA").
|
||||
|
||||
## Contributor License Agreement ("CLA")
|
||||
|
||||
In order to accept your pull request, we need you to submit a CLA. You only need
|
||||
to do this once to work on any of Facebook's open source projects.
|
||||
|
||||
Complete your CLA here: <https://code.facebook.com/cla>
|
||||
|
||||
## Issues
|
||||
|
||||
We use GitHub issues to track public bugs. Please ensure your description is
|
||||
clear and has sufficient instructions to be able to reproduce the issue.
|
||||
|
||||
## License
|
||||
|
||||
By contributing to tree-sitter-erlang, you agree that your contributions will be
|
||||
licensed under the [LICENSE](LICENSE) in the root directory of this source tree.
|
||||
@ -0,0 +1,25 @@
|
||||
[package]
|
||||
categories = ["parsing", "text-editors"]
|
||||
description = "erlang grammar for the tree-sitter parsing library"
|
||||
edition = "2018"
|
||||
keywords = ["incremental", "parsing", "erlang"]
|
||||
license = "MIT"
|
||||
name = "tree-sitter-erlang"
|
||||
version = "0.0.1"
|
||||
|
||||
build = "bindings/rust/build.rs"
|
||||
include = [
|
||||
"bindings/rust/*",
|
||||
"grammar.js",
|
||||
"queries/*",
|
||||
"src/*",
|
||||
]
|
||||
|
||||
[lib]
|
||||
path = "bindings/rust/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
tree-sitter = "0.20.9"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0.73"
|
||||
@ -0,0 +1,201 @@
|
||||
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
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@ -0,0 +1,42 @@
|
||||
# TREE_SITTER=tree-sitter
|
||||
TREE_SITTER=npm run
|
||||
|
||||
all: fmt gen test
|
||||
|
||||
fmt:
|
||||
./node_modules/.bin/prettier --write grammar.js
|
||||
|
||||
.PHONY: test
|
||||
test: gen
|
||||
$(TREE_SITTER) test
|
||||
|
||||
.PHONY: update
|
||||
update: gen
|
||||
$(TREE_SITTER) test -- --update
|
||||
|
||||
.PHONY: debug
|
||||
debug: gen
|
||||
$(TREE_SITTER) test -d
|
||||
|
||||
.PHONY: gen
|
||||
gen:
|
||||
$(TREE_SITTER) generate
|
||||
ruby -e 'ARGV.each{|f| File.write(f, "// @"+"generated\n\n"+File.read(f))}' src/parser.c src/tree_sitter/parser.h
|
||||
ruby -rjson -e 'ARGV.each{|f| File.write(f, JSON.pretty_generate(JSON.parse(File.read(f)).tap{|j| j["@"+"generated"] = true}))}' src/grammar.json
|
||||
ruby -rjson -e 'ARGV.each{|f| File.write(f, JSON.pretty_generate(JSON.parse(File.read(f)).tap{|j| j << {"@"+"generated" => true}}))}' src/node-types.json
|
||||
|
||||
.PHONY: deps
|
||||
deps:
|
||||
npm install
|
||||
|
||||
.PHONY: web
|
||||
web: wasm
|
||||
$(TREE_SITTER) web-ui
|
||||
|
||||
.PHONY: wasm
|
||||
wasm:
|
||||
$(TREE_SITTER) build-wasm
|
||||
|
||||
.PHONY: publish
|
||||
publish: all wasm
|
||||
cp ./tree-sitter-erlang.wasm ./docs
|
||||
@ -0,0 +1,34 @@
|
||||
# Tree Sitter Erlang
|
||||
|
||||
This represents tree-sitter grammar used for the Erlang language in the
|
||||
ELP project.
|
||||
|
||||
It started as a direct clone of
|
||||
https://github.com/AbstractMachinesLab/tree-sitter-erlang at
|
||||
[7b436e1ca50f0002f6765a9a2a00f6156b2cc881](https://github.com/AbstractMachinesLab/tree-sitter-erlang/commit/7b436e1ca50f0002f6765a9a2a00f6156b2cc881),
|
||||
but was later heavily modified for completeness.
|
||||
|
||||
## Usage
|
||||
|
||||
Install the required toolchain with
|
||||
|
||||
```
|
||||
make deps
|
||||
```
|
||||
|
||||
Edit the `grammar.js` file and re-generate the code with:
|
||||
|
||||
```
|
||||
make gen
|
||||
```
|
||||
|
||||
Useful test command, parses `foo.erl` and opens a browser window to
|
||||
show the process, with pretty pictures of the generated AST.
|
||||
|
||||
```
|
||||
npm run parse -- --debug-graph testdata/foo.erl
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
tree-sitter-erlang is [Apache licensed](./LICENSE).
|
||||
@ -0,0 +1,18 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "tree_sitter_erlang_binding",
|
||||
"include_dirs": [
|
||||
"<!(node -e \"require('nan')\")",
|
||||
"src"
|
||||
],
|
||||
"sources": [
|
||||
"src/parser.c",
|
||||
"bindings/node/binding.cc"
|
||||
],
|
||||
"cflags_c": [
|
||||
"-std=c99",
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
// @generated
|
||||
|
||||
#include "tree_sitter/parser.h"
|
||||
#include <node.h>
|
||||
#include "nan.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
extern "C" TSLanguage * tree_sitter_erlang();
|
||||
|
||||
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_erlang());
|
||||
|
||||
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("erlang").ToLocalChecked());
|
||||
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
|
||||
}
|
||||
|
||||
NODE_MODULE(tree_sitter_erlang_binding, Init)
|
||||
|
||||
} // namespace
|
||||
@ -0,0 +1,19 @@
|
||||
try {
|
||||
module.exports = require("../../build/Release/tree_sitter_erlang_binding");
|
||||
} catch (error1) {
|
||||
if (error1.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error1;
|
||||
}
|
||||
try {
|
||||
module.exports = require("../../build/Debug/tree_sitter_erlang_binding");
|
||||
} catch (error2) {
|
||||
if (error2.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error2;
|
||||
}
|
||||
throw error1
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
module.exports.nodeTypeInfo = require("../../src/node-types.json");
|
||||
} catch (_) {}
|
||||
@ -0,0 +1,43 @@
|
||||
// Note: If this file does not exist, it is generated by `tree-sitter generate`.
|
||||
|
||||
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-const-variable")
|
||||
.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);
|
||||
|
||||
// If your language uses an external scanner written in C,
|
||||
// then include this block of code:
|
||||
|
||||
/*
|
||||
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");
|
||||
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
|
||||
|
||||
// If your language uses an external scanner written in C++,
|
||||
// then include this block of code:
|
||||
|
||||
/*
|
||||
let mut cpp_config = cc::Build::new();
|
||||
cpp_config.cpp(true);
|
||||
cpp_config.include(&src_dir);
|
||||
cpp_config
|
||||
.flag_if_supported("-Wno-unused-parameter")
|
||||
.flag_if_supported("-Wno-unused-but-set-variable");
|
||||
let scanner_path = src_dir.join("scanner.cc");
|
||||
cpp_config.file(&scanner_path);
|
||||
cpp_config.compile("scanner");
|
||||
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
|
||||
*/
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
// Note: If this file does not exist, it is generated by `tree-sitter generate`.
|
||||
|
||||
//! This crate provides erlang language support for the [tree-sitter][] parsing library.
|
||||
//!
|
||||
//! 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_erlang::language()).expect("Error loading erlang 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_erlang() -> 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_erlang() }
|
||||
}
|
||||
|
||||
/// 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 erlang language");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,948 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Higher value == higher precedence
|
||||
const PREC = {
|
||||
CATCH: 0,
|
||||
DCOLON: 1, // `::`
|
||||
PIPE: 2, // `|`
|
||||
PREFIX_OP: 3, // prefix op binds directly to its argument
|
||||
MULT_OP: 4, // mult_op is left-associative
|
||||
ADD_OP: 4, // add_op is left-associative
|
||||
DOTDOT: 6, // `..` in Type
|
||||
DARROW: 7, // `=>` in Type, Expr
|
||||
CEQ: 8, // `:=` in Type, Expr
|
||||
EQ: 12, // `:=` in Expr
|
||||
BANG: 13, // `:=` in Expr
|
||||
ORELSE: 14, // `:=` in Expr
|
||||
ANDALSO: 15, // `:=` in Expr
|
||||
LIST_OP: 16, // `:=` in Expr
|
||||
COMP_OP: 17, // `:=` in Expr
|
||||
|
||||
// For remote vs binary :
|
||||
CALL: 80,
|
||||
REMOTE: 1,
|
||||
BIT_EXPR: 2,
|
||||
|
||||
// In macro def, prefer expressions, if type and expr would parse
|
||||
DYN_CR_CLAUSES: 1,
|
||||
DYN_FUNCTION_CLAUSES: 2,
|
||||
DYN_GUARD_OR: 3,
|
||||
DYN_GUARD_AND: 4,
|
||||
DYN_EXPR: 5,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Combinators
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
const sepBy1 = (sep, x) => seq(x, repeat(seq(sep, x)));
|
||||
const sepBy = (sep, x) => optional(sepBy1(sep, x));
|
||||
|
||||
const atom_const = (x) => choice(x, alias('\'' + x + '\'', x));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Grammar
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Experimenting with converting the erlfmt grammar
|
||||
|
||||
module.exports = grammar({
|
||||
name: 'erlang',
|
||||
|
||||
word: $ => $.atom,
|
||||
|
||||
extras: $ => [
|
||||
// $.whitespace causes issues with error recovery,
|
||||
// emulate it manually when traversing the tree
|
||||
/[\x01-\x20\x80-\xA0]/,
|
||||
$.comment,
|
||||
],
|
||||
|
||||
inline: $ => [
|
||||
$._fun_expr,
|
||||
$._map_expr,
|
||||
$._record_expr,
|
||||
$._exprs,
|
||||
$._catch_clauses,
|
||||
],
|
||||
|
||||
supertypes: $ => [
|
||||
$._form,
|
||||
$._preprocessor_directive,
|
||||
$._include_detail,
|
||||
$._function_or_macro_clause,
|
||||
$._macro_def_replacement,
|
||||
$._arity_value,
|
||||
$._concatable,
|
||||
$._name,
|
||||
$._macro_name,
|
||||
$._lc_expr,
|
||||
$._cr_clause_or_macro,
|
||||
$._bit_type,
|
||||
$._bit_expr,
|
||||
$._map_expr_base,
|
||||
$._record_expr_base,
|
||||
$._expr,
|
||||
$._expr_max,
|
||||
$._catch_pat,
|
||||
],
|
||||
|
||||
|
||||
// The erlfmt grammar tries to parse a complete `define` attribute
|
||||
// for an expression, if that fails it tries for a type, if that
|
||||
// fails for a clause.
|
||||
// Instead, we allow conflicts between _expr and type, and clause.
|
||||
conflicts: $ => [
|
||||
// `Base#record{...}` vs `Base#{...}`
|
||||
[$._record_expr_base, $._map_expr_base],
|
||||
// In some places we don't accept args for a macro, it would create even more conflicts
|
||||
[$.macro_call_expr, $.macro_call_none],
|
||||
// Concatables are ambiguous
|
||||
[$._expr_max, $._concatable],
|
||||
[$._expr_max, $._name],
|
||||
// All can be just a macro and can apprear in the macro definition
|
||||
[$._function_or_macro_clause, $._cr_clause_or_macro, $._macro_body_expr],
|
||||
// This is intentionally ambiguous to simplify the produced tree
|
||||
[$._macro_def_replacement, $.replacement_guard_and],
|
||||
[$._macro_def_replacement, $.replacement_guard_or],
|
||||
// Fun type vs regular function `fun()` vs `fun() -> ...`
|
||||
[$.fun_type, $.expr_args],
|
||||
],
|
||||
|
||||
rules: {
|
||||
|
||||
source_file: $ => field('forms', repeat($._form)),
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
_form: $ => choice(
|
||||
$.module_attribute,
|
||||
$.behaviour_attribute,
|
||||
$.export_attribute,
|
||||
$.import_attribute,
|
||||
$.export_type_attribute,
|
||||
$.optional_callbacks_attribute,
|
||||
$.compile_options_attribute,
|
||||
$.file_attribute,
|
||||
$.record_decl,
|
||||
$.type_alias,
|
||||
$.opaque,
|
||||
$.spec,
|
||||
$.callback,
|
||||
$.wild_attribute,
|
||||
$.fun_decl,
|
||||
// preprocessor, not an OTP abstract form
|
||||
$._preprocessor_directive,
|
||||
),
|
||||
|
||||
_preprocessor_directive: $ => choice(
|
||||
$.pp_include,
|
||||
$.pp_include_lib,
|
||||
// https://www.erlang.org/doc/reference_manual/macros.html#flow-control-in-macros
|
||||
$.pp_undef,
|
||||
$.pp_ifdef,
|
||||
$.pp_ifndef,
|
||||
$.pp_else,
|
||||
$.pp_endif,
|
||||
$.pp_if,
|
||||
$.pp_elif,
|
||||
|
||||
$.pp_define,
|
||||
),
|
||||
pp_include: $ => seq(
|
||||
'-', atom_const('include'), '(',
|
||||
field("file", repeat1($._include_detail)),
|
||||
')', '.'
|
||||
),
|
||||
pp_include_lib: $ => seq(
|
||||
'-', atom_const('include_lib'), '(',
|
||||
field("file", repeat1($._include_detail)),
|
||||
')', '.'
|
||||
),
|
||||
pp_undef: $ => seq('-', atom_const('undef'), '(', field("name", $._macro_name), ')', '.'),
|
||||
pp_ifdef: $ => seq('-', atom_const('ifdef'), '(', field("name", $._macro_name), ')', '.'),
|
||||
pp_ifndef: $ => seq('-', atom_const('ifndef'), '(', field("name", $._macro_name), ')', '.'),
|
||||
pp_else: $ => seq('-', atom_const('else'), '.'),
|
||||
pp_endif: $ => seq('-', atom_const('endif'), '.'),
|
||||
pp_if: $ => seq('-', atom_const('if'), field("cond", $._expr), '.'),
|
||||
pp_elif: $ => seq('-', atom_const('elif'), field("cond", $._expr), '.'),
|
||||
|
||||
pp_define: $ => seq(
|
||||
'-',
|
||||
atom_const('define'),
|
||||
'(',
|
||||
field("lhs", $.macro_lhs),
|
||||
',',
|
||||
field("replacement", optional($._macro_def_replacement)),
|
||||
')',
|
||||
'.',
|
||||
),
|
||||
|
||||
_include_detail: $ => choice(
|
||||
$.string,
|
||||
$.macro_call_expr
|
||||
),
|
||||
|
||||
module_attribute: $ => seq('-', atom_const('module'), '(', field("name", $._name), ')', '.'),
|
||||
|
||||
behaviour_attribute: $ => seq(
|
||||
'-',
|
||||
choice(atom_const('behaviour'), atom_const('behavior')),
|
||||
'(',
|
||||
field("name", $._name),
|
||||
')',
|
||||
'.'
|
||||
),
|
||||
|
||||
export_attribute: $ => seq(
|
||||
'-',
|
||||
atom_const('export'),
|
||||
'(',
|
||||
'[',
|
||||
sepBy(optional(','), field("funs", $.fa)),
|
||||
']',
|
||||
')',
|
||||
'.'
|
||||
),
|
||||
|
||||
import_attribute: $ => seq(
|
||||
'-', atom_const('import'), '(',
|
||||
field("module", $._name), ',',
|
||||
'[', sepBy(optional(','), field("funs", $.fa)), ']', ')', '.'),
|
||||
|
||||
optional_callbacks_attribute: $ => seq(
|
||||
'-', atom_const('optional_callbacks'), '(', '[',
|
||||
sepBy(optional(','), field("callbacks", $.fa)),
|
||||
']', ')', '.',
|
||||
),
|
||||
|
||||
// Used in imports and exports only, make it concrete.
|
||||
fa: $ => seq(field("fun", $._name), field("arity", $.arity)),
|
||||
|
||||
export_type_attribute: $ => seq(
|
||||
'-',
|
||||
atom_const('export_type'),
|
||||
'(',
|
||||
'[',
|
||||
sepBy(optional(','), field("types", $.fa)),
|
||||
']',
|
||||
')',
|
||||
'.'
|
||||
),
|
||||
|
||||
compile_options_attribute: $ => seq(
|
||||
'-',
|
||||
atom_const('compile'),
|
||||
'(',
|
||||
field("options", $._expr),
|
||||
')',
|
||||
'.'
|
||||
),
|
||||
|
||||
file_attribute: $ => seq(
|
||||
'-',
|
||||
atom_const('file'),
|
||||
'(',
|
||||
field("original_file", $.string), ',',
|
||||
field("original_line", $.integer),
|
||||
')', '.'),
|
||||
|
||||
type_alias: $ => seq('-', atom_const('type'), $._type_def, '.'),
|
||||
|
||||
opaque: $ => seq('-', atom_const('opaque'), $._type_def, '.'),
|
||||
|
||||
_type_def: $ => choice(
|
||||
seq(field("name", $.type_name), '::', field("ty", $._expr)),
|
||||
seq('(', field("name", $.type_name), '::', field("ty", $._expr), ')')
|
||||
),
|
||||
type_name: $ => seq(field("name", $._name), field("args", $.var_args)),
|
||||
|
||||
record_decl: $ => seq(
|
||||
'-',
|
||||
atom_const('record'),
|
||||
'(',
|
||||
field("name", $._name),
|
||||
optional(','),
|
||||
$._record_tuple,
|
||||
')',
|
||||
'.',
|
||||
),
|
||||
|
||||
spec: $ => seq('-', atom_const('spec'), $._spec_def, '.'),
|
||||
|
||||
callback: $ => seq('-', atom_const('callback'), $._spec_def, '.'),
|
||||
|
||||
_spec_def: $ => choice(
|
||||
seq($._spec_fun, sepBy1(';', field("sigs", $.type_sig))),
|
||||
seq('(', $._spec_fun, sepBy1(';', field("sigs", $.type_sig)), ')'),
|
||||
),
|
||||
|
||||
_spec_fun: $ => seq(field("module", optional($.module)), field("fun", $._name)),
|
||||
module: $ => seq(field("name", $._name), ':'),
|
||||
|
||||
wild_attribute: $ => seq(field("name", $.attr_name), field("value", $._expr), '.'),
|
||||
|
||||
attr_name: $ => seq('-', field("name", $._name)),
|
||||
|
||||
fun_decl: $ => seq(
|
||||
sepBy1(optional(';'), field("clauses", $._function_or_macro_clause)),
|
||||
'.'
|
||||
),
|
||||
|
||||
type_sig: $ => seq(
|
||||
field("args", $.expr_args),
|
||||
'->',
|
||||
field("ty", $._expr),
|
||||
optional(field("guard", $.type_guards)),
|
||||
),
|
||||
|
||||
type_guards: $ => seq('when', sepBy1(',', field("guards", $.ann_type))),
|
||||
|
||||
ann_type: $ => prec(PREC.DCOLON, seq(field("var", $.ann_var), field("ty", $._expr))),
|
||||
|
||||
ann_var: $ => prec(PREC.DCOLON, seq(field("var", $.var), '::')),
|
||||
|
||||
// Both union type and list tail
|
||||
pipe: $ => prec.right(PREC.PIPE, seq(field("lhs", $._expr), '|', field("rhs", $._expr))),
|
||||
|
||||
fun_type: $ => seq('fun', '(', field("sig", optional($.fun_type_sig)), ')'),
|
||||
|
||||
fun_type_sig: $ => seq(
|
||||
field("args", $.expr_args),
|
||||
'->',
|
||||
field("ty", $._expr)
|
||||
),
|
||||
|
||||
range_type: $ => prec.left(PREC.DOTDOT, seq(
|
||||
field("lhs", $._expr),
|
||||
'..',
|
||||
field("rhs", $._expr)
|
||||
)),
|
||||
|
||||
_function_or_macro_clause: $ => choice(
|
||||
$.function_clause,
|
||||
$.macro_call_expr,
|
||||
),
|
||||
|
||||
function_clause: $ => seq(
|
||||
field("name", $._name),
|
||||
field("args", $.expr_args),
|
||||
optional($._clause_guard),
|
||||
field("body", $.clause_body)
|
||||
),
|
||||
|
||||
// This is optional, but tree-sitter complains if we put
|
||||
// 'optional' here, must put it at each usage site.
|
||||
_clause_guard: $ => seq('when', field("guard", $.guard)),
|
||||
|
||||
clause_body: $ => prec.right(seq('->', sepBy1(',', field("exprs", $._expr)))),
|
||||
|
||||
_expr: $ => choice(
|
||||
$.ann_type,
|
||||
$.pipe,
|
||||
$.dotdotdot,
|
||||
$.range_type,
|
||||
$.catch_expr,
|
||||
$.binary_op_expr,
|
||||
$.match_expr,
|
||||
$.unary_op_expr,
|
||||
$._map_expr,
|
||||
$.call,
|
||||
$._record_expr,
|
||||
$.remote,
|
||||
$._expr_max,
|
||||
),
|
||||
|
||||
dotdotdot: $ => '...',
|
||||
|
||||
catch_expr: $ => prec(PREC.CATCH, seq('catch', field("expr", $._expr))),
|
||||
|
||||
match_expr: $ =>
|
||||
prec.right(PREC.EQ, seq(
|
||||
field("lhs", $._expr),
|
||||
'=',
|
||||
field("rhs", prec.right($._expr)),
|
||||
)),
|
||||
binary_op_expr: $ => choice(
|
||||
prec.right(PREC.BANG, seq(
|
||||
field("lhs", $._expr),
|
||||
'!',
|
||||
field("rhs", $._expr),
|
||||
)),
|
||||
prec.right(PREC.ORELSE, seq(
|
||||
field("lhs", $._expr),
|
||||
'orelse',
|
||||
field("rhs", $._expr),
|
||||
)),
|
||||
prec.right(PREC.ANDALSO, seq(
|
||||
field("lhs", $._expr),
|
||||
'andalso',
|
||||
field("rhs", $._expr),
|
||||
)),
|
||||
prec.left(PREC.COMP_OP, seq(
|
||||
field("lhs", $._expr),
|
||||
$._comp_op,
|
||||
field("rhs", $._expr),
|
||||
)),
|
||||
prec.right(PREC.LIST_OP, seq(
|
||||
field("lhs", $._expr),
|
||||
$._list_op,
|
||||
field("rhs", $._expr),
|
||||
)),
|
||||
prec.left(PREC.ADD_OP, seq(
|
||||
field("lhs", $._expr),
|
||||
$._add_op,
|
||||
field("rhs", $._expr),
|
||||
)),
|
||||
prec.left(PREC.MULT_OP, seq(
|
||||
field("lhs", $._expr),
|
||||
$._mult_op,
|
||||
field("rhs", $._expr),
|
||||
)),
|
||||
),
|
||||
|
||||
unary_op_expr: $ => prec(PREC.PREFIX_OP, seq(
|
||||
$._prefix_op,
|
||||
field("operand", $._expr),
|
||||
)),
|
||||
|
||||
_expr_max: $ => choice(
|
||||
$.char,
|
||||
$.integer,
|
||||
$.atom,
|
||||
$.float,
|
||||
$.string,
|
||||
$.concatables,
|
||||
$._macro_body_expr,
|
||||
$.var,
|
||||
$.list,
|
||||
$.binary,
|
||||
$.list_comprehension,
|
||||
$.binary_comprehension,
|
||||
$.tuple,
|
||||
$.paren_expr,
|
||||
$.block_expr,
|
||||
$.if_expr,
|
||||
$.case_expr,
|
||||
$.receive_expr,
|
||||
$._fun_expr,
|
||||
$.try_expr,
|
||||
),
|
||||
|
||||
remote: $ => prec.right(PREC.REMOTE, seq(field("module", $.remote_module), field("fun", $._expr_max))),
|
||||
remote_module: $ => prec(PREC.REMOTE, seq(field("module", $._expr_max), ':')),
|
||||
|
||||
paren_expr: $ => seq('(', field("expr", $._expr), ')'),
|
||||
block_expr: $ => seq('begin', sepBy1(',', field("exprs", $._expr)), 'end'),
|
||||
|
||||
list: $ => seq(
|
||||
'[',
|
||||
sepBy(',', field("exprs", $._expr)),
|
||||
']',
|
||||
),
|
||||
|
||||
binary: $ => seq(
|
||||
'<<',
|
||||
sepBy(',', field("elements", $.bin_element)),
|
||||
'>>',
|
||||
),
|
||||
|
||||
bin_element: $ => seq(
|
||||
field("element", $._bit_expr),
|
||||
field("size", optional($.bit_size_expr)),
|
||||
field("types", optional($.bit_type_list)),
|
||||
),
|
||||
bit_size_expr: $ => seq(
|
||||
':',
|
||||
field("size", $._bit_expr),
|
||||
),
|
||||
bit_type_list: $ => seq(
|
||||
'/',
|
||||
sepBy1('-', field("types", $._bit_type)),
|
||||
),
|
||||
|
||||
_bit_expr: $ => prec(PREC.BIT_EXPR, choice(
|
||||
alias($.unary_op_expr_max, $.unary_op_expr),
|
||||
alias($.binary_op_expr_max, $.binary_op_expr),
|
||||
$._expr_max,
|
||||
)),
|
||||
|
||||
unary_op_expr_max: $ => prec(PREC.PREFIX_OP, seq(
|
||||
$._prefix_op,
|
||||
field("operand", $._expr_max),
|
||||
)),
|
||||
|
||||
binary_op_expr_max: $ => prec(PREC.MULT_OP, seq(
|
||||
field("lhs", $._expr_max),
|
||||
'*',
|
||||
field("rhs", $._expr_max),
|
||||
)),
|
||||
|
||||
_bit_type: $ => choice(
|
||||
$._name,
|
||||
$.bit_type_unit,
|
||||
),
|
||||
bit_type_unit: $ => seq('unit', ':', field("size", $._arity_value)),
|
||||
|
||||
list_comprehension: $ => seq(
|
||||
'[',
|
||||
field("expr", $._expr),
|
||||
field("lc_exprs", $.lc_exprs),
|
||||
']'
|
||||
),
|
||||
binary_comprehension: $ => seq(
|
||||
'<<',
|
||||
field("expr", $._expr_max),
|
||||
field("lc_exprs", $.lc_exprs),
|
||||
'>>'
|
||||
),
|
||||
|
||||
lc_exprs: $ => seq('||', sepBy1(',', field("exprs", $._lc_expr))),
|
||||
|
||||
_lc_expr: $ => choice(
|
||||
$._expr,
|
||||
$.generator,
|
||||
$.b_generator,
|
||||
),
|
||||
|
||||
generator: $ => seq(
|
||||
field("lhs", $._expr),
|
||||
'<-',
|
||||
field("rhs", $._expr),
|
||||
),
|
||||
b_generator: $ => seq(
|
||||
field("lhs", $._expr),
|
||||
'<=',
|
||||
field("rhs", $._expr),
|
||||
),
|
||||
|
||||
tuple: $ => seq(
|
||||
'{',
|
||||
sepBy(',', field("expr", $._expr)),
|
||||
'}'
|
||||
),
|
||||
|
||||
_map_expr: $ => choice(
|
||||
$.map_expr,
|
||||
$.map_expr_update,
|
||||
),
|
||||
|
||||
map_expr_update: $ => prec.right(seq(
|
||||
field("expr", $._map_expr_base),
|
||||
'#',
|
||||
'{',
|
||||
sepBy(',', field("fields", $.map_field)),
|
||||
'}',
|
||||
)),
|
||||
|
||||
map_expr: $ => seq(
|
||||
'#',
|
||||
'{',
|
||||
sepBy(',', field("fields", $.map_field)),
|
||||
'}',
|
||||
),
|
||||
|
||||
_map_expr_base: $ => choice(
|
||||
$._expr_max,
|
||||
$._map_expr,
|
||||
),
|
||||
|
||||
map_field: $ => prec.left(PREC.DARROW, seq(
|
||||
field("key", $._expr),
|
||||
$._map_field_op,
|
||||
field("value", $._expr),
|
||||
)),
|
||||
_map_field_op: $ => choice('=>', ':='),
|
||||
|
||||
_record_expr: $ => choice(
|
||||
$.record_index_expr,
|
||||
$.record_field_expr,
|
||||
$.record_update_expr,
|
||||
$.record_expr,
|
||||
),
|
||||
|
||||
record_index_expr: $ => seq(
|
||||
field("name", $.record_name),
|
||||
field("field", $.record_field_name),
|
||||
),
|
||||
|
||||
record_field_expr: $ => prec.right(seq(
|
||||
field("expr", $._record_expr_base),
|
||||
field("name", $.record_name),
|
||||
field("field", $.record_field_name),
|
||||
)),
|
||||
|
||||
record_update_expr: $ => prec.right(seq(
|
||||
field("expr", $._record_expr_base),
|
||||
field("name", $.record_name),
|
||||
$._record_tuple,
|
||||
)),
|
||||
|
||||
record_expr: $ => seq(
|
||||
field("name", $.record_name),
|
||||
$._record_tuple,
|
||||
),
|
||||
|
||||
record_name: $ => seq('#', field("name", $._name)),
|
||||
|
||||
record_field_name: $ => seq('.', field("name", $._name)),
|
||||
|
||||
_record_expr_base: $ => choice(
|
||||
$._expr_max,
|
||||
$._record_expr,
|
||||
),
|
||||
|
||||
_record_tuple: $ => seq(
|
||||
'{',
|
||||
optional(sepBy1(',', field("fields", $.record_field))),
|
||||
'}'
|
||||
),
|
||||
|
||||
record_field: $ => seq(
|
||||
field("name", $._name),
|
||||
optional(field("expr", $.field_expr)),
|
||||
optional(field("ty", $.field_type)),
|
||||
),
|
||||
|
||||
field_expr: $ => seq('=', field("expr", $._expr)),
|
||||
|
||||
field_type: $ => seq('::', field("expr", $._expr)),
|
||||
|
||||
call: $ => prec(PREC.CALL, seq(
|
||||
field("expr", $._expr),
|
||||
field("args", $.expr_args),
|
||||
)),
|
||||
|
||||
if_expr: $ => seq(
|
||||
'if',
|
||||
optional(sepBy1(';', field("clauses", $.if_clause))),
|
||||
'end',
|
||||
),
|
||||
|
||||
if_clause: $ => seq(
|
||||
field("guard", $.guard),
|
||||
field("body", $.clause_body),
|
||||
),
|
||||
|
||||
case_expr: $ => seq(
|
||||
'case',
|
||||
field("expr", $._expr),
|
||||
'of',
|
||||
optional($._cr_clauses),
|
||||
'end',
|
||||
),
|
||||
|
||||
_cr_clauses: $ => sepBy1(';', field("clauses", $._cr_clause_or_macro)),
|
||||
|
||||
_cr_clause_or_macro: $ => choice(
|
||||
$.cr_clause,
|
||||
$.macro_call_expr,
|
||||
),
|
||||
|
||||
cr_clause: $ => seq(
|
||||
field("pat", $._expr),
|
||||
optional($._clause_guard),
|
||||
field("body", $.clause_body),
|
||||
),
|
||||
|
||||
receive_expr: $ => seq(
|
||||
'receive',
|
||||
optional($._cr_clauses),
|
||||
optional(field("after", $.receive_after)),
|
||||
'end'
|
||||
),
|
||||
|
||||
receive_after: $ => seq(
|
||||
'after',
|
||||
field("expr", $._expr),
|
||||
field("body", $.clause_body),
|
||||
),
|
||||
|
||||
_fun_expr: $ => choice(
|
||||
$.internal_fun,
|
||||
$.external_fun,
|
||||
$.anonymous_fun,
|
||||
$.fun_type,
|
||||
),
|
||||
internal_fun: $ => seq(
|
||||
'fun',
|
||||
field("fun", $._name),
|
||||
field("arity", $.arity),
|
||||
),
|
||||
external_fun: $ => seq(
|
||||
'fun',
|
||||
field("module", $.module),
|
||||
field("fun", $._name),
|
||||
field("arity", $.arity),
|
||||
),
|
||||
anonymous_fun: $ => seq(
|
||||
'fun',
|
||||
sepBy1(';', field("clauses", $.fun_clause)),
|
||||
'end'
|
||||
),
|
||||
|
||||
_macro_name: $ => choice(
|
||||
$.atom,
|
||||
$.var,
|
||||
),
|
||||
|
||||
_name: $ => choice(
|
||||
$.atom,
|
||||
$.var,
|
||||
alias($.macro_call_none, $.macro_call_expr),
|
||||
),
|
||||
|
||||
arity: $ => seq('/', field("value", $._arity_value)),
|
||||
|
||||
_arity_value: $ => choice(
|
||||
$.integer,
|
||||
$.var,
|
||||
$.macro_call_expr,
|
||||
),
|
||||
|
||||
fun_clauses: $ => sepBy1(';', $.fun_clause),
|
||||
|
||||
fun_clause: $ => seq(
|
||||
field("name", optional($.var)),
|
||||
field("args", $.expr_args),
|
||||
optional($._clause_guard),
|
||||
field("body", $.clause_body),
|
||||
),
|
||||
|
||||
try_expr: $ => choice(
|
||||
seq('try', $._exprs, 'of', $._cr_clauses, $._try_catch),
|
||||
seq('try', $._exprs, $._try_catch),
|
||||
),
|
||||
|
||||
_try_catch: $ => choice(
|
||||
seq('catch', optional($._catch_clauses), 'end'),
|
||||
seq('catch', optional($._catch_clauses), field("after", $.try_after), 'end'),
|
||||
seq(field("after", $.try_after), 'end'),
|
||||
),
|
||||
|
||||
try_after: $ => seq('after', $._exprs),
|
||||
|
||||
_catch_clauses: $ => sepBy1(';', field("catch", $.catch_clause)),
|
||||
|
||||
catch_clause: $ => seq(
|
||||
choice(
|
||||
field("pat", $._catch_pat),
|
||||
seq(field("class", $.try_class), field("pat", $._catch_pat)),
|
||||
seq(field("class", $.try_class), field("pat", $._catch_pat), field("stack", $.try_stack)),
|
||||
),
|
||||
optional($._clause_guard),
|
||||
field("body", $.clause_body)
|
||||
),
|
||||
|
||||
try_class: $ => seq(field("class", $._name), ':'),
|
||||
|
||||
try_stack: $ => seq(':', field("class", $.var)),
|
||||
|
||||
_catch_pat: $ => choice(
|
||||
alias($.binary_op_catch_pat, $.binary_op_expr),
|
||||
alias($.match_catch_pat, $.binary_op_expr),
|
||||
$.unary_op_expr,
|
||||
$.map_expr,
|
||||
$.record_index_expr,
|
||||
$.record_expr,
|
||||
$._expr_max,
|
||||
),
|
||||
|
||||
match_catch_pat: $ =>
|
||||
prec.right(PREC.EQ, seq(
|
||||
field("lhs", $._catch_pat),
|
||||
'=',
|
||||
field("rhs", $._catch_pat),
|
||||
)),
|
||||
binary_op_catch_pat: $ => choice(
|
||||
prec.left(PREC.COMP_OP, seq(
|
||||
field("lhs", $._catch_pat),
|
||||
$._comp_op,
|
||||
field("rhs", $._catch_pat),
|
||||
)),
|
||||
prec.right(PREC.LIST_OP, seq(
|
||||
field("lhs", $._catch_pat),
|
||||
$._list_op,
|
||||
field("rhs", $._catch_pat),
|
||||
)),
|
||||
prec.left(PREC.ADD_OP, seq(
|
||||
field("lhs", $._catch_pat),
|
||||
$._add_op,
|
||||
field("rhs", $._catch_pat),
|
||||
)),
|
||||
prec.left(PREC.MULT_OP, seq(
|
||||
field("lhs", $._catch_pat),
|
||||
$._mult_op,
|
||||
field("rhs", $._catch_pat),
|
||||
)),
|
||||
),
|
||||
|
||||
_macro_def_replacement: $ => choice(
|
||||
prec.dynamic(PREC.DYN_EXPR, $._expr),
|
||||
prec.dynamic(PREC.DYN_FUNCTION_CLAUSES, $.replacement_function_clauses),
|
||||
prec.dynamic(PREC.DYN_CR_CLAUSES, $.replacement_cr_clauses),
|
||||
prec.dynamic(PREC.DYN_GUARD_OR, $.replacement_guard_or),
|
||||
prec.dynamic(PREC.DYN_GUARD_AND, $.replacement_guard_and),
|
||||
$.replacement_parens,
|
||||
),
|
||||
|
||||
replacement_function_clauses: $ => sepBy1(';', field("clauses", $._function_or_macro_clause)),
|
||||
|
||||
replacement_cr_clauses: $ => sepBy1(';', field("clauses", $._cr_clause_or_macro)),
|
||||
|
||||
replacement_guard_or: $ => sepBy1(';', field("guard", $.replacement_guard_and)),
|
||||
|
||||
replacement_guard_and: $ => sepBy1(',', field("guard", $._expr)),
|
||||
|
||||
replacement_parens: $ => seq('(', ')'),
|
||||
|
||||
macro_lhs: $ => seq(
|
||||
field("name", $._macro_name),
|
||||
field("args", optional($.var_args)),
|
||||
),
|
||||
|
||||
_macro_body_expr: $ => choice(
|
||||
$.macro_string,
|
||||
$.macro_call_expr,
|
||||
),
|
||||
|
||||
macro_call_expr: $ => prec.right(seq(
|
||||
'?',
|
||||
field("name", $._macro_name),
|
||||
field("args", optional($.macro_call_args)),
|
||||
)),
|
||||
|
||||
macro_call_args: $ => seq(
|
||||
'(',
|
||||
sepBy(',', field("args", $.macro_expr)),
|
||||
')'
|
||||
),
|
||||
|
||||
macro_call_none: $ => seq(
|
||||
'?',
|
||||
field("name", $._macro_name),
|
||||
),
|
||||
|
||||
macro_string: $ => seq(
|
||||
'?', '?',
|
||||
field("name", $._macro_name),
|
||||
),
|
||||
|
||||
macro_expr: $ => choice(
|
||||
field("expr", $._expr),
|
||||
seq(field("expr", $._expr), 'when', field("guard", $._expr)),
|
||||
),
|
||||
|
||||
_exprs: $ => sepBy1(',', field("exprs", $._expr)),
|
||||
|
||||
expr_args: $ => seq(
|
||||
'(',
|
||||
sepBy(',', field("args", $._expr)),
|
||||
')',
|
||||
),
|
||||
|
||||
var_args: $ => seq(
|
||||
'(',
|
||||
sepBy(optional(','), field("args", $.var)),
|
||||
')'
|
||||
),
|
||||
|
||||
guard: $ => prec.right(sepBy1(';', field("clauses", $.guard_clause))),
|
||||
guard_clause: $ => prec.right(sepBy1(',', field("exprs", $._expr))),
|
||||
|
||||
concatables: $ => prec.right(field("elems", seq($._concatable, repeat1($._concatable)))),
|
||||
|
||||
_concatable: $ => choice(
|
||||
$.string,
|
||||
$.var,
|
||||
$._macro_body_expr
|
||||
),
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Operators
|
||||
|
||||
_prefix_op: $ => choice(
|
||||
'+',
|
||||
'-',
|
||||
'bnot',
|
||||
'not',
|
||||
),
|
||||
|
||||
_mult_op: $ => choice(
|
||||
'/',
|
||||
'*',
|
||||
'div',
|
||||
'rem',
|
||||
'band',
|
||||
'and',
|
||||
),
|
||||
|
||||
_add_op: $ => choice(
|
||||
'+',
|
||||
'-',
|
||||
'bor',
|
||||
'bxor',
|
||||
'bsl',
|
||||
'bsr',
|
||||
'or',
|
||||
'xor',
|
||||
),
|
||||
|
||||
_list_op: $ => choice('++', '--'),
|
||||
|
||||
_comp_op: $ => choice(
|
||||
'==',
|
||||
'/=',
|
||||
'=<',
|
||||
'<',
|
||||
'>=',
|
||||
'>',
|
||||
'=:=',
|
||||
'=/=',
|
||||
),
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Tokens
|
||||
|
||||
var: $ => token(/[_A-Z\xC0-\xD6\xD8-\xDE][_@a-zA-Z0-9\xC0-\xD6\xD8-\xDE\xDF-\xF6\xF8-\xFF]*/),
|
||||
|
||||
integer: $ => token(
|
||||
/\d{1,2}#[0-9a-zA-Z](_?[0-9a-zA-Z])*|\d(_?\d)*/,
|
||||
),
|
||||
|
||||
float: $ => token(
|
||||
/\d(_?\d)*\.\d(_?\d)*([eE][+-]?\d(_?\d)*)?/,
|
||||
),
|
||||
|
||||
string: $ => /"([^"\\]|\\([^x\^]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\{[0-9a-fA-F]+\}|\^.))*"/,
|
||||
|
||||
// Check via https://regexr.com/
|
||||
// Should match https://www.erlang.org/doc/reference_manual/data_types.html#escape-sequences
|
||||
// Regex is based on https://github.com/erlang/otp/blob/30e0b342a50ce70b204a47e1e442e3dc33f9a41b/lib/stdlib/src/erl_scan.erl#L874-L922
|
||||
char: $ => token(
|
||||
/\$([^\\]|\\([0-7]{1,3}|x[0-9a-fA-F]{2}|x{[0-9a-fA-F]+}|\^.|\\n|\\\\|.))/,
|
||||
),
|
||||
|
||||
atom: $ => token(
|
||||
/([a-z\xDF-\xF6\xF8-\xFF][_@a-zA-Z0-9\xC0-\xD6\xD8-\xDE\xDF-\xF6\xF8-\xFF]*)|('([^'\\]|\\([^x\^]|[0-7]{1,3}|x[0-9a-fA-F]{2}|x\{[0-9a-fA-F]+\}|\^.))*')/,
|
||||
),
|
||||
|
||||
comment: $ => token(/%[^\n]*/),
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,63 @@
|
||||
{
|
||||
"name": "tree-sitter-erlang",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "tree-sitter-erlang",
|
||||
"version": "0.0.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"nan": "^2.14.1",
|
||||
"prettier": "^2.2.1",
|
||||
"tree-sitter-cli": "^0.20.7"
|
||||
}
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
|
||||
"integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA=="
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"tree-sitter": "cli.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
|
||||
"integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA=="
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g=="
|
||||
},
|
||||
"tree-sitter-cli": {
|
||||
"version": "0.20.7",
|
||||
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.7.tgz",
|
||||
"integrity": "sha512-MHABT8oCPr4D0fatsPo6ATQ9H4h9vHpPRjlxkxJs80tpfAEKGn6A1zU3eqfCKBcgmfZDe9CiL3rKOGMzYHwA3w=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "tree-sitter-erlang",
|
||||
"version": "0.0.0",
|
||||
"description": "Tree Sitter grammar for Erlang",
|
||||
"scripts": {
|
||||
"test": "tree-sitter test",
|
||||
"generate": "tree-sitter generate",
|
||||
"parse": "tree-sitter parse"
|
||||
},
|
||||
"authors": ["Leandro Ostera <leandro@ostera.io>", "Alan Zimmerman <alanzimm@fb.com>"],
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"nan": "^2.14.1",
|
||||
"prettier": "^2.2.1",
|
||||
"tree-sitter-cli": "^0.20.7"
|
||||
},
|
||||
"main": "bindings/node"
|
||||
}
|
||||
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
@ -0,0 +1,226 @@
|
||||
// @generated
|
||||
|
||||
#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_
|
||||
@ -0,0 +1,757 @@
|
||||
================================================================================
|
||||
module attribute
|
||||
================================================================================
|
||||
|
||||
-module(foo).
|
||||
-'module'(foo).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(module_attribute
|
||||
(atom))
|
||||
(module_attribute
|
||||
(atom)))
|
||||
|
||||
================================================================================
|
||||
behaviour attribute
|
||||
================================================================================
|
||||
|
||||
-behaviour(gen_server).
|
||||
-behavior(gen_server).
|
||||
-'behaviour'(gen_server).
|
||||
-'behavior'(gen_server).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(behaviour_attribute
|
||||
(atom))
|
||||
(behaviour_attribute
|
||||
(atom))
|
||||
(behaviour_attribute
|
||||
(atom))
|
||||
(behaviour_attribute
|
||||
(atom)))
|
||||
|
||||
================================================================================
|
||||
include attribute
|
||||
================================================================================
|
||||
|
||||
-include("foo.h").
|
||||
-'include'("foo.h").
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_include
|
||||
(string))
|
||||
(pp_include
|
||||
(string)))
|
||||
|
||||
================================================================================
|
||||
include attribute, concatenation
|
||||
================================================================================
|
||||
|
||||
-include("root" "foo.h").
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_include
|
||||
(string)
|
||||
(string)))
|
||||
|
||||
================================================================================
|
||||
include_lib attribute
|
||||
================================================================================
|
||||
|
||||
-include_lib("foo.h").
|
||||
-'include_lib'("foo.h").
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_include_lib
|
||||
(string))
|
||||
(pp_include_lib
|
||||
(string)))
|
||||
|
||||
================================================================================
|
||||
include_lib attribute, concatenation
|
||||
================================================================================
|
||||
|
||||
-include_lib(?APP "foo.h").
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_include_lib
|
||||
(macro_call_expr
|
||||
(var))
|
||||
(string)))
|
||||
|
||||
================================================================================
|
||||
export attribute
|
||||
================================================================================
|
||||
|
||||
-export([foo/1]).
|
||||
-'export'([]).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(export_attribute
|
||||
(fa
|
||||
(atom)
|
||||
(arity
|
||||
(integer))))
|
||||
(export_attribute))
|
||||
|
||||
================================================================================
|
||||
import attribute
|
||||
================================================================================
|
||||
|
||||
-import(bar, [foo/1, baz/3]).
|
||||
-'import'(baz, []).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(import_attribute
|
||||
(atom)
|
||||
(fa
|
||||
(atom)
|
||||
(arity
|
||||
(integer)))
|
||||
(fa
|
||||
(atom)
|
||||
(arity
|
||||
(integer))))
|
||||
(import_attribute
|
||||
(atom)))
|
||||
|
||||
================================================================================
|
||||
export type attribute
|
||||
================================================================================
|
||||
|
||||
-export_type([foo/0]).
|
||||
-'export_type'([]).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(export_type_attribute
|
||||
(fa
|
||||
(atom)
|
||||
(arity
|
||||
(integer))))
|
||||
(export_type_attribute))
|
||||
|
||||
================================================================================
|
||||
compile attribute
|
||||
================================================================================
|
||||
|
||||
-compile(export_all).
|
||||
-'compile'([export_all, blah]).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(compile_options_attribute
|
||||
(atom))
|
||||
(compile_options_attribute
|
||||
(list
|
||||
(atom)
|
||||
(atom))))
|
||||
|
||||
================================================================================
|
||||
file attribute
|
||||
================================================================================
|
||||
|
||||
-file("baz.erl", 45).
|
||||
-'file'("baz.erl", 45).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(file_attribute
|
||||
(string)
|
||||
(integer))
|
||||
(file_attribute
|
||||
(string)
|
||||
(integer)))
|
||||
|
||||
================================================================================
|
||||
record decl
|
||||
================================================================================
|
||||
|
||||
-record(foo, {f1, f2 = 3}).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(record_decl
|
||||
(atom)
|
||||
(record_field
|
||||
(atom))
|
||||
(record_field
|
||||
(atom)
|
||||
(field_expr
|
||||
(integer)))))
|
||||
|
||||
================================================================================
|
||||
record decl with types
|
||||
================================================================================
|
||||
|
||||
-record(foo, {f1 :: atom(), f2 = 3}).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(record_decl
|
||||
(atom)
|
||||
(record_field
|
||||
(atom)
|
||||
(field_type
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))))
|
||||
(record_field
|
||||
(atom)
|
||||
(field_expr
|
||||
(integer)))))
|
||||
|
||||
================================================================================
|
||||
record decl from manual
|
||||
================================================================================
|
||||
|
||||
-record(name, {first = "Robert", last = "Ericsson"}).
|
||||
-record(person, {name = #name{}, phone}).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(record_decl
|
||||
(atom)
|
||||
(record_field
|
||||
(atom)
|
||||
(field_expr
|
||||
(string)))
|
||||
(record_field
|
||||
(atom)
|
||||
(field_expr
|
||||
(string))))
|
||||
(record_decl
|
||||
(atom)
|
||||
(record_field
|
||||
(atom)
|
||||
(field_expr
|
||||
(record_expr
|
||||
(record_name
|
||||
(atom)))))
|
||||
(record_field
|
||||
(atom))))
|
||||
|
||||
================================================================================
|
||||
record decl - empty record
|
||||
================================================================================
|
||||
|
||||
-'record'(state, {}).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(record_decl
|
||||
(atom)))
|
||||
|
||||
================================================================================
|
||||
type decl
|
||||
================================================================================
|
||||
|
||||
-type my_struct_type() :: atom() | integer().
|
||||
-opaque my_opaq_type() :: term().
|
||||
-'type' orddict(Key, Val) :: [{Key, Val}].
|
||||
-'opaque' useless(A) :: A.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args))
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))))
|
||||
(opaque
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))
|
||||
(type_alias
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args
|
||||
(var)
|
||||
(var)))
|
||||
(list
|
||||
(tuple
|
||||
(var)
|
||||
(var))))
|
||||
(opaque
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args
|
||||
(var)))
|
||||
(var)))
|
||||
|
||||
================================================================================
|
||||
function spec 1
|
||||
================================================================================
|
||||
|
||||
-spec my_function(integer()) -> integer().
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(spec
|
||||
(atom)
|
||||
(type_sig
|
||||
(expr_args
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))))
|
||||
|
||||
================================================================================
|
||||
function spec 2
|
||||
================================================================================
|
||||
|
||||
-spec empty_map_02() -> map().
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(spec
|
||||
(atom)
|
||||
(type_sig
|
||||
(expr_args)
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))))
|
||||
|
||||
================================================================================
|
||||
function spec 3
|
||||
================================================================================
|
||||
|
||||
-spec foo() -> #{A => B} when A :: integer(), B :: float().
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(spec
|
||||
(atom)
|
||||
(type_sig
|
||||
(expr_args)
|
||||
(map_expr
|
||||
(map_field
|
||||
(var)
|
||||
(var)))
|
||||
(type_guards
|
||||
(ann_type
|
||||
(ann_var
|
||||
(var))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))
|
||||
(ann_type
|
||||
(ann_var
|
||||
(var))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))))))
|
||||
|
||||
================================================================================
|
||||
wild attribute 1
|
||||
================================================================================
|
||||
|
||||
-foo(bar).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(wild_attribute
|
||||
(attr_name
|
||||
(atom))
|
||||
(paren_expr
|
||||
(atom))))
|
||||
|
||||
================================================================================
|
||||
wild attribute 2
|
||||
================================================================================
|
||||
|
||||
-oncall("whatsapp_c3").
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(wild_attribute
|
||||
(attr_name
|
||||
(atom))
|
||||
(paren_expr
|
||||
(string))))
|
||||
|
||||
================================================================================
|
||||
function declaration
|
||||
================================================================================
|
||||
|
||||
foo(Bar, Baz) -> ok.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(var)
|
||||
(var))
|
||||
(clause_body
|
||||
(atom)))))
|
||||
|
||||
================================================================================
|
||||
undef attribute
|
||||
================================================================================
|
||||
|
||||
-undef(FOO).
|
||||
-'undef'(FOO).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_undef
|
||||
(var))
|
||||
(pp_undef
|
||||
(var)))
|
||||
|
||||
================================================================================
|
||||
ifdef attribute
|
||||
================================================================================
|
||||
|
||||
-ifdef(FOO).
|
||||
-'ifdef'(FOO).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_ifdef
|
||||
(var))
|
||||
(pp_ifdef
|
||||
(var)))
|
||||
|
||||
================================================================================
|
||||
ifndef attribute
|
||||
================================================================================
|
||||
|
||||
-ifndef(FOO).
|
||||
-'ifndef'(FOO).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_ifndef
|
||||
(var))
|
||||
(pp_ifndef
|
||||
(var)))
|
||||
|
||||
================================================================================
|
||||
else attribute
|
||||
================================================================================
|
||||
|
||||
-else.
|
||||
-'else'.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_else)
|
||||
(pp_else))
|
||||
|
||||
================================================================================
|
||||
endif attribute
|
||||
================================================================================
|
||||
|
||||
-endif.
|
||||
-'endif'.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_endif)
|
||||
(pp_endif))
|
||||
|
||||
================================================================================
|
||||
if $.expression
|
||||
================================================================================
|
||||
|
||||
-if 1.
|
||||
-'if'(1).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_if
|
||||
(integer))
|
||||
(pp_if
|
||||
(paren_expr
|
||||
(integer))))
|
||||
|
||||
================================================================================
|
||||
elif attribute
|
||||
================================================================================
|
||||
|
||||
-elif(TRUE).
|
||||
-'elif'(TRUE).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_elif
|
||||
(paren_expr
|
||||
(var)))
|
||||
(pp_elif
|
||||
(paren_expr
|
||||
(var))))
|
||||
|
||||
================================================================================
|
||||
simple spec
|
||||
================================================================================
|
||||
|
||||
-spec foo() -> ok.
|
||||
-'spec' foo() -> ok.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(spec
|
||||
(atom)
|
||||
(type_sig
|
||||
(expr_args)
|
||||
(atom)))
|
||||
(spec
|
||||
(atom)
|
||||
(type_sig
|
||||
(expr_args)
|
||||
(atom))))
|
||||
|
||||
================================================================================
|
||||
callback
|
||||
================================================================================
|
||||
|
||||
-callback foo(Bar) -> ok.
|
||||
-'callback' foo(Bar) -> ok.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(callback
|
||||
(atom)
|
||||
(type_sig
|
||||
(expr_args
|
||||
(var))
|
||||
(atom)))
|
||||
(callback
|
||||
(atom)
|
||||
(type_sig
|
||||
(expr_args
|
||||
(var))
|
||||
(atom))))
|
||||
|
||||
================================================================================
|
||||
string with % in it
|
||||
================================================================================
|
||||
|
||||
foo() -> "\"%".
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(string)))))
|
||||
|
||||
================================================================================
|
||||
string
|
||||
================================================================================
|
||||
|
||||
foo() -> ("whatsapp_c3").
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(paren_expr
|
||||
(string))))))
|
||||
|
||||
================================================================================
|
||||
char %
|
||||
================================================================================
|
||||
|
||||
foo() -> $%.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(char)))))
|
||||
|
||||
================================================================================
|
||||
char space
|
||||
================================================================================
|
||||
|
||||
foo() -> $ .
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(char)))))
|
||||
|
||||
================================================================================
|
||||
char \]
|
||||
================================================================================
|
||||
|
||||
foo() -> $\].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(char)))))
|
||||
|
||||
================================================================================
|
||||
char \^g
|
||||
================================================================================
|
||||
|
||||
foo() -> $\^g.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(char)))))
|
||||
|
||||
================================================================================
|
||||
char \\
|
||||
================================================================================
|
||||
|
||||
foo() -> $\\.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(char)))))
|
||||
|
||||
================================================================================
|
||||
char \^]
|
||||
================================================================================
|
||||
|
||||
foo() -> $\^].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(char)))))
|
||||
|
||||
================================================================================
|
||||
char \^Z
|
||||
================================================================================
|
||||
|
||||
foo() -> $\^Z.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(char)))))
|
||||
|
||||
================================================================================
|
||||
char \%
|
||||
================================================================================
|
||||
|
||||
foo() -> $\%.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(char)))))
|
||||
|
||||
================================================================================
|
||||
optional_callbacks attribute
|
||||
================================================================================
|
||||
|
||||
-optional_callbacks([foo/1, bar/2]).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(optional_callbacks_attribute
|
||||
(fa
|
||||
(atom)
|
||||
(arity
|
||||
(integer)))
|
||||
(fa
|
||||
(atom)
|
||||
(arity
|
||||
(integer)))))
|
||||
@ -0,0 +1,44 @@
|
||||
================================================================================
|
||||
top level error
|
||||
================================================================================
|
||||
|
||||
-if (true).
|
||||
-define(CASE_START_PEER_NODE,
|
||||
case true of
|
||||
Node ->
|
||||
Node;
|
||||
).
|
||||
-else.
|
||||
-define(CASE_START_PEER_NODE,
|
||||
case true of
|
||||
Node ->
|
||||
Node;).
|
||||
-endif.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(ERROR
|
||||
(pp_if
|
||||
(paren_expr
|
||||
(atom)))
|
||||
(macro_lhs
|
||||
(var))
|
||||
(atom)
|
||||
(cr_clause
|
||||
(var)
|
||||
(clause_body
|
||||
(var)))
|
||||
(ERROR)
|
||||
(atom)
|
||||
(ERROR)
|
||||
(atom)
|
||||
(var)
|
||||
(atom)
|
||||
(cr_clause
|
||||
(var)
|
||||
(clause_body
|
||||
(var)))
|
||||
(ERROR)
|
||||
(unary_op_expr
|
||||
(atom)))
|
||||
@ -0,0 +1,521 @@
|
||||
================================================================================
|
||||
record index
|
||||
================================================================================
|
||||
|
||||
f() -> #record.field.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(record_index_expr
|
||||
(record_name
|
||||
(atom))
|
||||
(record_field_name
|
||||
(atom)))))))
|
||||
|
||||
================================================================================
|
||||
record field
|
||||
================================================================================
|
||||
|
||||
f(X) -> X#record.field.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(var))
|
||||
(clause_body
|
||||
(record_field_expr
|
||||
(var)
|
||||
(record_name
|
||||
(atom))
|
||||
(record_field_name
|
||||
(atom)))))))
|
||||
|
||||
================================================================================
|
||||
record expr
|
||||
================================================================================
|
||||
|
||||
f() -> #record{a = 1}.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(record_expr
|
||||
(record_name
|
||||
(atom))
|
||||
(record_field
|
||||
(atom)
|
||||
(field_expr
|
||||
(integer))))))))
|
||||
|
||||
================================================================================
|
||||
record update
|
||||
================================================================================
|
||||
|
||||
f(X) -> X#record{a = 1}.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(var))
|
||||
(clause_body
|
||||
(record_update_expr
|
||||
(var)
|
||||
(record_name
|
||||
(atom))
|
||||
(record_field
|
||||
(atom)
|
||||
(field_expr
|
||||
(integer))))))))
|
||||
|
||||
================================================================================
|
||||
try
|
||||
================================================================================
|
||||
|
||||
f(X) ->
|
||||
try 1 of
|
||||
X -> ok;
|
||||
Y when Z -> ok
|
||||
catch
|
||||
Pattern -> ok;
|
||||
error:Pattern -> ok;
|
||||
throw:Pattern:Stack -> ok;
|
||||
exit:Complex + Pattern:Stack -> ok
|
||||
after
|
||||
ok
|
||||
end,
|
||||
try _
|
||||
catch
|
||||
end.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(var))
|
||||
(clause_body
|
||||
(try_expr
|
||||
(integer)
|
||||
(cr_clause
|
||||
(var)
|
||||
(clause_body
|
||||
(atom)))
|
||||
(cr_clause
|
||||
(var)
|
||||
(guard
|
||||
(guard_clause
|
||||
(var)))
|
||||
(clause_body
|
||||
(atom)))
|
||||
(catch_clause
|
||||
(var)
|
||||
(clause_body
|
||||
(atom)))
|
||||
(catch_clause
|
||||
(try_class
|
||||
(atom))
|
||||
(var)
|
||||
(clause_body
|
||||
(atom)))
|
||||
(catch_clause
|
||||
(try_class
|
||||
(atom))
|
||||
(var)
|
||||
(try_stack
|
||||
(var))
|
||||
(clause_body
|
||||
(atom)))
|
||||
(catch_clause
|
||||
(try_class
|
||||
(atom))
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(var))
|
||||
(try_stack
|
||||
(var))
|
||||
(clause_body
|
||||
(atom)))
|
||||
(try_after
|
||||
(atom)))
|
||||
(try_expr
|
||||
(var))))))
|
||||
|
||||
================================================================================
|
||||
funs
|
||||
================================================================================
|
||||
|
||||
f() -> [
|
||||
fun foo/1,
|
||||
fun mod:foo/1,
|
||||
fun () -> ok end
|
||||
].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(list
|
||||
(internal_fun
|
||||
(atom)
|
||||
(arity
|
||||
(integer)))
|
||||
(external_fun
|
||||
(module
|
||||
(atom))
|
||||
(atom)
|
||||
(arity
|
||||
(integer)))
|
||||
(anonymous_fun
|
||||
(fun_clause
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(atom)))))))))
|
||||
|
||||
================================================================================
|
||||
list
|
||||
================================================================================
|
||||
|
||||
f() ->
|
||||
[],
|
||||
[A],
|
||||
[A, B],
|
||||
[A | B],
|
||||
[A + B | B + C],
|
||||
[A, B | C].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(list)
|
||||
(list
|
||||
(var))
|
||||
(list
|
||||
(var)
|
||||
(var))
|
||||
(list
|
||||
(pipe
|
||||
(var)
|
||||
(var)))
|
||||
(list
|
||||
(pipe
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(var))
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(var))))
|
||||
(list
|
||||
(var)
|
||||
(pipe
|
||||
(var)
|
||||
(var)))))))
|
||||
|
||||
================================================================================
|
||||
binary
|
||||
================================================================================
|
||||
|
||||
f(<<_>>) ->
|
||||
<<>>,
|
||||
<<1>>,
|
||||
<<1/integer>>,
|
||||
<<1:32/integer>>,
|
||||
<<+1:32/integer>>,
|
||||
<<1:32/integer-unit:8>>.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(binary
|
||||
(bin_element
|
||||
(var))))
|
||||
(clause_body
|
||||
(binary)
|
||||
(binary
|
||||
(bin_element
|
||||
(integer)))
|
||||
(binary
|
||||
(bin_element
|
||||
(integer)
|
||||
(bit_type_list
|
||||
(atom))))
|
||||
(binary
|
||||
(bin_element
|
||||
(integer)
|
||||
(bit_size_expr
|
||||
(integer))
|
||||
(bit_type_list
|
||||
(atom))))
|
||||
(binary
|
||||
(bin_element
|
||||
(unary_op_expr
|
||||
(integer))
|
||||
(bit_size_expr
|
||||
(integer))
|
||||
(bit_type_list
|
||||
(atom))))
|
||||
(binary
|
||||
(bin_element
|
||||
(integer)
|
||||
(bit_size_expr
|
||||
(integer))
|
||||
(bit_type_list
|
||||
(atom)
|
||||
(bit_type_unit
|
||||
(integer)))))))))
|
||||
|
||||
================================================================================
|
||||
catch
|
||||
================================================================================
|
||||
|
||||
f() ->
|
||||
catch 1 + 2.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(catch_expr
|
||||
(binary_op_expr
|
||||
(integer)
|
||||
(integer)))))))
|
||||
|
||||
================================================================================
|
||||
receive
|
||||
================================================================================
|
||||
|
||||
f() ->
|
||||
receive
|
||||
end,
|
||||
receive
|
||||
ok -> ok;
|
||||
error -> error
|
||||
end,
|
||||
receive
|
||||
after 1000 -> ok
|
||||
end,
|
||||
receive
|
||||
ok -> ok
|
||||
after Timeout -> timeout
|
||||
end.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(receive_expr)
|
||||
(receive_expr
|
||||
(cr_clause
|
||||
(atom)
|
||||
(clause_body
|
||||
(atom)))
|
||||
(cr_clause
|
||||
(atom)
|
||||
(clause_body
|
||||
(atom))))
|
||||
(receive_expr
|
||||
(receive_after
|
||||
(integer)
|
||||
(clause_body
|
||||
(atom))))
|
||||
(receive_expr
|
||||
(cr_clause
|
||||
(atom)
|
||||
(clause_body
|
||||
(atom)))
|
||||
(receive_after
|
||||
(var)
|
||||
(clause_body
|
||||
(atom))))))))
|
||||
|
||||
================================================================================
|
||||
case
|
||||
================================================================================
|
||||
|
||||
f() ->
|
||||
case _ of
|
||||
end,
|
||||
case Foo of
|
||||
A when A; B, C -> ok;
|
||||
_ -> error
|
||||
end.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(case_expr
|
||||
(var))
|
||||
(case_expr
|
||||
(var)
|
||||
(cr_clause
|
||||
(var)
|
||||
(guard
|
||||
(guard_clause
|
||||
(var))
|
||||
(guard_clause
|
||||
(var)
|
||||
(var)))
|
||||
(clause_body
|
||||
(atom)))
|
||||
(cr_clause
|
||||
(var)
|
||||
(clause_body
|
||||
(atom))))))))
|
||||
|
||||
================================================================================
|
||||
function call
|
||||
================================================================================
|
||||
|
||||
f() ->
|
||||
foo(),
|
||||
(foo)(),
|
||||
mod:foo(),
|
||||
(mod:foo)(),
|
||||
(Mod):(Foo)().
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(call
|
||||
(paren_expr
|
||||
(atom))
|
||||
(expr_args))
|
||||
(call
|
||||
(remote
|
||||
(remote_module
|
||||
(atom))
|
||||
(atom))
|
||||
(expr_args))
|
||||
(call
|
||||
(paren_expr
|
||||
(remote
|
||||
(remote_module
|
||||
(atom))
|
||||
(atom)))
|
||||
(expr_args))
|
||||
(call
|
||||
(remote
|
||||
(remote_module
|
||||
(paren_expr
|
||||
(var)))
|
||||
(paren_expr
|
||||
(var)))
|
||||
(expr_args))))))
|
||||
|
||||
================================================================================
|
||||
variable assignment
|
||||
================================================================================
|
||||
|
||||
f() ->
|
||||
A = 3 + B.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(match_expr
|
||||
(var)
|
||||
(binary_op_expr
|
||||
(integer)
|
||||
(var)))))))
|
||||
|
||||
================================================================================
|
||||
fun
|
||||
================================================================================
|
||||
|
||||
foo() -> fun(X) -> X end.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(anonymous_fun
|
||||
(fun_clause
|
||||
(expr_args
|
||||
(var))
|
||||
(clause_body
|
||||
(var))))))))
|
||||
|
||||
================================================================================
|
||||
named fun
|
||||
================================================================================
|
||||
|
||||
foo() -> fun Named(X) -> X end.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(anonymous_fun
|
||||
(fun_clause
|
||||
(var)
|
||||
(expr_args
|
||||
(var))
|
||||
(clause_body
|
||||
(var))))))))
|
||||
@ -0,0 +1,100 @@
|
||||
================================================================================
|
||||
incomplete behaviour attribute WIP
|
||||
================================================================================
|
||||
|
||||
-behavior(gen
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(ERROR
|
||||
(atom)))
|
||||
|
||||
|
||||
================================================================================
|
||||
missing dot after export attribute (limitation)
|
||||
================================================================================
|
||||
|
||||
-export([foo/1]).
|
||||
-'export'([])
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(export_attribute
|
||||
(fa
|
||||
(atom)
|
||||
(arity
|
||||
(integer))))
|
||||
(export_attribute
|
||||
(MISSING ".")))
|
||||
|
||||
================================================================================
|
||||
missing dot after variable (limitation)
|
||||
================================================================================
|
||||
|
||||
test(X) ->
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(ERROR
|
||||
(atom)
|
||||
(expr_args
|
||||
(var))))
|
||||
|
||||
================================================================================
|
||||
function after missing dot (limitation)
|
||||
================================================================================
|
||||
|
||||
foo() ->
|
||||
b
|
||||
bar() -> ok. % ideally would be in AST
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(atom)))
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(atom))))
|
||||
(comment))
|
||||
|
||||
================================================================================
|
||||
function reference missing dot (limitation)
|
||||
================================================================================
|
||||
|
||||
foo() ->
|
||||
fun sample2:f
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(ERROR
|
||||
(atom)
|
||||
(expr_args)
|
||||
(module
|
||||
(atom))
|
||||
(atom)))
|
||||
|
||||
================================================================================
|
||||
incomplete record index (limitation)
|
||||
================================================================================
|
||||
|
||||
foo() -> #r.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(ERROR
|
||||
(atom)
|
||||
(expr_args)
|
||||
(record_name
|
||||
(atom))))
|
||||
@ -0,0 +1,405 @@
|
||||
================================================================================
|
||||
expr
|
||||
================================================================================
|
||||
|
||||
-define(X, a).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var))
|
||||
(atom)))
|
||||
|
||||
================================================================================
|
||||
guard and
|
||||
================================================================================
|
||||
|
||||
-define(X, a, b, c).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var))
|
||||
(replacement_guard_and
|
||||
(atom)
|
||||
(atom)
|
||||
(atom))))
|
||||
|
||||
================================================================================
|
||||
guard or
|
||||
================================================================================
|
||||
|
||||
-define(X, a; b, c).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var))
|
||||
(replacement_guard_or
|
||||
(replacement_guard_and
|
||||
(atom))
|
||||
(replacement_guard_and
|
||||
(atom)
|
||||
(atom)))))
|
||||
|
||||
================================================================================
|
||||
function clauses
|
||||
================================================================================
|
||||
|
||||
-define(X,
|
||||
foo() -> ok;
|
||||
foo() -> not_ok
|
||||
).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var))
|
||||
(replacement_function_clauses
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(atom)))
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args)
|
||||
(clause_body
|
||||
(atom))))))
|
||||
|
||||
================================================================================
|
||||
statement list
|
||||
================================================================================
|
||||
|
||||
-define(IS_STRING(X), is_binary(X); is_list(X); is_atom(X)).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var)
|
||||
(var_args
|
||||
(var)))
|
||||
(replacement_guard_or
|
||||
(replacement_guard_and
|
||||
(call
|
||||
(atom)
|
||||
(expr_args
|
||||
(var))))
|
||||
(replacement_guard_and
|
||||
(call
|
||||
(atom)
|
||||
(expr_args
|
||||
(var))))
|
||||
(replacement_guard_and
|
||||
(call
|
||||
(atom)
|
||||
(expr_args
|
||||
(var)))))))
|
||||
|
||||
================================================================================
|
||||
function clause
|
||||
================================================================================
|
||||
|
||||
-define(MATCH(Type, Predicate),
|
||||
match({type, _, Type, []}, Val) ->
|
||||
?CHECK(Predicate(Val), ?FMT("Expected ~p, got ~p", [Type, Val]))
|
||||
).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var)
|
||||
(var_args
|
||||
(var)
|
||||
(var)))
|
||||
(replacement_function_clauses
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(tuple
|
||||
(atom)
|
||||
(var)
|
||||
(var)
|
||||
(list))
|
||||
(var))
|
||||
(clause_body
|
||||
(macro_call_expr
|
||||
(var)
|
||||
(macro_call_args
|
||||
(macro_expr
|
||||
(call
|
||||
(var)
|
||||
(expr_args
|
||||
(var))))
|
||||
(macro_expr
|
||||
(macro_call_expr
|
||||
(var)
|
||||
(macro_call_args
|
||||
(macro_expr
|
||||
(string))
|
||||
(macro_expr
|
||||
(list
|
||||
(var)
|
||||
(var)))))))))))))
|
||||
|
||||
================================================================================
|
||||
LOOP macro
|
||||
================================================================================
|
||||
|
||||
-define(LOOP(),
|
||||
[] when Suffix =:= []; length(Prefix) > 3 ->
|
||||
null;
|
||||
[] ->
|
||||
[Digit | Rest] = Suffix,
|
||||
?FUNCTION_NAME(Prefix ++ [Digit], Rest)
|
||||
).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var)
|
||||
(var_args))
|
||||
(replacement_cr_clauses
|
||||
(cr_clause
|
||||
(list)
|
||||
(guard
|
||||
(guard_clause
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(list)))
|
||||
(guard_clause
|
||||
(binary_op_expr
|
||||
(call
|
||||
(atom)
|
||||
(expr_args
|
||||
(var)))
|
||||
(integer))))
|
||||
(clause_body
|
||||
(atom)))
|
||||
(cr_clause
|
||||
(list)
|
||||
(clause_body
|
||||
(match_expr
|
||||
(list
|
||||
(pipe
|
||||
(var)
|
||||
(var)))
|
||||
(var))
|
||||
(macro_call_expr
|
||||
(var)
|
||||
(macro_call_args
|
||||
(macro_expr
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(list
|
||||
(var))))
|
||||
(macro_expr
|
||||
(var)))))))))
|
||||
|
||||
================================================================================
|
||||
Comma separated macro
|
||||
================================================================================
|
||||
|
||||
-define(SECURE_REQUEST(SessionID, Env, ImplFun, Args, Flag),
|
||||
{current_function, {_Mod, CurFunction, _Arity}} = process_info(
|
||||
self(),
|
||||
current_function
|
||||
),
|
||||
secure_req(SessionID, Env, CurFunction, ImplFun, Args, Flag)
|
||||
).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var)
|
||||
(var_args
|
||||
(var)
|
||||
(var)
|
||||
(var)
|
||||
(var)
|
||||
(var)))
|
||||
(replacement_guard_and
|
||||
(match_expr
|
||||
(tuple
|
||||
(atom)
|
||||
(tuple
|
||||
(var)
|
||||
(var)
|
||||
(var)))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(atom))))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args
|
||||
(var)
|
||||
(var)
|
||||
(var)
|
||||
(var)
|
||||
(var)
|
||||
(var))))))
|
||||
|
||||
================================================================================
|
||||
Empty macro
|
||||
================================================================================
|
||||
|
||||
-define(E2E_SPEC, ).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var))))
|
||||
|
||||
================================================================================
|
||||
Calling a macro
|
||||
================================================================================
|
||||
|
||||
lookup(Prefix, Suffix) ->
|
||||
case ets:select(Prefix) of
|
||||
[CCI] ->
|
||||
{CCI, Suffix};
|
||||
?LOOP()
|
||||
end.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(var)
|
||||
(var))
|
||||
(clause_body
|
||||
(case_expr
|
||||
(call
|
||||
(remote
|
||||
(remote_module
|
||||
(atom))
|
||||
(atom))
|
||||
(expr_args
|
||||
(var)))
|
||||
(cr_clause
|
||||
(list
|
||||
(var))
|
||||
(clause_body
|
||||
(tuple
|
||||
(var)
|
||||
(var))))
|
||||
(macro_call_expr
|
||||
(var)
|
||||
(macro_call_args)))))))
|
||||
|
||||
================================================================================
|
||||
Macro type
|
||||
================================================================================
|
||||
|
||||
-define(TYPE, integer() | atom()).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var))
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))))
|
||||
|
||||
================================================================================
|
||||
Concatables
|
||||
================================================================================
|
||||
|
||||
-define(TXT(Str), "abc" Str ??Str).
|
||||
-define(TXT(Str), Str "abc").
|
||||
-define(TXT(Str), ??Str "abc").
|
||||
-define(TXT(Str), "abc" "def").
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var)
|
||||
(var_args
|
||||
(var)))
|
||||
(concatables
|
||||
(string)
|
||||
(var)
|
||||
(macro_string
|
||||
(var))))
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var)
|
||||
(var_args
|
||||
(var)))
|
||||
(concatables
|
||||
(var)
|
||||
(string)))
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var)
|
||||
(var_args
|
||||
(var)))
|
||||
(concatables
|
||||
(macro_string
|
||||
(var))
|
||||
(string)))
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var)
|
||||
(var_args
|
||||
(var)))
|
||||
(concatables
|
||||
(string)
|
||||
(string))))
|
||||
|
||||
================================================================================
|
||||
Macro type in call
|
||||
================================================================================
|
||||
|
||||
-define(X, ?MACRO(integer() | atom())).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(pp_define
|
||||
(macro_lhs
|
||||
(var))
|
||||
(macro_call_expr
|
||||
(var)
|
||||
(macro_call_args
|
||||
(macro_expr
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))))))))
|
||||
@ -0,0 +1,108 @@
|
||||
================================================================================
|
||||
binary operator
|
||||
================================================================================
|
||||
|
||||
f(1 + 1) -> ok;
|
||||
f([] ++ []) -> ok.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(binary_op_expr
|
||||
(integer)
|
||||
(integer)))
|
||||
(clause_body
|
||||
(atom)))
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(binary_op_expr
|
||||
(list)
|
||||
(list)))
|
||||
(clause_body
|
||||
(atom)))))
|
||||
|
||||
================================================================================
|
||||
unary operator
|
||||
================================================================================
|
||||
|
||||
f(+1) -> ok.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(unary_op_expr
|
||||
(integer)))
|
||||
(clause_body
|
||||
(atom)))))
|
||||
|
||||
================================================================================
|
||||
match
|
||||
================================================================================
|
||||
|
||||
f(A = B) -> ok.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(match_expr
|
||||
(var)
|
||||
(var)))
|
||||
(clause_body
|
||||
(atom)))))
|
||||
|
||||
================================================================================
|
||||
record index
|
||||
================================================================================
|
||||
|
||||
f(#record.field) -> ok.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(record_index_expr
|
||||
(record_name
|
||||
(atom))
|
||||
(record_field_name
|
||||
(atom))))
|
||||
(clause_body
|
||||
(atom)))))
|
||||
|
||||
================================================================================
|
||||
record pat
|
||||
================================================================================
|
||||
|
||||
f(#record{a = 1}) -> ok.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(fun_decl
|
||||
(function_clause
|
||||
(atom)
|
||||
(expr_args
|
||||
(record_expr
|
||||
(record_name
|
||||
(atom))
|
||||
(record_field
|
||||
(atom)
|
||||
(field_expr
|
||||
(integer)))))
|
||||
(clause_body
|
||||
(atom)))))
|
||||
@ -0,0 +1,191 @@
|
||||
================================================================================
|
||||
binary type
|
||||
================================================================================
|
||||
|
||||
-type x() :: {<<>>, <<_:_*8>>, <<_:8, _:_*8>>, <<_:_*1>>, <<_:1, _:_*1>>}.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args))
|
||||
(tuple
|
||||
(binary)
|
||||
(binary
|
||||
(bin_element
|
||||
(var)
|
||||
(bit_size_expr
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(integer)))))
|
||||
(binary
|
||||
(bin_element
|
||||
(var)
|
||||
(bit_size_expr
|
||||
(integer)))
|
||||
(bin_element
|
||||
(var)
|
||||
(bit_size_expr
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(integer)))))
|
||||
(binary
|
||||
(bin_element
|
||||
(var)
|
||||
(bit_size_expr
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(integer)))))
|
||||
(binary
|
||||
(bin_element
|
||||
(var)
|
||||
(bit_size_expr
|
||||
(integer)))
|
||||
(bin_element
|
||||
(var)
|
||||
(bit_size_expr
|
||||
(binary_op_expr
|
||||
(var)
|
||||
(integer))))))))
|
||||
|
||||
================================================================================
|
||||
ann type
|
||||
================================================================================
|
||||
|
||||
-type x() :: A :: B :: atom().
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args))
|
||||
(ann_type
|
||||
(ann_var
|
||||
(var))
|
||||
(ann_type
|
||||
(ann_var
|
||||
(var))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))))))
|
||||
|
||||
================================================================================
|
||||
union type
|
||||
================================================================================
|
||||
|
||||
-type x() :: atom() | integer() | float().
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args))
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))))))
|
||||
|
||||
================================================================================
|
||||
union type in list
|
||||
================================================================================
|
||||
|
||||
-type x() :: [atom() | integer() | float()].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args))
|
||||
(list
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))))))
|
||||
|
||||
================================================================================
|
||||
union and ann types mixed
|
||||
================================================================================
|
||||
|
||||
-type x() :: A :: B :: atom() | C :: term() | none().
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args))
|
||||
(ann_type
|
||||
(ann_var
|
||||
(var))
|
||||
(ann_type
|
||||
(ann_var
|
||||
(var))
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(ann_type
|
||||
(ann_var
|
||||
(var))
|
||||
(pipe
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))))))))
|
||||
|
||||
================================================================================
|
||||
fun types
|
||||
================================================================================
|
||||
|
||||
-type x() :: {fun(), fun((...) -> atom()), fun((atom()) -> atom())}.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(type_name
|
||||
(atom)
|
||||
(var_args))
|
||||
(tuple
|
||||
(fun_type)
|
||||
(fun_type
|
||||
(fun_type_sig
|
||||
(expr_args
|
||||
(dotdotdot))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args))))
|
||||
(fun_type
|
||||
(fun_type_sig
|
||||
(expr_args
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))
|
||||
(call
|
||||
(atom)
|
||||
(expr_args)))))))
|
||||
Loading…
Reference in New Issue