rogdl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ == 0.1.0 / 2007-08-20
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
5
+
data/README.txt ADDED
@@ -0,0 +1,51 @@
1
+ rogdl
2
+ by Ben Hidalgo
3
+ http://rogdl.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Rogdl is designed to make using the Ordered Graph Data Language (OGDL) simple and easy within Ruby. It contains a parser, some utilities and classes to support OGDL files.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ OGDL Parsing. A bridge to ERB. XML file generation. Schema definition and validation of OGDL documents. Fully OGDL syntax not yet supported (but most is.) Simple OGDL writer not yet written (haven't needed it yet).
12
+
13
+ == SYNOPSIS:
14
+
15
+ clouds = Parser.parse_file("./rspec/clouds.ogdl")
16
+ families = clouds.find_all_named('family')
17
+ writer = Writer.new.load_templates('./rspec')
18
+ writer.write_to_files(families, proc {|family| "./rspec/samples/html/#{family.name.gvalue}.htm"})
19
+
20
+ == REQUIREMENTS:
21
+
22
+ erb
23
+
24
+ == INSTALL:
25
+
26
+ sudo gem install rogdl
27
+
28
+ == LICENSE:
29
+
30
+ (The MIT License)
31
+
32
+ Copyright (c) 2007 FIX
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining
35
+ a copy of this software and associated documentation files (the
36
+ 'Software'), to deal in the Software without restriction, including
37
+ without limitation the rights to use, copy, modify, merge, publish,
38
+ distribute, sublicense, and/or sell copies of the Software, and to
39
+ permit persons to whom the Software is furnished to do so, subject to
40
+ the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be
43
+ included in all copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
46
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
48
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
49
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
50
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
51
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/lib/array.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'lib/rogdl'
2
+
3
+ class Array
4
+
5
+
6
+ def to_n
7
+ first = nil
8
+ self.entries.each do |entry|
9
+ if first.nil?
10
+ first = entry.to_n
11
+ else
12
+ first.add(entry.to_n)
13
+ end
14
+ end
15
+ return first
16
+ end
17
+
18
+ end
data/lib/fixnum.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'lib/rogdl'
2
+
3
+ class Fixnum
4
+
5
+
6
+ def to_n
7
+ return Rogdl::Node.new(self.to_s)
8
+ end
9
+
10
+ end
data/lib/hash.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'lib/rogdl'
2
+
3
+ class Hash
4
+
5
+
6
+ def to_n
7
+ return self.to_a.to_n
8
+ end
9
+
10
+ end
data/lib/nil.rb ADDED
@@ -0,0 +1,21 @@
1
+ class NilClass
2
+
3
+ def gvalue
4
+ nil
5
+ end
6
+
7
+ def to_b
8
+ false
9
+ end
10
+
11
+ def to_n
12
+ nil
13
+ end
14
+
15
+ def find_all_named(aName)
16
+ []
17
+ end
18
+ alias gkids find_all_named
19
+
20
+
21
+ end
data/lib/node.rb ADDED
@@ -0,0 +1,139 @@
1
+ module Rogdl
2
+ class Node
3
+ include Enumerable
4
+ include Comparable
5
+
6
+ attr_accessor :gname, :gparent
7
+
8
+ def initialize(aName)
9
+ self.gname = aName
10
+ end
11
+
12
+ def subs(key,value)
13
+ @@subs ||= {}
14
+ @@subs[key] = value
15
+ end
16
+
17
+ def each
18
+ children.each {|element| yield(element)}
19
+ end
20
+
21
+ def empty?
22
+ children.empty?
23
+ end
24
+
25
+ def glength
26
+ children.length
27
+ end
28
+
29
+ def gvalue
30
+ if empty?
31
+ return nil
32
+ else
33
+ val = gfirst.gname
34
+ return val unless val[0,1] == ':'
35
+ return @@subs[val[1, val.length].to_sym]
36
+ end
37
+ end
38
+ alias gval gvalue
39
+
40
+ def gfirst
41
+ return children.first
42
+ end
43
+
44
+
45
+ def [](aName)
46
+ if aName.is_a?(String)
47
+ children.each do |node|
48
+ return node if node.gname == aName
49
+ end
50
+ return nil
51
+ elsif aName.is_a?(Fixnum)
52
+ return children[aName]
53
+ else
54
+ throw "aName must be a String or Fixnum"
55
+ end
56
+ end
57
+
58
+ def []=(arg1, arg2)
59
+ a1 = arg1.to_n
60
+ a1.add arg2.to_n
61
+ add(a1)
62
+ end
63
+
64
+ def method_missing(keyword, *args)
65
+ word = keyword.to_s
66
+ if word.reverse[0,2] == 'zz'
67
+ return self["#{keyword}"] unless self["#{keyword}"].nil?
68
+ return find_all_named(word[0, word.length-2])
69
+ else
70
+ return self["#{keyword}"]
71
+ end
72
+
73
+ end
74
+
75
+ def find_all_named(aName)
76
+ if aName.is_a?(String)
77
+ find_all {|node| node.gname == aName}
78
+ elsif aName.is_a?(Array)
79
+ find_all {|node| aName.include?(node.gname)}
80
+ else
81
+ throw 'aName must be a String or Array'
82
+ end
83
+
84
+ end
85
+ alias gkids find_all_named
86
+
87
+ def <=>(anOther)
88
+ self.gname <=> anOther.gname
89
+ end
90
+
91
+ def add(aNode)
92
+ node = aNode.to_n
93
+ children << node
94
+ node.gparent = self
95
+ return self
96
+ end
97
+
98
+ def to_n
99
+ self
100
+ end
101
+
102
+ def to_xml
103
+ return "<#{@gname}/>" if empty?
104
+ s = "<#{@gname}>"
105
+ if glength == 1 && gfirst.glength == 0
106
+ s += gvalue
107
+ else
108
+ children.each {|node| s += node.to_xml}
109
+ end
110
+ s += "</#{@gname}>"
111
+ return s
112
+ end
113
+
114
+
115
+
116
+ def eql?(bNode)
117
+ return self.flatten.collect {|n| n.gname} == bNode.flatten.collect {|n| n.gname}
118
+ end
119
+
120
+ def ==(bNode)
121
+ return false if bNode.nil?
122
+ return self.eql?(bNode)
123
+ end
124
+
125
+ def flatten
126
+ me = []
127
+ me << self
128
+ self.each {|n| me << n.flatten}
129
+ return me.flatten
130
+ end
131
+
132
+ private
133
+
134
+ def children
135
+ @children ||= []
136
+ end
137
+
138
+ end
139
+ end
data/lib/parser.rb ADDED
@@ -0,0 +1,398 @@
1
+ require 'lib/node'
2
+ module Rogdl
3
+
4
+
5
+ InLine = :in_line
6
+ InPhrase = :in_phrase
7
+ InClause = :in_clause
8
+ InSQString = :in_sq_string
9
+ InDQString = :in_dq_string
10
+ InString = :in_string
11
+ InEscape = :in_escape
12
+ InWhitespace = :in_whitespace
13
+ InComment = :in_comment
14
+ Indent = :indent
15
+
16
+ SchemaString = '#schema://'
17
+
18
+ class Parser
19
+ attr_accessor :state, :spaces, :lines, :prev_state, :escape, :indenting, :line_count
20
+
21
+
22
+
23
+
24
+ def initialize
25
+ @spaces = 0
26
+ @lines = [[]]
27
+ @prev_state = nil
28
+ @escape = false
29
+ @state = InLine
30
+ @indenting = true
31
+ @line_count = 0
32
+ end
33
+
34
+ def Parser.parse_file(filename)
35
+ file = File.new(filename)
36
+ contents = ""
37
+ file.each_byte do |ch|
38
+ contents << ch
39
+ end
40
+ first_line = contents.split("\n").first
41
+ schema = nil
42
+ if first_line[0, SchemaString.length] == SchemaString
43
+ schema = Schema.new(Parser.parse_file(first_line[SchemaString.length, first_line.length]))
44
+ end
45
+ node = Parser.parse(contents)
46
+ if !schema.nil?
47
+ messages = schema.validate(node);
48
+ if messages.length > 0
49
+ puts filename + ' does not match the supplied schema'
50
+ puts messages
51
+ end
52
+ end
53
+ return node
54
+ end
55
+
56
+ def Parser.parse(text)
57
+ p = Parser.new
58
+ p.translate(text)
59
+ return p.convert
60
+ end
61
+
62
+ def append(char)
63
+ @lines.last.last << char
64
+ @indenting = false
65
+ end
66
+
67
+ def add_line
68
+ @lines << []
69
+ @indenting = true
70
+ end
71
+
72
+ def indent
73
+ @lines.last << nil
74
+ end
75
+
76
+ def to_s
77
+ @lines.to_s
78
+ end
79
+
80
+ def changeto(state)
81
+ @state = state
82
+ end
83
+
84
+ def complain(message)
85
+ raise message + " line count: #{@line_count}"
86
+ end
87
+
88
+ def translate(string)
89
+ string.length.times {|i| read(string[i,1])}
90
+ end
91
+
92
+ def capture(state)
93
+ @prev_state = state
94
+ end
95
+
96
+ # def end_string
97
+ # @lines.last << ''
98
+ # end
99
+
100
+ def begin_string
101
+ @lines.last << ''
102
+ end
103
+
104
+
105
+ def read(char)
106
+ case
107
+ when self.state == InLine
108
+ read_line(char)
109
+
110
+ when self.state == InString
111
+ read_string(char)
112
+
113
+ when self.state == InSQString
114
+ read_sq_string(char)
115
+
116
+ when self.state == InDQString
117
+ read_dq_string(char)
118
+
119
+ when self.state == InPhrase
120
+ read_phrase(char)
121
+
122
+ when self.state == InComment
123
+ read_comment(char)
124
+
125
+ else
126
+ complain "unexpected state #{@state}"
127
+ end #switch state
128
+ end # read
129
+
130
+ def read_line(char)
131
+ case
132
+ when char == "'" # Single Quotes
133
+ complain 'invalid indentation ' if @spaces != 0
134
+ begin_string
135
+ capture(InLine)
136
+ changeto(InSQString)
137
+
138
+ when char == '"' # Double Quotes
139
+ complain 'invalid indentation ' if @spaces != 0
140
+ begin_string
141
+ capture(InLine)
142
+ changeto(InDQString)
143
+
144
+ when char == ' ' # Whitespace
145
+ if @indenting
146
+ @spaces += 1
147
+ if @spaces == 4
148
+ @spaces = 0
149
+ indent
150
+ end
151
+ else
152
+ # ignore in line whitespace
153
+ end
154
+
155
+ when char == '#' # Comment
156
+ changeto(InComment)
157
+
158
+ when char == "\t" # Tab
159
+ complain "invalid number of white spaces" if @spaces != 0
160
+ indent
161
+
162
+ when char == "\n" # New Line
163
+ add_line
164
+ @line_count += 1
165
+ @spaces = 0
166
+
167
+ when char == "(" # Open parentheses
168
+ count = 0
169
+ @lines.last.each {|n| count += 1 if n.nil?}
170
+ add_line
171
+ indent
172
+ count.times {indent}
173
+ changeto(InPhrase)
174
+
175
+ when char == ")" # Close parentheses
176
+ complain "close parentheses is unexpected"
177
+
178
+ when char == "," # Comma
179
+ complain "comma is unexpected"
180
+
181
+ else # Normal Character
182
+ complain "invalid indentation parsing character: #{char}" if @spaces != 0
183
+ begin_string
184
+ capture(InLine)
185
+ changeto(InString)
186
+ read(char)
187
+
188
+ end # switch
189
+
190
+ end # read_line
191
+
192
+ def read_phrase(char)
193
+
194
+ case
195
+ when char == "'" # Single Quotes
196
+ capture(InPhrase)
197
+ changeto(InSQString)
198
+ begin_string
199
+
200
+ when char == '"' # Double Quotes
201
+ capture(InPhrase)
202
+ changeto(InDQString)
203
+ begin_string
204
+
205
+ when char == ' ' # Whitespace
206
+ # ignore whitespace
207
+
208
+ when char == '#' # Comment
209
+ complain "unexpected comment '#' in phrase"
210
+
211
+ when char == "\t" # Tab
212
+ # ignore Tab
213
+
214
+ when char == "\n" # New Line
215
+ # complain "unexpected new line character in phrase"
216
+ # add_line
217
+ changeto(InLine)
218
+ read(char)
219
+
220
+ when char == "(" # Open parentheses
221
+ complain "Invalid open parentheses"
222
+
223
+ when char == ")" # Close parentheses
224
+ changeto(InLine)
225
+
226
+ when char == "," # Comma
227
+ count = 0
228
+ @lines.last.each {|n| count += 1 if n.nil?}
229
+ add_line
230
+ count.times {indent}
231
+
232
+ else # Normal Character
233
+ capture(InPhrase)
234
+ changeto(InString)
235
+ begin_string
236
+ read(char)
237
+
238
+ end # switch
239
+
240
+ end # read_phrase
241
+
242
+ def read_string(char)
243
+ case
244
+ when char == "'" # Single Quotes
245
+ complain "single quotes not allowed inside of Node name"
246
+
247
+ when char == '"' # Double Quotes
248
+ complain "double quotes not allowed inside of Node name"
249
+
250
+ when char == ' ' # Whitespace
251
+ changeto(@prev_state)
252
+
253
+ when char == '#' # Comment
254
+ complain "double quotes not allowed inside of Node name"
255
+
256
+ when char == '\\' # Escape
257
+ complain "escape is not allowed inside of Node name"
258
+
259
+ when char == "\t" # Tab
260
+ complain "tabs not allowed inside of Node name"
261
+
262
+ when char == "\n" # New Line
263
+ changeto(InLine)
264
+ add_line
265
+ @line_count += 1
266
+
267
+ when char == "," # Comma
268
+ complain "unexpected comma" unless @prev_state == InPhrase
269
+ changeto(InPhrase)
270
+ read(char)
271
+
272
+ when char == ")" # Close parentheses
273
+ changeto(@prev_state)
274
+
275
+ else # Normal Character
276
+ append(char)
277
+ end # switch
278
+
279
+ end # read_string
280
+
281
+
282
+
283
+ def read_sq_string(char)
284
+ case
285
+ when char == "'" # Single Quotes
286
+ if @escape
287
+ append(char)
288
+ @escape = false
289
+ else
290
+ changeto(@prev_state)
291
+ end
292
+
293
+ when char == '\\' # Escape
294
+ @escape = true
295
+
296
+ when char == "\n" # New Line
297
+ complain "new line is unexpected"
298
+
299
+ else # Normal Character
300
+ append(char)
301
+ @escape = false
302
+ end # switch
303
+
304
+ end # read_sq_string
305
+
306
+ def read_dq_string(char)
307
+ case
308
+ when char == '"' # Double Quotes
309
+ if @escape
310
+ append(char)
311
+ @escape = false
312
+ else
313
+ changeto(@prev_state)
314
+ end
315
+
316
+ when char == '\\' # Escape
317
+ @escape = true
318
+
319
+ when char == "\n" # New Line
320
+ complain "new line is unexpected"
321
+
322
+ else # Normal Character
323
+ append(char)
324
+ @escape = false
325
+ end # switch
326
+
327
+ end # read_sq_string
328
+
329
+
330
+
331
+ def read_comment(char)
332
+ case
333
+ when char == "\n" # New Line
334
+ add_line
335
+ changeto(InLine)
336
+ else
337
+ # ignore characters
338
+
339
+ end # switch
340
+
341
+ end # read_line
342
+
343
+
344
+ def convert
345
+
346
+ nodes = convert_nodes
347
+
348
+ nodes.each_with_index do |line, i|
349
+ first_in_line = nil
350
+ line.each_with_index do |node, j|
351
+
352
+ if !node.nil?
353
+
354
+ if first_in_line.nil?
355
+ first_in_line = node
356
+ #find parent here
357
+
358
+ nodes[0..i].reverse.each do |array|
359
+
360
+ if !array[j-1].nil? && i != 0
361
+ array[j-1].add(node)
362
+ break
363
+ end
364
+
365
+ end
366
+
367
+ else
368
+ first_in_line.add(node)
369
+ end
370
+ end
371
+ end
372
+ end
373
+ # puts parent.flatten.collect {|n| n.gname}
374
+ return nodes[0][0]
375
+ end
376
+
377
+ def convert_nodes
378
+
379
+ nodes = []
380
+
381
+ @lines.each_with_index do |line, i|
382
+ if line != []
383
+ temp = []
384
+ nodes << temp
385
+
386
+ line.each_with_index do |name, j|
387
+ temp[j] = Node.new(name) unless name.nil?
388
+ end
389
+ end
390
+ end
391
+ return nodes
392
+ end
393
+
394
+
395
+ end # class Parser
396
+
397
+
398
+ end # module Rogdl