Skip to content

Parse anonymous function with no clauses #78

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,26 @@ Resolving some of these conflicts (for instance special keywords like `{}` or `%
requires the use of external scanner. Given the complexities this approach
brings to the grammar, and consequently the parser, we stick to the simpler
approach.

### Ref 8. Empty anonymous function

As opposed to the Elixir parser, we successfully parse anonymous functions with
no stab clauses, so this is valid:

```
x = fn

end
```

This code may appear if an editor extension automatically inserts `end` after
`fn`. We want it to parse as anonymous function node, so that functionality such
as indentation works as expected.

If we require at least one stab clause, the above would be parsed with an error,
where `fn` and `end` are both identifiers. That is not useful. Note that both
`fn` and `end` are reserved keywords, so there is no case where they would
actually be identifiers, hence no ambiguity.

Ideally, this would parse it as an anonymous function node with an error, however
that does not seem straightforward to achieve.
3 changes: 2 additions & 1 deletion grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,8 @@ module.exports = grammar({
seq(
"fn",
optional($._terminator),
sep1($.stab_clause, $._terminator),
// See Ref 8. in the docs
optional(sep1($.stab_clause, $._terminator)),
"end"
),

Expand Down
15 changes: 15 additions & 0 deletions test/corpus/expression/anonymous_function.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,21 @@ end
(body
(atom)))))

=====================================
no clauses
=====================================

fn
end

fn end

---

(source
(anonymous_function)
(anonymous_function))

=====================================
with guard / no arguments
=====================================
Expand Down
Loading