#haskell #parser #incremental

npezza93-tree-sitter-haskell

tree-sitter 解析库的 Haskell 语法

2 个不稳定版本

0.15.1 2024年4月18日
0.14.1 2023年9月29日

84 / 文本编辑器

MIT 许可证

25MB
1M SLoC

C 1M SLoC // 0.0% comments JavaScript 163 SLoC // 0.4% comments Scheme 101 SLoC // 0.2% comments Rust 36 SLoC // 0.3% comments

tree-sitter-haskell

CI discord matrix crates npm

tree-sitter 的 Haskell 语法

参考资料

使用 nvim-treesitter 构建

从源代码安装语法时,请确保包含扫描器在内的源文件

lua <<EOF
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
parser_config.haskell = {
  install_info = {
    url = "~/path/to/tree-sitter-haskell",
    files = {"src/parser.c", "src/scanner.c", "src/unicode.h"}
  }
}
EOF

支持的语言扩展

这些扩展是支持的 ✅,不支持的 ❌ 或不适用,因为它们不涉及解析 ➖️

  • AllowAmbiguousTypes ➖️
  • ApplicativeDo ➖️
  • Arrows ❌
  • BangPatterns ✅
  • BinaryLiterals ✅
  • BlockArguments ✅
  • CApiFFI ✅
  • ConstrainedClassMethods ✅
  • ConstraintKinds ✅
  • CPP ✅
  • CUSKs ✅
  • DataKinds ✅
  • DatatypeContexts ✅
  • DefaultSignatures ✅
  • DeriveAnyClass ➖️
  • DeriveDataTypeable ➖️
  • DeriveFoldable ➖️
  • DeriveFunctor ➖️
  • DeriveGeneric ➖️
  • DeriveLift ➖️
  • DeriveTraversable ➖️
  • DerivingStrategies ✅
  • DerivingVia ✅
  • DisambiguateRecordFields ➖️
  • DuplicateRecordFields ➖️
  • EmptyCase ✅
  • EmptyDataDecls ✅
  • EmptyDataDeriving ✅
  • ExistentialQuantification ✅
  • ExplicitForAll ✅
  • ExplicitNamespaces ✅
  • ExtendedDefaultRules ➖️
  • FlexibleContexts ✅
  • FlexibleInstances ✅
  • ForeignFunctionInterface ✅
  • FunctionalDependencies ✅
  • GADTs ✅
  • GADTSyntax ✅
  • GeneralisedNewtypeDeriving ➖️
  • GHCForeignImportPrim ✅
  • Haskell2010 ➖️
  • Haskell98 ➖️
  • HexFloatLiterals ✅
  • ImplicitParams ✅
  • ImplicitPrelude ➖️
  • ImportQualifiedPost ✅
  • ImpredicativeTypes ➖️
  • IncoherentInstances ➖️
  • InstanceSigs ✅
  • InterruptibleFFI ✅
  • KindSignatures ✅
  • LambdaCase ✅
  • LexicalNegation ❌
  • LiberalTypeSynonyms ✅
  • LinearTypes ✅
  • MagicHash ✅
  • Modifiers ❌
  • MonadComprehensions ➖️
  • MonadFailDesugaring ➖️
  • MonoLocalBinds ➖️
  • MonomorphismRestriction ➖️
  • MultiParamTypeClasses ✅
  • MultiWayIf ✅
  • 命名字段双关语 ✅
  • 命名通配符 ✅
  • 负数文字 ➖️
  • 非递增缩进 ❌
  • N+K模式 ➖️
  • 空值类型类 ✅
  • 小数位数 ➖️
  • 数字下划线 ✅
  • 重叠实例 ➖️
  • 重载标签 ✅
  • 重载列表 ➖️
  • 重载记录点 ✅
  • 重载记录更新 ✅
  • 重载字符串 ➖️
  • 包导入 ✅
  • 并行列表推导 ✅
  • 部分类型签名 ✅
  • 模式守卫 ✅
  • 模式同义词 ✅
  • 多态类型类 ➖️
  • 后缀运算符 ➖️
  • 限定do ✅
  • 量化约束 ✅
  • 准引号 ✅
  • 秩2类型 ✅
  • 秩N类型 ✅
  • 可重新绑定语法 ➖️
  • 记录通配符 ➖️
  • 递归do ✅
  • 角色注解 ✅
  • 安全 ➖️
  • 作用域类型变量 ✅
  • 独立推导 ✅
  • 独立类型签名 ✅
  • 星号是类型 ✅
  • 静态指针 ❌
  • 严格 ➖️
  • 严格数据 ✅
  • 模板Haskell ✅
  • 模板Haskell引号 ✅
  • 传统记录语法 ➖️
  • 转换列表推导 ✅
  • 可信 ➖️
  • 元组部分 ✅
  • 类型应用 ✅
  • 类型数据 ✅
  • 类型族 ✅
  • 类型族依赖 ✅
  • 类型在类型中 ✅
  • 类型运算符 ✅
  • 类型同义词实例 ➖️
  • 无包装求和 ✅
  • 无包装元组 ✅
  • 不可判定实例 ➖️
  • 不可判定超类 ➖️
  • Unicode语法 ✅
  • 非提升FFI类型 ➖️
  • 非提升新类型 ✅
  • 不安全 ➖️
  • 视图模式 ✅

错误

CPP

预处理 #elif#else 指令无法正确处理,因为解析器的状态需要手动重置到 #if 的状态。作为 workaround,备选分支中的代码块被解析为指令的一部分。

布局

NondecreasingIndentation 不受支持(尚未)。

do 中换行符上的运算符

一个奇怪的边缘情况是,当一个中缀运算符紧跟在具有与 do 布局列相同的或更少缩进的 do 块的表达式语句之后时

f = do
  readSomething
  >>= doSomething

>>= 会终止 do 的布局,导致类似于以下 AST 的 AST

f = (do readSomething) >>= doSomething

这是通过启发式方法检查的,可能不可靠。

测试

需要: tree-sitter(-cli)

运行测试语料库

这些存储在 ./tests/corpus/

$ tree-sitter test

测试解析示例代码库

需要: bc 这将打印解析代码库的百分比和所花费的时间

$ ./script/parse-examples             # this clones all repos
$ ./script/parse-example <example>    # where <example> is a project under ./examples/

启用扫描器调试输出

要获得一个额外的详细、未优化的扫描器,带有调试符号,请取消注释以下代码

$ CFLAGS='-DDEBUG' make debug.so
$ cp debug.so $HOME/.cache/tree-sitter/lib/haskell.so    # So `tree-sitter-cli` uses our binary
$ tree-sitter test
$ ./script/parse-example <example>

如果您想使用 gdb 调试扫描器,可以在 tree--sitter test 时使用 b tree_sitter_haskell_external_scanner_scan

创建解析步骤的可视图

需要: graphviz

$ tree-sitter parse -D test/Basic.hs    # Produces log.html

依赖关系

~2.8–4MB
~72K SLoC