citrus 2.3.7 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,12 @@
1
+ = 2.4.0 / 2011-05-11
2
+
3
+ * Fixed a bug that prevented parsing nested blocks correctly (issue #21).
4
+
5
+ * Added URI example.
6
+
7
+ * Moved example grammars inside lib/citrus/grammars and added
8
+ lib/citrus/grammars.rb for easily requiring Citrus example grammars.
9
+
1
10
  = 2.3.7 / 2011-02-20
2
11
 
3
12
  * Fixed a bug that prevented forward slashes from being used inside character
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ task :default => :test
6
6
  # TESTS #######################################################################
7
7
 
8
8
  Rake::TestTask.new(:test) do |t|
9
- t.test_files = FileList['test/*_test.rb'] + FileList['examples/*_test.rb']
9
+ t.test_files = FileList['test/**/*_test.rb']
10
10
  end
11
11
 
12
12
  # DOCS ########################################################################
data/citrus.gemspec CHANGED
@@ -17,7 +17,6 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.files = Dir['benchmark/**'] +
19
19
  Dir['doc/**'] +
20
- Dir['examples/**'] +
21
20
  Dir['extras/**'] +
22
21
  Dir['lib/**/*.rb'] +
23
22
  Dir['test/**/*'] +
data/lib/citrus.rb CHANGED
@@ -648,6 +648,11 @@ module Citrus
648
648
  nil
649
649
  end
650
650
 
651
+ # Tests the given +obj+ for case equality with this rule.
652
+ def ===(obj)
653
+ !test(obj).nil?
654
+ end
655
+
651
656
  # Returns +true+ if this rule is a Terminal.
652
657
  def terminal?
653
658
  false
@@ -700,6 +705,8 @@ module Citrus
700
705
  end
701
706
  end
702
707
 
708
+ alias_method :eql?, :==
709
+
703
710
  def inspect # :nodoc:
704
711
  to_s
705
712
  end
@@ -872,6 +879,8 @@ module Citrus
872
879
  end
873
880
  end
874
881
 
882
+ alias_method :eql?, :==
883
+
875
884
  # Returns +true+ if this rule is a Terminal.
876
885
  def terminal? # :nodoc:
877
886
  true
@@ -915,6 +924,8 @@ module Citrus
915
924
  end
916
925
  end
917
926
 
927
+ alias_method :eql?, :==
928
+
918
929
  # Returns the Citrus notation of this rule as a string.
919
930
  def to_citrus # :nodoc:
920
931
  if case_sensitive?
@@ -1336,6 +1347,8 @@ module Citrus
1336
1347
  end
1337
1348
  end
1338
1349
 
1350
+ alias_method :eql?, :==
1351
+
1339
1352
  def inspect
1340
1353
  @string.inspect
1341
1354
  end
data/lib/citrus/file.rb CHANGED
@@ -73,7 +73,7 @@ module Citrus
73
73
  end
74
74
 
75
75
  rule :expression do
76
- all(:sequence, zero_or_more([ :bar, :sequence ])) {
76
+ all(:sequence, zero_or_more([['|', zero_or_one(:space)], :sequence])) {
77
77
  rules = captures[:sequence].map {|s| s.value }
78
78
  rules.length > 1 ? Choice.new(rules) : rules.first
79
79
  }
@@ -123,7 +123,7 @@ module Citrus
123
123
  end
124
124
 
125
125
  rule :grouping do
126
- all(:lparen, :expression, :rparen) {
126
+ all(['(', zero_or_one(:space)], :expression, [')', zero_or_one(:space)]) {
127
127
  expression.value
128
128
  }
129
129
  end
@@ -241,7 +241,11 @@ module Citrus
241
241
  end
242
242
 
243
243
  rule :tag do
244
- mod all(:lt, :module_name, :gt) do
244
+ mod all(
245
+ ['<', zero_or_one(:space)],
246
+ :module_name,
247
+ ['>', zero_or_one(:space)]
248
+ ) do
245
249
  include ModuleNameHelpers
246
250
 
247
251
  def value
@@ -251,7 +255,11 @@ module Citrus
251
255
  end
252
256
 
253
257
  rule :block do
254
- all(:lcurly, zero_or_more(any(:block, /[^{}]+/)), :rcurly) {
258
+ all(
259
+ '{',
260
+ zero_or_more(any(:block, /[^{}]+/)),
261
+ ['}', zero_or_one(:space)]
262
+ ) {
255
263
  proc = eval("Proc.new #{to_s}", TOPLEVEL_BINDING)
256
264
 
257
265
  # Attempt to detect if this is a module block using some
@@ -322,13 +330,6 @@ module Citrus
322
330
  rule :root_keyword, [ /\broot\b/, :space ]
323
331
  rule :rule_keyword, [ /\brule\b/, :space ]
324
332
  rule :end_keyword, [ /\bend\b/, :space ]
325
- rule :lparen, [ '(', :space ]
326
- rule :rparen, [ ')', :space ]
327
- rule :lcurly, [ '{', :space ]
328
- rule :rcurly, [ '}', :space ]
329
- rule :bar, [ '|', :space ]
330
- rule :lt, [ '<', :space ]
331
- rule :gt, [ '>', :space ]
332
333
 
333
334
  rule :constant, /[A-Z][a-zA-Z0-9_]*/
334
335
  rule :white, /[ \t\n\r]/
@@ -0,0 +1,11 @@
1
+ # Require this file to use any of the bundled Citrus grammars.
2
+ #
3
+ # require 'citrus/grammars'
4
+ # Citrus.require 'uri'
5
+ #
6
+ # match = UniformResourceIdentifier.parse(uri_string)
7
+ # # => #<Citrus::Match ... >
8
+
9
+ require 'citrus'
10
+
11
+ $LOAD_PATH.unshift(::File.expand_path('../grammars', __FILE__))
@@ -1,6 +1,6 @@
1
1
  module Citrus
2
2
  # The current version of Citrus as [major, minor, patch].
3
- VERSION = [2, 3, 7]
3
+ VERSION = [2, 4, 0]
4
4
 
5
5
  # Returns the current version of Citrus as a string.
6
6
  def self.version
@@ -0,0 +1,5 @@
1
+ rule method
2
+ (def space method_name statements ends) {
3
+ "#{method_name.value} = function() { #{statements.value} }"
4
+ }
5
+ end
data/test/grammar_test.rb CHANGED
@@ -118,7 +118,8 @@ class GrammarTest < Test::Unit::TestCase
118
118
  assert_equal('((a))', match)
119
119
  assert_equal(5, match.length)
120
120
 
121
- str = ('(' * 200) + 'a' + (')' * 200)
121
+ n = 100
122
+ str = ('(' * n) + 'a' + (')' * n)
122
123
  match = grammar.parse(str)
123
124
  assert(match)
124
125
  assert_equal(str, match)
@@ -1,8 +1,7 @@
1
- # This file contains a suite of tests for the Calc grammar found in calc.citrus.
1
+ require File.expand_path('../../helper', __FILE__)
2
+ require 'citrus/grammars'
2
3
 
3
- require 'citrus'
4
- Citrus.require File.expand_path('../calc', __FILE__)
5
- require 'test/unit'
4
+ Citrus.require 'calc'
6
5
 
7
6
  class CalcTest < Test::Unit::TestCase
8
7
  # A helper method that tests the successful parsing and evaluation of the
File without changes
@@ -1,9 +1,7 @@
1
- # This file contains a suite of tests for the EmailAddress grammar
2
- # found in email.citrus.
1
+ require File.expand_path('../../helper', __FILE__)
2
+ require 'citrus/grammars'
3
3
 
4
- require 'citrus'
5
- Citrus.require File.expand_path('../email', __FILE__)
6
- require 'test/unit'
4
+ Citrus.require 'email'
7
5
 
8
6
  class EmailAddressTest < Test::Unit::TestCase
9
7
  def test_addr_spec_valid
@@ -1,12 +1,7 @@
1
- examples = File.expand_path('..', __FILE__)
2
- $LOAD_PATH.unshift(examples) unless $LOAD_PATH.include?(examples)
1
+ require File.expand_path('../../helper', __FILE__)
2
+ require 'citrus/grammars'
3
3
 
4
- # This file contains a suite of tests for the IPAddress grammar found in
5
- # ipaddress.citrus.
6
-
7
- require 'citrus'
8
4
  Citrus.require 'ipaddress'
9
- require 'test/unit'
10
5
 
11
6
  class IPAddressTest < Test::Unit::TestCase
12
7
  def test_v4
File without changes
@@ -1,12 +1,7 @@
1
- examples = File.expand_path('..', __FILE__)
2
- $LOAD_PATH.unshift(examples) unless $LOAD_PATH.include?(examples)
1
+ require File.expand_path('../../helper', __FILE__)
2
+ require 'citrus/grammars'
3
3
 
4
- # This file contains a suite of tests for the IPv4Address grammar found in
5
- # ipv4address.citrus.
6
-
7
- require 'citrus'
8
4
  Citrus.require 'ipv4address'
9
- require 'test/unit'
10
5
 
11
6
  class IPv4AddressTest < Test::Unit::TestCase
12
7
  def test_dec_octet
File without changes
@@ -1,12 +1,7 @@
1
- examples = File.expand_path('..', __FILE__)
2
- $LOAD_PATH.unshift(examples) unless $LOAD_PATH.include?(examples)
1
+ require File.expand_path('../../helper', __FILE__)
2
+ require 'citrus/grammars'
3
3
 
4
- # This file contains a suite of tests for the IPv6Address grammar found in
5
- # ipv6address.citrus.
6
-
7
- require 'citrus'
8
4
  Citrus.require 'ipv6address'
9
- require 'test/unit'
10
5
 
11
6
  class IPv6AddressTest < Test::Unit::TestCase
12
7
  def test_hexdig
File without changes
@@ -0,0 +1,53 @@
1
+ require File.expand_path('../../helper', __FILE__)
2
+ require 'citrus/grammars'
3
+
4
+ Citrus.require 'uri'
5
+
6
+ class UniformResourceIdentifierTest < Test::Unit::TestCase
7
+ U = UniformResourceIdentifier
8
+
9
+ def test_uri
10
+ match = U.parse('http://www.example.com')
11
+ assert(match)
12
+ end
13
+
14
+ def test_uri_with_query_string
15
+ match = U.parse('http://www.example.com/?q=some+query')
16
+ assert(match)
17
+ end
18
+
19
+ def test_authority
20
+ match = U.parse('michael@', :root => :authority)
21
+ assert(match)
22
+ end
23
+
24
+ def test_host
25
+ match = U.parse('127.0.0.1', :root => :host)
26
+ assert(match)
27
+
28
+ match = U.parse('[12AD:34FC:A453:1922::]', :root => :host)
29
+ assert(match)
30
+ end
31
+
32
+ def test_userinfo
33
+ match = U.parse('michael', :root => :userinfo)
34
+ assert(match)
35
+
36
+ assert_raise(Citrus::ParseError) do
37
+ U.parse('michael@', :root => :userinfo)
38
+ end
39
+ end
40
+
41
+ def test_ipliteral
42
+ match = U.parse('[12AD:34FC:A453:1922::]', :root => :'IP-literal')
43
+ assert(match)
44
+ end
45
+
46
+ def test_ipvfuture
47
+ match = U.parse('v1.123:456:789', :root => :IPvFuture)
48
+ assert(match)
49
+
50
+ match = U.parse('v5A.ABCD:1234', :root => :IPvFuture)
51
+ assert(match)
52
+ end
53
+ end
@@ -118,7 +118,7 @@ x
118
118
  17
119
119
  MemoizedInputTest
120
120
  i
121
- 68
121
+ 92
122
122
  5
123
123
  66
124
124
  99
@@ -186,6 +186,30 @@ i
186
186
  49
187
187
  3
188
188
  4
189
+ 15
190
+ 5
191
+ 7
192
+ 13
193
+ 56
194
+ 14
195
+ 47
196
+ 50
197
+ 6
198
+ 1
199
+ 15
200
+ 99
201
+ 7
202
+ 15
203
+ 7
204
+ 16
205
+ 65
206
+ 67
207
+ 49
208
+ 2
209
+ 0
210
+ 49
211
+ 3
212
+ 4
189
213
  11
190
214
  I
191
215
  5
@@ -197,7 +221,7 @@ I
197
221
  0
198
222
  n
199
223
  p
200
- 13
224
+ 17
201
225
  x
202
226
  14
203
227
  test_memoized?
@@ -649,7 +673,7 @@ x
649
673
  16
650
674
  test_cache_hits1
651
675
  i
652
- 59
676
+ 60
653
677
  45
654
678
  0
655
679
  1
@@ -698,7 +722,8 @@ i
698
722
  1
699
723
  15
700
724
  5
701
- 80
725
+ 4
726
+ 3
702
727
  20
703
728
  0
704
729
  49
@@ -774,7 +799,7 @@ I
774
799
  I
775
800
  1d
776
801
  I
777
- 3b
802
+ 3c
778
803
  x
779
804
  58
780
805
  /Users/michael/Projects/citrus/test/memoized_input_test.rb
@@ -1073,11 +1098,461 @@ p
1073
1098
  x
1074
1099
  5
1075
1100
  input
1101
+ x
1102
+ 10
1103
+ LettersABC
1104
+ M
1105
+ 1
1106
+ p
1107
+ 2
1108
+ x
1109
+ 9
1110
+ for_block
1111
+ t
1112
+ n
1113
+ x
1114
+ 17
1115
+ MemoizedInputTest
1116
+ i
1117
+ 40
1118
+ 5
1119
+ 7
1120
+ 0
1121
+ 56
1122
+ 1
1123
+ 47
1124
+ 50
1125
+ 2
1126
+ 1
1127
+ 15
1128
+ 5
1129
+ 7
1130
+ 3
1131
+ 56
1132
+ 4
1133
+ 47
1134
+ 50
1135
+ 2
1136
+ 1
1137
+ 15
1138
+ 5
1139
+ 7
1140
+ 5
1141
+ 56
1142
+ 6
1143
+ 47
1144
+ 50
1145
+ 2
1146
+ 1
1147
+ 15
1148
+ 5
1149
+ 7
1150
+ 7
1151
+ 56
1152
+ 8
1153
+ 47
1154
+ 50
1155
+ 2
1156
+ 1
1157
+ 11
1158
+ I
1159
+ 4
1160
+ I
1161
+ 0
1162
+ I
1163
+ 0
1164
+ I
1165
+ 0
1166
+ I
1167
+ -2
1168
+ p
1169
+ 9
1170
+ x
1171
+ 3
1172
+ top
1173
+ M
1174
+ 1
1175
+ p
1176
+ 2
1177
+ x
1178
+ 9
1179
+ for_block
1180
+ t
1181
+ n
1182
+ x
1183
+ 17
1184
+ MemoizedInputTest
1185
+ i
1186
+ 39
1187
+ 5
1188
+ 5
1189
+ 7
1190
+ 0
1191
+ 7
1192
+ 1
1193
+ 7
1194
+ 2
1195
+ 47
1196
+ 49
1197
+ 3
1198
+ 3
1199
+ 5
1200
+ 7
1201
+ 1
1202
+ 7
1203
+ 0
1204
+ 7
1205
+ 2
1206
+ 47
1207
+ 49
1208
+ 3
1209
+ 3
1210
+ 5
1211
+ 7
1212
+ 1
1213
+ 7
1214
+ 2
1215
+ 7
1216
+ 0
1217
+ 47
1218
+ 49
1219
+ 3
1220
+ 3
1221
+ 47
1222
+ 49
1223
+ 4
1224
+ 3
1225
+ 11
1226
+ I
1227
+ 8
1228
+ I
1229
+ 0
1230
+ I
1231
+ 0
1232
+ I
1233
+ 0
1234
+ I
1235
+ -2
1236
+ p
1237
+ 5
1238
+ x
1239
+ 1
1240
+ a
1241
+ x
1242
+ 1
1243
+ b
1244
+ x
1245
+ 1
1246
+ c
1247
+ x
1248
+ 3
1249
+ all
1250
+ x
1251
+ 3
1252
+ any
1253
+ p
1254
+ 3
1255
+ I
1256
+ 0
1257
+ I
1258
+ 2e
1259
+ I
1260
+ 27
1261
+ x
1262
+ 58
1263
+ /Users/michael/Projects/citrus/test/memoized_input_test.rb
1264
+ p
1265
+ 0
1266
+ x
1267
+ 4
1268
+ rule
1269
+ x
1270
+ 1
1271
+ a
1272
+ M
1273
+ 1
1274
+ p
1275
+ 2
1276
+ x
1277
+ 9
1278
+ for_block
1279
+ t
1280
+ n
1281
+ x
1282
+ 17
1283
+ MemoizedInputTest
1284
+ i
1285
+ 4
1286
+ 7
1287
+ 0
1288
+ 64
1289
+ 11
1290
+ I
1291
+ 2
1292
+ I
1293
+ 0
1294
+ I
1295
+ 0
1296
+ I
1297
+ 0
1298
+ I
1299
+ -2
1300
+ p
1301
+ 1
1302
+ s
1303
+ 1
1304
+ a
1076
1305
  p
1306
+ 3
1307
+ I
1308
+ 0
1309
+ I
1310
+ 31
1311
+ I
1312
+ 4
1313
+ x
1314
+ 58
1315
+ /Users/michael/Projects/citrus/test/memoized_input_test.rb
1316
+ p
1317
+ 0
1318
+ x
1319
+ 1
1320
+ b
1321
+ M
1322
+ 1
1323
+ p
1324
+ 2
1325
+ x
1326
+ 9
1327
+ for_block
1328
+ t
1329
+ n
1330
+ x
1331
+ 17
1332
+ MemoizedInputTest
1333
+ i
1334
+ 4
1335
+ 7
1336
+ 0
1337
+ 64
1338
+ 11
1339
+ I
1340
+ 2
1341
+ I
1342
+ 0
1343
+ I
1344
+ 0
1345
+ I
1346
+ 0
1347
+ I
1348
+ -2
1349
+ p
1350
+ 1
1351
+ s
1352
+ 1
1353
+ b
1354
+ p
1355
+ 3
1356
+ I
1357
+ 0
1358
+ I
1359
+ 34
1360
+ I
1361
+ 4
1362
+ x
1363
+ 58
1364
+ /Users/michael/Projects/citrus/test/memoized_input_test.rb
1365
+ p
1366
+ 0
1367
+ x
1368
+ 1
1369
+ c
1370
+ M
1371
+ 1
1372
+ p
1373
+ 2
1374
+ x
1375
+ 9
1376
+ for_block
1377
+ t
1378
+ n
1379
+ x
1380
+ 17
1381
+ MemoizedInputTest
1382
+ i
1383
+ 4
1384
+ 7
1385
+ 0
1386
+ 64
1077
1387
  11
1078
1388
  I
1079
1389
  2
1080
1390
  I
1391
+ 0
1392
+ I
1393
+ 0
1394
+ I
1395
+ 0
1396
+ I
1397
+ -2
1398
+ p
1399
+ 1
1400
+ s
1401
+ 1
1402
+ c
1403
+ p
1404
+ 3
1405
+ I
1406
+ 0
1407
+ I
1408
+ 37
1409
+ I
1410
+ 4
1411
+ x
1412
+ 58
1413
+ /Users/michael/Projects/citrus/test/memoized_input_test.rb
1414
+ p
1415
+ 0
1416
+ p
1417
+ 9
1418
+ I
1419
+ 0
1420
+ I
1421
+ 2d
1422
+ I
1423
+ a
1424
+ I
1425
+ 30
1426
+ I
1427
+ 14
1428
+ I
1429
+ 33
1430
+ I
1431
+ 1e
1432
+ I
1433
+ 36
1434
+ I
1435
+ 28
1436
+ x
1437
+ 58
1438
+ /Users/michael/Projects/citrus/test/memoized_input_test.rb
1439
+ p
1440
+ 0
1441
+ x
1442
+ 16
1443
+ test_memoization
1444
+ M
1445
+ 1
1446
+ n
1447
+ n
1448
+ x
1449
+ 16
1450
+ test_memoization
1451
+ i
1452
+ 38
1453
+ 45
1454
+ 0
1455
+ 1
1456
+ 7
1457
+ 2
1458
+ 64
1459
+ 44
1460
+ 43
1461
+ 3
1462
+ 79
1463
+ 49
1464
+ 4
1465
+ 1
1466
+ 13
1467
+ 7
1468
+ 5
1469
+ 2
1470
+ 49
1471
+ 6
1472
+ 2
1473
+ 15
1474
+ 49
1475
+ 7
1476
+ 2
1477
+ 19
1478
+ 0
1479
+ 15
1480
+ 5
1481
+ 7
1482
+ 2
1483
+ 64
1484
+ 20
1485
+ 0
1486
+ 47
1487
+ 49
1488
+ 8
1489
+ 2
1490
+ 11
1491
+ I
1492
+ 7
1493
+ I
1494
+ 1
1495
+ I
1496
+ 0
1497
+ I
1498
+ 0
1499
+ n
1500
+ p
1501
+ 9
1502
+ x
1503
+ 10
1504
+ LettersABC
1505
+ n
1506
+ s
1507
+ 3
1508
+ bca
1509
+ x
1510
+ 4
1511
+ Hash
1512
+ x
1513
+ 16
1514
+ new_from_literal
1515
+ x
1516
+ 7
1517
+ memoize
1518
+ x
1519
+ 3
1520
+ []=
1521
+ x
1522
+ 5
1523
+ parse
1524
+ x
1525
+ 12
1526
+ assert_equal
1527
+ p
1528
+ 7
1529
+ I
1530
+ -1
1531
+ I
1532
+ 3b
1533
+ I
1534
+ 0
1535
+ I
1536
+ 3c
1537
+ I
1538
+ 1b
1539
+ I
1540
+ 3d
1541
+ I
1542
+ 26
1543
+ x
1544
+ 58
1545
+ /Users/michael/Projects/citrus/test/memoized_input_test.rb
1546
+ p
1547
+ 1
1548
+ x
1549
+ 5
1550
+ match
1551
+ p
1552
+ 15
1553
+ I
1554
+ 2
1555
+ I
1081
1556
  4
1082
1557
  I
1083
1558
  10
@@ -1097,6 +1572,14 @@ I
1097
1572
  26
1098
1573
  I
1099
1574
  44
1575
+ I
1576
+ 2c
1577
+ I
1578
+ 4e
1579
+ I
1580
+ 3b
1581
+ I
1582
+ 5c
1100
1583
  x
1101
1584
  58
1102
1585
  /Users/michael/Projects/citrus/test/memoized_input_test.rb