worked 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/History.txt +5 -0
- data/Manifest.txt +6 -0
- data/README.rdoc +6 -2
- data/Rakefile +1 -0
- data/bin/worked +2 -2
- data/lib/worked.rb +1 -1
- data/lib/worked/cli.rb +51 -20
- data/lib/worked/graph.rb +37 -0
- data/lib/worked/inputgrammar.rb +741 -0
- data/lib/worked/inputparser.rb +29 -17
- data/lib/worked/reader.rb +74 -0
- data/tasks/parser_generate.rake +4 -0
- data/test/test_grammar.rb +23 -29
- data/test/test_reader.rb +101 -0
- data/test/test_worked_cli.rb +22 -3
- data/website/index.html +120 -0
- metadata +35 -7
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -7,18 +7,24 @@ bin/worked
|
|
7
7
|
config/website.yml
|
8
8
|
lib/worked.rb
|
9
9
|
lib/worked/cli.rb
|
10
|
+
lib/worked/graph.rb
|
11
|
+
lib/worked/inputgrammar.rb
|
10
12
|
lib/worked/inputgrammar.treetop
|
11
13
|
lib/worked/inputparser.rb
|
14
|
+
lib/worked/reader.rb
|
12
15
|
lib/worked/recorder.rb
|
13
16
|
script/console
|
14
17
|
script/destroy
|
15
18
|
script/generate
|
16
19
|
script/txt2html
|
20
|
+
tasks/parser_generate.rake
|
17
21
|
tasks/website.rake
|
18
22
|
test/test_grammar.rb
|
19
23
|
test/test_helper.rb
|
24
|
+
test/test_reader.rb
|
20
25
|
test/test_worked.rb
|
21
26
|
test/test_worked_cli.rb
|
27
|
+
website/index.html
|
22
28
|
website/javascripts/rounded_corners_lite.inc.js
|
23
29
|
website/stylesheets/screen.css
|
24
30
|
website/template.rhtml
|
data/README.rdoc
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
= Worked
|
2
2
|
|
3
|
-
The easiest time recording application imagineable.
|
4
|
-
|
5
3
|
* http://worked.rubyforge.org/
|
6
4
|
|
5
|
+
The easiest time recording application imagineable.
|
6
|
+
|
7
7
|
== DESCRIPTION:
|
8
8
|
|
9
9
|
Worked is really the simplest time recording (or tracking, whatever term you
|
@@ -19,6 +19,7 @@ Right now, the times are just recorded, no report generation yet.
|
|
19
19
|
== FEATURES:
|
20
20
|
|
21
21
|
* Appends a time range and an activity to a file.
|
22
|
+
* Create a graph from the collected data, showing hours/week.
|
22
23
|
|
23
24
|
== SYNOPSIS:
|
24
25
|
|
@@ -57,6 +58,9 @@ write:
|
|
57
58
|
Specifying dates is not supported right now, but you can of course edit the file
|
58
59
|
directly if necessary.
|
59
60
|
|
61
|
+
Since version 0.2, worked also has the ability to generate a graph from the
|
62
|
+
collected data, using the -g argument. [TODO: Add image here.]
|
63
|
+
|
60
64
|
== STORY:
|
61
65
|
|
62
66
|
The week before my new semester started, I promised to myself to do better (or,
|
data/Rakefile
CHANGED
data/bin/worked
CHANGED
data/lib/worked.rb
CHANGED
data/lib/worked/cli.rb
CHANGED
@@ -1,37 +1,68 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
require 'worked/recorder'
|
3
|
+
require 'worked/graph'
|
3
4
|
|
4
5
|
module Worked
|
5
6
|
class CLI
|
6
7
|
def self.execute(stdout, arguments, file)
|
7
8
|
|
8
|
-
|
9
|
+
if arguments.empty?
|
10
|
+
parse_options(stdout, ["--help"], file)
|
11
|
+
end
|
9
12
|
|
10
|
-
|
11
|
-
# :path => '~'
|
12
|
-
#}
|
13
|
+
begin
|
13
14
|
|
14
|
-
|
15
|
-
# opts.banner = <<-BANNER.gsub(/^ /,'')
|
16
|
-
# This application is wonderful because...
|
15
|
+
try_to_parse(file, arguments.join(" "))
|
17
16
|
|
18
|
-
|
17
|
+
rescue CannotParse
|
19
18
|
|
20
|
-
|
21
|
-
# BANNER
|
22
|
-
# opts.separator ""
|
23
|
-
# opts.on("-p", "--path=PATH", String,
|
24
|
-
# "This is a sample message.",
|
25
|
-
# "For multiple lines, add more strings.",
|
26
|
-
# "Default: ~") { |arg| options[:path] = arg }
|
27
|
-
# opts.on("-h", "--help",
|
28
|
-
# "Show this help message.") { stdout.puts opts; exit }
|
19
|
+
options = parse_options(stdout, arguments, file)
|
29
20
|
|
30
|
-
|
31
|
-
#end
|
21
|
+
if options[:graph_path]
|
32
22
|
|
33
|
-
|
23
|
+
graph(stdout, file, options[:graph_path])
|
34
24
|
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.try_to_parse file, string
|
30
|
+
|
31
|
+
Recorder.new(file).record(string)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.graph stdout, file, path
|
35
|
+
|
36
|
+
Graph::create_weekly(Reader::by_week(file.readlines), path)
|
37
|
+
|
38
|
+
stdout.puts "Graph saved to #{path}."
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.parse_options(stdout, arguments, file)
|
42
|
+
|
43
|
+
options = {}
|
44
|
+
|
45
|
+
parser = OptionParser.new do |opts|
|
46
|
+
opts.banner = <<-BANNER.gsub(/^ /,'')
|
47
|
+
This application is wonderful!
|
48
|
+
|
49
|
+
Usage: #{File.basename($0)} [options]
|
50
|
+
#{File.basename($0)} work time specification
|
51
|
+
|
52
|
+
Options are:
|
53
|
+
BANNER
|
54
|
+
opts.separator ""
|
55
|
+
opts.on("-g", "--graph=PATH", String,
|
56
|
+
"Prints a graph to the specified file.") { |arg|
|
57
|
+
options[:graph_path] = arg
|
58
|
+
}
|
59
|
+
opts.on("-h", "--help",
|
60
|
+
"Show this help message.") { stdout.puts opts; exit }
|
61
|
+
|
62
|
+
opts.parse!(arguments)
|
63
|
+
end
|
64
|
+
|
65
|
+
options
|
35
66
|
end
|
36
67
|
end
|
37
68
|
end
|
data/lib/worked/graph.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'gruff'
|
3
|
+
|
4
|
+
require 'worked/reader'
|
5
|
+
|
6
|
+
module Worked
|
7
|
+
|
8
|
+
class Graph
|
9
|
+
|
10
|
+
def self.create_weekly entries, output_file
|
11
|
+
create(entries, output_file)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.create_daily entries, output_file
|
15
|
+
create(entries, output_file)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.create entries, output_file
|
21
|
+
|
22
|
+
g = Gruff::Bar.new
|
23
|
+
g.title = "My Work Hours"
|
24
|
+
g.y_axis_increment = 2
|
25
|
+
g.y_axis_label = "Hours"
|
26
|
+
g.x_axis_label = "Week of the Year"
|
27
|
+
|
28
|
+
g.data("Total: #{entries.sum{|e| e.hours.to_f}.to_i.to_s} Hours", entries.collect {|e| e.hours.to_f})
|
29
|
+
|
30
|
+
g.minimum_value = 0
|
31
|
+
|
32
|
+
g.labels = entries.inject({}) {|h, e| h.merge( { h.size => e.date.to_s }) }
|
33
|
+
|
34
|
+
g.write output_file
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,741 @@
|
|
1
|
+
|
2
|
+
module InputGrammar
|
3
|
+
include Treetop::Runtime
|
4
|
+
|
5
|
+
def root
|
6
|
+
@root || :root
|
7
|
+
end
|
8
|
+
|
9
|
+
module Root0
|
10
|
+
def time
|
11
|
+
elements[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
def activity
|
15
|
+
elements[2]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def _nt_root
|
20
|
+
start_index = index
|
21
|
+
if node_cache[:root].has_key?(index)
|
22
|
+
cached = node_cache[:root][index]
|
23
|
+
@index = cached.interval.end if cached
|
24
|
+
return cached
|
25
|
+
end
|
26
|
+
|
27
|
+
i0, s0 = index, []
|
28
|
+
r1 = _nt_time
|
29
|
+
s0 << r1
|
30
|
+
if r1
|
31
|
+
if input.index(" on ", index) == index
|
32
|
+
r2 = instantiate_node(SyntaxNode,input, index...(index + 4))
|
33
|
+
@index += 4
|
34
|
+
else
|
35
|
+
terminal_parse_failure(" on ")
|
36
|
+
r2 = nil
|
37
|
+
end
|
38
|
+
s0 << r2
|
39
|
+
if r2
|
40
|
+
r3 = _nt_activity
|
41
|
+
s0 << r3
|
42
|
+
end
|
43
|
+
end
|
44
|
+
if s0.last
|
45
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
46
|
+
r0.extend(Root0)
|
47
|
+
else
|
48
|
+
self.index = i0
|
49
|
+
r0 = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
node_cache[:root][start_index] = r0
|
53
|
+
|
54
|
+
return r0
|
55
|
+
end
|
56
|
+
|
57
|
+
def _nt_activity
|
58
|
+
start_index = index
|
59
|
+
if node_cache[:activity].has_key?(index)
|
60
|
+
cached = node_cache[:activity][index]
|
61
|
+
@index = cached.interval.end if cached
|
62
|
+
return cached
|
63
|
+
end
|
64
|
+
|
65
|
+
s0, i0 = [], index
|
66
|
+
loop do
|
67
|
+
if index < input_length
|
68
|
+
r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
69
|
+
@index += 1
|
70
|
+
else
|
71
|
+
terminal_parse_failure("any character")
|
72
|
+
r1 = nil
|
73
|
+
end
|
74
|
+
if r1
|
75
|
+
s0 << r1
|
76
|
+
else
|
77
|
+
break
|
78
|
+
end
|
79
|
+
end
|
80
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
81
|
+
|
82
|
+
node_cache[:activity][start_index] = r0
|
83
|
+
|
84
|
+
return r0
|
85
|
+
end
|
86
|
+
|
87
|
+
def _nt_time
|
88
|
+
start_index = index
|
89
|
+
if node_cache[:time].has_key?(index)
|
90
|
+
cached = node_cache[:time][index]
|
91
|
+
@index = cached.interval.end if cached
|
92
|
+
return cached
|
93
|
+
end
|
94
|
+
|
95
|
+
i0 = index
|
96
|
+
r1 = _nt_time_from
|
97
|
+
if r1
|
98
|
+
r0 = r1
|
99
|
+
else
|
100
|
+
r2 = _nt_time_in_words
|
101
|
+
if r2
|
102
|
+
r0 = r2
|
103
|
+
else
|
104
|
+
r3 = _nt_time_range
|
105
|
+
if r3
|
106
|
+
r0 = r3
|
107
|
+
else
|
108
|
+
r4 = _nt_time_in_digits
|
109
|
+
if r4
|
110
|
+
r0 = r4
|
111
|
+
else
|
112
|
+
self.index = i0
|
113
|
+
r0 = nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
node_cache[:time][start_index] = r0
|
120
|
+
|
121
|
+
return r0
|
122
|
+
end
|
123
|
+
|
124
|
+
module TimeFrom0
|
125
|
+
def am_pm_time
|
126
|
+
elements[1]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
module TimeFrom1
|
131
|
+
def from
|
132
|
+
am_pm_time.to_24h
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def _nt_time_from
|
137
|
+
start_index = index
|
138
|
+
if node_cache[:time_from].has_key?(index)
|
139
|
+
cached = node_cache[:time_from][index]
|
140
|
+
@index = cached.interval.end if cached
|
141
|
+
return cached
|
142
|
+
end
|
143
|
+
|
144
|
+
i0, s0 = index, []
|
145
|
+
if input.index("from ", index) == index
|
146
|
+
r1 = instantiate_node(SyntaxNode,input, index...(index + 5))
|
147
|
+
@index += 5
|
148
|
+
else
|
149
|
+
terminal_parse_failure("from ")
|
150
|
+
r1 = nil
|
151
|
+
end
|
152
|
+
s0 << r1
|
153
|
+
if r1
|
154
|
+
r2 = _nt_am_pm_time
|
155
|
+
s0 << r2
|
156
|
+
end
|
157
|
+
if s0.last
|
158
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
159
|
+
r0.extend(TimeFrom0)
|
160
|
+
r0.extend(TimeFrom1)
|
161
|
+
else
|
162
|
+
self.index = i0
|
163
|
+
r0 = nil
|
164
|
+
end
|
165
|
+
|
166
|
+
node_cache[:time_from][start_index] = r0
|
167
|
+
|
168
|
+
return r0
|
169
|
+
end
|
170
|
+
|
171
|
+
module TimeRange0
|
172
|
+
def f
|
173
|
+
elements[0]
|
174
|
+
end
|
175
|
+
|
176
|
+
def t
|
177
|
+
elements[2]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
module TimeRange1
|
182
|
+
def from
|
183
|
+
f.to_24h
|
184
|
+
end
|
185
|
+
|
186
|
+
def to
|
187
|
+
t.to_24h
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def _nt_time_range
|
192
|
+
start_index = index
|
193
|
+
if node_cache[:time_range].has_key?(index)
|
194
|
+
cached = node_cache[:time_range][index]
|
195
|
+
@index = cached.interval.end if cached
|
196
|
+
return cached
|
197
|
+
end
|
198
|
+
|
199
|
+
i0, s0 = index, []
|
200
|
+
r1 = _nt_am_pm_time
|
201
|
+
s0 << r1
|
202
|
+
if r1
|
203
|
+
if input.index(" to ", index) == index
|
204
|
+
r2 = instantiate_node(SyntaxNode,input, index...(index + 4))
|
205
|
+
@index += 4
|
206
|
+
else
|
207
|
+
terminal_parse_failure(" to ")
|
208
|
+
r2 = nil
|
209
|
+
end
|
210
|
+
s0 << r2
|
211
|
+
if r2
|
212
|
+
r3 = _nt_am_pm_time
|
213
|
+
s0 << r3
|
214
|
+
end
|
215
|
+
end
|
216
|
+
if s0.last
|
217
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
218
|
+
r0.extend(TimeRange0)
|
219
|
+
r0.extend(TimeRange1)
|
220
|
+
else
|
221
|
+
self.index = i0
|
222
|
+
r0 = nil
|
223
|
+
end
|
224
|
+
|
225
|
+
node_cache[:time_range][start_index] = r0
|
226
|
+
|
227
|
+
return r0
|
228
|
+
end
|
229
|
+
|
230
|
+
module AmPmTime0
|
231
|
+
def time_in_digits
|
232
|
+
elements[0]
|
233
|
+
end
|
234
|
+
|
235
|
+
def am_pm
|
236
|
+
elements[1]
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
module AmPmTime1
|
241
|
+
def to_24h
|
242
|
+
|
243
|
+
if methods.include?("am_pm") && am_pm.text_value =~ /pm/
|
244
|
+
return time_in_digits.total + 12.hours
|
245
|
+
end
|
246
|
+
|
247
|
+
time_in_digits.total
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def _nt_am_pm_time
|
252
|
+
start_index = index
|
253
|
+
if node_cache[:am_pm_time].has_key?(index)
|
254
|
+
cached = node_cache[:am_pm_time][index]
|
255
|
+
@index = cached.interval.end if cached
|
256
|
+
return cached
|
257
|
+
end
|
258
|
+
|
259
|
+
i0, s0 = index, []
|
260
|
+
r1 = _nt_time_in_digits
|
261
|
+
s0 << r1
|
262
|
+
if r1
|
263
|
+
i3 = index
|
264
|
+
if input.index(" am", index) == index
|
265
|
+
r4 = instantiate_node(SyntaxNode,input, index...(index + 3))
|
266
|
+
@index += 3
|
267
|
+
else
|
268
|
+
terminal_parse_failure(" am")
|
269
|
+
r4 = nil
|
270
|
+
end
|
271
|
+
if r4
|
272
|
+
r3 = r4
|
273
|
+
else
|
274
|
+
if input.index(" pm", index) == index
|
275
|
+
r5 = instantiate_node(SyntaxNode,input, index...(index + 3))
|
276
|
+
@index += 3
|
277
|
+
else
|
278
|
+
terminal_parse_failure(" pm")
|
279
|
+
r5 = nil
|
280
|
+
end
|
281
|
+
if r5
|
282
|
+
r3 = r5
|
283
|
+
else
|
284
|
+
if input.index("am", index) == index
|
285
|
+
r6 = instantiate_node(SyntaxNode,input, index...(index + 2))
|
286
|
+
@index += 2
|
287
|
+
else
|
288
|
+
terminal_parse_failure("am")
|
289
|
+
r6 = nil
|
290
|
+
end
|
291
|
+
if r6
|
292
|
+
r3 = r6
|
293
|
+
else
|
294
|
+
if input.index("pm", index) == index
|
295
|
+
r7 = instantiate_node(SyntaxNode,input, index...(index + 2))
|
296
|
+
@index += 2
|
297
|
+
else
|
298
|
+
terminal_parse_failure("pm")
|
299
|
+
r7 = nil
|
300
|
+
end
|
301
|
+
if r7
|
302
|
+
r3 = r7
|
303
|
+
else
|
304
|
+
self.index = i3
|
305
|
+
r3 = nil
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
if r3
|
311
|
+
r2 = r3
|
312
|
+
else
|
313
|
+
r2 = instantiate_node(SyntaxNode,input, index...index)
|
314
|
+
end
|
315
|
+
s0 << r2
|
316
|
+
end
|
317
|
+
if s0.last
|
318
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
319
|
+
r0.extend(AmPmTime0)
|
320
|
+
r0.extend(AmPmTime1)
|
321
|
+
else
|
322
|
+
self.index = i0
|
323
|
+
r0 = nil
|
324
|
+
end
|
325
|
+
|
326
|
+
node_cache[:am_pm_time][start_index] = r0
|
327
|
+
|
328
|
+
return r0
|
329
|
+
end
|
330
|
+
|
331
|
+
module TimeInWords0
|
332
|
+
def minutes
|
333
|
+
elements[1]
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
module TimeInWords1
|
338
|
+
def hours
|
339
|
+
elements[0]
|
340
|
+
end
|
341
|
+
|
342
|
+
def m
|
343
|
+
elements[1]
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
module TimeInWords2
|
348
|
+
def total
|
349
|
+
minutes.to_i.minutes + hours.to_i.hours + m.to_i.minutes
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def _nt_time_in_words
|
354
|
+
start_index = index
|
355
|
+
if node_cache[:time_in_words].has_key?(index)
|
356
|
+
cached = node_cache[:time_in_words][index]
|
357
|
+
@index = cached.interval.end if cached
|
358
|
+
return cached
|
359
|
+
end
|
360
|
+
|
361
|
+
i0 = index
|
362
|
+
r1 = _nt_minutes
|
363
|
+
if r1
|
364
|
+
r0 = r1
|
365
|
+
else
|
366
|
+
i2, s2 = index, []
|
367
|
+
r3 = _nt_hours
|
368
|
+
s2 << r3
|
369
|
+
if r3
|
370
|
+
i5, s5 = index, []
|
371
|
+
if input.index(" ", index) == index
|
372
|
+
r7 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
373
|
+
@index += 1
|
374
|
+
else
|
375
|
+
terminal_parse_failure(" ")
|
376
|
+
r7 = nil
|
377
|
+
end
|
378
|
+
if r7
|
379
|
+
r6 = r7
|
380
|
+
else
|
381
|
+
r6 = instantiate_node(SyntaxNode,input, index...index)
|
382
|
+
end
|
383
|
+
s5 << r6
|
384
|
+
if r6
|
385
|
+
r8 = _nt_minutes
|
386
|
+
s5 << r8
|
387
|
+
end
|
388
|
+
if s5.last
|
389
|
+
r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
|
390
|
+
r5.extend(TimeInWords0)
|
391
|
+
else
|
392
|
+
self.index = i5
|
393
|
+
r5 = nil
|
394
|
+
end
|
395
|
+
if r5
|
396
|
+
r4 = r5
|
397
|
+
else
|
398
|
+
r4 = instantiate_node(SyntaxNode,input, index...index)
|
399
|
+
end
|
400
|
+
s2 << r4
|
401
|
+
end
|
402
|
+
if s2.last
|
403
|
+
r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
|
404
|
+
r2.extend(TimeInWords1)
|
405
|
+
r2.extend(TimeInWords2)
|
406
|
+
else
|
407
|
+
self.index = i2
|
408
|
+
r2 = nil
|
409
|
+
end
|
410
|
+
if r2
|
411
|
+
r0 = r2
|
412
|
+
else
|
413
|
+
self.index = i0
|
414
|
+
r0 = nil
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
node_cache[:time_in_words][start_index] = r0
|
419
|
+
|
420
|
+
return r0
|
421
|
+
end
|
422
|
+
|
423
|
+
module TimeInDigits0
|
424
|
+
def integer
|
425
|
+
elements[1]
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
module TimeInDigits1
|
430
|
+
def integer
|
431
|
+
elements[0]
|
432
|
+
end
|
433
|
+
|
434
|
+
def m
|
435
|
+
elements[1]
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
module TimeInDigits2
|
440
|
+
def total
|
441
|
+
integer.to_i.hours + m.to_i.minutes
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
def _nt_time_in_digits
|
446
|
+
start_index = index
|
447
|
+
if node_cache[:time_in_digits].has_key?(index)
|
448
|
+
cached = node_cache[:time_in_digits][index]
|
449
|
+
@index = cached.interval.end if cached
|
450
|
+
return cached
|
451
|
+
end
|
452
|
+
|
453
|
+
i0, s0 = index, []
|
454
|
+
r1 = _nt_integer
|
455
|
+
s0 << r1
|
456
|
+
if r1
|
457
|
+
i3, s3 = index, []
|
458
|
+
if input.index(":", index) == index
|
459
|
+
r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
460
|
+
@index += 1
|
461
|
+
else
|
462
|
+
terminal_parse_failure(":")
|
463
|
+
r4 = nil
|
464
|
+
end
|
465
|
+
s3 << r4
|
466
|
+
if r4
|
467
|
+
r5 = _nt_integer
|
468
|
+
s3 << r5
|
469
|
+
end
|
470
|
+
if s3.last
|
471
|
+
r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
|
472
|
+
r3.extend(TimeInDigits0)
|
473
|
+
else
|
474
|
+
self.index = i3
|
475
|
+
r3 = nil
|
476
|
+
end
|
477
|
+
if r3
|
478
|
+
r2 = r3
|
479
|
+
else
|
480
|
+
r2 = instantiate_node(SyntaxNode,input, index...index)
|
481
|
+
end
|
482
|
+
s0 << r2
|
483
|
+
end
|
484
|
+
if s0.last
|
485
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
486
|
+
r0.extend(TimeInDigits1)
|
487
|
+
r0.extend(TimeInDigits2)
|
488
|
+
else
|
489
|
+
self.index = i0
|
490
|
+
r0 = nil
|
491
|
+
end
|
492
|
+
|
493
|
+
node_cache[:time_in_digits][start_index] = r0
|
494
|
+
|
495
|
+
return r0
|
496
|
+
end
|
497
|
+
|
498
|
+
module Hours0
|
499
|
+
end
|
500
|
+
|
501
|
+
module Hours1
|
502
|
+
def integer
|
503
|
+
elements[0]
|
504
|
+
end
|
505
|
+
|
506
|
+
end
|
507
|
+
|
508
|
+
def _nt_hours
|
509
|
+
start_index = index
|
510
|
+
if node_cache[:hours].has_key?(index)
|
511
|
+
cached = node_cache[:hours][index]
|
512
|
+
@index = cached.interval.end if cached
|
513
|
+
return cached
|
514
|
+
end
|
515
|
+
|
516
|
+
i0, s0 = index, []
|
517
|
+
r1 = _nt_integer
|
518
|
+
s0 << r1
|
519
|
+
if r1
|
520
|
+
if input.index(" ", index) == index
|
521
|
+
r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
522
|
+
@index += 1
|
523
|
+
else
|
524
|
+
terminal_parse_failure(" ")
|
525
|
+
r3 = nil
|
526
|
+
end
|
527
|
+
if r3
|
528
|
+
r2 = r3
|
529
|
+
else
|
530
|
+
r2 = instantiate_node(SyntaxNode,input, index...index)
|
531
|
+
end
|
532
|
+
s0 << r2
|
533
|
+
if r2
|
534
|
+
i4 = index
|
535
|
+
i5, s5 = index, []
|
536
|
+
if input.index("hour", index) == index
|
537
|
+
r6 = instantiate_node(SyntaxNode,input, index...(index + 4))
|
538
|
+
@index += 4
|
539
|
+
else
|
540
|
+
terminal_parse_failure("hour")
|
541
|
+
r6 = nil
|
542
|
+
end
|
543
|
+
s5 << r6
|
544
|
+
if r6
|
545
|
+
if input.index("s", index) == index
|
546
|
+
r8 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
547
|
+
@index += 1
|
548
|
+
else
|
549
|
+
terminal_parse_failure("s")
|
550
|
+
r8 = nil
|
551
|
+
end
|
552
|
+
if r8
|
553
|
+
r7 = r8
|
554
|
+
else
|
555
|
+
r7 = instantiate_node(SyntaxNode,input, index...index)
|
556
|
+
end
|
557
|
+
s5 << r7
|
558
|
+
end
|
559
|
+
if s5.last
|
560
|
+
r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
|
561
|
+
r5.extend(Hours0)
|
562
|
+
else
|
563
|
+
self.index = i5
|
564
|
+
r5 = nil
|
565
|
+
end
|
566
|
+
if r5
|
567
|
+
r4 = r5
|
568
|
+
else
|
569
|
+
if input.index("h", index) == index
|
570
|
+
r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
571
|
+
@index += 1
|
572
|
+
else
|
573
|
+
terminal_parse_failure("h")
|
574
|
+
r9 = nil
|
575
|
+
end
|
576
|
+
if r9
|
577
|
+
r4 = r9
|
578
|
+
else
|
579
|
+
self.index = i4
|
580
|
+
r4 = nil
|
581
|
+
end
|
582
|
+
end
|
583
|
+
s0 << r4
|
584
|
+
end
|
585
|
+
end
|
586
|
+
if s0.last
|
587
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
588
|
+
r0.extend(Hours1)
|
589
|
+
else
|
590
|
+
self.index = i0
|
591
|
+
r0 = nil
|
592
|
+
end
|
593
|
+
|
594
|
+
node_cache[:hours][start_index] = r0
|
595
|
+
|
596
|
+
return r0
|
597
|
+
end
|
598
|
+
|
599
|
+
module Minutes0
|
600
|
+
end
|
601
|
+
|
602
|
+
module Minutes1
|
603
|
+
def integer
|
604
|
+
elements[0]
|
605
|
+
end
|
606
|
+
|
607
|
+
end
|
608
|
+
|
609
|
+
module Minutes2
|
610
|
+
def total
|
611
|
+
integer.to_i.minutes
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
def _nt_minutes
|
616
|
+
start_index = index
|
617
|
+
if node_cache[:minutes].has_key?(index)
|
618
|
+
cached = node_cache[:minutes][index]
|
619
|
+
@index = cached.interval.end if cached
|
620
|
+
return cached
|
621
|
+
end
|
622
|
+
|
623
|
+
i0, s0 = index, []
|
624
|
+
r1 = _nt_integer
|
625
|
+
s0 << r1
|
626
|
+
if r1
|
627
|
+
if input.index(" ", index) == index
|
628
|
+
r3 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
629
|
+
@index += 1
|
630
|
+
else
|
631
|
+
terminal_parse_failure(" ")
|
632
|
+
r3 = nil
|
633
|
+
end
|
634
|
+
if r3
|
635
|
+
r2 = r3
|
636
|
+
else
|
637
|
+
r2 = instantiate_node(SyntaxNode,input, index...index)
|
638
|
+
end
|
639
|
+
s0 << r2
|
640
|
+
if r2
|
641
|
+
i4 = index
|
642
|
+
i5, s5 = index, []
|
643
|
+
if input.index("minute", index) == index
|
644
|
+
r6 = instantiate_node(SyntaxNode,input, index...(index + 6))
|
645
|
+
@index += 6
|
646
|
+
else
|
647
|
+
terminal_parse_failure("minute")
|
648
|
+
r6 = nil
|
649
|
+
end
|
650
|
+
s5 << r6
|
651
|
+
if r6
|
652
|
+
if input.index("s", index) == index
|
653
|
+
r8 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
654
|
+
@index += 1
|
655
|
+
else
|
656
|
+
terminal_parse_failure("s")
|
657
|
+
r8 = nil
|
658
|
+
end
|
659
|
+
if r8
|
660
|
+
r7 = r8
|
661
|
+
else
|
662
|
+
r7 = instantiate_node(SyntaxNode,input, index...index)
|
663
|
+
end
|
664
|
+
s5 << r7
|
665
|
+
end
|
666
|
+
if s5.last
|
667
|
+
r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
|
668
|
+
r5.extend(Minutes0)
|
669
|
+
else
|
670
|
+
self.index = i5
|
671
|
+
r5 = nil
|
672
|
+
end
|
673
|
+
if r5
|
674
|
+
r4 = r5
|
675
|
+
else
|
676
|
+
if input.index("m", index) == index
|
677
|
+
r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
678
|
+
@index += 1
|
679
|
+
else
|
680
|
+
terminal_parse_failure("m")
|
681
|
+
r9 = nil
|
682
|
+
end
|
683
|
+
if r9
|
684
|
+
r4 = r9
|
685
|
+
else
|
686
|
+
self.index = i4
|
687
|
+
r4 = nil
|
688
|
+
end
|
689
|
+
end
|
690
|
+
s0 << r4
|
691
|
+
end
|
692
|
+
end
|
693
|
+
if s0.last
|
694
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
695
|
+
r0.extend(Minutes1)
|
696
|
+
r0.extend(Minutes2)
|
697
|
+
else
|
698
|
+
self.index = i0
|
699
|
+
r0 = nil
|
700
|
+
end
|
701
|
+
|
702
|
+
node_cache[:minutes][start_index] = r0
|
703
|
+
|
704
|
+
return r0
|
705
|
+
end
|
706
|
+
|
707
|
+
def _nt_integer
|
708
|
+
start_index = index
|
709
|
+
if node_cache[:integer].has_key?(index)
|
710
|
+
cached = node_cache[:integer][index]
|
711
|
+
@index = cached.interval.end if cached
|
712
|
+
return cached
|
713
|
+
end
|
714
|
+
|
715
|
+
s0, i0 = [], index
|
716
|
+
loop do
|
717
|
+
if input.index(Regexp.new('[0-9]'), index) == index
|
718
|
+
r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
719
|
+
@index += 1
|
720
|
+
else
|
721
|
+
r1 = nil
|
722
|
+
end
|
723
|
+
if r1
|
724
|
+
s0 << r1
|
725
|
+
else
|
726
|
+
break
|
727
|
+
end
|
728
|
+
end
|
729
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
730
|
+
|
731
|
+
node_cache[:integer][start_index] = r0
|
732
|
+
|
733
|
+
return r0
|
734
|
+
end
|
735
|
+
|
736
|
+
end
|
737
|
+
|
738
|
+
class InputGrammarParser < Treetop::Runtime::CompiledParser
|
739
|
+
include InputGrammar
|
740
|
+
end
|
741
|
+
|