Class: RAML::RipperParser

Inherits:
Object
  • Object
show all
Defined in:
lib/raml/ripper_parser.rb

Overview

RAML document parser utilizoing Ripper.

NOTE: This code is probably far from robust and is almost certainly not best the approach to implmentation. But your humble author is no expert on Ripper or parsers in general.

FIXME: This class needs work. I currently handles basic cases, but will incorrectly parse complex cases.

FIXME: Add non hash block value support.

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ RipperParser

Returns a new instance of RipperParser.



19
20
21
22
23
# File 'lib/raml/ripper_parser.rb', line 19

def initialize(options={})
  @options   = options

  self.multi_key = options[:multikey]
end

Instance Method Details

#clean(tree, data = {}) ⇒ Object (private)



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
# File 'lib/raml/ripper_parser.rb', line 50

def clean(tree, data={})
  d = data

  tag, *rest = *tree

  #show(tag, rest)

  case tag.to_s
  when "@ident"
    set(d)
    @k = rest.shift
  when "@kw"
    case rest.shift
    when "nil"   then @v << nil
    when "true"  then @v << true
    when "false" then @v << false
    end
  when "@int"
    @v << rest.shift.to_i
  when "@float"
    @v << rest.shift.to_f
  when /^@/
    @v << rest.shift
  when "do_block"
    h = [d, @k, @v]
    @k, @v = nil, []
    n = {}
    rest.each do |r|
      clean(r, n)
    end
    set(n)
    d, @k, @v = *h
    @v << n
    set(d)
  when '.'
    raise SyntaxError, "evaluations forbidden"
  else
    rest.each do |r|
      clean(r, d)
    end
  end

  return d
end

#multi_key=(bool) ⇒ Object

Set multi-key option.



31
32
33
# File 'lib/raml/ripper_parser.rb', line 31

def multi_key=(bool)
  @multi_key = !!bool
end

#multi_key?Boolean

Returns [Boolean] true/false.

Returns:

  • (Boolean)


26
27
28
# File 'lib/raml/ripper_parser.rb', line 26

def multi_key?
  @multi_key
end

#parse(code, file = nil) ⇒ Object

Parse the RAML document via Ripper.



36
37
38
39
40
41
42
43
44
45
# File 'lib/raml/ripper_parser.rb', line 36

def parse(code, file=nil)
  tree = Ripper::SexpBuilder.new(code).parse

  @k, @v = nil, []

  d = clean(tree)
  set(d)

  return d
end

#set(data) ⇒ Object (private)



96
97
98
99
100
101
102
103
# File 'lib/raml/ripper_parser.rb', line 96

def set(data)
  return unless @k
  if multi_key?
    set_multi_key(data)
  else
    set_key(data)
  end
end

#set_key(data) ⇒ Object (private)



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/raml/ripper_parser.rb', line 106

def set_key(data)
  key = @k.to_sym
  case @v.size
  when 0
    data[key] = nil
  when 1
    data[key] = @v.first
  else
    data[key] = @v
  end
  @k, @v = nil, []
end

#set_multi_key(data) ⇒ Object (private)



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/raml/ripper_parser.rb', line 120

def set_multi_key(data)
  key = @k.to_sym

  if data.key?(key)
    unless MultiValue === data[key]
      data[key] = MultiValue.new(data[key])
    end

    case @v.size
    when 1
      data[key] << @v.first
    else
      data[key] << @v
    end
    @k, @v = nil, []
  else
    set_key(data)
  end
end

#show(name, args) ⇒ Object (private)

Used for development purposes only.



141
142
143
144
145
146
147
# File 'lib/raml/ripper_parser.rb', line 141

def show(name, args)
  if @options[:debug]
    puts "#{name}:"
    p args
    puts
  end
end