tree-sitter 的 grammar.js 编写方法

news2025/4/13 3:20:20

tree-sitter 的 grammar.js 编写方法

    • 一、`grammar.js` 的作用是什么?
    • 二、基本结构
    • 三、关键词解释
    • 四、编写小技巧
      • 1. 起点是 `source_file`
      • 2. 所有规则名(如 `identifier`, `number`)都是 `$ => ...`
      • 3. 正则表达式用于定义词法规则(终结符),例如:
    • 五、🍀 `$`的简单解释:`$` 是规则的“引用工具”
      • ❓ 那 `$` 到底能干嘛?
      • 🧠 举个例子来说明
    • 🔧 类比一下:

要掌握 tree-sittergrammar.js 编写方法,首先我们要理解 tree-sitter 的核心概念,它是一个 基于GLR算法的增量解析器生成工具,常用于语法高亮、代码分析等任务。

一、grammar.js 的作用是什么?

这是 tree-sitter 语法的定义文件,描述了一个语言的 词法规则(Lexing)语法规则(Parsing)


二、基本结构

grammar.js 是一个 CommonJS 模块,通常长这样:

module.exports = grammar({
  name: 'my_language', // 语言名称

  // 词法规则
  extras: $ => [/\s/, $.comment], // 忽略的内容,如空格、注释

  // 定义词法(token)
  rules: {
    source_file: $ => repeat($.statement),

    statement: $ => choice(
      $.variable_declaration,
      $.function_call
    ),

    variable_declaration: $ => seq(
      'let',
      $.identifier,
      '=',
      $.expression,
      ';'
    ),

    function_call: $ => seq(
      $.identifier,
      '(',
      optional($.expression),
      ')',
      ';'
    ),

    expression: $ => choice(
      $.number,
      $.string,
      $.identifier
    ),

    identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/,
    number: $ => /\d+/,
    string: $ => /"[^"]*"/,
    comment: $ => /\/\/.*/
  }
});

三、关键词解释

  • seq(...): 顺序匹配(sequence),表示一段连续的符号。
  • choice(...): 匹配多个可能之一(like OR)。
  • repeat(...): 重复0次或多次。
  • repeat1(...): 重复至少1次。
  • optional(...): 可选项。
  • token(...): 表示这是一个词法单元(token),不会再细分。
  • prec(n, rule): 设置优先级(n 越大,优先级越高)。

四、编写小技巧

1. 起点是 source_file

tree-sitter 会从你定义的 rules.source_file 开始解析整个文件。

2. 所有规则名(如 identifier, number)都是 $ => ...

这个 $ 是构造语法树时的“工具”,让你可以引用别的规则。

3. 正则表达式用于定义词法规则(终结符),例如:

identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/,
number: $ => /\d+/,

五、🍀 $的简单解释:$ 是规则的“引用工具”

grammar.js 中,你写的每一个语法规则都是一个函数,比如这样:

identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/

这里的 $ => 就是给 tree-sitter 传递一个函数,这个函数的参数 $ 是个“语法引用器”。

❓ 那 $ 到底能干嘛?

它能让你“引用其他规则”。

🧠 举个例子来说明

比如你想定义这样一个语句:

let x = 42;

你在写规则时会写成:

variable_declaration: $ => seq(
  'let',
  $.identifier,
  '=',
  $.expression,
  ';'
)

这里的 $.identifier$.expression 就是**“引用”之前定义的两个规则**。注意:

  • $.identifier -> 指向你之前写的 identifier: $ => ...
  • $.expression -> 指向你之前写的 expression: $ => ...

这样 tree-sitter 就能在 variable_declaration 这个规则里,使用别的规则了。


🔧 类比一下:

你可以把 rules 想象成一个对象:

rules = {
  identifier: ...,
  expression: ...,
  variable_declaration: ...
}

$.identifier 就相当于 rules.identifier

所以这个 $ 就是代表你整个 rules 对象本身。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2333523.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Stable Diffusion 四重调参优化——项目学习记录

学习记录还原:在本次实验中,我基于 Stable Diffusion v1.5模型,通过一系列优化方法提升生成图像的质量,最终实现了图像质量的显著提升。实验从基础的 Img2Img 技术入手,逐步推进到参数微调、DreamShaper 模型和 Contro…

我可能用到的网站和软件

我可能用到的网站和软件 程序员交流的网站代码管理工具前端组件库前端框架在线工具人工智能问答工具学习的网站Windows系统电脑的常用工具 程序员交流的网站 csdn博客博客园 - 开发者的网上家园InfoQ - 软件开发及相关领域-极客邦掘金 (juejin.cn) 代码管理工具 GitHub 有时…

FPGA状态机设计:流水灯实现、Modelsim仿真、HDLBits练习

一、状态机思想 1.概念 状态机(Finite State Machine, FSM)是计算机科学和工程领域中的一种抽象模型,用于描述系统在不同状态之间的转换逻辑。其核心思想是将复杂的行为拆解为有限的状态,并通过事件触发状态间的转移。 2.状态机…

2024年第十五届蓝桥杯CC++大学A组--成绩统计

2024年第十五届蓝桥杯C&C大学A组--成绩统计 题目: 动态规划, 对于该题,考虑动态规划解法,先取前k个人的成绩计算其方差,并将成绩记录在数组中,记录当前均值,设小蓝已检查前i-1个人的成绩&…

Kotlin 学习-集合

/*** kotlin 集合* List:是一个有序列表,可通过索引(下标)访问元素。元素可以在list中出现多次、元素可重复* Set:是元素唯一的集合。一般来说 set中的元素顺序并不重要、无序集合* Map:(字典)是一组键值对。键是唯一的…

自动驾驶的未来:多模态感知融合技术最新进展

作为自动驾驶领域的专业人士,我很高兴与大家分享关于多模态感知融合技术的前沿研究和实践经验。在迅速发展的自动驾驶领域,多模态感知融合已成为提升系统性能的关键技术。本文将深入探讨基于摄像头和激光雷达的多模态感知融合技术,重点关注最…

亮相2025全球分布式云大会,火山引擎边缘云落地AI新场景

4 月 9 日,2025 全球分布式云大会暨 AI 基础设施大会在深圳成功举办,火山引擎边缘云产品解决方案高级总监沈建发出席并以《智启边缘,畅想未来:边缘计算新场景落地与 Al 趋势新畅想》为主题,分享了边缘计算在 AI 技术趋…

无损分区管理,硬盘管理的“瑞士军刀”!

打工人们你们好!这里是摸鱼 特供版~ 今天给大家带来一款简单易用、功能强大的无损分区软件——分区助手技术员版,让你的硬盘管理变得轻松又高效! 推荐指数:★★★★★ 软件简介 分区助手技术员版是一款功能强大的硬盘分区工具&…

VS Code下开发FPGA——FPGA开发体验提升__下

上一篇:IntelliJ IDEA下开发FPGA-CSDN博客 Type:Quartus 一、安装插件 在应用商店先安装Digtal IDE插件 安装后,把其他相关的Verilog插件禁用,避免可能的冲突。重启后,可能会弹出下面提示 这是插件默认要求的工具链&a…

ffmpeg播放音视频流程

文章目录 🎬 FFmpeg 解码播放流程概览(以音视频文件为例)1️⃣ 创建结构体2️⃣ 打开音视频文件3️⃣ 查找解码器并打开解码器4️⃣ 循环读取数据包(Packet)5️⃣ 解码成帧(Frame)6️⃣ 播放 / …

SpringCloud微服务: 分布式架构实战

# SpringCloud微服务: 分布式架构实战 第一章:理解SpringCloud微服务架构 什么是SpringCloud微服务架构? 在当今互联网应用开发中,微服务架构已经成为业界的主流趋势。SpringCloud是一个基于Spring Boot的快速开发微服务架构的工具&#xff0…

AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年4月11日第49弹

从今天开始,咱们还是暂时基于旧的模型进行预测,好了,废话不多说,按照老办法,重点8-9码定位,配合三胆下1或下2,杀1-2个和尾,再杀6-8个和值,可以做到100-300注左右。 (1)定…

【models】Transformer 之 各种 Attention 原理和实现

Transformer 之 各种 Attention 原理和实现 本文将介绍Transformer 中常见的Attention的原理和实现,其中包括: Self Attention、Spatial Attention、Temporal Attention、Cross Attention、Grouped Attention、Tensor Product Attention、FlashAttentio…

老硬件也能运行的Win11 IoT LTSC (OEM)物联网版

#记录工作 Windows 11 IoT Enterprise LTSC 2024 属于物联网相关的版本。 Windows 11 IoT Enterprise 是为物联网设备和场景设计的操作系统版本。它通常针对特定的工业控制、智能设备等物联网应用进行了优化和定制,以满足这些领域对稳定性、安全性和长期支持的需求…

Git开发

目录 Linux下Git安装Git基本指令分支管理远程仓库与本地仓库标签管理多人协作同一分支下不同分支下 企业级开发模型 -- git flow 模型 在现实中,当我们完成一个文档的初稿后,后面可能还需要对初稿进行反复修改,从而形成不同版本的文档。显然&…

verilog有符号数的乘法

无符号整数的乘法 1、单周期乘法器( 无符号整数 ) 对于低速要求的乘法器,可以简单的使用 * 实现。 module Mult(input wire [7:0] multiplicand ,input wire [7:0] multipliter ,output wire [7:0] product);as…

DevDocs:抓取并整理技术文档的MCP服务

GitHub:https://github.com/cyberagiinc/DevDocs 更多AI开源软件:发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI DevDocs 是一个完全免费的开源工具,由 CyberAGI 团队开发,托管在 GitHub 上。它专为程序员和软件开发…

第十四届蓝桥杯大赛软件赛国赛Python大学B组题解

文章目录 弹珠堆放划分偶串交易账本背包问题翻转最大阶梯最长回文前后缀贸易航线困局 弹珠堆放 递推式 a i a i − 1 i a_ia_{i-1}i ai​ai−1​i, n 20230610 n20230610 n20230610非常小,直接模拟 答案等于 494 494 494 划分 因为总和为 1 e 6 1e6…

折叠屏手机:技术进步了,柔性OLED面板测试技术需求跟上了吗?

全球智能手机市场陷入创新焦虑,折叠屏手机被寄予厚望,2023 年出货量同比增长 62%。但在供应链技术狂欢背后,存在诸多问题。消费端数据显示,用户使用频率低,定价策略反常。产业链重构虽让部分企业获利,却推高…

30天学Java第九天——线程

并行与并发的区别 并行是多核 CPU 上的多任务处理,多个任务在同一时间真正的同时执行并发是单核 CPU 上的多任务处理,多个任务在同一时间段内交替执行,通过时间片轮转实现交替执行,用于解决 IO 密集型任务的瓶颈 线程的创建方式…