Class: Packrat::AST

Inherits:
Object
  • Object
show all
Defined in:
lib/packrat/grammar.rb

Overview

Node in AST trees.

Constant Summary collapse

DefaultOptions =
{:only_nonconstant => true}

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(children, options = {}) ⇒ AST

Returns a new instance of AST.



445
446
447
448
449
450
451
452
453
454
# File 'lib/packrat/grammar.rb', line 445

def initialize(children, options = {})
  options = DefaultOptions.clone.update(options)
  if options[:only_nonconstant]
    @children = self.class.sig.map do |n|
      n.kind_of?(String) ? n : children.shift
    end
  else
    @children = children
  end
end

Class Attribute Details

.sigObject

Returns the value of attribute sig.



371
372
373
# File 'lib/packrat/grammar.rb', line 371

def sig
  @sig
end

Instance Attribute Details

#childrenObject (readonly)

Returns the value of attribute children.



455
456
457
# File 'lib/packrat/grammar.rb', line 455

def children
  @children
end

Class Method Details

.[](*args) ⇒ Object



440
# File 'lib/packrat/grammar.rb', line 440

def [](*args); new(args); end

.constant_elem_at?(index) ⇒ Boolean

Returns:

  • (Boolean)


436
437
438
# File 'lib/packrat/grammar.rb', line 436

def constant_elem_at?(index)
  self.sig[index].kind_of?(String)
end

.extract_sig(production, nameMap = {}) ⇒ Object

Return a sig for the given <production>. The sig has strings in the positions where the production rhs has a String or StringLiteral, has symbols in the positions where a rhs element refer to another production, and has nil in other positions. The <nameMap> can contain explicit names for certing indices (indices as key and name as symbol value).



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/packrat/grammar.rb', line 404

def extract_sig(production, nameMap = {})
  sig = []
  production.rhs.each_with_index do |e, i|
    unless e.hidden
      case e
      when String
        sig << e
      when Packrat::StringLiteral
        sig << e.string
      when Packrat::RuleRef
        sig << sub_element_name(e.rule_name)
      else
        sig << nil  # Expand this so that names are lifted out of Maybe, and "s" is added when plus and mult etc
      end
    end
  end
  number_multioccurences(sig).map {|n| nameMap[n] || n}
end

.new_subclass(name, production, nameMap = {}) ⇒ Object

Create a new AST subclass. The <nameMap> hash can specify names for certain element indices (such explicitly specified names will override the default naming scheme which is to use a downcase version of the production name).



376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/packrat/grammar.rb', line 376

def new_subclass(name, production, nameMap = {})
  klass = Class.new(self)
  klass.sig = extract_sig(production, nameMap)
  # Add accessor methods for all symbols in the sig
  num_strings = 0
  klass.sig.each_with_index do |sn, i|
    if Symbol === sn
      # We should subtract the num_strings in the index below
      # if we optimize this so that non-named children are never
      # added to the result array!
      klass.module_eval %{
        def #{sn.to_s}
          @children[#{i}]
        end
      }
    elsif String === sn
      num_strings += 1
    end
  end
  klass
end

.number_multioccurences(sig) ⇒ Object



423
424
425
426
427
428
429
# File 'lib/packrat/grammar.rb', line 423

def number_multioccurences(sig)
  num_sigs = sig.inject(Hash.new(0)) {|h, s| h[s] += 1 if Symbol === s; h}
  counters = Hash.new(0)
  sig.map do |s|
    (num_sigs[s] > 1) ? (s.to_s + (counters[s] += 1).to_s).intern : s
  end
end

.sub_element_name(name) ⇒ Object



431
432
433
434
# File 'lib/packrat/grammar.rb', line 431

def sub_element_name(name)
  parts = name.to_s.split(/([A-Z][a-z0-9]*)/).select {|e| e.length > 0}
  parts.map {|p| p.downcase}.join("_").intern
end

Instance Method Details

#==(other) ⇒ Object



459
460
461
# File 'lib/packrat/grammar.rb', line 459

def ==(other)
  self.class == other.class && @children == other.children
end

#[](index) ⇒ Object



457
# File 'lib/packrat/grammar.rb', line 457

def [](index); @children[index]; end

#inspectObject



463
464
465
466
# File 'lib/packrat/grammar.rb', line 463

def inspect
  self.class.inspect.split("::").last + "[" +
    @children.map {|c| c.inspect}.join(", ") + "]"
end