Class: Kanocc::Nonterminal

Inherits:
Object
  • Object
show all
Defined in:
lib/kanocc/nonterminal.rb

Direct Known Subclasses

AnonymousNonterminal, Error, StartSymbol

Constant Summary collapse

Left =
1
Right =
2
@@rules =
Hash.new
@@last_rule =
Hash.new
@@bind_right =
Hash.new
@@method_names =
Hash.new
@@listClassNumber =
0

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_rule(rule) ⇒ Object



34
35
36
37
38
# File 'lib/kanocc/nonterminal.rb', line 34

def Nonterminal.add_rule(rule)
  @@rules[self] ||= []
  @@rules[self].push(rule)
  @@last_rule[self] = rule
end

.derives_rightObject



127
128
129
130
# File 'lib/kanocc/nonterminal.rb', line 127

def Nonterminal.derives_right
  raise "Call to derives_right must be preceded by a rule" unless @@last_rule[self]
  @@last_rule[self].derives_right = true
end

.generate_method_name(*args) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/kanocc/nonterminal.rb', line 109

def Nonterminal.generate_method_name(*args)
  class_name = self.name || ""
  method_name = class_name + " --> " + args.map {|a| a.inspect}.join(' ')
  @@method_names[self] ||= []
  i = 1
  while @@method_names[self].member?(method_name) do 
    method_name += ' ';
  end
  @@method_names[self].push(method_name)
  return method_name
end

.is_a_grammarsymbol?(x) ⇒ Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/kanocc/nonterminal.rb', line 40

def Nonterminal.is_a_grammarsymbol?(x) 
  x.is_a?(String) or (x.respond_to?("is_a_kanocc_grammarsymbol?") and x.is_a_kanocc_grammarsymbol?)
end

.is_a_kanocc_grammarsymbol?Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/kanocc/nonterminal.rb', line 44

def Nonterminal.is_a_kanocc_grammarsymbol? 
  return true 
end

.new_list_classObject



98
99
100
101
102
103
104
105
106
107
# File 'lib/kanocc/nonterminal.rb', line 98

def Nonterminal.new_list_class
  list_class = Class.new(AnonymousNonterminal)
  @@listClassNumber += 1

  def list_class.inspect
    return "anonList_#{@@listClassNumber}"
  end

  return list_class
end

.om(symbols, sep = nil) ⇒ Object



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

def Nonterminal.om(symbols, sep = nil)
  symbols = [symbols] unless symbols.is_a? Array
  non_empty_list_class = new_list_class
  non_empty_list_class.rule(*symbols) {@elements = @rhs}
  if sep
    non_empty_list_class.rule(non_empty_list_class, sep, *symbols) {@elements = @rhs[0].elements + @rhs[2..@rhs.length]}
  else
    non_empty_list_class.rule(non_empty_list_class, *symbols) {@elements = @rhs[0].elements + @rhs[1..@rhs.length]}
  end
  return non_empty_list_class
end

.precedence(prec) ⇒ Object



121
122
123
124
125
# File 'lib/kanocc/nonterminal.rb', line 121

def Nonterminal.precedence(prec)
  raise "Given rule precedence was not a Numeric" unless prec.is_a? Numeric
  raise "Call to precedence must be preceded by a rule" unless @@last_rule[self]
  @@last_rule[self].precedence = prec
end

.rule(*rhs, &block) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/kanocc/nonterminal.rb', line 48

def Nonterminal.rule(*rhs, &block)
  for pos in 0..rhs.length - 1 do
    unless is_a_grammarsymbol?(rhs[pos])
      raise "Problem with rule: #{rhs.inspect}, element:#{pos.to_s} - #{rhs[pos].inspect}\nElements of a rule must be Strings, Tokens or Nonterminals"
    end
  end
       
  if block_given?
    method_name = generate_method_name(*rhs) 
    define_method(method_name.to_sym, &block)
    add_rule(GrammarRule.new(self, rhs, method_name.to_sym))
  else
    add_rule(GrammarRule.new(self, rhs, nil))
  end
end

.rulesObject



29
30
31
32
# File 'lib/kanocc/nonterminal.rb', line 29

def Nonterminal.rules
  rules = @@rules[self] 
  return rules ? rules : []
end

.show_all_rulesObject



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/kanocc/nonterminal.rb', line 146

def Nonterminal.show_all_rules
   queue = [self]
   done = {}
   i = 0
   while (i < queue.length)
	 queue[i].show_rules
	 done[queue[i]] = true
     queue[i].rules.each do |rule|
rule.rhs.each do |gs|
  if gs.respond_to?(:rules) and not done[gs]
    queue.push(gs)
         end
       end
     end
	 i += 1
   end
end

.show_method_namesObject



132
133
134
# File 'lib/kanocc/nonterminal.rb', line 132

def Nonterminal.show_method_names
  @@method_names[self].each{|mn| puts mn.inspect} if @@method_names[self]
end

.show_rulesObject



140
141
142
143
144
# File 'lib/kanocc/nonterminal.rb', line 140

def Nonterminal.show_rules
  rules.each do |rule| 
	puts rule.inspect
  end
end

.zm(symbols, sep = nil) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/kanocc/nonterminal.rb', line 64

def Nonterminal.zm(symbols, sep = nil)
  list_class = new_list_class 
  non_empty_list_class = new_list_class
  list_class.rule() {@elements = []}
  list_class.rule(non_empty_list_class) {@elements = @rhs[0].elements}
  non_empty_list_class.rule(*symbols) {@elements = @rhs}
  if sep
    non_empty_list_class.rule(non_empty_list_class, sep, *symbols) {@elements = @rhs[0].elements + @rhs[2..@rhs.length]}
  else
	non_empty_list_class.rule(non_empty_list_class, *symbols) {@elements = @rhs[0].elements + @rhs[1..@rhs.length]}
  end
  return list_class
end

.zo(symbols) ⇒ Object



90
91
92
93
94
# File 'lib/kanocc/nonterminal.rb', line 90

def Nonterminal.zo(symbols)
  zero_or_one_class = new_list_class
  zero_or_one_class.rule(*symbols) {@elements = @rhs}
  zero_or_one_class.rule() {@elements = []}
end

Instance Method Details

#inspectObject



136
137
138
# File 'lib/kanocc/nonterminal.rb', line 136

def inspect
  self.class.name  
end