class Antelope::Generation::Recognizer::Rule

Defines a rule. A rule has a corresponding production, and a position in that production. It also contains extra information for other reasons.

Attributes

block[R]

The block to be executed on production match.

@deprecated Use {Grammar::Production#block} instead. @return [String]

id[RW]

The id for this rule. Initialy, this is set to a string of hexadecimal characters; after construction of all states, however, it is a number.

@return [String, Numeric]

left[R]

The left-hand side of the rule.

@return [Grammar::Token::Nonterminal]

lookahead[RW]

The lookahead set for this specific rule. Contains nothing unless {#final?} returns true.

@return [Set<Symbol>]

position[R]

The current position inside of the rule.

@return [Numeric]

precedence[RW]

The precedence for this rule.

@return [Grammar::Precedence]

production[R]

The associated production.

@return [Grammar::Production]

right[R]

The right-hand side of the rule.

@return [Array<Grammar::Token>]

Public Class Methods

new(production, position, inherited = false) click to toggle source

Initialize the rule.

@param production [Grammar::Production] the production

that this rule is based off of.

@param position [Numeric] the position that this rule is in

the production.

@param inherited [nil] do not use.

# File lib/antelope/generation/recognizer/rule.rb, line 67
def initialize(production, position, inherited = false)
  @left       = production.label.dup
  @position   = position
  @lookahead  = Set.new
  @precedence = production.prec
  @production = production
  @block      = production.block
  @id         = format('%10x', object_id)

  if inherited
    @left, @right = inherited
  else
    @right = production.items.map(&:dup)
  end
end

Public Instance Methods

<=>(other) click to toggle source

Compares this rule to another object. If the other object is not a rule, it delegates the comparison. Otherwise, it converts both this and the other rule into arrays and compares the result.

@param other [Object] the object to compare. @return [Numeric]

Calls superclass method
# File lib/antelope/generation/recognizer/rule.rb, line 155
def <=>(other)
  if other.is_a? Rule
    to_a <=> other.to_a
  else
    super
  end
end
==(other) click to toggle source
# File lib/antelope/generation/recognizer/rule.rb, line 163
def ==(other)
  hash == other.hash if other.respond_to?(:hash)
end
Also aliased as: eql?
===(other) click to toggle source

Fuzzily compares this object to another object. If the other object is not a rule, it delegates the comparison. Otherwise, it fuzzily compares the left and right sides.

@param other [Object] the object to compare. @return [Numeric]

Calls superclass method
# File lib/antelope/generation/recognizer/rule.rb, line 175
def ===(other)
  if other.is_a? Rule
    left === other.left && right.size == other.right.size &&
      right.each_with_index
        .all? { |e, i| e === other.right[i] }
  else
    super
  end
end
active() click to toggle source

Returns the active token. If there is no active token, it returns a blank {Grammar::Token}.

@return [Grammar::Token]

# File lib/antelope/generation/recognizer/rule.rb, line 108
def active
  right[position] || Grammar::Token.new(nil)
end
clone() click to toggle source

Produces a clone of the rule; any modifications made to the contents of that rule do not reflect the contents of this rule.

@return [Rule]

# File lib/antelope/generation/recognizer/rule.rb, line 190
def clone
  Rule.new(production, position)
end
eql?(other)
Alias for: ==
final?() click to toggle source

Checks to see if this is the final rule, as in no rule can exist after this one; i.e. the position is equal to the size of the right side.

@return [Boolean]

# File lib/antelope/generation/recognizer/rule.rb, line 135
def final?
  !succ?
end
hash() click to toggle source

Generates a hash for this class.

@note This is not intended for use. It is only defined to be

compatible with Hashs (and by extension, Sets).

@private @return [Object]

# File lib/antelope/generation/recognizer/rule.rb, line 200
def hash
  @_hash ||= to_a.hash
end
inspect() click to toggle source

Give a nice representation of the rule as a string.

@return [String]

# File lib/antelope/generation/recognizer/rule.rb, line 86
def inspect
  "#<#{self.class} id=#{id} left=#{left} " \
    "right=[#{right.join(' ')}] position=#{position}>"
end
start?() click to toggle source

The complete opposite of {#final?} - it checks to see if this is the first rule, as in no rule can exist before this one; i.e. the position is zero.

@return [Boolean]

# File lib/antelope/generation/recognizer/rule.rb, line 144
def start?
  position.zero?
end
succ() click to toggle source

Creates the rule after this one by incrementing the position by one. {#succ?} should be called to make sure that this rule exists.

@return [Rule]

# File lib/antelope/generation/recognizer/rule.rb, line 117
def succ
  Rule.new(production, position + 1, [left, right])
end
succ?() click to toggle source

Checks to see if a rule can exist after this one; i.e. the position is not equal to the size of the right side of the rule.

@return [Boolean]

# File lib/antelope/generation/recognizer/rule.rb, line 126
def succ?
  right.size > position
end
to_a() click to toggle source

Creates an array representation of this class.

@note This is not intended for use. It is only defined to

make equality checking easier, and to create a hash.

@private @return [Array<(Grammar::Token::Nonterminal, Array<Grammar::Token>, Numeric)>]

# File lib/antelope/generation/recognizer/rule.rb, line 210
def to_a
  @_array ||= [left, right, position]
end
to_s(dot = true) click to toggle source

Give a nicer representation of the rule as a string. Shows the id of the rule, the precedence, and the actual production; if the given argument is true, it will show a dot to show the position of the rule.

@param dot [Boolean] show the current position of the rule. @return [String]

# File lib/antelope/generation/recognizer/rule.rb, line 98
def to_s(dot = true)
  "#{id}/#{precedence.type.to_s[0]}#{precedence.level}: " \
    "#{left} → #{right[0, position].join(' ')}" \
    "#{' • ' if dot}#{right[position..-1].join(' ')}"
end