Module: Citrus::Rule

Included in:
Nonterminal, Proxy, Terminal
Defined in:
lib/citrus.rb

Overview

A Rule is an object that is used by a grammar to create matches on an Input during parsing.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#extension ⇒ Object

The module this rule uses to extend new matches.



638
639
640
# File 'lib/citrus.rb', line 638

def extension
  @extension
end

#grammar ⇒ Object

The grammar this rule belongs to, if any.



604
605
606
# File 'lib/citrus.rb', line 604

def grammar
  @grammar
end

#label ⇒ Object

A label for this rule. If a rule has a label, all matches that it creates will be accessible as named captures from the scope of their parent match using that label.



622
623
624
# File 'lib/citrus.rb', line 622

def label
  @label
end

#name ⇒ Object

The name of this rule.



612
613
614
# File 'lib/citrus.rb', line 612

def name
  @name
end

Class Method Details

.for(obj) ⇒ Object

Returns a new Rule object depending on the type of object given.



589
590
591
592
593
594
595
596
597
598
599
600
601
# File 'lib/citrus.rb', line 589

def self.for(obj)
  case obj
  when Rule     then obj
  when Symbol   then Alias.new(obj)
  when String   then StringTerminal.new(obj)
  when Regexp   then Terminal.new(obj)
  when Array    then Sequence.new(obj)
  when Range    then Choice.new(obj.to_a)
  when Numeric  then StringTerminal.new(obj.to_s)
  else
    raise ArgumentError, "Invalid rule object: #{obj.inspect}"
  end
end

Instance Method Details

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



732
733
734
735
736
737
738
739
# File 'lib/citrus.rb', line 732

def ==(other)
  case other
  when Rule
    to_s == other.to_s
  else
    super
  end
end

#===(obj) ⇒ Object

Tests the given obj for case equality with this rule.



685
686
687
# File 'lib/citrus.rb', line 685

def ===(obj)
  !test(obj).nil?
end

#default_options ⇒ Object

The default set of options to use when calling #parse.



641
642
643
644
645
646
# File 'lib/citrus.rb', line 641

def default_options # :nodoc:
  { :consume  => true,
    :memoize  => false,
    :offset   => 0
  }
end

#elide? ⇒ Boolean

Returns true if this rule should extend a match but should not appear in its event stream.

Returns:

  • (Boolean)


696
697
698
# File 'lib/citrus.rb', line 696

def elide?
  false
end

#extend_match(match) ⇒ Object

:nodoc:



747
748
749
# File 'lib/citrus.rb', line 747

def extend_match(match) # :nodoc:
  match.extend(extension) if extension
end

#inspect ⇒ Object

:nodoc:



743
744
745
# File 'lib/citrus.rb', line 743

def inspect # :nodoc:
  to_s
end

#needs_paren? ⇒ Boolean

Returns true if this rule needs to be surrounded by parentheses when using #to_embedded_s.

Returns:

  • (Boolean)


702
703
704
# File 'lib/citrus.rb', line 702

def needs_paren? # :nodoc:
  is_a?(Nonterminal) && rules.length > 1
end

#parse(source, options = {}) ⇒ Object

Attempts to parse the given string and return a Match if any can be made. options may contain any of the following keys:

consume

If this is true a ParseError will be raised unless the entire input string is consumed. Defaults to true.

memoize

If this is true the matches generated during a parse are memoized. See MemoizedInput for more information. Defaults to false.

offset

The offset in string at which to start parsing. Defaults to 0.



658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
# File 'lib/citrus.rb', line 658

def parse(source, options={})
  opts = default_options.merge(options)

  input = (opts[:memoize] ? MemoizedInput : Input).new(source)
  string = input.string
  input.pos = opts[:offset] if opts[:offset] > 0

  events = input.exec(self)
  length = events[-1]

  if !length || (opts[:consume] && length < (string.length - opts[:offset]))
    raise ParseError, input
  end

  Match.new(input, events, opts[:offset])
end

#terminal? ⇒ Boolean

Returns true if this rule is a Terminal.

Returns:

  • (Boolean)


690
691
692
# File 'lib/citrus.rb', line 690

def terminal?
  false
end

#test(string, options = {}) ⇒ Object

Tests whether or not this rule matches on the given string. Returns the length of the match if any can be made, nil otherwise. Accepts the same options as #parse.



678
679
680
681
682
# File 'lib/citrus.rb', line 678

def test(string, options={})
  parse(string, options).length
rescue ParseError
  nil
end

#to_embedded_s ⇒ Object

Returns the Citrus notation of this rule as a string that is suitable to be embedded in the string representation of another rule.



724
725
726
727
728
729
730
# File 'lib/citrus.rb', line 724

def to_embedded_s # :nodoc:
  if name
    name.to_s
  else
    needs_paren? && label.nil? ? "(#{to_s})" : to_s
  end
end

#to_s ⇒ Object Also known as: to_str

Returns the Citrus notation of this rule as a string.



707
708
709
710
711
712
713
# File 'lib/citrus.rb', line 707

def to_s
  if label
    "#{label}:" + (needs_paren? ? "(#{to_citrus})" : to_citrus)
  else
    to_citrus
  end
end