Class: EDN::Parser
- Inherits:
-
Object
- Object
- EDN::Parser
- Defined in:
- lib/edn/parser.rb
Instance Method Summary collapse
- #call_reader(reader) ⇒ Object
- #eof? ⇒ Boolean
- #escape_char(ch) ⇒ Object
- #finish_float(whole_part) ⇒ Object
-
#initialize(source, *extra) ⇒ Parser
constructor
A new instance of Parser.
- #read ⇒ Object
- #read_basic ⇒ Object
- #read_char ⇒ Object
- #read_collection(clazz, closing) ⇒ Object
- #read_digits(min_digits = 0) ⇒ Object
- #read_eof ⇒ Object
- #read_extension ⇒ Object
- #read_keyword ⇒ Object
- #read_list ⇒ Object
- #read_map ⇒ Object
- #read_meta ⇒ Object
- #read_number(leading = '') ⇒ Object
- #read_number_or_symbol ⇒ Object
- #read_slash ⇒ Object
- #read_string ⇒ Object
- #read_symbol(leading = '') ⇒ Object
- #read_symbol_chars ⇒ Object
- #read_vector ⇒ Object
- #unknown ⇒ Object
Constructor Details
#initialize(source, *extra) ⇒ Parser
Returns a new instance of Parser.
85 86 87 88 |
# File 'lib/edn/parser.rb', line 85 def initialize(source, *extra) io = source.instance_of?(String) ? StringIO.new(source) : source @s = CharStream.new(io) end |
Instance Method Details
#call_reader(reader) ⇒ Object
224 225 226 227 228 229 230 |
# File 'lib/edn/parser.rb', line 224 def call_reader(reader) if reader.instance_of? Symbol self.send(reader) else self.instance_exec(&reader) end end |
#eof? ⇒ Boolean
100 101 102 |
# File 'lib/edn/parser.rb', line 100 def eof? @s.eof? end |
#escape_char(ch) ⇒ Object
198 199 200 201 202 203 204 |
# File 'lib/edn/parser.rb', line 198 def escape_char(ch) return '\\' if ch == '\\' return "\n" if ch == 'n' return "\t" if ch == 't' return "\r" if ch == 'r' ch end |
#finish_float(whole_part) ⇒ Object
262 263 264 265 266 267 268 269 270 271 |
# File 'lib/edn/parser.rb', line 262 def finish_float(whole_part) result = whole_part result += @s.skip_past('.', 'Expected .') result += read_digits(1) if @s.current == 'e' || @s.current == 'E' @s.advance result = result + 'e' + read_digits end result.to_f end |
#read ⇒ Object
90 91 92 93 94 95 96 97 98 |
# File 'lib/edn/parser.rb', line 90 def read = value = read_basic if value.extend EDN::Metadata value. = end value end |
#read_basic ⇒ Object
232 233 234 235 236 237 238 239 240 241 |
# File 'lib/edn/parser.rb', line 232 def read_basic @s.skip_ws ch = @s.current result = call_reader(READERS[ch]) while result == NOTHING @s.skip_ws result = call_reader(READERS[@s.current]) end result end |
#read_char ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/edn/parser.rb', line 112 def read_char result = @s.advance @s.advance until @s.eof? break unless @s.digit? || @s.alpha? result += @s.current @s.advance end return result if result.size == 1 case result when 'newline' "\n" when 'return' "\r" when 'tab' "\t" when 'space' " " else raise "Unknown char #{result}" end end |
#read_collection(clazz, closing) ⇒ Object
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/edn/parser.rb', line 321 def read_collection(clazz, closing) result = clazz.new @s.skip_ws ch = @s.current while ch != closing raise "Unexpected eof" if ch == :eof result << read @s.skip_ws ch = @s.current end @s.advance result end |
#read_digits(min_digits = 0) ⇒ Object
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/edn/parser.rb', line 243 def read_digits(min_digits=0) result = '' if @s.current == '+' || @s.current == '-' result << @s.current @s.advance end n_digits = 0 while @s.current =~ /[0-9]/ n_digits += 1 result << @s.current @s.advance end raise "Expected at least #{min_digits} digits, found #{result}" unless n_digits >= min_digits result end |
#read_eof ⇒ Object
108 109 110 |
# File 'lib/edn/parser.rb', line 108 def read_eof EOF end |
#read_extension ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/edn/parser.rb', line 169 def read_extension @s.advance if @s.current == '{' @s.advance read_collection(Set, '}') elsif @s.current == "_" @s.advance x = read NOTHING else tag = read_symbol_chars value = read EDN.tagged_element(tag, value) end end |
#read_keyword ⇒ Object
193 194 195 196 |
# File 'lib/edn/parser.rb', line 193 def read_keyword @s.advance read_symbol_chars.to_sym end |
#read_list ⇒ Object
304 305 306 307 |
# File 'lib/edn/parser.rb', line 304 def read_list @s.advance read_collection(EDN::Type::List, ')') end |
#read_map ⇒ Object
314 315 316 317 318 319 |
# File 'lib/edn/parser.rb', line 314 def read_map @s.advance array = read_collection(Array, '}') raise "Need an even number of items for a map" unless array.count.even? Hash[*array] end |
#read_meta ⇒ Object
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/edn/parser.rb', line 285 def = [] @s.skip_ws while @s.current == '^' @s.advance << read_basic @s.skip_ws end = .reverse.reduce({}) do |acc, m| case m when Symbol then acc.merge(m => true) when EDN::Type::Symbol then acc.merge(:tag => m) else acc.merge(m) end end .empty? ? nil : end |
#read_number(leading = '') ⇒ Object
273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/edn/parser.rb', line 273 def read_number(leading='') result = leading + read_digits if @s.current == '.' return finish_float(result) elsif @s.skip_past('M') || @s.skip_past('N') result.to_i else result.to_i end end |
#read_number_or_symbol ⇒ Object
142 143 144 145 146 147 |
# File 'lib/edn/parser.rb', line 142 def read_number_or_symbol leading = @s.current @s.advance return read_number(leading) if @s.digit? read_symbol(leading) end |
#read_slash ⇒ Object
137 138 139 140 |
# File 'lib/edn/parser.rb', line 137 def read_slash @s.advance Type::Symbol.new('/') end |
#read_string ⇒ Object
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/edn/parser.rb', line 206 def read_string @s.advance result = '' until @s.current == '"' raise "Unexpected eof" if @s.eof? if @s.current == '\\' @s.advance result << escape_char(@s.current) else result << @s.current end @s.advance end @s.advance result end |
#read_symbol(leading = '') ⇒ Object
185 186 187 188 189 190 191 |
# File 'lib/edn/parser.rb', line 185 def read_symbol(leading='') token = leading + read_symbol_chars return true if token == "true" return false if token == "false" return nil if token == "nil" Type::Symbol.new(token) end |
#read_symbol_chars ⇒ Object
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/edn/parser.rb', line 149 def read_symbol_chars result = '' ch = @s.current while SYMBOL_INTERIOR_CHARS.include?(ch) result << ch ch = @s.advance end return result unless @s.skip_past('/') result << '/' ch = @s.current while SYMBOL_INTERIOR_CHARS.include?(ch) result << ch ch = @s.advance end result end |
#read_vector ⇒ Object
309 310 311 312 |
# File 'lib/edn/parser.rb', line 309 def read_vector @s.advance read_collection(Array, ']') end |
#unknown ⇒ Object
104 105 106 |
# File 'lib/edn/parser.rb', line 104 def unknown raise "Don't know what to do with #{@s.current} #{@s.current.class}" end |