tree_haver 4.0.5 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +144 -1
- data/README.md +497 -356
- data/lib/tree_haver/backends/citrus.rb +98 -114
- data/lib/tree_haver/backends/ffi.rb +76 -13
- data/lib/tree_haver/backends/java.rb +99 -14
- data/lib/tree_haver/backends/mri.rb +25 -1
- data/lib/tree_haver/backends/parslet.rb +560 -0
- data/lib/tree_haver/backends/prism.rb +1 -1
- data/lib/tree_haver/backends/psych.rb +1 -1
- data/lib/tree_haver/backends/rust.rb +1 -1
- data/lib/tree_haver/base/node.rb +8 -1
- data/lib/tree_haver/language.rb +44 -13
- data/lib/tree_haver/parser.rb +128 -38
- data/lib/tree_haver/parslet_grammar_finder.rb +224 -0
- data/lib/tree_haver/point.rb +6 -44
- data/lib/tree_haver/rspec/dependency_tags.rb +40 -1
- data/lib/tree_haver/version.rb +1 -1
- data/lib/tree_haver.rb +100 -13
- data.tar.gz.sig +0 -0
- metadata +15 -14
- metadata.gz.sig +0 -0
data/lib/tree_haver/point.rb
CHANGED
|
@@ -7,6 +7,9 @@ module TreeHaver
|
|
|
7
7
|
# - Hash access: point[:row], point[:column]
|
|
8
8
|
# - Method access: point.row, point.column
|
|
9
9
|
#
|
|
10
|
+
# TreeHaver::Point is an alias for TreeHaver::Base::Point, which is a Struct
|
|
11
|
+
# providing all the necessary functionality.
|
|
12
|
+
#
|
|
10
13
|
# @example Method access
|
|
11
14
|
# point = TreeHaver::Point.new(5, 10)
|
|
12
15
|
# point.row # => 5
|
|
@@ -18,48 +21,7 @@ module TreeHaver
|
|
|
18
21
|
#
|
|
19
22
|
# @example Converting to hash
|
|
20
23
|
# point.to_h # => {row: 5, column: 10}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Create a new Point
|
|
25
|
-
#
|
|
26
|
-
# @param row [Integer] the row (line) number, 0-indexed
|
|
27
|
-
# @param column [Integer] the column number, 0-indexed
|
|
28
|
-
def initialize(row, column)
|
|
29
|
-
@row = row
|
|
30
|
-
@column = column
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Hash-like access for compatibility
|
|
34
|
-
#
|
|
35
|
-
# @param key [Symbol, String] :row or :column
|
|
36
|
-
# @return [Integer, nil] the value or nil if key not recognized
|
|
37
|
-
def [](key)
|
|
38
|
-
case key
|
|
39
|
-
when :row, "row" then @row
|
|
40
|
-
when :column, "column" then @column
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Convert to a hash
|
|
45
|
-
#
|
|
46
|
-
# @return [Hash{Symbol => Integer}]
|
|
47
|
-
def to_h
|
|
48
|
-
{row: @row, column: @column}
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# String representation
|
|
52
|
-
#
|
|
53
|
-
# @return [String]
|
|
54
|
-
def to_s
|
|
55
|
-
"(#{@row}, #{@column})"
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Inspect representation
|
|
59
|
-
#
|
|
60
|
-
# @return [String]
|
|
61
|
-
def inspect
|
|
62
|
-
"#<TreeHaver::Point row=#{@row} column=#{@column}>"
|
|
63
|
-
end
|
|
64
|
-
end
|
|
24
|
+
#
|
|
25
|
+
# @see Base::Point The underlying Struct implementation
|
|
26
|
+
Point = Base::Point
|
|
65
27
|
end
|
|
@@ -577,6 +577,16 @@ module TreeHaver
|
|
|
577
577
|
@citrus_available = TreeHaver::BackendRegistry.available?(:citrus)
|
|
578
578
|
end
|
|
579
579
|
|
|
580
|
+
# Check if Parslet backend is available
|
|
581
|
+
#
|
|
582
|
+
# This checks if the parslet gem is installed and the backend works.
|
|
583
|
+
#
|
|
584
|
+
# @return [Boolean] true if Parslet backend is available
|
|
585
|
+
def parslet_available?
|
|
586
|
+
return @parslet_available if defined?(@parslet_available)
|
|
587
|
+
@parslet_available = TreeHaver::BackendRegistry.available?(:parslet)
|
|
588
|
+
end
|
|
589
|
+
|
|
580
590
|
# ============================================================
|
|
581
591
|
# Ruby Engine Detection
|
|
582
592
|
# ============================================================
|
|
@@ -697,11 +707,33 @@ module TreeHaver
|
|
|
697
707
|
end
|
|
698
708
|
end
|
|
699
709
|
|
|
710
|
+
# Check if toml gem is available and functional (Parslet backend for TOML)
|
|
711
|
+
#
|
|
712
|
+
# @return [Boolean] true if toml gem is available and can parse TOML
|
|
713
|
+
def toml_gem_available?
|
|
714
|
+
return @toml_gem_available if defined?(@toml_gem_available)
|
|
715
|
+
@toml_gem_available = begin
|
|
716
|
+
require "toml"
|
|
717
|
+
# Verify it can actually parse - just requiring isn't enough
|
|
718
|
+
source_toml = <<~TOML
|
|
719
|
+
# My Information
|
|
720
|
+
[machine]
|
|
721
|
+
host = "localhost"
|
|
722
|
+
TOML
|
|
723
|
+
TOML.load(source_toml)
|
|
724
|
+
true
|
|
725
|
+
rescue LoadError
|
|
726
|
+
false
|
|
727
|
+
rescue StandardError
|
|
728
|
+
false
|
|
729
|
+
end
|
|
730
|
+
end
|
|
731
|
+
|
|
700
732
|
# Check if at least one TOML backend is available
|
|
701
733
|
#
|
|
702
734
|
# @return [Boolean] true if any TOML backend works
|
|
703
735
|
def any_toml_backend_available?
|
|
704
|
-
tree_sitter_toml_available? || toml_rb_gem_available?
|
|
736
|
+
tree_sitter_toml_available? || toml_rb_gem_available? || toml_gem_available?
|
|
705
737
|
end
|
|
706
738
|
|
|
707
739
|
# Check if at least one markdown backend is available
|
|
@@ -795,6 +827,7 @@ module TreeHaver
|
|
|
795
827
|
commonmarker_backend: blocked.include?(:commonmarker) ? :blocked : commonmarker_available?,
|
|
796
828
|
markly_backend: blocked.include?(:markly) ? :blocked : markly_available?,
|
|
797
829
|
citrus_backend: blocked.include?(:citrus) ? :blocked : citrus_available?,
|
|
830
|
+
parslet_backend: blocked.include?(:parslet) ? :blocked : parslet_available?,
|
|
798
831
|
rbs_backend: blocked.include?(:rbs) ? :blocked : rbs_backend_available?,
|
|
799
832
|
# Ruby engines (*_engine)
|
|
800
833
|
ruby_engine: RUBY_ENGINE,
|
|
@@ -816,6 +849,7 @@ module TreeHaver
|
|
|
816
849
|
rbs_parsing: any_rbs_backend_available?,
|
|
817
850
|
# Specific libraries (*_gem)
|
|
818
851
|
toml_rb_gem: toml_rb_gem_available?,
|
|
852
|
+
toml_gem: toml_gem_available?,
|
|
819
853
|
rbs_gem: rbs_gem_available?,
|
|
820
854
|
}
|
|
821
855
|
end
|
|
@@ -1040,6 +1074,7 @@ RSpec.configure do |config|
|
|
|
1040
1074
|
commonmarker: :commonmarker_available?,
|
|
1041
1075
|
markly: :markly_available?,
|
|
1042
1076
|
citrus: :citrus_available?,
|
|
1077
|
+
parslet: :parslet_available?,
|
|
1043
1078
|
rbs: :rbs_backend_available?,
|
|
1044
1079
|
}
|
|
1045
1080
|
|
|
@@ -1054,6 +1089,7 @@ RSpec.configure do |config|
|
|
|
1054
1089
|
commonmarker: :commonmarker_backend,
|
|
1055
1090
|
markly: :markly_backend,
|
|
1056
1091
|
citrus: :citrus_backend,
|
|
1092
|
+
parslet: :parslet_backend,
|
|
1057
1093
|
rbs: :rbs_backend,
|
|
1058
1094
|
}
|
|
1059
1095
|
|
|
@@ -1202,10 +1238,12 @@ RSpec.configure do |config|
|
|
|
1202
1238
|
# Specific Library Tags
|
|
1203
1239
|
# ============================================================
|
|
1204
1240
|
# Tags for specific gems/libraries (*_gem suffix)
|
|
1241
|
+
# :toml_gem - the toml gem (Parslet-based TOML parser)
|
|
1205
1242
|
# :toml_rb_gem - the toml-rb gem (Citrus-based TOML parser)
|
|
1206
1243
|
# :rbs_gem - the rbs gem (official RBS parser, MRI only)
|
|
1207
1244
|
# Note: :rbs_backend is also available as an alias for :rbs_gem
|
|
1208
1245
|
|
|
1246
|
+
config.filter_run_excluding(toml_gem: true) unless deps.toml_gem_available?
|
|
1209
1247
|
config.filter_run_excluding(toml_rb_gem: true) unless deps.toml_rb_gem_available?
|
|
1210
1248
|
config.filter_run_excluding(rbs_gem: true) unless deps.rbs_gem_available?
|
|
1211
1249
|
|
|
@@ -1249,6 +1287,7 @@ RSpec.configure do |config|
|
|
|
1249
1287
|
end
|
|
1250
1288
|
|
|
1251
1289
|
# Specific libraries
|
|
1290
|
+
config.filter_run_excluding(not_toml_gem: true) if deps.toml_gem_available?
|
|
1252
1291
|
config.filter_run_excluding(not_toml_rb_gem: true) if deps.toml_rb_gem_available?
|
|
1253
1292
|
config.filter_run_excluding(not_rbs_gem: true) if deps.rbs_gem_available?
|
|
1254
1293
|
end
|
data/lib/tree_haver/version.rb
CHANGED
data/lib/tree_haver.rb
CHANGED
|
@@ -175,6 +175,20 @@ module TreeHaver
|
|
|
175
175
|
},
|
|
176
176
|
}.freeze
|
|
177
177
|
|
|
178
|
+
# Default Parslet configurations for known languages
|
|
179
|
+
#
|
|
180
|
+
# These are used by {TreeHaver.parser_for} when no explicit parslet_config is provided
|
|
181
|
+
# and tree-sitter backends are not available (e.g., on TruffleRuby).
|
|
182
|
+
#
|
|
183
|
+
# @api private
|
|
184
|
+
PARSLET_DEFAULTS = {
|
|
185
|
+
toml: {
|
|
186
|
+
gem_name: "toml",
|
|
187
|
+
grammar_const: "TOML::Parslet",
|
|
188
|
+
require_path: "toml",
|
|
189
|
+
},
|
|
190
|
+
}.freeze
|
|
191
|
+
|
|
178
192
|
# Namespace for backend implementations
|
|
179
193
|
#
|
|
180
194
|
# TreeHaver provides multiple backends to support different Ruby implementations:
|
|
@@ -183,6 +197,7 @@ module TreeHaver
|
|
|
183
197
|
# - {Backends::FFI} - Uses Ruby FFI to call libtree-sitter directly
|
|
184
198
|
# - {Backends::Java} - Uses JRuby's Java integration
|
|
185
199
|
# - {Backends::Citrus} - Uses Citrus PEG parser (pure Ruby, portable)
|
|
200
|
+
# - {Backends::Parslet} - Uses Parslet PEG parser (pure Ruby, portable)
|
|
186
201
|
# - {Backends::Prism} - Uses Ruby's built-in Prism parser (Ruby-only, stdlib in 3.4+)
|
|
187
202
|
# - {Backends::Psych} - Uses Ruby's built-in Psych parser (YAML-only, stdlib)
|
|
188
203
|
module Backends
|
|
@@ -191,6 +206,7 @@ module TreeHaver
|
|
|
191
206
|
autoload :FFI, File.join(__dir__, "tree_haver", "backends", "ffi")
|
|
192
207
|
autoload :Java, File.join(__dir__, "tree_haver", "backends", "java")
|
|
193
208
|
autoload :Citrus, File.join(__dir__, "tree_haver", "backends", "citrus")
|
|
209
|
+
autoload :Parslet, File.join(__dir__, "tree_haver", "backends", "parslet")
|
|
194
210
|
autoload :Prism, File.join(__dir__, "tree_haver", "backends", "prism")
|
|
195
211
|
autoload :Psych, File.join(__dir__, "tree_haver", "backends", "psych")
|
|
196
212
|
|
|
@@ -205,6 +221,7 @@ module TreeHaver
|
|
|
205
221
|
ffi: [:mri], # FFI segfaults if MRI (ruby_tree_sitter) has been loaded
|
|
206
222
|
java: [],
|
|
207
223
|
citrus: [],
|
|
224
|
+
parslet: [], # Parslet has no conflicts with other backends
|
|
208
225
|
prism: [], # Prism has no conflicts with other backends
|
|
209
226
|
psych: [], # Psych has no conflicts with other backends
|
|
210
227
|
}.freeze
|
|
@@ -260,6 +277,19 @@ module TreeHaver
|
|
|
260
277
|
# @see CitrusGrammarFinder
|
|
261
278
|
autoload :CitrusGrammarFinder, File.join(__dir__, "tree_haver", "citrus_grammar_finder")
|
|
262
279
|
|
|
280
|
+
# Parslet grammar finder for discovering and registering Parslet-based parsers
|
|
281
|
+
#
|
|
282
|
+
# @example Register toml gem
|
|
283
|
+
# finder = TreeHaver::ParsletGrammarFinder.new(
|
|
284
|
+
# language: :toml,
|
|
285
|
+
# gem_name: "toml",
|
|
286
|
+
# grammar_const: "TOML::Parslet"
|
|
287
|
+
# )
|
|
288
|
+
# finder.register! if finder.available?
|
|
289
|
+
#
|
|
290
|
+
# @see ParsletGrammarFinder
|
|
291
|
+
autoload :ParsletGrammarFinder, File.join(__dir__, "tree_haver", "parslet_grammar_finder")
|
|
292
|
+
|
|
263
293
|
# Point class for position information (row, column)
|
|
264
294
|
autoload :Point, File.join(__dir__, "tree_haver", "point")
|
|
265
295
|
|
|
@@ -368,7 +398,7 @@ module TreeHaver
|
|
|
368
398
|
VALID_NATIVE_BACKENDS = %w[mri rust ffi java].freeze
|
|
369
399
|
|
|
370
400
|
# Valid pure Ruby backend names (no native extensions)
|
|
371
|
-
VALID_RUBY_BACKENDS = %w[citrus prism psych commonmarker markly].freeze
|
|
401
|
+
VALID_RUBY_BACKENDS = %w[citrus parslet prism psych commonmarker markly].freeze
|
|
372
402
|
|
|
373
403
|
# All valid backend names
|
|
374
404
|
VALID_BACKENDS = (VALID_NATIVE_BACKENDS + VALID_RUBY_BACKENDS + %w[auto none]).freeze
|
|
@@ -734,6 +764,8 @@ module TreeHaver
|
|
|
734
764
|
Backends::Java
|
|
735
765
|
when :citrus
|
|
736
766
|
Backends::Citrus
|
|
767
|
+
when :parslet
|
|
768
|
+
Backends::Parslet
|
|
737
769
|
when :prism
|
|
738
770
|
Backends::Prism
|
|
739
771
|
when :psych
|
|
@@ -875,6 +907,8 @@ module TreeHaver
|
|
|
875
907
|
Backends::Java
|
|
876
908
|
when :citrus
|
|
877
909
|
Backends::Citrus
|
|
910
|
+
when :parslet
|
|
911
|
+
Backends::Parslet
|
|
878
912
|
when :prism
|
|
879
913
|
Backends::Prism
|
|
880
914
|
when :psych
|
|
@@ -958,6 +992,7 @@ module TreeHaver
|
|
|
958
992
|
# @param path [String, nil] absolute path to the language shared library (for tree-sitter)
|
|
959
993
|
# @param symbol [String, nil] optional exported factory symbol (e.g., "tree_sitter_toml")
|
|
960
994
|
# @param grammar_module [Module, nil] Citrus grammar module that responds to .parse(source)
|
|
995
|
+
# @param grammar_class [Class, nil] Parslet grammar class that inherits from Parslet::Parser
|
|
961
996
|
# @param backend_module [Module, nil] pure Ruby backend module with Language/Parser classes
|
|
962
997
|
# @param backend_type [Symbol, nil] backend type for backend_module (defaults to module name)
|
|
963
998
|
# @param gem_name [String, nil] optional gem name for error messages
|
|
@@ -974,6 +1009,12 @@ module TreeHaver
|
|
|
974
1009
|
# grammar_module: TomlRB::Document,
|
|
975
1010
|
# gem_name: "toml-rb"
|
|
976
1011
|
# )
|
|
1012
|
+
# @example Register Parslet grammar only
|
|
1013
|
+
# TreeHaver.register_language(
|
|
1014
|
+
# :toml,
|
|
1015
|
+
# grammar_class: TOML::Parslet,
|
|
1016
|
+
# gem_name: "toml"
|
|
1017
|
+
# )
|
|
977
1018
|
# @example Register pure Ruby backend (external gem like rbs-merge)
|
|
978
1019
|
# TreeHaver.register_language(
|
|
979
1020
|
# :rbs,
|
|
@@ -1001,7 +1042,7 @@ module TreeHaver
|
|
|
1001
1042
|
# gem_name: "toml-rb"
|
|
1002
1043
|
# )
|
|
1003
1044
|
# # Now TreeHaver::Language.toml works with ANY backend!
|
|
1004
|
-
def register_language(name, path: nil, symbol: nil, grammar_module: nil, backend_module: nil, backend_type: nil, gem_name: nil)
|
|
1045
|
+
def register_language(name, path: nil, symbol: nil, grammar_module: nil, grammar_class: nil, backend_module: nil, backend_type: nil, gem_name: nil)
|
|
1005
1046
|
# Register tree-sitter backend if path provided
|
|
1006
1047
|
# Note: Uses `if` not `elsif` so both backends can be registered in one call
|
|
1007
1048
|
if path
|
|
@@ -1019,6 +1060,16 @@ module TreeHaver
|
|
|
1019
1060
|
LanguageRegistry.register(name, :citrus, grammar_module: grammar_module, gem_name: gem_name)
|
|
1020
1061
|
end
|
|
1021
1062
|
|
|
1063
|
+
# Register Parslet backend if grammar_class provided
|
|
1064
|
+
# Note: Uses `if` not `elsif` so multiple backends can be registered in one call
|
|
1065
|
+
if grammar_class
|
|
1066
|
+
unless grammar_class.respond_to?(:new)
|
|
1067
|
+
raise ArgumentError, "Grammar class must respond to :new"
|
|
1068
|
+
end
|
|
1069
|
+
|
|
1070
|
+
LanguageRegistry.register(name, :parslet, grammar_class: grammar_class, gem_name: gem_name)
|
|
1071
|
+
end
|
|
1072
|
+
|
|
1022
1073
|
# Register pure Ruby backend if backend_module provided
|
|
1023
1074
|
# This is used by external gems (like rbs-merge) to register their own backends
|
|
1024
1075
|
if backend_module
|
|
@@ -1028,13 +1079,13 @@ module TreeHaver
|
|
|
1028
1079
|
end
|
|
1029
1080
|
|
|
1030
1081
|
# Require at least one backend to be registered
|
|
1031
|
-
if path.nil? && grammar_module.nil? && backend_module.nil?
|
|
1032
|
-
raise ArgumentError, "Must provide at least one of: path (tree-sitter), grammar_module (Citrus), or backend_module (pure Ruby)"
|
|
1082
|
+
if path.nil? && grammar_module.nil? && grammar_class.nil? && backend_module.nil?
|
|
1083
|
+
raise ArgumentError, "Must provide at least one of: path (tree-sitter), grammar_module (Citrus), grammar_class (Parslet), or backend_module (pure Ruby)"
|
|
1033
1084
|
end
|
|
1034
1085
|
|
|
1035
|
-
# Note: No early return! This method intentionally processes
|
|
1086
|
+
# Note: No early return! This method intentionally processes all `if` blocks
|
|
1036
1087
|
# above to allow registering multiple backends for the same language.
|
|
1037
|
-
#
|
|
1088
|
+
# tree-sitter, Citrus, and Parslet can be registered simultaneously for maximum
|
|
1038
1089
|
# flexibility. See method documentation for rationale.
|
|
1039
1090
|
nil
|
|
1040
1091
|
end
|
|
@@ -1075,15 +1126,17 @@ module TreeHaver
|
|
|
1075
1126
|
# Respects the effective backend setting (via TREE_HAVER_BACKEND env var,
|
|
1076
1127
|
# TreeHaver.backend=, or with_backend block).
|
|
1077
1128
|
#
|
|
1078
|
-
# Supports
|
|
1129
|
+
# Supports four types of backends:
|
|
1079
1130
|
# 1. Tree-sitter native backends (auto-discovered or explicit path)
|
|
1080
1131
|
# 2. Citrus grammars (pure Ruby, via CITRUS_DEFAULTS or explicit config)
|
|
1081
|
-
# 3.
|
|
1132
|
+
# 3. Parslet grammars (pure Ruby, via PARSLET_DEFAULTS or explicit config)
|
|
1133
|
+
# 4. Pure Ruby backends (registered via backend_module, e.g., Prism, Psych, RBS)
|
|
1082
1134
|
#
|
|
1083
1135
|
# @param language_name [Symbol, String] the language to parse (e.g., :toml, :json, :ruby, :yaml, :rbs)
|
|
1084
1136
|
# @param library_path [String, nil] optional explicit path to tree-sitter grammar library
|
|
1085
1137
|
# @param symbol [String, nil] optional tree-sitter symbol name (defaults to "tree_sitter_<name>")
|
|
1086
1138
|
# @param citrus_config [Hash, nil] optional Citrus fallback configuration
|
|
1139
|
+
# @param parslet_config [Hash, nil] optional Parslet fallback configuration
|
|
1087
1140
|
# @return [TreeHaver::Parser] configured parser with language set
|
|
1088
1141
|
# @raise [TreeHaver::NotAvailable] if no parser backend is available for the language
|
|
1089
1142
|
#
|
|
@@ -1093,11 +1146,14 @@ module TreeHaver
|
|
|
1093
1146
|
# @example Force Citrus backend
|
|
1094
1147
|
# TreeHaver.with_backend(:citrus) { TreeHaver.parser_for(:toml) }
|
|
1095
1148
|
#
|
|
1149
|
+
# @example Force Parslet backend
|
|
1150
|
+
# TreeHaver.with_backend(:parslet) { TreeHaver.parser_for(:toml) }
|
|
1151
|
+
#
|
|
1096
1152
|
# @example Use registered pure Ruby backend (e.g., RBS)
|
|
1097
1153
|
# # First, rbs-merge registers its backend:
|
|
1098
1154
|
# # TreeHaver.register_language(:rbs, backend_module: Rbs::Merge::RbsBackend, backend_type: :rbs)
|
|
1099
1155
|
# parser = TreeHaver.parser_for(:rbs)
|
|
1100
|
-
def parser_for(language_name, library_path: nil, symbol: nil, citrus_config: nil)
|
|
1156
|
+
def parser_for(language_name, library_path: nil, symbol: nil, citrus_config: nil, parslet_config: nil)
|
|
1101
1157
|
# Ensure built-in pure Ruby backends are registered
|
|
1102
1158
|
ensure_builtin_backends_registered!
|
|
1103
1159
|
|
|
@@ -1106,18 +1162,24 @@ module TreeHaver
|
|
|
1106
1162
|
requested = effective_backend
|
|
1107
1163
|
|
|
1108
1164
|
# Determine which backends to try based on effective_backend
|
|
1165
|
+
# When a specific backend is requested, only try that backend
|
|
1109
1166
|
try_tree_sitter = (requested == :auto) || NATIVE_BACKENDS.include?(requested)
|
|
1110
1167
|
try_citrus = (requested == :auto) || (requested == :citrus)
|
|
1168
|
+
try_parslet = (requested == :auto) || (requested == :parslet)
|
|
1169
|
+
|
|
1170
|
+
# When Citrus or Parslet is explicitly requested, don't try tree-sitter
|
|
1171
|
+
if requested == :citrus || requested == :parslet
|
|
1172
|
+
try_tree_sitter = false
|
|
1173
|
+
end
|
|
1111
1174
|
|
|
1112
1175
|
language = nil
|
|
1113
|
-
parser = nil
|
|
1114
1176
|
|
|
1115
1177
|
# First, check for registered pure Ruby backends
|
|
1116
1178
|
# These take precedence when explicitly requested or when no other backend is available
|
|
1117
1179
|
registration = registered_language(name)
|
|
1118
|
-
# Find any registered backend_module (not tree_sitter or
|
|
1180
|
+
# Find any registered backend_module (not tree_sitter, citrus, or parslet)
|
|
1119
1181
|
registration&.each do |backend_type, config|
|
|
1120
|
-
next if %i[tree_sitter citrus].include?(backend_type)
|
|
1182
|
+
next if %i[tree_sitter citrus parslet].include?(backend_type)
|
|
1121
1183
|
next unless config[:backend_module]
|
|
1122
1184
|
|
|
1123
1185
|
backend_mod = config[:backend_module]
|
|
@@ -1153,9 +1215,14 @@ module TreeHaver
|
|
|
1153
1215
|
language = load_citrus_language(name, citrus_config: citrus_config)
|
|
1154
1216
|
end
|
|
1155
1217
|
|
|
1218
|
+
# Try Parslet if applicable
|
|
1219
|
+
if try_parslet && !language
|
|
1220
|
+
language = load_parslet_language(name, parslet_config: parslet_config)
|
|
1221
|
+
end
|
|
1222
|
+
|
|
1156
1223
|
# Raise if nothing worked
|
|
1157
1224
|
raise NotAvailable, "No parser available for #{name}. " \
|
|
1158
|
-
"Install tree-sitter-#{name} or configure a Citrus grammar." unless language
|
|
1225
|
+
"Install tree-sitter-#{name} or configure a Citrus/Parslet grammar." unless language
|
|
1159
1226
|
|
|
1160
1227
|
# Create and configure parser
|
|
1161
1228
|
parser = Parser.new
|
|
@@ -1218,6 +1285,26 @@ module TreeHaver
|
|
|
1218
1285
|
rescue NotAvailable, ArgumentError, LoadError, NameError, TypeError
|
|
1219
1286
|
nil
|
|
1220
1287
|
end
|
|
1288
|
+
|
|
1289
|
+
# Load a Parslet language from configuration or defaults
|
|
1290
|
+
# @return [Language, nil]
|
|
1291
|
+
def load_parslet_language(name, parslet_config: nil)
|
|
1292
|
+
config = parslet_config || PARSLET_DEFAULTS[name] || {}
|
|
1293
|
+
return unless config[:gem_name] && config[:grammar_const]
|
|
1294
|
+
|
|
1295
|
+
finder = ParsletGrammarFinder.new(
|
|
1296
|
+
language: name,
|
|
1297
|
+
gem_name: config[:gem_name],
|
|
1298
|
+
grammar_const: config[:grammar_const],
|
|
1299
|
+
require_path: config[:require_path],
|
|
1300
|
+
)
|
|
1301
|
+
return unless finder.available?
|
|
1302
|
+
|
|
1303
|
+
finder.register!
|
|
1304
|
+
Language.public_send(name)
|
|
1305
|
+
rescue NotAvailable, ArgumentError, LoadError, NameError, TypeError
|
|
1306
|
+
nil
|
|
1307
|
+
end
|
|
1221
1308
|
end
|
|
1222
1309
|
|
|
1223
1310
|
# Language and Parser classes have been moved to separate files:
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tree_haver
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 5.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -227,12 +227,11 @@ dependencies:
|
|
|
227
227
|
- - ">="
|
|
228
228
|
- !ruby/object:Gem::Version
|
|
229
229
|
version: 1.0.3
|
|
230
|
-
description: "\U0001F334 TreeHaver is a cross-Ruby adapter for
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
Rust extensions, FFI, or Java)."
|
|
230
|
+
description: "\U0001F334 TreeHaver is a cross-Ruby adapter for many AST parsing libraries;
|
|
231
|
+
supporting MRI Ruby, JRuby, & TruffleRuby. Provides unified parsing API & AST when
|
|
232
|
+
using ruby_tree_sitter, parslet, citrus, ffi, tree_stump (Rust), JRuby JARs, etc.
|
|
233
|
+
As Faraday is to HTTP clients, this is for ASTs: 'Learn once & write once & run
|
|
234
|
+
anywhere'"
|
|
236
235
|
email:
|
|
237
236
|
- floss@galtzo.com
|
|
238
237
|
executables: []
|
|
@@ -266,6 +265,7 @@ files:
|
|
|
266
265
|
- lib/tree_haver/backends/ffi.rb
|
|
267
266
|
- lib/tree_haver/backends/java.rb
|
|
268
267
|
- lib/tree_haver/backends/mri.rb
|
|
268
|
+
- lib/tree_haver/backends/parslet.rb
|
|
269
269
|
- lib/tree_haver/backends/prism.rb
|
|
270
270
|
- lib/tree_haver/backends/psych.rb
|
|
271
271
|
- lib/tree_haver/backends/rust.rb
|
|
@@ -283,6 +283,7 @@ files:
|
|
|
283
283
|
- lib/tree_haver/library_path_utils.rb
|
|
284
284
|
- lib/tree_haver/node.rb
|
|
285
285
|
- lib/tree_haver/parser.rb
|
|
286
|
+
- lib/tree_haver/parslet_grammar_finder.rb
|
|
286
287
|
- lib/tree_haver/path_validator.rb
|
|
287
288
|
- lib/tree_haver/point.rb
|
|
288
289
|
- lib/tree_haver/rspec.rb
|
|
@@ -298,10 +299,10 @@ licenses:
|
|
|
298
299
|
- MIT
|
|
299
300
|
metadata:
|
|
300
301
|
homepage_uri: https://tree-haver.galtzo.com/
|
|
301
|
-
source_code_uri: https://github.com/kettle-rb/tree_haver/tree/
|
|
302
|
-
changelog_uri: https://github.com/kettle-rb/tree_haver/blob/
|
|
302
|
+
source_code_uri: https://github.com/kettle-rb/tree_haver/tree/v5.0.0
|
|
303
|
+
changelog_uri: https://github.com/kettle-rb/tree_haver/blob/v5.0.0/CHANGELOG.md
|
|
303
304
|
bug_tracker_uri: https://github.com/kettle-rb/tree_haver/issues
|
|
304
|
-
documentation_uri: https://www.rubydoc.info/gems/tree_haver/
|
|
305
|
+
documentation_uri: https://www.rubydoc.info/gems/tree_haver/5.0.0
|
|
305
306
|
funding_uri: https://github.com/sponsors/pboling
|
|
306
307
|
wiki_uri: https://github.com/kettle-rb/tree_haver/wiki
|
|
307
308
|
news_uri: https://www.railsbling.com/tags/tree_haver
|
|
@@ -309,8 +310,8 @@ metadata:
|
|
|
309
310
|
rubygems_mfa_required: 'true'
|
|
310
311
|
rdoc_options:
|
|
311
312
|
- "--title"
|
|
312
|
-
- "tree_haver - \U0001F334 Cross-Ruby adapter for
|
|
313
|
-
MRI, JRuby, and TruffleRuby"
|
|
313
|
+
- "tree_haver - \U0001F334 Cross-Ruby adapter for AST parsing libraries, like tree-sitter,
|
|
314
|
+
citrus, & parslet; works on MRI, JRuby, and TruffleRuby"
|
|
314
315
|
- "--main"
|
|
315
316
|
- README.md
|
|
316
317
|
- "--exclude"
|
|
@@ -333,6 +334,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
333
334
|
requirements: []
|
|
334
335
|
rubygems_version: 4.0.3
|
|
335
336
|
specification_version: 4
|
|
336
|
-
summary: "\U0001F334 Cross-Ruby adapter for
|
|
337
|
-
JRuby, and TruffleRuby"
|
|
337
|
+
summary: "\U0001F334 Cross-Ruby adapter for AST parsing libraries, like tree-sitter,
|
|
338
|
+
citrus, & parslet; works on MRI, JRuby, and TruffleRuby"
|
|
338
339
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|