citrus 1.2.2 → 1.3.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/citrus.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'citrus'
3
- s.version = '1.2.2'
4
- s.date = '2010-06-09'
3
+ s.version = '1.3.0'
4
+ s.date = '2010-06-21'
5
5
 
6
6
  s.summary = 'Parsing Expressions for Ruby'
7
7
  s.description = 'Parsing Expressions for Ruby'
data/examples/calc.citrus CHANGED
@@ -3,11 +3,7 @@
3
3
  # ignoring whitespace.
4
4
  grammar Calc
5
5
  rule term
6
- (additive | factor) {
7
- def value
8
- first.value
9
- end
10
- }
6
+ additive | factor
11
7
  end
12
8
 
13
9
  rule additive
@@ -19,11 +15,7 @@ grammar Calc
19
15
  end
20
16
 
21
17
  rule factor
22
- (multiplicative | primary) {
23
- def value
24
- first.value
25
- end
26
- }
18
+ multiplicative | primary
27
19
  end
28
20
 
29
21
  rule multiplicative
@@ -35,11 +27,7 @@ grammar Calc
35
27
  end
36
28
 
37
29
  rule primary
38
- (term_paren | number) {
39
- def value
40
- first.value
41
- end
42
- }
30
+ term_paren | number
43
31
  end
44
32
 
45
33
  rule term_paren
@@ -67,11 +55,7 @@ grammar Calc
67
55
  end
68
56
 
69
57
  rule number
70
- (float | integer) {
71
- def value
72
- first.value
73
- end
74
- }
58
+ float | integer
75
59
  end
76
60
 
77
61
  rule float
data/examples/calc.rb CHANGED
@@ -6,14 +6,8 @@ require 'citrus'
6
6
  module Calc
7
7
  include Citrus::Grammar
8
8
 
9
- module FirstValue
10
- def value
11
- first.value
12
- end
13
- end
14
-
15
9
  rule :term do
16
- ext(any(:additive, :factor), FirstValue)
10
+ any(:additive, :factor)
17
11
  end
18
12
 
19
13
  rule :additive do
@@ -25,7 +19,7 @@ module Calc
25
19
  end
26
20
 
27
21
  rule :factor do
28
- ext(any(:multiplicative, :primary), FirstValue)
22
+ any(:multiplicative, :primary)
29
23
  end
30
24
 
31
25
  rule :multiplicative do
@@ -37,7 +31,7 @@ module Calc
37
31
  end
38
32
 
39
33
  rule :primary do
40
- ext(any(:term_paren, :number), FirstValue)
34
+ any(:term_paren, :number)
41
35
  end
42
36
 
43
37
  rule :term_paren do
@@ -65,7 +59,7 @@ module Calc
65
59
  end
66
60
 
67
61
  rule :number do
68
- ext(any(:float, :integer), FirstValue)
62
+ any(:float, :integer)
69
63
  end
70
64
 
71
65
  rule :float do
@@ -4,14 +4,8 @@ require 'citrus/sugar'
4
4
  # non-negative numbers (integers and floats), respecting operator precedence and
5
5
  # ignoring whitespace.
6
6
  Calc = Citrus::Grammar.new {
7
- module FirstValue
8
- def value
9
- first.value
10
- end
11
- end
12
-
13
7
  rule term do
14
- ext(any(additive, factor), FirstValue)
8
+ any(additive, factor)
15
9
  end
16
10
 
17
11
  rule additive do
@@ -23,7 +17,7 @@ Calc = Citrus::Grammar.new {
23
17
  end
24
18
 
25
19
  rule factor do
26
- ext(any(multiplicative, primary), FirstValue)
20
+ any(multiplicative, primary)
27
21
  end
28
22
 
29
23
  rule multiplicative do
@@ -35,7 +29,7 @@ Calc = Citrus::Grammar.new {
35
29
  end
36
30
 
37
31
  rule primary do
38
- ext(any(term_paren, number), FirstValue)
32
+ any(term_paren, number)
39
33
  end
40
34
 
41
35
  rule term_paren do
@@ -63,7 +57,7 @@ Calc = Citrus::Grammar.new {
63
57
  end
64
58
 
65
59
  rule number do
66
- ext(any(float, integer), FirstValue)
60
+ any(float, integer)
67
61
  end
68
62
 
69
63
  rule float do
data/lib/citrus.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # http://mjijackson.com/citrus
6
6
  module Citrus
7
- VERSION = [1, 2, 2]
7
+ VERSION = [1, 3, 0]
8
8
 
9
9
  Infinity = 1.0 / 0
10
10
 
@@ -419,13 +419,13 @@ module Citrus
419
419
  private
420
420
 
421
421
  def extend_match(match)
422
- match.ext = ext if ext
422
+ match.extend(ext) if ext
423
423
  end
424
424
 
425
425
  def create_match(data, offset)
426
426
  match = Match.new(data, offset)
427
427
  extend_match(match)
428
- match.name = name
428
+ match.names << name if name
429
429
  match
430
430
  end
431
431
  end
@@ -437,13 +437,13 @@ module Citrus
437
437
  module Proxy
438
438
  include Rule
439
439
 
440
- def initialize(name='<proxy>')
441
- self.rule_name = name
440
+ def initialize(rule_name='<proxy>')
441
+ self.rule_name = rule_name
442
442
  end
443
443
 
444
444
  # Sets the name of the rule this rule is proxy for.
445
- def rule_name=(name)
446
- @rule_name = name.to_sym
445
+ def rule_name=(rule_name)
446
+ @rule_name = rule_name.to_sym
447
447
  end
448
448
 
449
449
  # The name of this proxy's rule.
@@ -460,8 +460,8 @@ module Citrus
460
460
  m = input.match(rule, offset)
461
461
  if m
462
462
  extend_match(m)
463
- # If this Proxy has a name then it should rename all of its matches.
464
- m.name = name if name
463
+ # This proxy's name should be added to the names of the match.
464
+ m.names << name if name
465
465
  m
466
466
  end
467
467
  end
@@ -675,13 +675,18 @@ module Citrus
675
675
  class Label
676
676
  include Predicate
677
677
 
678
- def initialize(label='<label>', rule='')
679
- @label = label.to_sym
678
+ def initialize(label_name='<label>', rule='')
680
679
  super(rule)
680
+ self.label_name = label_name
681
681
  end
682
682
 
683
- # The symbol this rule uses to re-name all its matches.
684
- attr_reader :label
683
+ # Sets the name of this label.
684
+ def label_name=(label_name)
685
+ @label_name = label_name.to_sym
686
+ end
687
+
688
+ # The name this rule adds to all its matches.
689
+ attr_reader :label_name
685
690
 
686
691
  # Returns the Match for this rule on +input+ at the given +offset+, +nil+ if
687
692
  # no match can be made. When a Label makes a match, it re-names the match to
@@ -690,14 +695,15 @@ module Citrus
690
695
  m = rule.match(input, offset)
691
696
  if m
692
697
  extend_match(m)
693
- m.name = label
698
+ # This label's name should be added to the names of the match.
699
+ m.names << label_name
694
700
  m
695
701
  end
696
702
  end
697
703
 
698
704
  # Returns the Citrus notation of this rule as a string.
699
705
  def to_s
700
- label.to_s + ':' + rule.embed
706
+ label_name.to_s + ':' + rule.embed
701
707
  end
702
708
  end
703
709
 
@@ -794,7 +800,12 @@ module Citrus
794
800
  def match(input, offset=0)
795
801
  rules.each do |rule|
796
802
  m = input.match(rule, offset)
797
- return create_match([m], offset) if m
803
+ if m
804
+ extend_match(m)
805
+ # This choice's name should be added to the names of the match.
806
+ m.names << name if name
807
+ return m
808
+ end
798
809
  end
799
810
  nil
800
811
  end
@@ -851,18 +862,26 @@ module Citrus
851
862
  @offset = offset
852
863
  end
853
864
 
854
- # The name by which this match can be accessed from a parent match. This
855
- # will be the name of the rule that generated the match in most cases.
856
- # However, if the match is the result of a Label this will be the value of
857
- # the label.
858
- attr_accessor :name
859
-
860
- # A module that will be used to extend this match.
861
- attr_accessor :ext
862
-
863
865
  # The offset in the input at which this match occurred.
864
866
  attr_reader :offset
865
867
 
868
+ # An array of all names of this match. A name is added to a match object
869
+ # for each rule that returns that object when matching. These names can then
870
+ # be used to determine which rules were satisfied by a given match.
871
+ def names
872
+ @names ||= []
873
+ end
874
+
875
+ # The name of the lowest level rule that originally created this match.
876
+ def name
877
+ names.first
878
+ end
879
+
880
+ # Returns +true+ if this match has the given +name+.
881
+ def has_name?(name)
882
+ names.include?(name)
883
+ end
884
+
866
885
  # An array of all sub-matches of this match.
867
886
  def matches
868
887
  @matches ||= []
@@ -897,7 +916,7 @@ module Citrus
897
916
  # match.
898
917
  def find(name, deep=true)
899
918
  sym = name.to_sym
900
- ms = matches.select {|m| sym == m.name }
919
+ ms = matches.select {|m| m.has_name?(sym) }
901
920
  ms.concat(matches.map {|m| m.find(name, deep) }.flatten) if deep
902
921
  ms
903
922
  end
@@ -925,23 +944,9 @@ module Citrus
925
944
  # Uses #match to allow sub-matches of this match to be called by name as
926
945
  # instance methods.
927
946
  def method_missing(sym, *args)
928
- # Extend this object only when needed and immediately redefine
929
- # #method_missing so that the new version is used on all future calls.
930
- extend(ext) if ext
931
- redefine_method_missing!
932
- __send__(sym, *args)
933
- end
934
-
935
- private
936
-
937
- def redefine_method_missing! # :nodoc:
938
- instance_eval(<<-RUBY, __FILE__, __LINE__ + 1)
939
- def method_missing(sym, *args)
940
- m = first(sym)
941
- return m if m
942
- raise 'No match named "%s" in %s (%s)' % [sym, self, name]
943
- end
944
- RUBY
947
+ m = first(sym)
948
+ return m if m
949
+ raise 'No match named "%s" in %s (%s)' % [sym, self, name]
945
950
  end
946
951
  end
947
952
  end
data/lib/citrus/debug.rb CHANGED
@@ -13,10 +13,12 @@ module Citrus
13
13
  xml.instruct!
14
14
  end
15
15
 
16
+ attrs = { "names" => names.join(','), "text" => text, "offset" => offset }
17
+
16
18
  if matches.empty?
17
- xml.match("name" => name, "text" => text, "offset" => offset)
19
+ xml.match(attrs)
18
20
  else
19
- xml.match("name" => name, "text" => text, "offset" => offset) do
21
+ xml.match(attrs) do
20
22
  matches.each {|m| m.to_markup(xml) }
21
23
  end
22
24
  end
data/lib/citrus/file.rb CHANGED
@@ -74,7 +74,7 @@ module Citrus
74
74
  end
75
75
 
76
76
  def values
77
- choices.map {|s| s.value }
77
+ choices.map {|c| c.value }
78
78
  end
79
79
 
80
80
  def value
@@ -137,11 +137,7 @@ module Citrus
137
137
  end
138
138
 
139
139
  rule :primary do
140
- any(:super, :alias, :rule_body_paren, :terminal) {
141
- def value
142
- first.value
143
- end
144
- }
140
+ any(:super, :alias, :rule_body_paren, :terminal)
145
141
  end
146
142
 
147
143
  rule :rule_body_paren do
@@ -205,7 +201,7 @@ module Citrus
205
201
  rule :terminal do
206
202
  any(:quoted_string, :character_class, :anything_symbol, :regular_expression) {
207
203
  def value
208
- Rule.create(first.value)
204
+ Rule.create(super)
209
205
  end
210
206
  }
211
207
  end
@@ -243,11 +239,7 @@ module Citrus
243
239
  end
244
240
 
245
241
  rule :qualifier do
246
- any(:and, :not, :label) {
247
- def wrap(rule)
248
- first.wrap(rule)
249
- end
250
- }
242
+ any(:and, :not, :label)
251
243
  end
252
244
 
253
245
  rule :and do
@@ -281,7 +273,7 @@ module Citrus
281
273
  rule :extension do
282
274
  any(:tag, :block) {
283
275
  def wrap(rule)
284
- rule.ext = first.value
276
+ rule.ext = value
285
277
  rule
286
278
  end
287
279
  }
@@ -305,9 +297,6 @@ module Citrus
305
297
 
306
298
  rule :quantifier do
307
299
  any(:question, :plus, :repeat) {
308
- def min; first.min end
309
- def max; first.max end
310
-
311
300
  def wrap(rule)
312
301
  Repeat.new(min, max, rule)
313
302
  end
@@ -7,5 +7,5 @@ end
7
7
  Citrus.load(File.dirname(__FILE__) + '/../examples/calc')
8
8
 
9
9
  class CalcFileTest < Test::Unit::TestCase
10
- include CalcTests
10
+ include CalcTestMethods
11
11
  end
@@ -7,5 +7,5 @@ end
7
7
  require File.dirname(__FILE__) + '/../examples/calc_sugar'
8
8
 
9
9
  class CalcSugarTest < Test::Unit::TestCase
10
- include CalcTests
10
+ include CalcTestMethods
11
11
  end
data/test/calc_test.rb CHANGED
@@ -7,5 +7,5 @@ end
7
7
  require File.dirname(__FILE__) + '/../examples/calc'
8
8
 
9
9
  class CalcTest < Test::Unit::TestCase
10
- include CalcTests
10
+ include CalcTestMethods
11
11
  end
data/test/helper.rb CHANGED
@@ -43,7 +43,7 @@ class Test::Unit::TestCase
43
43
  end
44
44
  end
45
45
 
46
- module CalcTests
46
+ module CalcTestMethods
47
47
  def test_int
48
48
  match = Calc.parse('3')
49
49
  assert(match)
data/test/super_test.rb CHANGED
@@ -51,11 +51,11 @@ class SuperTest < Test::Unit::TestCase
51
51
 
52
52
  match = grammar2.parse('a')
53
53
  assert(match)
54
- assert_equal(:a, match.first.name)
54
+ assert_equal(:a, match.name)
55
55
 
56
56
  match = grammar2.parse('b')
57
57
  assert(match)
58
- assert_equal(:b, match.first.name)
58
+ assert_equal(:b, match.name)
59
59
  end
60
60
 
61
61
  def test_to_s
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 2
8
- - 2
9
- version: 1.2.2
7
+ - 3
8
+ - 0
9
+ version: 1.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Michael Jackson
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-09 00:00:00 -06:00
17
+ date: 2010-06-21 00:00:00 -06:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency