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, '(?' assert_equal exp.reference, 'A' 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, '()' assert_equal exp.reference, 'A' end def test_parse_conditional_condition_with_number_ref regexp = /(a)(?(1)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, '(1)' assert_equal exp.reference, 1 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 all_captures = alt.all? do |exp| exp.first.is_a?(Group::Capture) end assert_equal true, all_captures 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(d)(e))))(?(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 def test_parse_conditional_quantified regexp = /(foo)(?(1)\d|(\w)){42}/ root = RP.parse(regexp, 'ruby/2.0') conditional = root[1] assert conditional.quantified? assert_equal '{42}', conditional.quantifier.text assert_equal '(?(1)\d|(\w)){42}', conditional.to_s refute conditional.branches.any?(&:quantified?) end def test_parse_conditional_branch_content_quantified regexp = /(foo)(?(1)\d{23}|(\w){42})/ root = RP.parse(regexp, 'ruby/2.0') conditional = root[1] refute conditional.quantified? refute conditional.branches.any?(&:quantified?) assert conditional.branches[0][0].quantified? assert_equal '{23}', conditional.branches[0][0].quantifier.text assert conditional.branches[1][0].quantified? assert_equal '{42}', conditional.branches[1][0].quantifier.text 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