I'm building an Emacs major mode (fsharp-ts-mode) using this grammar and ran into two related issues with script files.
Shebang lines
A standard .fsx shebang produces an ERROR node and poisons the rest of the parse:
#!/usr/bin/env dotnet fsi
let x = 1
Parses as:
(file (ERROR) (application_expression ...) (ERROR (function_or_value_defn ...)))
Most tree-sitter grammars for scripting languages handle shebangs natively (e.g., tree-sitter-python, tree-sitter-bash). Would it be possible to add shebang support to the file rule?
I currently work around this by excluding the first line from the parser's range when it starts with #!.
Bare expressions between declarations
Mixing let bindings with bare expressions (common in .fsx scripts) causes the grammar to chain subsequent declarations under application_expression or produce ERROR nodes:
let x = 1
printfn "%d" x
let y = 2
Parses as:
(file
(declaration_expression (function_or_value_defn ...)) ;; let x = 1
(application_expression ...) ;; printfn "%d" x
(ERROR (function_or_value_defn ...))) ;; let y = 2 ← ERROR
The let y = 2 ends up inside an ERROR because the grammar doesn't expect a declaration_expression after a bare application_expression at the top level. With more bare expressions the nesting gets deeper:
let x = 1
printfn "%d" x
let y = 2
printfn "%d" y
let z = 3
Here let y nests under application_expression and let z nests two levels deep. Using do printfn ... instead works correctly, but most F# scripts don't use do for bare expressions.
Could the file rule be extended to accept application_expression (or a more general expression) as a top-level alternative alongside declaration_expression? Something like how F# Interactive accepts both declarations and expressions at the top level.
I currently work around this by detecting declarations whose ancestor chain leads back to file through application_expression/ERROR nodes and forcing them to column 0, but it's fragile.
I'm building an Emacs major mode (fsharp-ts-mode) using this grammar and ran into two related issues with script files.
Shebang lines
A standard .fsx shebang produces an ERROR node and poisons the rest of the parse:
Parses as:
Most tree-sitter grammars for scripting languages handle shebangs natively (e.g., tree-sitter-python, tree-sitter-bash). Would it be possible to add shebang support to the
filerule?I currently work around this by excluding the first line from the parser's range when it starts with
#!.Bare expressions between declarations
Mixing
letbindings with bare expressions (common in .fsx scripts) causes the grammar to chain subsequent declarations underapplication_expressionor produce ERROR nodes:Parses as:
The
let y = 2ends up inside an ERROR because the grammar doesn't expect adeclaration_expressionafter a bareapplication_expressionat the top level. With more bare expressions the nesting gets deeper:Here
let ynests underapplication_expressionandlet znests two levels deep. Usingdo printfn ...instead works correctly, but most F# scripts don't usedofor bare expressions.Could the
filerule be extended to acceptapplication_expression(or a more general expression) as a top-level alternative alongsidedeclaration_expression? Something like how F# Interactive accepts both declarations and expressions at the top level.I currently work around this by detecting declarations whose ancestor chain leads back to
filethroughapplication_expression/ERRORnodes and forcing them to column 0, but it's fragile.