schedule_job 1.0.1 → 1.0.6
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.
- checksums.yaml +4 -4
- data/Gemfile +1 -4
- data/Gemfile.lock +1 -1
- data/README.md +71 -1
- data/lib/schedule_job/cli.rb +21 -12
- data/lib/schedule_job/cron.rb +58 -42
- data/lib/schedule_job/cron_parser.rb +0 -13
- data/lib/schedule_job/version.rb +1 -1
- data/schedule_job.gemspec +1 -1
- metadata +2 -3
- data/lib/schedule_job/cron.treetop +0 -167
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a0f470384777a45f805dc1ff41c9f6386db8378c509eec95b647a577f43e06e
|
4
|
+
data.tar.gz: 9fa202bc1743951f7a2e350c379a1d0d79e0a5f2926fad5aa3c9393be042287d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddd20ca47d699cf56bd6e653a84065fe45c10133fd716af28fc092e2550deffe9a5465041e21ee287a3f4e9bfb34a9cdb14dd642ee5db1b3a807b6430fd9da28
|
7
|
+
data.tar.gz: 2e268c4aaa999e4c75df56aa0d4396a0269d9064cc9c46498598c0a5a0086ac1fe7e809cf243b8ddb2df98020b13fde6f6d40fd076e43ad440dc518918dadf81
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -5,13 +5,83 @@ schedule is a frontend around crontab to add/remove cron jobs from user cron tab
|
|
5
5
|
## Installation
|
6
6
|
|
7
7
|
```
|
8
|
-
gem install schedule_job
|
8
|
+
~ ❯ gem install schedule_job
|
9
|
+
Fetching schedule_job-1.0.1.gem
|
10
|
+
Successfully installed schedule_job-1.0.1
|
11
|
+
Parsing documentation for schedule_job-1.0.1
|
12
|
+
Installing ri documentation for schedule_job-1.0.1
|
13
|
+
Done installing documentation for schedule_job after 0 seconds
|
9
14
|
```
|
10
15
|
|
11
16
|
## Usage
|
12
17
|
|
18
|
+
Example usage:
|
13
19
|
```
|
20
|
+
~ ❯ schedule --help
|
21
|
+
Usage: schedule [options] command
|
22
|
+
-d, --dryrun Report what would happen but do not install the scheduled job.
|
23
|
+
-l, --list List installed cron jobs.
|
24
|
+
-r, --rm JOB_ID Remove the specified job id as indicated by --list
|
25
|
+
-u, --user USER User that the crontab belongs to.
|
26
|
+
-e, --every DURATION Run command every DURATION units of time (valid suffixes are m, h, d, M). DURATION may also be one of the special keywords: reboot, year, month, week, day, hour
|
27
|
+
For example:
|
28
|
+
--every 10m # every 10 minutes
|
29
|
+
--every 5h # every 5 hours
|
30
|
+
--every 2d # every 2 days
|
31
|
+
--every 3M # every 3 months
|
14
32
|
|
33
|
+
Special durations:
|
34
|
+
--every reboot # after every reboot
|
35
|
+
--every year # every year
|
36
|
+
--every month # every month
|
37
|
+
--every week # every week
|
38
|
+
--every day # every day
|
39
|
+
--every hour # every hour
|
40
|
+
|
41
|
+
-c, --cron CRON Run command on the given cron schedule.
|
42
|
+
For example:
|
43
|
+
--cron "*/5 15 * * 1-5" # Every 5 minutes, at 3:00 PM, Monday through Friday
|
44
|
+
--cron "0 0/30 8-9 5,20 * ?" # Every 30 minutes, between 8:00 AM and 9:59 AM, on day 5 and 20 of the month
|
45
|
+
|
46
|
+
~ ❯ schedule -l
|
47
|
+
~ ❯ schedule -d -e 10m backup.sh
|
48
|
+
Scheduling: backup.sh Every 10 minutes
|
49
|
+
Next three runs:
|
50
|
+
1. 2021-11-01 21:50:00 -0500
|
51
|
+
2. 2021-11-01 22:00:00 -0500
|
52
|
+
3. 2021-11-01 22:10:00 -0500
|
53
|
+
~ ❯ schedule -l
|
54
|
+
Jobs
|
55
|
+
1. backup.sh Every 10 minutes
|
56
|
+
~ ❯ crontab -l
|
57
|
+
*/10 * * * * backup.sh
|
58
|
+
~ ❯ schedule -e 3M quarterly_backup.sh
|
59
|
+
Scheduling: quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
|
60
|
+
Next three runs:
|
61
|
+
1. 2022-01-01 21:50:00 -0600
|
62
|
+
2. 2022-04-01 21:50:00 -0500
|
63
|
+
3. 2022-07-01 21:50:00 -0500
|
64
|
+
~ ❯ schedule -l
|
65
|
+
Jobs
|
66
|
+
1. backup.sh Every 10 minutes
|
67
|
+
2. quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
|
68
|
+
~ ❯ crontab -l
|
69
|
+
*/10 * * * * backup.sh
|
70
|
+
50 21 1 */3 * quarterly_backup.sh
|
71
|
+
~ ❯ schedule --dryrun --rm 1
|
72
|
+
Would remove: backup.sh Every 10 minutes
|
73
|
+
~ ❯ schedule --dryrun --rm 2
|
74
|
+
Would remove: quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
|
75
|
+
~ ❯ schedule --rm 1
|
76
|
+
Removing: backup.sh Every 10 minutes
|
77
|
+
~ ❯ schedule -l
|
78
|
+
Jobs
|
79
|
+
1. quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
|
80
|
+
~ ❯ schedule --rm 1
|
81
|
+
Removing: quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
|
82
|
+
~ ❯ schedule -l
|
83
|
+
~ ❯ crontab -l
|
84
|
+
~ ❯
|
15
85
|
```
|
16
86
|
|
17
87
|
## License
|
data/lib/schedule_job/cli.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require "optparse"
|
2
2
|
|
3
|
-
# schedule --every 10m "my_command --foo --bar"
|
4
|
-
|
5
3
|
module ScheduleJob
|
6
4
|
class Cli
|
7
5
|
def self.run(argv = ARGV)
|
@@ -32,20 +30,28 @@ module ScheduleJob
|
|
32
30
|
options[:crontab_user] = user
|
33
31
|
end
|
34
32
|
|
35
|
-
opts.on("-e", "--every DURATION", "Run command every DURATION units of time.
|
33
|
+
opts.on("-e", "--every DURATION", "Run command every DURATION units of time (valid suffixes are m, h, d, M). DURATION may also be one of the special keywords: reboot, year, month, week, day, hour
|
36
34
|
For example:
|
37
|
-
--every 10m #
|
38
|
-
--every 5h #
|
39
|
-
--every 2d #
|
40
|
-
--every 3M #
|
35
|
+
--every 10m # every 10 minutes
|
36
|
+
--every 5h # every 5 hours
|
37
|
+
--every 2d # every 2 days
|
38
|
+
--every 3M # every 3 months
|
39
|
+
|
40
|
+
Special durations:
|
41
|
+
--every reboot # after every reboot
|
42
|
+
--every year # every year
|
43
|
+
--every month # every month
|
44
|
+
--every week # every week
|
45
|
+
--every day # every day
|
46
|
+
--every hour # every hour
|
41
47
|
") do |every|
|
42
48
|
options[:every] = every
|
43
49
|
end
|
44
50
|
|
45
51
|
opts.on("-c", "--cron CRON", "Run command on the given cron schedule.
|
46
52
|
For example:
|
47
|
-
--cron \"*/5 15 * * 1-5\" #
|
48
|
-
--cron \"0 0/30 8-9 5,20 * ?\" #
|
53
|
+
--cron \"*/5 15 * * 1-5\" # Every 5 minutes, at 3:00 PM, Monday through Friday
|
54
|
+
--cron \"0 0/30 8-9 5,20 * ?\" # Every 30 minutes, between 8:00 AM and 9:59 AM, on day 5 and 20 of the month
|
49
55
|
") do |cron_schedule|
|
50
56
|
options[:cron] = cron_schedule
|
51
57
|
end
|
@@ -63,6 +69,8 @@ module ScheduleJob
|
|
63
69
|
remove_job(args)
|
64
70
|
when args[:cron] || args[:every] # write jobs
|
65
71
|
install_job(args)
|
72
|
+
else
|
73
|
+
puts "No parameters specified. Please specify one of: --every, --cron, --list, or --rm"
|
66
74
|
end
|
67
75
|
end
|
68
76
|
|
@@ -90,13 +98,14 @@ module ScheduleJob
|
|
90
98
|
Cron::Job.new(cron_schedule, command)
|
91
99
|
when args[:every]
|
92
100
|
duration = args[:every]
|
93
|
-
match = duration.match(/(\d+)(m|h|d|M)/)
|
94
|
-
if match
|
101
|
+
if match = duration.match(/(\d+)(m|h|d|M)/)
|
95
102
|
qty = match[1].to_i
|
96
103
|
unit_of_time = match[2].to_s
|
97
104
|
Cron::Job.every(qty, unit_of_time, command)
|
105
|
+
elsif duration.match(/reboot|year|month|week|day|hour/)
|
106
|
+
Cron::Job.every_simple_duration(duration, command)
|
98
107
|
else
|
99
|
-
puts "'#{duration}' is an invalid duration. The duration must be specified as
|
108
|
+
puts "'#{duration}' is an invalid duration. The duration must be specified as either (1) integer followed immediately by m (minutes), h (hours), d (days), M (months) (e.g. 10m) or (2) reboot, year, month, week, day, hour"
|
100
109
|
exit(1)
|
101
110
|
end
|
102
111
|
end
|
data/lib/schedule_job/cron.rb
CHANGED
@@ -50,12 +50,6 @@ module ScheduleJob
|
|
50
50
|
|
51
51
|
raise("Unable to read crontab: #{error_output}") if !exit_status.success? && !no_crontab
|
52
52
|
|
53
|
-
# puts "read_crontab()"
|
54
|
-
# puts "stdout:"
|
55
|
-
# puts stdout
|
56
|
-
# puts "stderr:"
|
57
|
-
# puts stderr
|
58
|
-
|
59
53
|
crontab_output
|
60
54
|
end
|
61
55
|
|
@@ -63,16 +57,8 @@ module ScheduleJob
|
|
63
57
|
def parse_crontab(user_crontab)
|
64
58
|
parser = TableParser.new(user_crontab)
|
65
59
|
|
66
|
-
# user_crontab.each_line do |line|
|
67
|
-
# puts line
|
68
|
-
# puts "valid? #{LineParser.valid?(line)}"
|
69
|
-
# puts LineParser.parse(line)
|
70
|
-
# end
|
71
|
-
|
72
60
|
return [], [] unless parser.valid?
|
73
61
|
|
74
|
-
# puts "valid!"
|
75
|
-
|
76
62
|
environment_vars = parser.environment_vars&.map do |env_directive|
|
77
63
|
name = env_directive[:var].to_s
|
78
64
|
expr = env_directive[:expr].to_s
|
@@ -96,21 +82,25 @@ module ScheduleJob
|
|
96
82
|
puts "Scheduling: #{job.to_s}"
|
97
83
|
install_cron_job(job)
|
98
84
|
end
|
99
|
-
|
100
|
-
cron_parser = CronParser.new(job.schedule_spec)
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
85
|
+
|
86
|
+
cron_parser = CronParser.new(job.schedule_spec) rescue nil
|
87
|
+
if cron_parser
|
88
|
+
puts "Next three runs:"
|
89
|
+
first_run_time = cron_parser.next(Time.now)
|
90
|
+
second_run_time = cron_parser.next(first_run_time)
|
91
|
+
third_run_time = cron_parser.next(second_run_time)
|
92
|
+
|
93
|
+
puts "1. #{first_run_time}"
|
94
|
+
puts "2. #{second_run_time}"
|
95
|
+
puts "3. #{third_run_time}"
|
96
|
+
end
|
107
97
|
end
|
108
98
|
|
109
99
|
def install_cron_job(job)
|
110
100
|
job_spec = job.specification
|
111
|
-
# puts "Installing new cron job: #{job_spec}"
|
112
101
|
|
113
102
|
new_crontab = [read_crontab(@user).strip, job_spec.strip].reject(&:empty?).join("\n")
|
103
|
+
new_crontab << "\n" # add a trailing newline
|
114
104
|
write_crontab(new_crontab)
|
115
105
|
end
|
116
106
|
|
@@ -135,21 +125,12 @@ module ScheduleJob
|
|
135
125
|
end
|
136
126
|
|
137
127
|
def write_crontab(new_crontab, user = @user)
|
128
|
+
# overwrite crontab interactively, per https://stackoverflow.com/questions/610839/how-can-i-programmatically-create-a-new-cron-job
|
138
129
|
command = ["crontab"]
|
139
130
|
command << "-u #{user}" if user
|
140
131
|
command << "-"
|
141
132
|
command = command.join(" ")
|
142
133
|
|
143
|
-
# command = "(crontab -l ; echo \"#{job_spec}\") | crontab -" # add new job to bottom of crontab, per https://stackoverflow.com/questions/610839/how-can-i-programmatically-create-a-new-cron-job
|
144
|
-
# puts "writing new crontab:"
|
145
|
-
# puts new_crontab
|
146
|
-
# puts "*" * 80
|
147
|
-
|
148
|
-
# puts "write_crontab:"
|
149
|
-
# puts "command: #{command}"
|
150
|
-
# puts "new crontab:"
|
151
|
-
# puts new_crontab
|
152
|
-
|
153
134
|
stdout, stderr, exit_status = Open3.capture3(command, stdin_data: new_crontab)
|
154
135
|
crontab_output = stdout
|
155
136
|
error_output = stderr
|
@@ -184,14 +165,33 @@ module ScheduleJob
|
|
184
165
|
hour = next_moment.hour
|
185
166
|
day = next_moment.day
|
186
167
|
schedule_spec = case duration_unit_of_time
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
168
|
+
when "m"
|
169
|
+
"*/#{duration_quantity} * * * *"
|
170
|
+
when "h"
|
171
|
+
"#{minute} */#{duration_quantity} * * *"
|
172
|
+
when "d"
|
173
|
+
"#{minute} #{hour} */#{duration_quantity} * *"
|
174
|
+
when "M"
|
175
|
+
"#{minute} #{hour} #{day} */#{duration_quantity} *"
|
176
|
+
end
|
177
|
+
self.new(schedule_spec, command)
|
178
|
+
end
|
179
|
+
|
180
|
+
# duration is one of: reboot, year, month, week, day, hour
|
181
|
+
def self.every_simple_duration(duration, command)
|
182
|
+
schedule_spec = case duration
|
183
|
+
when "reboot"
|
184
|
+
"@reboot"
|
185
|
+
when "year"
|
186
|
+
"@yearly"
|
187
|
+
when "month"
|
188
|
+
"@monthly"
|
189
|
+
when "week"
|
190
|
+
"@weekly"
|
191
|
+
when "day"
|
192
|
+
"@daily"
|
193
|
+
when "hour"
|
194
|
+
"@hourly"
|
195
195
|
end
|
196
196
|
self.new(schedule_spec, command)
|
197
197
|
end
|
@@ -222,7 +222,23 @@ module ScheduleJob
|
|
222
222
|
end
|
223
223
|
|
224
224
|
def to_s
|
225
|
-
schedule =
|
225
|
+
schedule = case @schedule_spec
|
226
|
+
when "@reboot"
|
227
|
+
"at every reboot"
|
228
|
+
when "@yearly", "@annually"
|
229
|
+
"every year"
|
230
|
+
when "@monthly"
|
231
|
+
"every month"
|
232
|
+
when "@weekly"
|
233
|
+
"every week"
|
234
|
+
when "@daily"
|
235
|
+
"every day"
|
236
|
+
when "@hourly"
|
237
|
+
"every hour"
|
238
|
+
else
|
239
|
+
Cronex::ExpressionDescriptor.new(@schedule_spec).description
|
240
|
+
end
|
241
|
+
|
226
242
|
# str = "#{@command} #{schedule} (line #{@line_number}, pos #{@pos_offset})"
|
227
243
|
str = "#{@command} #{schedule}"
|
228
244
|
end
|
@@ -17,10 +17,6 @@ end
|
|
17
17
|
|
18
18
|
Citrus.require("schedule_job/cron")
|
19
19
|
|
20
|
-
# require "polyglot"
|
21
|
-
# require "treetop"
|
22
|
-
# require "schedule_job/cron.treetop"
|
23
|
-
|
24
20
|
module ScheduleJob
|
25
21
|
module Cron
|
26
22
|
Grammar = ScheduleCronParser
|
@@ -34,7 +30,6 @@ module ScheduleJob
|
|
34
30
|
|
35
31
|
def self.parse(user_crontab_string)
|
36
32
|
Grammar.parse(user_crontab_string, root: :user_crontab)
|
37
|
-
# ::CrontabParser.new.parse(user_crontab_string, root: :user_crontab)
|
38
33
|
end
|
39
34
|
|
40
35
|
def initialize(user_crontab_string)
|
@@ -55,17 +50,10 @@ module ScheduleJob
|
|
55
50
|
|
56
51
|
def environment_vars
|
57
52
|
@user_crontab&.capture(:environment)&.captures(:directive)
|
58
|
-
# puts @user_crontab.methods.sort.inspect
|
59
|
-
# puts @user_crontab.inspect
|
60
|
-
# puts "*" * 80
|
61
|
-
# puts @user_crontab.environment_spec.inspect
|
62
|
-
# exit()
|
63
|
-
# @user_crontab&.environment&.directive
|
64
53
|
end
|
65
54
|
|
66
55
|
def job_specs
|
67
56
|
@user_crontab&.capture(:jobspecs)&.captures(:jobspec)
|
68
|
-
# @user_crontab&.jobspecs&.jobspec
|
69
57
|
end
|
70
58
|
end
|
71
59
|
|
@@ -78,7 +66,6 @@ module ScheduleJob
|
|
78
66
|
|
79
67
|
def self.parse(cron_line)
|
80
68
|
Grammar.parse(cron_line, root: :jobspec, consume: false)
|
81
|
-
# ::CrontabParser.new.parse(cron_line, root: :jobspec, consume_all_input: false)
|
82
69
|
end
|
83
70
|
end
|
84
71
|
end
|
data/lib/schedule_job/version.rb
CHANGED
data/schedule_job.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.description = "job scheduler"
|
11
11
|
spec.homepage = "https://github.com/davidkellis/scheduler"
|
12
12
|
spec.license = "MIT"
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
14
14
|
|
15
15
|
spec.files = Dir["**/**"].
|
16
16
|
grep_v(/.gem$/).
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schedule_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Ellis
|
@@ -69,7 +69,6 @@ files:
|
|
69
69
|
- lib/schedule_job/cli.rb
|
70
70
|
- lib/schedule_job/cron.citrus
|
71
71
|
- lib/schedule_job/cron.rb
|
72
|
-
- lib/schedule_job/cron.treetop
|
73
72
|
- lib/schedule_job/cron_parser.rb
|
74
73
|
- lib/schedule_job/version.rb
|
75
74
|
- schedule_job.gemspec
|
@@ -85,7 +84,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
84
|
requirements:
|
86
85
|
- - ">="
|
87
86
|
- !ruby/object:Gem::Version
|
88
|
-
version: 2.
|
87
|
+
version: 2.5.0
|
89
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
89
|
requirements:
|
91
90
|
- - ">="
|
@@ -1,167 +0,0 @@
|
|
1
|
-
grammar Crontab
|
2
|
-
rule user_crontab
|
3
|
-
sep?
|
4
|
-
environment_spec:(environment sep)?
|
5
|
-
jobspecs?
|
6
|
-
sep?
|
7
|
-
end
|
8
|
-
|
9
|
-
rule environment
|
10
|
-
head:directive tail:(sep directive)*
|
11
|
-
end
|
12
|
-
|
13
|
-
rule directive
|
14
|
-
var space "=" space expr
|
15
|
-
end
|
16
|
-
|
17
|
-
rule var
|
18
|
-
alpha alphanumeric?
|
19
|
-
end
|
20
|
-
|
21
|
-
rule expr
|
22
|
-
command
|
23
|
-
end
|
24
|
-
|
25
|
-
rule jobspecs
|
26
|
-
head:jobspec tail:(sep jobspec)*
|
27
|
-
end
|
28
|
-
|
29
|
-
rule jobspec
|
30
|
-
schedule_spec space command ws*
|
31
|
-
end
|
32
|
-
|
33
|
-
rule schedule_spec
|
34
|
-
standard / special
|
35
|
-
end
|
36
|
-
|
37
|
-
rule standard
|
38
|
-
minute space hour space dayofmonth space month space dayofweek
|
39
|
-
end
|
40
|
-
|
41
|
-
rule special
|
42
|
-
"@" ("yearly" / "annually" / "monthly" / "weekly" / "daily" / "hourly" / "reboot")
|
43
|
-
end
|
44
|
-
|
45
|
-
rule minute
|
46
|
-
step
|
47
|
-
end
|
48
|
-
|
49
|
-
rule hour
|
50
|
-
step
|
51
|
-
end
|
52
|
-
|
53
|
-
rule dayofmonthtypes
|
54
|
-
step
|
55
|
-
end
|
56
|
-
|
57
|
-
rule monthtypes
|
58
|
-
step / altmonths
|
59
|
-
end
|
60
|
-
|
61
|
-
rule dayofweektypes
|
62
|
-
step / altdays
|
63
|
-
end
|
64
|
-
|
65
|
-
rule dayofmonth
|
66
|
-
dayofmonthtypes ("," dayofmonthtypes)*
|
67
|
-
end
|
68
|
-
|
69
|
-
rule month
|
70
|
-
monthtypes ("," monthtypes)*
|
71
|
-
end
|
72
|
-
|
73
|
-
rule dayofweek
|
74
|
-
dayofweektypes ("," dayofweektypes)*
|
75
|
-
end
|
76
|
-
|
77
|
-
rule command
|
78
|
-
quoted_string
|
79
|
-
/ (!("\n" / comment) .)+
|
80
|
-
end
|
81
|
-
|
82
|
-
rule step
|
83
|
-
common ("/" int)?
|
84
|
-
end
|
85
|
-
|
86
|
-
rule common
|
87
|
-
range / int / any
|
88
|
-
end
|
89
|
-
|
90
|
-
rule range
|
91
|
-
int "-" int
|
92
|
-
end
|
93
|
-
|
94
|
-
rule altdays
|
95
|
-
days ("," days)*
|
96
|
-
end
|
97
|
-
|
98
|
-
rule altmonths
|
99
|
-
months ("," months)*
|
100
|
-
end
|
101
|
-
|
102
|
-
rule days
|
103
|
-
"MON" / "TUE" / "WED" / "THU" / "FRI" / "SAT" / "SUN"
|
104
|
-
end
|
105
|
-
|
106
|
-
rule months
|
107
|
-
"JAN" / "FEB" / "MAR" / "APR" / "MAY" / "JUN" / "JUL" / "AUG" / "SEP" / "OCT" / "NOV" / "DEC"
|
108
|
-
end
|
109
|
-
|
110
|
-
rule any
|
111
|
-
"*"
|
112
|
-
end
|
113
|
-
|
114
|
-
rule int
|
115
|
-
[0-9]+
|
116
|
-
end
|
117
|
-
|
118
|
-
rule alpha
|
119
|
-
[a-zA-Z]+
|
120
|
-
end
|
121
|
-
|
122
|
-
rule alphanumeric
|
123
|
-
[a-zA-Z0-9]+
|
124
|
-
end
|
125
|
-
|
126
|
-
rule sep
|
127
|
-
(ws* nl)+
|
128
|
-
end
|
129
|
-
|
130
|
-
rule ws
|
131
|
-
space / comment
|
132
|
-
end
|
133
|
-
|
134
|
-
rule space
|
135
|
-
[ \t]+
|
136
|
-
end
|
137
|
-
|
138
|
-
rule nl
|
139
|
-
[\n]+
|
140
|
-
end
|
141
|
-
|
142
|
-
rule comment
|
143
|
-
"#" (!"\n" .)*
|
144
|
-
end
|
145
|
-
|
146
|
-
rule quoted_string
|
147
|
-
"\"" ( (!("\"" / "\\") .) / escape)* "\""
|
148
|
-
/ "'" ( (!("'" / "\\") .) / escape)* "'"
|
149
|
-
end
|
150
|
-
|
151
|
-
rule escape
|
152
|
-
"\\" escape_sequence
|
153
|
-
end
|
154
|
-
|
155
|
-
rule escape_sequence
|
156
|
-
"'"
|
157
|
-
/ "\""
|
158
|
-
/ "\\"
|
159
|
-
/ "b"
|
160
|
-
/ "f"
|
161
|
-
/ "n"
|
162
|
-
/ "r"
|
163
|
-
/ "t"
|
164
|
-
/ "v"
|
165
|
-
end
|
166
|
-
|
167
|
-
end
|