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 +2 -2
- data/examples/calc.citrus +4 -20
- data/examples/calc.rb +4 -10
- data/examples/calc_sugar.rb +4 -10
- data/lib/citrus.rb +48 -43
- data/lib/citrus/debug.rb +4 -2
- data/lib/citrus/file.rb +5 -16
- data/test/calc_file_test.rb +1 -1
- data/test/calc_sugar_test.rb +1 -1
- data/test/calc_test.rb +1 -1
- data/test/helper.rb +1 -1
- data/test/super_test.rb +2 -2
- metadata +4 -4
data/citrus.gemspec
CHANGED
data/examples/calc.citrus
CHANGED
@@ -3,11 +3,7 @@
|
|
3
3
|
# ignoring whitespace.
|
4
4
|
grammar Calc
|
5
5
|
rule term
|
6
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
62
|
+
any(:float, :integer)
|
69
63
|
end
|
70
64
|
|
71
65
|
rule :float do
|
data/examples/calc_sugar.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
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
|
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
|
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(
|
441
|
-
self.rule_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=(
|
446
|
-
@rule_name =
|
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
|
-
#
|
464
|
-
m.
|
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(
|
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
|
-
#
|
684
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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|
|
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
|
-
|
929
|
-
|
930
|
-
|
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(
|
19
|
+
xml.match(attrs)
|
18
20
|
else
|
19
|
-
xml.match(
|
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 {|
|
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(
|
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 =
|
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
|
data/test/calc_file_test.rb
CHANGED
data/test/calc_sugar_test.rb
CHANGED
data/test/calc_test.rb
CHANGED
data/test/helper.rb
CHANGED
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.
|
54
|
+
assert_equal(:a, match.name)
|
55
55
|
|
56
56
|
match = grammar2.parse('b')
|
57
57
|
assert(match)
|
58
|
-
assert_equal(:b, match.
|
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
|
-
-
|
8
|
-
-
|
9
|
-
version: 1.
|
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-
|
17
|
+
date: 2010-06-21 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|