Class: Whittle::RuleSet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/whittle/rule_set.rb

Overview

RuleSets are named collections of Rules.

When you use the name of a rule in the grammar, you actually refer to the entire RuleSet and not an individual rule within it (unless of course, it only contains one Rule)

Instance Method Summary collapse

Constructor Details

#initialize(name, terminal = false) ⇒ RuleSet

Create a new RuleSet named name.

Parameters:

  • name (Symbol, String)

    the name of the rule in the grammar

  • terminal (Boolean) (defaults to: false)

    the class the use to add new rules



21
22
23
24
25
# File 'lib/whittle/rule_set.rb', line 21

def initialize(name, terminal = false)
  @name       = name
  @rules      = []
  @terminal   = terminal
end

Instance Method Details

#[](*components) ⇒ Object

Add a new Rule to the set.

Parameters:

  • components... (Object...)

    a variable list of components (Symbols, Strings, or Regexps)



36
37
38
39
40
41
# File 'lib/whittle/rule_set.rb', line 36

def [](*components)
  klass = terminal? ? Terminal : NonTerminal
  klass.new(@name, *components).tap do |rule|
    @rules << rule
  end
end

#assocSymbol

Convenience method to access the associativity of a RuleSet representing a terminal.

Returns:

  • (Symbol)

    the associativty of the terminal Symbol.



119
120
121
# File 'lib/whittle/rule_set.rb', line 119

def assoc
  terminal? ? @rules.first.assoc : :right
end

#build_parse_table(table, parser, context) ⇒ Hash

Recursively builds the parse table into table.

Parameters:

  • table (Hash<Fixnum,Hash>)

    the parse table as constructed so far

  • parser (Parser)

    the parser containing the grammar

  • context (Hash)

    a Hash used to track state when building the parse table

Returns:

  • (Hash)

    the parse table



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/whittle/rule_set.rb', line 78

def build_parse_table(table, parser, context)
  return table if context[:seen].include?([context[:state], self])

  context[:seen] << [context[:state], self]

  table.tap do
    each do |rule|
      rule.build_parse_table(table, parser, context)
    end
  end
end

#each(&block) ⇒ Object

Enumerate all Rules in the set.



28
29
30
# File 'lib/whittle/rule_set.rb', line 28

def each(&block)
  @rules.each(&block)
end

#nonterminal?Boolean

Predicate test for whether or not this RuleSet references a nonterminal Symbol.

Returns:

  • (Boolean)

    true if this rule is a nonterminal symbol



103
104
105
# File 'lib/whittle/rule_set.rb', line 103

def nonterminal?
  !terminal?
end

#precFixnum

Convenience method to access the precedence of a RuleSet representing a terminal.

Returns:

  • (Fixnum)

    the precedence of the terminal Symbol, or zero for nonterminals.



111
112
113
# File 'lib/whittle/rule_set.rb', line 111

def prec
  terminal? ? @rules.first.prec : 0
end

#scan(source, offset, line) ⇒ Hash

Invoked during lexing, delegating to each rule in the set.

Parameters:

  • source (String)

    the complete input string

  • offset (Fixnum)

    the current index in the search

  • line (Fixnum)

    the current line number

Returns:

  • (Hash)

    a Hash representing the found token, or nil



55
56
57
58
59
60
61
62
63
# File 'lib/whittle/rule_set.rb', line 55

def scan(source, offset, line)
  each do |rule|
    if token = rule.scan(source, offset, line)
      return token
    end
  end

  nil
end

#terminal?Boolean

Predicate test for whether or not this RuleSet references a single terminal Symbol.

Returns:

  • (Boolean)

    true if this rule is a terminal symbol



95
96
97
# File 'lib/whittle/rule_set.rb', line 95

def terminal?
  @terminal
end