mirror of https://github.com/Wilfred/difftastic/
parent
8bb43e5fec
commit
6047469f71
@ -1 +0,0 @@
|
||||
../tree-sitter-gleam/queries/highlights.scm
|
||||
@ -1,3 +0,0 @@
|
||||
src/** linguist-generated
|
||||
src/scanner.c -linguist-generated
|
||||
test/** linguist-documentation
|
||||
@ -1 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
@ -1,12 +0,0 @@
|
||||
---
|
||||
name: Issue
|
||||
about: A problem or suggestion
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Please ensure you are using the latest commit in this repo.
|
||||
> Older versions are not supported.
|
||||
@ -1,67 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Ensure generated parser files are up to date
|
||||
run: npx tree-sitter generate
|
||||
|
||||
- name: Run tree-sitter tests
|
||||
run: npx tree-sitter test
|
||||
|
||||
- name: Check formatting
|
||||
run: npm run check-formatted
|
||||
|
||||
integration-test:
|
||||
name: Integration Test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Ensure generated parser files are up to date
|
||||
run: npx tree-sitter generate
|
||||
|
||||
- name: Run integration tests
|
||||
run: ./scripts/integration_test.sh
|
||||
@ -1,41 +0,0 @@
|
||||
# generates the parser with 'tree-sitter generate' if the parser is out of date
|
||||
name: Generate Parser
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
name: Generate Parser
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Generate parser files
|
||||
run: npx tree-sitter generate
|
||||
|
||||
- name: Commit generated parser files
|
||||
run: |
|
||||
git config --local user.email "$(git log --format='%ae' HEAD^!)"
|
||||
git config --local user.name "$(git log --format='%an' HEAD^!)"
|
||||
git add src
|
||||
git commit -m "Generate parser" || true
|
||||
git push
|
||||
@ -1,56 +0,0 @@
|
||||
name: release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
build-release:
|
||||
name: build-release
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Ensure generated parser files are up to date
|
||||
run: npx tree-sitter generate
|
||||
|
||||
- name: Ensure tests pass
|
||||
run: npx tree-sitter test
|
||||
|
||||
- name: Compile library file
|
||||
run: cc -shared -fPIC -g -O2 -I src src/parser.c src/scanner.c -o tree-sitter-gleam.so
|
||||
|
||||
- name: Create archive
|
||||
run: |
|
||||
VERSION="${GITHUB_REF#refs/tags/}"
|
||||
case ${{ matrix.os }} in
|
||||
"ubuntu-latest") FAMILY="linux";;
|
||||
"macos-latest") FAMILY="macos";;
|
||||
esac
|
||||
ARCHIVE="tree-sitter-gleam-$VERSION-$FAMILY.tar.gz"
|
||||
|
||||
tar -czf $ARCHIVE tree-sitter-gleam.so
|
||||
|
||||
echo "ASSET=$ARCHIVE" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload release archive
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
fail_on_unmatched_files: true
|
||||
files: |
|
||||
${{ env.ASSET }}
|
||||
@ -1,6 +0,0 @@
|
||||
*.wasm
|
||||
build
|
||||
gleam.so*
|
||||
log.html
|
||||
node_modules
|
||||
target
|
||||
@ -1,89 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20f4cd3642c47a85052a887d86704f4eac272969f61b686bdd3f772122aabaff"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
"tree-sitter-language",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-gleam"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter",
|
||||
"tree-sitter-language",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-language"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2545046bd1473dac6c626659cc2567c6c0ff302fc8b84a56c4243378276f7f57"
|
||||
@ -1,29 +0,0 @@
|
||||
[package]
|
||||
name = "tree-sitter-gleam"
|
||||
description = "gleam grammar for the tree-sitter parsing library"
|
||||
version = "1.0.0"
|
||||
keywords = ["incremental", "parsing", "gleam"]
|
||||
categories = ["parsing", "text-editors"]
|
||||
repository = "https://github.com/tree-sitter/tree-sitter-gleam"
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
|
||||
build = "bindings/rust/build.rs"
|
||||
include = [
|
||||
"bindings/rust/*",
|
||||
"grammar.js",
|
||||
"queries/*",
|
||||
"src/*",
|
||||
]
|
||||
|
||||
[lib]
|
||||
path = "bindings/rust/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
tree-sitter-language = "0.1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tree-sitter = "0.23"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
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.
|
||||
@ -1,103 +0,0 @@
|
||||
tree-sitter-gleam
|
||||
=================
|
||||
|
||||
A [tree-sitter] grammar for the [Gleam programming language]
|
||||
|
||||
[tree-sitter]: https://tree-sitter.github.io
|
||||
[Gleam programming language]: https://gleam.run
|
||||
|
||||
This grammar is able to parse the entire Gleam language. It is largely based
|
||||
on the Gleam parser itself, and deviations from that are noted throughout the
|
||||
codebase.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
tree-sitter-gleam, as with all tree-sitter grammars, is of limited utility on
|
||||
its own. Instead, tree-sitter-gleam is best used as a Gleam parser that can be
|
||||
embedded in other projects. An example of such a project is
|
||||
[tree-sitter-gleam-rust-example].
|
||||
|
||||
However, [tree-sitter-cli] can be used with this grammar to show generated parse
|
||||
trees and syntax highlighting for a given Gleam file.
|
||||
|
||||
1. [Install tree-sitter-cli]
|
||||
2. Create a `tree-sitters` directory in your home directory.
|
||||
3. Clone this repository (or symlink it) into the new `~/tree-sitters/` directory.
|
||||
4. Run `tree-sitter parse path/to/file.gleam` to be shown the parse tree for the
|
||||
file.
|
||||
5. Run `tree-sitter highlight path/to/file.gleam` to be shown the file with
|
||||
syntax highlighting applied.
|
||||
|
||||
[tree-sitter-gleam-rust-example]: https://github.com/J3RN/tree-sitter-gleam-rust-example
|
||||
[tree-sitter-cli]: https://github.com/tree-sitter/tree-sitter/blob/master/cli/README.md
|
||||
[Install tree-sitter-cli]: https://github.com/tree-sitter/tree-sitter/blob/master/cli/README.md#installation
|
||||
|
||||
Various Gotchas
|
||||
---------------
|
||||
|
||||
There are a few nodes in the generated AST that may be confusing at first:
|
||||
|
||||
- `type` :: A very ambiguous name, but this refers to a concrete type such as
|
||||
`List(#(String, Int))`
|
||||
- `type_name` :: Refers to essentially the left side of a type declaration and
|
||||
includes parameters, e.g. `MyType(foo, bar)`.
|
||||
- `type_identifier` :: Known in the parser as "UpName", this is what you would
|
||||
intuitively think of as a type's name, such as `List` or `Result`.
|
||||
- `function_call` :: The name is not confusing, but its structure may be. Since
|
||||
Gleam supports first-class functions, the function being invoked could be a
|
||||
variable, a field of a record, an element of a tuple, etc. Some of these are
|
||||
ambiguous without context that tree-sitter does not have. e.g.
|
||||
In `string.replace(x, y, z)`, `string` could be a record with a field
|
||||
`replace` that is a function or it could be a module with a function `replace`
|
||||
—there's no way for the parser to know. In this case, it will be parsed to
|
||||
`(function_call function: (field_access ...) ...)` , as I arbitrarily decided
|
||||
to always assume the code is accessing a field on a record.
|
||||
- `constant_field_access` :: Recognizes when a reference to a remote function is used as a constant's value. Generally field accesses are indistinguishable from remote function invocations by the parser so `field_access` is the node name used for both (hence this misnomer).
|
||||
|
||||
This is not a comprehensive list. If you find a node confusing, search for it
|
||||
in `grammar.js`, as it might have an explanatory comment. Either way, feel free
|
||||
to add it to this list and send a PR! ✨
|
||||
|
||||
To-do List
|
||||
----------
|
||||
|
||||
- [x] Add ability to parse all language constructs
|
||||
- [x] Syntax highlighting queries
|
||||
- [ ] Have an issue? Let me know! Please [open an issue] 💁
|
||||
|
||||
[open an issue]: https://github.com/J3RN/tree-sitter-gleam/issues/new
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
1. Change files such as `grammar.js` and `queries/highlight.scm`.
|
||||
2. The grammar needs to be generated from the `grammar.js` file by running `npm run generate`.
|
||||
3. Add parser feature tests to the relevant file(s) in `test/corpus/`, or make a new one.
|
||||
4. Run `npm run test` and fix any failing tests.
|
||||
|
||||
Policies
|
||||
--------
|
||||
|
||||
### Backwards-Compatibility Policy
|
||||
|
||||
Per the conversation in [#55](https://github.com/gleam-lang/tree-sitter-gleam/pull/55), we have decided that from v0.28.0 forward, tree-sitter-gleam will maintain backwards compatibility with the previous two minor versions; meaning that each release will support three versions:
|
||||
- 0.x.0
|
||||
- 0.x-1.*
|
||||
- 0.x-2.*
|
||||
|
||||
e.g. The v0.30.0 release of tree-sitter gleam will support the following version of the Gleam language:
|
||||
- v0.30.0
|
||||
- v0.29.*
|
||||
- v0.28.*
|
||||
|
||||
Style
|
||||
-----
|
||||
|
||||
To prevent headaches from stylistic differences, I request that you please
|
||||
follow these style suggestions. 🙏
|
||||
|
||||
- Remove all non-mandatory trailing whitespace.
|
||||
- Ensure a final newline is present at the end of all files (this is the default
|
||||
in Vim, Emacs).
|
||||
- Format JavaScript by running `npm run format`.
|
||||
@ -1,19 +0,0 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "tree_sitter_gleam_binding",
|
||||
"include_dirs": [
|
||||
"<!(node -e \"require('nan')\")",
|
||||
"src"
|
||||
],
|
||||
"sources": [
|
||||
"bindings/node/binding.cc",
|
||||
"src/parser.c",
|
||||
"src/scanner.c"
|
||||
],
|
||||
"cflags_c": [
|
||||
"-std=c99",
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
#include "tree_sitter/parser.h"
|
||||
#include <node.h>
|
||||
#include "nan.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
extern "C" TSLanguage * tree_sitter_gleam();
|
||||
|
||||
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_gleam());
|
||||
|
||||
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("gleam").ToLocalChecked());
|
||||
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
|
||||
}
|
||||
|
||||
NODE_MODULE(tree_sitter_gleam_binding, Init)
|
||||
|
||||
} // namespace
|
||||
@ -1,19 +0,0 @@
|
||||
try {
|
||||
module.exports = require("../../build/Release/tree_sitter_gleam_binding");
|
||||
} catch (error1) {
|
||||
if (error1.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error1;
|
||||
}
|
||||
try {
|
||||
module.exports = require("../../build/Debug/tree_sitter_gleam_binding");
|
||||
} catch (error2) {
|
||||
if (error2.code !== 'MODULE_NOT_FOUND') {
|
||||
throw error2;
|
||||
}
|
||||
throw error1
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
module.exports.nodeTypeInfo = require("../../src/node-types.json");
|
||||
} catch (_) {}
|
||||
@ -1,35 +0,0 @@
|
||||
fn main() {
|
||||
let src_dir = std::path::Path::new("src");
|
||||
|
||||
let mut c_config = cc::Build::new();
|
||||
c_config.include(&src_dir);
|
||||
c_config
|
||||
.flag_if_supported("-Wno-unused-parameter")
|
||||
.flag_if_supported("-Wno-unused-but-set-variable")
|
||||
.flag_if_supported("-Wno-trigraphs");
|
||||
let parser_path = src_dir.join("parser.c");
|
||||
c_config.file(&parser_path);
|
||||
|
||||
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());
|
||||
*/
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
//! This crate provides Gleam 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:
|
||||
//!
|
||||
//! ```
|
||||
//! use tree_sitter::Parser;
|
||||
//!
|
||||
//! let code = r#"
|
||||
//! import gleam/io
|
||||
//!
|
||||
//! pub fn main() {
|
||||
//! io.println("hello, friend!")
|
||||
//! }
|
||||
//! "#;
|
||||
//! let mut parser = Parser::new();
|
||||
//! let language = tree_sitter_gleam::LANGUAGE;
|
||||
//! parser
|
||||
//! .set_language(&language.into())
|
||||
//! .expect("Error loading Gleam parser");
|
||||
//! let tree = parser.parse(code, None).unwrap();
|
||||
//! assert!(!tree.root_node().has_error());
|
||||
//! ```
|
||||
//!
|
||||
//! [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::LanguageFn;
|
||||
|
||||
extern "C" {
|
||||
fn tree_sitter_gleam() -> *const ();
|
||||
}
|
||||
|
||||
/// The tree-sitter [`LanguageFn`] for this grammar.
|
||||
pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_gleam) };
|
||||
|
||||
/// 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");
|
||||
|
||||
/// The syntax highlighting query for this language.
|
||||
pub const HIGHLIGHT_QUERY: &'static str = include_str!("../../queries/highlights.scm");
|
||||
|
||||
// The locals tagging query for this language.
|
||||
pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
|
||||
|
||||
/// The symbol tagging query for this language.
|
||||
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.into())
|
||||
.expect("Error loading Gleam parser");
|
||||
}
|
||||
}
|
||||
@ -1,902 +0,0 @@
|
||||
const NEWLINE = /\r?\n/;
|
||||
|
||||
module.exports = grammar({
|
||||
name: "gleam",
|
||||
externals: ($) => [$.quoted_content],
|
||||
extras: ($) => [
|
||||
NEWLINE,
|
||||
/\s/,
|
||||
$.module_comment,
|
||||
$.statement_comment,
|
||||
$.comment,
|
||||
],
|
||||
conflicts: ($) => [
|
||||
[$._maybe_record_expression, $._maybe_tuple_expression],
|
||||
[
|
||||
$._maybe_record_expression,
|
||||
$._maybe_tuple_expression,
|
||||
$.remote_constructor_name,
|
||||
],
|
||||
[$.case_subjects],
|
||||
[$.source_file],
|
||||
[$._constant_value, $._case_clause_guard_unit],
|
||||
[$.integer],
|
||||
[$.echo],
|
||||
],
|
||||
rules: {
|
||||
/* General rules */
|
||||
source_file: ($) =>
|
||||
repeat(choice($.target_group, $._module_statement, $._statement_seq)),
|
||||
|
||||
_module_statement: ($) =>
|
||||
choice(
|
||||
$.import,
|
||||
$.constant,
|
||||
$.external_type,
|
||||
$.external_function,
|
||||
$.function,
|
||||
$.type_definition,
|
||||
$.type_alias,
|
||||
$.attribute
|
||||
),
|
||||
|
||||
/* Comments */
|
||||
module_comment: ($) => token(seq("////", /.*/)),
|
||||
statement_comment: ($) => token(seq("///", /.*/)),
|
||||
comment: ($) => token(seq("//", /.*/)),
|
||||
|
||||
/* Target groups
|
||||
* DEPRECATED: This syntax was replaced with attributes in v0.30.
|
||||
*/
|
||||
target_group: ($) =>
|
||||
seq(
|
||||
"if",
|
||||
field("target", $.target),
|
||||
"{",
|
||||
repeat($._module_statement),
|
||||
"}"
|
||||
),
|
||||
target: ($) => choice("erlang", "javascript"),
|
||||
|
||||
/* Attributes */
|
||||
attribute: ($) =>
|
||||
seq(
|
||||
"@",
|
||||
field("name", $.identifier),
|
||||
optional(field("arguments", alias($._attribute_arguments, $.arguments)))
|
||||
),
|
||||
|
||||
_attribute_arguments: ($) =>
|
||||
seq("(", series_of($.attribute_value, ","), ")"),
|
||||
|
||||
attribute_value: ($) =>
|
||||
choice(
|
||||
$._constant_value,
|
||||
seq(field("label", $.label), ":", field("value", $._constant_value))
|
||||
),
|
||||
|
||||
/* Import statements */
|
||||
import: ($) =>
|
||||
seq(
|
||||
"import",
|
||||
field("module", $.module),
|
||||
optional(seq(".", field("imports", $.unqualified_imports))),
|
||||
optional(seq("as", field("alias", choice($.identifier, $.discard))))
|
||||
),
|
||||
module: ($) => seq($._name, repeat(seq("/", $._name))),
|
||||
unqualified_imports: ($) =>
|
||||
seq("{", optional(series_of($.unqualified_import, ",")), "}"),
|
||||
unqualified_import: ($) =>
|
||||
choice(
|
||||
seq(
|
||||
field("name", $.identifier),
|
||||
optional(seq("as", field("alias", $.identifier)))
|
||||
),
|
||||
seq(
|
||||
"type",
|
||||
field("name", $.type_identifier),
|
||||
optional(seq("as", field("alias", $.type_identifier)))
|
||||
),
|
||||
seq(
|
||||
field("name", $.constructor_name),
|
||||
optional(seq("as", field("alias", $.constructor_name)))
|
||||
)
|
||||
),
|
||||
|
||||
/* Constant statements */
|
||||
constant: ($) =>
|
||||
seq(
|
||||
optional($.visibility_modifier),
|
||||
"const",
|
||||
field("name", $.identifier),
|
||||
optional($._constant_type_annotation),
|
||||
"=",
|
||||
field("value", $._constant_value)
|
||||
),
|
||||
_constant_value: ($) =>
|
||||
choice(
|
||||
$.string,
|
||||
$.float,
|
||||
$.integer,
|
||||
alias($.constant_tuple, $.tuple),
|
||||
alias($.constant_list, $.list),
|
||||
alias($._constant_bit_string, $.bit_string),
|
||||
alias($.constant_record, $.record),
|
||||
$.identifier,
|
||||
alias($.constant_field_access, $.field_access)
|
||||
),
|
||||
constant_tuple: ($) =>
|
||||
seq("#", "(", optional(series_of($._constant_value, ",")), ")"),
|
||||
constant_list: ($) =>
|
||||
seq("[", optional(series_of($._constant_value, ",")), "]"),
|
||||
...bit_string_rules("constant", "_constant_value", "integer"),
|
||||
constant_record: ($) =>
|
||||
seq(
|
||||
field("name", choice($.constructor_name, $.remote_constructor_name)),
|
||||
optional(
|
||||
field("arguments", alias($.constant_record_arguments, $.arguments))
|
||||
)
|
||||
),
|
||||
constant_record_arguments: ($) =>
|
||||
seq(
|
||||
"(",
|
||||
optional(series_of(alias($.constant_record_argument, $.argument), ",")),
|
||||
")"
|
||||
),
|
||||
constant_record_argument: ($) =>
|
||||
choice(
|
||||
seq(
|
||||
optional(seq(field("label", $.label), ":")),
|
||||
field("value", $._constant_value)
|
||||
),
|
||||
seq(field("label", $.label), ":")
|
||||
),
|
||||
// This rule exists to parse remote function references which are generally
|
||||
// indistinguishable from field accesses and so share an AST node.
|
||||
constant_field_access: ($) =>
|
||||
seq(field("record", $.identifier), ".", field("field", $.label)),
|
||||
|
||||
/* Special constant types */
|
||||
// Versions of $._type, $._type_annotation, etc, that have constraints
|
||||
// specific to constants.
|
||||
_constant_type: ($) =>
|
||||
choice(
|
||||
$.type_hole,
|
||||
alias($.constant_tuple_type, $.tuple_type),
|
||||
alias($.constant_function_type, $.function_type),
|
||||
alias($.constant_type, $.type)
|
||||
),
|
||||
_constant_type_annotation: ($) => seq(":", field("type", $._constant_type)),
|
||||
constant_tuple_type: ($) =>
|
||||
seq("#", "(", optional(series_of($._constant_type, ",")), ")"),
|
||||
constant_function_type: ($) =>
|
||||
seq(
|
||||
"fn",
|
||||
optional(
|
||||
field(
|
||||
"parameter_types",
|
||||
alias(
|
||||
$.constant_function_parameter_types,
|
||||
$.function_parameter_types
|
||||
)
|
||||
)
|
||||
),
|
||||
"->",
|
||||
field("return_type", $._constant_type)
|
||||
),
|
||||
constant_function_parameter_types: ($) =>
|
||||
seq("(", optional(series_of($._constant_type, ",")), ")"),
|
||||
constant_type: ($) =>
|
||||
seq(
|
||||
field("name", choice($.type_identifier, $.remote_type_identifier)),
|
||||
optional(
|
||||
field("arguments", alias($.constant_type_arguments, $.type_arguments))
|
||||
)
|
||||
),
|
||||
constant_type_arguments: ($) =>
|
||||
seq(
|
||||
"(",
|
||||
optional(
|
||||
series_of(alias($.constant_type_argument, $.type_argument), ",")
|
||||
),
|
||||
")"
|
||||
),
|
||||
constant_type_argument: ($) => $._constant_type,
|
||||
|
||||
external_type: ($) =>
|
||||
prec.right(
|
||||
seq(
|
||||
optional($.visibility_modifier),
|
||||
// DEPRECATED: the external token was removed in v0.30.
|
||||
optional("external"),
|
||||
"type",
|
||||
$.type_name
|
||||
)
|
||||
),
|
||||
|
||||
/* External function */
|
||||
external_function: ($) =>
|
||||
seq(
|
||||
optional($.visibility_modifier),
|
||||
"external",
|
||||
"fn",
|
||||
field("name", $.identifier),
|
||||
field(
|
||||
"parameters",
|
||||
alias($.external_function_parameters, $.function_parameters)
|
||||
),
|
||||
"->",
|
||||
field("return_type", $._type),
|
||||
"=",
|
||||
field("body", $.external_function_body)
|
||||
),
|
||||
// Different from module function parameters in that module function
|
||||
// parameters may be labeled whereas external function parameters cannot.
|
||||
external_function_parameters: ($) =>
|
||||
seq(
|
||||
"(",
|
||||
optional(
|
||||
series_of(
|
||||
alias($.external_function_parameter, $.function_parameter),
|
||||
","
|
||||
)
|
||||
),
|
||||
")"
|
||||
),
|
||||
external_function_parameter: ($) =>
|
||||
seq(
|
||||
optional(seq(field("name", $.identifier), ":")),
|
||||
field("type", $._type)
|
||||
),
|
||||
external_function_body: ($) => seq($.string, $.string),
|
||||
|
||||
/* Functions */
|
||||
function: ($) =>
|
||||
prec.right(
|
||||
seq(
|
||||
optional($.visibility_modifier),
|
||||
"fn",
|
||||
field("name", $.identifier),
|
||||
field("parameters", $.function_parameters),
|
||||
optional(seq("->", field("return_type", $._type))),
|
||||
optional(field("body", $.block))
|
||||
)
|
||||
),
|
||||
function_parameters: ($) =>
|
||||
seq("(", optional(series_of($.function_parameter, ",")), ")"),
|
||||
function_parameter: ($) =>
|
||||
seq(
|
||||
choice(
|
||||
$._labeled_discard_param,
|
||||
$._discard_param,
|
||||
$._labeled_name_param,
|
||||
$._name_param
|
||||
),
|
||||
optional($._type_annotation)
|
||||
),
|
||||
_labeled_discard_param: ($) =>
|
||||
seq(field("label", $.label), field("name", $.discard)),
|
||||
_discard_param: ($) => field("name", $.discard),
|
||||
_labeled_name_param: ($) =>
|
||||
seq(field("label", $.label), field("name", $.identifier)),
|
||||
_name_param: ($) => field("name", $.identifier),
|
||||
_statement_seq: ($) => repeat1($._statement),
|
||||
_statement: ($) =>
|
||||
choice($._expression, $.let, $.let_assert, $.use, $.assert),
|
||||
_expression: ($) => choice($._expression_unit, $.binary_expression),
|
||||
binary_expression: ($) =>
|
||||
choice(
|
||||
binaryExpr(prec.left, 1, "||", $._expression),
|
||||
binaryExpr(prec.left, 2, "&&", $._expression),
|
||||
binaryExpr(prec.left, 3, "==", $._expression),
|
||||
binaryExpr(prec.left, 3, "!=", $._expression),
|
||||
binaryExpr(prec.left, 4, "<", $._expression),
|
||||
binaryExpr(prec.left, 4, "<=", $._expression),
|
||||
binaryExpr(prec.left, 4, "<.", $._expression),
|
||||
binaryExpr(prec.left, 4, "<=.", $._expression),
|
||||
binaryExpr(prec.left, 4, ">", $._expression),
|
||||
binaryExpr(prec.left, 4, ">=", $._expression),
|
||||
binaryExpr(prec.left, 4, ">.", $._expression),
|
||||
binaryExpr(prec.left, 4, ">=.", $._expression),
|
||||
binaryExpr(
|
||||
prec.left,
|
||||
5,
|
||||
"|>",
|
||||
$._expression,
|
||||
choice($.pipeline_echo, $._expression)
|
||||
),
|
||||
binaryExpr(prec.left, 6, "+", $._expression),
|
||||
binaryExpr(prec.left, 6, "+.", $._expression),
|
||||
binaryExpr(prec.left, 6, "-", $._expression),
|
||||
binaryExpr(prec.left, 6, "-.", $._expression),
|
||||
binaryExpr(prec.left, 7, "*", $._expression),
|
||||
binaryExpr(prec.left, 7, "*.", $._expression),
|
||||
binaryExpr(prec.left, 7, "/", $._expression),
|
||||
binaryExpr(prec.left, 7, "/.", $._expression),
|
||||
binaryExpr(prec.left, 7, "%", $._expression),
|
||||
binaryExpr(prec.left, 7, "<>", $._expression)
|
||||
),
|
||||
// The way that this function is written in the Gleam parser is essentially
|
||||
// incompatible with tree-sitter. It first parses some base expression,
|
||||
// then potentially parses tuple access, field access, record updates, or
|
||||
// function calls as an extension of that base expression that was
|
||||
// previously parsed. tree-sitter provides no facility to amend a node that
|
||||
// was already successfully parsed. Therefore, tuple access, field access,
|
||||
// record updates, and function calls must be parsed as alternatives to the
|
||||
// expressions they build upon rather than extensions thereof.
|
||||
_expression_unit: ($) =>
|
||||
choice(
|
||||
$.string,
|
||||
$.integer,
|
||||
$.float,
|
||||
// If we decide that record constructors (value constructors) are
|
||||
// actually functions, this will require a refactor.
|
||||
$.record,
|
||||
$.identifier,
|
||||
$.todo,
|
||||
$.panic,
|
||||
$.tuple,
|
||||
$.echo,
|
||||
$.list,
|
||||
alias($._expression_bit_string, $.bit_string),
|
||||
$.anonymous_function,
|
||||
$.block,
|
||||
$.case,
|
||||
$.boolean_negation,
|
||||
$.integer_negation,
|
||||
$.record_update,
|
||||
$.tuple_access,
|
||||
$.field_access,
|
||||
$.function_call
|
||||
),
|
||||
record: ($) =>
|
||||
seq(
|
||||
field("name", choice($.constructor_name, $.remote_constructor_name)),
|
||||
optional(field("arguments", $.arguments))
|
||||
),
|
||||
todo: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
"todo",
|
||||
optional(
|
||||
choice(
|
||||
// DEPRECATED: The 'as' syntax was introduced in v0.30.
|
||||
seq("(", field("message", $.string), ")"),
|
||||
seq("as", field("message", $._expression))
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
panic: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
"panic",
|
||||
optional(
|
||||
choice(
|
||||
seq("(", field("message", $.string), ")"),
|
||||
seq("as", field("message", $._expression))
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
pipeline_echo: (_$) => prec.left("echo"),
|
||||
echo: ($) => seq("echo", $._expression),
|
||||
tuple: ($) => seq("#", "(", optional(series_of($._expression, ",")), ")"),
|
||||
list: ($) =>
|
||||
seq(
|
||||
"[",
|
||||
optional(
|
||||
seq(
|
||||
$._expression,
|
||||
optional(repeat(seq(",", $._expression))),
|
||||
optional(","),
|
||||
optional(seq("..", field("spread", $._expression)))
|
||||
)
|
||||
),
|
||||
"]"
|
||||
),
|
||||
...bit_string_rules("expression", "_expression_unit", "_expression"),
|
||||
anonymous_function: ($) =>
|
||||
seq(
|
||||
"fn",
|
||||
field(
|
||||
"parameters",
|
||||
alias($.anonymous_function_parameters, $.function_parameters)
|
||||
),
|
||||
optional(seq("->", field("return_type", $._type))),
|
||||
field("body", $.block)
|
||||
),
|
||||
anonymous_function_parameters: ($) =>
|
||||
seq(
|
||||
"(",
|
||||
optional(
|
||||
series_of(
|
||||
alias($.anonymous_function_parameter, $.function_parameter),
|
||||
","
|
||||
)
|
||||
),
|
||||
")"
|
||||
),
|
||||
anonymous_function_parameter: ($) =>
|
||||
seq(
|
||||
choice($._discard_param, $._name_param),
|
||||
optional($._type_annotation)
|
||||
),
|
||||
block: ($) => seq("{", optional($._statement_seq), "}"),
|
||||
case: ($) =>
|
||||
seq(
|
||||
"case",
|
||||
field("subjects", $.case_subjects),
|
||||
"{",
|
||||
optional(field("clauses", $.case_clauses)),
|
||||
"}"
|
||||
),
|
||||
case_subjects: ($) => seq(series_of($._expression, ",")),
|
||||
case_clauses: ($) => repeat1($.case_clause),
|
||||
case_clause: ($) =>
|
||||
seq(
|
||||
field("patterns", $.case_clause_patterns),
|
||||
optional(field("guard", $.case_clause_guard)),
|
||||
"->",
|
||||
field("value", $._expression)
|
||||
),
|
||||
// Technically the Gleam parser does support something like this:
|
||||
// 1 | | 5 -> True
|
||||
// However, that will cause an error further into the compiler. That format
|
||||
// is not supported by this function.
|
||||
case_clause_patterns: ($) => seq(series_of($.case_clause_pattern, "|")),
|
||||
// The issue above comes from the fact that the parser equivalent of this
|
||||
// function supports 0 patterns. This function does not.
|
||||
case_clause_pattern: ($) => series_of($._pattern, ","),
|
||||
case_clause_guard: ($) => seq("if", $._case_clause_guard_expression),
|
||||
_case_clause_guard_expression: ($) =>
|
||||
choice(
|
||||
$._case_clause_guard_unit,
|
||||
alias($._case_clause_guard_binary_expression, $.binary_expression),
|
||||
$.boolean_negation
|
||||
),
|
||||
_case_clause_guard_binary_expression: ($) =>
|
||||
choice(
|
||||
binaryExpr(prec.left, 1, "||", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 2, "&&", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 3, "==", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 3, "!=", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 4, "<", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 4, "<=", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 4, "<.", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 4, "<=.", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 4, ">", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 4, ">=", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 4, ">.", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 4, ">=.", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 5, "+", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 5, "+.", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 5, "-", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 5, "-.", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 6, "*", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 6, "*.", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 6, "/", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 6, "/.", $._case_clause_guard_expression),
|
||||
binaryExpr(prec.left, 6, "%", $._case_clause_guard_expression)
|
||||
),
|
||||
_case_clause_guard_unit: ($) =>
|
||||
choice(
|
||||
$.identifier,
|
||||
prec(1, alias($._case_clause_tuple_access, $.tuple_access)),
|
||||
seq("{", $._case_clause_guard_expression, "}"),
|
||||
$._constant_value
|
||||
),
|
||||
_case_clause_tuple_access: ($) =>
|
||||
seq(field("tuple", $.identifier), ".", field("index", $.integer)),
|
||||
let_assert: ($) =>
|
||||
seq(
|
||||
"let",
|
||||
"assert",
|
||||
$._assignment,
|
||||
optional(seq("as", field("message", $._expression)))
|
||||
),
|
||||
assert: ($) =>
|
||||
seq(
|
||||
"assert",
|
||||
field("value", $._expression),
|
||||
optional(seq("as", field("message", $._expression)))
|
||||
),
|
||||
let: ($) => seq("let", $._assignment),
|
||||
use: ($) =>
|
||||
seq(
|
||||
"use",
|
||||
optional(field("assignments", $.use_assignments)),
|
||||
"<-",
|
||||
field("value", $._expression)
|
||||
),
|
||||
use_assignments: ($) => series_of($.use_assignment, ","),
|
||||
use_assignment: ($) => seq($._pattern, optional($._type_annotation)),
|
||||
boolean_negation: ($) => seq("!", $._expression_unit),
|
||||
integer_negation: ($) => seq("-", $._expression_unit),
|
||||
_assignment: ($) =>
|
||||
seq(
|
||||
field("pattern", $._pattern),
|
||||
optional($._type_annotation),
|
||||
"=",
|
||||
field("value", $._expression)
|
||||
),
|
||||
record_update: ($) =>
|
||||
seq(
|
||||
field(
|
||||
"constructor",
|
||||
choice($.constructor_name, $.remote_constructor_name)
|
||||
),
|
||||
"(",
|
||||
"..",
|
||||
field("spread", $._expression),
|
||||
",",
|
||||
field("arguments", $.record_update_arguments),
|
||||
")"
|
||||
),
|
||||
record_update_arguments: ($) => series_of($.record_update_argument, ","),
|
||||
record_update_argument: ($) =>
|
||||
choice(
|
||||
seq(field("label", $.label), ":", field("value", $._expression)),
|
||||
seq(field("label", $.label), ":")
|
||||
),
|
||||
// As with other AST nodes in this section, `_maybe_record_expression`,
|
||||
// `_maybe_tuple_expression`, and `_maybe_function_expresssion` have no
|
||||
// corollaries in the Gleam parser. These anonymous AST node denote any
|
||||
// expression whose return type could be a record, tuple, or function,
|
||||
// respectively.
|
||||
//
|
||||
// `let` and `assert` are exempted because in order to parse correctly,
|
||||
// they would have to be wrapped in an expression group anyways.
|
||||
_maybe_tuple_expression: ($) =>
|
||||
choice(
|
||||
$.identifier,
|
||||
$.function_call,
|
||||
$.tuple,
|
||||
$.block,
|
||||
$.case,
|
||||
$.field_access,
|
||||
$.tuple_access
|
||||
),
|
||||
tuple_access: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
field("tuple", $._maybe_tuple_expression),
|
||||
".",
|
||||
field("index", $.integer)
|
||||
)
|
||||
),
|
||||
_maybe_record_expression: ($) =>
|
||||
choice(
|
||||
$.record,
|
||||
$.identifier,
|
||||
$.function_call,
|
||||
$.block,
|
||||
$.case,
|
||||
$.record_update,
|
||||
$.field_access,
|
||||
$.tuple_access
|
||||
),
|
||||
field_access: ($) =>
|
||||
prec.left(
|
||||
seq(
|
||||
field("record", $._maybe_record_expression),
|
||||
".",
|
||||
field("field", $.label)
|
||||
)
|
||||
),
|
||||
// Remote functions (e.g. int.to_string) is parsed as a field access
|
||||
// (accessing field to_string on record int) as it is impossible for the
|
||||
// parser to determine with int is a module (and thus to_string a member
|
||||
// function) or a local variable containing a record (and thus to_string is
|
||||
// a field of that record).
|
||||
// Similarly, the function name in local function calls (e.g. foo(arg)) is
|
||||
// parsed as an $.identifier which is used to refer to both local variables
|
||||
// and module functions, embodying the same ambiguity.
|
||||
_maybe_function_expression: ($) =>
|
||||
choice(
|
||||
$.identifier,
|
||||
$.anonymous_function,
|
||||
$.block,
|
||||
$.case,
|
||||
$.tuple_access,
|
||||
$.field_access,
|
||||
$.function_call
|
||||
),
|
||||
// Interestingly, the code that parses function arguments also parses
|
||||
// record arguments, hence the ambiguous name.
|
||||
arguments: ($) => seq("(", optional(series_of($.argument, ",")), ")"),
|
||||
argument: ($) =>
|
||||
choice(
|
||||
seq(
|
||||
optional(seq(field("label", $.label), ":")),
|
||||
field("value", choice($.hole, $._expression))
|
||||
),
|
||||
seq(field("label", $.label), ":")
|
||||
),
|
||||
hole: ($) => $._discard_name,
|
||||
function_call: ($) =>
|
||||
seq(
|
||||
field("function", $._maybe_function_expression),
|
||||
field("arguments", $.arguments)
|
||||
),
|
||||
_pattern_expression: ($) =>
|
||||
choice(
|
||||
$.identifier,
|
||||
$.discard,
|
||||
$.record_pattern,
|
||||
$.string,
|
||||
$.integer,
|
||||
$.float,
|
||||
$.tuple_pattern,
|
||||
alias($._pattern_bit_string, $.bit_string_pattern),
|
||||
$.list_pattern,
|
||||
alias($._pattern_binary_expression, $.binary_expression)
|
||||
),
|
||||
_pattern_binary_expression: ($) =>
|
||||
choice(
|
||||
binaryExpr(prec.left, 1, "<>", $._pattern_expression),
|
||||
binaryExpr(prec.left, 1, "as", $.string, $.identifier)
|
||||
),
|
||||
_pattern: ($) =>
|
||||
seq(
|
||||
$._pattern_expression,
|
||||
optional(field("assign", seq("as", $.identifier)))
|
||||
),
|
||||
record_pattern: ($) =>
|
||||
seq(
|
||||
field("name", choice($.constructor_name, $.remote_constructor_name)),
|
||||
optional(field("arguments", $.record_pattern_arguments))
|
||||
),
|
||||
record_pattern_arguments: ($) =>
|
||||
seq(
|
||||
"(",
|
||||
optional(series_of($.record_pattern_argument, ",")),
|
||||
optional($.pattern_spread),
|
||||
")"
|
||||
),
|
||||
record_pattern_argument: ($) =>
|
||||
choice(
|
||||
seq(
|
||||
optional(seq(field("label", $.label), ":")),
|
||||
field("pattern", $._pattern)
|
||||
),
|
||||
seq(field("label", $.label), ":")
|
||||
),
|
||||
pattern_spread: ($) => seq("..", optional(",")),
|
||||
tuple_pattern: ($) =>
|
||||
seq("#", "(", optional(series_of($._pattern, ",")), ")"),
|
||||
// The Gleam parser has a special catch for nested bitstrings here, which
|
||||
// is interesting as the same error does not exist on constants. Anyhow, I
|
||||
// wasn't really sure how to implement that easily here, and so didn't.
|
||||
...bit_string_rules(
|
||||
"pattern",
|
||||
"_pattern",
|
||||
"_pattern_bit_string_segment_argument"
|
||||
),
|
||||
_pattern_bit_string_segment_argument: ($) =>
|
||||
choice($.identifier, $.integer),
|
||||
list_pattern: ($) =>
|
||||
seq(
|
||||
"[",
|
||||
optional(series_of($._pattern, ",")),
|
||||
optional($.list_pattern_tail),
|
||||
"]"
|
||||
),
|
||||
list_pattern_tail: ($) =>
|
||||
seq("..", optional(choice($.identifier, $.discard))),
|
||||
|
||||
visibility_modifier: ($) => "pub",
|
||||
opacity_modifier: ($) => "opaque",
|
||||
|
||||
/* Custom type definitions */
|
||||
type_definition: ($) =>
|
||||
seq(
|
||||
optional($.visibility_modifier),
|
||||
optional($.opacity_modifier),
|
||||
"type",
|
||||
$.type_name,
|
||||
"{",
|
||||
$.data_constructors,
|
||||
"}"
|
||||
),
|
||||
data_constructors: ($) => repeat1($.data_constructor),
|
||||
data_constructor: ($) =>
|
||||
seq(
|
||||
optional($.attribute),
|
||||
field("name", $.constructor_name),
|
||||
optional(field("arguments", $.data_constructor_arguments))
|
||||
),
|
||||
data_constructor_arguments: ($) =>
|
||||
seq("(", optional(series_of($.data_constructor_argument, ",")), ")"),
|
||||
data_constructor_argument: ($) =>
|
||||
seq(optional(seq(field("label", $.label), ":")), field("value", $._type)),
|
||||
|
||||
/* Type aliases */
|
||||
type_alias: ($) =>
|
||||
seq(
|
||||
optional($.visibility_modifier),
|
||||
optional($.opacity_modifier),
|
||||
"type",
|
||||
$.type_name,
|
||||
"=",
|
||||
$._type
|
||||
),
|
||||
|
||||
/* Literals */
|
||||
string: ($) =>
|
||||
seq(
|
||||
'"',
|
||||
repeat(choice($.escape_sequence, $.quoted_content)),
|
||||
token.immediate('"')
|
||||
),
|
||||
escape_sequence: ($) =>
|
||||
choice(
|
||||
token.immediate(/\\[efnrt\"\\]/),
|
||||
token.immediate(/\\u\{[0-9a-fA-F]{1,6}\}/)
|
||||
),
|
||||
float: ($) => /-?[0-9_]+\.[0-9_]*(e-?[0-9_]+)?/,
|
||||
integer: ($) =>
|
||||
seq(optional("-"), choice($._hex, $._decimal, $._octal, $._binary)),
|
||||
_hex: ($) => /0[xX][0-9a-fA-F_]+/,
|
||||
_decimal: ($) => /[0-9][0-9_]*/,
|
||||
_octal: ($) => /0[oO][0-7_]+/,
|
||||
_binary: ($) => /0[bB][0-1_]+/,
|
||||
_bit_string_segment_option: ($) =>
|
||||
choice(
|
||||
"binary",
|
||||
"bytes",
|
||||
"int",
|
||||
"float",
|
||||
"bit_string",
|
||||
"bits",
|
||||
"utf8",
|
||||
"utf16",
|
||||
"utf32",
|
||||
"utf8_codepoint",
|
||||
"utf16_codepoint",
|
||||
"utf32_codepoint",
|
||||
"signed",
|
||||
"unsigned",
|
||||
"big",
|
||||
"little",
|
||||
"native",
|
||||
seq("unit", "(", $.integer, ")")
|
||||
),
|
||||
|
||||
/* Types */
|
||||
_type: ($) =>
|
||||
choice($.type_hole, $.tuple_type, $.function_type, $.type, $.type_var),
|
||||
_type_annotation: ($) => seq(":", field("type", $._type)),
|
||||
type_hole: ($) => $._discard_name,
|
||||
// If you're wondering why there isn't a `list_type` here, the answer is
|
||||
// that the "type" form for lists is `List`, which is identical to
|
||||
// user-defined types etc and thus is not parsed specially.
|
||||
tuple_type: ($) => seq("#", "(", optional(series_of($._type, ",")), ")"),
|
||||
function_type: ($) =>
|
||||
seq(
|
||||
"fn",
|
||||
optional(field("parameter_types", $.function_parameter_types)),
|
||||
"->",
|
||||
field("return_type", $._type)
|
||||
),
|
||||
function_parameter_types: ($) =>
|
||||
seq("(", optional(series_of($._type, ",")), ")"),
|
||||
// "type" is a somewhat ambiguous name, but it refers to a concrete type
|
||||
// such as `Bool` or `List(Int)` or even `result.Result(#(Int, Int), Nil)`.
|
||||
type: ($) =>
|
||||
seq(
|
||||
field("name", choice($.type_identifier, $.remote_type_identifier)),
|
||||
optional(field("arguments", $.type_arguments))
|
||||
),
|
||||
type_arguments: ($) =>
|
||||
seq("(", optional(series_of($.type_argument, ",")), ")"),
|
||||
type_argument: ($) => $._type,
|
||||
type_var: ($) => $._name,
|
||||
|
||||
// "type_name" essentially refers to the declaration of a type. The type
|
||||
// parameters are part of the "name." Bit odd, but 🤷
|
||||
// e.g. MyType(a, b)
|
||||
type_name: ($) =>
|
||||
seq(
|
||||
field("name", choice($.type_identifier, $.remote_type_identifier)),
|
||||
optional(field("parameters", $.type_parameters))
|
||||
),
|
||||
type_parameters: ($) =>
|
||||
seq("(", optional(series_of($.type_parameter, ",")), ")"),
|
||||
type_parameter: ($) => $._name,
|
||||
|
||||
/* Shared AST nodes */
|
||||
identifier: ($) => $._name,
|
||||
label: ($) => $._name,
|
||||
discard: ($) => $._discard_name,
|
||||
type_identifier: ($) => $._upname,
|
||||
remote_type_identifier: ($) =>
|
||||
seq(field("module", $.identifier), ".", field("name", $.type_identifier)),
|
||||
constructor_name: ($) => $._upname,
|
||||
remote_constructor_name: ($) =>
|
||||
seq(
|
||||
field("module", $.identifier),
|
||||
".",
|
||||
field("name", $.constructor_name)
|
||||
),
|
||||
|
||||
/* Reused types from the Gleam lexer */
|
||||
_discard_name: ($) => /_[_0-9a-z]*/,
|
||||
_name: ($) => /[_a-z][_0-9a-z]*/,
|
||||
_upname: ($) => /[A-Z][0-9a-zA-Z]*/,
|
||||
},
|
||||
});
|
||||
|
||||
// This function and the following function are vaguely congruent with the
|
||||
// `parse_bit_string_segment` function of the Gleam parser.
|
||||
function bit_string_rules(name, value_parser, arg_parser) {
|
||||
return {
|
||||
[`_${name}_bit_string`]: ($) =>
|
||||
seq(
|
||||
"<<",
|
||||
optional(
|
||||
series_of(
|
||||
alias($[`${name}_bit_string_segment`], $.bit_string_segment),
|
||||
","
|
||||
)
|
||||
),
|
||||
">>"
|
||||
),
|
||||
[`${name}_bit_string_segment`]: ($) =>
|
||||
seq(
|
||||
field("value", $[value_parser]),
|
||||
optional(
|
||||
field(
|
||||
"options",
|
||||
seq(
|
||||
":",
|
||||
alias(
|
||||
$[`${name}_bit_string_segment_options`],
|
||||
$.bit_string_segment_options
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
...bit_string_segment_options(name, arg_parser),
|
||||
};
|
||||
}
|
||||
|
||||
function bit_string_segment_options(name, arg_parser) {
|
||||
return {
|
||||
[`${name}_bit_string_segment_options`]: ($) =>
|
||||
series_of($[`_${name}_bit_string_segment_option`], "-"),
|
||||
[`_${name}_bit_string_segment_option`]: ($) =>
|
||||
choice($[`_${name}_bit_string_named_segment_option`], $.integer),
|
||||
[`_${name}_bit_string_named_segment_option`]: ($) =>
|
||||
alias(
|
||||
choice(
|
||||
$._bit_string_segment_option,
|
||||
$[`_${name}_bit_string_segment_option_size`]
|
||||
),
|
||||
$.bit_string_segment_option
|
||||
),
|
||||
[`_${name}_bit_string_segment_option_size`]: ($) =>
|
||||
seq("size", "(", $[arg_parser], ")"),
|
||||
};
|
||||
}
|
||||
|
||||
// Shamelessly stolen "sep1" from tree-sitter-elixir, renamed to match a similar
|
||||
// function in the Gleam parser.
|
||||
// https://github.com/elixir-lang/tree-sitter-elixir/blob/de3ec57591aebf451e710fc9c984cf601258baf5/grammar.js#L817-L819
|
||||
function series_of(rule, separator) {
|
||||
return seq(rule, repeat(seq(separator, rule)), optional(separator));
|
||||
}
|
||||
|
||||
// A binary expression with a left-hand side, infix operator, and then right-hand-side
|
||||
// https://github.com/elixir-lang/tree-sitter-elixir/blob/de20391afe5cb03ef1e8a8e43167e7b58cc52869/grammar.js#L850-L859
|
||||
function binaryExpr(assoc, precedence, operator, left, right = null) {
|
||||
return assoc(
|
||||
precedence,
|
||||
seq(
|
||||
field("left", left),
|
||||
field("operator", operator),
|
||||
field("right", right || left)
|
||||
)
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
||||
{
|
||||
"name": "tree-sitter-gleam",
|
||||
"version": "1.0.0",
|
||||
"description": "A tree-sitter grammar for the Gleam programming language",
|
||||
"main": "bindings/node",
|
||||
"scripts": {
|
||||
"generate": "tree-sitter generate",
|
||||
"test": "tree-sitter test",
|
||||
"format": "prettier --write grammar.js",
|
||||
"check-formatted": "prettier --check grammar.js",
|
||||
"build-wasm": "tree-sitter build-wasm"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/J3RN/tree-sitter-gleam.git"
|
||||
},
|
||||
"keywords": [
|
||||
"gleam",
|
||||
"parser",
|
||||
"lexer",
|
||||
"tree-sitter"
|
||||
],
|
||||
"author": "Jonathan Arnett",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/J3RN/tree-sitter-gleam/issues"
|
||||
},
|
||||
"homepage": "https://github.com/J3RN/tree-sitter-gleam#readme",
|
||||
"dependencies": {
|
||||
"nan": "^2.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^2.5.1",
|
||||
"tree-sitter-cli": "^0.20.6",
|
||||
"node-gyp": "^10.0.1"
|
||||
},
|
||||
"tree-sitter": [
|
||||
{
|
||||
"scope": "source.gleam",
|
||||
"file-types": [
|
||||
"gleam"
|
||||
],
|
||||
"injection-regex": "^gleam$"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,131 +0,0 @@
|
||||
; Comments
|
||||
(module_comment) @comment
|
||||
(statement_comment) @comment
|
||||
(comment) @comment
|
||||
|
||||
; Constants
|
||||
(constant
|
||||
name: (identifier) @constant)
|
||||
|
||||
; Modules
|
||||
(module) @module
|
||||
(import alias: (identifier) @module)
|
||||
(remote_type_identifier
|
||||
module: (identifier) @module)
|
||||
(remote_constructor_name
|
||||
module: (identifier) @module)
|
||||
((field_access
|
||||
record: (identifier) @module
|
||||
field: (label) @function)
|
||||
(#is-not? local))
|
||||
|
||||
; Functions
|
||||
(unqualified_import (identifier) @function)
|
||||
(unqualified_import "type" (type_identifier) @type)
|
||||
(unqualified_import (type_identifier) @constructor)
|
||||
(function
|
||||
name: (identifier) @function)
|
||||
(external_function
|
||||
name: (identifier) @function)
|
||||
(function_parameter
|
||||
name: (identifier) @variable.parameter)
|
||||
((function_call
|
||||
function: (identifier) @function)
|
||||
(#is-not? local))
|
||||
((binary_expression
|
||||
operator: "|>"
|
||||
right: (identifier) @function)
|
||||
(#is-not? local))
|
||||
|
||||
; "Properties"
|
||||
; Assumed to be intended to refer to a name for a field; something that comes
|
||||
; before ":" or after "."
|
||||
; e.g. record field names, tuple indices, names for named arguments, etc
|
||||
(label) @property
|
||||
(tuple_access
|
||||
index: (integer) @property)
|
||||
|
||||
; Attributes
|
||||
(attribute
|
||||
"@" @attribute
|
||||
name: (identifier) @attribute)
|
||||
|
||||
(attribute_value (identifier) @constant)
|
||||
|
||||
; Type names
|
||||
(remote_type_identifier) @type
|
||||
(type_identifier) @type
|
||||
|
||||
; Data constructors
|
||||
(constructor_name) @constructor
|
||||
|
||||
; Literals
|
||||
(string) @string
|
||||
((escape_sequence) @warning
|
||||
; Deprecated in v0.33.0-rc2:
|
||||
(#eq? @warning "\\e"))
|
||||
(escape_sequence) @string.escape
|
||||
(bit_string_segment_option) @function.builtin
|
||||
(integer) @number
|
||||
(float) @number
|
||||
|
||||
; Reserved identifiers
|
||||
; TODO: when tree-sitter supports `#any-of?` in the Rust bindings,
|
||||
; refactor this to use `#any-of?` rather than `#match?`
|
||||
((identifier) @error
|
||||
(#match? @error "^(auto|delegate|derive|else|implement|macro|test)$"))
|
||||
|
||||
; Variables
|
||||
(identifier) @variable
|
||||
(discard) @comment.unused
|
||||
|
||||
; Keywords
|
||||
[
|
||||
(visibility_modifier) ; "pub"
|
||||
(opacity_modifier) ; "opaque"
|
||||
"as"
|
||||
"assert"
|
||||
"case"
|
||||
"const"
|
||||
"echo"
|
||||
; DEPRECATED: 'external' was removed in v0.30.
|
||||
"external"
|
||||
"fn"
|
||||
"if"
|
||||
"import"
|
||||
"let"
|
||||
"panic"
|
||||
"todo"
|
||||
"type"
|
||||
"use"
|
||||
] @keyword
|
||||
|
||||
; Operators
|
||||
(binary_expression
|
||||
operator: _ @operator)
|
||||
(boolean_negation "!" @operator)
|
||||
(integer_negation "-" @operator)
|
||||
|
||||
; Punctuation
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
"<<"
|
||||
">>"
|
||||
] @punctuation.bracket
|
||||
[
|
||||
"."
|
||||
","
|
||||
;; Controversial -- maybe some are operators?
|
||||
":"
|
||||
"#"
|
||||
"="
|
||||
"->"
|
||||
".."
|
||||
"-"
|
||||
"<-"
|
||||
] @punctuation.delimiter
|
||||
@ -1,17 +0,0 @@
|
||||
; Scopes
|
||||
(block) @local.scope
|
||||
|
||||
(function) @local.scope
|
||||
|
||||
(case_clause) @local.scope
|
||||
|
||||
; Definitions
|
||||
(let pattern: (identifier) @local.definition)
|
||||
(function_parameter name: (identifier) @local.definition)
|
||||
(list_pattern (identifier) @local.definition)
|
||||
(list_pattern assign: (identifier) @local.definition)
|
||||
(tuple_pattern (identifier) @local.definition)
|
||||
(record_pattern_argument pattern: (identifier) @local.definition)
|
||||
|
||||
; References
|
||||
(identifier) @local.reference
|
||||
@ -1,41 +0,0 @@
|
||||
; Modules
|
||||
(module) @name @reference.module
|
||||
(import alias: (identifier) @name) @reference.module
|
||||
(remote_type_identifier
|
||||
module: (identifier) @name) @reference.module
|
||||
((field_access
|
||||
record: (identifier) @name)
|
||||
(#is-not? local)) @reference.module
|
||||
|
||||
; Functions
|
||||
(function
|
||||
name: (identifier) @name) @definition.function
|
||||
(external_function
|
||||
name: (identifier) @name) @definition.function
|
||||
(unqualified_import (identifier) @name) @reference.function
|
||||
((function_call
|
||||
function: (identifier) @name) @reference.function
|
||||
(#is-not? local))
|
||||
((field_access
|
||||
record: (identifier) @ignore
|
||||
field: (label) @name)
|
||||
(#is-not? local)) @reference.function
|
||||
((binary_expression
|
||||
operator: "|>"
|
||||
right: (identifier) @name)
|
||||
(#is-not? local)) @reference.function
|
||||
|
||||
; Types
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier) @name)) @definition.type
|
||||
(type_definition
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name) @name))) @definition.constructor
|
||||
(external_type
|
||||
(type_name
|
||||
name: (type_identifier) @name)) @definition.type
|
||||
|
||||
(type_identifier) @name @reference.type
|
||||
(constructor_name) @name @reference.constructor
|
||||
@ -1,24 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
usage() {
|
||||
echo "$0"
|
||||
echo ""
|
||||
echo "Tests that the parser does not create error nodes"
|
||||
echo "when tested against real Gleam repos"
|
||||
echo ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -ne 0 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
repos="gleam-lang/stdlib gleam-lang/json gleam-lang/http gleam-lang/example-todomvc gleam-lang/bitwise gleam-lang/erlang gleam-lang/otp gleam-lang/cowboy gleam-lang/hackney gleam-lang/httpc gleam-lang/elli gleam-lang/javascript gleam-lang/example-echo-server gleam-lang/plug"
|
||||
|
||||
for repo in $repos; do
|
||||
./scripts/parse_repo.sh $repo
|
||||
done
|
||||
@ -1,29 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
usage() {
|
||||
echo "$0 owner/repository"
|
||||
echo ""
|
||||
echo "Runs the parser against Gleam files in a GitHub repository"
|
||||
echo ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
gh_repo="$1"
|
||||
dir="test/integration/${gh_repo//[\/-]/_}"
|
||||
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
mkdir -p "$(dirname "$dir")"
|
||||
git clone --depth 1 "https://github.com/$gh_repo.git" "$dir"
|
||||
fi
|
||||
|
||||
echo "Running parser against $gh_repo"
|
||||
|
||||
npx tree-sitter parse --quiet --stat "$dir/**/*.gleam"
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,29 +0,0 @@
|
||||
#include <tree_sitter/parser.h>
|
||||
|
||||
enum TokenType {
|
||||
QUOTED_CONTENT
|
||||
};
|
||||
|
||||
void * tree_sitter_gleam_external_scanner_create() {return NULL;}
|
||||
void tree_sitter_gleam_external_scanner_destroy(void * payload) {}
|
||||
unsigned tree_sitter_gleam_external_scanner_serialize(void * payload, char * buffer) {return 0;}
|
||||
void tree_sitter_gleam_external_scanner_deserialize(void * payload, const char * buffer, unsigned length) {}
|
||||
|
||||
bool tree_sitter_gleam_external_scanner_scan(void * payload, TSLexer *lexer, const bool * valid_symbols) {
|
||||
if (valid_symbols[QUOTED_CONTENT]) {
|
||||
bool has_content = false;
|
||||
|
||||
while (true) {
|
||||
if (lexer->lookahead == '\"' || lexer->lookahead == '\\') {
|
||||
break;
|
||||
} else if (lexer->lookahead == 0) {
|
||||
return false;
|
||||
}
|
||||
has_content = true;
|
||||
lexer->advance(lexer, false);
|
||||
}
|
||||
lexer->result_symbol = QUOTED_CONTENT;
|
||||
return has_content;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1,224 +0,0 @@
|
||||
#ifndef TREE_SITTER_PARSER_H_
|
||||
#define TREE_SITTER_PARSER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ts_builtin_sym_error ((TSSymbol)-1)
|
||||
#define ts_builtin_sym_end 0
|
||||
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
|
||||
|
||||
typedef uint16_t TSStateId;
|
||||
|
||||
#ifndef TREE_SITTER_API_H_
|
||||
typedef uint16_t TSSymbol;
|
||||
typedef uint16_t TSFieldId;
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
TSFieldId field_id;
|
||||
uint8_t child_index;
|
||||
bool inherited;
|
||||
} TSFieldMapEntry;
|
||||
|
||||
typedef struct {
|
||||
uint16_t index;
|
||||
uint16_t length;
|
||||
} TSFieldMapSlice;
|
||||
|
||||
typedef struct {
|
||||
bool visible;
|
||||
bool named;
|
||||
bool supertype;
|
||||
} TSSymbolMetadata;
|
||||
|
||||
typedef struct TSLexer TSLexer;
|
||||
|
||||
struct TSLexer {
|
||||
int32_t lookahead;
|
||||
TSSymbol result_symbol;
|
||||
void (*advance)(TSLexer *, bool);
|
||||
void (*mark_end)(TSLexer *);
|
||||
uint32_t (*get_column)(TSLexer *);
|
||||
bool (*is_at_included_range_start)(const TSLexer *);
|
||||
bool (*eof)(const TSLexer *);
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
TSParseActionTypeShift,
|
||||
TSParseActionTypeReduce,
|
||||
TSParseActionTypeAccept,
|
||||
TSParseActionTypeRecover,
|
||||
} TSParseActionType;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t type;
|
||||
TSStateId state;
|
||||
bool extra;
|
||||
bool repetition;
|
||||
} shift;
|
||||
struct {
|
||||
uint8_t type;
|
||||
uint8_t child_count;
|
||||
TSSymbol symbol;
|
||||
int16_t dynamic_precedence;
|
||||
uint16_t production_id;
|
||||
} reduce;
|
||||
uint8_t type;
|
||||
} TSParseAction;
|
||||
|
||||
typedef struct {
|
||||
uint16_t lex_state;
|
||||
uint16_t external_lex_state;
|
||||
} TSLexMode;
|
||||
|
||||
typedef union {
|
||||
TSParseAction action;
|
||||
struct {
|
||||
uint8_t count;
|
||||
bool reusable;
|
||||
} entry;
|
||||
} TSParseActionEntry;
|
||||
|
||||
struct TSLanguage {
|
||||
uint32_t version;
|
||||
uint32_t symbol_count;
|
||||
uint32_t alias_count;
|
||||
uint32_t token_count;
|
||||
uint32_t external_token_count;
|
||||
uint32_t state_count;
|
||||
uint32_t large_state_count;
|
||||
uint32_t production_id_count;
|
||||
uint32_t field_count;
|
||||
uint16_t max_alias_sequence_length;
|
||||
const uint16_t *parse_table;
|
||||
const uint16_t *small_parse_table;
|
||||
const uint32_t *small_parse_table_map;
|
||||
const TSParseActionEntry *parse_actions;
|
||||
const char * const *symbol_names;
|
||||
const char * const *field_names;
|
||||
const TSFieldMapSlice *field_map_slices;
|
||||
const TSFieldMapEntry *field_map_entries;
|
||||
const TSSymbolMetadata *symbol_metadata;
|
||||
const TSSymbol *public_symbol_map;
|
||||
const uint16_t *alias_map;
|
||||
const TSSymbol *alias_sequences;
|
||||
const TSLexMode *lex_modes;
|
||||
bool (*lex_fn)(TSLexer *, TSStateId);
|
||||
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
||||
TSSymbol keyword_capture_token;
|
||||
struct {
|
||||
const bool *states;
|
||||
const TSSymbol *symbol_map;
|
||||
void *(*create)(void);
|
||||
void (*destroy)(void *);
|
||||
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
|
||||
unsigned (*serialize)(void *, char *);
|
||||
void (*deserialize)(void *, const char *, unsigned);
|
||||
} external_scanner;
|
||||
const TSStateId *primary_state_ids;
|
||||
};
|
||||
|
||||
/*
|
||||
* Lexer Macros
|
||||
*/
|
||||
|
||||
#define START_LEXER() \
|
||||
bool result = false; \
|
||||
bool skip = false; \
|
||||
bool eof = false; \
|
||||
int32_t lookahead; \
|
||||
goto start; \
|
||||
next_state: \
|
||||
lexer->advance(lexer, skip); \
|
||||
start: \
|
||||
skip = false; \
|
||||
lookahead = lexer->lookahead;
|
||||
|
||||
#define ADVANCE(state_value) \
|
||||
{ \
|
||||
state = state_value; \
|
||||
goto next_state; \
|
||||
}
|
||||
|
||||
#define SKIP(state_value) \
|
||||
{ \
|
||||
skip = true; \
|
||||
state = state_value; \
|
||||
goto next_state; \
|
||||
}
|
||||
|
||||
#define ACCEPT_TOKEN(symbol_value) \
|
||||
result = true; \
|
||||
lexer->result_symbol = symbol_value; \
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
#define END_STATE() return result;
|
||||
|
||||
/*
|
||||
* Parse Table Macros
|
||||
*/
|
||||
|
||||
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
|
||||
|
||||
#define STATE(id) id
|
||||
|
||||
#define ACTIONS(id) id
|
||||
|
||||
#define SHIFT(state_value) \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.state = state_value \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define SHIFT_REPEAT(state_value) \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.state = state_value, \
|
||||
.repetition = true \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define SHIFT_EXTRA() \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.extra = true \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define REDUCE(symbol_val, child_count_val, ...) \
|
||||
{{ \
|
||||
.reduce = { \
|
||||
.type = TSParseActionTypeReduce, \
|
||||
.symbol = symbol_val, \
|
||||
.child_count = child_count_val, \
|
||||
__VA_ARGS__ \
|
||||
}, \
|
||||
}}
|
||||
|
||||
#define RECOVER() \
|
||||
{{ \
|
||||
.type = TSParseActionTypeRecover \
|
||||
}}
|
||||
|
||||
#define ACCEPT_INPUT() \
|
||||
{{ \
|
||||
.type = TSParseActionTypeAccept \
|
||||
}}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_PARSER_H_
|
||||
@ -1,101 +0,0 @@
|
||||
================================================================================
|
||||
Target attribute
|
||||
================================================================================
|
||||
|
||||
@target(erlang)
|
||||
pub fn main() { todo }
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(attribute
|
||||
name: (identifier)
|
||||
arguments: (arguments
|
||||
(attribute_value
|
||||
(identifier))))
|
||||
(function
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
parameters: (function_parameters)
|
||||
body: (block
|
||||
(todo))))
|
||||
|
||||
================================================================================
|
||||
Attribute with multiple values
|
||||
================================================================================
|
||||
|
||||
@deprecated(since: "1.2.0", replacement: wobble)
|
||||
pub fn wibble() { todo }
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(attribute
|
||||
name: (identifier)
|
||||
arguments: (arguments
|
||||
(attribute_value
|
||||
label: (label)
|
||||
value: (string
|
||||
(quoted_content)))
|
||||
(attribute_value
|
||||
label: (label)
|
||||
value: (identifier))))
|
||||
(function
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
parameters: (function_parameters)
|
||||
body: (block
|
||||
(todo))))
|
||||
|
||||
================================================================================
|
||||
Attribute without arguments
|
||||
================================================================================
|
||||
|
||||
@internal
|
||||
pub fn wibble() { todo }
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(attribute
|
||||
name: (identifier))
|
||||
(function
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
parameters: (function_parameters)
|
||||
body: (block
|
||||
(todo))))
|
||||
|
||||
================================================================================
|
||||
Individually deprecated constructors
|
||||
================================================================================
|
||||
|
||||
pub type SomeType {
|
||||
NotDeprecated
|
||||
@deprecated("Please use the NotDeprecated variant")
|
||||
Deprecated(reason: String)
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_definition
|
||||
(visibility_modifier)
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name))
|
||||
(data_constructor
|
||||
(attribute
|
||||
name: (identifier)
|
||||
arguments: (arguments
|
||||
(attribute_value
|
||||
(string
|
||||
(quoted_content)))))
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier))))))))
|
||||
@ -1,255 +0,0 @@
|
||||
================================================================================
|
||||
Case examples
|
||||
================================================================================
|
||||
|
||||
case value {
|
||||
"A" -> True
|
||||
_ -> False
|
||||
}
|
||||
|
||||
case value {}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(string
|
||||
(quoted_content))))
|
||||
(record
|
||||
(constructor_name)))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(discard)))
|
||||
(record
|
||||
(constructor_name)))))
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))))
|
||||
|
||||
================================================================================
|
||||
Case examples
|
||||
================================================================================
|
||||
|
||||
// From https://gleam.run/news/v0.31-keeping-dependencies-explicit/#quality-of-life-improvements
|
||||
pub fn listed(names: List(String), person: Person) -> String {
|
||||
case names {
|
||||
[name, ..names] if name == person.name -> True
|
||||
[_, ..names] -> listed(names, person)
|
||||
[] -> False
|
||||
}
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(comment)
|
||||
(function
|
||||
(visibility_modifier)
|
||||
(identifier)
|
||||
(function_parameters
|
||||
(function_parameter
|
||||
(identifier)
|
||||
(type
|
||||
(type_identifier)
|
||||
(type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
(type_identifier))))))
|
||||
(function_parameter
|
||||
(identifier)
|
||||
(type
|
||||
(type_identifier))))
|
||||
(type
|
||||
(type_identifier))
|
||||
(block
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(list_pattern
|
||||
(identifier)
|
||||
(list_pattern_tail
|
||||
(identifier)))))
|
||||
(case_clause_guard
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(field_access
|
||||
(identifier)
|
||||
(label))))
|
||||
(record
|
||||
(constructor_name)))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(list_pattern
|
||||
(discard)
|
||||
(list_pattern_tail
|
||||
(identifier)))))
|
||||
(function_call
|
||||
(identifier)
|
||||
(arguments
|
||||
(argument
|
||||
(identifier))
|
||||
(argument
|
||||
(identifier)))))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(list_pattern)))
|
||||
(record
|
||||
(constructor_name))))))))
|
||||
|
||||
================================================================================
|
||||
Pattern matching binaries with 'as'
|
||||
================================================================================
|
||||
|
||||
// From https://gleam.run/news/v0.31-keeping-dependencies-explicit/#quality-of-life-improvements
|
||||
case tag {
|
||||
"category " as key <> value
|
||||
| "region " as key <> value
|
||||
| "priority " as key <> value -> {
|
||||
let key = string.trim(key)
|
||||
Ok(Tag(key, value))
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(comment)
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(string
|
||||
(quoted_content))
|
||||
(identifier))
|
||||
(identifier)))
|
||||
(case_clause_pattern
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(string
|
||||
(quoted_content))
|
||||
(identifier))
|
||||
(identifier)))
|
||||
(case_clause_pattern
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(string
|
||||
(quoted_content))
|
||||
(identifier))
|
||||
(identifier))))
|
||||
(block
|
||||
(let
|
||||
(identifier)
|
||||
(function_call
|
||||
(field_access
|
||||
(identifier)
|
||||
(label))
|
||||
(arguments
|
||||
(argument
|
||||
(identifier)))))
|
||||
(record
|
||||
(constructor_name)
|
||||
(arguments
|
||||
(argument
|
||||
(record
|
||||
(constructor_name)
|
||||
(arguments
|
||||
(argument
|
||||
(identifier))
|
||||
(argument
|
||||
(identifier)))))))))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(discard)))
|
||||
(record
|
||||
(constructor_name)
|
||||
(arguments
|
||||
(argument
|
||||
(record
|
||||
(constructor_name)))))))))
|
||||
|
||||
================================================================================
|
||||
Case with boolean negation in a guard
|
||||
================================================================================
|
||||
|
||||
case var {
|
||||
1 if !other_var -> True
|
||||
_ -> False
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(integer)))
|
||||
(case_clause_guard
|
||||
(boolean_negation
|
||||
(identifier)))
|
||||
(record
|
||||
(constructor_name)))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(discard)))
|
||||
(record
|
||||
(constructor_name))))))
|
||||
|
||||
================================================================================
|
||||
Case with int remainder in guard
|
||||
================================================================================
|
||||
|
||||
case var {
|
||||
_ if 11 % 2 == 0 -> True
|
||||
_ -> False
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(discard)))
|
||||
(case_clause_guard
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(integer)
|
||||
(integer))
|
||||
(integer)))
|
||||
(record
|
||||
(constructor_name)))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(discard)))
|
||||
(record
|
||||
(constructor_name))))))
|
||||
@ -1,465 +0,0 @@
|
||||
================================================================================
|
||||
Constants
|
||||
================================================================================
|
||||
|
||||
const a = "hello"
|
||||
const a = "hello\nworld!"
|
||||
const a = 1_234
|
||||
const a = 0b110
|
||||
const a = 0o7224
|
||||
const a = 0xBEef
|
||||
const a: Int = 1234
|
||||
const a: Float = -1_234.53__23
|
||||
const a: Float = 0.
|
||||
const a: #(Int, String) = #(1, "Hello!")
|
||||
const a: #() = #()
|
||||
const a: List(Int) = [1, 2]
|
||||
const a: List(_) = []
|
||||
const a = <<3>>
|
||||
const a = <<0:4, 1:3, 1:1>>
|
||||
const a = <<3:size(8)>>
|
||||
const a = <<52:size(4)-unit(4)>>
|
||||
const a = <<"Hello Gleam 💫":utf8>>
|
||||
const a = Node
|
||||
const a = Node()
|
||||
const a = Cat("Ginny", 1950)
|
||||
const a = Person(name: "Billy", age: 52)
|
||||
const a = uri.Uri(host: "github.com")
|
||||
const a: option.Option(String) = option.Some("Hello, World!")
|
||||
const var_alias = b
|
||||
const int_identity_alias: fn(Int) -> Int = int_identity
|
||||
const fun_tuple: #(fn(Float) -> String, fn(Int) -> String) = #(float.to_string, int.to_string)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (string
|
||||
(quoted_content)))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (string
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content)))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (integer))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (integer))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (integer))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (integer))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))
|
||||
value: (integer))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))
|
||||
value: (float))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))
|
||||
value: (float))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (tuple_type
|
||||
(type
|
||||
name: (type_identifier))
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
value: (tuple
|
||||
(integer)
|
||||
(string
|
||||
(quoted_content))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (tuple_type)
|
||||
value: (tuple))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))))
|
||||
value: (list
|
||||
(integer)
|
||||
(integer)))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type_hole))))
|
||||
value: (list))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (integer))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(integer)))
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(integer)))
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(integer)))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(bit_string_segment_option
|
||||
(integer))))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(bit_string_segment_option
|
||||
(integer))
|
||||
(bit_string_segment_option
|
||||
(integer))))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (string
|
||||
(quoted_content))
|
||||
options: (bit_string_segment_options
|
||||
(bit_string_segment_option)))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (constructor_name)))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (constructor_name)
|
||||
arguments: (arguments)))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (constructor_name)
|
||||
arguments: (arguments
|
||||
(argument
|
||||
value: (string
|
||||
(quoted_content)))
|
||||
(argument
|
||||
value: (integer)))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (constructor_name)
|
||||
arguments: (arguments
|
||||
(argument
|
||||
label: (label)
|
||||
value: (string
|
||||
(quoted_content)))
|
||||
(argument
|
||||
label: (label)
|
||||
value: (integer)))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (remote_constructor_name
|
||||
module: (identifier)
|
||||
name: (constructor_name))
|
||||
arguments: (arguments
|
||||
(argument
|
||||
label: (label)
|
||||
value: (string
|
||||
(quoted_content))))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (remote_type_identifier
|
||||
module: (identifier)
|
||||
name: (type_identifier))
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))))
|
||||
value: (record
|
||||
name: (remote_constructor_name
|
||||
module: (identifier)
|
||||
name: (constructor_name))
|
||||
arguments: (arguments
|
||||
(argument
|
||||
value: (string
|
||||
(quoted_content))))))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (identifier))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (function_type
|
||||
parameter_types: (function_parameter_types
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
return_type: (type
|
||||
name: (type_identifier)))
|
||||
value: (identifier))
|
||||
(constant
|
||||
name: (identifier)
|
||||
type: (tuple_type
|
||||
(function_type
|
||||
parameter_types: (function_parameter_types
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
return_type: (type
|
||||
name: (type_identifier)))
|
||||
(function_type
|
||||
parameter_types: (function_parameter_types
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
return_type: (type
|
||||
name: (type_identifier))))
|
||||
value: (tuple
|
||||
(field_access
|
||||
record: (identifier)
|
||||
field: (label))
|
||||
(field_access
|
||||
record: (identifier)
|
||||
field: (label)))))
|
||||
|
||||
================================================================================
|
||||
Public constants
|
||||
================================================================================
|
||||
|
||||
pub const a = "hello"
|
||||
pub const a: Int = 1234
|
||||
pub const a: Float = -1_234.53__23
|
||||
pub const a: #(Int, String) = #(1, "Hello!")
|
||||
pub const a: #() = #()
|
||||
pub const a: List(Int) = [1, 2]
|
||||
pub const a: List(_) = []
|
||||
pub const a = <<3>>
|
||||
pub const a = <<0:4, 1:3, 1:1>>
|
||||
pub const a = <<3:size(8)>>
|
||||
pub const a = <<52:size(4)-unit(4)>>
|
||||
pub const a = <<"Hello Gleam 💫":utf8>>
|
||||
pub const a = Node
|
||||
pub const a = Node()
|
||||
pub const a = Cat("Ginny", 1950)
|
||||
pub const a = Person(name: "Billy", age: 52)
|
||||
pub const a = uri.Uri(host: "github.com")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (string
|
||||
(quoted_content)))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))
|
||||
value: (integer))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))
|
||||
value: (float))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
type: (tuple_type
|
||||
(type
|
||||
name: (type_identifier))
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
value: (tuple
|
||||
(integer)
|
||||
(string
|
||||
(quoted_content))))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
type: (tuple_type)
|
||||
value: (tuple))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))))
|
||||
value: (list
|
||||
(integer)
|
||||
(integer)))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type_hole))))
|
||||
value: (list))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (integer))))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(integer)))
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(integer)))
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(integer)))))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(bit_string_segment_option
|
||||
(integer))))))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (integer)
|
||||
options: (bit_string_segment_options
|
||||
(bit_string_segment_option
|
||||
(integer))
|
||||
(bit_string_segment_option
|
||||
(integer))))))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (bit_string
|
||||
(bit_string_segment
|
||||
value: (string
|
||||
(quoted_content))
|
||||
options: (bit_string_segment_options
|
||||
(bit_string_segment_option)))))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (constructor_name)))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (constructor_name)
|
||||
arguments: (arguments)))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (constructor_name)
|
||||
arguments: (arguments
|
||||
(argument
|
||||
value: (string
|
||||
(quoted_content)))
|
||||
(argument
|
||||
value: (integer)))))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (constructor_name)
|
||||
arguments: (arguments
|
||||
(argument
|
||||
label: (label)
|
||||
value: (string
|
||||
(quoted_content)))
|
||||
(argument
|
||||
label: (label)
|
||||
value: (integer)))))
|
||||
(constant
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
value: (record
|
||||
name: (remote_constructor_name
|
||||
module: (identifier)
|
||||
name: (constructor_name))
|
||||
arguments: (arguments
|
||||
(argument
|
||||
label: (label)
|
||||
value: (string
|
||||
(quoted_content)))))))
|
||||
|
||||
================================================================================
|
||||
Scientific notation
|
||||
================================================================================
|
||||
|
||||
const a = 0.0e0
|
||||
const a = 1.0e123_456
|
||||
const a = -100.001e-1_230
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(constant
|
||||
(identifier)
|
||||
(float))
|
||||
(constant
|
||||
(identifier)
|
||||
(float))
|
||||
(constant
|
||||
(identifier)
|
||||
(float)))
|
||||
|
||||
================================================================================
|
||||
Constant with shorthand labels
|
||||
================================================================================
|
||||
|
||||
const b = Wibble(arg:, arg:)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(constant
|
||||
(identifier)
|
||||
(record
|
||||
(constructor_name)
|
||||
(arguments
|
||||
(argument
|
||||
(label))
|
||||
(argument
|
||||
(label))))))
|
||||
@ -1,272 +0,0 @@
|
||||
================================================================================
|
||||
Parser example custom types
|
||||
================================================================================
|
||||
|
||||
type A { A }
|
||||
type A { A(String) }
|
||||
type Box(inner_type) { Box(inner: inner_type) }
|
||||
type NamedBox(inner_type) { Box(String, inner: inner_type) }
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name))))
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
value: (type
|
||||
name: (type_identifier)))))))
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type_var))))))
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
value: (type
|
||||
name: (type_identifier)))
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type_var)))))))
|
||||
|
||||
================================================================================
|
||||
Other custom type examples
|
||||
================================================================================
|
||||
|
||||
type Cat {
|
||||
Cat(name: String, cuteness: Int)
|
||||
}
|
||||
|
||||
type Animal() {
|
||||
Cat(name: String, cuteness: Int)
|
||||
Dog(name: String, cuteness: Int)
|
||||
}
|
||||
|
||||
type Result(success_type, failure_type) {
|
||||
Ok(success_type)
|
||||
Error(failure_type)
|
||||
}
|
||||
|
||||
type Ord {
|
||||
LT
|
||||
EQ
|
||||
GT
|
||||
}
|
||||
|
||||
type Boring {
|
||||
Boring
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))))))
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))))
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))))))
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)
|
||||
(type_parameter)))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
value: (type_var))))
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
value: (type_var))))))
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name))
|
||||
(data_constructor
|
||||
name: (constructor_name))
|
||||
(data_constructor
|
||||
name: (constructor_name))))
|
||||
(type_definition
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)))))
|
||||
|
||||
================================================================================
|
||||
Public custom type definitions
|
||||
================================================================================
|
||||
|
||||
pub type Animal(name, cuteness) {
|
||||
Cat(name: String, cuteness: Int)
|
||||
Dog(name: String, cuteness: Int)
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_definition
|
||||
(visibility_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)
|
||||
(type_parameter)))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))))
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier))))))))
|
||||
|
||||
================================================================================
|
||||
Public opaque custom type definitions
|
||||
================================================================================
|
||||
|
||||
pub opaque type Animal(name, cuteness) {
|
||||
Cat(name: String, cuteness: Int)
|
||||
Dog(name: String, cuteness: Int)
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_definition
|
||||
(visibility_modifier)
|
||||
(opacity_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)
|
||||
(type_parameter)))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))))
|
||||
(data_constructor
|
||||
name: (constructor_name)
|
||||
arguments: (data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier)))
|
||||
(data_constructor_argument
|
||||
label: (label)
|
||||
value: (type
|
||||
name: (type_identifier))))))))
|
||||
|
||||
================================================================================
|
||||
Record update with shorthand labels
|
||||
================================================================================
|
||||
|
||||
Wibble(..wibble, arg:, arg:, arg: todo as "no shorthand")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(record_update
|
||||
(constructor_name)
|
||||
(identifier)
|
||||
(record_update_arguments
|
||||
(record_update_argument
|
||||
(label))
|
||||
(record_update_argument
|
||||
(label))
|
||||
(record_update_argument
|
||||
(label)
|
||||
(todo
|
||||
(string
|
||||
(quoted_content)))))))
|
||||
@ -1,78 +0,0 @@
|
||||
================================================================================
|
||||
Case with spread
|
||||
================================================================================
|
||||
|
||||
pub fn main() {
|
||||
case xs {
|
||||
[[]] -> io.println("one")
|
||||
[[], ..] -> io.println("many")
|
||||
}
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(function
|
||||
(visibility_modifier)
|
||||
(identifier)
|
||||
(function_parameters)
|
||||
(block
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(list_pattern
|
||||
(list_pattern))))
|
||||
(function_call
|
||||
(field_access
|
||||
(identifier)
|
||||
(label))
|
||||
(arguments
|
||||
(argument
|
||||
(string
|
||||
(quoted_content))))))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(list_pattern
|
||||
(list_pattern)
|
||||
(list_pattern_tail))))
|
||||
(function_call
|
||||
(field_access
|
||||
(identifier)
|
||||
(label))
|
||||
(arguments
|
||||
(argument
|
||||
(string
|
||||
(quoted_content)))))))))))
|
||||
|
||||
================================================================================
|
||||
Pattern with label shorthand
|
||||
================================================================================
|
||||
|
||||
pub fn main() {
|
||||
let Wibble(arg1:, arg2:) = todo as "a"
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(function
|
||||
(visibility_modifier)
|
||||
(identifier)
|
||||
(function_parameters)
|
||||
(block
|
||||
(let
|
||||
(record_pattern
|
||||
(constructor_name)
|
||||
(record_pattern_arguments
|
||||
(record_pattern_argument
|
||||
(label))
|
||||
(record_pattern_argument
|
||||
(label))))
|
||||
(todo
|
||||
(string
|
||||
(quoted_content)))))))
|
||||
@ -1,112 +0,0 @@
|
||||
================================================================================
|
||||
Echo with expression
|
||||
================================================================================
|
||||
|
||||
pub fn main() {
|
||||
echo 1
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(function
|
||||
(visibility_modifier)
|
||||
(identifier)
|
||||
(function_parameters)
|
||||
(block
|
||||
(echo
|
||||
(integer)))))
|
||||
|
||||
================================================================================
|
||||
Echo in pipeline
|
||||
================================================================================
|
||||
|
||||
pub fn main() {
|
||||
[]
|
||||
|> echo
|
||||
|> panic
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(function
|
||||
(visibility_modifier)
|
||||
(identifier)
|
||||
(function_parameters)
|
||||
(block
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(list)
|
||||
(pipeline_echo))
|
||||
(panic)))))
|
||||
|
||||
================================================================================
|
||||
Echo last in pipeline
|
||||
================================================================================
|
||||
|
||||
pub fn main() {
|
||||
[]
|
||||
|> echo
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(function
|
||||
(visibility_modifier)
|
||||
(identifier)
|
||||
(function_parameters)
|
||||
(block
|
||||
(binary_expression
|
||||
(list)
|
||||
(pipeline_echo))
|
||||
(integer))))
|
||||
|
||||
================================================================================
|
||||
Echo precedence with pipes
|
||||
================================================================================
|
||||
|
||||
pub fn main() {
|
||||
echo 1 |> 2
|
||||
3
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(function
|
||||
(visibility_modifier)
|
||||
(identifier)
|
||||
(function_parameters)
|
||||
(block
|
||||
(echo
|
||||
(binary_expression
|
||||
(integer)
|
||||
(integer)))
|
||||
(integer))))
|
||||
|
||||
================================================================================
|
||||
Echo precedence with binop
|
||||
================================================================================
|
||||
|
||||
pub fn main() {
|
||||
echo 1 + 2
|
||||
3
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(function
|
||||
(visibility_modifier)
|
||||
(identifier)
|
||||
(function_parameters)
|
||||
(block
|
||||
(echo
|
||||
(binary_expression
|
||||
(integer)
|
||||
(integer)))
|
||||
(integer))))
|
||||
@ -1,179 +0,0 @@
|
||||
================================================================================
|
||||
Bit-string expression
|
||||
================================================================================
|
||||
|
||||
<<code:int-size(8)-unit(2), reason:utf8>>
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(bit_string
|
||||
(bit_string_segment
|
||||
(identifier)
|
||||
(bit_string_segment_options
|
||||
(bit_string_segment_option)
|
||||
(bit_string_segment_option
|
||||
(integer))
|
||||
(bit_string_segment_option
|
||||
(integer))))
|
||||
(bit_string_segment
|
||||
(identifier)
|
||||
(bit_string_segment_options
|
||||
(bit_string_segment_option)))))
|
||||
|
||||
================================================================================
|
||||
Boolean Negation
|
||||
================================================================================
|
||||
|
||||
!False
|
||||
True && !False
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(boolean_negation
|
||||
(record
|
||||
(constructor_name)))
|
||||
(binary_expression
|
||||
(record
|
||||
(constructor_name))
|
||||
(boolean_negation
|
||||
(record
|
||||
(constructor_name)))))
|
||||
|
||||
================================================================================
|
||||
Integer Negation
|
||||
================================================================================
|
||||
|
||||
{-x}
|
||||
{-{5*30}}
|
||||
{-my_fun()}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(block
|
||||
(integer_negation
|
||||
(identifier)))
|
||||
(block
|
||||
(integer_negation
|
||||
(block
|
||||
(binary_expression
|
||||
(integer)
|
||||
(integer)))))
|
||||
(block
|
||||
(integer_negation
|
||||
(function_call
|
||||
(identifier)
|
||||
(arguments)))))
|
||||
|
||||
================================================================================
|
||||
Concatenation
|
||||
================================================================================
|
||||
|
||||
let concat = "a" <> "b"
|
||||
|
||||
case "12345" {
|
||||
"0" <> rest -> rest
|
||||
"12" <> "34" <> "5" -> "match"
|
||||
_ -> ""
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(let
|
||||
(identifier)
|
||||
(binary_expression
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))))
|
||||
(case
|
||||
(case_subjects
|
||||
(string
|
||||
(quoted_content)))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(binary_expression
|
||||
(string
|
||||
(quoted_content))
|
||||
(identifier))))
|
||||
(identifier))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))
|
||||
(string
|
||||
(quoted_content)))))
|
||||
(string
|
||||
(quoted_content)))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(discard)))
|
||||
(string)))))
|
||||
|
||||
================================================================================
|
||||
Todo and panic 'as' with string expressions
|
||||
================================================================================
|
||||
|
||||
todo as { "Hello, " <> "world!" }
|
||||
panic as { "Hello, " <> "world!" }
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(todo
|
||||
(block
|
||||
(binary_expression
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))))
|
||||
(panic
|
||||
(block
|
||||
(binary_expression
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))))))
|
||||
|
||||
================================================================================
|
||||
Todo and panic in function application style
|
||||
================================================================================
|
||||
|
||||
todo("don't panic")
|
||||
panic("aaaah!")
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(todo
|
||||
(string
|
||||
(quoted_content)))
|
||||
(panic
|
||||
(string
|
||||
(quoted_content))))
|
||||
|
||||
================================================================================
|
||||
Nested field access
|
||||
================================================================================
|
||||
|
||||
config.connection.host
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(field_access
|
||||
(field_access
|
||||
(identifier)
|
||||
(label))
|
||||
(label)))
|
||||
@ -1,175 +0,0 @@
|
||||
================================================================================
|
||||
External functions
|
||||
================================================================================
|
||||
|
||||
external fn read_file(String) -> Result(String, Reason) =
|
||||
"file" "open"
|
||||
external fn a(name: String) -> String = "x" "y"
|
||||
external fn a() -> #(List(Int), fn(Int) -> String) = "x" "y"
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(external_function
|
||||
name: (identifier)
|
||||
parameters: (function_parameters
|
||||
(function_parameter
|
||||
type: (type
|
||||
name: (type_identifier))))
|
||||
return_type: (type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))))
|
||||
body: (external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))))
|
||||
(external_function
|
||||
name: (identifier)
|
||||
parameters: (function_parameters
|
||||
(function_parameter
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))))
|
||||
return_type: (type
|
||||
name: (type_identifier))
|
||||
body: (external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))))
|
||||
(external_function
|
||||
name: (identifier)
|
||||
parameters: (function_parameters)
|
||||
return_type: (tuple_type
|
||||
(type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))))
|
||||
(function_type
|
||||
parameter_types: (function_parameter_types
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
return_type: (type
|
||||
name: (type_identifier))))
|
||||
body: (external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))))
|
||||
|
||||
================================================================================
|
||||
Public external functions
|
||||
================================================================================
|
||||
|
||||
pub external fn read_file(String) -> Result(String, Reason) =
|
||||
"file" "open"
|
||||
pub external fn a(name: String) -> String = "x" "y"
|
||||
pub external fn a() -> #(List(Int), fn(Int) -> String) = "x" "y"
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(external_function
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
parameters: (function_parameters
|
||||
(function_parameter
|
||||
type: (type
|
||||
name: (type_identifier))))
|
||||
return_type: (type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))))
|
||||
body: (external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))))
|
||||
(external_function
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
parameters: (function_parameters
|
||||
(function_parameter
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))))
|
||||
return_type: (type
|
||||
name: (type_identifier))
|
||||
body: (external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))))
|
||||
(external_function
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
parameters: (function_parameters)
|
||||
return_type: (tuple_type
|
||||
(type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
name: (type_identifier)))))
|
||||
(function_type
|
||||
parameter_types: (function_parameter_types
|
||||
(type
|
||||
name: (type_identifier)))
|
||||
return_type: (type
|
||||
name: (type_identifier))))
|
||||
body: (external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))))
|
||||
|
||||
================================================================================
|
||||
External function with attribute syntax
|
||||
================================================================================
|
||||
|
||||
@external(erlang, "erlang", "integer_to_list")
|
||||
fn integer_to_list(int int: Int, base base: Int) -> String
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(attribute
|
||||
(identifier)
|
||||
(arguments
|
||||
(attribute_value
|
||||
(identifier))
|
||||
(attribute_value
|
||||
(string
|
||||
(quoted_content)))
|
||||
(attribute_value
|
||||
(string
|
||||
(quoted_content)))))
|
||||
(function
|
||||
(identifier)
|
||||
(function_parameters
|
||||
(function_parameter
|
||||
(label)
|
||||
(identifier)
|
||||
(type
|
||||
(type_identifier)))
|
||||
(function_parameter
|
||||
(label)
|
||||
(identifier)
|
||||
(type
|
||||
(type_identifier))))
|
||||
(type
|
||||
(type_identifier))))
|
||||
@ -1,52 +0,0 @@
|
||||
================================================================================
|
||||
External types
|
||||
================================================================================
|
||||
|
||||
type IODevice
|
||||
type IODevice()
|
||||
type Map(key, value)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(external_type
|
||||
(type_name
|
||||
name: (type_identifier)))
|
||||
(external_type
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters)))
|
||||
(external_type
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)
|
||||
(type_parameter)))))
|
||||
|
||||
================================================================================
|
||||
Public external types
|
||||
================================================================================
|
||||
|
||||
pub type IODevice
|
||||
pub type IODevice()
|
||||
pub type Map(key, value)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(external_type
|
||||
(visibility_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)))
|
||||
(external_type
|
||||
(visibility_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters)))
|
||||
(external_type
|
||||
(visibility_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)
|
||||
(type_parameter)))))
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,73 +0,0 @@
|
||||
================================================================================
|
||||
Guard Expressions
|
||||
================================================================================
|
||||
|
||||
case value {
|
||||
n if n + 1 > 10 -> True
|
||||
n if n / 2 < 5 -> False
|
||||
}
|
||||
|
||||
case value {
|
||||
n if n -. 1.0 <. 10.0 -> True
|
||||
n if n *. 2 >. 5 -> False
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(identifier)))
|
||||
(case_clause_guard
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(integer))
|
||||
(integer)))
|
||||
(record
|
||||
(constructor_name)))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(identifier)))
|
||||
(case_clause_guard
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(integer))
|
||||
(integer)))
|
||||
(record
|
||||
(constructor_name)))))
|
||||
(case
|
||||
(case_subjects
|
||||
(identifier))
|
||||
(case_clauses
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(identifier)))
|
||||
(case_clause_guard
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(float))
|
||||
(float)))
|
||||
(record
|
||||
(constructor_name)))
|
||||
(case_clause
|
||||
(case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(identifier)))
|
||||
(case_clause_guard
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(integer))
|
||||
(integer)))
|
||||
(record
|
||||
(constructor_name))))))
|
||||
@ -1,144 +0,0 @@
|
||||
================================================================================
|
||||
Imports
|
||||
================================================================================
|
||||
|
||||
import a
|
||||
import a/b
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(import
|
||||
module: (module))
|
||||
(import
|
||||
module: (module)))
|
||||
|
||||
================================================================================
|
||||
Unqualified imports
|
||||
================================================================================
|
||||
|
||||
import a.{b}
|
||||
import a/b.{c, d}
|
||||
import a/b.{c as d, e}
|
||||
import a/b.{c, D as E}
|
||||
import a/b.{A as B, type C as D}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (identifier))))
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (identifier))
|
||||
(unqualified_import
|
||||
name: (identifier))))
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (identifier)
|
||||
alias: (identifier))
|
||||
(unqualified_import
|
||||
name: (identifier))))
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (identifier))
|
||||
(unqualified_import
|
||||
name: (constructor_name)
|
||||
alias: (constructor_name))))
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (constructor_name)
|
||||
alias: (constructor_name))
|
||||
(unqualified_import
|
||||
name: (type_identifier)
|
||||
alias: (type_identifier)))))
|
||||
|
||||
================================================================================
|
||||
Aliased imports
|
||||
================================================================================
|
||||
|
||||
import a/b.{c as d} as e
|
||||
import animal/cat as kitty
|
||||
import animal.{Cat as Kitty} as a
|
||||
import animal.{type Cat as Kitty} as a
|
||||
import animal.{}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (identifier)
|
||||
alias: (identifier)))
|
||||
alias: (identifier))
|
||||
(import
|
||||
module: (module)
|
||||
alias: (identifier))
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (constructor_name)
|
||||
alias: (constructor_name)))
|
||||
alias: (identifier))
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (type_identifier)
|
||||
alias: (type_identifier)))
|
||||
alias: (identifier))
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports)))
|
||||
|
||||
================================================================================
|
||||
Type imports
|
||||
================================================================================
|
||||
|
||||
import a/b.{type C}
|
||||
import animal.{type Cat as Kitty}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (type_identifier))))
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (type_identifier)
|
||||
alias: (type_identifier)))))
|
||||
|
||||
================================================================================
|
||||
Discard module imports
|
||||
================================================================================
|
||||
|
||||
import wibble.{wobble} as _
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(import
|
||||
(module)
|
||||
(unqualified_imports
|
||||
(unqualified_import
|
||||
(identifier)))
|
||||
(discard)))
|
||||
@ -1,20 +0,0 @@
|
||||
================================================================================
|
||||
Pipes
|
||||
================================================================================
|
||||
|
||||
string
|
||||
|> iodata.new
|
||||
|> iodata.reverse
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(binary_expression
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(field_access
|
||||
(identifier)
|
||||
(label)))
|
||||
(field_access
|
||||
(identifier)
|
||||
(label))))
|
||||
@ -1,59 +0,0 @@
|
||||
================================================================================
|
||||
Use
|
||||
================================================================================
|
||||
|
||||
use <- f()
|
||||
|
||||
use a <- f()
|
||||
|
||||
use a, b, c, d, e <- f()
|
||||
|
||||
use #(a, b) <- blah
|
||||
|
||||
use x : OfType <- f()
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(use
|
||||
(function_call
|
||||
(identifier)
|
||||
(arguments)))
|
||||
(use
|
||||
(use_assignments
|
||||
(use_assignment
|
||||
(identifier)))
|
||||
(function_call
|
||||
(identifier)
|
||||
(arguments)))
|
||||
(use
|
||||
(use_assignments
|
||||
(use_assignment
|
||||
(identifier))
|
||||
(use_assignment
|
||||
(identifier))
|
||||
(use_assignment
|
||||
(identifier))
|
||||
(use_assignment
|
||||
(identifier))
|
||||
(use_assignment
|
||||
(identifier)))
|
||||
(function_call
|
||||
(identifier)
|
||||
(arguments)))
|
||||
(use
|
||||
(use_assignments
|
||||
(use_assignment
|
||||
(tuple_pattern
|
||||
(identifier)
|
||||
(identifier))))
|
||||
(identifier))
|
||||
(use
|
||||
(use_assignments
|
||||
(use_assignment
|
||||
(identifier)
|
||||
(type
|
||||
(type_identifier))))
|
||||
(function_call
|
||||
(identifier)
|
||||
(arguments))))
|
||||
@ -1,38 +0,0 @@
|
||||
================================================================================
|
||||
Escape sequences
|
||||
================================================================================
|
||||
|
||||
"\t\t\r\nHello, CRLF!"
|
||||
"¯\\_(ツ)_/¯"
|
||||
"\"\""
|
||||
"Hello, \e\f"
|
||||
// 🏴☠️ is 🏴 and ☠️ joined with a zero-width joiner (U+200D)
|
||||
"🏴☠️ == \u{1F3F4}\u{200D}\u{2620}\u{FE0F}"
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(string
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(quoted_content))
|
||||
(string
|
||||
(escape_sequence)
|
||||
(escape_sequence))
|
||||
(string
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(escape_sequence))
|
||||
(comment)
|
||||
(string
|
||||
(quoted_content)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(escape_sequence)
|
||||
(escape_sequence)))
|
||||
@ -1,48 +0,0 @@
|
||||
==============
|
||||
Target groups
|
||||
==============
|
||||
|
||||
if erlang {
|
||||
const a = 1
|
||||
}
|
||||
|
||||
if javascript {
|
||||
const a = 1
|
||||
const b = "Hello"
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(target_group
|
||||
target: (target)
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (integer)))
|
||||
(target_group
|
||||
target: (target)
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (integer))
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (string
|
||||
(quoted_content)))))
|
||||
|
||||
========================
|
||||
Target group edge cases
|
||||
========================
|
||||
|
||||
if erlang {}
|
||||
if javascript {const a = 1}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(target_group
|
||||
target: (target))
|
||||
(target_group
|
||||
target: (target)
|
||||
(constant
|
||||
name: (identifier)
|
||||
value: (integer))))
|
||||
@ -1,131 +0,0 @@
|
||||
================================================================================
|
||||
Type aliases
|
||||
================================================================================
|
||||
|
||||
type Headers =
|
||||
List(#(String, String))
|
||||
type Box(a) = #(a)
|
||||
type NamedBox(a) = #(String, a)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(tuple_type
|
||||
(type
|
||||
name: (type_identifier))
|
||||
(type
|
||||
name: (type_identifier)))))))
|
||||
(type_alias
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)))
|
||||
(tuple_type
|
||||
(type_var)))
|
||||
(type_alias
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)))
|
||||
(tuple_type
|
||||
(type
|
||||
name: (type_identifier))
|
||||
(type_var))))
|
||||
|
||||
================================================================================
|
||||
Public type aliases
|
||||
================================================================================
|
||||
|
||||
pub type Headers =
|
||||
List(#(String, String))
|
||||
pub type Box(a) = #(a)
|
||||
pub type NamedBox(a) = #(String, a)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(visibility_modifier)
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(tuple_type
|
||||
(type
|
||||
name: (type_identifier))
|
||||
(type
|
||||
name: (type_identifier)))))))
|
||||
(type_alias
|
||||
(visibility_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)))
|
||||
(tuple_type
|
||||
(type_var)))
|
||||
(type_alias
|
||||
(visibility_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)))
|
||||
(tuple_type
|
||||
(type
|
||||
name: (type_identifier))
|
||||
(type_var))))
|
||||
|
||||
================================================================================
|
||||
Public opaque type aliases
|
||||
================================================================================
|
||||
|
||||
pub opaque type Headers =
|
||||
List(#(String, String))
|
||||
pub opaque type Box(a) = #(a)
|
||||
pub opaque type NamedBox(a) = #(String, a)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(type_alias
|
||||
(visibility_modifier)
|
||||
(opacity_modifier)
|
||||
(type_name
|
||||
name: (type_identifier))
|
||||
(type
|
||||
name: (type_identifier)
|
||||
arguments: (type_arguments
|
||||
(type_argument
|
||||
(tuple_type
|
||||
(type
|
||||
name: (type_identifier))
|
||||
(type
|
||||
name: (type_identifier)))))))
|
||||
(type_alias
|
||||
(visibility_modifier)
|
||||
(opacity_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)))
|
||||
(tuple_type
|
||||
(type_var)))
|
||||
(type_alias
|
||||
(visibility_modifier)
|
||||
(opacity_modifier)
|
||||
(type_name
|
||||
name: (type_identifier)
|
||||
parameters: (type_parameters
|
||||
(type_parameter)))
|
||||
(tuple_type
|
||||
(type
|
||||
name: (type_identifier))
|
||||
(type_var))))
|
||||
@ -1,323 +0,0 @@
|
||||
================================================================================
|
||||
Excerpt from stdlib's base.gleam
|
||||
================================================================================
|
||||
|
||||
import gleam/bit_string
|
||||
import gleam/string
|
||||
|
||||
/// Encodes a BitString into a base 64 encoded string.
|
||||
///
|
||||
pub fn encode64(input: BitString, padding: Bool) -> String {
|
||||
let encoded = do_encode64(input)
|
||||
case padding {
|
||||
True -> encoded
|
||||
False -> string.replace(encoded, "=", "")
|
||||
}
|
||||
}
|
||||
|
||||
if erlang {
|
||||
external fn do_encode64(BitString) -> String =
|
||||
"base64" "encode"
|
||||
}
|
||||
|
||||
if javascript {
|
||||
external fn do_encode64(BitString) -> String =
|
||||
"../gleam_stdlib.mjs" "encode64"
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(import
|
||||
module: (module))
|
||||
(import
|
||||
module: (module))
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(function
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
parameters: (function_parameters
|
||||
(function_parameter
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier)))
|
||||
(function_parameter
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))))
|
||||
return_type: (type
|
||||
name: (type_identifier))
|
||||
body: (block
|
||||
(let
|
||||
pattern: (identifier)
|
||||
value: (function_call
|
||||
function: (identifier)
|
||||
arguments: (arguments
|
||||
(argument
|
||||
value: (identifier)))))
|
||||
(case
|
||||
subjects: (case_subjects
|
||||
(identifier))
|
||||
clauses: (case_clauses
|
||||
(case_clause
|
||||
patterns: (case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(record_pattern
|
||||
name: (constructor_name))))
|
||||
value: (identifier))
|
||||
(case_clause
|
||||
patterns: (case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(record_pattern
|
||||
name: (constructor_name))))
|
||||
value: (function_call
|
||||
function: (field_access
|
||||
record: (identifier)
|
||||
field: (label))
|
||||
arguments: (arguments
|
||||
(argument
|
||||
value: (identifier))
|
||||
(argument
|
||||
value: (string
|
||||
(quoted_content)))
|
||||
(argument
|
||||
value: (string)))))))))
|
||||
(target_group
|
||||
target: (target)
|
||||
(external_function
|
||||
name: (identifier)
|
||||
parameters: (function_parameters
|
||||
(function_parameter
|
||||
type: (type
|
||||
name: (type_identifier))))
|
||||
return_type: (type
|
||||
name: (type_identifier))
|
||||
body: (external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content)))))
|
||||
(target_group
|
||||
target: (target)
|
||||
(external_function
|
||||
name: (identifier)
|
||||
parameters: (function_parameters
|
||||
(function_parameter
|
||||
type: (type
|
||||
name: (type_identifier))))
|
||||
return_type: (type
|
||||
name: (type_identifier))
|
||||
body: (external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))))))
|
||||
|
||||
================================================================================
|
||||
Excerpt from stdlib's bool.gleam
|
||||
================================================================================
|
||||
|
||||
//// A type with two possible values, `True` and `False`. Used to indicate whether
|
||||
//// things are... true or false!
|
||||
////
|
||||
//// Often is it clearer and offers more type safety to define a custom type
|
||||
//// than to use `Bool`. For example, rather than having a `is_teacher: Bool`
|
||||
//// field consider having a `role: SchoolRole` field where `SchoolRole` is a custom
|
||||
//// type that can be either `Student` or `Teacher`.
|
||||
|
||||
import gleam/order.{Order}
|
||||
|
||||
/// Returns the opposite bool value.
|
||||
///
|
||||
/// This is the same as the `!` or `not` operators in some other languages.
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// > negate(True)
|
||||
/// False
|
||||
///
|
||||
/// > negate(False)
|
||||
/// True
|
||||
///
|
||||
pub fn negate(bool: Bool) -> Bool {
|
||||
case bool {
|
||||
True -> False
|
||||
False -> True
|
||||
}
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(module_comment)
|
||||
(module_comment)
|
||||
(module_comment)
|
||||
(module_comment)
|
||||
(module_comment)
|
||||
(module_comment)
|
||||
(module_comment)
|
||||
(import
|
||||
module: (module)
|
||||
imports: (unqualified_imports
|
||||
(unqualified_import
|
||||
name: (constructor_name))))
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(statement_comment)
|
||||
(function
|
||||
(visibility_modifier)
|
||||
name: (identifier)
|
||||
parameters: (function_parameters
|
||||
(function_parameter
|
||||
name: (identifier)
|
||||
type: (type
|
||||
name: (type_identifier))))
|
||||
return_type: (type
|
||||
name: (type_identifier))
|
||||
body: (block
|
||||
(case
|
||||
subjects: (case_subjects
|
||||
(identifier))
|
||||
clauses: (case_clauses
|
||||
(case_clause
|
||||
patterns: (case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(record_pattern
|
||||
name: (constructor_name))))
|
||||
value: (record
|
||||
name: (constructor_name)))
|
||||
(case_clause
|
||||
patterns: (case_clause_patterns
|
||||
(case_clause_pattern
|
||||
(record_pattern
|
||||
name: (constructor_name))))
|
||||
value: (record
|
||||
name: (constructor_name))))))))
|
||||
|
||||
================================================================================
|
||||
Trailing commas
|
||||
================================================================================
|
||||
|
||||
import animal.{Cat,}
|
||||
|
||||
const foo: #(Int,) = #(1,)
|
||||
const bar = [1,]
|
||||
const cat:Cat(String,) = Cat(name: "Nubi",)
|
||||
|
||||
type Thing {
|
||||
First(name: String,)
|
||||
}
|
||||
|
||||
external fn foo(String,) -> String = "foo" "bar"
|
||||
|
||||
fn foo(a,) {
|
||||
myfun(a,)
|
||||
let Cat(name: name,) = Cat(..a, name: "George",)
|
||||
let #(a) = #(a,)
|
||||
let [x,] = [1,]
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(source_file
|
||||
(import
|
||||
(module)
|
||||
(unqualified_imports
|
||||
(unqualified_import
|
||||
(constructor_name))))
|
||||
(constant
|
||||
(identifier)
|
||||
(tuple_type
|
||||
(type
|
||||
(type_identifier)))
|
||||
(tuple
|
||||
(integer)))
|
||||
(constant
|
||||
(identifier)
|
||||
(list
|
||||
(integer)))
|
||||
(constant
|
||||
(identifier)
|
||||
(type
|
||||
(type_identifier)
|
||||
(type_arguments
|
||||
(type_argument
|
||||
(type
|
||||
(type_identifier)))))
|
||||
(record
|
||||
(constructor_name)
|
||||
(arguments
|
||||
(argument
|
||||
(label)
|
||||
(string
|
||||
(quoted_content))))))
|
||||
(type_definition
|
||||
(type_name
|
||||
(type_identifier))
|
||||
(data_constructors
|
||||
(data_constructor
|
||||
(constructor_name)
|
||||
(data_constructor_arguments
|
||||
(data_constructor_argument
|
||||
(label)
|
||||
(type
|
||||
(type_identifier)))))))
|
||||
(external_function
|
||||
(identifier)
|
||||
(function_parameters
|
||||
(function_parameter
|
||||
(type
|
||||
(type_identifier))))
|
||||
(type
|
||||
(type_identifier))
|
||||
(external_function_body
|
||||
(string
|
||||
(quoted_content))
|
||||
(string
|
||||
(quoted_content))))
|
||||
(function
|
||||
(identifier)
|
||||
(function_parameters
|
||||
(function_parameter
|
||||
(identifier)))
|
||||
(block
|
||||
(function_call
|
||||
(identifier)
|
||||
(arguments
|
||||
(argument
|
||||
(identifier))))
|
||||
(let
|
||||
(record_pattern
|
||||
(constructor_name)
|
||||
(record_pattern_arguments
|
||||
(record_pattern_argument
|
||||
(label)
|
||||
(identifier))))
|
||||
(record_update
|
||||
(constructor_name)
|
||||
(identifier)
|
||||
(record_update_arguments
|
||||
(record_update_argument
|
||||
(label)
|
||||
(string
|
||||
(quoted_content))))))
|
||||
(let
|
||||
(tuple_pattern
|
||||
(identifier))
|
||||
(tuple
|
||||
(identifier)))
|
||||
(let
|
||||
(list_pattern
|
||||
(identifier))
|
||||
(list
|
||||
(integer))))))
|
||||
@ -1,25 +0,0 @@
|
||||
<<3>>
|
||||
// <- punctuation.bracket
|
||||
//^ number
|
||||
// ^ punctuation.bracket
|
||||
<<3:8>>
|
||||
//^ number
|
||||
// ^ punctuation.delimiter
|
||||
// ^ number
|
||||
<<3:size(8)>>
|
||||
//^ number
|
||||
// ^ punctuation.delimiter
|
||||
// ^ function.builtin
|
||||
// ^ punctuation.bracket
|
||||
// ^ number
|
||||
// ^ punctuation.bracket
|
||||
<<code:int-size(8)-unit(2), reason:utf8>>
|
||||
// ^ variable
|
||||
// ^ function.builtin
|
||||
// ^ punctuation.delimiter
|
||||
// ^ function.builtin
|
||||
// ^ number
|
||||
// ^ function.builtin
|
||||
// ^ number
|
||||
// ^ variable
|
||||
// ^ function.builtin
|
||||
@ -1,11 +0,0 @@
|
||||
pub fn case_with_remainder() {
|
||||
case todo {
|
||||
_ if 1 % 2 == 0 -> todo
|
||||
// ^ number
|
||||
// ^ operator
|
||||
// ^ number
|
||||
// ^ operator
|
||||
// ^ number
|
||||
_ -> todo
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
const f = 100.001e523
|
||||
// ^ number
|
||||
// ^ number
|
||||
// ^ number
|
||||
|
||||
const s = "Hello, \e\t\n"
|
||||
// ^ warning
|
||||
// ^ warning
|
||||
// ^ string.escape
|
||||
// ^ string.escape
|
||||
@ -1,32 +0,0 @@
|
||||
fn case_case(x: Option(String)) {
|
||||
// ^ variable.parameter
|
||||
// ^ type
|
||||
case #(x, x) {
|
||||
// ^ variable.parameter
|
||||
// ^ variable.parameter
|
||||
#(None, None) -> None
|
||||
// ^ constructor
|
||||
// ^ constructor
|
||||
// ^ constructor
|
||||
#(Some(y), Some(z)) -> #(y, z)
|
||||
// ^ constructor
|
||||
// ^ variable
|
||||
// ^ constructor
|
||||
// ^ variable
|
||||
// ^ variable
|
||||
// ^ variable
|
||||
}
|
||||
|
||||
// this is bound above but no longer in scope,
|
||||
// so it should be interpereted as a module
|
||||
z.foo()
|
||||
// <- module
|
||||
}
|
||||
|
||||
fn shorthand_label_pattern_arg() {
|
||||
case todo {
|
||||
Wibble(arg1:, arg2:) -> todo
|
||||
// ^ property
|
||||
// ^ property
|
||||
}
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
pub fn main() {
|
||||
echo 2
|
||||
// ^ keyword
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
case "12345" {
|
||||
"123" <> rest -> rest
|
||||
// <- string
|
||||
// ^ operator
|
||||
// ^ variable
|
||||
_ -> ""
|
||||
// ^ string
|
||||
}
|
||||
|
||||
-x
|
||||
// ^ operator
|
||||
// ^ variable
|
||||
panic as "aaah!"
|
||||
// <- keyword
|
||||
// ^ keyword
|
||||
// ^ string
|
||||
@ -1,129 +0,0 @@
|
||||
pub fn replace(
|
||||
// <- keyword
|
||||
// <- keyword
|
||||
// ^ function
|
||||
// ^ punctuation.bracket
|
||||
in original: String,
|
||||
// <- property
|
||||
// ^ variable.parameter
|
||||
// ^ type
|
||||
// ^ punctuation.delimiter
|
||||
each pattern: String,
|
||||
// <- property
|
||||
// ^ variable.parameter
|
||||
// ^ type
|
||||
// ^ punctuation.delimiter
|
||||
with replacement: String,
|
||||
// <- property
|
||||
// ^ variable.parameter
|
||||
// ^ type
|
||||
// ^ punctuation.delimiter
|
||||
) -> String {
|
||||
// <- punctuation.delimiter
|
||||
// ^ type
|
||||
// ^ punctuation.bracket
|
||||
string.replace(in: original, each: pattern, with: replacement)
|
||||
// <- module
|
||||
// ^ function
|
||||
// ^ property
|
||||
// ^ variable.parameter
|
||||
// ^ property
|
||||
// ^ variable.parameter
|
||||
// ^ property
|
||||
// ^ variable.parameter
|
||||
original
|
||||
// ^ variable.parameter
|
||||
|> string.replace(pattern, replacement)
|
||||
// <- operator
|
||||
// ^ module
|
||||
// ^ function
|
||||
// ^ variable.parameter
|
||||
// ^ variable.parameter
|
||||
}
|
||||
|
||||
fn record_with_fun_field(record) {
|
||||
let foo = Bar(baz: fn(x) { x + 1 })
|
||||
// ^ constructor
|
||||
foo.baz(41)
|
||||
// <- variable
|
||||
// ^ property
|
||||
record.foobar("hello")
|
||||
// ^ variable.parameter
|
||||
// ^ property
|
||||
string.replace("hello", "l", "o")
|
||||
// ^ module
|
||||
// ^ function
|
||||
}
|
||||
|
||||
fn trial(uri) {
|
||||
// ^ variable.parameter
|
||||
case uri {
|
||||
// ^ variable.parameter
|
||||
Uri(scheme: None) -> True
|
||||
// <- constructor
|
||||
// ^ property
|
||||
// ^ constructor
|
||||
// ^ constructor
|
||||
_ -> False
|
||||
// <- comment.unused
|
||||
}
|
||||
}
|
||||
|
||||
fn my_uri_to_string(my_uri) -> String {
|
||||
uri.to_string(my_uri)
|
||||
// <- module
|
||||
// ^ function
|
||||
// ^ variable.parameter
|
||||
}
|
||||
|
||||
fn myfun(argument) {
|
||||
let local_fun = fn(x) { x + 1 }
|
||||
// ^ variable
|
||||
// ^ variable.parameter
|
||||
// ^ variable.parameter
|
||||
|
||||
argument
|
||||
// ^ variable.parameter
|
||||
|> local_fun
|
||||
// <- operator
|
||||
// ^ variable
|
||||
|> module_fun
|
||||
// ^ function
|
||||
|
||||
module_fun(local_fun(argument))
|
||||
// ^ function
|
||||
// ^ variable
|
||||
// ^ variable.parameter
|
||||
}
|
||||
|
||||
fn negate(arg) {
|
||||
!arg
|
||||
// <- operator
|
||||
// ^ variable.parameter
|
||||
}
|
||||
|
||||
fn comment_string_test() {
|
||||
io.println("// hello world!")
|
||||
// <- module
|
||||
// ^ function
|
||||
// ^ string
|
||||
}
|
||||
|
||||
fn let_assert_test() {
|
||||
let assert #(x, _) = #(1, 2)
|
||||
// <- keyword
|
||||
// ^ keyword
|
||||
}
|
||||
|
||||
fn assert_test() {
|
||||
assert x == add(1, 4)
|
||||
// <- keyword
|
||||
// ^ function
|
||||
}
|
||||
|
||||
fn punned_call_arg_test() {
|
||||
wibble(arg:, arg2:)
|
||||
// ^ function
|
||||
// ^ property
|
||||
// ^ property
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
import gleam/io
|
||||
// ^ module
|
||||
// ^ module
|
||||
// ^ module
|
||||
import animal/cat as kitty
|
||||
// ^ module
|
||||
// ^ module
|
||||
|
||||
import animal/cat.{Cat, type Cat}
|
||||
// ^ constructor
|
||||
// ^ keyword
|
||||
// ^ type
|
||||
|
||||
import wibble.{wobble} as _
|
||||
// ^ module
|
||||
// ^ function
|
||||
// ^ comment.unused
|
||||
|
||||
pub fn main() {
|
||||
io.println("hello world")
|
||||
// <- module
|
||||
}
|
||||
|
||||
type MyType {
|
||||
MyType(func: fn() -> Int)
|
||||
}
|
||||
|
||||
fn record_access_case(param: MyType) {
|
||||
let binding = MyType(func: fn() { 42 })
|
||||
let _ = binding.func()
|
||||
// ^ comment.unused
|
||||
// ^ variable
|
||||
let _ = param.func()
|
||||
// ^ comment.unused
|
||||
// ^ variable.parameter
|
||||
}
|
||||
|
||||
fn pipe_operator_case(string: String) {
|
||||
string
|
||||
// <- variable.parameter
|
||||
|> iodata.new
|
||||
// ^ module
|
||||
|> iodata.reverse
|
||||
// ^ module
|
||||
}
|
||||
|
||||
fn remote_type_case() {
|
||||
gleam.Ok(1)
|
||||
// <- module
|
||||
// ^ punctuation.delimiter
|
||||
// ^ constructor
|
||||
}
|
||||
|
||||
fn make_cat() -> kitty.Cat {
|
||||
// ^ module
|
||||
// ^ type
|
||||
kitty.Cat(name: "Nubi")
|
||||
// ^ module
|
||||
// ^ constructor
|
||||
}
|
||||
|
||||
@target(erlang)
|
||||
// <- attribute
|
||||
// ^ attribute
|
||||
// ^ constant
|
||||
pub external fn display() -> Bool = "erlang" "display"
|
||||
|
||||
@target(erlang)
|
||||
@external(erlang, "wobble", "main")
|
||||
// <- attribute
|
||||
// ^ attribute
|
||||
// ^ constant
|
||||
// ^ string
|
||||
// string
|
||||
pub fn main() -> Int
|
||||
|
||||
@deprecated(since: "1.2.0", replacement: wobble)
|
||||
// <- attribute
|
||||
// ^ attribute
|
||||
// ^ property
|
||||
// ^ string
|
||||
// ^ property
|
||||
// ^constant
|
||||
pub fn wibble() { todo }
|
||||
@ -1,28 +0,0 @@
|
||||
pub type User {
|
||||
// ^ type
|
||||
User(name: String)
|
||||
// <- constructor
|
||||
// ^ property
|
||||
// ^ type
|
||||
}
|
||||
|
||||
pub fn new(name: String) {
|
||||
// ^ variable.parameter
|
||||
User(name: name)
|
||||
// ^ property
|
||||
// ^ variable.parameter
|
||||
}
|
||||
|
||||
pub fn access() {
|
||||
let config = Config()
|
||||
config.connection.host
|
||||
// ^ variable
|
||||
// ^ property
|
||||
// ^ property
|
||||
}
|
||||
|
||||
pub fn record_update_shorthand_label() {
|
||||
User(..user, name:)
|
||||
// ^ constructor
|
||||
// ^ property
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
auto
|
||||
// <- error
|
||||
delegate
|
||||
// <- error
|
||||
derive
|
||||
// <- error
|
||||
else
|
||||
// <- error
|
||||
implement
|
||||
// <- error
|
||||
macro
|
||||
// <- error
|
||||
test
|
||||
// <- error
|
||||
@ -1,2 +0,0 @@
|
||||
*
|
||||
!.gitignore
|
||||
@ -1,75 +0,0 @@
|
||||
import gleam/option.{type Option, Some, None}
|
||||
// ^ reference.module
|
||||
// ^ reference.type
|
||||
// ^ reference.constructor
|
||||
// ^ reference.constructor
|
||||
import gleam/bit_builder
|
||||
// ^ reference.module
|
||||
|
||||
pub type FrameData {
|
||||
// ^ definition.type
|
||||
Text(String)
|
||||
// <- definition.constructor
|
||||
// ^ reference.type
|
||||
Binary(BitString)
|
||||
Continuation(BitString)
|
||||
Ping(BitString)
|
||||
Pong(BitString)
|
||||
Close(code: Option(Int), reason: Option(String))
|
||||
// <- definition.constructor
|
||||
// ^ reference.type
|
||||
// ^ reference.type
|
||||
// ^ reference.type
|
||||
// ^ reference.type
|
||||
}
|
||||
|
||||
pub type Frame {
|
||||
// ^ definition.type
|
||||
Frame(reserved: BitString, mask: Option(BitString), data: FrameData, fin: Bool)
|
||||
}
|
||||
|
||||
fn encode_frame(frame: Frame) -> bit_builder.BitBuilder {
|
||||
// ^ definition.function
|
||||
// ^ reference.type
|
||||
// ^ reference.module
|
||||
// ^ reference.type
|
||||
let fin =
|
||||
case frame.fin {
|
||||
True -> <<1:size(1)>>
|
||||
False -> <<0:size(1)>>
|
||||
}
|
||||
|
||||
let opcode =
|
||||
case frame.data {
|
||||
Continuation(_) -> <<0x0:size(1)>>
|
||||
// <- reference.constructor
|
||||
Text(_) -> <<0x1:size(1)>>
|
||||
Binary(_) -> <<0x2:size(1)>>
|
||||
// 0x3-7 reserved for future non-control frames
|
||||
Close(..) -> <<0x8:size(1)>>
|
||||
Pong(_) -> <<0x9:size(1)>>
|
||||
Pong(_) -> <<0xA:size(1)>>
|
||||
}
|
||||
|
||||
let is_masked_bit =
|
||||
case frame.mask {
|
||||
Some(_) -> <<1:size(1)>>
|
||||
None -> <<0:size(1)>>
|
||||
}
|
||||
|
||||
bit_builder.new()
|
||||
// <- reference.module
|
||||
// ^ reference.function
|
||||
|> bit_builder.append(fin)
|
||||
// ^ reference.function
|
||||
|> bit_builder.append(frame.reserved)
|
||||
|> bit_builder.append(opcode)
|
||||
|> bit_builder.append(is_masked_bit)
|
||||
|> bit_builder.append(option.unwrap(frame.mask, <<>>))
|
||||
// ^ reference.module
|
||||
// ^ reference.module
|
||||
// ^ reference.function
|
||||
|> bit_builder.append(mask_data(frame))
|
||||
// ^ reference.function
|
||||
}
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
fn record_with_fun_field(record) {
|
||||
let foo = Bar(baz: fn(x) { x + 1 })
|
||||
// ^ reference.constructor
|
||||
foo.baz(41)
|
||||
record.foobar("hello")
|
||||
|
||||
string.replace("hello", "l", "o")
|
||||
// ^ reference.module
|
||||
// ^ reference.function
|
||||
}
|
||||
Loading…
Reference in New Issue