Class: Starry::Parser

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/starry/parser.rb

Instance Method Summary collapse

Constructor Details

#initialize(input, symbolize_names: false) ⇒ Parser

Returns a new instance of Parser.



9
10
11
12
# File 'lib/starry/parser.rb', line 9

def initialize(input, symbolize_names: false)
  @s = StringScanner.new(input)
  @symbolize_names = symbolize_names
end

Instance Method Details

#parse(type) ⇒ Object



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

def parse(type)
  consume_sp
  output = (
    case type
    when :list
      parse_list
    when :dictionary
      parse_dictionary
    when :item
      parse_item
    else
      raise ArgumentError
    end
  )
  consume_sp
  unless @s.eos?
    parse_error(:eos)
  end
  output
end

#parse_bare_itemObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/starry/parser.rb', line 99

def parse_bare_item
  case
  when check(/[-0-9]/)
    parse_integer_or_decimal
  when check('"')
    parse_string
  when check(/[A-Za-z*]/)
    parse_token
  when check(':')
    parse_byte_sequence
  when check('?')
    parse_boolean
  else
    parse_error
  end
end

#parse_booleanObject



178
179
180
181
182
183
# File 'lib/starry/parser.rb', line 178

def parse_boolean
  unless scan(/\?([01])/)
    parse_error
  end
  @s[1] == '1'
end

#parse_byte_sequenceObject



171
172
173
174
175
176
# File 'lib/starry/parser.rb', line 171

def parse_byte_sequence
  expect(':')
  output = scan(/[A-Za-z0-9+\/=]*/)
  expect(':')
  Base64.decode64(output)
end

#parse_dictionaryObject



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/starry/parser.rb', line 73

def parse_dictionary
  output = {}
  until eos?
    key = parse_key
    if scan('=')
      value = parse_item_or_inner_list
    else
      parameters = parse_parameters
      value = Starry::Item.new(true, parameters)
    end
    output[key] = value
    consume_ows
    return output if eos?
    expect(',')
    consume_ows
    parse_error if eos?
  end
  output
end

#parse_inner_listObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/starry/parser.rb', line 56

def parse_inner_list
  output = []
  expect('(')
  until eos?
    consume_sp
    if scan(')')
      parameters = parse_parameters
      return Starry::InnerList.new(output, parameters)
    end
    output << parse_item
    unless check(/[ )]/)
      parse_error([' ', ')'])
    end
  end
  parse_error(')')
end

#parse_integer_or_decimalObject



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/starry/parser.rb', line 142

def parse_integer_or_decimal
  unless output = scan(/-?(\d+)(\.\d+)?/)
    parse_error
  end
  if @s[2]
    if @s[1].size > 12 || @s[2].size > 4
      parse_error
    end
    output.to_f
  else
    if @s[1].size > 15
      parse_error
    end
    output.to_i
  end
end

#parse_itemObject



93
94
95
96
97
# File 'lib/starry/parser.rb', line 93

def parse_item
  value = parse_bare_item
  parameters = parse_parameters
  Starry::Item.new(value, parameters)
end

#parse_item_or_inner_listObject



48
49
50
51
52
53
54
# File 'lib/starry/parser.rb', line 48

def parse_item_or_inner_list
  if check('(')
    parse_inner_list
  else
    parse_item
  end
end

#parse_keyObject



132
133
134
135
136
137
138
139
140
# File 'lib/starry/parser.rb', line 132

def parse_key
  parse_error unless check(/[a-z*]/)
  output = scan(/[a-z0-9_\-.*]*/)
  if @symbolize_names
    output.to_sym
  else
    output
  end
end

#parse_listObject



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/starry/parser.rb', line 35

def parse_list
  output = []
  until eos?
    output << parse_item_or_inner_list
    consume_ows
    return output if eos?
    expect(',')
    consume_ows
    parse_error if eos?
  end
  output
end

#parse_parametersObject



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/starry/parser.rb', line 116

def parse_parameters
  output = {}
  until eos?
    break unless scan(';')
    consume_sp
    key = parse_key
    if scan('=')
      value = parse_bare_item
    else
      value = true
    end
    output[key] = value
  end
  output
end

#parse_stringObject



159
160
161
162
163
164
# File 'lib/starry/parser.rb', line 159

def parse_string
  expect('"')
  output = scan(/([\u0020-\u0021\u0023-\u005b\u005d-\u007e]|\\[\\"])*/)
  expect('"')
  output.gsub(/\\([\\"])/, '\1')
end

#parse_tokenObject



166
167
168
169
# File 'lib/starry/parser.rb', line 166

def parse_token
  check(/[A-Za-z*]/)
  scan(/[!#$%&'*+\-.^_`|~0-9A-Za-z:\/]*/).to_sym
end