Class: Citrus::Match

Inherits:
Object show all
Defined in:
lib/citrus.rb

Overview

The base class for all matches. Matches are organized into a tree where any match may contain any number of other matches. Nodes of the tree are lazily instantiated as needed. This class provides several convenient tree traversal methods that help when examining and interpreting parse results.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(input, events = [], offset = 0) ⇒ Match

Returns a new instance of Match.



1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
# File 'lib/citrus.rb', line 1275

def initialize(input, events=[], offset=0)
  @input = input
  @offset = offset
  @captures = nil
  @matches = nil

  if events.length > 0
    elisions = []

    while events[0].elide?
      elisions.unshift(events.shift)
      events.slice!(-2, events.length)
    end

    events[0].extend_match(self)

    elisions.each do |rule|
      rule.extend_match(self)
    end
  else
    # Create a default stream of events for the given string.
    string = input.to_str
    events = [Rule.for(string), CLOSE, string.length]
  end

  @events = events
end

Instance Attribute Details

#events ⇒ Object (readonly)

The array of events for this match.



1310
1311
1312
# File 'lib/citrus.rb', line 1310

def events
  @events
end

#input ⇒ Object (readonly)

The original Input this Match was generated on.



1304
1305
1306
# File 'lib/citrus.rb', line 1304

def input
  @input
end

#offset ⇒ Object (readonly)

The index of this match in the #input.



1307
1308
1309
# File 'lib/citrus.rb', line 1307

def offset
  @offset
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
# File 'lib/citrus.rb', line 1381

def ==(other)
  case other
  when String
    string == other
  when Match
    string == other.to_s
  else
    super
  end
end

#[](key, *args) ⇒ Object

Returns the capture at the given key. If it is an Integer (and an optional length) or a Range, the result of #to_a with the same arguments is returned. Otherwise, the value at key in #captures is returned.



1372
1373
1374
1375
1376
1377
1378
1379
# File 'lib/citrus.rb', line 1372

def [](key, *args)
  case key
  when Integer, Range
    to_a[key, *args]
  else
    captures[key]
  end
end

#capture(name) ⇒ Object

Convenient method for captures.first.



1335
1336
1337
# File 'lib/citrus.rb', line 1335

def capture(name)
  captures[name].first
end

#captures(name = nil) ⇒ Object

Returns a hash of capture names to arrays of matches with that name, in the order they appeared in the input.



1329
1330
1331
1332
# File 'lib/citrus.rb', line 1329

def captures(name = nil)
  process_events! unless @captures
  name ? @captures[name] : @captures
end

#dump(indent = ' ') ⇒ Object

Prints the entire subtree of this match using the given indent to indicate nested match levels. Useful for debugging.



1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
# File 'lib/citrus.rb', line 1400

def dump(indent=' ')
  lines = []
  stack = []
  offset = 0
  close = false
  index = 0
  last_length = nil

  while index < @events.size
    event = @events[index]

    if close
      os = stack.pop
      start = stack.pop
      rule = stack.pop

      space = indent * (stack.size / 3)
      string = self.string.slice(os, event)
      lines[start] = "#{space}#{string.inspect} rule=#{rule}, offset=#{os}, length=#{event}"

      last_length = event unless last_length

      close = false
    elsif event == CLOSE
      close = true
    else
      if last_length
        offset += last_length
        last_length = nil
      end

      stack << event
      stack << index
      stack << offset
    end

    index += 1
  end

  puts lines.compact.join("\n")
end

#first ⇒ Object

A shortcut for retrieving the first immediate submatch of this match.



1346
1347
1348
# File 'lib/citrus.rb', line 1346

def first
  matches.first
end

#inspect ⇒ Object



1394
1395
1396
# File 'lib/citrus.rb', line 1394

def inspect
  string.inspect
end

#length ⇒ Object

Returns the length of this match.



1313
1314
1315
# File 'lib/citrus.rb', line 1313

def length
  events.last
end

#matches ⇒ Object

Returns an array of all immediate submatches of this match.



1340
1341
1342
1343
# File 'lib/citrus.rb', line 1340

def matches
  process_events! unless @matches
  @matches
end

#source ⇒ Object

Convenient shortcut for input.source



1318
1319
1320
# File 'lib/citrus.rb', line 1318

def source
  (input.respond_to?(:source) && input.source) || input
end

#string ⇒ Object Also known as: to_s

Returns the slice of the source text that this match captures.



1323
1324
1325
# File 'lib/citrus.rb', line 1323

def string
  @string ||= input.to_str[offset, length]
end

#to_a ⇒ Object

Returns this match plus all sub #matches in an array.



1365
1366
1367
# File 'lib/citrus.rb', line 1365

def to_a
  [self] + matches
end