This makes me a little uneasy, as the way that the Gleam parser parses
"let assert" is that it first parses "let", then calls
"parse_assignment" which will look to see if an "assert" comes next,
and uses this information to choose the node type.
I think a closer tree-sitter implementation would look like this:
_statement: ($) => choice($._expression, $._assignment, $.use),
...
_assignment: ($) => choice($.let, $.let_assert),
let: ($) => seq("let", $._assignment2),
let_assert: ($) => seq("let", "assert", $._assignment2)
_assignment2: ($) =>
...
However this requires an awkward "_assignment2" and isn't
substantially closer to the Gleam parser to warrant the change.
Also we could simply do `optional("assert")`, but that would make
"let" and "let assert" the same node type, which I suspect is an anti-feature.
With the latest changes to the gleam parser, code that uses let/use as
expressions is now rejected. This change reorganizes let and use under
a new '_statement' rule. This restricts let/use from taking other
let/use statements since they only accept expressions.
floats may have a trailing dot with no trailing digits, like in
the float stdlib module:
pub fn absolute_value(x: Float) -> Float {
case x >=. 0. {
True -> x
_ -> 0. -. x
}
}
Nodes defined in `extras` can be expected before an node. Thus, `comment` could be expected before `escape_sequence` or `quoted_content`; aka inside of a string. Naturally, this makes no sense.
I tried wrapping `escape_sequence` and `quoted_content` in `token.immediate` to resolve the issue, but it had no effect (maybe is specific to whitespace?). Instead, I found success in largely copying [`tree-sitter-rust`'s solution of using an external scanner for string content](9a6d980afb/src/scanner.c (L27-L40)).
* parse top-level expressions
This change allows the parser to return valid nodes for expressions
on the "top-level" of a document.
Here "top-level" is read as "not within a function." This is actually
invalid Gleam code: for example, you cannot write a `case/2` statement
outside of a function body. This is desirable for the tree-sitter
parser, though, because the parser will end up being used in flexible
situations, such as one-off highlights in fenced markdown blocks, e.g.:
```gleam
<<code:int-size(8)-unit(2), reason:utf8>>
```
Which is a common usage in an editor, or on GitHub.
* remove test cases for invalid syntax
closes#17
This refactor brings this grammar more in line with tree-sitter-rust.
A function or type declaration may have a visibility modifier ("pub") and
type declarations may also have an opacity modifier ("opaque"). This ends
up reducing the number of named rules, which cleans up the queries a bit.
* make locals.scm queries more granular
* split out (label) nodes from (identifier)
* run formatter
* use (label) for labeled params nodes
* capture all (label)s as properties
* add CI and 'generate parser' actions workflows
* ignore debug log.html file and wasm files
* mark src/ and bindings/ as generated
* run formatter
* rename CI workflow to 'Test'
* use linguist-vendored rather than linguist-generated
* use raw 'git' commands instead of action
Highlights:
- Give "_upname" the visible name "type_identifier". Name stolen
shamelessly from tree-sitter-rust.
- Remove "record_name" in favor of "type_identifier".
- Remote "function_name" in favor of "identifier".
- Surface names for several nodes, mostly using "type_identifier".
- Remove "remote_" variants of several nodes. Essentially we needed to
give these nodes "names" anyhow, and having the name encapsulate the
local vs remote information proved wildly efficient.
In a previous commit, I removed several encapsulating nodes such as
"parameters" or "arguments" where they were not absolutely necessary.
While reviewing tree-sitter-rust, I noticed that they always
incorporated these encapsulating nodes. This likely helps with AST-based
code navigation, and so I introduced or re-introduced them here.