citrus 1.7.0 → 1.8.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.
@@ -9,19 +9,15 @@ class RuleTest < Test::Unit::TestCase
9
9
  end
10
10
 
11
11
  NumericProc = Proc.new {
12
- def to_i
13
- text.to_i
14
- end
15
-
16
- def to_f
17
- text.to_f
12
+ def add_one
13
+ to_i + 1
18
14
  end
19
15
  }
20
16
 
21
17
  NumericModule = Module.new(&NumericProc)
22
18
 
23
19
  def test_create
24
- rule = Rule.create('"a"')
20
+ rule = Rule.eval('"a"')
25
21
  assert(rule)
26
22
  match = rule.match(input('a'))
27
23
  assert(match)
@@ -40,7 +36,7 @@ class RuleTest < Test::Unit::TestCase
40
36
  rule.extension = NumericProc
41
37
  match = rule.match(input('1'))
42
38
  assert(match)
43
- assert_equal(1, match.to_i)
39
+ assert_equal(2, match.add_one)
44
40
  assert_instance_of(Float, match.to_f)
45
41
  end
46
42
 
@@ -49,7 +45,7 @@ class RuleTest < Test::Unit::TestCase
49
45
  rule.extension = NumericModule
50
46
  match = rule.match(input('1'))
51
47
  assert(match)
52
- assert_equal(1, match.to_i)
48
+ assert_equal(2, match.add_one)
53
49
  assert_instance_of(Float, match.to_f)
54
50
  end
55
51
 
@@ -18,7 +18,7 @@ class SequenceTest < Test::Unit::TestCase
18
18
 
19
19
  match = rule.match(input('ab'))
20
20
  assert(match)
21
- assert_equal('ab', match.text)
21
+ assert_equal('ab', match)
22
22
  assert_equal(2, match.length)
23
23
  end
24
24
 
@@ -26,7 +26,7 @@ class SequenceTest < Test::Unit::TestCase
26
26
  rule = Sequence.new([/\d+/, '+', /\d+/])
27
27
  match = rule.match(input('1+2'))
28
28
  assert(match)
29
- assert_equal('1+2', match.text)
29
+ assert_equal('1+2', match)
30
30
  assert_equal(3, match.length)
31
31
  end
32
32
 
@@ -34,7 +34,7 @@ class SequenceTest < Test::Unit::TestCase
34
34
  rule = Sequence.new([/[0-9]+/, Choice.new(%w<+ ->), /\d+/])
35
35
  match = rule.match(input('1+2'))
36
36
  assert(match)
37
- assert_equal('1+2', match.text)
37
+ assert_equal('1+2', match)
38
38
  assert_equal(3, match.length)
39
39
  end
40
40
 
@@ -20,12 +20,12 @@ class SuperTest < Test::Unit::TestCase
20
20
 
21
21
  match = grammar2.parse('b')
22
22
  assert(match)
23
- assert_equal('b', match.text)
23
+ assert_equal('b', match)
24
24
  assert_equal(1, match.length)
25
25
 
26
26
  match = grammar2.parse('a')
27
27
  assert(match)
28
- assert_equal('a', match.text)
28
+ assert_equal('a', match)
29
29
  assert_equal(1, match.length)
30
30
  end
31
31
 
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 7
7
+ - 8
8
8
  - 0
9
- version: 1.7.0
9
+ version: 1.8.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-08-17 00:00:00 -05:00
17
+ date: 2010-08-17 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -55,12 +55,12 @@ files:
55
55
  - benchmark/seqpar.citrus
56
56
  - benchmark/seqpar.gnuplot
57
57
  - benchmark/seqpar.rb
58
- - doc/background.rdoc
59
- - doc/example.rdoc
60
- - doc/index.rdoc
61
- - doc/license.rdoc
62
- - doc/links.rdoc
63
- - doc/syntax.rdoc
58
+ - doc/background.markdown
59
+ - doc/example.markdown
60
+ - doc/index.markdown
61
+ - doc/license.markdown
62
+ - doc/links.markdown
63
+ - doc/syntax.markdown
64
64
  - examples/calc.citrus
65
65
  - examples/calc.rb
66
66
  - examples/ip.citrus
@@ -79,6 +79,7 @@ files:
79
79
  - test/_files/super.citrus
80
80
  - test/alias_test.rb
81
81
  - test/and_predicate_test.rb
82
+ - test/but_predicate_test.rb
82
83
  - test/calc_file_test.rb
83
84
  - test/calc_test.rb
84
85
  - test/choice_test.rb
@@ -138,6 +139,7 @@ summary: Parsing Expressions for Ruby
138
139
  test_files:
139
140
  - test/alias_test.rb
140
141
  - test/and_predicate_test.rb
142
+ - test/but_predicate_test.rb
141
143
  - test/calc_file_test.rb
142
144
  - test/calc_test.rb
143
145
  - test/choice_test.rb
@@ -1,115 +0,0 @@
1
- = Example
2
-
3
- Below is an example of a simple grammar that is able to parse strings of
4
- integers separated by any amount of white space and a <tt>+</tt> symbol.
5
-
6
- grammar Addition
7
- rule additive
8
- number plus (additive | number)
9
- end
10
-
11
- rule number
12
- [0-9]+ space
13
- end
14
-
15
- rule plus
16
- '+' space
17
- end
18
-
19
- rule space
20
- [ \t]*
21
- end
22
- end
23
-
24
- Several things to note about the above example:
25
-
26
- * Grammar and rule declarations end with the <tt>end</tt> keyword
27
- * A Sequence of rules is created by separating expressions with a space
28
- * Likewise, ordered choice is represented with a vertical bar
29
- * Parentheses may be used to override the natural binding order
30
- * Rules may refer to other rules in their own definitions simply by using the
31
- other rule's name
32
- * Any expression may be followed by a quantifier
33
-
34
- == Interpretation
35
-
36
- The grammar above is able to parse simple mathematical expressions such as "1+2"
37
- and "1 + 2+3", but it does not have enough semantic information to be able to
38
- actually interpret these expressions.
39
-
40
- At this point, when the grammar parses a string it generates a tree of Match[link:api/classes/Citrus/Match.html]
41
- objects. Each match is created by a rule. A match will know what text it
42
- contains, its offset in the original input, and what submatches it contains.
43
-
44
- Submatches are created whenever a rule contains another rule. For example, in
45
- the grammar above the number rule matches a string of digits followed by white
46
- space. Thus, a match generated by the number rule will contain two submatches.
47
-
48
- We can use Ruby's block syntax to create a module that will be attached to these
49
- matches when they are created and is used to lazily extend them when we want to
50
- interpret them. The following example shows one way to do this.
51
-
52
- grammar Addition
53
- rule additive
54
- (number plus term:(additive | number)) {
55
- def value
56
- number.value + term.value
57
- end
58
- }
59
- end
60
-
61
- rule number
62
- ([0-9]+ space) {
63
- def value
64
- text.strip.to_i
65
- end
66
- }
67
- end
68
-
69
- rule plus
70
- '+' space
71
- end
72
-
73
- rule space
74
- [ \t]*
75
- end
76
- end
77
-
78
- In this version of the grammar we have added two semantic blocks, one each for
79
- the +additive+ and +number+ rules. These blocks contain methods that will be present
80
- on all match objects that result from matches of those particular rules. It's
81
- easiest to explain what is going on here by starting with the lowest level
82
- block, which is defined within the +number+ rule.
83
-
84
- The semantic block associated with the +number+ rule defines one method, +value+.
85
- Inside this method, we can see that the value of a number match is determined to
86
- be its text value, stripped of white space and converted to an integer.
87
-
88
- The +additive+ rule also extends its matches with a +value+ method. Notice the use
89
- of the "term" label within the rule definition. This label allows the match that
90
- is created by either the +additive+ or the +number+ rule to be retrieved using the
91
- "term" label. The value of an additive is determined to be the values of its
92
- number and term matches added together using Ruby's addition operator.
93
-
94
- Since additive is the first rule defined in the grammar, any match that results
95
- from parsing a string with this grammar will have a value method that can be
96
- used to recursively calculate the collective value of the entire match tree.
97
-
98
- To give it a try, save the code for the Addition grammar in a file called
99
- addition.citrus. Next, assuming you have the Citrus gem installed, try the
100
- following sequence of commands in a terminal.
101
-
102
- $ irb
103
- > require 'citrus'
104
- => true
105
- > Citrus.load 'addition'
106
- => [Addition]
107
- > m = Addition.parse '1 + 2 + 3'
108
- => #<Citrus::Match ...
109
- > m.value
110
- => 6
111
-
112
- Congratulations! You just ran your first piece of Citrus code.
113
-
114
- Take a look at examples/calc.citrus[http://github.com/mjijackson/citrus/blob/master/examples/calc.citrus] for an example of a calculator that is able
115
- to parse and evaluate more complex mathematical expressions.
@@ -1,15 +0,0 @@
1
- Citrus is a compact and powerful parsing library for Ruby[http://ruby-lang.org/] that combines the
2
- elegance and expressiveness of the language with the simplicity and power of
3
- parsing expressions.
4
-
5
- = Installation
6
-
7
- Via RubyGems[http://rubygems.org/]:
8
-
9
- $ sudo gem install citrus
10
-
11
- From a local copy:
12
-
13
- $ git clone git://github.com/mjijackson/citrus.git
14
- $ cd citrus
15
- $ rake package && sudo rake install
@@ -1,18 +0,0 @@
1
- = Links
2
-
3
- The primary resource for all things to do with parsing expressions can be found
4
- at MIT.
5
-
6
- http://pdos.csail.mit.edu/~baford/packrat
7
-
8
- A useful summary of parsing expression grammars can be found on Wikipedia as
9
- well.
10
-
11
- http://en.wikipedia.org/wiki/Parsing_expression_grammar
12
-
13
- Citrus draws inspiration from another Ruby library for writing parsing
14
- expression grammars, Treetop. While Citrus' syntax is similar to that of
15
- Treetop, it's not identical. The link is included here for those who may wish to
16
- explore an alternative implementation.
17
-
18
- http://treetop.rubyforge.org
@@ -1,96 +0,0 @@
1
- = Syntax
2
-
3
- The most straightforward way to compose a Citrus grammar is to use Citrus' own
4
- custom grammar syntax. This syntax borrows heavily from Ruby, so it should
5
- already be familiar to Ruby programmers.
6
-
7
- == Terminals
8
-
9
- Terminals may be represented by a string or a regular expression. Both follow
10
- the same rules as Ruby string and regular expression literals.
11
-
12
- 'abc'
13
- "abc\n"
14
- /\xFF/
15
-
16
- Character classes and the dot (match anything) symbol are supported as well for
17
- compatibility with other parsing expression implementations.
18
-
19
- [a-z0-9] # match any lowercase letter or digit
20
- [\x00-\xFF] # match any octet
21
- . # match anything, even new lines
22
-
23
- See FixedWidth[link:api/classes/Citrus/FixedWidth.html] and
24
- Expression[link:api/classes/Citrus/Expression.html] for more information.
25
-
26
- == Repetition
27
-
28
- Quantifiers may be used after any expression to specify a number of times it
29
- must match. The universal form of a quantifier is N*M where N is the minimum and
30
- M is the maximum number of times the expression may match.
31
-
32
- 'abc'1*2 # match "abc" a minimum of one, maximum
33
- # of two times
34
- 'abc'1* # match "abc" at least once
35
- 'abc'*2 # match "abc" a maximum of twice
36
-
37
- The + and ? operators are supported as well for the common cases of 1* and *1
38
- respectively.
39
-
40
- 'abc'+ # match "abc" at least once
41
- 'abc'? # match "abc" a maximum of once
42
-
43
- See Repeat[link:api/classes/Citrus/Repeat.html] for more information.
44
-
45
- == Lookahead
46
-
47
- Both positive and negative lookahead are supported in Citrus. Use the & and !
48
- operators to indicate that an expression either should or should not match. In
49
- neither case is any input consumed.
50
-
51
- &'a' 'b' # match a "b" preceded by an "a"
52
- !'a' 'b' # match a "b" that is not preceded by an "a"
53
- !'a' . # match any character except for "a"
54
-
55
- See AndPredicate[link:api/classes/Citrus/AndPredicate.html] and
56
- NotPredicate[link:api/classes/Citrus/NotPredicate.html] for more information.
57
-
58
- == Sequences
59
-
60
- Sequences of expressions may be separated by a space to indicate that the rules
61
- should match in that order.
62
-
63
- 'a' 'b' 'c' # match "a", then "b", then "c"
64
- 'a' [0-9] # match "a", then a numeric digit
65
-
66
- See Sequence[link:api/classes/Citrus/Sequence.html] for more information.
67
-
68
- == Choices
69
-
70
- Ordered choice is indicated by a vertical bar that separates two expressions.
71
- Note that any operator binds more tightly than the bar.
72
-
73
- 'a' | 'b' # match "a" or "b"
74
- 'a' 'b' | 'c' # match "a" then "b" (in sequence), or "c"
75
-
76
- See Choice[link:api/classes/Citrus/Choice.html] for more information.
77
-
78
- == Super
79
-
80
- When including a grammar inside another, all rules in the child that have the
81
- same name as a rule in the parent also have access to the super keyword to
82
- invoke the parent rule.
83
-
84
- See Super[link:api/classes/Citrus/Super.html] for more information.
85
-
86
- == Labels
87
-
88
- Match objects may be referred to by a different name than the rule that
89
- originally generated them. Labels are created by placing the label and a colon
90
- immediately preceding any expression.
91
-
92
- chars:/[a-z]+/ # the characters matched by the regular
93
- # expression may be referred to as "chars"
94
- # in a block method
95
-
96
- See Label[link:api/classes/Citrus/Label.html] for more information.