Tree-sitter-Parsing
Tree-sitter-Parsing
Abschnitt betitelt „Tree-sitter-Parsing“Parsen Sie Quellcode in konkrete Syntaxbäume mit Tree-sitter. Basiert auf go-tree-sitter Bindings.
Tree-sitter produziert Syntaxbäume, die:
- Die vollständige Struktur des Quellcodes repräsentieren
- Inkrementell aktualisiert werden, wenn sich Code ändert
- Robust gegenüber Syntaxfehlern sind (partielles Parsing)
- Musterbasierte Abfragen mit S-Ausdrücken unterstützen
local treesitter = require("treesitter")Unterstützte Sprachen
Abschnitt betitelt „Unterstützte Sprachen“| Sprache | Aliase | Root-Node |
|---|---|---|
| Go | go, golang | source_file |
| JavaScript | js, javascript | program |
| TypeScript | ts, typescript | program |
| TSX | tsx | program |
| Python | python, py | module |
| Lua | lua | chunk |
| PHP | php | program |
| C# | csharp, cs, c# | compilation_unit |
| HTML | html, html5 | document |
| Markdown | markdown, md | document |
| SQL | sql | - |
local langs = treesitter.supported_languages()-- {go = true, javascript = true, python = true, ...}Schnellstart
Abschnitt betitelt „Schnellstart“Code parsen
Abschnitt betitelt „Code parsen“local code = [[func hello() { return "Hello!"}]]
local tree, err = treesitter.parse("go", code)if err then return nil, errend
local root = tree:root_node()print(root:kind()) -- "source_file"print(root:child_count()) -- Anzahl Top-Level-DeklarationenSyntaxbaum abfragen
Abschnitt betitelt „Syntaxbaum abfragen“local code = [[func hello() {}func world() {}]]
local tree = treesitter.parse("go", code)local root = tree:root_node()
-- Alle Funktionsnamen findenlocal query = treesitter.query("go", [[ (function_declaration name: (identifier) @func_name)]])
local captures = query:captures(root, code)for _, capture in ipairs(captures) do print(capture.name, capture.text)end-- "func_name" "hello"-- "func_name" "world"Parsing
Abschnitt betitelt „Parsing“Einfaches Parsing
Abschnitt betitelt „Einfaches Parsing“Quellcode in einen Syntaxbaum parsen. Erstellt intern einen temporären Parser.
local tree, err = treesitter.parse("go", code)| Parameter | Typ | Beschreibung |
|---|---|---|
language | string | Sprachname oder Alias |
code | string | Quellcode |
Gibt zurück: Tree, error
Wiederverwendbarer Parser
Abschnitt betitelt „Wiederverwendbarer Parser“Erstellen Sie einen Parser für wiederholtes Parsing oder inkrementelle Updates.
local parser = treesitter.parser()parser:set_language("go")
local tree1 = parser:parse("package main")
-- Inkrementelles Parsing mit altem Baumlocal tree2 = parser:parse("package main\nfunc foo() {}", tree1)
parser:close()Gibt zurück: Parser
Parser-Methoden
Abschnitt betitelt „Parser-Methoden“| Methode | Beschreibung |
|---|---|
set_language(lang) | Parser-Sprache setzen, gibt boolean, error zurück |
get_language() | Aktuellen Sprachnamen abrufen |
parse(code, old_tree?) | Code parsen, optional mit altem Baum für inkrementelles Parsing |
set_timeout(duration) | Parse-Timeout setzen (String wie "1s" oder Nanosekunden) |
set_ranges(ranges) | Byte-Bereiche zum Parsen setzen |
reset() | Parser-Zustand zurücksetzen |
close() | Parser-Ressourcen freigeben |
Syntaxbäume
Abschnitt betitelt „Syntaxbäume“Root-Node abrufen
Abschnitt betitelt „Root-Node abrufen“local tree = treesitter.parse("go", "package main")local root = tree:root_node()
print(root:kind()) -- "source_file"print(root:text()) -- "package main"Tree-Methoden
Abschnitt betitelt „Tree-Methoden“| Methode | Beschreibung |
|---|---|
root_node() | Root-Node des Baums abrufen |
root_node_with_offset(bytes, point) | Root mit angewendetem Offset abrufen |
language() | Sprachobjekt des Baums abrufen |
copy() | Tiefe Kopie des Baums erstellen |
walk() | Cursor für Traversierung erstellen |
edit(edit_table) | Inkrementelle Bearbeitung anwenden |
changed_ranges(other_tree) | Geänderte Bereiche abrufen |
included_ranges() | Beim Parsing eingeschlossene Bereiche abrufen |
dot_graph() | DOT-Graph-Repräsentation abrufen |
close() | Tree-Ressourcen freigeben |
Inkrementelles Bearbeiten
Abschnitt betitelt „Inkrementelles Bearbeiten“Aktualisieren Sie den Baum, wenn sich Quellcode ändert:
local code = "func main() { x := 1 }"local tree = treesitter.parse("go", code)
-- Bearbeitung markieren: "1" zu "100" geändert bei Byte 19tree:edit({ start_byte = 19, old_end_byte = 20, new_end_byte = 22, start_row = 0, start_column = 19, old_end_row = 0, old_end_column = 20, new_end_row = 0, new_end_column = 22})
-- Mit bearbeitetem Baum neu parsen (schneller als vollständiges Parsing)local parser = treesitter.parser()parser:set_language("go")local new_tree = parser:parse("func main() { x := 100 }", tree)Nodes repräsentieren Elemente im Syntaxbaum.
Node-Typen
Abschnitt betitelt „Node-Typen“local node = root:child(0)
-- Typinformationenprint(node:kind()) -- "package_clause"print(node:type()) -- gleich wie kind()print(node:is_named()) -- true für signifikante Nodesprint(node:grammar_name()) -- Grammatik-RegelnameNavigation
Abschnitt betitelt „Navigation“-- Kinderlocal child = node:child(0) -- nach Index (0-basiert)local named = node:named_child(0) -- nur benannte Kinderlocal count = node:child_count()local named_count = node:named_child_count()
-- Geschwisterlocal next = node:next_sibling()local prev = node:prev_sibling()local next_named = node:next_named_sibling()local prev_named = node:prev_named_sibling()
-- Elternlocal parent = node:parent()
-- Nach Feldnamelocal name_node = func_decl:child_by_field_name("name")local field = node:field_name_for_child(0)Positionsinformationen
Abschnitt betitelt „Positionsinformationen“-- Byte-Offsetslocal start = node:start_byte()local end_ = node:end_byte()
-- Zeile/Spalte-Positionen (0-basiert)local start_pt = node:start_point() -- {row = 0, column = 0}local end_pt = node:end_point() -- {row = 0, column = 12}
-- Quelltextlocal text = node:text()Fehlererkennung
Abschnitt betitelt „Fehlererkennung“if root:has_error() then -- Baum enthält Syntaxfehlerend
if node:is_error() then -- Dieser spezifische Node ist ein Fehlerend
if node:is_missing() then -- Parser hat diesen zur Fehlerwiederherstellung eingefügtendS-Ausdruck
Abschnitt betitelt „S-Ausdruck“local sexp = node:to_sexp()-- "(source_file (package_clause (package_identifier)))"Queries
Abschnitt betitelt „Queries“Musterabgleich mit Tree-sitters Abfragesprache (S-Ausdrücke).
Query erstellen
Abschnitt betitelt „Query erstellen“local query, err = treesitter.query("go", [[ (function_declaration name: (identifier) @func_name parameters: (parameter_list) @params )]])| Parameter | Typ | Beschreibung |
|---|---|---|
language | string | Sprachname |
pattern | string | Query-Muster in S-Ausdruck-Syntax |
Gibt zurück: Query, error
Query ausführen
Abschnitt betitelt „Query ausführen“-- Alle Captures abrufen (flach)local captures = query:captures(root, source_code)for _, capture in ipairs(captures) do print(capture.name) -- "@func_name" print(capture.text) -- tatsächlicher Text print(capture.index) -- Capture-Index -- capture.node ist das Node-Objektend
-- Matches abrufen (nach Muster gruppiert)local matches = query:matches(root, source_code)for _, match in ipairs(matches) do print(match.id, match.pattern) for _, capture in ipairs(match.captures) do print(capture.name, capture.node:text()) endendQuery-Steuerung
Abschnitt betitelt „Query-Steuerung“-- Query-Bereich begrenzenquery:set_byte_range(0, 1000)query:set_point_range({row = 0, column = 0}, {row = 10, column = 0})
-- Matches begrenzenquery:set_match_limit(100)if query:did_exceed_match_limit() then -- Mehr Matches existierenend
-- Timeout (String-Dauer oder Nanosekunden)query:set_timeout("500ms")query:set_timeout(1000000000) -- 1 Sekunde in Nanosekunden
-- Muster/Captures deaktivierenquery:disable_pattern(0)query:disable_capture("func_name")Query-Inspektion
Abschnitt betitelt „Query-Inspektion“local pattern_count = query:pattern_count()local capture_count = query:capture_count()local name = query:capture_name_for_id(0)local id = query:capture_index_for_name("func_name")Tree-Cursor
Abschnitt betitelt „Tree-Cursor“Effiziente Traversierung ohne Node-Objekte bei jedem Schritt zu erstellen.
Grundlegende Traversierung
Abschnitt betitelt „Grundlegende Traversierung“local cursor = tree:walk()
-- Bei Root startenprint(cursor:current_node():kind()) -- "source_file"print(cursor:current_depth()) -- 0
-- Navigierenif cursor:goto_first_child() then print(cursor:current_node():kind()) print(cursor:current_depth()) -- 1end
if cursor:goto_next_sibling() then -- zum nächsten Geschwister gewechseltend
cursor:goto_parent() -- zurück zum Eltern
cursor:close()Cursor-Methoden
Abschnitt betitelt „Cursor-Methoden“| Methode | Gibt zurück | Beschreibung |
|---|---|---|
current_node() | Node | Node an Cursor-Position |
current_depth() | integer | Tiefe (0 = Root) |
current_field_name() | string? | Feldname falls vorhanden |
current_field_id() | integer | Feld-ID (0 falls keine) |
current_descendant_index() | integer | Nachfahren-Index des aktuellen Nodes |
goto_parent() | boolean | Zum Eltern wechseln |
goto_first_child() | boolean | Zum ersten Kind wechseln |
goto_last_child() | boolean | Zum letzten Kind wechseln |
goto_next_sibling() | boolean | Zum nächsten Geschwister wechseln |
goto_previous_sibling() | boolean | Zum vorherigen Geschwister wechseln |
goto_descendant(index) | - | Zum Nachfahren per Index wechseln |
goto_first_child_for_byte(n) | integer? | Zum Kind wechseln, das Byte enthält |
goto_first_child_for_point(pt) | integer? | Zum Kind wechseln, das Punkt enthält |
reset(node) | - | Cursor auf Node zurücksetzen |
reset_to(cursor) | - | Cursor auf Position eines anderen Cursors zurücksetzen |
copy() | Cursor | Kopie des Cursors erstellen |
close() | - | Ressourcen freigeben |
Sprach-Metadaten
Abschnitt betitelt „Sprach-Metadaten“local lang = treesitter.language("go")
print(lang:version()) -- ABI-Versionprint(lang:node_kind_count()) -- Anzahl Node-Typenprint(lang:field_count()) -- Anzahl Felderprint(lang:parse_state_count()) -- Anzahl Parse-States
-- Node-Kind-Lookuplocal kind = lang:node_kind_for_id(1)local id = lang:id_for_node_kind("identifier", true)local is_named = lang:node_kind_is_named(1)
-- Feld-Lookuplocal field_name = lang:field_name_for_id(1)local field_id = lang:field_id_for_name("name")| Bedingung | Art | Wiederholbar |
|---|---|---|
| Sprache nicht unterstützt | errors.INVALID | nein |
| Sprache hat kein Binding | errors.INVALID | nein |
| Ungültiges Query-Muster | errors.INVALID | nein |
| Ungültige Positionen | errors.INVALID | nein |
| Parsing fehlgeschlagen | errors.INTERNAL | nein |
Siehe Fehlerbehandlung für die Arbeit mit Fehlern.
Query-Syntax-Referenz
Abschnitt betitelt „Query-Syntax-Referenz“Tree-sitter-Queries verwenden S-Ausdruck-Muster:
; Node-Typ matchen(identifier)
; Mit Feldnamen matchen(function_declaration name: (identifier))
; Mit @name capturen(function_declaration name: (identifier) @func_name)
; Mehrere Muster[ (function_declaration) (method_declaration)] @declaration
; Wildcards(_) ; beliebiger Node(identifier)+ ; ein oder mehr(identifier)* ; null oder mehr(identifier)? ; optional
; Prädikate((identifier) @var (#match? @var "^_")) ; Regex-MatchSiehe Tree-sitter Query Syntax für vollständige Dokumentation.