mirror of https://github.com/Wilfred/difftastic/
Add 'vendor/tree-sitter-erlang/' from commit 'a8b8b0e16c4f5552f5e85af3dec976a5d16af8b9'
git-subtree-dir: vendor/tree-sitter-erlang git-subtree-mainline:pull/454/headc5985c88b2git-subtree-split:a8b8b0e16c
commit
db3a1db04e
@ -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