├── .gitignore
├── ConsoleReadPasFile.dpr
├── ConsoleReadPasFile.dproj
├── LICENSE
├── README.md
├── TreeSitter.Query.pas
├── TreeSitter.pas
├── TreeSitterLib.pas
└── VCLDemo
├── DelphiTreeSitterVCLDemo.dpr
├── DelphiTreeSitterVCLDemo.dproj
├── frmDTSLanguage.dfm
├── frmDTSLanguage.pas
├── frmDTSMain.dfm
├── frmDTSMain.pas
├── frmDTSQuery.dfm
└── frmDTSQuery.pas
/.gitignore:
--------------------------------------------------------------------------------
1 | # Uncomment these types if you want even more clean repository. But be careful.
2 | # It can make harm to an existing project source. Read explanations below.
3 | #
4 | # Resource files are binaries containing manifest, project icon and version info.
5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.
6 | #*.res
7 | #
8 | # Type library file (binary). In old Delphi versions it should be stored.
9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored.
10 | #*.tlb
11 | #
12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7.
13 | # Uncomment this if you are not using diagrams or use newer Delphi version.
14 | #*.ddp
15 | #
16 | # Visual LiveBindings file. Added in Delphi XE2.
17 | # Uncomment this if you are not using LiveBindings Designer.
18 | #*.vlb
19 | #
20 | # Deployment Manager configuration file for your project. Added in Delphi XE2.
21 | # Uncomment this if it is not mobile development and you do not use remote debug feature.
22 | #*.deployproj
23 | #
24 | # C++ object files produced when C/C++ Output file generation is configured.
25 | # Uncomment this if you are not using external objects (zlib library for example).
26 | #*.obj
27 | #
28 |
29 | # Delphi compiler-generated binaries (safe to delete)
30 | *.exe
31 | *.dll
32 | *.bpl
33 | *.bpi
34 | *.dcp
35 | *.so
36 | *.apk
37 | *.drc
38 | *.map
39 | *.dres
40 | *.rsm
41 | *.tds
42 | *.dcu
43 | *.lib
44 | *.a
45 | *.o
46 | *.ocx
47 |
48 | # Delphi autogenerated files (duplicated info)
49 | *.cfg
50 | *.hpp
51 | *Resource.rc
52 |
53 | # Delphi local files (user-specific info)
54 | *.local
55 | *.identcache
56 | *.projdata
57 | *.tvsconfig
58 | *.dsk
59 |
60 | # Delphi history and backups
61 | __history/
62 | __recovery/
63 | *.~*
64 |
65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi)
66 | *.stat
67 |
68 | # ignore auto-generated project .res files
69 | *.res
70 |
71 | # ignore auto-created DevExpress skin configuration file
72 | *.skincfg
73 |
--------------------------------------------------------------------------------
/ConsoleReadPasFile.dpr:
--------------------------------------------------------------------------------
1 | program ConsoleReadPasFile;
2 |
3 | {$APPTYPE CONSOLE}
4 |
5 | {$R *.res}
6 |
7 | uses
8 | Classes,
9 | System.SysUtils,
10 | IOUtils,
11 | TreeSitter in 'TreeSitter.pas',
12 | TreeSitterLib in 'TreeSitterLib.pas';
13 |
14 | function tree_sitter_pascal(): PTSLanguage; cdecl; external 'tree-sitter-pascal';
15 |
16 | procedure ReadAndParsePasFile(const AFileName: string);
17 | var
18 | parser: TTSParser;
19 | fs: TFileStream;
20 | tree: TTSTree;
21 | begin
22 | tree:= nil;
23 | parser:= nil;
24 | fs:= TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone);
25 | try
26 | parser:= TTSParser.Create;
27 | parser.Language:= tree_sitter_pascal;
28 | tree:= parser.parse(
29 | function (AByteIndex: UInt32; APosition: TTSPoint; var ABytesRead: UInt32): TBytes
30 | const
31 | BufSize = 10 * 1024;
32 | begin
33 | if fs.Seek(AByteIndex, soFromBeginning) < 0 then
34 | begin
35 | ABytesRead:= 0;
36 | Exit;
37 | end;
38 | SetLength(Result, BufSize);
39 | try
40 | ABytesRead:= fs.Read(Result, BufSize);
41 | except
42 | ABytesRead:= 0;
43 | end;
44 | SetLength(Result, ABytesRead);
45 | end, TTSInputEncoding.TSInputEncodingUTF8);
46 |
47 | WriteLn(tree.RootNode.ToString);
48 | finally
49 | tree.Free;
50 | parser.Free;
51 | fs.Free;
52 | end;
53 | end;
54 |
55 | var
56 | fn: string;
57 | begin
58 | try
59 | fn:= TPath.Combine(TPath.GetDirectoryName(ParamStr(0)), '..\..\TreeSitter.pas');
60 | if TFile.Exists(fn) then
61 | ReadAndParsePasFile(fn) else
62 | raise Exception.CreateFmt('Failed to find file to parse: "%s"', [fn]);
63 | ReadLn;
64 | except
65 | on E: Exception do
66 | Writeln(E.ClassName, ': ', E.Message);
67 | end;
68 | end.
69 |
--------------------------------------------------------------------------------
/ConsoleReadPasFile.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {45C77D6D-775B-4ECE-8759-F18B4127BF77}
4 | 19.5
5 | None
6 | True
7 | Debug
8 | Win64
9 | 3
10 | Console
11 | ConsoleReadPasFile.dpr
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Base
34 | true
35 |
36 |
37 | true
38 | Base
39 | true
40 |
41 |
42 | true
43 | Base
44 | true
45 |
46 |
47 | true
48 | Base
49 | true
50 |
51 |
52 | true
53 | Cfg_1
54 | true
55 | true
56 |
57 |
58 | true
59 | Base
60 | true
61 |
62 |
63 | .\$(Platform)\$(Config)
64 | .\$(Platform)\$(Config)
65 | false
66 | false
67 | false
68 | false
69 | false
70 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
71 | ConsoleReadPasFile
72 |
73 |
74 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
75 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
76 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
77 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
78 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
79 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
80 | $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
81 | $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
82 | $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
83 | $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
84 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
85 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
86 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
87 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
88 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
89 |
90 |
91 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
92 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
93 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
94 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
95 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
96 | $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
97 | $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
98 | $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
99 | $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
100 | $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
101 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
102 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
103 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
104 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
105 | $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
106 |
107 |
108 | fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonODBC;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;bindcompfmx;inetdb;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;DBXMySQLDriver;inet;fmxase;dbrtl;fmxdae;CustomIPTransport;DBXInterBaseDriver;IndySystem;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;FireDACPgDriver;FireDAC;inetdbxpress;xmlrtl;tethering;dsnap;CloudService;fmxobj;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
109 | true
110 |
111 |
112 | fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonODBC;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;bindcompfmx;inetdb;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;DBXMySQLDriver;inet;fmxase;dbrtl;fmxdae;CustomIPTransport;DBXInterBaseDriver;IndySystem;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;FireDACPgDriver;FireDAC;inetdbxpress;xmlrtl;tethering;dsnap;CloudService;fmxobj;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
113 | true
114 |
115 |
116 | dxPSdxSpreadSheetLnkRS28;vclwinx;rbIDE2128;rbTC2128;FMXTeeLanguage928;dclRBADO2128;fmx;dxRichEditDocumentModelRS28;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;FireDACCommonODBC;cxExportRS28;rbBDE2128;FireDACCommonDriver;dxHttpIndyRequestRS28;appanalytics;IndyProtocols;vclx;LWJSDialogRXAlexandria;rbRIDE2128;IndyIPClient;dbxcds;vcledge;cxLibraryRS28;dxCloudServiceLibraryRS28;bindcompvclwinx;rbCIDE2128;dxTileControlRS28;cxPivotGridOLAPRS28;dxPScxPivotGridLnkRS28;dxPScxVGridLnkRS28;dxGDIPlusRS28;dclRBE2128;dxPSdxDBOCLnkRS28;TeeUI928;bindcompfmx;TeeGL928;madBasic_;dxCoreRS28;cxPivotGridRS28;TeeTree2D28Tee9;dxPSdxPDFViewerLnkRS28;inetdb;FixInsight_11;dxSpreadSheetCoreRS28;dxPSCoreRS28;FireDACSqliteDriver;DbxClientDriver;dxSpreadSheetRS28;dxSkinsCoreRS28;rbFireDAC2128;dxTabbedMDIRS28;FmxTeeUI928;soapmidas;dxBarRS28;vclactnband;dxWizardControlRS28;dxADOServerModeRS28;fmxFireDAC;dbexpress;dxFireDACServerModeRS28;TeeImport928;dclRBDBE2128;FMXTree28;DBXMySQLDriver;TeeLanguage928;VclSmp;inet;dxServerModeRS28;dxPSdxLCLnkRS28;vcltouch;fmxase;cxTreeListRS28;dxBarDBNavRS28;LWRXAlexandriaPackage;dbrtl;TeeMaker128;dxPSLnksRS28;fmxdae;dxPScxCommonRS28;FireDACMSAccDriver;dxNavBarRS28;CustomIPTransport;rbDAD2128;rbRCL2128;dxSpreadSheetReportDesignerRS28;TeePro928;dxChartControlRS28;vcldsnap;madExcept_;dxComnRS28;DBXInterBaseDriver;dxFlowChartDesignerRS28;IndySystem;dxSpreadSheetConditionalFormattingDialogsRS28;cxVerticalGridRS28;FMXTeeDB928;dxOrgChartAdvancedCustomizeFormRS28;vcldb;dxDBXServerModeRS28;dxmdsRS28;dxRichEditControlRS28;dxRibbonRS28;VirtualTreesR;dxPSdxOCLnkRS28;dxFlowChartLayoutsRS28;dxPScxExtCommonRS28;ActiveXTest;rbRAP2128;dxdborRS28;vclFireDAC;madDisAsm_;dxRichEditControlCoreRS28;bindcomp;FireDACCommon;rbDBE2128;rbDIDE2128;dxPsPrVwAdvRS28;FMXTeePro928;dxRibbonCustomizationFormRS28;IndyCore;RESTBackendComponents;dxPScxGridLnkRS28;cxPivotGridChartRS28;rbDB2128;bindcompdbx;dxBarExtDBItemsRS28;dxRichEditCoreRS28;cxTreeListdxBarPopupMenuRS28;rtl;FireDACMySQLDriver;dxDockingRS28;dxPDFViewerRS28;FireDACADSDriver;rbCloudSC2128;dxGaugeControlRS28;dxFlowChartAdvancedCustomizeFormRS28;rbUSERDesign2128;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;adortl;dxBarExtItemsRS28;dxPSdxFCLnkRS28;dxorgcRS28;rbRest2128;dxSpreadSheetCoreConditionalFormattingDialogsRS28;TeeImage928;rbTCUI2128;TeeDB928;FMXTee928;dxPSdxGaugeControlLnkRS28;dxPSRichEditControlLnkRS28;cxGridRS28;rbADO2128;vclimg;FireDACPgDriver;FireDAC;inetdbxpress;GLScene_RunTime;xmlrtl;tethering;rbUSER2128;TeeWorld928;bindcompvcl;dsnap;rbRTL2128;CloudService;dxPScxTLLnkRS28;LWHanauRX11;fmxobj;bindcompvclsmp;Tee928;dclRBFireDAC2128;dxFlowChartRS28;dxPScxPCProdRS28;soaprtl;FMXTeeImport928;soapserver;FireDACIBDriver;$(DCC_UsePackage)
117 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
118 | Debug
119 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
120 | 1033
121 | true
122 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
123 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
124 |
125 |
126 | dxPSdxSpreadSheetLnkRS28;vclwinx;fmx;dxRichEditDocumentModelRS28;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;FireDACCommonODBC;cxExportRS28;FireDACCommonDriver;dxHttpIndyRequestRS28;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;cxLibraryRS28;dxCloudServiceLibraryRS28;bindcompvclwinx;dxTileControlRS28;cxPivotGridOLAPRS28;dxPScxPivotGridLnkRS28;dxPScxVGridLnkRS28;dxGDIPlusRS28;dxPSdxDBOCLnkRS28;bindcompfmx;dxCoreRS28;cxPivotGridRS28;dxPSdxPDFViewerLnkRS28;inetdb;dxSpreadSheetCoreRS28;dxPSCoreRS28;FireDACSqliteDriver;DbxClientDriver;dxSpreadSheetRS28;dxSkinsCoreRS28;dxTabbedMDIRS28;soapmidas;dxBarRS28;vclactnband;dxWizardControlRS28;dxADOServerModeRS28;fmxFireDAC;dbexpress;dxFireDACServerModeRS28;DBXMySQLDriver;VclSmp;inet;dxServerModeRS28;dxPSdxLCLnkRS28;vcltouch;fmxase;cxTreeListRS28;dxBarDBNavRS28;dbrtl;dxPSLnksRS28;fmxdae;dxPScxCommonRS28;FireDACMSAccDriver;dxNavBarRS28;CustomIPTransport;dxSpreadSheetReportDesignerRS28;dxChartControlRS28;vcldsnap;dxComnRS28;DBXInterBaseDriver;dxFlowChartDesignerRS28;IndySystem;dxSpreadSheetConditionalFormattingDialogsRS28;cxVerticalGridRS28;dxOrgChartAdvancedCustomizeFormRS28;vcldb;dxDBXServerModeRS28;dxmdsRS28;dxRichEditControlRS28;dxRibbonRS28;VirtualTreesR;dxPSdxOCLnkRS28;dxFlowChartLayoutsRS28;dxPScxExtCommonRS28;dxdborRS28;vclFireDAC;dxRichEditControlCoreRS28;bindcomp;FireDACCommon;dxPsPrVwAdvRS28;dxRibbonCustomizationFormRS28;IndyCore;RESTBackendComponents;dxPScxGridLnkRS28;cxPivotGridChartRS28;bindcompdbx;dxBarExtDBItemsRS28;dxRichEditCoreRS28;cxTreeListdxBarPopupMenuRS28;rtl;FireDACMySQLDriver;dxDockingRS28;dxPDFViewerRS28;FireDACADSDriver;dxGaugeControlRS28;dxFlowChartAdvancedCustomizeFormRS28;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;adortl;dxBarExtItemsRS28;dxPSdxFCLnkRS28;dxorgcRS28;dxSpreadSheetCoreConditionalFormattingDialogsRS28;dxPSdxGaugeControlLnkRS28;dxPSRichEditControlLnkRS28;cxGridRS28;vclimg;FireDACPgDriver;FireDAC;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;dxPScxTLLnkRS28;fmxobj;bindcompvclsmp;dxFlowChartRS28;dxPScxPCProdRS28;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
127 | true
128 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
129 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
130 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
131 | Debug
132 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
133 | 1033
134 |
135 |
136 | DEBUG;$(DCC_Define)
137 | true
138 | false
139 | true
140 | true
141 | true
142 | true
143 | true
144 |
145 |
146 | false
147 |
148 |
149 | false
150 | RELEASE;$(DCC_Define)
151 | 0
152 | 0
153 |
154 |
155 |
156 | MainSource
157 |
158 |
159 |
160 |
161 | Base
162 |
163 |
164 | Cfg_1
165 | Base
166 |
167 |
168 | Cfg_2
169 | Base
170 |
171 |
172 |
173 | Delphi.Personality.12
174 | Application
175 |
176 |
177 |
178 | ConsoleReadPasFile.dpr
179 |
180 |
181 |
182 |
183 |
184 | true
185 |
186 |
187 |
188 |
189 | true
190 |
191 |
192 |
193 |
194 | true
195 |
196 |
197 |
198 |
199 | ConsoleReadPasFile.exe
200 | true
201 |
202 |
203 |
204 |
205 | 1
206 |
207 |
208 | Contents\MacOS
209 | 1
210 |
211 |
212 | 0
213 |
214 |
215 |
216 |
217 | classes
218 | 64
219 |
220 |
221 | classes
222 | 64
223 |
224 |
225 |
226 |
227 | res\xml
228 | 1
229 |
230 |
231 | res\xml
232 | 1
233 |
234 |
235 |
236 |
237 | library\lib\armeabi-v7a
238 | 1
239 |
240 |
241 |
242 |
243 | library\lib\armeabi
244 | 1
245 |
246 |
247 | library\lib\armeabi
248 | 1
249 |
250 |
251 |
252 |
253 | library\lib\armeabi-v7a
254 | 1
255 |
256 |
257 |
258 |
259 | library\lib\mips
260 | 1
261 |
262 |
263 | library\lib\mips
264 | 1
265 |
266 |
267 |
268 |
269 | library\lib\armeabi-v7a
270 | 1
271 |
272 |
273 | library\lib\arm64-v8a
274 | 1
275 |
276 |
277 |
278 |
279 | library\lib\armeabi-v7a
280 | 1
281 |
282 |
283 |
284 |
285 | res\drawable
286 | 1
287 |
288 |
289 | res\drawable
290 | 1
291 |
292 |
293 |
294 |
295 | res\values
296 | 1
297 |
298 |
299 | res\values
300 | 1
301 |
302 |
303 |
304 |
305 | res\values-v21
306 | 1
307 |
308 |
309 | res\values-v21
310 | 1
311 |
312 |
313 |
314 |
315 | res\values
316 | 1
317 |
318 |
319 | res\values
320 | 1
321 |
322 |
323 |
324 |
325 | res\drawable
326 | 1
327 |
328 |
329 | res\drawable
330 | 1
331 |
332 |
333 |
334 |
335 | res\drawable-xxhdpi
336 | 1
337 |
338 |
339 | res\drawable-xxhdpi
340 | 1
341 |
342 |
343 |
344 |
345 | res\drawable-xxxhdpi
346 | 1
347 |
348 |
349 | res\drawable-xxxhdpi
350 | 1
351 |
352 |
353 |
354 |
355 | res\drawable-ldpi
356 | 1
357 |
358 |
359 | res\drawable-ldpi
360 | 1
361 |
362 |
363 |
364 |
365 | res\drawable-mdpi
366 | 1
367 |
368 |
369 | res\drawable-mdpi
370 | 1
371 |
372 |
373 |
374 |
375 | res\drawable-hdpi
376 | 1
377 |
378 |
379 | res\drawable-hdpi
380 | 1
381 |
382 |
383 |
384 |
385 | res\drawable-xhdpi
386 | 1
387 |
388 |
389 | res\drawable-xhdpi
390 | 1
391 |
392 |
393 |
394 |
395 | res\drawable-mdpi
396 | 1
397 |
398 |
399 | res\drawable-mdpi
400 | 1
401 |
402 |
403 |
404 |
405 | res\drawable-hdpi
406 | 1
407 |
408 |
409 | res\drawable-hdpi
410 | 1
411 |
412 |
413 |
414 |
415 | res\drawable-xhdpi
416 | 1
417 |
418 |
419 | res\drawable-xhdpi
420 | 1
421 |
422 |
423 |
424 |
425 | res\drawable-xxhdpi
426 | 1
427 |
428 |
429 | res\drawable-xxhdpi
430 | 1
431 |
432 |
433 |
434 |
435 | res\drawable-xxxhdpi
436 | 1
437 |
438 |
439 | res\drawable-xxxhdpi
440 | 1
441 |
442 |
443 |
444 |
445 | res\drawable-small
446 | 1
447 |
448 |
449 | res\drawable-small
450 | 1
451 |
452 |
453 |
454 |
455 | res\drawable-normal
456 | 1
457 |
458 |
459 | res\drawable-normal
460 | 1
461 |
462 |
463 |
464 |
465 | res\drawable-large
466 | 1
467 |
468 |
469 | res\drawable-large
470 | 1
471 |
472 |
473 |
474 |
475 | res\drawable-xlarge
476 | 1
477 |
478 |
479 | res\drawable-xlarge
480 | 1
481 |
482 |
483 |
484 |
485 | res\values
486 | 1
487 |
488 |
489 | res\values
490 | 1
491 |
492 |
493 |
494 |
495 | 1
496 |
497 |
498 | Contents\MacOS
499 | 1
500 |
501 |
502 | 0
503 |
504 |
505 |
506 |
507 | Contents\MacOS
508 | 1
509 | .framework
510 |
511 |
512 | Contents\MacOS
513 | 1
514 | .framework
515 |
516 |
517 | Contents\MacOS
518 | 1
519 | .framework
520 |
521 |
522 | 0
523 |
524 |
525 |
526 |
527 | 1
528 | .dylib
529 |
530 |
531 | 1
532 | .dylib
533 |
534 |
535 | 1
536 | .dylib
537 |
538 |
539 | Contents\MacOS
540 | 1
541 | .dylib
542 |
543 |
544 | Contents\MacOS
545 | 1
546 | .dylib
547 |
548 |
549 | Contents\MacOS
550 | 1
551 | .dylib
552 |
553 |
554 | 0
555 | .dll;.bpl
556 |
557 |
558 |
559 |
560 | 1
561 | .dylib
562 |
563 |
564 | 1
565 | .dylib
566 |
567 |
568 | 1
569 | .dylib
570 |
571 |
572 | Contents\MacOS
573 | 1
574 | .dylib
575 |
576 |
577 | Contents\MacOS
578 | 1
579 | .dylib
580 |
581 |
582 | Contents\MacOS
583 | 1
584 | .dylib
585 |
586 |
587 | 0
588 | .bpl
589 |
590 |
591 |
592 |
593 | 0
594 |
595 |
596 | 0
597 |
598 |
599 | 0
600 |
601 |
602 | 0
603 |
604 |
605 | 0
606 |
607 |
608 | Contents\Resources\StartUp\
609 | 0
610 |
611 |
612 | Contents\Resources\StartUp\
613 | 0
614 |
615 |
616 | Contents\Resources\StartUp\
617 | 0
618 |
619 |
620 | 0
621 |
622 |
623 |
624 |
625 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
626 | 1
627 |
628 |
629 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
630 | 1
631 |
632 |
633 |
634 |
635 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
636 | 1
637 |
638 |
639 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
640 | 1
641 |
642 |
643 |
644 |
645 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
646 | 1
647 |
648 |
649 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
650 | 1
651 |
652 |
653 |
654 |
655 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
656 | 1
657 |
658 |
659 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
660 | 1
661 |
662 |
663 |
664 |
665 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
666 | 1
667 |
668 |
669 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
670 | 1
671 |
672 |
673 |
674 |
675 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
676 | 1
677 |
678 |
679 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
680 | 1
681 |
682 |
683 |
684 |
685 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
686 | 1
687 |
688 |
689 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
690 | 1
691 |
692 |
693 |
694 |
695 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
696 | 1
697 |
698 |
699 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
700 | 1
701 |
702 |
703 |
704 |
705 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
706 | 1
707 |
708 |
709 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
710 | 1
711 |
712 |
713 |
714 |
715 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
716 | 1
717 |
718 |
719 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
720 | 1
721 |
722 |
723 |
724 |
725 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
726 | 1
727 |
728 |
729 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
730 | 1
731 |
732 |
733 |
734 |
735 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
736 | 1
737 |
738 |
739 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
740 | 1
741 |
742 |
743 |
744 |
745 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
746 | 1
747 |
748 |
749 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
750 | 1
751 |
752 |
753 |
754 |
755 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
756 | 1
757 |
758 |
759 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
760 | 1
761 |
762 |
763 |
764 |
765 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
766 | 1
767 |
768 |
769 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
770 | 1
771 |
772 |
773 |
774 |
775 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
776 | 1
777 |
778 |
779 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
780 | 1
781 |
782 |
783 |
784 |
785 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
786 | 1
787 |
788 |
789 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
790 | 1
791 |
792 |
793 |
794 |
795 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
796 | 1
797 |
798 |
799 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
800 | 1
801 |
802 |
803 |
804 |
805 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
806 | 1
807 |
808 |
809 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
810 | 1
811 |
812 |
813 |
814 |
815 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
816 | 1
817 |
818 |
819 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
820 | 1
821 |
822 |
823 |
824 |
825 | 1
826 |
827 |
828 | 1
829 |
830 |
831 |
832 |
833 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
834 | 1
835 |
836 |
837 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
838 | 1
839 |
840 |
841 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
842 | 1
843 |
844 |
845 |
846 |
847 | ..\
848 | 1
849 |
850 |
851 | ..\
852 | 1
853 |
854 |
855 | ..\
856 | 1
857 |
858 |
859 |
860 |
861 | 1
862 |
863 |
864 | 1
865 |
866 |
867 | 1
868 |
869 |
870 |
871 |
872 | ..\$(PROJECTNAME).launchscreen
873 | 64
874 |
875 |
876 | ..\$(PROJECTNAME).launchscreen
877 | 64
878 |
879 |
880 |
881 |
882 | 1
883 |
884 |
885 | 1
886 |
887 |
888 | 1
889 |
890 |
891 |
892 |
893 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
894 | 1
895 |
896 |
897 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
898 | 1
899 |
900 |
901 |
902 |
903 | ..\
904 | 1
905 |
906 |
907 | ..\
908 | 1
909 |
910 |
911 | ..\
912 | 1
913 |
914 |
915 |
916 |
917 | Contents
918 | 1
919 |
920 |
921 | Contents
922 | 1
923 |
924 |
925 | Contents
926 | 1
927 |
928 |
929 |
930 |
931 | Contents\Resources
932 | 1
933 |
934 |
935 | Contents\Resources
936 | 1
937 |
938 |
939 | Contents\Resources
940 | 1
941 |
942 |
943 |
944 |
945 | library\lib\armeabi-v7a
946 | 1
947 |
948 |
949 | library\lib\arm64-v8a
950 | 1
951 |
952 |
953 | 1
954 |
955 |
956 | 1
957 |
958 |
959 | 1
960 |
961 |
962 | 1
963 |
964 |
965 | Contents\MacOS
966 | 1
967 |
968 |
969 | Contents\MacOS
970 | 1
971 |
972 |
973 | Contents\MacOS
974 | 1
975 |
976 |
977 | 0
978 |
979 |
980 |
981 |
982 | library\lib\armeabi-v7a
983 | 1
984 |
985 |
986 |
987 |
988 | 1
989 |
990 |
991 | 1
992 |
993 |
994 |
995 |
996 | Assets
997 | 1
998 |
999 |
1000 | Assets
1001 | 1
1002 |
1003 |
1004 |
1005 |
1006 | Assets
1007 | 1
1008 |
1009 |
1010 | Assets
1011 | 1
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
1024 |
1025 |
1026 |
1027 | False
1028 | False
1029 | False
1030 | False
1031 | True
1032 | True
1033 |
1034 |
1035 | 12
1036 |
1037 |
1038 |
1039 |
1040 |
1041 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 modersohn
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # delphi-tree-sitter
2 |
3 | Delphi (and potentially FreePascal) bindings for [tree-sitter][]
4 |
5 | [tree-sitter]: https://github.com/tree-sitter/tree-sitter
6 |
7 | ## Status
8 |
9 | Windows only for now and only tested with Delphi.
10 |
11 |
12 | | API section | Status |
13 | | --- | --- |
14 | | Parser | Basics covered |
15 | | Language | Mostly complete |
16 | | Tree | Mostly complete |
17 | | TreeCursor | Mostly complete |
18 | | Node | Mostly complete |
19 | | Query | Mostly complete |
20 | | QueryCursor | Mostly complete |
21 | | LookAheadIterator | Missing |
22 | | WebAssembly Integration | Missing |
23 |
24 | ## Installation
25 |
26 | No design-time packages etc. necessary. The demos with GUI - as of yet - do not require any additional 3rd party packages.
27 |
28 | To run the demos, you need to have `tree-sitter.dll` (of the right architecure) somewhere, where the EXE will
29 | be able to find it (it won't even start without).
30 |
31 | For the different parsers (sometimes called grammars) you need a DLL too, e.g. [tree-sitter-c][]
32 |
33 | If you don't have a C compiler setup at hand to compile the tree-sitter DLLs, I can highly recommend [zig][].
34 |
35 | Tree-sitter itself already comes with a `build.zig` file, so running `zig build` in the root directory of tree-sitter will work.
36 | This might build a .lib instead of a .dll, so in `build.zig` you would need to change `b.addStaticLibrary` into `b.addSharedLibrary`.
37 |
38 | Most parsers do not seem to come with zig-support out of the box, but it should be straightforward to create a `build.zig` and use the one from tree-sitter itself as a template.
39 |
40 | [tree-sitter-c]: https://github.com/tree-sitter/tree-sitter-c
41 | [zig]: https://ziglang.org
42 |
43 | ## VCL demo project
44 |
45 | Instead of demoing a typical use-case, the VCL demo is intended to allow exploring the API and functionality that tree-sitter supplies.
46 | 
47 |
48 | Currently supports a handful of languages out of the box and a treeview of nodes with field name and ID where applicable. Selects the corresponding code part in the memo when a node gets selected.
49 |
50 | Inspector-like grid with node properties. Navigation via popup menu of the tree. Lists field names of the language and allows finding child node by field ID.
51 |
52 | Now with secondary form listing symbols, fields and version of the language:
53 | 
54 |
55 | New query form, showing info about the query and allowing iterating over matches and listing their captures. Selecting a capture, selects the captured node in the main form and selects the corresponding code section:
56 | 
57 |
58 | ## Console demo project loading .pas
59 |
60 | [Simple console project](ConsoleReadPasFile.dpr) which demonstrates TTSParser.Parse called with an anonymous method for reading the text to parse.
61 |
--------------------------------------------------------------------------------
/TreeSitter.Query.pas:
--------------------------------------------------------------------------------
1 | unit TreeSitter.Query;
2 |
3 | interface
4 |
5 | uses
6 | TreeSitterLib, TreeSitter;
7 |
8 | type
9 | TTSQueryError = TreeSitterLib.TSQueryError;
10 | TTSQueryPredicateStep = TreeSitterLib.TSQueryPredicateStep;
11 | TTSQueryPredicateStepType = TreeSitterLib.TSQueryPredicateStepType;
12 |
13 | TTSQueryPredicateStepArray = array of TTSQueryPredicateStep;
14 | TTSQuantifier = TreeSitterLib.TSQuantifier;
15 |
16 | TTSQuery = class
17 | strict private
18 | FQuery: PTSQuery;
19 | public
20 | constructor Create(ALanguage: PTSLanguage; const ASource: string;
21 | var AErrorOffset: UInt32; var AErrorType: TTSQueryError); virtual;
22 | destructor Destroy; override;
23 |
24 | function PatternCount: UInt32;
25 | function CaptureCount: UInt32;
26 | function StringCount: UInt32;
27 |
28 | function StartByteForPattern(APatternIndex: UInt32): UInt32;
29 | function PredicatesForPattern(APatternIndex: UInt32): TTSQueryPredicateStepArray;
30 |
31 | function CaptureNameForID(ACaptureIndex: UInt32): string;
32 | function StringValueForID(AStringIndex: UInt32): string;
33 |
34 | function QuantifierForCapture(APatternIndex, ACaptureIndex: UInt32): TTSQuantifier;
35 |
36 | property Query: PTSQuery read FQuery;
37 | end;
38 |
39 | TTSQueryCapture = TreeSitterLib.TSQueryCapture;
40 | TTSQueryCaptureArray = array of TTSQueryCapture;
41 |
42 | TTSQueryMatch = TreeSitterLib.TSQueryMatch;
43 |
44 | TTSQueryMatchHelper = record helper for TTSQueryMatch
45 | function CapturesArray: TTSQueryCaptureArray;
46 | end;
47 |
48 | TTSQueryCursor = class
49 | strict private
50 | FQueryCursor: PTSQueryCursor;
51 |
52 | function GetMatchLimit: UInt32;
53 | procedure SetMatchLimit(const Value: UInt32);
54 | public
55 | constructor Create; virtual;
56 | destructor Destroy; override;
57 |
58 | procedure Execute(AQuery: TTSQuery; ANode: TTSNode);
59 | function DidExceedMatchLimit: Boolean;
60 | procedure SetMaxStartDepth(AMaxStartDepth: UInt32);
61 |
62 | function NextMatch(var AMatch: TTSQueryMatch): Boolean;
63 | function NextCapture(var AMatch: TTSQueryMatch; var ACaptureIndex: UInt32): Boolean;
64 |
65 | property QueryCursor: PTSQueryCursor read FQueryCursor;
66 | property MatchLimit: UInt32 read GetMatchLimit write SetMatchLimit;
67 | end;
68 |
69 |
70 | implementation
71 |
72 | { TTSQuery }
73 |
74 | function TTSQuery.CaptureCount: UInt32;
75 | begin
76 | Result:= ts_query_capture_count(FQuery);
77 | end;
78 |
79 | function TTSQuery.CaptureNameForID(ACaptureIndex: UInt32): string;
80 | var
81 | pac: PAnsiChar;
82 | len: UInt32;
83 | res: AnsiString;
84 | begin
85 | pac:= ts_query_capture_name_for_id(FQuery, ACaptureIndex, len);
86 | SetLength(res, len);
87 | if len > 0 then
88 | Move(pac[0], res[1], len * SizeOf(pac[0]));
89 | Result:= string(res);
90 | end;
91 |
92 | constructor TTSQuery.Create(ALanguage: PTSLanguage; const ASource: string;
93 | var AErrorOffset: UInt32; var AErrorType: TTSQueryError);
94 | var
95 | ansiSource: AnsiString;
96 | begin
97 | ansiSource:= AnsiString(ASource);
98 | FQuery:= ts_query_new(ALanguage, PAnsiChar(ansiSource), Length(ansiSource),
99 | AErrorOffset, AErrorType);
100 | end;
101 |
102 | destructor TTSQuery.Destroy;
103 | begin
104 | ts_query_delete(FQuery);
105 | inherited;
106 | end;
107 |
108 | function TTSQuery.PatternCount: UInt32;
109 | begin
110 | Result:= ts_query_pattern_count(FQuery);
111 | end;
112 |
113 | function TTSQuery.PredicatesForPattern(
114 | APatternIndex: UInt32): TTSQueryPredicateStepArray;
115 | var
116 | count: UInt32;
117 | parr: PTSQueryPredicateStepArray;
118 | begin
119 | count:= 0;
120 | parr:= ts_query_predicates_for_pattern(FQuery, APatternIndex, count);
121 | if (parr <> nil) and (count > 0) then
122 | begin
123 | SetLength(Result, count);
124 | Move(parr[0], Result[0], count * SizeOf(Result[0]));
125 | end;
126 | end;
127 |
128 | function TTSQuery.QuantifierForCapture(APatternIndex,
129 | ACaptureIndex: UInt32): TTSQuantifier;
130 | begin
131 | Result:= ts_query_capture_quantifier_for_id(FQuery, APatternIndex, ACaptureIndex);
132 | end;
133 |
134 | function TTSQuery.StartByteForPattern(APatternIndex: UInt32): UInt32;
135 | begin
136 | Result:= ts_query_start_byte_for_pattern(FQuery, APatternIndex);
137 | end;
138 |
139 | function TTSQuery.StringCount: UInt32;
140 | begin
141 | Result:= ts_query_string_count(FQuery);
142 | end;
143 |
144 | function TTSQuery.StringValueForID(AStringIndex: UInt32): string;
145 | var
146 | pac: PAnsiChar;
147 | len: UInt32;
148 | res: AnsiString;
149 | begin
150 | pac:= ts_query_string_value_for_id(FQuery, AStringIndex, len);
151 | SetLength(res, len);
152 | if len > 0 then
153 | Move(pac[0], res[1], len * SizeOf(pac[0]));
154 | Result:= string(res);
155 | end;
156 |
157 | { TTSQueryCursor }
158 |
159 | constructor TTSQueryCursor.Create;
160 | begin
161 | FQueryCursor:= ts_query_cursor_new;
162 | end;
163 |
164 | destructor TTSQueryCursor.Destroy;
165 | begin
166 | ts_query_cursor_delete(FQueryCursor);
167 | inherited;
168 | end;
169 |
170 | function TTSQueryCursor.DidExceedMatchLimit: Boolean;
171 | begin
172 | Result:= ts_query_cursor_did_exceed_match_limit(FQueryCursor);
173 | end;
174 |
175 | procedure TTSQueryCursor.Execute(AQuery: TTSQuery; ANode: TTSNode);
176 | begin
177 | ts_query_cursor_exec(FQueryCursor, AQuery.Query, ANode);
178 | end;
179 |
180 | function TTSQueryCursor.GetMatchLimit: UInt32;
181 | begin
182 | Result:= ts_query_cursor_match_limit(FQueryCursor);
183 | end;
184 |
185 | function TTSQueryCursor.NextCapture(var AMatch: TTSQueryMatch;
186 | var ACaptureIndex: UInt32): Boolean;
187 | begin
188 | Result:= ts_query_cursor_next_capture(FQueryCursor, AMatch, ACaptureIndex);
189 | end;
190 |
191 | function TTSQueryCursor.NextMatch(var AMatch: TTSQueryMatch): Boolean;
192 | begin
193 | Result:= ts_query_cursor_next_match(FQueryCursor, AMatch);
194 | end;
195 |
196 | procedure TTSQueryCursor.SetMatchLimit(const Value: UInt32);
197 | begin
198 | ts_query_cursor_set_match_limit(FQueryCursor, Value);
199 | end;
200 |
201 | procedure TTSQueryCursor.SetMaxStartDepth(AMaxStartDepth: UInt32);
202 | begin
203 | ts_query_cursor_set_max_start_depth(FQueryCursor, AMaxStartDepth);
204 | end;
205 |
206 | { TTSQueryMatchHelper }
207 |
208 | function TTSQueryMatchHelper.CapturesArray: TTSQueryCaptureArray;
209 | begin
210 | SetLength(Result, capture_count);
211 | if capture_count > 0 then
212 | Move(captures[0], Result[0], capture_count * SizeOf(captures[0]));
213 | end;
214 |
215 | end.
216 |
--------------------------------------------------------------------------------
/TreeSitter.pas:
--------------------------------------------------------------------------------
1 | unit TreeSitter;
2 |
3 | interface
4 |
5 | uses
6 | SysUtils,
7 | TreeSitterLib;
8 |
9 | type
10 | ETreeSitterException = Exception;
11 |
12 | //some aliases, so TreeSitterLib is not needed in uses clause
13 | PTSLanguage = TreeSitterLib.PTSLanguage;
14 | TTSLanguage = TSLanguage;
15 |
16 | TSFieldId = TreeSitterLib.TSFieldId;
17 | TSSymbol = TreeSitterLib.TSSymbol;
18 | TSSymbolType = TreeSitterLib.TSSymbolType;
19 |
20 | PTSGetLanguageFunc = ^TTSGetLanguageFunc;
21 | TTSGetLanguageFunc = function(): PTSLanguage; cdecl;
22 |
23 | TTSLanguageHelper = record helper for TTSLanguage
24 | private
25 | function GetFieldName(AFieldId: TSFieldId): string;
26 | function GetFieldId(const AFieldName: string): TSFieldId;
27 | function GetSymbolName(ASymbol: TSSymbol): string;
28 | function GetSymbolForName(const ASymbolName: string; AIsNamed: Boolean): TSSymbol;
29 | function GetSymbolType(ASymbol: TSSymbol): TSSymbolType;
30 | public
31 | function Version: UInt32;
32 | function FieldCount: UInt32;
33 | function SymbolCount: UInt32;
34 |
35 | function NextState(AState: TSStateId; ASymbol: TSSymbol): TSStateId;
36 |
37 | property FieldName[AFieldId: TSFieldId]: string read GetFieldName;
38 | property FieldId[const AFieldName: string]: TSFieldId read GetFieldId;
39 | property SymbolName[ASymbol: TSSymbol]: string read GetSymbolName;
40 | property SymbolForName[const ASymbolName: string; AIsNamed: Boolean]: TSSymbol read GetSymbolForName;
41 | property SymbolType[ASymbol: TSSymbol]: TSSymbolType read GetSymbolType;
42 | end;
43 |
44 | TTSTree = class;
45 | TTSNode = TSNode;
46 | TTSPoint = TSPoint;
47 |
48 | TTSInputEncoding = TreeSitterLib.TSInputEncoding;
49 |
50 | TTSParseReadFunction = reference to function (AByteIndex: UInt32; APosition: TTSPoint; var ABytesRead: UInt32): TBytes;
51 |
52 | TTSParser = class
53 | strict private
54 | FParser: PTSParser;
55 | function GetLanguage: PTSLanguage;
56 | procedure SetLanguage(const Value: PTSLanguage);
57 | public
58 | constructor Create; virtual;
59 | destructor Destroy; override;
60 |
61 | procedure Reset;
62 |
63 | function ParseString(const AString: string; const AOldTree: TTSTree = nil): TTSTree;
64 | function Parse(AParseReadFunction: TTSParseReadFunction;
65 | AEncoding: TTSInputEncoding; const AOldTree: TTSTree = nil): TTSTree;
66 |
67 | property Parser: PTSParser read FParser;
68 | property Language: PTSLanguage read GetLanguage write SetLanguage;
69 | end;
70 |
71 | TTSTree = class
72 | strict private
73 | FTree: PTSTree;
74 | public
75 | constructor Create(ATree: PTSTree); virtual;
76 | destructor Destroy; override;
77 |
78 | function Language: PTSLanguage;
79 | function RootNode: TTSNode;
80 | function TreeNilSafe: PTSTree;
81 | function Clone: TTSTree;
82 |
83 | property Tree: PTSTree read FTree;
84 | end;
85 |
86 | TTSTreeCursor = class
87 | strict private
88 | FTreeCursor: TSTreeCursor;
89 | function GetTreeCursor: PTSTreeCursor;
90 | function GetCurrentNode: TTSNode;
91 | function GetCurrentFieldName: string;
92 | function GetCurrentFieldId: TSFieldId;
93 | function GetCurrentDepth: UInt32;
94 | function GetCurrentDescendantIndex: UInt32;
95 | public
96 | constructor Create(ANode: TTSNode); overload; virtual;
97 | constructor Create(ACursorToCopy: TTSTreeCursor); overload; virtual;
98 | destructor Destroy; override;
99 |
100 | procedure Reset(ANode: TTSNode); overload;
101 | procedure Reset(ACursor: TTSTreeCursor); overload;
102 |
103 | function GotoParent: Boolean;
104 | function GotoNextSibling: Boolean;
105 | function GotoPrevSibling: Boolean;
106 | function GotoFirstChild: Boolean;
107 | function GotoLastChild: Boolean;
108 | procedure GotoDescendant(AGoalDescendantIndex: UInt32);
109 | function GotoFirstChildForGoal(AGoalByte: UInt32): Int64; overload;
110 | function GotoFirstChildForGoal(AGoalPoint: TTSPoint): Int64; overload;
111 |
112 | property TreeCursor: PTSTreeCursor read GetTreeCursor;
113 | property CurrentNode: TTSNode read GetCurrentNode;
114 | property CurrentFieldName: string read GetCurrentFieldName;
115 | property CurrentFieldId: TSFieldId read GetCurrentFieldId;
116 | property CurrentDescendantIndex: UInt32 read GetCurrentDescendantIndex;
117 | property CurrentDepth: UInt32 read GetCurrentDepth;
118 | end;
119 |
120 | TTSNodeHelper = record helper for TTSNode
121 | function Language: PTSLanguage;
122 |
123 | function NodeType: string;
124 | function Symbol: TSSymbol;
125 | function GrammarType: string;
126 | function GrammarSymbol: TSSymbol;
127 |
128 | function IsNull: Boolean;
129 | function IsError: Boolean;
130 | function HasError: Boolean;
131 | function HasChanges: Boolean;
132 | function IsExtra: Boolean;
133 | function IsMissing: Boolean;
134 | function IsNamed: Boolean;
135 | function Parent: TTSNode;
136 | function ToString: string;
137 |
138 | function ChildCount: Integer;
139 | function Child(AIndex: Integer): TTSNode;
140 | function NextSibling: TTSNode;
141 | function PrevSibling: TTSNode;
142 |
143 | function NamedChildCount: Integer;
144 | function NamedChild(AIndex: Integer): TTSNode;
145 | function NextNamedSibling: TTSNode;
146 | function PrevNamedSibling: TTSNode;
147 |
148 | function StartByte: UInt32;
149 | function StartPoint: TTSPoint;
150 | function EndByte: UInt32;
151 | function EndPoint: TTSPoint;
152 |
153 | function ChildByField(const AFieldName: string): TTSNode; overload;
154 | function ChildByField(const AFieldId: UInt32): TTSNode; overload;
155 |
156 | function DescendantCount: UInt32;
157 |
158 | class operator Equal(A: TTSNode; B: TTSNode): Boolean;
159 | end;
160 |
161 | TTSPointHelper = record helper for TTSPoint
162 | function ToString: string;
163 | end;
164 |
165 |
166 | implementation
167 |
168 | { TTSParser }
169 |
170 | constructor TTSParser.Create;
171 | begin
172 | FParser:= ts_parser_new;
173 | end;
174 |
175 | destructor TTSParser.Destroy;
176 | begin
177 | ts_parser_delete(FParser);
178 | inherited;
179 | end;
180 |
181 | function TTSParser.GetLanguage: PTSLanguage;
182 | begin
183 | Result:= ts_parser_language(FParser);
184 | end;
185 |
186 | type
187 | PTSInputReadPayLoad = ^TSInputReadPayLoad;
188 | TSInputReadPayLoad = record
189 | ParseReadFunction: TTSParseReadFunction;
190 | Buffer: TBytes;
191 | end;
192 |
193 | function TSInputRead(payload: Pointer; byte_index: UInt32; position: TSPoint; var bytes_read: UInt32): PAnsiChar; cdecl;
194 | begin
195 | PTSInputReadPayLoad(payload)^.Buffer:= PTSInputReadPayLoad(payload)^.ParseReadFunction(byte_index, position, bytes_read);
196 | if Length(PTSInputReadPayLoad(payload)^.Buffer) = 0 then
197 | Result:= nil else
198 | Result:= PAnsiChar(@PTSInputReadPayLoad(payload)^.Buffer[0]);
199 | end;
200 |
201 | function TTSParser.Parse(AParseReadFunction: TTSParseReadFunction;
202 | AEncoding: TTSInputEncoding; const AOldTree: TTSTree): TTSTree;
203 | var
204 | tsi: TSInput;
205 | payload: TSInputReadPayLoad;
206 | begin
207 | payload.ParseReadFunction:= AParseReadFunction;
208 | tsi.payload:= @payload;
209 | tsi.read:= TSInputRead;
210 | tsi.encoding:= AEncoding;
211 | Result:= TTSTree.Create(ts_parser_parse(FParser, AOldTree.TreeNilSafe, tsi));
212 | end;
213 |
214 | function TTSParser.ParseString(const AString: string;
215 | const AOldTree: TTSTree): TTSTree;
216 | var
217 | bytes: TBytes;
218 | tree: PTSTree;
219 | len: Integer;
220 | begin
221 | bytes:= TEncoding.Unicode.GetBytes(AString);
222 | len:= Length(bytes);
223 | if len > 0 then
224 | tree:= ts_parser_parse_string_encoding(FParser, AOldTree.TreeNilSafe,
225 | @bytes[0], len, TSInputEncodingUTF16) else
226 | raise ETreeSitterException.Create('Cannot parse empty string');
227 | if tree = nil then
228 | raise ETreeSitterException.Create('Faild to parse string');
229 | Result:= TTSTree.Create(tree);
230 | end;
231 |
232 | procedure TTSParser.Reset;
233 | begin
234 | ts_parser_reset(FParser);
235 | end;
236 |
237 | procedure TTSParser.SetLanguage(const Value: PTSLanguage);
238 | begin
239 | if not ts_parser_set_language(FParser, Value) then
240 | raise ETreeSitterException.CreateFmt('Failed to set parser language to 0x%p', [Value]);
241 | end;
242 |
243 | { TTSTree }
244 |
245 | function TTSTree.Clone: TTSTree;
246 | begin
247 | Result:= TTSTree.Create(ts_tree_copy(FTree));
248 | end;
249 |
250 | constructor TTSTree.Create(ATree: PTSTree);
251 | begin
252 | FTree:= ATree;
253 | end;
254 |
255 | destructor TTSTree.Destroy;
256 | begin
257 | if FTree <> nil then
258 | ts_tree_delete(FTree);
259 | inherited;
260 | end;
261 |
262 | function TTSTree.Language: PTSLanguage;
263 | begin
264 | Result:= ts_tree_language(FTree);
265 | end;
266 |
267 | function TTSTree.RootNode: TTSNode;
268 | begin
269 | Result:= ts_tree_root_node(FTree);
270 | end;
271 |
272 | function TTSTree.TreeNilSafe: PTSTree;
273 | begin
274 | if Self <> nil then
275 | Result:= FTree else
276 | Result:= nil;
277 | end;
278 |
279 | { TTSNodeHelper }
280 |
281 | function TTSNodeHelper.Child(AIndex: Integer): TTSNode;
282 | begin
283 | Result:= ts_node_child(Self, AIndex);
284 | end;
285 |
286 | function TTSNodeHelper.ChildByField(const AFieldId: UInt32): TTSNode;
287 | begin
288 | Result:= ts_node_child_by_field_id(Self, AFieldId);
289 | end;
290 |
291 | function TTSNodeHelper.ChildByField(const AFieldName: string): TTSNode;
292 | var
293 | ansiFieldName: AnsiString;
294 | begin
295 | ansiFieldName:= AnsiString(AFieldName);
296 | Result:= ts_node_child_by_field_name(Self, PAnsiChar(ansiFieldName), Length(ansiFieldName));
297 | end;
298 |
299 | function TTSNodeHelper.ChildCount: Integer;
300 | begin
301 | Result:= ts_node_child_count(Self);
302 | end;
303 |
304 | function TTSNodeHelper.DescendantCount: UInt32;
305 | begin
306 | Result:= ts_node_descendant_count(Self);
307 | end;
308 |
309 | function TTSNodeHelper.EndByte: UInt32;
310 | begin
311 | Result:= ts_node_end_byte(Self);
312 | end;
313 |
314 | function TTSNodeHelper.EndPoint: TTSPoint;
315 | begin
316 | {$IFDEF WIN32}
317 | Result:= TTSPoint(ts_node_end_point(Self));
318 | {$ELSE}
319 | Result:= ts_node_end_point(Self);
320 | {$ENDIF}
321 | end;
322 |
323 | class operator TTSNodeHelper.Equal(A, B: TTSNode): Boolean;
324 | begin
325 | Result:= ts_node_eq(A, B);
326 | end;
327 |
328 | function TTSNodeHelper.GrammarSymbol: TSSymbol;
329 | begin
330 | Result:= ts_node_grammar_symbol(Self);
331 | end;
332 |
333 | function TTSNodeHelper.GrammarType: string;
334 | begin
335 | Result:= string(AnsiString(ts_node_grammar_type(Self)));
336 | end;
337 |
338 | function TTSNodeHelper.HasChanges: Boolean;
339 | begin
340 | Result:= ts_node_has_changes(Self);
341 | end;
342 |
343 | function TTSNodeHelper.HasError: Boolean;
344 | begin
345 | Result:= ts_node_has_error(Self);
346 | end;
347 |
348 | function TTSNodeHelper.IsError: Boolean;
349 | begin
350 | Result:= ts_node_is_error(Self);
351 | end;
352 |
353 | function TTSNodeHelper.IsExtra: Boolean;
354 | begin
355 | Result:= ts_node_is_extra(Self);
356 | end;
357 |
358 | function TTSNodeHelper.IsMissing: Boolean;
359 | begin
360 | Result:= ts_node_is_missing(Self);
361 | end;
362 |
363 | function TTSNodeHelper.IsNamed: Boolean;
364 | begin
365 | Result:= ts_node_is_named(Self);
366 | end;
367 |
368 | function TTSNodeHelper.IsNull: Boolean;
369 | begin
370 | Result:= ts_node_is_null(Self);
371 | end;
372 |
373 | function TTSNodeHelper.Language: PTSLanguage;
374 | begin
375 | Result:= ts_node_language(Self);
376 | end;
377 |
378 | function TTSNodeHelper.NamedChild(AIndex: Integer): TTSNode;
379 | begin
380 | Result:= ts_node_named_child(Self, AIndex);
381 | end;
382 |
383 | function TTSNodeHelper.NamedChildCount: Integer;
384 | begin
385 | Result:= ts_node_named_child_count(Self);
386 | end;
387 |
388 | function TTSNodeHelper.NextNamedSibling: TTSNode;
389 | begin
390 | Result:= ts_node_next_named_sibling(Self);
391 | end;
392 |
393 | function TTSNodeHelper.NextSibling: TTSNode;
394 | begin
395 | Result:= ts_node_next_sibling(Self);
396 | end;
397 |
398 | function TTSNodeHelper.NodeType: string;
399 | begin
400 | Result:= string(AnsiString(ts_node_type(Self)));
401 | end;
402 |
403 | function TTSNodeHelper.Parent: TTSNode;
404 | begin
405 | Result:= ts_node_parent(Self);
406 | end;
407 |
408 | function TTSNodeHelper.PrevNamedSibling: TTSNode;
409 | begin
410 | Result:= ts_node_prev_named_sibling(Self);
411 | end;
412 |
413 | function TTSNodeHelper.PrevSibling: TTSNode;
414 | begin
415 | Result:= ts_node_prev_sibling(Self);
416 | end;
417 |
418 | function TTSNodeHelper.StartByte: UInt32;
419 | begin
420 | Result:= ts_node_start_byte(Self);
421 | end;
422 |
423 | function TTSNodeHelper.StartPoint: TTSPoint;
424 | begin
425 | {$IFDEF WIN32}
426 | Result:= TTSPoint(ts_node_start_point(Self));
427 | {$ELSE}
428 | Result:= ts_node_start_point(Self);
429 | {$ENDIF}
430 | end;
431 |
432 | function TTSNodeHelper.Symbol: TSSymbol;
433 | begin
434 | Result:= ts_node_symbol(Self);
435 | end;
436 |
437 | function TTSNodeHelper.ToString: string;
438 | var
439 | pach: PAnsiChar;
440 | begin
441 | pach:= ts_node_string(Self);
442 | Result:= string(AnsiString(pach));
443 | FreeMem(pach);
444 | end;
445 |
446 | { TTSPointHelper }
447 |
448 | function TTSPointHelper.ToString: string;
449 | begin
450 | Result:= Format('(%d, %d)', [row, column]);
451 | end;
452 |
453 | { TTSLanguageHelper }
454 |
455 | function TTSLanguageHelper.FieldCount: UInt32;
456 | begin
457 | Result:= ts_language_field_count(@Self);
458 | end;
459 |
460 | function TTSLanguageHelper.GetFieldId(const AFieldName: string): TSFieldId;
461 | var
462 | ansiFieldName: AnsiString;
463 | begin
464 | ansiFieldName:= AnsiString(AFieldName);
465 | Result:= ts_language_field_id_for_name(@Self, PAnsiChar(ansiFieldName), Length(ansiFieldName));
466 | end;
467 |
468 | function TTSLanguageHelper.GetFieldName(AFieldId: TSFieldId): string;
469 | begin
470 | Result:= string(AnsiString(ts_language_field_name_for_id(@Self, AFieldId)));
471 | end;
472 |
473 | function TTSLanguageHelper.GetSymbolForName(const ASymbolName: string; AIsNamed: Boolean): TSSymbol;
474 | var
475 | ansiSymbolName: AnsiString;
476 | begin
477 | ansiSymbolName:= AnsiString(ASymbolName);
478 | Result:= ts_language_symbol_for_name(@Self, PAnsiChar(ansiSymbolName), Length(ansiSymbolName), AIsNamed);
479 | end;
480 |
481 | function TTSLanguageHelper.GetSymbolName(ASymbol: TSSymbol): string;
482 | begin
483 | Result:= string(AnsiString(ts_language_symbol_name(@Self, ASymbol)));
484 | end;
485 |
486 | function TTSLanguageHelper.GetSymbolType(ASymbol: TSSymbol): TSSymbolType;
487 | begin
488 | Result:= ts_language_symbol_type(@Self, ASymbol);
489 | end;
490 |
491 | function TTSLanguageHelper.NextState(AState: TSStateId;
492 | ASymbol: TSSymbol): TSStateId;
493 | begin
494 | Result:= ts_language_next_state(@Self, AState, ASymbol);
495 | end;
496 |
497 | function TTSLanguageHelper.SymbolCount: UInt32;
498 | begin
499 | Result:= ts_language_symbol_count(@Self);
500 | end;
501 |
502 | function TTSLanguageHelper.Version: UInt32;
503 | begin
504 | Result:= ts_language_version(@Self);
505 | end;
506 |
507 | { TTSTreeCursor }
508 |
509 | constructor TTSTreeCursor.Create(ANode: TTSNode);
510 | begin
511 | FTreeCursor:= ts_tree_cursor_new(ANode);
512 | end;
513 |
514 | constructor TTSTreeCursor.Create(ACursorToCopy: TTSTreeCursor);
515 | begin
516 | FTreeCursor:= ts_tree_cursor_copy(ACursorToCopy.TreeCursor);
517 | end;
518 |
519 | destructor TTSTreeCursor.Destroy;
520 | begin
521 | ts_tree_cursor_delete(@FTreeCursor);
522 | FillChar(FTreeCursor, SizeOf(FTreeCursor), 0);
523 | inherited;
524 | end;
525 |
526 | function TTSTreeCursor.GetCurrentDepth: UInt32;
527 | begin
528 | Result:= ts_tree_cursor_current_depth(@FTreeCursor);
529 | end;
530 |
531 | function TTSTreeCursor.GetCurrentDescendantIndex: UInt32;
532 | begin
533 | Result:= ts_tree_cursor_current_descendant_index(@FTreeCursor);
534 | end;
535 |
536 | function TTSTreeCursor.GetCurrentFieldId: TSFieldId;
537 | begin
538 | Result:= ts_tree_cursor_current_field_id(@FTreeCursor);
539 | end;
540 |
541 | function TTSTreeCursor.GetCurrentFieldName: string;
542 | begin
543 | Result:= string(AnsiString(ts_tree_cursor_current_field_name(@FTreeCursor)));
544 | end;
545 |
546 | function TTSTreeCursor.GetCurrentNode: TTSNode;
547 | begin
548 | Result:= ts_tree_cursor_current_node(@FTreeCursor);
549 | end;
550 |
551 | function TTSTreeCursor.GetTreeCursor: PTSTreeCursor;
552 | begin
553 | Result:= @FTreeCursor;
554 | end;
555 |
556 | procedure TTSTreeCursor.GotoDescendant(AGoalDescendantIndex: UInt32);
557 | begin
558 | ts_tree_cursor_goto_descendant(@FTreeCursor, AGoalDescendantIndex);
559 | end;
560 |
561 | function TTSTreeCursor.GotoFirstChild: Boolean;
562 | begin
563 | Result:= ts_tree_cursor_goto_first_child(@FTreeCursor);
564 | end;
565 |
566 | function TTSTreeCursor.GotoFirstChildForGoal(AGoalPoint: TTSPoint): Int64;
567 | begin
568 | Result:= ts_tree_cursor_goto_first_child_for_point(@FTreeCursor, AGoalPoint);
569 | end;
570 |
571 | function TTSTreeCursor.GotoFirstChildForGoal(AGoalByte: UInt32): Int64;
572 | begin
573 | Result:= ts_tree_cursor_goto_first_child_for_byte(@FTreeCursor, AGoalByte);
574 | end;
575 |
576 | function TTSTreeCursor.GotoLastChild: Boolean;
577 | begin
578 | Result:= ts_tree_cursor_goto_last_child(@FTreeCursor);
579 | end;
580 |
581 | function TTSTreeCursor.GotoNextSibling: Boolean;
582 | begin
583 | Result:= ts_tree_cursor_goto_next_sibling(@FTreeCursor);
584 | end;
585 |
586 | function TTSTreeCursor.GotoParent: Boolean;
587 | begin
588 | Result:= ts_tree_cursor_goto_parent(@FTreeCursor);
589 | end;
590 |
591 | function TTSTreeCursor.GotoPrevSibling: Boolean;
592 | begin
593 | Result:= ts_tree_cursor_goto_previous_sibling(@FTreeCursor);
594 | end;
595 |
596 | procedure TTSTreeCursor.Reset(ACursor: TTSTreeCursor);
597 | begin
598 | ts_tree_cursor_reset_to(@FTreeCursor, ACursor.TreeCursor);
599 | end;
600 |
601 | procedure TTSTreeCursor.Reset(ANode: TTSNode);
602 | begin
603 | ts_tree_cursor_reset(@FTreeCursor, ANode);
604 | end;
605 |
606 | { memory management functions }
607 |
608 | function ts_malloc_func(sizeOf: NativeUInt): Pointer; cdecl;
609 | begin
610 | GetMem(Result, sizeOf);
611 | end;
612 |
613 | function ts_calloc_func(nitems: NativeUInt; size: NativeUInt): Pointer; cdecl;
614 | begin
615 | GetMem(Result, nitems * size);
616 | FillChar(Result^, nitems * size, 0);
617 | end;
618 |
619 | procedure ts_free_func(ptr: Pointer); cdecl;
620 | begin
621 | FreeMem(ptr);
622 | end;
623 |
624 | function ts_realloc_func(ptr: Pointer; sizeOf: NativeUInt): Pointer; cdecl;
625 | begin
626 | Result:= ptr;
627 | ReallocMem(Result, sizeOf);
628 | end;
629 |
630 | initialization
631 | //provide our own MM functions so we can free data allocated by TS with our FreeMem
632 | ts_set_allocator(@ts_malloc_func, @ts_calloc_func, @ts_realloc_func, @ts_free_func);
633 | finalization
634 | end.
635 |
--------------------------------------------------------------------------------
/TreeSitterLib.pas:
--------------------------------------------------------------------------------
1 | unit TreeSitterLib;
2 |
3 | (*
4 |
5 | Translation of tree-sitter's api.h, at their commit 09d2b23 from 2024-03-21
6 |
7 | Work in progress. The intention is to leave as much of the original .h unchanged,
8 | hence the - for Delphi - unusual comment styles
9 |
10 | *)
11 |
12 | //enforce Quad Word alignment in records
13 | {$A8}
14 |
15 | interface
16 |
17 | const
18 | ModuleName = 'tree-sitter';
19 |
20 | (*
21 | /****************************/
22 | /* Section - ABI Versioning */
23 | /****************************/
24 | /**
25 | * The latest ABI version that is supported by the current version of the
26 | * library. When Languages are generated by the Tree-sitter CLI, they are
27 | * assigned an ABI version number that corresponds to the current CLI version.
28 | * The Tree-sitter library is generally backwards-compatible with languages
29 | * generated using older CLI versions, but is not forwards-compatible.
30 | */
31 | *)
32 | const TREE_SITTER_LANGUAGE_VERSION = 14;
33 | (*
34 | /**
35 | * The earliest ABI version that is supported by the current version of the
36 | * library.
37 | */
38 | *)
39 | const TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION = 13;
40 | (*
41 | /*******************/
42 | /* Section - Types */
43 | /*******************/
44 | *)
45 | type
46 | TSStateId = UInt16;
47 | TSSymbol = UInt16;
48 | TSFieldId = UInt16;
49 | PTSLanguage = ^TSLanguage;
50 | TSLanguage = record end;
51 | PTSParser = ^TSParser;
52 | TSParser = record end;
53 | PTSTree = ^TSTree;
54 | TSTree = record end;
55 | PTSQuery = ^TSQuery;
56 | TSQuery = record end;
57 | PTSQueryCursor = ^TSQueryCursor;
58 | TSQueryCursor = record end;
59 | TSLookaheadIterator = record end;
60 |
61 | {$MINENUMSIZE 4}
62 | TSInputEncoding = (TSInputEncodingUTF8, TSInputEncodingUTF16);
63 |
64 | TSSymbolType = (TSSymbolTypeRegular, TSSymbolTypeAnonymous,
65 | TSSymbolTypeAuxiliary);
66 |
67 | TSPoint = record
68 | row: UInt32;
69 | column: UInt32;
70 | end;
71 | (*
72 | typedef struct TSRange {
73 | TSPoint start_point;
74 | TSPoint end_point;
75 | uint32_t start_byte;
76 | uint32_t end_byte;
77 | } TSRange;
78 | *)
79 | TSInput = record
80 | payload: Pointer;
81 | read: function (payload: Pointer; byte_index: UInt32; position: TSPoint; var bytes_read: UInt32): PAnsiChar; cdecl;
82 | encoding: TSInputEncoding;
83 | end;
84 | (*
85 | typedef enum TSLogType {
86 | TSLogTypeParse,
87 | TSLogTypeLex,
88 | } TSLogType;
89 | typedef struct TSLogger {
90 | void *payload;
91 | void (*log)(void *payload, TSLogType log_type, const char *buffer);
92 | } TSLogger;
93 | typedef struct TSInputEdit {
94 | uint32_t start_byte;
95 | uint32_t old_end_byte;
96 | uint32_t new_end_byte;
97 | TSPoint start_point;
98 | TSPoint old_end_point;
99 | TSPoint new_end_point;
100 | } TSInputEdit;
101 | *)
102 | TSNode = record
103 | context: array[1..4] of UInt32;
104 | id: Pointer;
105 | tree: PTSTree;
106 | end;
107 |
108 | PTSTreeCursor = ^TSTreeCursor;
109 | TSTreeCursor = record
110 | tree: PTSTree;
111 | id: Pointer;
112 | context: array[1..3] of UInt32;
113 | end;
114 |
115 | TSQueryCapture = record
116 | node: TSNode;
117 | index: UInt32;
118 | end;
119 |
120 | PSQueryCaptureArray = ^TSQueryCaptureArray;
121 | TSQueryCaptureArray = array[0..0] of TSQueryCapture;
122 |
123 | TSQuantifier = (
124 | TSQuantifierZero,// = 0, // must match the array initialization value
125 | TSQuantifierZeroOrOne,
126 | TSQuantifierZeroOrMore,
127 | TSQuantifierOne,
128 | TSQuantifierOneOrMore);
129 |
130 | TSQueryMatch = record
131 | id: UInt32;
132 | pattern_index: UInt16;
133 | capture_count: UInt16;
134 | captures: PSQueryCaptureArray;
135 | end;
136 |
137 | PTSQueryMatchArray = ^TSQueryMatchArray;
138 | TSQueryMatchArray = array[0..0] of TSQueryMatch;
139 |
140 | TSQueryPredicateStepType = (
141 | TSQueryPredicateStepTypeDone,
142 | TSQueryPredicateStepTypeCapture,
143 | TSQueryPredicateStepTypeString);
144 |
145 | TSQueryPredicateStep = record
146 | &type: TSQueryPredicateStepType;
147 | value_id: UInt32;
148 | end;
149 |
150 | PTSQueryPredicateStepArray = ^TSQueryPredicateStepArray;
151 | TSQueryPredicateStepArray = array[0..0] of TSQueryPredicateStep;
152 |
153 | TSQueryError = (
154 | TSQueryErrorNone,// = 0,
155 | TSQueryErrorSyntax,
156 | TSQueryErrorNodeType,
157 | TSQueryErrorField,
158 | TSQueryErrorCapture,
159 | TSQueryErrorStructure,
160 | TSQueryErrorLanguage);
161 |
162 | (*
163 | /********************/
164 | /* Section - Parser */
165 | /********************/
166 | /**
167 | * Create a new parser.
168 | */
169 | *)
170 | function ts_parser_new(): PTSParser; cdecl; external ModuleName;
171 | (*
172 | /**
173 | * Delete the parser, freeing all of the memory that it used.
174 | */
175 | *)
176 | procedure ts_parser_delete(self: PTSParser); cdecl; external ModuleName;
177 | (*
178 | /**
179 | * Get the parser's current language.
180 | */
181 | *)
182 | function ts_parser_language(self: PTSParser): PTSLanguage; cdecl; external ModuleName;
183 | (*
184 | /**
185 | * Set the language that the parser should use for parsing.
186 | *
187 | * Returns a boolean indicating whether or not the language was successfully
188 | * assigned. True means assignment succeeded. False means there was a version
189 | * mismatch: the language was generated with an incompatible version of the
190 | * Tree-sitter CLI. Check the language's version using [`ts_language_version`]
191 | * and compare it to this library's [`TREE_SITTER_LANGUAGE_VERSION`] and
192 | * [`TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION`] constants.
193 | */
194 | *)
195 | function ts_parser_set_language(self: PTSParser; language: PTSLanguage): Boolean; cdecl; external ModuleName;
196 | {
197 | /**
198 | * Set the ranges of text that the parser should include when parsing.
199 | *
200 | * By default, the parser will always include entire documents. This function
201 | * allows you to parse only a *portion* of a document but still return a syntax
202 | * tree whose ranges match up with the document as a whole. You can also pass
203 | * multiple disjoint ranges.
204 | *
205 | * The second and third parameters specify the location and length of an array
206 | * of ranges. The parser does *not* take ownership of these ranges; it copies
207 | * the data, so it doesn't matter how these ranges are allocated.
208 | *
209 | * If `count` is zero, then the entire document will be parsed. Otherwise,
210 | * the given ranges must be ordered from earliest to latest in the document,
211 | * and they must not overlap. That is, the following must hold for all:
212 | *
213 | * `i < count - 1`: `ranges[i].end_byte <= ranges[i + 1].start_byte`
214 | *
215 | * If this requirement is not satisfied, the operation will fail, the ranges
216 | * will not be assigned, and this function will return `false`. On success,
217 | * this function returns `true`
218 | */
219 | bool ts_parser_set_included_ranges(
220 | TSParser *self,
221 | const TSRange *ranges,
222 | uint32_t count
223 | );
224 | /**
225 | * Get the ranges of text that the parser will include when parsing.
226 | *
227 | * The returned pointer is owned by the parser. The caller should not free it
228 | * or write to it. The length of the array will be written to the given
229 | * `count` pointer.
230 | */
231 | const TSRange *ts_parser_included_ranges(
232 | const TSParser *self,
233 | uint32_t *count
234 | );
235 | }
236 | (*
237 | /**
238 | * Use the parser to parse some source code and create a syntax tree.
239 | *
240 | * If you are parsing this document for the first time, pass `NULL` for the
241 | * `old_tree` parameter. Otherwise, if you have already parsed an earlier
242 | * version of this document and the document has since been edited, pass the
243 | * previous syntax tree so that the unchanged parts of it can be reused.
244 | * This will save time and memory. For this to work correctly, you must have
245 | * already edited the old syntax tree using the [`ts_tree_edit`] function in a
246 | * way that exactly matches the source code changes.
247 | *
248 | * The [`TSInput`] parameter lets you specify how to read the text. It has the
249 | * following three fields:
250 | * 1. [`read`]: A function to retrieve a chunk of text at a given byte offset
251 | * and (row, column) position. The function should return a pointer to the
252 | * text and write its length to the [`bytes_read`] pointer. The parser does
253 | * not take ownership of this buffer; it just borrows it until it has
254 | * finished reading it. The function should write a zero value to the
255 | * [`bytes_read`] pointer to indicate the end of the document.
256 | * 2. [`payload`]: An arbitrary pointer that will be passed to each invocation
257 | * of the [`read`] function.
258 | * 3. [`encoding`]: An indication of how the text is encoded. Either
259 | * `TSInputEncodingUTF8` or `TSInputEncodingUTF16`.
260 | *
261 | * This function returns a syntax tree on success, and `NULL` on failure. There
262 | * are three possible reasons for failure:
263 | * 1. The parser does not have a language assigned. Check for this using the
264 | [`ts_parser_language`] function.
265 | * 2. Parsing was cancelled due to a timeout that was set by an earlier call to
266 | * the [`ts_parser_set_timeout_micros`] function. You can resume parsing from
267 | * where the parser left out by calling [`ts_parser_parse`] again with the
268 | * same arguments. Or you can start parsing from scratch by first calling
269 | * [`ts_parser_reset`].
270 | * 3. Parsing was cancelled using a cancellation flag that was set by an
271 | * earlier call to [`ts_parser_set_cancellation_flag`]. You can resume parsing
272 | * from where the parser left out by calling [`ts_parser_parse`] again with
273 | * the same arguments.
274 | *
275 | * [`read`]: TSInput::read
276 | * [`payload`]: TSInput::payload
277 | * [`encoding`]: TSInput::encoding
278 | * [`bytes_read`]: TSInput::read
279 | */
280 | *)
281 | function ts_parser_parse(
282 | self: PTSParser;
283 | const old_tree: PTSTree;
284 | input: TSInput
285 | ): PTSTree; cdecl; external ModuleName;
286 | (*
287 | /**
288 | * Use the parser to parse some source code stored in one contiguous buffer.
289 | * The first two parameters are the same as in the [`ts_parser_parse`] function
290 | * above. The second two parameters indicate the location of the buffer and its
291 | * length in bytes.
292 | */
293 | *)
294 | function ts_parser_parse_string(
295 | self: PTSParser;
296 | old_tree: PTSTree;
297 | _string: PAnsiChar;
298 | length: UInt32
299 | ): PTSTree; cdecl; external ModuleName;
300 | (*
301 | /**
302 | * Use the parser to parse some source code stored in one contiguous buffer with
303 | * a given encoding. The first four parameters work the same as in the
304 | * [`ts_parser_parse_string`] method above. The final parameter indicates whether
305 | * the text is encoded as UTF8 or UTF16.
306 | */
307 | *)
308 | function ts_parser_parse_string_encoding(
309 | self: PTSParser;
310 | old_tree: PTSTree;
311 | _string: PByte;
312 | length: UInt32;
313 | encoding: TSInputEncoding
314 | ): PTSTree; cdecl; external ModuleName;
315 | (*
316 | /**
317 | * Instruct the parser to start the next parse from the beginning.
318 | *
319 | * If the parser previously failed because of a timeout or a cancellation, then
320 | * by default, it will resume where it left off on the next call to
321 | * [`ts_parser_parse`] or other parsing functions. If you don't want to resume,
322 | * and instead intend to use this parser to parse some other document, you must
323 | * call [`ts_parser_reset`] first.
324 | */
325 | *)
326 | procedure ts_parser_reset(self: PTSParser); cdecl; external ModuleName;
327 | (*
328 | /**
329 | * Set the maximum duration in microseconds that parsing should be allowed to
330 | * take before halting.
331 | *
332 | * If parsing takes longer than this, it will halt early, returning NULL.
333 | * See [`ts_parser_parse`] for more information.
334 | */
335 | void ts_parser_set_timeout_micros(TSParser *self, uint64_t timeout_micros);
336 | /**
337 | * Get the duration in microseconds that parsing is allowed to take.
338 | */
339 | uint64_t ts_parser_timeout_micros(const TSParser *self);
340 | /**
341 | * Set the parser's current cancellation flag pointer.
342 | *
343 | * If a non-null pointer is assigned, then the parser will periodically read
344 | * from this pointer during parsing. If it reads a non-zero value, it will
345 | * halt early, returning NULL. See [`ts_parser_parse`] for more information.
346 | */
347 | void ts_parser_set_cancellation_flag(TSParser *self, const size_t *flag);
348 | /**
349 | * Get the parser's current cancellation flag pointer.
350 | */
351 | const size_t *ts_parser_cancellation_flag(const TSParser *self);
352 | /**
353 | * Set the logger that a parser should use during parsing.
354 | *
355 | * The parser does not take ownership over the logger payload. If a logger was
356 | * previously assigned, the caller is responsible for releasing any memory
357 | * owned by the previous logger.
358 | */
359 | void ts_parser_set_logger(TSParser *self, TSLogger logger);
360 | /**
361 | * Get the parser's current logger.
362 | */
363 | TSLogger ts_parser_logger(const TSParser *self);
364 | /**
365 | * Set the file descriptor to which the parser should write debugging graphs
366 | * during parsing. The graphs are formatted in the DOT language. You may want
367 | * to pipe these graphs directly to a `dot(1)` process in order to generate
368 | * SVG output. You can turn off this logging by passing a negative number.
369 | */
370 | void ts_parser_print_dot_graphs(TSParser *self, int fd);
371 | *)
372 | (*
373 | /******************/
374 | /* Section - Tree */
375 | /******************/
376 | /**
377 | * Create a shallow copy of the syntax tree. This is very fast.
378 | *
379 | * You need to copy a syntax tree in order to use it on more than one thread at
380 | * a time, as syntax trees are not thread safe.
381 | */
382 | *)
383 | function ts_tree_copy(const self: PTSTree): PTSTree; cdecl; external ModuleName;
384 | (*
385 | /**
386 | * Delete the syntax tree, freeing all of the memory that it used.
387 | */
388 | *)
389 | procedure ts_tree_delete(self: PTSTree); cdecl; external ModuleName;
390 | (*
391 | /**
392 | * Get the root node of the syntax tree.
393 | */
394 | *)
395 | function ts_tree_root_node(self: PTSTree): TSNode; cdecl; external ModuleName;
396 | (*
397 | /**
398 | * Get the root node of the syntax tree, but with its position
399 | * shifted forward by the given offset.
400 | */
401 | TSNode ts_tree_root_node_with_offset(
402 | const TSTree *self,
403 | uint32_t offset_bytes,
404 | TSPoint offset_extent
405 | );
406 | *)
407 | (*
408 | /**
409 | * Get the language that was used to parse the syntax tree.
410 | */
411 | *)
412 | function ts_tree_language(const self: PTSTree): PTSLanguage; cdecl; external ModuleName;
413 | (*
414 | /**
415 | * Get the array of included ranges that was used to parse the syntax tree.
416 | *
417 | * The returned pointer must be freed by the caller.
418 | */
419 | TSRange *ts_tree_included_ranges(const TSTree *self, uint32_t *length);
420 | /**
421 | * Edit the syntax tree to keep it in sync with source code that has been
422 | * edited.
423 | *
424 | * You must describe the edit both in terms of byte offsets and in terms of
425 | * (row, column) coordinates.
426 | */
427 | void ts_tree_edit(TSTree *self, const TSInputEdit *edit);
428 | /**
429 | * Compare an old edited syntax tree to a new syntax tree representing the same
430 | * document, returning an array of ranges whose syntactic structure has changed.
431 | *
432 | * For this to work correctly, the old syntax tree must have been edited such
433 | * that its ranges match up to the new tree. Generally, you'll want to call
434 | * this function right after calling one of the [`ts_parser_parse`] functions.
435 | * You need to pass the old tree that was passed to parse, as well as the new
436 | * tree that was returned from that function.
437 | *
438 | * The returned array is allocated using `malloc` and the caller is responsible
439 | * for freeing it using `free`. The length of the array will be written to the
440 | * given `length` pointer.
441 | */
442 | TSRange *ts_tree_get_changed_ranges(
443 | const TSTree *old_tree,
444 | const TSTree *new_tree,
445 | uint32_t *length
446 | );
447 | /**
448 | * Write a DOT graph describing the syntax tree to the given file.
449 | */
450 | void ts_tree_print_dot_graph(const TSTree *self, int file_descriptor);
451 | *)
452 | (*
453 | /******************/
454 | /* Section - Node */
455 | /******************/
456 | /**
457 | * Get the node's type as a null-terminated string.
458 | */
459 | *)
460 | function ts_node_type(self: TSNode): PAnsiChar; cdecl; external ModuleName;
461 | (*
462 | /**
463 | * Get the node's type as a numerical id.
464 | */
465 | *)
466 | function ts_node_symbol(self: TSNode): TSSymbol; cdecl; external ModuleName;
467 | (*
468 | /**
469 | * Get the node's language.
470 | */
471 | *)
472 | function ts_node_language(self: TSNode): PTSLanguage; cdecl; external ModuleName;
473 | (*
474 | /**
475 | * Get the node's type as it appears in the grammar ignoring aliases as a
476 | * null-terminated string.
477 | */
478 | *)
479 | function ts_node_grammar_type(self: TSNode): PAnsiChar; cdecl; external ModuleName;
480 | (*
481 | /**
482 | * Get the node's type as a numerical id as it appears in the grammar ignoring
483 | * aliases. This should be used in [`ts_language_next_state`] instead of
484 | * [`ts_node_symbol`].
485 | */
486 | *)
487 | function ts_node_grammar_symbol(self: TSNode): TSSymbol; cdecl; external ModuleName;
488 | (*
489 | /**
490 | * Get the node's start byte.
491 | */
492 | *)
493 | function ts_node_start_byte(self: TSNode): UInt32; cdecl; external ModuleName;
494 | (*
495 | /**
496 | * Get the node's start position in terms of rows and columns.
497 | */
498 | *)
499 | {$IFDEF WIN32}
500 | //the returned struct TSPoint is 8-byte in size and should be returned in EDX:EAX
501 | //which Delphi does only for Int64 according to the Language Guide
502 | //https://stackoverflow.com/a/16119171/386473
503 | function ts_node_start_point(self: TSNode): Int64; cdecl; external ModuleName;
504 | {$ELSE}
505 | function ts_node_start_point(self: TSNode): TSPoint; cdecl; external ModuleName;
506 | {$ENDIF}
507 | (*
508 | /**
509 | * Get the node's end byte.
510 | */
511 | *)
512 | function ts_node_end_byte(self: TSNode): UInt32; cdecl; external ModuleName;
513 | (*
514 | /**
515 | * Get the node's end position in terms of rows and columns.
516 | */
517 | *)
518 | {$IFDEF WIN32}
519 | //the returned struct TSPoint is 8-byte in size and should be returned in EDX:EAX
520 | //which Delphi does only for Int64 according to the Language Guide
521 | //https://stackoverflow.com/a/16119171/386473
522 | function ts_node_end_point(self: TSNode): Int64; cdecl; external ModuleName;
523 | {$ELSE}
524 | function ts_node_end_point(self: TSNode): TSPoint; cdecl; external ModuleName;
525 | {$ENDIF}
526 | (*
527 | /**
528 | * Get an S-expression representing the node as a string.
529 | *
530 | * This string is allocated with `malloc` and the caller is responsible for
531 | * freeing it using `free`.
532 | */
533 | *)
534 | function ts_node_string(self: TSNode): PAnsiChar; cdecl; external ModuleName;
535 | (*
536 | /**
537 | * Check if the node is null. Functions like [`ts_node_child`] and
538 | * [`ts_node_next_sibling`] will return a null node to indicate that no such node
539 | * was found.
540 | */
541 | *)
542 | function ts_node_is_null(self: TSNode): Boolean; cdecl; external ModuleName;
543 | (*
544 | /**
545 | * Check if the node is *named*. Named nodes correspond to named rules in the
546 | * grammar, whereas *anonymous* nodes correspond to string literals in the
547 | * grammar.
548 | */
549 | *)
550 | function ts_node_is_named(self: TSNode): Boolean; cdecl; external ModuleName;
551 | (*
552 | /**
553 | * Check if the node is *missing*. Missing nodes are inserted by the parser in
554 | * order to recover from certain kinds of syntax errors.
555 | */
556 | *)
557 | function ts_node_is_missing(self: TSNode): Boolean; cdecl; external ModuleName;
558 | (*
559 | /**
560 | * Check if the node is *extra*. Extra nodes represent things like comments,
561 | * which are not required the grammar, but can appear anywhere.
562 | */
563 | *)
564 | function ts_node_is_extra(self: TSNode): Boolean; cdecl; external ModuleName;
565 | (*
566 | /**
567 | * Check if a syntax node has been edited.
568 | */
569 | *)
570 | function ts_node_has_changes(self: TSNode): Boolean; cdecl; external ModuleName;
571 | (*
572 | /**
573 | * Check if the node is a syntax error or contains any syntax errors.
574 | */
575 | *)
576 | function ts_node_has_error(self: TSNode): Boolean; cdecl; external ModuleName;
577 | (*
578 | /**
579 | * Check if the node is a syntax error.
580 | */
581 | *)
582 | function ts_node_is_error(self: TSNode): Boolean; cdecl; external ModuleName;
583 | (*
584 | /**
585 | * Get this node's parse state.
586 | */
587 | TSStateId ts_node_parse_state(TSNode self);
588 | /**
589 | * Get the parse state after this node.
590 | */
591 | TSStateId ts_node_next_parse_state(TSNode self);
592 | *)
593 | (*
594 | /**
595 | * Get the node's immediate parent.
596 | */
597 | *)
598 | function ts_node_parent(self: TSNode): TSNode; cdecl; external ModuleName;
599 | (*
600 | /**
601 | * Get the node's child at the given index, where zero represents the first
602 | * child.
603 | */
604 | *)
605 | function ts_node_child(self: TSNode; child_index: UInt32): TSNode; cdecl; external ModuleName;
606 | (*
607 | /**
608 | * Get the field name for node's child at the given index, where zero represents
609 | * the first child. Returns NULL, if no field is found.
610 | */
611 | const char *ts_node_field_name_for_child(TSNode self, uint32_t child_index);
612 | *)
613 | (*
614 | /**
615 | * Get the node's number of children.
616 | */
617 | *)
618 | function ts_node_child_count(self: TSNode): UInt32; cdecl; external ModuleName;
619 | (*
620 | /**
621 | * Get the node's *named* child at the given index.
622 | *
623 | * See also [`ts_node_is_named`].
624 | */
625 | *)
626 | function ts_node_named_child(self: TSNode; child_index: UInt32): TSNode; cdecl; external ModuleName;
627 | (*
628 | /**
629 | * Get the node's number of *named* children.
630 | *
631 | * See also [`ts_node_is_named`].
632 | */
633 | *)
634 | function ts_node_named_child_count(self: TSNode): UInt32; cdecl; external ModuleName;
635 | (*
636 | /**
637 | * Get the node's child with the given field name.
638 | */
639 | *)
640 | function ts_node_child_by_field_name(
641 | self: TSNode;
642 | const name: PAnsiChar;
643 | name_length: UInt32
644 | ): TSNode; cdecl; external ModuleName;
645 | (*
646 | /**
647 | * Get the node's child with the given numerical field id.
648 | *
649 | * You can convert a field name to an id using the
650 | * [`ts_language_field_id_for_name`] function.
651 | */
652 | *)
653 | function ts_node_child_by_field_id(self: TSNode; field_id: TSFieldId): TSNode; cdecl; external ModuleName;
654 | (*
655 | /**
656 | * Get the node's next / previous sibling.
657 | */
658 | *)
659 | function ts_node_next_sibling(self: TSNode): TSNode; cdecl; external ModuleName;
660 | function ts_node_prev_sibling(self: TSNode): TSNode; cdecl; external ModuleName;
661 | (*
662 | /**
663 | * Get the node's next / previous *named* sibling.
664 | */
665 | *)
666 | function ts_node_next_named_sibling(self: TSNode): TSNode; cdecl; external ModuleName;
667 | function ts_node_prev_named_sibling(self: TSNode): TSNode; cdecl; external ModuleName;
668 | (*
669 | /**
670 | * Get the node's first child that extends beyond the given byte offset.
671 | */
672 | TSNode ts_node_first_child_for_byte(TSNode self, uint32_t byte);
673 | /**
674 | * Get the node's first named child that extends beyond the given byte offset.
675 | */
676 | TSNode ts_node_first_named_child_for_byte(TSNode self, uint32_t byte);
677 | *)
678 | (*
679 | /**
680 | * Get the node's number of descendants, including one for the node itself.
681 | */
682 | *)
683 | function ts_node_descendant_count(self: TSNode): UInt32; cdecl; external ModuleName;
684 | (*
685 | /**
686 | * Get the smallest node within this node that spans the given range of bytes
687 | * or (row, column) positions.
688 | */
689 | TSNode ts_node_descendant_for_byte_range(TSNode self, uint32_t start, uint32_t end);
690 | TSNode ts_node_descendant_for_point_range(TSNode self, TSPoint start, TSPoint end);
691 | /**
692 | * Get the smallest named node within this node that spans the given range of
693 | * bytes or (row, column) positions.
694 | */
695 | TSNode ts_node_named_descendant_for_byte_range(TSNode self, uint32_t start, uint32_t end);
696 | TSNode ts_node_named_descendant_for_point_range(TSNode self, TSPoint start, TSPoint end);
697 | /**
698 | * Edit the node to keep it in-sync with source code that has been edited.
699 | *
700 | * This function is only rarely needed. When you edit a syntax tree with the
701 | * [`ts_tree_edit`] function, all of the nodes that you retrieve from the tree
702 | * afterward will already reflect the edit. You only need to use [`ts_node_edit`]
703 | * when you have a [`TSNode`] instance that you want to keep and continue to use
704 | * after an edit.
705 | */
706 | void ts_node_edit(TSNode *self, const TSInputEdit *edit);
707 | *)
708 | (*
709 | /**
710 | * Check if two nodes are identical.
711 | */
712 | *)
713 | function ts_node_eq(self, other: TSNode): Boolean; cdecl; external ModuleName;
714 | (*
715 | /************************/
716 | /* Section - TreeCursor */
717 | /************************/
718 | /**
719 | * Create a new tree cursor starting from the given node.
720 | *
721 | * A tree cursor allows you to walk a syntax tree more efficiently than is
722 | * possible using the [`TSNode`] functions. It is a mutable object that is always
723 | * on a certain syntax node, and can be moved imperatively to different nodes.
724 | */
725 | *)
726 | function ts_tree_cursor_new(node: TSNode): TSTreeCursor; cdecl; external ModuleName;
727 | (*
728 | /**
729 | * Delete a tree cursor, freeing all of the memory that it used.
730 | */
731 | *)
732 | procedure ts_tree_cursor_delete(self: PTSTreeCursor); cdecl; external ModuleName;
733 | (*
734 | /**
735 | * Re-initialize a tree cursor to start at a different node.
736 | */
737 | *)
738 | procedure ts_tree_cursor_reset(Self: PTSTreeCursor; node: TSNode); cdecl; external ModuleName;
739 | (*
740 | /**
741 | * Re-initialize a tree cursor to the same position as another cursor.
742 | *
743 | * Unlike [`ts_tree_cursor_reset`], this will not lose parent information and
744 | * allows reusing already created cursors.
745 | */
746 | *)
747 | procedure ts_tree_cursor_reset_to(dst: PTSTreeCursor; const src: PTSTreeCursor); cdecl; external ModuleName;
748 | (*
749 | /**
750 | * Get the tree cursor's current node.
751 | */
752 | *)
753 | function ts_tree_cursor_current_node(const self: PTSTreeCursor): TSNode; cdecl; external ModuleName;
754 | (*
755 | /**
756 | * Get the field name of the tree cursor's current node.
757 | *
758 | * This returns `NULL` if the current node doesn't have a field.
759 | * See also [`ts_node_child_by_field_name`].
760 | */
761 | *)
762 | function ts_tree_cursor_current_field_name(const self: PTSTreeCursor): PAnsiChar; cdecl; external ModuleName;
763 | (*
764 | /**
765 | * Get the field id of the tree cursor's current node.
766 | *
767 | * This returns zero if the current node doesn't have a field.
768 | * See also [`ts_node_child_by_field_id`], [`ts_language_field_id_for_name`].
769 | */
770 | *)
771 | function ts_tree_cursor_current_field_id(const self: PTSTreeCursor): TSFieldId; cdecl; external ModuleName;
772 | (*
773 | /**
774 | * Move the cursor to the parent of its current node.
775 | *
776 | * This returns `true` if the cursor successfully moved, and returns `false`
777 | * if there was no parent node (the cursor was already on the root node).
778 | */
779 | *)
780 | function ts_tree_cursor_goto_parent(self: PTSTreeCursor): Boolean; cdecl; external ModuleName;
781 | (*
782 | /**
783 | * Move the cursor to the next sibling of its current node.
784 | *
785 | * This returns `true` if the cursor successfully moved, and returns `false`
786 | * if there was no next sibling node.
787 | */
788 | *)
789 | function ts_tree_cursor_goto_next_sibling(self: PTSTreeCursor): Boolean; cdecl; external ModuleName;
790 | (*
791 | /**
792 | * Move the cursor to the previous sibling of its current node.
793 | *
794 | * This returns `true` if the cursor successfully moved, and returns `false` if
795 | * there was no previous sibling node.
796 | *
797 | * Note, that this function may be slower than
798 | * [`ts_tree_cursor_goto_next_sibling`] due to how node positions are stored. In
799 | * the worst case, this will need to iterate through all the children upto the
800 | * previous sibling node to recalculate its position.
801 | */
802 | *)
803 | function ts_tree_cursor_goto_previous_sibling(self: PTSTreeCursor): Boolean; cdecl; external ModuleName;
804 | (*
805 | /**
806 | * Move the cursor to the first child of its current node.
807 | *
808 | * This returns `true` if the cursor successfully moved, and returns `false`
809 | * if there were no children.
810 | */
811 | *)
812 | function ts_tree_cursor_goto_first_child(self: PTSTreeCursor): Boolean; cdecl; external ModuleName;
813 | (*
814 | /**
815 | * Move the cursor to the last child of its current node.
816 | *
817 | * This returns `true` if the cursor successfully moved, and returns `false` if
818 | * there were no children.
819 | *
820 | * Note that this function may be slower than [`ts_tree_cursor_goto_first_child`]
821 | * because it needs to iterate through all the children to compute the child's
822 | * position.
823 | */
824 | *)
825 | function ts_tree_cursor_goto_last_child(self: PTSTreeCursor): Boolean; cdecl; external ModuleName;
826 | (*
827 | /**
828 | * Move the cursor to the node that is the nth descendant of
829 | * the original node that the cursor was constructed with, where
830 | * zero represents the original node itself.
831 | */
832 | *)
833 | procedure ts_tree_cursor_goto_descendant(self: PTSTreeCursor; goal_descendant_index: UInt32); cdecl; external ModuleName;
834 | (*
835 | /**
836 | * Get the index of the cursor's current node out of all of the
837 | * descendants of the original node that the cursor was constructed with.
838 | */
839 | *)
840 | function ts_tree_cursor_current_descendant_index(const self: PTSTreeCursor): UInt32; cdecl; external ModuleName;
841 | (*
842 | /**
843 | * Get the depth of the cursor's current node relative to the original
844 | * node that the cursor was constructed with.
845 | */
846 | *)
847 | function ts_tree_cursor_current_depth(const self: PTSTreeCursor): UInt32; cdecl; external ModuleName;
848 | (*
849 | /**
850 | * Move the cursor to the first child of its current node that extends beyond
851 | * the given byte offset or point.
852 | *
853 | * This returns the index of the child node if one was found, and returns -1
854 | * if no such child was found.
855 | */
856 | *)
857 | function ts_tree_cursor_goto_first_child_for_byte(self: PTSTreeCursor; goal_byte: UInt32): Int64; cdecl; external ModuleName;
858 | function ts_tree_cursor_goto_first_child_for_point(self: PTSTreeCursor; goal_point: TSPoint): Int64; cdecl; external ModuleName;
859 |
860 | function ts_tree_cursor_copy(const cursor: PTSTreeCursor): TSTreeCursor; cdecl; external ModuleName;
861 | (*
862 | /*******************/
863 | /* Section - Query */
864 | /*******************/
865 | /**
866 | * Create a new query from a string containing one or more S-expression
867 | * patterns. The query is associated with a particular language, and can
868 | * only be run on syntax nodes parsed with that language.
869 | *
870 | * If all of the given patterns are valid, this returns a [`TSQuery`].
871 | * If a pattern is invalid, this returns `NULL`, and provides two pieces
872 | * of information about the problem:
873 | * 1. The byte offset of the error is written to the `error_offset` parameter.
874 | * 2. The type of error is written to the `error_type` parameter.
875 | */
876 | *)
877 | function ts_query_new(
878 | const language: PTSLanguage;
879 | const source: PAnsiChar;
880 | source_len: UInt32;
881 | var error_offset: UInt32;
882 | var error_type: TSQueryError): PTSQuery; cdecl; external ModuleName;
883 | (*
884 | /**
885 | * Delete a query, freeing all of the memory that it used.
886 | */
887 | *)
888 | procedure ts_query_delete(self: PTSQuery); cdecl; external ModuleName;
889 | (*
890 | /**
891 | * Get the number of patterns, captures, or string literals in the query.
892 | */
893 | *)
894 | function ts_query_pattern_count(const self: PTSQuery): UInt32; cdecl; external ModuleName;
895 | function ts_query_capture_count(const self: PTSQuery): UInt32; cdecl; external ModuleName;
896 | function ts_query_string_count(const self: PTSQuery): UInt32; cdecl; external ModuleName;
897 | (*
898 | /**
899 | * Get the byte offset where the given pattern starts in the query's source.
900 | *
901 | * This can be useful when combining queries by concatenating their source
902 | * code strings.
903 | */
904 | *)
905 | function ts_query_start_byte_for_pattern(const self: PTSQuery; pattern_index: UInt32): UInt32; cdecl; external ModuleName;
906 | (*
907 | /**
908 | * Get all of the predicates for the given pattern in the query.
909 | *
910 | * The predicates are represented as a single array of steps. There are three
911 | * types of steps in this array, which correspond to the three legal values for
912 | * the `type` field:
913 | * - `TSQueryPredicateStepTypeCapture` - Steps with this type represent names
914 | * of captures. Their `value_id` can be used with the
915 | * [`ts_query_capture_name_for_id`] function to obtain the name of the capture.
916 | * - `TSQueryPredicateStepTypeString` - Steps with this type represent literal
917 | * strings. Their `value_id` can be used with the
918 | * [`ts_query_string_value_for_id`] function to obtain their string value.
919 | * - `TSQueryPredicateStepTypeDone` - Steps with this type are *sentinels*
920 | * that represent the end of an individual predicate. If a pattern has two
921 | * predicates, then there will be two steps with this `type` in the array.
922 | */
923 | *)
924 | function ts_query_predicates_for_pattern(
925 | const self: PTSQuery;
926 | pattern_index: UInt32;
927 | var step_count: UInt32
928 | ): PTSQueryPredicateStepArray; cdecl; external ModuleName;
929 | (*
930 | /*
931 | * Check if the given pattern in the query has a single root node.
932 | */
933 | bool ts_query_is_pattern_rooted(const TSQuery *self, uint32_t pattern_index);
934 | /*
935 | * Check if the given pattern in the query is 'non local'.
936 | *
937 | * A non-local pattern has multiple root nodes and can match within a
938 | * repeating sequence of nodes, as specified by the grammar. Non-local
939 | * patterns disable certain optimizations that would otherwise be possible
940 | * when executing a query on a specific range of a syntax tree.
941 | */
942 | bool ts_query_is_pattern_non_local(const TSQuery *self, uint32_t pattern_index);
943 | /*
944 | * Check if a given pattern is guaranteed to match once a given step is reached.
945 | * The step is specified by its byte offset in the query's source code.
946 | */
947 | bool ts_query_is_pattern_guaranteed_at_step(const TSQuery *self, uint32_t byte_offset);
948 | *)
949 | (*
950 | /**
951 | * Get the name and length of one of the query's captures, or one of the
952 | * query's string literals. Each capture and string is associated with a
953 | * numeric id based on the order that it appeared in the query's source.
954 | */
955 | *)
956 | function ts_query_capture_name_for_id(
957 | const self: PTSQuery;
958 | index: UInt32;
959 | var length: UInt32
960 | ): PAnsiChar; cdecl; external ModuleName;
961 | (*
962 | /**
963 | * Get the quantifier of the query's captures. Each capture is * associated
964 | * with a numeric id based on the order that it appeared in the query's source.
965 | */
966 | *)
967 | function ts_query_capture_quantifier_for_id(
968 | const self: PTSQuery;
969 | pattern_index: UInt32;
970 | capture_index: UInt32
971 | ): TSQuantifier; cdecl; external ModuleName;
972 |
973 | function ts_query_string_value_for_id(
974 | const self: PTSQuery;
975 | index: UInt32;
976 | var length: UInt32
977 | ): PAnsiChar; cdecl; external ModuleName;
978 | (*
979 | /**
980 | * Disable a certain capture within a query.
981 | *
982 | * This prevents the capture from being returned in matches, and also avoids
983 | * any resource usage associated with recording the capture. Currently, there
984 | * is no way to undo this.
985 | */
986 | void ts_query_disable_capture(TSQuery *self, const char *name, uint32_t length);
987 | /**
988 | * Disable a certain pattern within a query.
989 | *
990 | * This prevents the pattern from matching and removes most of the overhead
991 | * associated with the pattern. Currently, there is no way to undo this.
992 | */
993 | void ts_query_disable_pattern(TSQuery *self, uint32_t pattern_index);
994 | *)
995 | (*
996 | /**
997 | * Create a new cursor for executing a given query.
998 | *
999 | * The cursor stores the state that is needed to iteratively search
1000 | * for matches. To use the query cursor, first call [`ts_query_cursor_exec`]
1001 | * to start running a given query on a given syntax node. Then, there are
1002 | * two options for consuming the results of the query:
1003 | * 1. Repeatedly call [`ts_query_cursor_next_match`] to iterate over all of the
1004 | * *matches* in the order that they were found. Each match contains the
1005 | * index of the pattern that matched, and an array of captures. Because
1006 | * multiple patterns can match the same set of nodes, one match may contain
1007 | * captures that appear *before* some of the captures from a previous match.
1008 | * 2. Repeatedly call [`ts_query_cursor_next_capture`] to iterate over all of the
1009 | * individual *captures* in the order that they appear. This is useful if
1010 | * don't care about which pattern matched, and just want a single ordered
1011 | * sequence of captures.
1012 | *
1013 | * If you don't care about consuming all of the results, you can stop calling
1014 | * [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] at any point.
1015 | * You can then start executing another query on another node by calling
1016 | * [`ts_query_cursor_exec`] again.
1017 | */
1018 | *)
1019 | function ts_query_cursor_new: PTSQueryCursor; cdecl; external ModuleName;
1020 | (*
1021 | /**
1022 | * Delete a query cursor, freeing all of the memory that it used.
1023 | */
1024 | *)
1025 | procedure ts_query_cursor_delete(self: PTSQueryCursor); cdecl; external ModuleName;
1026 | (*
1027 | /**
1028 | * Start running a given query on a given node.
1029 | */
1030 | *)
1031 | procedure ts_query_cursor_exec(self: PTSQueryCursor; const query: PTSQuery; node: TSNode); cdecl; external ModuleName;
1032 | (*
1033 | /**
1034 | * Manage the maximum number of in-progress matches allowed by this query
1035 | * cursor.
1036 | *
1037 | * Query cursors have an optional maximum capacity for storing lists of
1038 | * in-progress captures. If this capacity is exceeded, then the
1039 | * earliest-starting match will silently be dropped to make room for further
1040 | * matches. This maximum capacity is optional — by default, query cursors allow
1041 | * any number of pending matches, dynamically allocating new space for them as
1042 | * needed as the query is executed.
1043 | */
1044 | *)
1045 | function ts_query_cursor_did_exceed_match_limit(const self: PTSQueryCursor): Boolean; cdecl; external ModuleName;
1046 | function ts_query_cursor_match_limit(const self: PTSQueryCursor): UInt32; cdecl; external ModuleName;
1047 | procedure ts_query_cursor_set_match_limit(self: PTSQueryCursor; limit: UInt32); cdecl; external ModuleName;
1048 | (*
1049 | /**
1050 | * Set the range of bytes or (row, column) positions in which the query
1051 | * will be executed.
1052 | */
1053 | void ts_query_cursor_set_byte_range(TSQueryCursor *self, uint32_t start_byte, uint32_t end_byte);
1054 | void ts_query_cursor_set_point_range(TSQueryCursor *self, TSPoint start_point, TSPoint end_point);
1055 | *)
1056 | (*
1057 | /**
1058 | * Advance to the next match of the currently running query.
1059 | *
1060 | * If there is a match, write it to `*match` and return `true`.
1061 | * Otherwise, return `false`.
1062 | */
1063 | *)
1064 | function ts_query_cursor_next_match(self: PTSQueryCursor; var match: TSQueryMatch): Boolean; cdecl; external ModuleName;
1065 | procedure ts_query_cursor_remove_match(self: PTSQueryCursor; match_id: UInt32); cdecl; external ModuleName;
1066 | (*
1067 | /**
1068 | * Advance to the next capture of the currently running query.
1069 | *
1070 | * If there is a capture, write its match to `*match` and its index within
1071 | * the matche's capture list to `*capture_index`. Otherwise, return `false`.
1072 | */
1073 | *)
1074 | function ts_query_cursor_next_capture(
1075 | self: PTSQueryCursor;
1076 | var match: TSQueryMatch;
1077 | var capture_index: UInt32
1078 | ): Boolean; cdecl; external ModuleName;
1079 | (*
1080 | /**
1081 | * Set the maximum start depth for a query cursor.
1082 | *
1083 | * This prevents cursors from exploring children nodes at a certain depth.
1084 | * Note if a pattern includes many children, then they will still be checked.
1085 | *
1086 | * The zero max start depth value can be used as a special behavior and
1087 | * it helps to destructure a subtree by staying on a node and using captures
1088 | * for interested parts. Note that the zero max start depth only limit a search
1089 | * depth for a pattern's root node but other nodes that are parts of the pattern
1090 | * may be searched at any depth what defined by the pattern structure.
1091 | *
1092 | * Set to `UINT32_MAX` to remove the maximum start depth.
1093 | */
1094 | *)
1095 | procedure ts_query_cursor_set_max_start_depth(self: PTSQueryCursor; max_start_depth: UInt32); cdecl; external ModuleName;
1096 | (*
1097 | /**********************/
1098 | /* Section - Language */
1099 | /**********************/
1100 | /**
1101 | * Get another reference to the given language.
1102 | */
1103 | const TSLanguage *ts_language_copy(const TSLanguage *self);
1104 | /**
1105 | * Free any dynamically-allocated resources for this language, if
1106 | * this is the last reference.
1107 | */
1108 | void ts_language_delete(const TSLanguage *self);
1109 | *)
1110 | (*
1111 | /**
1112 | * Get the number of distinct node types in the language.
1113 | */
1114 | *)
1115 | function ts_language_symbol_count(const self: PTSLanguage): UInt32; cdecl; external ModuleName;
1116 | (*
1117 | /**
1118 | * Get the number of valid states in this language.
1119 | */
1120 | *)
1121 | function ts_language_state_count(const self: PTSLanguage): UInt32; cdecl; external ModuleName;
1122 | (*
1123 | /**
1124 | * Get a node type string for the given numerical id.
1125 | */
1126 | *)
1127 | function ts_language_symbol_name(const self: PTSLanguage; symbol: TSSymbol): PAnsiChar; cdecl; external ModuleName;
1128 | (*
1129 | /**
1130 | * Get the numerical id for the given node type string.
1131 | */
1132 | *)
1133 | function ts_language_symbol_for_name(
1134 | const self: PTSLanguage;
1135 | AString: PAnsiChar;
1136 | length: UInt32;
1137 | is_named: Boolean
1138 | ): TSSymbol; cdecl; external ModuleName;
1139 | (*
1140 | /**
1141 | * Get the number of distinct field names in the language.
1142 | */
1143 | *)
1144 | function ts_language_field_count(const Self: PTSLanguage): UInt32; cdecl; external ModuleName;
1145 | (*
1146 | /**
1147 | * Get the field name string for the given numerical id.
1148 | */
1149 | *)
1150 | function ts_language_field_name_for_id(const Self: PTSLanguage; id: TSFieldId): PAnsiChar; cdecl; external ModuleName;
1151 | (*
1152 | /**
1153 | * Get the numerical id for the given field name string.
1154 | */
1155 | *)
1156 | function ts_language_field_id_for_name(const Self: PTSLanguage; const name: PAnsiChar; name_length: UInt32): TSFieldId; cdecl; external ModuleName;
1157 | (*
1158 | /**
1159 | * Check whether the given node type id belongs to named nodes, anonymous nodes,
1160 | * or a hidden nodes.
1161 | *
1162 | * See also [`ts_node_is_named`]. Hidden nodes are never returned from the API.
1163 | */
1164 | *)
1165 | function ts_language_symbol_type(const self: PTSLanguage; symbol: TSSymbol): TSSymbolType; cdecl; external ModuleName;
1166 | (*
1167 | /**
1168 | * Get the ABI version number for this language. This version number is used
1169 | * to ensure that languages were generated by a compatible version of
1170 | * Tree-sitter.
1171 | *
1172 | * See also [`ts_parser_set_language`].
1173 | */
1174 | *)
1175 | function ts_language_version(const self: PTSLanguage): UInt32; cdecl; external ModuleName;
1176 | (*
1177 | /**
1178 | * Get the next parse state. Combine this with lookahead iterators to generate
1179 | * completion suggestions or valid symbols in error nodes. Use
1180 | * [`ts_node_grammar_symbol`] for valid symbols.
1181 | */
1182 | *)
1183 | function ts_language_next_state(const self: PTSLanguage; state: TSStateId; symbol: TSSymbol): TSStateId; cdecl; external ModuleName;
1184 | (*
1185 | /********************************/
1186 | /* Section - Lookahead Iterator */
1187 | /********************************/
1188 | /**
1189 | * Create a new lookahead iterator for the given language and parse state.
1190 | *
1191 | * This returns `NULL` if state is invalid for the language.
1192 | *
1193 | * Repeatedly using [`ts_lookahead_iterator_next`] and
1194 | * [`ts_lookahead_iterator_current_symbol`] will generate valid symbols in the
1195 | * given parse state. Newly created lookahead iterators will contain the `ERROR`
1196 | * symbol.
1197 | *
1198 | * Lookahead iterators can be useful to generate suggestions and improve syntax
1199 | * error diagnostics. To get symbols valid in an ERROR node, use the lookahead
1200 | * iterator on its first leaf node state. For `MISSING` nodes, a lookahead
1201 | * iterator created on the previous non-extra leaf node may be appropriate.
1202 | */
1203 | TSLookaheadIterator *ts_lookahead_iterator_new(const TSLanguage *self, TSStateId state);
1204 | /**
1205 | * Delete a lookahead iterator freeing all the memory used.
1206 | */
1207 | void ts_lookahead_iterator_delete(TSLookaheadIterator *self);
1208 | /**
1209 | * Reset the lookahead iterator to another state.
1210 | *
1211 | * This returns `true` if the iterator was reset to the given state and `false`
1212 | * otherwise.
1213 | */
1214 | bool ts_lookahead_iterator_reset_state(TSLookaheadIterator *self, TSStateId state);
1215 | /**
1216 | * Reset the lookahead iterator.
1217 | *
1218 | * This returns `true` if the language was set successfully and `false`
1219 | * otherwise.
1220 | */
1221 | bool ts_lookahead_iterator_reset(TSLookaheadIterator *self, const TSLanguage *language, TSStateId state);
1222 | /**
1223 | * Get the current language of the lookahead iterator.
1224 | */
1225 | const TSLanguage *ts_lookahead_iterator_language(const TSLookaheadIterator *self);
1226 | /**
1227 | * Advance the lookahead iterator to the next symbol.
1228 | *
1229 | * This returns `true` if there is a new symbol and `false` otherwise.
1230 | */
1231 | bool ts_lookahead_iterator_next(TSLookaheadIterator *self);
1232 | /**
1233 | * Get the current symbol of the lookahead iterator;
1234 | */
1235 | TSSymbol ts_lookahead_iterator_current_symbol(const TSLookaheadIterator *self);
1236 | /**
1237 | * Get the current symbol type of the lookahead iterator as a null terminated
1238 | * string.
1239 | */
1240 | const char *ts_lookahead_iterator_current_symbol_name(const TSLookaheadIterator *self);
1241 | }
1242 | (*
1243 | /*************************************/
1244 | /* Section - WebAssembly Integration */
1245 | /************************************/
1246 | typedef struct wasm_engine_t TSWasmEngine;
1247 | typedef struct TSWasmStore TSWasmStore;
1248 | typedef enum {
1249 | TSWasmErrorKindNone = 0,
1250 | TSWasmErrorKindParse,
1251 | TSWasmErrorKindCompile,
1252 | TSWasmErrorKindInstantiate,
1253 | TSWasmErrorKindAllocate,
1254 | } TSWasmErrorKind;
1255 | typedef struct {
1256 | TSWasmErrorKind kind;
1257 | char *message;
1258 | } TSWasmError;
1259 | /**
1260 | * Create a Wasm store.
1261 | */
1262 | TSWasmStore *ts_wasm_store_new(
1263 | TSWasmEngine *engine,
1264 | TSWasmError *error
1265 | );
1266 | /**
1267 | * Free the memory associated with the given Wasm store.
1268 | */
1269 | void ts_wasm_store_delete(TSWasmStore * );
1270 | /**
1271 | * Create a language from a buffer of Wasm. The resulting language behaves
1272 | * like any other Tree-sitter language, except that in order to use it with
1273 | * a parser, that parser must have a Wasm store. Note that the language
1274 | * can be used with any Wasm store, it doesn't need to be the same store that
1275 | * was used to originally load it.
1276 | */
1277 | const TSLanguage *ts_wasm_store_load_language(
1278 | TSWasmStore *,
1279 | const char *name,
1280 | const char *wasm,
1281 | uint32_t wasm_len,
1282 | TSWasmError *error
1283 | );
1284 | /**
1285 | * Get the number of languages instantiated in the given wasm store.
1286 | */
1287 | size_t ts_wasm_store_language_count(const TSWasmStore * );
1288 | /**
1289 | * Check if the language came from a Wasm module. If so, then in order to use
1290 | * this language with a Parser, that parser must have a Wasm store assigned.
1291 | */
1292 | bool ts_language_is_wasm(const TSLanguage * );
1293 | /**
1294 | * Assign the given Wasm store to the parser. A parser must have a Wasm store
1295 | * in order to use Wasm languages.
1296 | */
1297 | void ts_parser_set_wasm_store(TSParser *, TSWasmStore * );
1298 | /**
1299 | * Remove the parser's current Wasm store and return it. This returns NULL if
1300 | * the parser doesn't have a Wasm store.
1301 | */
1302 | TSWasmStore *ts_parser_take_wasm_store(TSParser * );
1303 | *)
1304 | {
1305 | /**********************************/
1306 | /* Section - Global Configuration */
1307 | /**********************************/
1308 | /**
1309 | * Set the allocation functions used by the library.
1310 | *
1311 | * By default, Tree-sitter uses the standard libc allocation functions,
1312 | * but aborts the process when an allocation fails. This function lets
1313 | * you supply alternative allocation functions at runtime.
1314 | *
1315 | * If you pass `NULL` for any parameter, Tree-sitter will switch back to
1316 | * its default implementation of that function.
1317 | *
1318 | * If you call this function after the library has already been used, then
1319 | * you must ensure that either:
1320 | * 1. All the existing objects have been freed.
1321 | * 2. The new allocator shares its state with the old one, so it is capable
1322 | * of freeing memory that was allocated by the old allocator.
1323 | */
1324 | }
1325 | type
1326 | Pts_malloc_func = ^Tts_malloc_func;
1327 | Tts_malloc_func = function(sizeOf: NativeUInt): Pointer; cdecl;
1328 | Pts_calloc_func = ^Tts_calloc_func;
1329 | Tts_calloc_func = function(nitems: NativeUInt; size: NativeUInt): Pointer; cdecl;
1330 | Pts_free_func = ^Tts_free_func;
1331 | Tts_free_func = procedure(ptr: Pointer); cdecl;
1332 | Pts_realloc_func = ^Tts_realloc_func;
1333 | Tts_realloc_func = function(ptr: Pointer; sizeOf: NativeUInt): Pointer; cdecl;
1334 |
1335 | procedure ts_set_allocator(
1336 | new_malloc: Pts_malloc_func;
1337 | new_calloc: Pts_calloc_func;
1338 | new_realloc: Pts_realloc_func;
1339 | new_free: Pts_free_func); cdecl; external ModuleName;
1340 |
1341 | implementation
1342 |
1343 | end.
1344 |
--------------------------------------------------------------------------------
/VCLDemo/DelphiTreeSitterVCLDemo.dpr:
--------------------------------------------------------------------------------
1 | program DelphiTreeSitterVCLDemo;
2 |
3 | uses
4 | Vcl.Forms,
5 | frmDTSMain in 'frmDTSMain.pas' {DTSMainForm},
6 | TreeSitter in '..\TreeSitter.pas',
7 | TreeSitterLib in '..\TreeSitterLib.pas',
8 | frmDTSLanguage in 'frmDTSLanguage.pas' {DTSLanguageForm},
9 | TreeSitter.Query in '..\TreeSitter.Query.pas',
10 | frmDTSQuery in 'frmDTSQuery.pas' {DTSQueryForm};
11 |
12 | {$R *.res}
13 |
14 | begin
15 | ReportMemoryLeaksOnShutdown:= True;
16 | Application.Initialize;
17 | Application.MainFormOnTaskbar := True;
18 | Application.CreateForm(TDTSMainForm, DTSMainForm);
19 | Application.Run;
20 | end.
21 |
--------------------------------------------------------------------------------
/VCLDemo/DelphiTreeSitterVCLDemo.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {AAA39C66-11BC-4D19-9713-3C4763BC51D7}
4 | 19.5
5 | VCL
6 | True
7 | Debug
8 | Win64
9 | 3
10 | Application
11 | DelphiTreeSitterVCLDemo.dpr
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Cfg_1
40 | true
41 | true
42 |
43 |
44 | true
45 | Base
46 | true
47 |
48 |
49 | true
50 | Cfg_2
51 | true
52 | true
53 |
54 |
55 | true
56 | Cfg_2
57 | true
58 | true
59 |
60 |
61 | ..\$(Platform)\$(Config)
62 | ..\$(Platform)\$(Config)
63 | false
64 | false
65 | false
66 | false
67 | false
68 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
69 | $(BDS)\bin\delphi_PROJECTICON.ico
70 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
71 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
72 | DelphiTreeSitterVCLDemo
73 | 1031
74 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
75 |
76 |
77 | vclwinx;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;FireDACCommonODBC;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;bindcompfmx;inetdb;FireDACSqliteDriver;DbxClientDriver;soapmidas;vclactnband;fmxFireDAC;dbexpress;DBXMySQLDriver;VclSmp;inet;vcltouch;fmxase;dbrtl;fmxdae;FireDACMSAccDriver;CustomIPTransport;vcldsnap;DBXInterBaseDriver;IndySystem;vcldb;ActiveXTest;vclFireDAC;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;adortl;vclimg;FireDACPgDriver;FireDAC;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;fmxobj;bindcompvclsmp;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
78 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
79 | Debug
80 | true
81 | 1033
82 | $(BDS)\bin\default_app.manifest
83 | none
84 |
85 |
86 | vclwinx;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;FireDACCommonODBC;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;bindcompfmx;inetdb;FireDACSqliteDriver;DbxClientDriver;soapmidas;vclactnband;fmxFireDAC;dbexpress;DBXMySQLDriver;VclSmp;inet;vcltouch;fmxase;dbrtl;fmxdae;FireDACMSAccDriver;CustomIPTransport;vcldsnap;DBXInterBaseDriver;IndySystem;vcldb;vclFireDAC;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;adortl;vclimg;FireDACPgDriver;FireDAC;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;fmxobj;bindcompvclsmp;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
87 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
88 | Debug
89 | true
90 | 1033
91 | $(BDS)\bin\default_app.manifest
92 |
93 |
94 | DEBUG;$(DCC_Define)
95 | true
96 | false
97 | true
98 | true
99 | true
100 | true
101 | true
102 |
103 |
104 | false
105 | PerMonitorV2
106 | true
107 | 1033
108 |
109 |
110 | PerMonitorV2
111 |
112 |
113 | false
114 | RELEASE;$(DCC_Define)
115 | 0
116 | 0
117 |
118 |
119 | PerMonitorV2
120 | true
121 | 1033
122 |
123 |
124 | PerMonitorV2
125 |
126 |
127 |
128 | MainSource
129 |
130 |
131 |
132 | dfm
133 |
134 |
135 |
136 |
137 |
138 | dfm
139 |
140 |
141 |
142 |
143 | dfm
144 |
145 |
146 | Base
147 |
148 |
149 | Cfg_1
150 | Base
151 |
152 |
153 | Cfg_2
154 | Base
155 |
156 |
157 |
158 | Delphi.Personality.12
159 | Application
160 |
161 |
162 |
163 | DelphiTreeSitterVCLDemo.dpr
164 |
165 |
166 |
167 | True
168 | True
169 |
170 |
171 | 12
172 |
173 |
174 |
175 |
176 |
177 |
--------------------------------------------------------------------------------
/VCLDemo/frmDTSLanguage.dfm:
--------------------------------------------------------------------------------
1 | object DTSLanguageForm: TDTSLanguageForm
2 | Left = 0
3 | Top = 0
4 | Caption = 'Language Info'
5 | ClientHeight = 441
6 | ClientWidth = 624
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -12
11 | Font.Name = 'Segoe UI'
12 | Font.Style = []
13 | OnClose = FormClose
14 | TextHeight = 15
15 | object Splitter1: TSplitter
16 | Left = 220
17 | Top = 28
18 | Height = 413
19 | ExplicitLeft = 621
20 | ExplicitTop = 0
21 | end
22 | object pnlTop: TPanel
23 | Left = 0
24 | Top = 0
25 | Width = 624
26 | Height = 28
27 | Align = alTop
28 | BevelOuter = bvNone
29 | TabOrder = 1
30 | DesignSize = (
31 | 624
32 | 28)
33 | object lblFieldCount: TLabel
34 | Left = 8
35 | Top = 8
36 | Width = 71
37 | Height = 15
38 | Caption = 'lblFieldCount'
39 | end
40 | object lblSymbolCount: TLabel
41 | Left = 229
42 | Top = 7
43 | Width = 51
44 | Height = 15
45 | Caption = 'lblVersion'
46 | end
47 | object lblVersion: TLabel
48 | Left = 560
49 | Top = 7
50 | Width = 51
51 | Height = 15
52 | Alignment = taRightJustify
53 | Anchors = [akTop, akRight]
54 | Caption = 'lblVersion'
55 | end
56 | end
57 | object sgSymbols: TStringGrid
58 | Left = 223
59 | Top = 28
60 | Width = 401
61 | Height = 413
62 | Align = alClient
63 | ColCount = 3
64 | DefaultColWidth = 130
65 | DefaultRowHeight = 18
66 | FixedCols = 0
67 | Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goFixedRowDefAlign]
68 | TabOrder = 2
69 | end
70 | object sgFields: TStringGrid
71 | Left = 0
72 | Top = 28
73 | Width = 220
74 | Height = 413
75 | Align = alLeft
76 | ColCount = 2
77 | DefaultColWidth = 120
78 | DefaultRowHeight = 18
79 | FixedCols = 0
80 | Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goFixedRowDefAlign]
81 | TabOrder = 0
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/VCLDemo/frmDTSLanguage.pas:
--------------------------------------------------------------------------------
1 | unit frmDTSLanguage;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
7 | System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
8 | Vcl.ExtCtrls, Vcl.Grids, Vcl.StdCtrls, TreeSitter;
9 |
10 | type
11 | TDTSLanguageForm = class(TForm)
12 | lblFieldCount: TLabel;
13 | pnlTop: TPanel;
14 | sgSymbols: TStringGrid;
15 | sgFields: TStringGrid;
16 | Splitter1: TSplitter;
17 | lblSymbolCount: TLabel;
18 | lblVersion: TLabel;
19 | procedure FormClose(Sender: TObject; var Action: TCloseAction);
20 | private
21 | FLanguage: PTSLanguage;
22 | procedure UpdateLanguage;
23 | public
24 | { Public declarations }
25 | end;
26 |
27 | var
28 | DTSLanguageForm: TDTSLanguageForm;
29 |
30 | procedure ShowLanguageInfo(ALanguage: PTSLanguage);
31 |
32 | implementation
33 |
34 | {$R *.dfm}
35 |
36 | procedure ShowLanguageInfo(ALanguage: PTSLanguage);
37 | begin
38 | if DTSLanguageForm = nil then
39 | begin
40 | Application.Createform(TDTSLanguageForm, DTSLanguageForm);
41 | DTSLanguageForm.sgFields.ColWidths[1]:= 50;
42 | DTSLanguageForm.sgSymbols.ColWidths[0]:= 200;
43 | DTSLanguageForm.sgSymbols.ColWidths[1]:= 50;
44 | end;
45 | DTSLanguageForm.FLanguage:= ALanguage;
46 | DTSLanguageForm.UpdateLanguage;
47 | DTSLanguageForm.Show;
48 | DTSLanguageForm.BringToFront;
49 | end;
50 |
51 | procedure TDTSLanguageForm.FormClose(Sender: TObject; var Action: TCloseAction);
52 | begin
53 | Action:= caFree;
54 | if Self = DTSLanguageForm then
55 | DTSLanguageForm:= nil;
56 | end;
57 |
58 | procedure TDTSLanguageForm.UpdateLanguage;
59 | const
60 | SymbolTypes: array[TSSymbolType] of string = ('Regular', 'Anonymous',
61 | 'Auxiliary');
62 | var
63 | i: Integer;
64 | begin
65 | lblFieldCount.Caption:= Format('Fields: %d', [FLanguage^.FieldCount]);
66 | lblSymbolCount.Caption:= Format('Symbols: %d', [FLanguage^.SymbolCount]);
67 | lblVersion.Caption:= Format('Version: %d', [FLanguage^.Version]);
68 |
69 | sgFields.RowCount:= FLanguage^.FieldCount + 1;
70 | sgFields.Cells[0, 0]:= 'Field name';
71 | sgFields.Cells[1, 0]:= 'Field Id';
72 | for i:= 1 to sgFields.RowCount - 1 do
73 | begin
74 | sgFields.Cells[0, i]:= FLanguage^.FieldName[TSFieldId(i)];
75 | sgFields.Cells[1, i]:= IntToStr(i);
76 | end;
77 |
78 | sgSymbols.RowCount:= FLanguage^.SymbolCount + 1;
79 | sgSymbols.Cells[0, 0]:= 'Symbol name';
80 | sgSymbols.Cells[1, 0]:= 'Symbol';
81 | sgSymbols.Cells[2, 0]:= 'Type';
82 | for i:= 1 to sgSymbols.RowCount - 1 do
83 | begin
84 | sgSymbols.Cells[0, i]:= FLanguage^.SymbolName[TSSymbol(i)];
85 | sgSymbols.Cells[1, i]:= IntToStr(i);
86 | sgSymbols.Cells[2, i]:= SymbolTypes[FLanguage^.SymbolType[TSSymbol(i)]];
87 | end;
88 | end;
89 |
90 | end.
91 |
--------------------------------------------------------------------------------
/VCLDemo/frmDTSMain.dfm:
--------------------------------------------------------------------------------
1 | object DTSMainForm: TDTSMainForm
2 | Left = 0
3 | Top = 0
4 | Caption =
5 | 'Tree-Sitter for Delphi demo - https://github.com/modersohn/delph' +
6 | 'i-tree-sitter'
7 | ClientHeight = 478
8 | ClientWidth = 765
9 | Color = clBtnFace
10 | Font.Charset = DEFAULT_CHARSET
11 | Font.Color = clWindowText
12 | Font.Height = -12
13 | Font.Name = 'Segoe UI'
14 | Font.Style = []
15 | OnCreate = FormCreate
16 | OnDestroy = FormDestroy
17 | TextHeight = 15
18 | object Splitter1: TSplitter
19 | Left = 512
20 | Top = 50
21 | Height = 428
22 | Align = alRight
23 | ExplicitLeft = 568
24 | ExplicitTop = 45
25 | ExplicitHeight = 425
26 | end
27 | object memCode: TMemo
28 | Left = 0
29 | Top = 50
30 | Width = 512
31 | Height = 428
32 | Align = alClient
33 | Font.Charset = ANSI_CHARSET
34 | Font.Color = clWindowText
35 | Font.Height = -15
36 | Font.Name = 'Consolas'
37 | Font.Style = []
38 | HideSelection = False
39 | ParentFont = False
40 | ScrollBars = ssBoth
41 | TabOrder = 1
42 | OnChange = memCodeChange
43 | OnExit = memCodeExit
44 | end
45 | object pnlTop: TPanel
46 | Left = 0
47 | Top = 0
48 | Width = 765
49 | Height = 50
50 | Align = alTop
51 | BevelOuter = bvNone
52 | TabOrder = 0
53 | object lblCode: TLabel
54 | Left = 96
55 | Top = 17
56 | Width = 31
57 | Height = 15
58 | Caption = 'Code:'
59 | end
60 | object Label1: TLabel
61 | Left = 411
62 | Top = 17
63 | Width = 86
64 | Height = 15
65 | Anchors = [akTop, akRight]
66 | Caption = 'Language fields:'
67 | end
68 | object btnLoad: TButton
69 | Left = 8
70 | Top = 13
71 | Width = 66
72 | Height = 25
73 | Caption = 'Load...'
74 | TabOrder = 0
75 | OnClick = btnLoadClick
76 | end
77 | object cbCode: TComboBox
78 | Left = 133
79 | Top = 14
80 | Width = 145
81 | Height = 23
82 | Style = csDropDownList
83 | TabOrder = 1
84 | OnChange = cbCodeChange
85 | Items.Strings = (
86 | 'c'
87 | 'cpp'
88 | 'pascal'
89 | 'proto')
90 | end
91 | object cbFields: TComboBox
92 | Left = 507
93 | Top = 14
94 | Width = 145
95 | Height = 23
96 | Style = csDropDownList
97 | Anchors = [akTop, akRight]
98 | TabOrder = 4
99 | end
100 | object btnGetChildByField: TButton
101 | Left = 658
102 | Top = 13
103 | Width = 97
104 | Height = 25
105 | Action = actGetChildByField
106 | Anchors = [akTop, akRight]
107 | TabOrder = 5
108 | end
109 | object btnLangInfo: TButton
110 | Left = 280
111 | Top = 13
112 | Width = 40
113 | Height = 25
114 | Caption = 'Info'
115 | TabOrder = 2
116 | OnClick = btnLangInfoClick
117 | end
118 | object btnQuery: TButton
119 | Left = 336
120 | Top = 13
121 | Width = 66
122 | Height = 25
123 | Caption = 'Query...'
124 | TabOrder = 3
125 | OnClick = btnQueryClick
126 | end
127 | end
128 | object Panel1: TPanel
129 | Left = 515
130 | Top = 50
131 | Width = 250
132 | Height = 428
133 | Align = alRight
134 | Caption = 'Panel1'
135 | TabOrder = 2
136 | object Splitter2: TSplitter
137 | Left = 1
138 | Top = 174
139 | Width = 248
140 | Height = 3
141 | Cursor = crVSplit
142 | Align = alBottom
143 | ExplicitLeft = 3
144 | ExplicitTop = 295
145 | ExplicitWidth = 183
146 | end
147 | object treeView: TTreeView
148 | Left = 1
149 | Top = 1
150 | Width = 248
151 | Height = 173
152 | Align = alClient
153 | HideSelection = False
154 | Indent = 19
155 | PopupMenu = pmTree
156 | ReadOnly = True
157 | TabOrder = 0
158 | OnChange = treeViewChange
159 | OnCreateNodeClass = treeViewCreateNodeClass
160 | OnExpanding = treeViewExpanding
161 | end
162 | object sgNodeProps: TStringGrid
163 | Left = 1
164 | Top = 177
165 | Width = 248
166 | Height = 250
167 | Align = alBottom
168 | ColCount = 2
169 | DefaultColWidth = 120
170 | DefaultRowHeight = 18
171 | FixedRows = 0
172 | Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goFixedRowDefAlign]
173 | TabOrder = 1
174 | end
175 | end
176 | object OD: TFileOpenDialog
177 | ClientGuid = '{58D00BB6-8E09-48B3-B19E-7E86D8D6B167}'
178 | FavoriteLinks = <>
179 | FileTypes = <
180 | item
181 | DisplayName = 'All files'
182 | FileMask = '*.*'
183 | end>
184 | Options = []
185 | Left = 376
186 | Top = 248
187 | end
188 | object AL: TActionList
189 | Left = 344
190 | Top = 336
191 | object actGoto: TAction
192 | Category = 'Goto'
193 | Caption = 'Go to'
194 | OnExecute = actGotoExecute
195 | OnUpdate = actGotoUpdate
196 | end
197 | object actGotoParent: TAction
198 | Category = 'Goto'
199 | Caption = 'Parent'
200 | OnExecute = actGotoParentExecute
201 | OnUpdate = actGotoParentUpdate
202 | end
203 | object actGetChildByField: TAction
204 | Caption = 'Child by fieldID'
205 | OnExecute = actGetChildByFieldExecute
206 | OnUpdate = actGetChildByFieldUpdate
207 | end
208 | object actShowNodeAsString: TAction
209 | Caption = 'Show S-expression...'
210 | OnExecute = actShowNodeAsStringExecute
211 | OnUpdate = actShowNodeAsStringUpdate
212 | end
213 | object actGotoFirstChild: TAction
214 | Category = 'Goto'
215 | Caption = 'First child'
216 | OnExecute = actGotoFirstChildExecute
217 | OnUpdate = actGotoFirstChildUpdate
218 | end
219 | object actGotoNextSibling: TAction
220 | Category = 'Goto'
221 | Caption = 'Next sibling'
222 | OnExecute = actGotoNextSiblingExecute
223 | OnUpdate = actGotoNextSiblingUpdate
224 | end
225 | object actGotoPrevSibling: TAction
226 | Category = 'Goto'
227 | Caption = 'Previous sibling'
228 | OnExecute = actGotoPrevSiblingExecute
229 | OnUpdate = actGotoPrevSiblingUpdate
230 | end
231 | object actNamedNodesOnly: TAction
232 | AutoCheck = True
233 | Caption = 'Named nodes only'
234 | Checked = True
235 | OnExecute = actNamedNodesOnlyExecute
236 | end
237 | end
238 | object pmTree: TPopupMenu
239 | Left = 416
240 | Top = 304
241 | object mnuactNamedNodesOnly: TMenuItem
242 | Action = actNamedNodesOnly
243 | AutoCheck = True
244 | end
245 | object N4: TMenuItem
246 | Caption = '-'
247 | end
248 | object mnuactGoto: TMenuItem
249 | Action = actGoto
250 | object mnuactGotoParent: TMenuItem
251 | Action = actGotoParent
252 | end
253 | object N2: TMenuItem
254 | Caption = '-'
255 | end
256 | object mnuactGotoFirstChild: TMenuItem
257 | Action = actGotoFirstChild
258 | end
259 | object N3: TMenuItem
260 | Caption = '-'
261 | end
262 | object mnuactGotoNextSibling: TMenuItem
263 | Action = actGotoNextSibling
264 | end
265 | object mnuactGotoPrevSibling: TMenuItem
266 | Action = actGotoPrevSibling
267 | end
268 | end
269 | object N1: TMenuItem
270 | Caption = '-'
271 | end
272 | object mnuactShowNodeAsString: TMenuItem
273 | Action = actShowNodeAsString
274 | end
275 | end
276 | end
277 |
--------------------------------------------------------------------------------
/VCLDemo/frmDTSMain.pas:
--------------------------------------------------------------------------------
1 | unit frmDTSMain;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
7 | System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
8 | Vcl.ExtCtrls, Vcl.ComCtrls, Vcl.StdCtrls, TreeSitter, Vcl.Grids,
9 | System.Actions, Vcl.ActnList, Vcl.Menus;
10 |
11 | type
12 | TTSTreeViewNode = class(TTreeNode)
13 | public
14 | TSNode: TTSNode;
15 | end;
16 |
17 | TDTSMainForm = class(TForm)
18 | memCode: TMemo;
19 | pnlTop: TPanel;
20 | treeView: TTreeView;
21 | Splitter1: TSplitter;
22 | OD: TFileOpenDialog;
23 | btnLoad: TButton;
24 | lblCode: TLabel;
25 | cbCode: TComboBox;
26 | Splitter2: TSplitter;
27 | Panel1: TPanel;
28 | sgNodeProps: TStringGrid;
29 | AL: TActionList;
30 | actGoto: TAction;
31 | actGotoParent: TAction;
32 | pmTree: TPopupMenu;
33 | mnuactGoto: TMenuItem;
34 | mnuactGotoParent: TMenuItem;
35 | cbFields: TComboBox;
36 | Label1: TLabel;
37 | btnGetChildByField: TButton;
38 | actGetChildByField: TAction;
39 | actShowNodeAsString: TAction;
40 | mnuactShowNodeAsString: TMenuItem;
41 | N1: TMenuItem;
42 | actGotoFirstChild: TAction;
43 | actGotoNextSibling: TAction;
44 | actGotoPrevSibling: TAction;
45 | mnuactGotoFirstChild: TMenuItem;
46 | mnuactGotoNextSibling: TMenuItem;
47 | mnuactGotoPrevSibling: TMenuItem;
48 | N2: TMenuItem;
49 | N3: TMenuItem;
50 | btnLangInfo: TButton;
51 | btnQuery: TButton;
52 | actNamedNodesOnly: TAction;
53 | mnuactNamedNodesOnly: TMenuItem;
54 | N4: TMenuItem;
55 | procedure FormCreate(Sender: TObject);
56 | procedure FormDestroy(Sender: TObject);
57 | procedure memCodeExit(Sender: TObject);
58 | procedure treeViewCreateNodeClass(Sender: TCustomTreeView;
59 | var NodeClass: TTreeNodeClass);
60 | procedure treeViewExpanding(Sender: TObject; Node: TTreeNode;
61 | var AllowExpansion: Boolean);
62 | procedure btnLoadClick(Sender: TObject);
63 | procedure cbCodeChange(Sender: TObject);
64 | procedure treeViewChange(Sender: TObject; Node: TTreeNode);
65 | procedure memCodeChange(Sender: TObject);
66 | procedure actGotoUpdate(Sender: TObject);
67 | procedure actGotoParentExecute(Sender: TObject);
68 | procedure actGotoParentUpdate(Sender: TObject);
69 | procedure actGotoExecute(Sender: TObject);
70 | procedure actGetChildByFieldExecute(Sender: TObject);
71 | procedure actGetChildByFieldUpdate(Sender: TObject);
72 | procedure actShowNodeAsStringUpdate(Sender: TObject);
73 | procedure actShowNodeAsStringExecute(Sender: TObject);
74 | procedure actGotoFirstChildExecute(Sender: TObject);
75 | procedure actGotoFirstChildUpdate(Sender: TObject);
76 | procedure actGotoNextSiblingExecute(Sender: TObject);
77 | procedure actGotoNextSiblingUpdate(Sender: TObject);
78 | procedure actGotoPrevSiblingExecute(Sender: TObject);
79 | procedure actGotoPrevSiblingUpdate(Sender: TObject);
80 | procedure btnLangInfoClick(Sender: TObject);
81 | procedure btnQueryClick(Sender: TObject);
82 | procedure actNamedNodesOnlyExecute(Sender: TObject);
83 | private
84 | FParser: TTSParser;
85 | FTree: TTSTree;
86 | FEditChanged: Boolean;
87 | procedure ParseContent;
88 | procedure LoadLanguageParser(const ALangBaseName: string);
89 | procedure LoadLanguageFields;
90 | procedure FillNodeProps(const ANode: TTSNode);
91 | procedure ClearNodeProps;
92 | function GetSelectedTSNode: TTSNode;
93 | procedure SetSelectedTSNode(const Value: TTSNode);
94 | procedure SetupTreeTSNode(ATreeNode: TTSTreeViewNode; ATSNode: TTSNode);
95 | public
96 | property SelectedTSNode: TTSNode read GetSelectedTSNode write SetSelectedTSNode;
97 | end;
98 |
99 | var
100 | DTSMainForm: TDTSMainForm;
101 |
102 | implementation
103 |
104 | uses
105 | frmDTSLanguage,
106 | frmDTSQuery,
107 | UITypes;
108 |
109 | {$R *.dfm}
110 |
111 | type
112 | TSGNodePropRow = (rowSymbol, rowGrammarType, rowGrammarSymbol, rowIsError,
113 | rowHasError, rowIsExtra, rowIsMissing, rowIsNamed, rowChildCount,
114 | rowNamedChildCount, rowStartByte, rowStartPoint, rowEndByte, rowEndPoint,
115 | rowDescendantCount);
116 |
117 | const
118 | sgNodePropCaptions: array[TSGNodePropRow] of string = (
119 | 'Symbol', 'GrammarType', 'GrammarSymbol', 'IsError',
120 | 'HasError', 'IsExtra', 'IsMissing', 'IsNamed', 'ChildCount',
121 | 'NamedChildCount', 'StartByte', 'StartPoint', 'EndByte', 'EndPoint',
122 | 'DescendantCount');
123 |
124 | procedure TDTSMainForm.actGetChildByFieldExecute(Sender: TObject);
125 | var
126 | foundNode: TTSNode;
127 | begin
128 | foundNode:= SelectedTSNode.ChildByField(cbFields.ItemIndex + 1);
129 | //foundNode:= SelectedTSNode.ChildByField(cbFields.Text);
130 | if foundNode.IsNull then
131 | MessageDlg(Format('No child for field "%s" (%d) found', [cbFields.Text, cbFields.ItemIndex]),
132 | TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0) else
133 | SelectedTSNode:= foundNode;
134 | end;
135 |
136 | procedure TDTSMainForm.actGetChildByFieldUpdate(Sender: TObject);
137 | begin
138 | actGetChildByField.Enabled:= (not SelectedTSNode.IsNull) and
139 | (cbFields.ItemIndex >= 0);
140 | end;
141 |
142 | procedure TDTSMainForm.actGotoExecute(Sender: TObject);
143 | begin
144 | //to keep it enabled
145 | end;
146 |
147 | procedure TDTSMainForm.actGotoFirstChildExecute(Sender: TObject);
148 | begin
149 | if actNamedNodesOnly.Checked then
150 | SelectedTSNode:= SelectedTSNode.NamedChild(0) else
151 | SelectedTSNode:= SelectedTSNode.Child(0);
152 | end;
153 |
154 | procedure TDTSMainForm.actGotoFirstChildUpdate(Sender: TObject);
155 | begin
156 | if actNamedNodesOnly.Checked then
157 | actGotoFirstChild.Enabled:= SelectedTSNode.NamedChildCount > 0 else
158 | actGotoFirstChild.Enabled:= SelectedTSNode.ChildCount > 0;
159 | end;
160 |
161 | procedure TDTSMainForm.actGotoNextSiblingExecute(Sender: TObject);
162 | begin
163 | if actNamedNodesOnly.Checked then
164 | SelectedTSNode:= SelectedTSNode.NextNamedSibling else
165 | SelectedTSNode:= SelectedTSNode.NextSibling;
166 | end;
167 |
168 | procedure TDTSMainForm.actGotoNextSiblingUpdate(Sender: TObject);
169 | begin
170 | if actNamedNodesOnly.Checked then
171 | actGotoNextSibling.Enabled:= not SelectedTSNode.NextNamedSibling.IsNull else
172 | actGotoNextSibling.Enabled:= not SelectedTSNode.NextSibling.IsNull;
173 | end;
174 |
175 | procedure TDTSMainForm.actGotoParentExecute(Sender: TObject);
176 | begin
177 | SelectedTSNode:= SelectedTSNode.Parent;
178 | end;
179 |
180 | procedure TDTSMainForm.actGotoParentUpdate(Sender: TObject);
181 | begin
182 | actGotoParent.Enabled:= not SelectedTSNode.Parent.IsNull;
183 | end;
184 |
185 | procedure TDTSMainForm.actGotoPrevSiblingExecute(Sender: TObject);
186 | begin
187 | if actNamedNodesOnly.Checked then
188 | SelectedTSNode:= SelectedTSNode.PrevNamedSibling else
189 | SelectedTSNode:= SelectedTSNode.PrevSibling;
190 | end;
191 |
192 | procedure TDTSMainForm.actGotoPrevSiblingUpdate(Sender: TObject);
193 | begin
194 | if actNamedNodesOnly.Checked then
195 | actGotoPrevSibling.Enabled:= not SelectedTSNode.PrevNamedSibling.IsNull else
196 | actGotoPrevSibling.Enabled:= not SelectedTSNode.PrevSibling.IsNull;
197 | end;
198 |
199 | procedure TDTSMainForm.actGotoUpdate(Sender: TObject);
200 | begin
201 | actGoto.Enabled:= not SelectedTSNode.IsNull;
202 | end;
203 |
204 | procedure TDTSMainForm.actNamedNodesOnlyExecute(Sender: TObject);
205 | var
206 | root, prevSelected: TTSNode;
207 | rootNode: TTSTreeViewNode;
208 | begin
209 | prevSelected:= SelectedTSNode;
210 | try
211 | treeView.Items.Clear;
212 | root:= FTree.RootNode;
213 | rootNode:= TTSTreeViewNode(treeView.Items.AddChild(nil, root.NodeType));
214 | SetupTreeTSNode(rootNode, root);
215 | finally
216 | SelectedTSNode:= prevSelected;
217 | end;
218 | end;
219 |
220 | procedure TDTSMainForm.actShowNodeAsStringExecute(Sender: TObject);
221 | begin
222 | ShowMessage(SelectedTSNode.ToString);
223 | end;
224 |
225 | procedure TDTSMainForm.actShowNodeAsStringUpdate(Sender: TObject);
226 | begin
227 | actShowNodeAsString.Enabled:= not SelectedTSNode.IsNull;
228 | end;
229 |
230 | procedure TDTSMainForm.btnLangInfoClick(Sender: TObject);
231 | begin
232 | ShowLanguageInfo(FParser.Language);
233 | end;
234 |
235 | procedure TDTSMainForm.btnLoadClick(Sender: TObject);
236 | begin
237 | if not OD.Execute(Handle) then
238 | Exit;
239 | memCode.Lines.LoadFromFile(OD.FileName);
240 | FEditChanged:= True;
241 | ParseContent;
242 | end;
243 |
244 | procedure TDTSMainForm.btnQueryClick(Sender: TObject);
245 | begin
246 | ShowQueryForm(FTree);
247 | end;
248 |
249 | procedure TDTSMainForm.LoadLanguageParser(const ALangBaseName: string);
250 | //hard coded naming scheme
251 | // DLL name: tree-sitter-
252 | // method name returning TSLanguage: tree_sitter_
253 | //this could also be fed from e.g. an INI file or could be
254 | //hardcoded depending on the use-case
255 | var
256 | tsLibName, tsAPIName: string;
257 | libHandle: THandle;
258 | pAPI: TTSGetLanguageFunc;
259 | begin
260 | tsLibName:= Format('tree-sitter-%s', [ALangBaseName]);
261 | libHandle:= LoadLibrary(PChar(tsLibName));
262 | if libHandle = 0 then
263 | raise Exception.CreateFmt('Could not load library "%s"', [tsLibName]);
264 | tsAPIName:= Format('tree_sitter_%s', [ALangBaseName]);
265 | pAPI:= GetProcAddress(libHandle, PChar(tsAPIName));
266 | if pAPI = nil then
267 | raise Exception.CreateFmt('The library "%s" does not provide a method "%s"',
268 | [tsLibName, tsAPIName]);
269 | FParser.Reset;
270 | FreeAndNil(FTree);
271 | FParser.Language:= pAPI;
272 | LoadLanguageFields;
273 | end;
274 |
275 | procedure TDTSMainForm.LoadLanguageFields;
276 | var
277 | i: UInt32;
278 | begin
279 | cbFields.Items.BeginUpdate;
280 | try
281 | cbFields.Items.Clear;
282 | if FParser.Language = nil then
283 | Exit;
284 | for i:= 1 to FParser.Language^.FieldCount do
285 | cbFields.Items.AddObject(FParser.Language^.FieldName[i], TObject(i));
286 | finally
287 | cbFields.Items.EndUpdate;
288 | end;
289 | end;
290 |
291 | procedure TDTSMainForm.cbCodeChange(Sender: TObject);
292 | begin
293 | LoadLanguageParser(cbCode.Items[cbCode.ItemIndex]);
294 | ParseContent;
295 | end;
296 |
297 | procedure TDTSMainForm.ClearNodeProps;
298 | var
299 | row: TSGNodePropRow;
300 | begin
301 | for row:= Low(TSGNodePropRow) to High(TSGNodePropRow) do
302 | sgNodeProps.Cells[1, Ord(row)]:= '';
303 | end;
304 |
305 | procedure TDTSMainForm.FillNodeProps(const ANode: TTSNode);
306 | begin
307 | sgNodeProps.Cells[1, Ord(rowSymbol)]:= Format('%d (%s)', [ANode.Symbol, ANode.Language^.SymbolName[ANode.Symbol]]);
308 | sgNodeProps.Cells[1, Ord(rowGrammarType)]:= ANode.GrammarType;
309 | sgNodeProps.Cells[1, Ord(rowGrammarSymbol)]:= Format('%d (%s)', [ANode.GrammarSymbol, ANode.Language^.SymbolName[ANode.GrammarSymbol]]);
310 | sgNodeProps.Cells[1, Ord(rowIsError)]:= BoolToStr(ANode.IsError, True);
311 | sgNodeProps.Cells[1, Ord(rowHasError)]:= BoolToStr(ANode.HasError, True);
312 | sgNodeProps.Cells[1, Ord(rowIsExtra)]:= BoolToStr(ANode.IsExtra, True);
313 | sgNodeProps.Cells[1, Ord(rowIsMissing)]:= BoolToStr(ANode.IsMissing, True);
314 | sgNodeProps.Cells[1, Ord(rowIsNamed)]:= BoolToStr(ANode.IsNamed, True);
315 | sgNodeProps.Cells[1, Ord(rowChildCount)]:= IntToStr(ANode.ChildCount);
316 | sgNodeProps.Cells[1, Ord(rowNamedChildCount)]:= IntToStr(ANode.NamedChildCount);
317 | sgNodeProps.Cells[1, Ord(rowStartByte)]:= IntToStr(ANode.StartByte);
318 | sgNodeProps.Cells[1, Ord(rowStartPoint)]:= ANode.StartPoint.ToString;
319 | sgNodeProps.Cells[1, Ord(rowEndByte)]:= IntToStr(ANode.EndByte);
320 | sgNodeProps.Cells[1, Ord(rowEndPoint)]:= ANode.EndPoint.ToString;
321 | sgNodeProps.Cells[1, Ord(rowDescendantCount)]:= IntToStr(ANode.DescendantCount);
322 | end;
323 |
324 | procedure TDTSMainForm.FormCreate(Sender: TObject);
325 | var
326 | row: TSGNodePropRow;
327 | begin
328 | //initialize property grid captions
329 | sgNodeProps.RowCount:= Ord(High(TSGNodePropRow)) - Ord(Low(TSGNodePropRow)) + 1;
330 | for row:= Low(TSGNodePropRow) to High(TSGNodePropRow) do
331 | sgNodeProps.Cells[0, Ord(row)]:= sgNodePropCaptions[row];
332 |
333 | FParser:= TTSParser.Create;
334 | cbCode.ItemIndex:= 0;
335 | cbCodeChange(nil);
336 | end;
337 |
338 | procedure TDTSMainForm.FormDestroy(Sender: TObject);
339 | begin
340 | FreeAndNil(FTree);
341 | FreeAndNil(FParser);
342 | end;
343 |
344 | function TDTSMainForm.GetSelectedTSNode: TTSNode;
345 | begin
346 | if treeView.Selected is TTSTreeViewNode then
347 | Result:= TTSTreeViewNode(treeView.Selected).TSNode else
348 | Result:= FTree.RootNode.Parent; //easy way to create a NULL node
349 | end;
350 |
351 | procedure TDTSMainForm.ParseContent;
352 | var
353 | root: TTSNode;
354 | rootNode: TTSTreeViewNode;
355 | sCode: string;
356 | begin
357 | treeView.Items.Clear;
358 | sCode:= memCode.Lines.Text;
359 | if DTSQueryForm <> nil then
360 | DTSQueryForm.TreeDeleted;
361 | FreeAndNil(FTree);
362 | if Length(sCode) = 0 then
363 | Exit; //avoid our own exception that empty string cannot be parsed
364 | //we no longer pass OldTree as we would need to track editing and call
365 | //ts_tree_edit
366 | FTree:= FParser.ParseString(sCode);
367 | root:= FTree.RootNode;
368 | rootNode:= TTSTreeViewNode(treeView.Items.AddChild(nil, root.NodeType));
369 | SetupTreeTSNode(rootNode, root);
370 | FEditChanged:= False;
371 | if DTSQueryForm <> nil then
372 | DTSQueryForm.NewTreeGenerated(FTree);
373 | end;
374 |
375 | procedure TDTSMainForm.SetSelectedTSNode(const Value: TTSNode);
376 |
377 | function FindViaParent(const ATSNode: TTSNode): TTreeNode;
378 | var
379 | tsParent: TTSNode;
380 | begin
381 | tsParent:= ATSNode.Parent;
382 | if tsParent.IsNull then
383 | Result:= treeView.Items.GetFirstNode else
384 | begin
385 | Result:= FindViaParent(tsParent);
386 | if Result <> nil then
387 | begin
388 | Result.Expand(False);
389 | Result:= Result.getFirstChild;
390 | end;
391 | end;
392 | if Result = nil then
393 | Exit;
394 | while Result is TTSTreeViewNode do
395 | begin
396 | if TTSTreeViewNode(Result).TSNode = ATSNode then
397 | Exit;
398 | Result:= Result.getNextSibling as TTSTreeViewNode;
399 | end;
400 | end;
401 |
402 | begin
403 | treeView.Selected:= FindViaParent(Value);
404 | end;
405 |
406 | procedure TDTSMainForm.treeViewChange(Sender: TObject; Node: TTreeNode);
407 | var
408 | tsSelected: TTSNode;
409 | ptStart, ptEnd: TTSPoint;
410 | memSel: TSelection;
411 | line: LRESULT;
412 | begin
413 | if Node = nil then
414 | begin
415 | ClearNodeProps;
416 | Exit;
417 | end;
418 | tsSelected:= TTSTreeViewNode(Node).TSNode;
419 | FillNodeProps(tsSelected);
420 |
421 | //select the corresponding code in the memo
422 | ptStart:= tsSelected.StartPoint;
423 | ptEnd:= tsSelected.EndPoint;
424 |
425 | line:= memcode.Perform(EM_LineIndex, ptStart.row, 0);
426 | if line < 0 then
427 | Exit; //something's not right
428 |
429 | //TSPoint.Column is in bytes, we use UTF16, so divide by 2 to get character,
430 | //which is a simplification not necessarily true
431 | memSel.StartPos:= line + Integer(ptStart.column) div 2;
432 |
433 | line:= memcode.Perform(EM_LineIndex, ptEnd.row, 0);
434 | if line < 0 then
435 | Exit; //something's not right
436 | memSel.EndPos:= line + Integer(ptEnd.column) div 2;
437 |
438 | SendMessage(memCode.Handle, EM_SETSEL, memSel.StartPos, memSel.EndPos);
439 | SendMessage(memCode.Handle, EM_SCROLLCARET, 0, 0);
440 | end;
441 |
442 | procedure TDTSMainForm.treeViewCreateNodeClass(Sender: TCustomTreeView;
443 | var NodeClass: TTreeNodeClass);
444 | begin
445 | NodeClass:= TTSTreeViewNode;
446 | end;
447 |
448 | procedure TDTSMainForm.treeViewExpanding(Sender: TObject; Node: TTreeNode;
449 | var AllowExpansion: Boolean);
450 | var
451 | tsCursor: TTSTreeCursor;
452 | tsNode: TTSNode;
453 | newTreeNode: TTSTreeViewNode;
454 | s: string;
455 | begin
456 | AllowExpansion:= True;
457 | if Node.getFirstChild <> nil then
458 | Exit;
459 | tsCursor:= TTSTreeCursor.Create(TTSTreeViewNode(Node).TSNode);
460 | try
461 | if tsCursor.GotoFirstChild then
462 | begin
463 | repeat
464 | tsNode:= tsCursor.CurrentNode;
465 | if actNamedNodesOnly.Checked and not tsNode.IsNamed then
466 | Continue;
467 | if tsCursor.CurrentFieldId > 0 then
468 | s:= Format('%s (%d): %s', [tsCursor.CurrentFieldName,
469 | tsCursor.CurrentFieldId, tsNode.NodeType])
470 | else
471 | s:= tsNode.NodeType;
472 | newTreeNode:= TTSTreeViewNode(treeView.Items.AddChild(Node, s));
473 | SetupTreeTSNode(newTreeNode, tsNode);
474 | until not tsCursor.GotoNextSibling;
475 | end;
476 | finally
477 | tsCursor.Free;
478 | end;
479 | end;
480 |
481 | procedure TDTSMainForm.memCodeChange(Sender: TObject);
482 | begin
483 | FEditChanged:= True;
484 | end;
485 |
486 | procedure TDTSMainForm.memCodeExit(Sender: TObject);
487 | begin
488 | if FEditChanged then
489 | ParseContent;
490 | end;
491 |
492 | procedure TDTSMainForm.SetupTreeTSNode(ATreeNode: TTSTreeViewNode; ATSNode: TTSNode);
493 | begin
494 | ATreeNode.TSNode:= ATSNode;
495 | if actNamedNodesOnly.Checked then
496 | ATreeNode.HasChildren:= ATSNode.NamedChildCount > 0 else
497 | ATreeNode.HasChildren:= ATSNode.ChildCount > 0;
498 | end;
499 |
500 | end.
501 |
--------------------------------------------------------------------------------
/VCLDemo/frmDTSQuery.dfm:
--------------------------------------------------------------------------------
1 | object DTSQueryForm: TDTSQueryForm
2 | Left = 0
3 | Top = 0
4 | Caption = 'Query'
5 | ClientHeight = 441
6 | ClientWidth = 764
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -12
11 | Font.Name = 'Segoe UI'
12 | Font.Style = []
13 | OnClose = FormClose
14 | OnDestroy = FormDestroy
15 | TextHeight = 15
16 | object Splitter1: TSplitter
17 | Left = 0
18 | Top = 250
19 | Width = 764
20 | Height = 3
21 | Cursor = crVSplit
22 | Align = alTop
23 | ExplicitTop = 120
24 | ExplicitWidth = 321
25 | end
26 | object Splitter2: TSplitter
27 | Left = 350
28 | Top = 253
29 | Height = 188
30 | ExplicitLeft = 376
31 | ExplicitTop = 165
32 | ExplicitHeight = 268
33 | end
34 | object pnlTop: TPanel
35 | Left = 0
36 | Top = 0
37 | Width = 764
38 | Height = 50
39 | Align = alTop
40 | BevelOuter = bvNone
41 | TabOrder = 0
42 | object lblQueryState: TLabel
43 | Left = 83
44 | Top = 17
45 | Width = 3
46 | Height = 15
47 | end
48 | object btnExecute: TButton
49 | Left = 8
50 | Top = 13
51 | Width = 66
52 | Height = 25
53 | Caption = 'Execute'
54 | TabOrder = 0
55 | OnClick = btnExecuteClick
56 | end
57 | end
58 | object memQuery: TMemo
59 | Left = 0
60 | Top = 50
61 | Width = 764
62 | Height = 200
63 | Align = alTop
64 | Font.Charset = DEFAULT_CHARSET
65 | Font.Color = clWindowText
66 | Font.Height = -15
67 | Font.Name = 'Consolas'
68 | Font.Style = []
69 | ParentFont = False
70 | ScrollBars = ssBoth
71 | TabOrder = 1
72 | end
73 | object pnlPredicates: TPanel
74 | Left = 0
75 | Top = 253
76 | Width = 350
77 | Height = 188
78 | Align = alLeft
79 | BevelOuter = bvNone
80 | TabOrder = 2
81 | object pnlPredicatesToolbar: TPanel
82 | Left = 0
83 | Top = 0
84 | Width = 350
85 | Height = 41
86 | Align = alTop
87 | BevelOuter = bvNone
88 | TabOrder = 0
89 | object Label1: TLabel
90 | Left = 8
91 | Top = 11
92 | Width = 41
93 | Height = 15
94 | Caption = 'Pattern:'
95 | end
96 | object cbPatternIdx: TComboBox
97 | Left = 56
98 | Top = 8
99 | Width = 57
100 | Height = 23
101 | Style = csDropDownList
102 | TabOrder = 0
103 | OnClick = cbPatternIdxClick
104 | end
105 | end
106 | object sgPredicateSteps: TStringGrid
107 | Left = 0
108 | Top = 41
109 | Width = 350
110 | Height = 147
111 | Align = alClient
112 | DefaultRowHeight = 18
113 | RowCount = 2
114 | Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goFixedRowDefAlign]
115 | TabOrder = 1
116 | end
117 | end
118 | object pnlMatches: TPanel
119 | Left = 353
120 | Top = 253
121 | Width = 411
122 | Height = 188
123 | Align = alClient
124 | BevelOuter = bvNone
125 | TabOrder = 3
126 | object pnlMatchesTop: TPanel
127 | Left = 0
128 | Top = 0
129 | Width = 411
130 | Height = 41
131 | Align = alTop
132 | BevelOuter = bvNone
133 | TabOrder = 0
134 | object lblMatch: TLabel
135 | Left = 219
136 | Top = 13
137 | Width = 3
138 | Height = 15
139 | end
140 | object btnMatchStart: TButton
141 | Left = 9
142 | Top = 9
143 | Width = 120
144 | Height = 25
145 | Caption = 'Start query cursor'
146 | Enabled = False
147 | TabOrder = 0
148 | OnClick = btnMatchStartClick
149 | end
150 | object btnMatchNext: TButton
151 | Left = 132
152 | Top = 9
153 | Width = 75
154 | Height = 25
155 | Caption = 'Next match'
156 | Enabled = False
157 | TabOrder = 1
158 | OnClick = btnMatchNextClick
159 | end
160 | end
161 | object sgMatchCaptures: TStringGrid
162 | Left = 0
163 | Top = 41
164 | Width = 411
165 | Height = 147
166 | Align = alClient
167 | ColCount = 2
168 | DefaultColWidth = 120
169 | DefaultRowHeight = 18
170 | RowCount = 1
171 | FixedRows = 0
172 | TabOrder = 1
173 | OnSelectCell = sgMatchCapturesSelectCell
174 | end
175 | end
176 | end
177 |
--------------------------------------------------------------------------------
/VCLDemo/frmDTSQuery.pas:
--------------------------------------------------------------------------------
1 | unit frmDTSQuery;
2 |
3 | interface
4 |
5 | uses
6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
7 | System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
8 | Vcl.ExtCtrls, Vcl.StdCtrls, TreeSitter.Query, TreeSitter, Vcl.Grids;
9 |
10 | type
11 | TDTSQueryForm = class(TForm)
12 | memQuery: TMemo;
13 | Splitter1: TSplitter;
14 | pnlTop: TPanel;
15 | btnExecute: TButton;
16 | lblQueryState: TLabel;
17 | pnlPredicates: TPanel;
18 | pnlPredicatesToolbar: TPanel;
19 | Label1: TLabel;
20 | cbPatternIdx: TComboBox;
21 | sgPredicateSteps: TStringGrid;
22 | Splitter2: TSplitter;
23 | pnlMatches: TPanel;
24 | pnlMatchesTop: TPanel;
25 | sgMatchCaptures: TStringGrid;
26 | btnMatchStart: TButton;
27 | btnMatchNext: TButton;
28 | lblMatch: TLabel;
29 | procedure btnExecuteClick(Sender: TObject);
30 | procedure FormDestroy(Sender: TObject);
31 | procedure FormClose(Sender: TObject; var Action: TCloseAction);
32 | procedure cbPatternIdxClick(Sender: TObject);
33 | procedure btnMatchStartClick(Sender: TObject);
34 | procedure btnMatchNextClick(Sender: TObject);
35 | procedure sgMatchCapturesSelectCell(Sender: TObject; ACol, ARow: Integer;
36 | var CanSelect: Boolean);
37 | private
38 | FTree: TTSTree;
39 | FQuery: TTSQuery;
40 | FQueryCursor: TTSQueryCursor;
41 | FCurrentMatch: TTSQueryMatch;
42 | procedure ClearQuery;
43 | procedure ClearMatches;
44 | procedure ClearPredicates;
45 | public
46 | procedure TreeDeleted;
47 | procedure NewTreeGenerated(ATree: TTSTree);
48 | end;
49 |
50 | var
51 | DTSQueryForm: TDTSQueryForm;
52 |
53 | procedure ShowQueryForm(ATree: TTSTree);
54 |
55 | implementation
56 |
57 | uses
58 | Math, frmDTSMain;
59 |
60 | {$R *.dfm}
61 |
62 | procedure ShowQueryForm(ATree: TTSTree);
63 | begin
64 | if DTSQueryForm = nil then
65 | begin
66 | Application.Createform(TDTSQueryForm, DTSQueryForm);
67 | end;
68 | DTSQueryForm.FTree:= ATree;
69 | DTSQueryForm.cbPatternIdxClick(nil);
70 | DTSQueryForm.Show;
71 | DTSQueryForm.BringToFront;
72 | end;
73 |
74 | { TDTSQuery }
75 |
76 | procedure TDTSQueryForm.btnExecuteClick(Sender: TObject);
77 | const
78 | errorStrings: array[TTSQueryError] of string = (
79 | 'None', 'Syntax', 'NodeType', 'Field', 'Capture', 'Structure', 'Language');
80 | var
81 | errorOffset: UInt32;
82 | errorType: TTSQueryError;
83 | i: Integer;
84 | begin
85 | ClearQuery;
86 |
87 | FQuery:= TTSQuery.Create(FTree.Language, memQuery.Lines.Text, errorOffset, errorType);
88 | if errorType <> TTSQueryError.TSQueryErrorNone then
89 | begin
90 | lblQueryState.Caption:= Format('Error at %d, type = %s', [errorOffset, errorStrings[errorType]]);
91 |
92 | memQuery.SetFocus;
93 | SendMessage(memQuery.Handle, EM_SETSEL, errorOffset, errorOffset);
94 | SendMessage(memQuery.Handle, EM_SCROLLCARET, 0, 0);
95 | end else
96 | begin
97 | lblQueryState.Caption:= Format('Patterns: %d, Captures: %d, Strings: %d',
98 | [FQuery.PatternCount, FQuery.CaptureCount, FQuery.StringCount]);
99 | for i:= 0 to FQuery.PatternCount - 1 do
100 | cbPatternIdx.Items.Add(IntToStr(i));
101 | btnMatchStart.Enabled:= True;
102 | end;
103 | if cbPatternIdx.Items.Count > 0 then
104 | cbPatternIdx.ItemIndex:= 0;
105 | cbPatternIdxClick(nil);
106 | end;
107 |
108 | procedure TDTSQueryForm.btnMatchNextClick(Sender: TObject);
109 | var
110 | i: Integer;
111 | captures: TTSQueryCaptureArray;
112 | begin
113 | if not FQueryCursor.NextMatch(FCurrentMatch) then
114 | begin
115 | ClearMatches;
116 | lblMatch.Caption:= 'No more matches';
117 | Exit;
118 | end;
119 | lblMatch.Caption:= Format('Match id = %d, pattern idx = %d', [FCurrentMatch.id, FCurrentMatch.pattern_index]);
120 |
121 | captures:= FCurrentMatch.CapturesArray;
122 | sgMatchCaptures.RowCount:= Length(captures) + 1;
123 | sgMatchCaptures.FixedRows:= 1;
124 | for i:= 0 to FCurrentMatch.capture_count - 1 do
125 | begin
126 | sgMatchCaptures.Cells[0, i + 1]:= IntToStr(captures[i].index);
127 | sgMatchCaptures.Cells[1, i + 1]:= captures[i].node.NodeType;
128 | end;
129 | if InRange(sgMatchCaptures.Selection.Top, 1, Length(captures)) then
130 | DTSMainForm.SelectedTSNode:= captures[sgMatchCaptures.Selection.Top - 1].node;
131 | end;
132 |
133 | procedure TDTSQueryForm.btnMatchStartClick(Sender: TObject);
134 | begin
135 | if FQueryCursor = nil then
136 | FQueryCursor:= TTSQueryCursor.Create;
137 | FQueryCursor.Execute(FQuery, FTree.RootNode);
138 | ClearMatches;
139 | sgMatchCaptures.Cells[0, 0]:= 'Capture index';
140 | sgMatchCaptures.Cells[1, 0]:= 'Node';
141 | btnMatchNext.Enabled:= True;
142 | btnMatchNextClick(nil);
143 | end;
144 |
145 | procedure TDTSQueryForm.cbPatternIdxClick(Sender: TObject);
146 | const
147 | stepTypeStrings: array[TTSQueryPredicateStepType] of string = (
148 | 'Done', 'Capture', 'String');
149 | quantifierStrings: array[TTSQuantifier] of string = (
150 | 'Zero', 'ZeroOrOne', 'ZeroOrMore', 'One', 'OneOrMore');
151 | var
152 | steps: TTSQueryPredicateStepArray;
153 | step: TTSQueryPredicateStep;
154 | i: Integer;
155 | begin
156 | if cbPatternIdx.ItemIndex >= 0 then
157 | steps:= FQuery.PredicatesForPattern(cbPatternIdx.ItemIndex);
158 | sgPredicateSteps.RowCount:= Length(steps) + 1;
159 | if sgPredicateSteps.RowCount > 1 then
160 | sgPredicateSteps.FixedRows:= 1;
161 | sgPredicateSteps.Cells[0, 0]:= 'Predicate';
162 | sgPredicateSteps.Cells[1, 0]:= 'Type';
163 | sgPredicateSteps.Cells[2, 0]:= 'ValueID';
164 | sgPredicateSteps.Cells[3, 0]:= 'Name';
165 | sgPredicateSteps.Cells[4, 0]:= 'Quantifier';
166 | for i:= 1 to Length(steps) do
167 | begin
168 | step:= steps[i - 1];
169 | sgPredicateSteps.Cells[0, i]:= IntToStr(i - 1);
170 | sgPredicateSteps.Cells[1, i]:= stepTypeStrings[step.&type];
171 | sgPredicateSteps.Cells[2, i]:= IntToStr(step.value_id);
172 | case step.&type of
173 | TTSQueryPredicateStepType.TSQueryPredicateStepTypeCapture:
174 | begin
175 | sgPredicateSteps.Cells[3, i]:= FQuery.CaptureNameForID(step.value_id);
176 | sgPredicateSteps.Cells[4, i]:= quantifierStrings[FQuery.QuantifierForCapture(cbPatternIdx.ItemIndex, step.value_id)];
177 | end;
178 | TTSQueryPredicateStepType.TSQueryPredicateStepTypeString:
179 | begin
180 | sgPredicateSteps.Cells[3, i]:= FQuery.StringValueForID(step.value_id);
181 | sgPredicateSteps.Cells[4, i]:= 'N/A';
182 | end
183 | else
184 | sgPredicateSteps.Cells[3, i]:= 'N/A';
185 | sgPredicateSteps.Cells[4, i]:= 'N/A';
186 | end;
187 | end;
188 | end;
189 |
190 | procedure TDTSQueryForm.ClearMatches;
191 | begin
192 | sgMatchCaptures.RowCount:= 1;
193 | lblMatch.Caption:= '';
194 | btnMatchNext.Enabled:= False;
195 | end;
196 |
197 | procedure TDTSQueryForm.ClearPredicates;
198 | begin
199 | cbPatternIdx.Items.Clear;
200 | sgPredicateSteps.RowCount:= 1;
201 | end;
202 |
203 | procedure TDTSQueryForm.ClearQuery;
204 | begin
205 | FreeAndNil(FQuery);
206 | btnMatchStart.Enabled:= False;
207 | lblQueryState.Caption:= '';
208 | ClearPredicates;
209 | ClearMatches;
210 | end;
211 |
212 | procedure TDTSQueryForm.FormClose(Sender: TObject; var Action: TCloseAction);
213 | begin
214 | Action:= caFree;
215 | end;
216 |
217 | procedure TDTSQueryForm.FormDestroy(Sender: TObject);
218 | begin
219 | FreeAndNil(FQueryCursor);
220 | FreeAndNil(FQuery);
221 | //FTree is no longer a clone/copy but identical to main form, otherwise
222 | //finding the node in the main forms tree would not work
223 | //(nodes belowing to different trees are not considered equal)
224 | FTree:= nil;
225 | if Self = DTSQueryForm then
226 | DTSQueryForm:= nil;
227 | end;
228 |
229 | procedure TDTSQueryForm.NewTreeGenerated(ATree: TTSTree);
230 | begin
231 | ClearQuery;
232 | FTree:= ATree;
233 | end;
234 |
235 | procedure TDTSQueryForm.sgMatchCapturesSelectCell(Sender: TObject; ACol,
236 | ARow: Integer; var CanSelect: Boolean);
237 | begin
238 | if not InRange(ARow, 1, FCurrentMatch.capture_count) then
239 | Exit;
240 |
241 | DTSMainForm.SelectedTSNode:= FCurrentMatch.captures[ARow - 1].node;
242 | end;
243 |
244 | procedure TDTSQueryForm.TreeDeleted;
245 | begin
246 | ClearQuery;
247 | end;
248 |
249 | end.
250 |
--------------------------------------------------------------------------------