require File.expand_path("../../helpers", __FILE__) class TestParserConditionals < Test::Unit::TestCase def test_parse_conditional regexp = /(?a)(?()T|F)/ root = RP.parse(regexp, 'ruby/2.0') exp = root.expressions[1] assert( exp.is_a?( Conditional::Expression ), "Expected Condition, but got #{exp.class.name}") assert_equal( exp.type, :conditional ) assert_equal( exp.token, :open ) assert_equal( exp.text, '(?' ) end def test_parse_conditional_condition regexp = /(?a)(?()T|F)/ root = RP.parse(regexp, 'ruby/2.0') exp = root[1].condition assert( exp.is_a?( Conditional::Condition ), "Expected Condition, but got #{exp.class.name}") assert_equal( exp.type, :conditional ) assert_equal( exp.token, :condition ) assert_equal( exp.text, '()' ) end def test_parse_conditional_nested_groups regexp = /((a)|(b)|((?(2)(c(d|e)+)?|(?(3)f|(?(4)(g|(h)(i)))))))/ root = RP.parse(regexp, 'ruby/2.0') assert_equal( regexp.source, root.to_s ) group = root.first assert_equal( Group::Capture, group.class ) alt = group.first assert_equal( Alternation, alt.class ) assert_equal( 3, alt.length ) assert_equal( true, alt.all? {|exp| exp.first.is_a?(Group::Capture) } ) subgroup = alt[2].first conditional = subgroup.first assert_equal( Conditional::Expression, conditional.class ) assert_equal( 3, conditional.length ) assert_equal( Conditional::Condition, conditional[0].class ) assert_equal( '(2)', conditional[0].text ) condition = conditional.condition assert_equal( Conditional::Condition, condition.class ) assert_equal( '(2)', condition.text ) branches = conditional.branches assert_equal( 2, branches.length ) assert_equal( Array, branches.class ) end def test_parse_conditional_nested regexp = /(a(b(c)))(?(1)(?(2)d|(?(3)e|f))|(?(4)(?(5)g|h)))/ root = RP.parse(regexp, 'ruby/2.0') assert_equal( regexp.source, root.to_s ) { 1 => [2, root[1]], 2 => [2, root[1][1][0]], 3 => [2, root[1][1][0][2][0]], 4 => [1, root[1][2][0]], 5 => [2, root[1][2][0][1][0]], }.each do |index, test| branch_count, exp = test assert_equal( Conditional::Expression, exp.class ) assert_equal( "(#{index})", exp.condition.text ) assert_equal( branch_count, exp.branches.length ) end end def test_parse_conditional_nested_alternation regexp = /(a)(?(1)(b|c|d)|(e|f|g))(h)(?(2)(i|j|k)|(l|m|n))|o|p/ root = RP.parse(regexp, 'ruby/2.0') assert_equal( regexp.source, root.to_s ) assert_equal( Alternation, root.first.class ) [ [3, 'b|c|d', root[0][0][1][1][0][0]], [3, 'e|f|g', root[0][0][1][2][0][0]], [3, 'i|j|k', root[0][0][3][1][0][0]], [3, 'l|m|n', root[0][0][3][2][0][0]], ].each do |test| alt_count, alt_text, exp = test assert_equal( Alternation, exp.class ) assert_equal( alt_text, exp.to_s ) assert_equal( alt_count, exp.alternatives.length ) end end def test_parse_conditional_extra_separator regexp = /(?a)(?()T|)/ root = RP.parse(regexp, 'ruby/2.0') branches = root[1].branches assert_equal( 2, branches.length ) seq_1, seq_2 = branches [seq_1, seq_2].each do |seq| assert( seq.is_a?( Sequence ), "Expected Condition, but got #{seq.class.name}") assert_equal( :expression, seq.type ) assert_equal( :sequence, seq.token ) end assert_equal( 'T', seq_1.to_s ) assert_equal( '', seq_2.to_s ) end # For source (text) expressions only, ruby raises an error otherwise. def test_parse_conditional_excessive_branches regexp = '(?a)(?()T|F|X)' assert_raise( Conditional::TooManyBranches ) { RP.parse(regexp, 'ruby/2.0') } end end