schedule_job 1.0.0 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -4
- data/Gemfile.lock +1 -1
- data/README.md +76 -2
- data/bin/schedule +2 -2
- data/lib/{schedule → schedule_job}/cli.rb +22 -13
- data/lib/{schedule → schedule_job}/cron.citrus +0 -0
- data/lib/{schedule → schedule_job}/cron.rb +22 -26
- data/lib/{schedule → schedule_job}/cron_parser.rb +2 -15
- data/lib/schedule_job/version.rb +3 -0
- data/lib/schedule_job.rb +2 -6
- data/schedule_job.gemspec +4 -2
- metadata +7 -8
- data/Rakefile +0 -8
- data/lib/schedule/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: 887f7a67ad740ea939e3c585534e820ad03d85695d07a74b26390c4300a8cb04
|
4
|
+
data.tar.gz: d61192e8ac1ba8b74f62de780b4b000d4b235aeb13f202d24e374f381f7c65ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86af048f9a4e1c2e50f9c7a63ffbe483fd5c8ffbda9ec521b5c7d2c39a8a6228367e239f0ab347d3c681a2fbbf03918691e3cbf95d67cbf5c256b8439e2dbfe3
|
7
|
+
data.tar.gz: 7866e34e5591ed82159cc81a268166562f07e50033998cee9ff0000baeafd92772df00a7ed3953a6e50f8d627f64fb636898bd432fe460f7099a958f7c078ae5
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,15 +1,89 @@
|
|
1
|
-
#
|
1
|
+
# ScheduleJob
|
2
2
|
|
3
3
|
schedule is a frontend around crontab to add/remove cron jobs from user cron tables.
|
4
4
|
|
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:
|
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
|
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
|
+
~ ❯
|
85
|
+
```
|
86
|
+
|
13
87
|
## License
|
14
88
|
|
15
89
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/bin/schedule
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require "optparse"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
module Schedule
|
3
|
+
module ScheduleJob
|
6
4
|
class Cli
|
7
5
|
def self.run(argv = ARGV)
|
8
6
|
cli = Cli.new
|
@@ -32,20 +30,28 @@ module Schedule
|
|
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 Schedule
|
|
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 Schedule
|
|
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
|
File without changes
|
@@ -8,7 +8,7 @@ require "stringio"
|
|
8
8
|
|
9
9
|
require_relative "./cron_parser"
|
10
10
|
|
11
|
-
module
|
11
|
+
module ScheduleJob
|
12
12
|
module Cron
|
13
13
|
|
14
14
|
class EnvironmentVar
|
@@ -50,12 +50,6 @@ module Schedule
|
|
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 Schedule
|
|
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
|
@@ -108,9 +94,9 @@ module Schedule
|
|
108
94
|
|
109
95
|
def install_cron_job(job)
|
110
96
|
job_spec = job.specification
|
111
|
-
# puts "Installing new cron job: #{job_spec}"
|
112
97
|
|
113
98
|
new_crontab = [read_crontab(@user).strip, job_spec.strip].reject(&:empty?).join("\n")
|
99
|
+
new_crontab << "\n" # add a trailing newline
|
114
100
|
write_crontab(new_crontab)
|
115
101
|
end
|
116
102
|
|
@@ -135,21 +121,12 @@ module Schedule
|
|
135
121
|
end
|
136
122
|
|
137
123
|
def write_crontab(new_crontab, user = @user)
|
124
|
+
# overwrite crontab interactively, per https://stackoverflow.com/questions/610839/how-can-i-programmatically-create-a-new-cron-job
|
138
125
|
command = ["crontab"]
|
139
126
|
command << "-u #{user}" if user
|
140
127
|
command << "-"
|
141
128
|
command = command.join(" ")
|
142
129
|
|
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
130
|
stdout, stderr, exit_status = Open3.capture3(command, stdin_data: new_crontab)
|
154
131
|
crontab_output = stdout
|
155
132
|
error_output = stderr
|
@@ -196,6 +173,25 @@ module Schedule
|
|
196
173
|
self.new(schedule_spec, command)
|
197
174
|
end
|
198
175
|
|
176
|
+
# duration is one of: reboot, year, month, week, day, hour
|
177
|
+
def self.every_simple_duration(duration, command)
|
178
|
+
schedule_spec = case duration
|
179
|
+
when "reboot"
|
180
|
+
"@reboot"
|
181
|
+
when "year"
|
182
|
+
"@yearly"
|
183
|
+
when "month"
|
184
|
+
"@monthly"
|
185
|
+
when "week"
|
186
|
+
"@weekly"
|
187
|
+
when "day"
|
188
|
+
"@daily"
|
189
|
+
when "hour"
|
190
|
+
"@hourly"
|
191
|
+
end
|
192
|
+
self.new(schedule_spec, command)
|
193
|
+
end
|
194
|
+
|
199
195
|
attr_reader :schedule_spec
|
200
196
|
attr_reader :line_number
|
201
197
|
|
@@ -15,13 +15,9 @@ module Citrus
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
Citrus.require("
|
18
|
+
Citrus.require("schedule_job/cron")
|
19
19
|
|
20
|
-
|
21
|
-
# require "treetop"
|
22
|
-
# require "schedule/cron.treetop"
|
23
|
-
|
24
|
-
module Schedule
|
20
|
+
module ScheduleJob
|
25
21
|
module Cron
|
26
22
|
Grammar = ScheduleCronParser
|
27
23
|
|
@@ -34,7 +30,6 @@ module Schedule
|
|
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 Schedule
|
|
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 Schedule
|
|
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.rb
CHANGED
data/schedule_job.gemspec
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require_relative "lib/schedule_job/version"
|
2
|
+
|
1
3
|
Gem::Specification.new do |spec|
|
2
4
|
spec.name = "schedule_job"
|
3
|
-
spec.version =
|
5
|
+
spec.version = ScheduleJob::VERSION
|
4
6
|
spec.authors = ["David Ellis"]
|
5
7
|
spec.email = ["david@conquerthelawn.com"]
|
6
8
|
|
@@ -8,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
8
10
|
spec.description = "job scheduler"
|
9
11
|
spec.homepage = "https://github.com/davidkellis/scheduler"
|
10
12
|
spec.license = "MIT"
|
11
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
12
14
|
|
13
15
|
spec.files = Dir["**/**"].
|
14
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.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Ellis
|
@@ -64,14 +64,13 @@ files:
|
|
64
64
|
- Gemfile.lock
|
65
65
|
- LICENSE.txt
|
66
66
|
- README.md
|
67
|
-
- Rakefile
|
68
67
|
- bin/schedule
|
69
|
-
- lib/schedule/cli.rb
|
70
|
-
- lib/schedule/cron.citrus
|
71
|
-
- lib/schedule/cron.rb
|
72
|
-
- lib/schedule/cron.treetop
|
73
|
-
- lib/schedule/cron_parser.rb
|
74
68
|
- lib/schedule_job.rb
|
69
|
+
- lib/schedule_job/cli.rb
|
70
|
+
- lib/schedule_job/cron.citrus
|
71
|
+
- lib/schedule_job/cron.rb
|
72
|
+
- lib/schedule_job/cron_parser.rb
|
73
|
+
- lib/schedule_job/version.rb
|
75
74
|
- schedule_job.gemspec
|
76
75
|
homepage: https://github.com/davidkellis/scheduler
|
77
76
|
licenses:
|
@@ -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
|
- - ">="
|
data/Rakefile
DELETED
data/lib/schedule/cron.treetop
DELETED
@@ -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
|