Class: Rule

Inherits:
Object
  • Object
show all
Defined in:
lib/cofgratx/cfg/rule.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(subrules = [], translations = []) ⇒ Rule

Returns a new instance of Rule.



4
5
6
7
8
# File 'lib/cofgratx/cfg/rule.rb', line 4

def initialize subrules = [], translations = []
  @translation_error_message = nil
  @rule = set_rule subrules
  @translation = set_translation translations
end

Instance Attribute Details

#ruleObject (readonly)

Returns the value of attribute rule.



2
3
4
# File 'lib/cofgratx/cfg/rule.rb', line 2

def rule
  @rule
end

#translationObject (readonly)

Returns the value of attribute translation.



2
3
4
# File 'lib/cofgratx/cfg/rule.rb', line 2

def translation
  @translation
end

#translation_error_messageObject (readonly)

Returns the value of attribute translation_error_message.



2
3
4
# File 'lib/cofgratx/cfg/rule.rb', line 2

def translation_error_message
  @translation_error_message
end

Instance Method Details

#extract(candidate, translate_non_terminals = false) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/cofgratx/cfg/rule.rb', line 58

def extract candidate, translate_non_terminals = false
  working_matches = [ ["",candidate.dup,[[]]] ]

  @rule.each do |subrule|
    surviving_matches = []
    working_matches.each do |current_match, working_candidate, current_set|

      if subrule.class == Repetition
        surviving_matches.concat extract_repetition_character subrule, current_match.dup, deep_clone_a_set(current_set), working_candidate.dup, translate_non_terminals
      elsif subrule.class == Terminal
        match, working_candidate = subrule.extract working_candidate
        if match
          current_set.first << match
          surviving_matches << [ current_match + match, working_candidate.dup, deep_clone_a_set(current_set) ]
        end
      elsif subrule.class == NonTerminal
        matches = if translate_non_terminals
                    translations = subrule.translate(working_candidate).select{|tx| tx[0]}
                    translations.map{|tx| tx[2] = deep_clone_a_set(current_set); tx[2].first << tx[0].dup; tx }
                    translations
                  else
                    subrule.extract(working_candidate)
                  end

        if matches.size > 0 and matches.first[0]
          surviving_matches.concat matches
        end
      else
        raise "Rule is corrupt, found a bad subrule:#{subrule} with class:#{subrule.class}"
      end
    end
    working_matches = surviving_matches.dup
  end
  return [ [nil,candidate,[[]]] ] if working_matches.size == 0

  working_matches
end

#match?(candidate) ⇒ Boolean

Returns:

  • (Boolean)


54
55
56
# File 'lib/cofgratx/cfg/rule.rb', line 54

def match? candidate
  extract(candidate).first[0] != nil
end

#set_rule(*rule) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/cofgratx/cfg/rule.rb', line 10

def set_rule *rule
  good_parts = []
  rule.flatten(2).each do |part|
    if ! [Repetition, Terminal, NonTerminal].include? part.class
      raise ArgumentError.new("expected Terminal, NonTerminal or Repetition; got #{part.class.name}")
    elsif part.class == Repetition and good_parts.size == 0
      raise RuleError.new("cannot have repetition as the first part of the rule")
    elsif good_parts.last.class == Repetition
      raise RuleError.new("nothing can follow the repetition")
    end
    good_parts << part
  end
  @rule = good_parts
end

#set_translation(*translation) ⇒ Object



25
26
27
28
29
30
31
32
33
34
# File 'lib/cofgratx/cfg/rule.rb', line 25

def set_translation *translation
  good_parts = []
  translation.flatten.each do |part|
    if ! [Fixnum, String, TranslationRepetitionSet].include? part.class
      raise ArgumentError.new("expected Fixnum, String or TranslationRepetitionSet; got #{part.class.name}")
    end
    good_parts << part
  end
  @translation = good_parts
end

#translate(candidate) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/cofgratx/cfg/rule.rb', line 96

def translate candidate
  matches = extract candidate, true
  translations = matches.inject([]) do |txs, match|
    current_match, working_candidate, current_set = match
    next txs << [nil, candidate] unless current_match
    next txs << [current_set.join(""), working_candidate.dup] unless @translation.size > 0
    current_translation = ""
    @translation.each do |sub_translation|
      if sub_translation.class == TranslationRepetitionSet
        current_set[(sub_translation.offset-1)..-1].to_a.each do |current|
          sub_translation.translations.each do |translation|
            current_translation += translation_helper current, translation
          end
        end
      else
        current_translation += translation_helper current_set.first, sub_translation
      end
    end
    txs << [current_translation, working_candidate]
  end
  return [ [nil, candidate] ] unless translations.size > 0
  translations
end

#valid_translation?Boolean

Returns:

  • (Boolean)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/cofgratx/cfg/rule.rb', line 36

def valid_translation?
  @translation.each do |part|
    if part.class == TranslationRepetitionSet
      if @rule.last.class != Repetition
        @translation_error_message = "rule does not contain repetition"
        return false
      elsif part.translations.select{|tx| tx.class == Fixnum and tx > @rule.size}.count > 0
        @translation_error_message = "rule contains fewer parts than the TranslationRepetitionSet has for a translation: #{part.translations.inspect}"
        return false
      end
    elsif part.class == Fixnum
      @translation_error_message = "rule contains fewer parts than translation number: #{part.inspect}"
      return false if part > @rule.size
    end
  end
  true
end