Module: Piggly::Parser

Defined in:
lib/piggly/parser.rb,
lib/piggly/parser/nodes.rb,
lib/piggly/parser/traversal.rb

Overview

Pl/pgSQL Parser, returns a tree of NodeClass values (see nodes.rb)

Defined Under Namespace

Modules: Nodes, Traversal Classes: Failure

Class Method Summary collapse

Class Method Details

.grammar_pathObject



34
# File 'lib/piggly/parser.rb', line 34

def grammar_path; "#{File.dirname(__FILE__)}/parser/grammar.tt" end

.nodes_pathObject



35
# File 'lib/piggly/parser.rb', line 35

def nodes_path;   "#{File.dirname(__FILE__)}/parser/nodes.rb"   end

.parse(string) ⇒ Object

Returns lazy parse tree (only parsed when the value is needed)



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/piggly/parser.rb', line 15

def parse(string)
  Util::Thunk.new do
    p = parser

    begin
      # Ensure input is UTF-8 encoded
      input = string.dup.force_encoding('UTF-8')
      # Downcase input for case-insensitive parsing
      input = input.downcase
      tree = p.parse(input)
      tree or raise Failure, "#{p.failure_reason}"
    ensure
      # Restore the original string after parsing
      input.replace(string)
    end
  end
end

.parserObject

Returns treetop parser (recompiled as needed)



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/piggly/parser.rb', line 38

def parser
  return @parser if @parser
  
  load_support

  # @todo: Compare with the version of treetop
  if Util::File.stale?(parser_path, grammar_path)
    # Regenerate the parser when the grammar is updated
    Treetop::Compiler::GrammarCompiler.new.compile(grammar_path, parser_path)
    # Remove existing constant before loading to avoid warnings
    Object.send(:remove_const, :PigglyParser) if Object.const_defined?(:PigglyParser)
    Object.send(:remove_const, :PigglyParserParser) if Object.const_defined?(:PigglyParserParser)
    load parser_path
    @parser = nil  # Clear cache when regenerating
  else
    require parser_path unless defined?(::PigglyParser::Parser)
  end

  @parser ||= ::PigglyParser::Parser.new
end

.parser_pathObject



33
# File 'lib/piggly/parser.rb', line 33

def parser_path;  "#{File.dirname(__FILE__)}/parser/parser.rb"  end