regexp_parser 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +57 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE +1 -1
  5. data/README.md +225 -206
  6. data/Rakefile +9 -3
  7. data/lib/regexp_parser.rb +7 -11
  8. data/lib/regexp_parser/expression.rb +72 -14
  9. data/lib/regexp_parser/expression/classes/alternation.rb +3 -16
  10. data/lib/regexp_parser/expression/classes/conditional.rb +57 -0
  11. data/lib/regexp_parser/expression/classes/free_space.rb +17 -0
  12. data/lib/regexp_parser/expression/classes/keep.rb +7 -0
  13. data/lib/regexp_parser/expression/classes/set.rb +28 -7
  14. data/lib/regexp_parser/expression/methods/strfregexp.rb +113 -0
  15. data/lib/regexp_parser/expression/methods/tests.rb +116 -0
  16. data/lib/regexp_parser/expression/methods/traverse.rb +63 -0
  17. data/lib/regexp_parser/expression/quantifier.rb +10 -0
  18. data/lib/regexp_parser/expression/sequence.rb +45 -0
  19. data/lib/regexp_parser/expression/subexpression.rb +29 -1
  20. data/lib/regexp_parser/lexer.rb +31 -8
  21. data/lib/regexp_parser/parser.rb +118 -45
  22. data/lib/regexp_parser/scanner.rb +1745 -1404
  23. data/lib/regexp_parser/scanner/property.rl +57 -3
  24. data/lib/regexp_parser/scanner/scanner.rl +161 -34
  25. data/lib/regexp_parser/syntax.rb +12 -2
  26. data/lib/regexp_parser/syntax/ruby/1.9.1.rb +3 -3
  27. data/lib/regexp_parser/syntax/ruby/1.9.3.rb +2 -7
  28. data/lib/regexp_parser/syntax/ruby/2.0.0.rb +4 -1
  29. data/lib/regexp_parser/syntax/ruby/2.1.4.rb +13 -0
  30. data/lib/regexp_parser/syntax/ruby/2.1.5.rb +13 -0
  31. data/lib/regexp_parser/syntax/ruby/2.1.rb +2 -2
  32. data/lib/regexp_parser/syntax/ruby/2.2.0.rb +16 -0
  33. data/lib/regexp_parser/syntax/ruby/2.2.rb +8 -0
  34. data/lib/regexp_parser/syntax/tokens.rb +19 -2
  35. data/lib/regexp_parser/syntax/tokens/conditional.rb +22 -0
  36. data/lib/regexp_parser/syntax/tokens/keep.rb +14 -0
  37. data/lib/regexp_parser/syntax/tokens/unicode_property.rb +45 -4
  38. data/lib/regexp_parser/token.rb +23 -8
  39. data/lib/regexp_parser/version.rb +5 -0
  40. data/regexp_parser.gemspec +35 -0
  41. data/test/expression/test_all.rb +6 -1
  42. data/test/expression/test_base.rb +19 -0
  43. data/test/expression/test_conditionals.rb +114 -0
  44. data/test/expression/test_free_space.rb +33 -0
  45. data/test/expression/test_set.rb +61 -0
  46. data/test/expression/test_strfregexp.rb +214 -0
  47. data/test/expression/test_subexpression.rb +24 -0
  48. data/test/expression/test_tests.rb +99 -0
  49. data/test/expression/test_to_h.rb +48 -0
  50. data/test/expression/test_to_s.rb +46 -0
  51. data/test/expression/test_traverse.rb +164 -0
  52. data/test/lexer/test_all.rb +16 -3
  53. data/test/lexer/test_conditionals.rb +101 -0
  54. data/test/lexer/test_keep.rb +24 -0
  55. data/test/lexer/test_literals.rb +51 -51
  56. data/test/lexer/test_nesting.rb +62 -62
  57. data/test/lexer/test_refcalls.rb +18 -20
  58. data/test/parser/test_all.rb +18 -3
  59. data/test/parser/test_alternation.rb +11 -14
  60. data/test/parser/test_conditionals.rb +148 -0
  61. data/test/parser/test_escapes.rb +29 -5
  62. data/test/parser/test_free_space.rb +139 -0
  63. data/test/parser/test_groups.rb +40 -0
  64. data/test/parser/test_keep.rb +21 -0
  65. data/test/scanner/test_all.rb +8 -2
  66. data/test/scanner/test_conditionals.rb +166 -0
  67. data/test/scanner/test_escapes.rb +8 -5
  68. data/test/scanner/test_free_space.rb +133 -0
  69. data/test/scanner/test_groups.rb +28 -0
  70. data/test/scanner/test_keep.rb +33 -0
  71. data/test/scanner/test_properties.rb +4 -0
  72. data/test/scanner/test_scripts.rb +71 -1
  73. data/test/syntax/ruby/test_1.9.3.rb +2 -2
  74. data/test/syntax/ruby/test_2.0.0.rb +38 -0
  75. data/test/syntax/ruby/test_2.2.0.rb +38 -0
  76. data/test/syntax/ruby/test_all.rb +1 -8
  77. data/test/syntax/ruby/test_files.rb +104 -0
  78. data/test/test_all.rb +2 -1
  79. data/test/token/test_all.rb +2 -0
  80. data/test/token/test_token.rb +109 -0
  81. metadata +75 -21
  82. data/VERSION.yml +0 -5
  83. data/lib/regexp_parser/ctype.rb +0 -48
  84. data/test/syntax/ruby/test_2.x.rb +0 -46
@@ -1,5 +1,6 @@
1
+ require File.expand_path('../syntax/tokens', __FILE__)
2
+
1
3
  module Regexp::Syntax
2
- require File.expand_path('../syntax/tokens', __FILE__)
3
4
 
4
5
  class SyntaxError < StandardError
5
6
  def initialize(what)
@@ -63,10 +64,18 @@ module Regexp::Syntax
63
64
  when 'ruby/2.1.0'; syntax = Regexp::Syntax::Ruby::V210.new
64
65
  when 'ruby/2.1.2'; syntax = Regexp::Syntax::Ruby::V212.new
65
66
  when 'ruby/2.1.3'; syntax = Regexp::Syntax::Ruby::V213.new
67
+ when 'ruby/2.1.4'; syntax = Regexp::Syntax::Ruby::V214.new
68
+ when 'ruby/2.1.5'; syntax = Regexp::Syntax::Ruby::V215.new
66
69
 
67
70
  # aliases for the latest 2.1 implementations
68
71
  when 'ruby/2.1'; syntax = Regexp::Syntax::Ruby::V21.new
69
72
 
73
+ # Ruby 2.2.x
74
+ when 'ruby/2.2.0'; syntax = Regexp::Syntax::Ruby::V220.new
75
+
76
+ # aliases for the latest 2.2 implementations
77
+ when 'ruby/2.2'; syntax = Regexp::Syntax::Ruby::V22.new
78
+
70
79
  else
71
80
  raise UnknownSyntaxError.new(name)
72
81
  end
@@ -87,7 +96,8 @@ module Regexp::Syntax
87
96
  def initialize
88
97
  @implements = {}
89
98
 
90
- implements :literal, [:literal]
99
+ implements Token::Literal::Type, Token::Literal::All
100
+ implements Token::FreeSpace::Type, Token::FreeSpace::All
91
101
  end
92
102
 
93
103
  def implementation
@@ -18,10 +18,10 @@ module Regexp::Syntax
18
18
  implements :escape, CharacterType::Hex
19
19
 
20
20
  implements :property,
21
- UnicodeProperty::All
21
+ UnicodeProperty::V190
22
22
 
23
23
  implements :nonproperty,
24
- UnicodeProperty::All
24
+ UnicodeProperty::V190
25
25
 
26
26
  implements :quantifier,
27
27
  Quantifier::Possessive + Quantifier::IntervalPossessive
@@ -30,7 +30,7 @@ module Regexp::Syntax
30
30
  CharacterSet::POSIX::StandardNegative +
31
31
  CharacterSet::POSIX::Extensions +
32
32
  CharacterSet::POSIX::ExtensionsNegative +
33
- UnicodeProperty::All
33
+ UnicodeProperty::V190
34
34
 
35
35
  implements :subset, CharacterSet::OpenClose +
36
36
  CharacterSet::Extended + CharacterSet::Types +
@@ -10,13 +10,8 @@ module Regexp::Syntax
10
10
  super
11
11
 
12
12
  # these were added with update of Oniguruma to Unicode 6.0
13
- implements :property,
14
- [:script_mandaic, :script_batak, :script_brahmi] +
15
- UnicodeProperty::Age
16
-
17
- implements :nonproperty,
18
- [:script_mandaic, :script_batak, :script_brahmi] +
19
- UnicodeProperty::Age
13
+ implements :property, UnicodeProperty::V193
14
+ implements :nonproperty, UnicodeProperty::V193
20
15
  end
21
16
  end
22
17
  end
@@ -8,7 +8,10 @@ module Regexp::Syntax
8
8
  def initialize
9
9
  super
10
10
 
11
- #implements :escape, CharacterType::Hex
11
+ implements :keep, Keep::All
12
+ implements :conditional, Conditional::All
13
+ implements :property, UnicodeProperty::V200
14
+ implements :nonproperty, UnicodeProperty::V200
12
15
  end
13
16
  end
14
17
 
@@ -0,0 +1,13 @@
1
+ require File.expand_path('../2.1.3', __FILE__)
2
+
3
+ module Regexp::Syntax
4
+ module Ruby
5
+
6
+ class V214 < Regexp::Syntax::Ruby::V213
7
+ def initialize
8
+ super
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path('../2.1.4', __FILE__)
2
+
3
+ module Regexp::Syntax
4
+ module Ruby
5
+
6
+ class V215 < Regexp::Syntax::Ruby::V214
7
+ def initialize
8
+ super
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -1,8 +1,8 @@
1
- require File.expand_path('../2.1.3', __FILE__)
1
+ require File.expand_path('../2.1.5', __FILE__)
2
2
 
3
3
  module Regexp::Syntax
4
4
  module Ruby
5
5
  # uses the latest 2.1 release
6
- class V21 < Regexp::Syntax::Ruby::V213; end
6
+ class V21 < Regexp::Syntax::Ruby::V215; end
7
7
  end
8
8
  end
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../2.1', __FILE__)
2
+
3
+ module Regexp::Syntax
4
+ module Ruby
5
+
6
+ class V220 < Regexp::Syntax::Ruby::V21
7
+ def initialize
8
+ super
9
+
10
+ implements :property, UnicodeProperty::V220
11
+ implements :nonproperty, UnicodeProperty::V220
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ require File.expand_path('../2.2.0', __FILE__)
2
+
3
+ module Regexp::Syntax
4
+ module Ruby
5
+ # uses the latest 2.2 release
6
+ class V22 < Regexp::Syntax::Ruby::V220; end
7
+ end
8
+ end
@@ -8,13 +8,30 @@ module Regexp::Syntax
8
8
  Type = :literal
9
9
  end
10
10
 
11
- Map[Literal::Type] = Literal::All
11
+ module FreeSpace
12
+ All = [:comment, :whitespace]
13
+ Type = :free_space
14
+ end
15
+
16
+ Map[FreeSpace::Type] = FreeSpace::All
17
+ Map[Literal::Type] = Literal::All
12
18
  end
13
19
  end
14
20
 
15
21
 
16
22
  # Load all the token files, they will populate the Map constant.
17
- Dir[File.dirname(__FILE__) + '/tokens/*.rb'].each {|f| require f }
23
+ require 'regexp_parser/syntax/tokens/anchor'
24
+ require 'regexp_parser/syntax/tokens/assertion'
25
+ require 'regexp_parser/syntax/tokens/backref'
26
+ require 'regexp_parser/syntax/tokens/character_set'
27
+ require 'regexp_parser/syntax/tokens/character_type'
28
+ require 'regexp_parser/syntax/tokens/conditional'
29
+ require 'regexp_parser/syntax/tokens/escape'
30
+ require 'regexp_parser/syntax/tokens/group'
31
+ require 'regexp_parser/syntax/tokens/keep'
32
+ require 'regexp_parser/syntax/tokens/meta'
33
+ require 'regexp_parser/syntax/tokens/quantifier'
34
+ require 'regexp_parser/syntax/tokens/unicode_property'
18
35
 
19
36
 
20
37
  # After loading all the tokens the map is full. Extract all tokens and types
@@ -0,0 +1,22 @@
1
+ module Regexp::Syntax
2
+ module Token
3
+
4
+ module Conditional
5
+ Delimiters = [:open, :close]
6
+
7
+ Condition = [:condition_open, :condition, :condition_close]
8
+ Separator = [:separator]
9
+
10
+ All = (
11
+ Conditional::Delimiters +
12
+ Conditional::Condition +
13
+ Conditional::Separator
14
+ ).flatten
15
+
16
+ Type = :conditional
17
+ end
18
+
19
+ Map[Conditional::Type] = Conditional::All
20
+
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Regexp::Syntax
2
+ module Token
3
+
4
+ module Keep
5
+ Mark = [:mark]
6
+
7
+ All = Mark
8
+ Type = :keep
9
+ end
10
+
11
+ Map[Keep::Type] = Keep::All
12
+
13
+ end
14
+ end
@@ -34,9 +34,17 @@ module Regexp::Syntax
34
34
  Symbol + Separator + Codepoint
35
35
  end
36
36
 
37
- Age = [:age_1_1, :age_2_0, :age_2_1, :age_3_0, :age_3_1,
38
- :age_3_2, :age_4_0, :age_4_1, :age_5_0, :age_5_1,
39
- :age_5_2, :age_6_0]
37
+ # As of ruby version 1.9.3
38
+ Age_V193 = [:age_1_1, :age_2_0, :age_2_1, :age_3_0, :age_3_1,
39
+ :age_3_2, :age_4_0, :age_4_1, :age_5_0, :age_5_1,
40
+ :age_5_2, :age_6_0]
41
+
42
+ Age_V200 = [:age_6_1]
43
+
44
+ # These were merged (from Onigmo) in the branch for 2.2.0
45
+ Age_V220 = [:age_6_2, :age_6_3, :age_7_0]
46
+
47
+ Age = Age_V193 + Age_V200 + Age_V220
40
48
 
41
49
  Derived = [
42
50
  :ascii_hex,
@@ -191,7 +199,40 @@ module Regexp::Syntax
191
199
 
192
200
  Script_6_0 = [:script_brahmi, :script_batak, :script_mandaic]
193
201
 
194
- All = CharType + POSIX + Category::All + Age + Derived + Script
202
+ Script_7_0 = [
203
+ :script_caucasian_albanian,
204
+ :script_bassa_vah,
205
+ :script_duployan,
206
+ :script_elbasan,
207
+ :script_grantha,
208
+ :script_pahawh_hmong,
209
+ :script_khojki,
210
+ :script_linear_a,
211
+ :script_mahajani,
212
+ :script_manichaean,
213
+ :script_mende_kikakui,
214
+ :script_modi,
215
+ :script_mro,
216
+ :script_old_north_arabian,
217
+ :script_nabataean,
218
+ :script_palmyrene,
219
+ :script_pau_cin_hau,
220
+ :script_old_permic,
221
+ :script_psalter_pahlavi,
222
+ :script_siddham,
223
+ :script_khudawadi,
224
+ :script_tirhuta,
225
+ :script_warang_citi
226
+ ]
227
+
228
+ V190 = CharType + POSIX + Category::All + Derived + Script
229
+ V193 = Age_V193 + Script_6_0
230
+
231
+ V200 = Age_V200
232
+
233
+ V220 = Age_V220 + Script_7_0
234
+
235
+ All = V190 + V193 + V200 + V220
195
236
 
196
237
  Type = :property
197
238
  NonType = :nonproperty
@@ -1,6 +1,16 @@
1
1
  class Regexp
2
2
 
3
- TOKEN_KEYS = [:type, :token, :text, :ts, :te, :level, :set_level].freeze
3
+ TOKEN_KEYS = [
4
+ :type,
5
+ :token,
6
+ :text,
7
+ :ts,
8
+ :te,
9
+ :level,
10
+ :set_level,
11
+ :conditional_level
12
+ ].freeze
13
+
4
14
  Token = Struct.new(*TOKEN_KEYS) do
5
15
  def offset
6
16
  [self.ts, self.te]
@@ -10,13 +20,6 @@ class Regexp
10
20
  self.te - self.ts
11
21
  end
12
22
 
13
- def to_h
14
- hash = {}
15
- members.each do |member|
16
- hash[member.to_sym] = self.send(member.to_sym)
17
- end; hash
18
- end
19
-
20
23
  def next(exp = nil)
21
24
  if exp
22
25
  @next = exp
@@ -32,6 +35,18 @@ class Regexp
32
35
  @previous
33
36
  end
34
37
  end
38
+
39
+ if RUBY_VERSION < '2.0.0'
40
+ def to_h
41
+ hash = {}
42
+
43
+ members.each do |member|
44
+ hash[member.to_sym] = self.send(member.to_sym)
45
+ end
46
+
47
+ hash
48
+ end
49
+ end
35
50
  end
36
51
 
37
52
  end
@@ -0,0 +1,5 @@
1
+ class Regexp
2
+ module Parser
3
+ VERSION = '0.2.0'
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+
3
+ require 'regexp_parser/version'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'regexp_parser'
7
+ gem.version = ::Regexp::Parser::VERSION
8
+
9
+ gem.summary = "Scanner, lexer, parser for ruby's regular expressions"
10
+ gem.description = 'A library for tokenizing, lexing, and parsing Ruby regular expressions.'
11
+ gem.homepage = 'http://github.com/ammar/regexp_parser'
12
+
13
+ if gem.respond_to?(:metadata)
14
+ gem.metadata = { 'issue_tracker' => 'https://github.com/ammar/regexp_parser/issues' }
15
+ end
16
+
17
+ gem.authors = ['Ammar Ali']
18
+ gem.email = ['ammarabuali@gmail.com']
19
+
20
+ gem.license = 'MIT'
21
+
22
+ gem.require_paths = ['lib']
23
+
24
+ gem.files = Dir.glob('{lib,test}/**/*.rb') +
25
+ Dir.glob('lib/**/*.rl') +
26
+ %w(Gemfile Rakefile LICENSE README.md ChangeLog regexp_parser.gemspec)
27
+
28
+ gem.test_files = Dir.glob('test/**/*.rb')
29
+
30
+ gem.rdoc_options = ["--inline-source", "--charset=UTF-8"]
31
+
32
+ gem.platform = Gem::Platform::RUBY
33
+
34
+ gem.required_ruby_version = '>= 1.8.7'
35
+ end
@@ -1,7 +1,12 @@
1
1
  require File.expand_path("../../helpers", __FILE__)
2
2
 
3
3
  %w{
4
- base to_s clone
4
+ base to_s to_h clone subexpression free_space tests
5
+ traverse strfregexp
5
6
  }.each do|tc|
6
7
  require File.expand_path("../test_#{tc}", __FILE__)
7
8
  end
9
+
10
+ if RUBY_VERSION >= '2.0.0'
11
+ require File.expand_path("../test_conditionals", __FILE__)
12
+ end
@@ -13,6 +13,25 @@ class ExpressionBase < Test::Unit::TestCase
13
13
  assert_equal( re.source, re_text )
14
14
  end
15
15
 
16
+ def test_expression_level
17
+ regexp = /^a(b(c(d)))e$/
18
+ root = RP.parse(regexp)
19
+
20
+ %w{^ a (b(c(d))) e $}.each_with_index do |t, i|
21
+ assert_equal( t, root[i].to_s )
22
+ assert_equal( 0, root[i].level )
23
+ end
24
+
25
+ assert_equal( 'b', root[2][0].to_s )
26
+ assert_equal( 1, root[2][0].level )
27
+
28
+ assert_equal( 'c', root[2][1][0].to_s )
29
+ assert_equal( 2, root[2][1][0].level )
30
+
31
+ assert_equal( 'd', root[2][1][1][0].to_s )
32
+ assert_equal( 3, root[2][1][1][0].level )
33
+ end
34
+
16
35
  def test_expression_terminal?
17
36
  root = RP.parse('^a([b]+)c$')
18
37
 
@@ -0,0 +1,114 @@
1
+ require File.expand_path("../../helpers", __FILE__)
2
+
3
+ class ExpressionConditionals < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @root = RP.parse(/^a(b(?(1)c|(?(2)d|(?(3)e|f)))g)$/)
7
+
8
+ @cond_1 = @root[2][1]
9
+ @cond_2 = @root[2][1][2][0]
10
+ @cond_3 = @root[2][1][2][0][2][0]
11
+ end
12
+
13
+ def is_conditional_condition?(exp)
14
+ exp.is_a?(Conditional::Condition)
15
+ end
16
+
17
+ def is_conditional_branch?(exp)
18
+ exp.is_a?(Conditional::Branch)
19
+ end
20
+
21
+ def test_expression_conditional_root_level
22
+ %w{^ a (b(?(1)c|(?(2)d|(?(3)e|f)))g) $}.each_with_index do |t, i|
23
+ assert_equal( 0, @root[i].conditional_level )
24
+ assert_equal( t, @root[i].to_s )
25
+ end
26
+
27
+ # First capture group
28
+ assert_equal( 'b', @root[2][0].text )
29
+ assert_equal( 0, @root[2][0].conditional_level )
30
+ end
31
+
32
+ def test_expression_conditional_level_one
33
+ condition = @cond_1.condition
34
+ branch_1 = @cond_1.branches.first
35
+ branch_2 = @cond_1.branches.last
36
+
37
+ # Condition
38
+ assert_equal( true, is_conditional_condition?(condition) )
39
+ assert_equal( '(1)', condition.text )
40
+ assert_equal( 1, condition.conditional_level )
41
+
42
+ # Branch 1
43
+ assert_equal( true, is_conditional_branch?(branch_1) )
44
+ assert_equal( 'c', branch_1.text )
45
+ assert_equal( 1, branch_1.conditional_level )
46
+
47
+ # Literal
48
+ assert_equal( 'c', branch_1.first.text )
49
+ assert_equal( 1, branch_1.first.conditional_level )
50
+
51
+ end
52
+
53
+ def test_expression_conditional_level_two
54
+ condition = @cond_2.condition
55
+ branch_1 = @cond_2.branches.first
56
+ branch_2 = @cond_2.branches.last
57
+
58
+ assert_equal( '(?', @cond_2.text )
59
+ assert_equal( 1, @cond_2.conditional_level )
60
+
61
+ # Condition
62
+ assert_equal( true, is_conditional_condition?(condition) )
63
+ assert_equal( '(2)', condition.text )
64
+ assert_equal( 2, condition.conditional_level )
65
+
66
+ # Branch 1
67
+ assert_equal( true, is_conditional_branch?(branch_1) )
68
+ assert_equal( 'd', branch_1.text )
69
+ assert_equal( 2, branch_1.conditional_level )
70
+
71
+ # Literal
72
+ assert_equal( 'd', branch_1.first.text )
73
+ assert_equal( 2, branch_1.first.conditional_level )
74
+
75
+ # Branch 2
76
+ assert_equal( '(?', branch_2.first.text )
77
+ assert_equal( 2, branch_2.first.conditional_level )
78
+ end
79
+
80
+ def test_expression_conditional_level_three
81
+ condition = @cond_3.condition
82
+ branch_1 = @cond_3.branches.first
83
+ branch_2 = @cond_3.branches.last
84
+
85
+ # Condition
86
+ assert_equal( true, is_conditional_condition?(condition) )
87
+ assert_equal( '(3)', condition.text )
88
+ assert_equal( 3, condition.conditional_level )
89
+
90
+ # Same as branch 2 in level two
91
+ assert_equal( '(?', @cond_3.text )
92
+ assert_equal( '(?(3)e|f)', @cond_3.to_s )
93
+ assert_equal( 2, @cond_3.conditional_level )
94
+
95
+ # Branch 1
96
+ assert_equal( true, is_conditional_branch?(branch_1) )
97
+ assert_equal( 'e', branch_1.text )
98
+ assert_equal( 3, branch_1.conditional_level )
99
+
100
+ # Literal
101
+ assert_equal( 'e', branch_1.first.text )
102
+ assert_equal( 3, branch_1.first.conditional_level )
103
+
104
+ # Branch 2
105
+ assert_equal( true, is_conditional_branch?(branch_2) )
106
+ assert_equal( 'f', branch_2.text )
107
+ assert_equal( 3, branch_2.conditional_level )
108
+
109
+ # Literal
110
+ assert_equal( 'f', branch_2.first.text )
111
+ assert_equal( 3, branch_2.first.conditional_level )
112
+ end
113
+
114
+ end