citrus 2.4.1 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +13 -0
- data/Rakefile +1 -1
- data/lib/citrus.rb +87 -35
- data/lib/citrus/file.rb +2 -1
- data/lib/citrus/version.rb +1 -1
- data/test/_files/rule6.citrus +1 -0
- data/test/_files/rule7.citrus +3 -0
- data/test/alias_test.rb +0 -2
- data/test/grammar_test.rb +25 -2
- data/test/input_test.rb +15 -0
- data/test/match_test.rb +25 -1
- data/test/super_test.rb +0 -4
- metadata +37 -51
data/CHANGES
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
= 2.5.0 / 2014-03-13
|
2
|
+
|
3
|
+
* Inputs may be generated from many different sources, including Pathname and
|
4
|
+
IO objects (thanks blambeau).
|
5
|
+
|
6
|
+
* Matches keep track of their offset in the original source (thanks
|
7
|
+
blambeau).
|
8
|
+
|
9
|
+
* Citrus.load no longer raises Citrus::LoadError for files that can't be found
|
10
|
+
or are not readable. Users must rescue Errno::ENOENT instead, for example.
|
11
|
+
|
12
|
+
* Removed a few ruby warnings (thanks tbuehlmann)
|
13
|
+
|
1
14
|
= 2.4.1 / 2011-11-04
|
2
15
|
|
3
16
|
* Fixed a bug that prevented rule names from starting with "super".
|
data/Rakefile
CHANGED
@@ -15,7 +15,7 @@ desc "Generate API documentation"
|
|
15
15
|
task :api => 'lib/citrus.rb' do |t|
|
16
16
|
output_dir = ENV['OUTPUT_DIR'] || 'api'
|
17
17
|
rm_rf output_dir
|
18
|
-
sh((<<-SH).gsub(
|
18
|
+
sh((<<-SH).gsub(/\s+/, ' ').strip)
|
19
19
|
hanna
|
20
20
|
--op #{output_dir}
|
21
21
|
--promiscuous
|
data/lib/citrus.rb
CHANGED
@@ -73,9 +73,6 @@ module Citrus
|
|
73
73
|
force = options.delete(:force)
|
74
74
|
|
75
75
|
if force || !cache[file]
|
76
|
-
raise LoadError, "Cannot find file #{file}" unless ::File.file?(file)
|
77
|
-
raise LoadError, "Cannot read file #{file}" unless ::File.readable?(file)
|
78
|
-
|
79
76
|
begin
|
80
77
|
cache[file] = eval(::File.read(file), options)
|
81
78
|
rescue SyntaxError => e
|
@@ -117,7 +114,10 @@ module Citrus
|
|
117
114
|
end
|
118
115
|
|
119
116
|
# A base class for all Citrus errors.
|
120
|
-
class Error <
|
117
|
+
class Error < StandardError; end
|
118
|
+
|
119
|
+
# Raised when Citrus.require can't find the file to load.
|
120
|
+
class LoadError < Error; end
|
121
121
|
|
122
122
|
# Raised when a parse fails.
|
123
123
|
class ParseError < Error
|
@@ -156,9 +156,6 @@ module Citrus
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
-
# Raised when Citrus.load fails to load a file.
|
160
|
-
class LoadError < Error; end
|
161
|
-
|
162
159
|
# Raised when Citrus::File.parse fails.
|
163
160
|
class SyntaxError < Error
|
164
161
|
# The +error+ given here is an instance of Citrus::ParseError.
|
@@ -173,14 +170,19 @@ module Citrus
|
|
173
170
|
# An Input is a scanner that is responsible for executing rules at different
|
174
171
|
# positions in the input string and persisting event streams.
|
175
172
|
class Input < StringScanner
|
176
|
-
def initialize(
|
177
|
-
super(
|
173
|
+
def initialize(source)
|
174
|
+
super(source_text(source))
|
175
|
+
@source = source
|
178
176
|
@max_offset = 0
|
179
177
|
end
|
180
178
|
|
181
179
|
# The maximum offset in the input that was successfully parsed.
|
182
180
|
attr_reader :max_offset
|
183
181
|
|
182
|
+
# The initial source passed at construction. Typically a String
|
183
|
+
# or a Pathname.
|
184
|
+
attr_reader :source
|
185
|
+
|
184
186
|
def reset # :nodoc:
|
185
187
|
@max_offset = 0
|
186
188
|
super
|
@@ -263,8 +265,24 @@ module Citrus
|
|
263
265
|
events[-1]
|
264
266
|
end
|
265
267
|
|
268
|
+
# Returns the scanned string.
|
269
|
+
alias_method :to_str, :string
|
270
|
+
|
266
271
|
private
|
267
272
|
|
273
|
+
# Returns the text to parse from +source+.
|
274
|
+
def source_text(source)
|
275
|
+
if source.respond_to?(:to_path)
|
276
|
+
::File.read(source.to_path)
|
277
|
+
elsif source.respond_to?(:read)
|
278
|
+
source.read
|
279
|
+
elsif source.respond_to?(:to_str)
|
280
|
+
source.to_str
|
281
|
+
else
|
282
|
+
raise ArgumentError, "Unable to parse from #{source}", caller
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
268
286
|
# Appends all events for +rule+ at the given +position+ to +events+.
|
269
287
|
def apply_rule(rule, position, events)
|
270
288
|
rule.exec(self, events)
|
@@ -361,17 +379,24 @@ module Citrus
|
|
361
379
|
super
|
362
380
|
end
|
363
381
|
|
364
|
-
# Parses the given +
|
382
|
+
# Parses the given +source+ using this grammar's root rule. Accepts the same
|
365
383
|
# +options+ as Rule#parse, plus the following:
|
366
384
|
#
|
367
385
|
# root:: The name of the root rule to start parsing at. Defaults to this
|
368
386
|
# grammar's #root.
|
369
|
-
def parse(
|
387
|
+
def parse(source, options={})
|
370
388
|
rule_name = options.delete(:root) || root
|
371
389
|
raise Error, "No root rule specified" unless rule_name
|
372
390
|
rule = rule(rule_name)
|
373
391
|
raise Error, "No rule named \"#{rule_name}\"" unless rule
|
374
|
-
rule.parse(
|
392
|
+
rule.parse(source, options)
|
393
|
+
end
|
394
|
+
|
395
|
+
# Parses the contents of the file at the given +path+ using this grammar's
|
396
|
+
# #root rule. Accepts the same +options+ as #parse.
|
397
|
+
def parse_file(path, options={})
|
398
|
+
path = Pathname.new(path.to_str) unless Pathname === path
|
399
|
+
parse(path, options)
|
375
400
|
end
|
376
401
|
|
377
402
|
# Returns the name of this grammar as a string.
|
@@ -455,9 +480,16 @@ module Citrus
|
|
455
480
|
# Gets/sets the +name+ of the root rule of this grammar. If no root rule is
|
456
481
|
# explicitly specified, the name of this grammar's first rule is returned.
|
457
482
|
def root(name=nil)
|
458
|
-
|
459
|
-
|
460
|
-
|
483
|
+
if name
|
484
|
+
@root = name.to_sym
|
485
|
+
else
|
486
|
+
# The first rule in a grammar is the default root.
|
487
|
+
if instance_variable_defined?(:@root)
|
488
|
+
@root
|
489
|
+
else
|
490
|
+
rule_names.first
|
491
|
+
end
|
492
|
+
end
|
461
493
|
end
|
462
494
|
|
463
495
|
# Creates a new rule that will match any single character. A block may be
|
@@ -623,10 +655,11 @@ module Citrus
|
|
623
655
|
# +false+.
|
624
656
|
# offset:: The offset in +string+ at which to start parsing. Defaults
|
625
657
|
# to 0.
|
626
|
-
def parse(
|
658
|
+
def parse(source, options={})
|
627
659
|
opts = default_options.merge(options)
|
628
660
|
|
629
|
-
input = (opts[:memoize] ? MemoizedInput : Input).new(
|
661
|
+
input = (opts[:memoize] ? MemoizedInput : Input).new(source)
|
662
|
+
string = input.string
|
630
663
|
input.pos = opts[:offset] if opts[:offset] > 0
|
631
664
|
|
632
665
|
events = input.exec(self)
|
@@ -636,7 +669,7 @@ module Citrus
|
|
636
669
|
raise ParseError, input
|
637
670
|
end
|
638
671
|
|
639
|
-
Match.new(
|
672
|
+
Match.new(input, events, opts[:offset])
|
640
673
|
end
|
641
674
|
|
642
675
|
# Tests whether or not this rule matches on the given +string+. Returns the
|
@@ -1239,14 +1272,13 @@ module Citrus
|
|
1239
1272
|
# instantiated as needed. This class provides several convenient tree
|
1240
1273
|
# traversal methods that help when examining and interpreting parse results.
|
1241
1274
|
class Match
|
1242
|
-
def initialize(
|
1243
|
-
@
|
1275
|
+
def initialize(input, events=[], offset=0)
|
1276
|
+
@input = input
|
1277
|
+
@offset = offset
|
1278
|
+
@captures = nil
|
1279
|
+
@matches = nil
|
1244
1280
|
|
1245
1281
|
if events.length > 0
|
1246
|
-
if events[-1] != string.length
|
1247
|
-
raise ArgumentError, "Invalid events for length #{string.length}"
|
1248
|
-
end
|
1249
|
-
|
1250
1282
|
elisions = []
|
1251
1283
|
|
1252
1284
|
while events[0].elide?
|
@@ -1261,18 +1293,35 @@ module Citrus
|
|
1261
1293
|
end
|
1262
1294
|
else
|
1263
1295
|
# Create a default stream of events for the given string.
|
1296
|
+
string = input.to_str
|
1264
1297
|
events = [Rule.for(string), CLOSE, string.length]
|
1265
1298
|
end
|
1266
1299
|
|
1267
1300
|
@events = events
|
1268
1301
|
end
|
1269
1302
|
|
1303
|
+
# The original Input this Match was generated on.
|
1304
|
+
attr_reader :input
|
1305
|
+
|
1306
|
+
# The index of this match in the #input.
|
1307
|
+
attr_reader :offset
|
1308
|
+
|
1270
1309
|
# The array of events for this match.
|
1271
1310
|
attr_reader :events
|
1272
1311
|
|
1273
1312
|
# Returns the length of this match.
|
1274
1313
|
def length
|
1275
|
-
|
1314
|
+
events.last
|
1315
|
+
end
|
1316
|
+
|
1317
|
+
# Convenient shortcut for +input.source+
|
1318
|
+
def source
|
1319
|
+
(input.respond_to?(:source) && input.source) || input
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
# Returns the slice of the source text that this match captures.
|
1323
|
+
def string
|
1324
|
+
@string ||= input.to_str[offset, length]
|
1276
1325
|
end
|
1277
1326
|
|
1278
1327
|
# Returns a hash of capture names to arrays of matches with that name,
|
@@ -1296,16 +1345,18 @@ module Citrus
|
|
1296
1345
|
# Allows methods of this match's string to be called directly and provides
|
1297
1346
|
# a convenient interface for retrieving the first match with a given name.
|
1298
1347
|
def method_missing(sym, *args, &block)
|
1299
|
-
|
1300
|
-
|
1348
|
+
unless defined?(Citrus::METHOD_MISSING_WARNED)
|
1349
|
+
warn("[`#{sym}`] Citrus::Match#method_missing is unsafe and will be removed in 3.0. Use captures.")
|
1350
|
+
Citrus.send(:const_set, :METHOD_MISSING_WARNED, true)
|
1351
|
+
end
|
1352
|
+
if string.respond_to?(sym)
|
1353
|
+
string.__send__(sym, *args, &block)
|
1301
1354
|
else
|
1302
1355
|
captures[sym].first
|
1303
1356
|
end
|
1304
1357
|
end
|
1305
1358
|
|
1306
|
-
|
1307
|
-
@string
|
1308
|
-
end
|
1359
|
+
alias_method :to_s, :string
|
1309
1360
|
|
1310
1361
|
# This alias allows strings to be compared to the string value of Match
|
1311
1362
|
# objects. It is most useful in assertions in unit tests, e.g.:
|
@@ -1339,9 +1390,9 @@ module Citrus
|
|
1339
1390
|
def ==(other)
|
1340
1391
|
case other
|
1341
1392
|
when String
|
1342
|
-
|
1393
|
+
string == other
|
1343
1394
|
when Match
|
1344
|
-
|
1395
|
+
string == other.to_s
|
1345
1396
|
else
|
1346
1397
|
super
|
1347
1398
|
end
|
@@ -1350,7 +1401,7 @@ module Citrus
|
|
1350
1401
|
alias_method :eql?, :==
|
1351
1402
|
|
1352
1403
|
def inspect
|
1353
|
-
|
1404
|
+
string.inspect
|
1354
1405
|
end
|
1355
1406
|
|
1356
1407
|
# Prints the entire subtree of this match using the given +indent+ to
|
@@ -1372,7 +1423,7 @@ module Citrus
|
|
1372
1423
|
rule = stack.pop
|
1373
1424
|
|
1374
1425
|
space = indent * (stack.size / 3)
|
1375
|
-
string =
|
1426
|
+
string = self.string.slice(os, event)
|
1376
1427
|
lines[start] = "#{space}#{string.inspect} rule=#{rule}, offset=#{os}, length=#{event}"
|
1377
1428
|
|
1378
1429
|
last_length = event unless last_length
|
@@ -1425,7 +1476,7 @@ module Citrus
|
|
1425
1476
|
os = stack.pop
|
1426
1477
|
start = stack.pop
|
1427
1478
|
|
1428
|
-
match = Match.new(
|
1479
|
+
match = Match.new(input, @events[start..index], @offset + os)
|
1429
1480
|
capture!(rule, match)
|
1430
1481
|
|
1431
1482
|
if stack.size == 1
|
@@ -1518,6 +1569,7 @@ class Object
|
|
1518
1569
|
# end
|
1519
1570
|
#
|
1520
1571
|
def grammar(name, &block)
|
1572
|
+
warn("Object#grammar will no longer be available by default in citrus 3.0; You should require 'citrus/core_ext'.")
|
1521
1573
|
namespace = respond_to?(:const_set) ? self : Object
|
1522
1574
|
namespace.const_set(name, Citrus::Grammar.new(&block))
|
1523
1575
|
rescue NameError
|
data/lib/citrus/file.rb
CHANGED
@@ -165,7 +165,7 @@ module Citrus
|
|
165
165
|
end
|
166
166
|
|
167
167
|
rule :super do
|
168
|
-
|
168
|
+
ext(:super_keyword) {
|
169
169
|
Super.new
|
170
170
|
}
|
171
171
|
end
|
@@ -329,6 +329,7 @@ module Citrus
|
|
329
329
|
rule :grammar_keyword, [ /\bgrammar\b/, :space ]
|
330
330
|
rule :root_keyword, [ /\broot\b/, :space ]
|
331
331
|
rule :rule_keyword, [ /\brule\b/, :space ]
|
332
|
+
rule :super_keyword, [ /\bsuper\b/, :space ]
|
332
333
|
rule :end_keyword, [ /\bend\b/, :space ]
|
333
334
|
|
334
335
|
rule :constant, /[A-Z][a-zA-Z0-9_]*/
|
data/lib/citrus/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
rule super end
|
data/test/alias_test.rb
CHANGED
@@ -12,7 +12,6 @@ class AliasTest < Test::Unit::TestCase
|
|
12
12
|
rule :b, 'abc'
|
13
13
|
}
|
14
14
|
rule_a = grammar.rule(:a)
|
15
|
-
rule_b = grammar.rule(:b)
|
16
15
|
events = rule_a.exec(Input.new('abc'))
|
17
16
|
assert_equal([rule_a, CLOSE, 3], events)
|
18
17
|
end
|
@@ -36,7 +35,6 @@ class AliasTest < Test::Unit::TestCase
|
|
36
35
|
rule :b, :a
|
37
36
|
}
|
38
37
|
rule_b2 = grammar2.rule(:b)
|
39
|
-
rule_a1 = grammar1.rule(:a)
|
40
38
|
events = rule_b2.exec(Input.new('abc'))
|
41
39
|
assert_equal([rule_b2, CLOSE, 3], events)
|
42
40
|
end
|
data/test/grammar_test.rb
CHANGED
@@ -74,7 +74,7 @@ class GrammarTest < Test::Unit::TestCase
|
|
74
74
|
rule(:num) { all(1, 2, 3) }
|
75
75
|
}
|
76
76
|
assert_raise ParseError do
|
77
|
-
|
77
|
+
grammar.parse('12')
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -99,7 +99,7 @@ class GrammarTest < Test::Unit::TestCase
|
|
99
99
|
rule(:alphanum) { any(/[a-z]/, 0..9) }
|
100
100
|
}
|
101
101
|
assert_raise ParseError do
|
102
|
-
|
102
|
+
grammar.parse('A')
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -126,6 +126,29 @@ class GrammarTest < Test::Unit::TestCase
|
|
126
126
|
assert_equal(str.length, match.length)
|
127
127
|
end
|
128
128
|
|
129
|
+
def test_parse_file
|
130
|
+
grammar = Grammar.new {
|
131
|
+
rule("words"){ rep(any(" ", /[a-z]+/)) }
|
132
|
+
}
|
133
|
+
|
134
|
+
require 'tempfile'
|
135
|
+
Tempfile.open('citrus') do |tmp|
|
136
|
+
tmp << "abd def"
|
137
|
+
tmp.close
|
138
|
+
|
139
|
+
match = grammar.parse_file(tmp.path)
|
140
|
+
|
141
|
+
assert(match)
|
142
|
+
assert_instance_of(Input, match.input)
|
143
|
+
assert_instance_of(Pathname, match.source)
|
144
|
+
|
145
|
+
match.matches.each do |m|
|
146
|
+
assert_instance_of(Input, m.input)
|
147
|
+
assert_instance_of(Pathname, m.source)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
129
152
|
def test_global_grammar
|
130
153
|
assert_raise ArgumentError do
|
131
154
|
grammar(:abc)
|
data/test/input_test.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
require File.expand_path('../helper', __FILE__)
|
2
2
|
|
3
3
|
class InputTest < Test::Unit::TestCase
|
4
|
+
def test_new
|
5
|
+
# to_str
|
6
|
+
assert_equal('abc', Input.new('abc').string)
|
7
|
+
|
8
|
+
# read
|
9
|
+
selftext = ::File.read(__FILE__)
|
10
|
+
::File.open(__FILE__, 'r') do |io|
|
11
|
+
assert_equal(selftext, Input.new(io).string)
|
12
|
+
end
|
13
|
+
|
14
|
+
# to_path
|
15
|
+
path = Struct.new(:to_path).new(__FILE__)
|
16
|
+
assert_equal(selftext, Input.new(path).string)
|
17
|
+
end
|
18
|
+
|
4
19
|
def test_memoized?
|
5
20
|
assert_equal(false, Input.new('').memoized?)
|
6
21
|
end
|
data/test/match_test.rb
CHANGED
@@ -20,6 +20,23 @@ class MatchTest < Test::Unit::TestCase
|
|
20
20
|
assert_equal(false, match2 == match1)
|
21
21
|
end
|
22
22
|
|
23
|
+
def test_source
|
24
|
+
match1 = Match.new('abcdef')
|
25
|
+
assert_equal 'abcdef', match1.source
|
26
|
+
|
27
|
+
path = Struct.new(:to_path).new(__FILE__)
|
28
|
+
match2 = Match.new(Input.new(path))
|
29
|
+
assert_equal path, match2.source
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_string
|
33
|
+
match1 = Match.new('abcdef')
|
34
|
+
assert_equal 'abcdef', match1.string
|
35
|
+
|
36
|
+
match2 = Match.new('abcdef', [Rule.for('bcd'), -1, 3], 1)
|
37
|
+
assert_equal 'bcd', match2.string
|
38
|
+
end
|
39
|
+
|
23
40
|
def test_matches
|
24
41
|
a = Rule.for('a')
|
25
42
|
b = Rule.for('b')
|
@@ -59,11 +76,18 @@ class MatchTest < Test::Unit::TestCase
|
|
59
76
|
CLOSE, 3
|
60
77
|
]
|
61
78
|
|
62
|
-
match.matches.
|
79
|
+
match.matches.each_with_index do |m, i|
|
63
80
|
assert_equal(sub_events, m.events)
|
81
|
+
assert_equal(i*3, m.offset)
|
82
|
+
assert_equal(3, m.length)
|
83
|
+
assert_equal("abc", m.string)
|
64
84
|
assert_equal("abc", m)
|
65
85
|
assert(m.matches)
|
66
86
|
assert_equal(3, m.matches.length)
|
87
|
+
m.matches.each_with_index do |m2,i2|
|
88
|
+
assert_equal(i*3+i2, m2.offset)
|
89
|
+
assert_equal(1, m2.length)
|
90
|
+
end
|
67
91
|
end
|
68
92
|
end
|
69
93
|
|
data/test/super_test.rb
CHANGED
@@ -18,7 +18,6 @@ class SuperTest < Test::Unit::TestCase
|
|
18
18
|
rule_2a = grammar2.rule(:a)
|
19
19
|
rule_2a_als = rule_2a.rules[0]
|
20
20
|
rule_2a_sup = rule_2a.rules[1]
|
21
|
-
rule_1a = grammar1.rule(:a)
|
22
21
|
|
23
22
|
events = rule_2a.exec(Input.new('abc'))
|
24
23
|
assert_equal([
|
@@ -58,12 +57,9 @@ class SuperTest < Test::Unit::TestCase
|
|
58
57
|
rule :a, any(sup, :b)
|
59
58
|
rule :b, sup
|
60
59
|
}
|
61
|
-
rule_1a = grammar1.rule(:a)
|
62
|
-
rule_1b = grammar1.rule(:b)
|
63
60
|
rule_2a = grammar2.rule(:a)
|
64
61
|
rule_2a_sup = rule_2a.rules[0]
|
65
62
|
rule_2a_als = rule_2a.rules[1]
|
66
|
-
rule_2b = grammar2.rule(:b)
|
67
63
|
|
68
64
|
events = rule_2a.exec(Input.new('abc'))
|
69
65
|
assert_equal([
|
metadata
CHANGED
@@ -1,47 +1,40 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: citrus
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.5.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 2
|
8
|
-
- 4
|
9
|
-
- 1
|
10
|
-
version: 2.4.1
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Michael Jackson
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2014-03-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: rake
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
33
22
|
type: :development
|
34
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
35
30
|
description: Parsing Expressions for Ruby
|
36
31
|
email: mjijackson@gmail.com
|
37
32
|
executables: []
|
38
|
-
|
39
33
|
extensions: []
|
40
|
-
|
41
|
-
extra_rdoc_files:
|
34
|
+
extra_rdoc_files:
|
42
35
|
- README.md
|
43
36
|
- CHANGES
|
44
|
-
files:
|
37
|
+
files:
|
45
38
|
- benchmark/seqpar.citrus
|
46
39
|
- benchmark/seqpar.gnuplot
|
47
40
|
- benchmark/seqpar.rb
|
@@ -69,6 +62,8 @@ files:
|
|
69
62
|
- test/_files/rule3.citrus
|
70
63
|
- test/_files/rule4.citrus
|
71
64
|
- test/_files/rule5.citrus
|
65
|
+
- test/_files/rule6.citrus
|
66
|
+
- test/_files/rule7.citrus
|
72
67
|
- test/alias_test.rb
|
73
68
|
- test/and_predicate_test.rb
|
74
69
|
- test/but_predicate_test.rb
|
@@ -99,46 +94,37 @@ files:
|
|
99
94
|
- Rakefile
|
100
95
|
- README.md
|
101
96
|
- CHANGES
|
102
|
-
has_rdoc: true
|
103
97
|
homepage: http://mjijackson.com/citrus
|
104
98
|
licenses: []
|
105
|
-
|
106
99
|
post_install_message:
|
107
|
-
rdoc_options:
|
100
|
+
rdoc_options:
|
108
101
|
- --line-numbers
|
109
102
|
- --inline-source
|
110
103
|
- --title
|
111
104
|
- Citrus
|
112
105
|
- --main
|
113
106
|
- Citrus
|
114
|
-
require_paths:
|
107
|
+
require_paths:
|
115
108
|
- lib
|
116
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
110
|
none: false
|
118
|
-
requirements:
|
119
|
-
- -
|
120
|
-
- !ruby/object:Gem::Version
|
121
|
-
|
122
|
-
|
123
|
-
- 0
|
124
|
-
version: "0"
|
125
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
116
|
none: false
|
127
|
-
requirements:
|
128
|
-
- -
|
129
|
-
- !ruby/object:Gem::Version
|
130
|
-
|
131
|
-
segments:
|
132
|
-
- 0
|
133
|
-
version: "0"
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
134
121
|
requirements: []
|
135
|
-
|
136
122
|
rubyforge_project:
|
137
|
-
rubygems_version: 1.
|
123
|
+
rubygems_version: 1.8.23
|
138
124
|
signing_key:
|
139
125
|
specification_version: 3
|
140
126
|
summary: Parsing Expressions for Ruby
|
141
|
-
test_files:
|
127
|
+
test_files:
|
142
128
|
- test/alias_test.rb
|
143
129
|
- test/and_predicate_test.rb
|
144
130
|
- test/but_predicate_test.rb
|