나무모에 미러 (일반/밝은 화면)
최근 수정 시각 : 2025-11-10 16:17:42

Tree-sitter


[[GitHub|
파일:GitHub 아이콘 화이트.svg파일:GitHub 로고 화이트.svg
]]
{{{#!wiki style="min-height: calc(1.5em + 5px); margin: 0 -10px -5px"
{{{#!folding [ 펼치기 · 접기 ]
{{{#!wiki style="margin: -5px -1px -11px"
<colbgcolor=#000,#000><colcolor=#fff,#fff> 관련 인물 톰 프레스턴 워너
서비스 저장소 · GitHub Pages · GitHub Action · GitHub Packages · GitHub Wiki · GitHub Gist · GitHub Copilot
클라이언트 GitHub CLI · GitHub Desktop · GitHub Mobile
오픈 소스 Electron · Atom · Linguist · Tree-sitter
관련 문서 사건 사고 · GitHub Universe · npm
}}}}}}}}} ||
<colcolor=#fff><bgcolor=#7d8f30> Tree-sitter
파일:Tree-sitter.png
<colbgcolor=#7d8f30> 종류 증분 파서 제너레이터
최초 개발자 맥스 브런스펠드(Max Brunsfeld)
안정 버전 v0.25.10
언어 C, Rust
라이선스 MIT 라이선스
링크 파일:홈페이지 아이콘.svg 파일:GitHub 아이콘.svg파일:GitHub 아이콘 화이트.svg 파일:cargo.rs.png 파일:npm, lnc. n-logo.png
1. 개요2. 역사3. 특징4. Grammar DSL5. TSQuery6. 활용
6.1. 바인딩6.2. 지원 플랫폼6.3. 파생 소프트웨어
7. 기타8. 외부 링크9. 관련 문서

1. 개요

증분식 GLR 파서 제너레이터 구현체.

2. 역사

최초 개발자인 맥스 브런스필드는 2013년 GitHub에 입사해 당시 깃헙의 최대 야심작 중 하나였던 Atom 에디터 팀으로 일하기 시작했다.[z][2] 동시에 2013년 11월 6일[3] CC++로 증분 파싱 시스템인 Tree-sitter를 사이드 프로젝트로 개발하다가[4], Atom이 1.0버전 출시를 준비하는 동안 이를 GitHub의 정식 프로젝트로 포함시킨다.

이후 브런스필드는 2018년 1월 8일 당시 CoffeeScript 기반이었던 Atom의 구문 강조 시스템 및 코드 폴딩 기능에 선택적 Tree-sitter 지원을 추가하는 PR을 작성했고[5] 이는 2018년 2월 14일(안정 릴리즈는 2018년 3월 16일) Atom v1.25.0-beta0 버전부터 core.useTreeSitterParsers 플래그를 통한 실험적 기능으로 제공되기 시작해[6][7] 2018년 10월 31일 Atom v1.31 버전부터는 기본 설정으로 완전히 통합되었다.[8]

2019년 1월 5일, 파서 제너레이터 구현체를 C++에서 Rust로 재작성하고, 파서 개발용 CLI 인터페이스까지 Rust로 재작성하며 node-gyp를 통해 별도의 저장소에서 개발되고 있던 tree-sitter-clideprecate시켰다.[9]

GitHub의 새 code search 및 navigation 기능에 GitHub가 개발한 stackgraph와 함께 중점적으로 쓰이고 있다.## Linguist의 모든 언어가 지원되는 것은 아니고, 현재 C##, Python#, Ruby#, Elixir#, Rust#, TypeScript# 등의 언어 navigation 기능이 Tree-sitter 파서 기반으로 구현되어 있다.

3. 특징

4. Grammar DSL

JavaScript 함수들로 구성된 문법 정의(metasyntax)용 도메인 특화 언어. TreeQL처럼 별도의 언어는 아니고 상술했듯 실행 가능한 JS 함수 목록을 제공하는 것이기에 파서를 생성할 때면 우선 이를 Node.js 환경에서 실행시켜 결과를 JSON 형태로 얻어내는 과정이 한 단계 더 필요하게 되며, 덕분에 사용자 정의 함수를 분리하거나 앞서 사용된 논터미널 규칙을 변수로 참조할 수도 있는 등, 문법 설계에 원하는 매우 높은 자유도를 누릴 수 있다.

문법 정의는 grammar.js 파일에 들어 있다. 해당 파일은 파서 생성에 필요한 문법 객체를 반환하는 하나의 commonjs 모듈을 이루며, 이는 grammar() 함수에 파싱 규칙을 정의한 객체를 전달해서 얻을 수 있다. 개별 규칙은 rules 객체의 개별 프로퍼티로써 정의되는데, 프로퍼티 이름이 해당 규칙의 이름이 되고 프로퍼티 값은 하나의 인자(주로 $)를 받아 패턴을 반환하는 함수의 형태이다.

대표적인 함수 목록은 다음과 같다. external scanner 설정을 하지 않는 한 렉서와 파서 레벨을 구분하지 않음에 주의.
TypeScript를 사용한다면 tree-sitter-cli 패키지에 내장된 타입 정의를 활용해 자동완성 지원을 받을 수 있다. grammar.js 파일에
<reference types="tree-sitter-cli/dsl" />
tirple slash directive로 삽입하고, 타입 검사 기능을 켜면 된다.

5. TSQuery

문서

Grammar DSL은 파서 문법을 정의하기 위한 언어이고, 해당 파서로 파싱된 파스 트리를 쿼리하기 위해서는 S-표현식 기반의 쿼리 언어를 사용한다. 이는 tree-sitter parse 명령을 실행했을 때도 보여지는 문법과도 비슷한데, 이 경우 sexpr의 함수 부분이 alias가 완료된 구문 규칙의 이름이며, 대괄호 사이에 span 정보가 오고 나머지 인자 위치에 해당 트리의 자식 노드들이 놓여진다. 쿼리의 경우 각각의 패턴이 구문 규칙의 이름을 정하고, 패턴 내에 인자로 주어진 다른 패턴이 있다면 자식 노드로 재귀적으로 매칭한다.

이외에도 인자란에 조건절을 추가할 수 있는데, 조건절은 자식 노드가 아니라 상위 스코프에서 캡쳐한 노드에 대해(주로 렉심) 검사한다.
예를 들어, 코드에서 "unset" 또는 "variable" 명령 구문만 찾고 하이라이트하고 싶다면 다음과 같이 쿼리할 수 있다.
#!syntax lisp
(command
  name: (simple_word) @keyword
  arguments: (word_list) @variable
  (#any-of? @keyword
    "unset"
    "variable"))

6. 활용

6.1. 바인딩

아래 언어/런타임별 바인딩을 기본으로 지원한다. 비공식 바인딩 지원은 아래 문단 참고.

6.2. 지원 플랫폼

6.3. 파생 소프트웨어

7. 기타

8. 외부 링크

9. 관련 문서


[z] Max joined the Atom team in 2013 after working at Pivotal Labs. While driving Atom towards its 1.0 launch during the day, Max spent nights and weekends building Tree-sitter, a blazing-fast and expressive incremental parsing framework that currently powers all code analysis at GitHub. Before leaving to start Zed, Max helped GitHub's semantic analysis team integrate Tree-sitter to support syntax highlighting and code navigation on github.com. #@[2] Max Brunsfeld is an engineer on GitHub's Atom team. Tree-sitter - a new parsing system for programming tools[3] Commit 84c5bceb818127fd7728655fb209a1be92e53fde - Nov 6, 2013[4] Today, I'm gonna be talking about a piece of software I've been working on for almost 4 years now, called Tree-sitter. I worked on it as a side project for a long time and now I'm working on it as part of some project of GitHub. Tree-sitter: a new parsing system for programming tools - GitHub Universe 2017 - Dec 21, 2017[5] This pull request adds a new config setting to Atom: core.useTreeSitterParsers, which defaults to false. If you set that setting to true, when editing files written in certain languages, Atom will use a new parsing system called Tree-sitter to provide improved syntax highlighting and code folding. Allow Tree-sitter parsers to be used for syntax highlighting and code folding #16299 - Jan 8, 2018[6] Support greatly improved syntax highlighting and code folding with a next-generation parsing system called tree-sitter. See the pull request for details about opting in to try it out. 1.25.0-beta0 release - Feb 14, 2018[7] For syntax highlighting and code-folding, an incremental parsing system, called tree-sitter, is available in beta form. Tree-sitter is a C library used via bindings to higher-level languages. Tree-sitter currently is disabled by default but can be turned on via the User Tree Sitter Parsers setting. What's new in GitHub's Atom text editor - Mar 16, 2018[8] At GitHub, we want to explore new ways of making programming intuitive and delightful, so we've developed a parsing system called Tree-sitter that will serve as a new foundation for code analysis in Atom. Tree-sitter makes it possible for Atom to parse your code while you type—maintaining a syntax tree at all times that precisely describes the structure of your code. We've enabled the new system by default in Atom, bringing a number of improvements. Atom understands your code better than ever before - Oct 31, 2018[9] In this PR, I'm moving the functionality of tree-sitter-cli into this repository. Instead of implementing the CLI in JavaScript like before, it will now be in Rust. In addition, I'm porting the C++ compiler library (used by the CLI) to Rust, and consolidating it into the CLI crate. Include CLI functionality in the main repo, using Rust instead of C++ #260 - Jan 5, 2019[10] To use the two grammars, first parse the document with the block grammar. Then perform a second parse with the inline grammar using ts_parser_set_included_ranges to specify which parts are inline content. These parts are marked as inline nodes. Children of those inline nodes should be excluded from these ranges. #