Class: TreeHaver::ParsletGrammarFinder
- Inherits:
-
Object
- Object
- TreeHaver::ParsletGrammarFinder
- Defined in:
- lib/tree_haver/parslet_grammar_finder.rb
Overview
Utility for finding and registering Parslet grammar gems.
ParsletGrammarFinder provides language-agnostic discovery of Parslet grammar gems. Given a language name and gem information, it attempts to load the grammar and register it with tree_haver.
Unlike tree-sitter grammars (which are .so files), Parslet grammars are Ruby classes that inherit from Parslet::Parser. This class handles the discovery and registration of these grammars.
Instance Attribute Summary collapse
-
#gem_name ⇒ String
readonly
The gem name to require.
-
#grammar_const ⇒ String
readonly
The constant path to the grammar class (e.g., "TOML::Parslet").
-
#language_name ⇒ Symbol
readonly
The language identifier.
-
#require_path ⇒ String?
readonly
Custom require path (defaults to gem_name).
Instance Method Summary collapse
-
#available? ⇒ Boolean
Check if the Parslet grammar is available.
-
#grammar_class ⇒ Class?
Get the resolved grammar class.
-
#initialize(language:, gem_name:, grammar_const:, require_path: nil) ⇒ ParsletGrammarFinder
constructor
Initialize a Parslet grammar finder.
-
#not_found_message ⇒ String
Get a human-readable error message when grammar is not found.
-
#register!(raise_on_missing: false) ⇒ Boolean
Register this Parslet grammar with TreeHaver.
-
#search_info ⇒ Hash
Get debug information about the search.
Constructor Details
#initialize(language:, gem_name:, grammar_const:, require_path: nil) ⇒ ParsletGrammarFinder
Initialize a Parslet grammar finder
51 52 53 54 55 56 57 58 59 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 51 def initialize(language:, gem_name:, grammar_const:, require_path: nil) @language_name = language.to_sym @gem_name = gem_name @grammar_const = grammar_const @require_path = require_path || gem_name @load_attempted = false @available = false @grammar_class = nil end |
Instance Attribute Details
#gem_name ⇒ String (readonly)
Returns the gem name to require.
37 38 39 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 37 def gem_name @gem_name end |
#grammar_const ⇒ String (readonly)
Returns the constant path to the grammar class (e.g., "TOML::Parslet").
40 41 42 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 40 def grammar_const @grammar_const end |
#language_name ⇒ Symbol (readonly)
Returns the language identifier.
34 35 36 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 34 def language_name @language_name end |
#require_path ⇒ String? (readonly)
Returns custom require path (defaults to gem_name).
43 44 45 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 43 def require_path @require_path end |
Instance Method Details
#available? ⇒ Boolean
Check if the Parslet grammar is available
Attempts to require the gem and resolve the grammar constant. Result is cached after first call.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 67 def available? return @available if @load_attempted @load_attempted = true debug = ENV['TREE_HAVER_DEBUG'] # Guard against nil require_path (can happen if gem_name was nil) if @require_path.nil? || @require_path.empty? warn("ParsletGrammarFinder: require_path is nil or empty for #{@language_name}") if debug @available = false return false end begin # Try to require the gem require @require_path # Try to resolve the constant @grammar_class = resolve_constant(@grammar_const) # Verify it can create a parser instance with a parse method unless valid_grammar_class?(@grammar_class) if debug warn("ParsletGrammarFinder: #{@grammar_const} is not a valid Parslet grammar class") warn("ParsletGrammarFinder: #{@grammar_const}.class = #{@grammar_class.class}") end @available = false return false end @available = true rescue LoadError => e # simplecov:disable defensive - requires gem to not be installed if debug warn("ParsletGrammarFinder: Failed to load '#{@require_path}': #{e.class}: #{e.}") warn("ParsletGrammarFinder: LoadError backtrace:\n #{e.backtrace&.first(10)&.join("\n ")}") end @available = false # simplecov:enable rescue NameError => e # simplecov:disable defensive - requires gem with missing constant if debug warn("ParsletGrammarFinder: Failed to resolve '#{@grammar_const}': #{e.class}: #{e.}") warn("ParsletGrammarFinder: NameError backtrace:\n #{e.backtrace&.first(10)&.join("\n ")}") end @available = false # simplecov:enable rescue TypeError => e # simplecov:disable defensive - TruffleRuby-specific edge case warn("ParsletGrammarFinder: TypeError during load of '#{@require_path}': #{e.class}: #{e.}") warn('ParsletGrammarFinder: This may be a TruffleRuby bundled_gems.rb issue') warn("ParsletGrammarFinder: TypeError backtrace:\n #{e.backtrace&.first(10)&.join("\n ")}") if debug @available = false # simplecov:enable rescue StandardError => e # simplecov:disable defensive - catch-all for unexpected errors warn("ParsletGrammarFinder: Unexpected error: #{e.class}: #{e.}") warn("ParsletGrammarFinder: backtrace:\n #{e.backtrace&.first(10)&.join("\n ")}") if debug @available = false # simplecov:enable end @available end |
#grammar_class ⇒ Class?
Get the resolved grammar class
135 136 137 138 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 135 def grammar_class available? # Ensure we've tried to load @grammar_class end |
#not_found_message ⇒ String
Get a human-readable error message when grammar is not found
180 181 182 183 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 180 def "Parslet grammar for #{@language_name} not found. " \ "Install #{@gem_name} gem: gem install #{@gem_name}" end |
#register!(raise_on_missing: false) ⇒ Boolean
Register this Parslet grammar with TreeHaver
After registration, the language can be used via:
TreeHaver::Language.{language_name}
148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 148 def register!(raise_on_missing: false) unless available? raise NotAvailable, if raise_on_missing return false end TreeHaver.register_language( @language_name, grammar_class: @grammar_class, gem_name: @gem_name ) true end |
#search_info ⇒ Hash
Get debug information about the search
166 167 168 169 170 171 172 173 174 175 |
# File 'lib/tree_haver/parslet_grammar_finder.rb', line 166 def search_info { language: @language_name, gem_name: @gem_name, grammar_const: @grammar_const, require_path: @require_path, available: available?, grammar_class: @grammar_class&.name } end |