Class: Parslet::Parser::PrettyPrinter

Inherits:
Object
  • Object
show all
Defined in:
lib/parslet/export.rb

Overview

A helper class that formats Citrus and Treetop grammars as a string.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(visitor_klass) ⇒ PrettyPrinter

Returns a new instance of PrettyPrinter.



73
74
75
# File 'lib/parslet/export.rb', line 73

def initialize(visitor_klass)
  @visitor = visitor_klass.new(self)
end

Instance Attribute Details

#visitorObject (readonly)

Returns the value of attribute visitor.



72
73
74
# File 'lib/parslet/export.rb', line 72

def visitor
  @visitor
end

Instance Method Details

#deferred(name, content) ⇒ Object

Whenever the visitor encounters an rule in a parslet, it defers the pretty printing of the rule by calling this method.



114
115
116
117
# File 'lib/parslet/export.rb', line 114

def deferred(name, content)
  @todo ||= []
  @todo << [name, content]
end

#mangle_name(str) ⇒ Object

Mangles names so that Citrus and Treetop can live with it. This mostly transforms some of the things that Ruby allows into other patterns. If there is collision, we will not detect it for now.



123
124
125
# File 'lib/parslet/export.rb', line 123

def mangle_name(str)
  str.to_s.sub(/\?$/, '_p')
end

#pretty_print(name, parslet) ⇒ Object

Pretty prints the given parslet using the visitor that has been configured in initialize. Returns the string representation of the Citrus or Treetop grammar.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/parslet/export.rb', line 81

def pretty_print(name, parslet)
  output = "grammar #{name}\n"
  
  output << rule('root', parslet)
  
  seen = Set.new
  loop do
    # @todo is constantly filled by the visitor (see #deferred). We 
    # keep going until it is empty.
    break if @todo.empty?
    name, block = @todo.shift

    # Track what rules we've already seen. This breaks loops.
    next if seen.include?(name)
    seen << name

    output << rule(name, block.call)
  end
  
  output << "end\n"
end

#rule(name, parslet) ⇒ Object

Formats a rule in either dialect.



105
106
107
108
109
# File 'lib/parslet/export.rb', line 105

def rule(name, parslet)
  "  rule #{mangle_name name}\n" << 
  "    " << parslet.accept(visitor) << "\n" <<
  "  end\n"
end