citrus 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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