Class: Habaki::FormalSyntax::Tree

Inherits:
Object
  • Object
show all
Defined in:
lib/habaki/formal_syntax.rb

Overview

format syntax tree parser

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTree

Returns a new instance of Tree.



106
107
# File 'lib/habaki/formal_syntax.rb', line 106

def initialize
end

Instance Attribute Details

#propertiesObject

Returns the value of attribute properties.



104
105
106
# File 'lib/habaki/formal_syntax.rb', line 104

def properties
  @properties
end

Class Method Details

.nObject



133
134
135
# File 'lib/habaki/formal_syntax.rb', line 133

def self.n
  Float::INFINITY
end

.parse(str) ⇒ Object

formal syntax parser



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/habaki/formal_syntax.rb', line 138

def self.parse(str)
  current_node = Node.new(:and)
  current_node.orig = str
  scanner = StringScanner.new(str.gsub("", "N"))

  until scanner.eos?
    case
    when scanner.scan(/\[/)
      prev_node = current_node
      current_node = Node.new(:and)
      current_node.parent = prev_node
    when scanner.scan(/<([a-zA-Z0-9-]+)\(/)
      prev_node = current_node
      current_node = Node.new(:function_ref, scanner[1])
      current_node.parent = prev_node
    when scanner.scan(/([a-zA-Z0-9-]+)\(/)
      prev_node = current_node
      current_node = Node.new(:function, scanner[1])
      current_node.parent = prev_node
    when scanner.scan(/\?/)
      prev_node = current_node.children.last
      prev_node.occurence = 0..1
    when scanner.scan(/\*/)
      prev_node = current_node.children.last
      prev_node.occurence = 0..n
    when scanner.scan(/\+/)
      prev_node = current_node.children.last
      prev_node.occurence = 1..n
    when scanner.scan(/\!/)
      # at least one required
      prev_node = current_node.children.last
      prev_node.occurence = 1..n
    when scanner.scan(/\#/)
      # one or more comma separated
      prev_node = current_node.children.last
      # embed :type in :or
      if prev_node.type == :type
        emb_node = Node.new(:or)
        emb_node.children << prev_node
        emb_node.push_children(Node.new(:token, ","))
        emb_node.occurence = 1..n
        current_node.children[-1] = emb_node
      else
        prev_node.push_children(Node.new(:token, ","))
        prev_node.occurence = 1..n
      end
    when scanner.scan(/\{(\d)\}/)
      prev_node = current_node.children.last
      prev_node.occurence = (scanner[1].to_i)..(scanner[1].to_i)
    when scanner.scan(/\{(\d),(\d)\}/)
      prev_node = current_node.children.last
      prev_node.occurence = (scanner[1].to_i)..(scanner[2].to_i)
    when scanner.scan(/\]/)
      current_node.occurence_from_children!
      if current_node.parent
        prev_node = current_node
        current_node = current_node.parent
        current_node.push_children prev_node
      else
        raise FormalSyntaxError, "Formal syntax problem: #{current_node}"
      end
    when scanner.scan(/\)>?/)
      if current_node.parent
        prev_node = current_node
        current_node = current_node.parent
        current_node.push_children prev_node
      else
        raise FormalSyntaxError, "Formal syntax problem: #{current_node}"
      end
    when scanner.scan(/\s?(\/|,|:|;|%)\s?/)
      current_node.push_children Node.new(:token, scanner[1])
    when scanner.scan(/<([a-zA-Z0-9-]+)(\s\[\d,N?\d*\])?>/)
      current_node.push_children Node.new(:type, scanner[1])
    when scanner.scan(/([a-zA-Z-]+)/)
      current_node.push_children Node.new(:ident, scanner[1]) #if scanner[1] != "inherit"
    when scanner.scan(/([0-9]+)/)
      current_node.push_children Node.new(:number, scanner[1].to_i)
    when scanner.scan(/<?'([a-zA-Z-]+)'>?/)
      current_node.push_children Node.new(:ref, scanner[1])
    when scanner.scan(/'(..?)'/)
      current_node.push_children Node.new(:token, scanner[1])
    when scanner.scan(/\|\|/)
      current_node.type = :or_and
    when scanner.scan(/\|/)
      current_node.type = :or
    when scanner.scan(/\&\&/)
      current_node.type = :and
    else
      result = scanner.scan(/.+/)
      raise FormalSyntaxError, "Cannot parse formal syntax: #{result}"
    end
    scanner.scan(/\s+/)
  end
  current_node.occurence_from_children!
  current_node
end

.treeObject



121
122
123
# File 'lib/habaki/formal_syntax.rb', line 121

def self.tree
  @@tree ||= self.new.parse_all(Tree.tree_data)
end

.tree_dataObject



125
126
127
# File 'lib/habaki/formal_syntax.rb', line 125

def self.tree_data
  @@tree_data ||= YAML.load_file(File.join(File.dirname(__FILE__), '../../data/formal_syntax.yml')).freeze
end

Instance Method Details

#parse_all(data) ⇒ Object



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

def parse_all(data)
  @properties = {}
  data.each do |k, v|
    begin
      @properties[k] = Tree.parse(v)
    rescue FormalSyntaxError #=> e
      #STDERR.puts("#{k}: #{e}")
    end
  end
  self
end

#property(prop) ⇒ Object



129
130
131
# File 'lib/habaki/formal_syntax.rb', line 129

def property(prop)
  @properties[prop]
end