You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
495 lines
12 KiB
495 lines
12 KiB
#!/usr/bin/ruby
|
|
# encoding: utf-8
|
|
|
|
require 'antlr3'
|
|
require 'antlr3/tree/wizard'
|
|
require 'test/unit'
|
|
require 'spec'
|
|
|
|
include ANTLR3
|
|
include ANTLR3::AST
|
|
|
|
class TestPatternLexer < Test::Unit::TestCase
|
|
|
|
# vvvvvvvv tests vvvvvvvvv
|
|
|
|
def test_open
|
|
lexer = Wizard::PatternLexer.new( '(' )
|
|
type = lexer.next_token
|
|
assert_equal( type, :open )
|
|
assert_equal( lexer.text, '' )
|
|
assert_equal( lexer.error, false )
|
|
end
|
|
|
|
def test_close
|
|
lexer = Wizard::PatternLexer.new(')')
|
|
type = lexer.next_token
|
|
assert_equal(type, :close)
|
|
assert_equal(lexer.text, '')
|
|
assert_equal(lexer.error, false)
|
|
end
|
|
|
|
def test_percent
|
|
lexer = Wizard::PatternLexer.new('%')
|
|
type = lexer.next_token
|
|
assert_equal(type, :percent)
|
|
assert_equal(lexer.text, '')
|
|
assert_equal(lexer.error, false)
|
|
end
|
|
|
|
def test_dot
|
|
lexer = Wizard::PatternLexer.new('.')
|
|
type = lexer.next_token
|
|
assert_equal(type, :dot)
|
|
assert_equal(lexer.text, '')
|
|
assert_equal(lexer.error, false)
|
|
end
|
|
|
|
def test_eof
|
|
lexer = Wizard::PatternLexer.new(" \n \r \t ")
|
|
type = lexer.next_token
|
|
assert_equal(type, EOF)
|
|
assert_equal(lexer.text, '')
|
|
assert_equal(lexer.error, false)
|
|
end
|
|
|
|
def test_id
|
|
lexer = Wizard::PatternLexer.new('__whatever_1__')
|
|
type = lexer.next_token
|
|
assert_equal(:identifier, type)
|
|
assert_equal('__whatever_1__', lexer.text)
|
|
assert( !(lexer.error) )
|
|
end
|
|
|
|
def test_arg
|
|
lexer = Wizard::PatternLexer.new('[ \]bla\n]')
|
|
type = lexer.next_token
|
|
assert_equal(type, :argument)
|
|
assert_equal(' ]bla\n', lexer.text)
|
|
assert( !(lexer.error) )
|
|
end
|
|
|
|
def test_error
|
|
lexer = Wizard::PatternLexer.new("1")
|
|
type = lexer.next_token
|
|
assert_equal(type, EOF)
|
|
assert_equal(lexer.text, '')
|
|
assert_equal(lexer.error, true)
|
|
end
|
|
|
|
end
|
|
|
|
|
|
class TestPatternParser < Test::Unit::TestCase
|
|
Tokens = TokenScheme.build %w(A B C D E ID VAR)
|
|
include Tokens
|
|
|
|
def setup
|
|
@adaptor = CommonTreeAdaptor.new( Tokens.token_class )
|
|
@pattern_adaptor = Wizard::PatternAdaptor.new( Tokens.token_class )
|
|
@wizard = Wizard.new( :adaptor => @adaptor, :token_scheme => Tokens )
|
|
end
|
|
|
|
# vvvvvvvv tests vvvvvvvvv
|
|
def test_single_node
|
|
tree = Wizard::PatternParser.parse( 'ID', Tokens, @adaptor )
|
|
|
|
assert_instance_of(CommonTree, tree)
|
|
assert_equal( ID, tree.type )
|
|
assert_equal( 'ID', tree.text )
|
|
end
|
|
|
|
def test_single_node_with_arg
|
|
tree = Wizard::PatternParser.parse( 'ID[foo]', Tokens, @adaptor )
|
|
|
|
assert_instance_of( CommonTree, tree )
|
|
assert_equal( ID, tree.type )
|
|
assert_equal( 'foo', tree.text )
|
|
end
|
|
|
|
def test_single_level_tree
|
|
tree = Wizard::PatternParser.parse( '(A B)', Tokens, @adaptor )
|
|
|
|
assert_instance_of( CommonTree, tree )
|
|
assert_equal(A, tree.type)
|
|
assert_equal('A', tree.text)
|
|
assert_equal(tree.child_count, 1)
|
|
assert_equal(tree.child(0).type, B)
|
|
assert_equal(tree.child(0).text, 'B')
|
|
end
|
|
|
|
def test_nil
|
|
tree = Wizard::PatternParser.parse( 'nil', Tokens, @adaptor )
|
|
|
|
assert_instance_of(CommonTree, tree)
|
|
assert_equal(0, tree.type)
|
|
assert_nil tree.text
|
|
end
|
|
|
|
def test_wildcard
|
|
tree = Wizard::PatternParser.parse( '(.)', Tokens, @adaptor )
|
|
assert_instance_of( Wizard::WildcardPattern, tree )
|
|
end
|
|
|
|
def test_label
|
|
tree = Wizard::PatternParser.parse( '(%a:A)', Tokens, @pattern_adaptor )
|
|
assert_instance_of(Wizard::Pattern, tree)
|
|
assert_equal('a', tree.label)
|
|
end
|
|
|
|
def test_error_1
|
|
tree = Wizard::PatternParser.parse( ')', Tokens, @adaptor )
|
|
assert_nil tree
|
|
end
|
|
|
|
def test_error_2
|
|
tree = Wizard::PatternParser.parse( '()', Tokens, @adaptor )
|
|
assert_nil tree
|
|
end
|
|
|
|
def test_error_3
|
|
tree = Wizard::PatternParser.parse( '(A ])', Tokens, @adaptor )
|
|
assert_nil tree
|
|
end
|
|
|
|
end
|
|
|
|
|
|
class TestTreeWizard < Test::Unit::TestCase
|
|
Tokens = TokenScheme.build %w(A B C D E ID VAR)
|
|
include Tokens
|
|
|
|
def setup
|
|
@adaptor = CommonTreeAdaptor.new( Tokens.token_class )
|
|
@wizard = Wizard.new( :adaptor => @adaptor, :token_scheme => Tokens )
|
|
end
|
|
|
|
def create_wizard( tokens )
|
|
Wizard.new( :tokens => tokens )
|
|
end
|
|
|
|
# vvvvvvvv tests vvvvvvvvv
|
|
def test_init
|
|
@wizard = Wizard.new( :tokens => %w(A B), :adaptor => @adaptor )
|
|
|
|
assert_equal( @wizard.adaptor, @adaptor )
|
|
assert_kind_of( ANTLR3::TokenScheme, @wizard.token_scheme )
|
|
end
|
|
|
|
def test_single_node
|
|
t = @wizard.create("ID")
|
|
assert_equal(t.inspect, 'ID')
|
|
end
|
|
|
|
def test_single_node_with_arg
|
|
t = @wizard.create("ID[foo]")
|
|
|
|
assert_equal(t.inspect, 'foo')
|
|
end
|
|
|
|
def test_single_node_tree
|
|
t = @wizard.create("(A)")
|
|
assert_equal(t.inspect, 'A')
|
|
end
|
|
|
|
def test_single_level_tree
|
|
t = @wizard.create("(A B C D)")
|
|
assert_equal(t.inspect, '(A B C D)')
|
|
end
|
|
|
|
def test_list_tree
|
|
t = @wizard.create("(nil A B C)")
|
|
assert_equal(t.inspect, 'A B C')
|
|
end
|
|
|
|
def test_invalid_list_tree
|
|
t = @wizard.create("A B C")
|
|
assert_nil t
|
|
end
|
|
|
|
def test_double_level_tree
|
|
t = @wizard.create("(A (B C) (B D) E)")
|
|
assert_equal(t.inspect, "(A (B C) (B D) E)")
|
|
end
|
|
|
|
SIMPLIFY_MAP = lambda do |imap|
|
|
Hash[
|
|
imap.map { |type, nodes| [type, nodes.map { |n| n.to_s }] }
|
|
]
|
|
end
|
|
|
|
def test_single_node_index
|
|
tree = @wizard.create("ID")
|
|
index_map = SIMPLIFY_MAP[@wizard.index(tree)]
|
|
|
|
assert_equal(index_map, ID => %w(ID))
|
|
end
|
|
|
|
|
|
def test_no_repeats_index
|
|
tree = @wizard.create("(A B C D)")
|
|
index_map = SIMPLIFY_MAP[@wizard.index(tree)]
|
|
|
|
assert_equal(index_map,
|
|
D => %w(D), B => %w(B),
|
|
C => %w(C), A => %w(A)
|
|
)
|
|
end
|
|
|
|
def test_repeats_index
|
|
tree = @wizard.create("(A B (A C B) B D D)")
|
|
index_map = SIMPLIFY_MAP[@wizard.index(tree)]
|
|
|
|
assert_equal(index_map,
|
|
D => %w(D D), B => %w(B B B),
|
|
C => %w(C), A => %w(A A)
|
|
)
|
|
end
|
|
|
|
|
|
def test_no_repeats_visit
|
|
tree = @wizard.create("(A B C D)")
|
|
|
|
elements = []
|
|
@wizard.visit( tree, B ) do |node, parent, child_index, labels|
|
|
elements << node.to_s
|
|
end
|
|
|
|
assert_equal( %w(B), elements )
|
|
end
|
|
|
|
|
|
def test_no_repeats_visit2
|
|
tree = @wizard.create("(A B (A C B) B D D)")
|
|
|
|
elements = []
|
|
@wizard.visit( tree, C ) do |node, parent, child_index, labels|
|
|
elements << node.to_s
|
|
end
|
|
|
|
assert_equal(%w(C), elements)
|
|
end
|
|
|
|
|
|
def test_repeats_visit
|
|
tree = @wizard.create("(A B (A C B) B D D)")
|
|
|
|
elements = []
|
|
@wizard.visit( tree, B ) do |node, parent, child_index, labels|
|
|
elements << node.to_s
|
|
end
|
|
|
|
assert_equal(%w(B B B), elements)
|
|
end
|
|
|
|
|
|
def test_repeats_visit2
|
|
tree = @wizard.create("(A B (A C B) B D D)")
|
|
|
|
elements = []
|
|
@wizard.visit( tree, A ) do |node, parent, child_index, labels|
|
|
elements << node.to_s
|
|
end
|
|
|
|
assert_equal(%w(A A), elements)
|
|
end
|
|
|
|
def context(node, parent, index)
|
|
'%s@%s[%d]' % [node.to_s, (parent || 'nil').to_s, index]
|
|
end
|
|
|
|
def test_repeats_visit_with_context
|
|
tree = @wizard.create("(A B (A C B) B D D)")
|
|
|
|
elements = []
|
|
@wizard.visit( tree, B ) do |node, parent, child_index, labels|
|
|
elements << context(node, parent, child_index)
|
|
end
|
|
|
|
assert_equal(['B@A[0]', 'B@A[1]', 'B@A[2]'], elements)
|
|
end
|
|
|
|
|
|
def test_repeats_visit_with_null_parent_and_context
|
|
tree = @wizard.create("(A B (A C B) B D D)")
|
|
|
|
elements = []
|
|
@wizard.visit( tree, A ) do |node, parent, child_index, labels|
|
|
elements << context(node, parent, child_index)
|
|
end
|
|
|
|
assert_equal(['A@nil[-1]', 'A@A[1]'], elements)
|
|
end
|
|
|
|
def test_visit_pattern
|
|
tree = @wizard.create("(A B C (A B) D)")
|
|
|
|
elements = []
|
|
@wizard.visit(tree, '(A B)') do |node, parent, child_index, labels|
|
|
elements << node.to_s
|
|
end
|
|
|
|
assert_equal(%w(A), elements)
|
|
end
|
|
|
|
|
|
def test_visit_pattern_multiple
|
|
tree = @wizard.create("(A B C (A B) (D (A B)))")
|
|
|
|
elements = []
|
|
@wizard.visit(tree, '(A B)') do |node, parent, child_index, labels|
|
|
elements << context(node, parent, child_index)
|
|
end
|
|
|
|
assert_equal( %w(A@A[2] A@D[0]) , elements )
|
|
end
|
|
|
|
def labeled_context(node, parent, index, labels, *names)
|
|
suffix = names.map { |n| labels[n].to_s }.join('&')
|
|
'%s@%s[%d]%s' % [node.to_s, (parent || 'nil').to_s, index, suffix]
|
|
end
|
|
|
|
def test_visit_pattern_multiple_with_labels
|
|
tree = @wizard.create("(A B C (A[foo] B[bar]) (D (A[big] B[dog])))")
|
|
|
|
elements = []
|
|
@wizard.visit(tree, '(%a:A %b:B)') do |node, parent, child_index, labels|
|
|
elements << labeled_context(node, parent, child_index, labels, 'a', 'b')
|
|
end
|
|
|
|
assert_equal( ['foo@A[2]foo&bar', 'big@D[0]big&dog'] , elements )
|
|
end
|
|
|
|
|
|
def test_match
|
|
tree = @wizard.create("(A B C)")
|
|
assert @wizard.match(tree, "(A B C)")
|
|
end
|
|
|
|
def test_match_single_node
|
|
tree = @wizard.create('A')
|
|
assert @wizard.match(tree, 'A')
|
|
end
|
|
|
|
def test_match_single_node_fails
|
|
tree = @wizard.create('A')
|
|
assert( !(@wizard.match(tree, 'B')) )
|
|
end
|
|
|
|
|
|
def test_match_flat_tree
|
|
tree = @wizard.create('(nil A B C)')
|
|
assert @wizard.match(tree, '(nil A B C)')
|
|
end
|
|
|
|
def test_match_flat_tree_fails
|
|
tree = @wizard.create('(nil A B C)')
|
|
assert( !(@wizard.match(tree, '(nil A B)')) )
|
|
end
|
|
|
|
def test_match_flat_tree_fails2
|
|
tree = @wizard.create('(nil A B C)')
|
|
assert( !(@wizard.match(tree, '(nil A B A)')) )
|
|
end
|
|
|
|
def test_wildcard
|
|
tree = @wizard.create('(A B C)')
|
|
assert @wizard.match(tree, '(A . .)')
|
|
end
|
|
|
|
def test_match_with_text
|
|
tree = @wizard.create('(A B[foo] C[bar])')
|
|
assert @wizard.match(tree, '(A B[foo] C)')
|
|
end
|
|
|
|
def test_match_with_text_fails
|
|
tree = @wizard.create('(A B C)')
|
|
assert( !(@wizard.match(tree, '(A[foo] B C)')) )
|
|
end
|
|
|
|
def test_match_labels
|
|
tree = @wizard.create('(A B C)')
|
|
labels = @wizard.match( tree, '(%a:A %b:B %c:C)' )
|
|
|
|
assert_equal('A', labels['a'].to_s)
|
|
assert_equal('B', labels['b'].to_s)
|
|
assert_equal('C', labels['c'].to_s)
|
|
end
|
|
|
|
def test_match_with_wildcard_labels
|
|
tree = @wizard.create('(A B C)')
|
|
labels = @wizard.match(tree, '(A %b:. %c:.)')
|
|
assert_kind_of( Hash, labels )
|
|
assert_equal('B', labels['b'].to_s)
|
|
assert_equal('C', labels['c'].to_s)
|
|
end
|
|
|
|
|
|
def test_match_labels_and_test_text
|
|
tree = @wizard.create('(A B[foo] C)')
|
|
labels = @wizard.match( tree, '(%a:A %b:B[foo] %c:C)' )
|
|
assert_kind_of( Hash, labels )
|
|
assert_equal('A', labels['a'].to_s)
|
|
assert_equal('foo', labels['b'].to_s)
|
|
assert_equal('C', labels['c'].to_s)
|
|
end
|
|
|
|
def test_match_labels_in_nested_tree
|
|
tree = @wizard.create('(A (B C) (D E))')
|
|
labels = @wizard.match( tree, '(%a:A (%b:B %c:C) (%d:D %e:E))' )
|
|
assert_kind_of( Hash, labels )
|
|
assert_equal('A', labels['a'].to_s)
|
|
assert_equal('B', labels['b'].to_s)
|
|
assert_equal('C', labels['c'].to_s)
|
|
assert_equal('D', labels['d'].to_s)
|
|
assert_equal('E', labels['e'].to_s)
|
|
end
|
|
|
|
|
|
def test_equals
|
|
tree1 = @wizard.create("(A B C)")
|
|
tree2 = @wizard.create("(A B C)")
|
|
assert @wizard.equals(tree1, tree2)
|
|
end
|
|
|
|
|
|
def test_equals_with_text
|
|
tree1 = @wizard.create("(A B[foo] C)")
|
|
tree2 = @wizard.create("(A B[foo] C)")
|
|
assert @wizard.equals(tree1, tree2)
|
|
end
|
|
|
|
|
|
def test_equals_with_mismatched_text
|
|
tree1 = @wizard.create("(A B[foo] C)")
|
|
tree2 = @wizard.create("(A B C)")
|
|
assert( !(@wizard.equals(tree1, tree2)) )
|
|
end
|
|
|
|
|
|
def test_equals_with_mismatched_list
|
|
tree1 = @wizard.create("(A B C)")
|
|
tree2 = @wizard.create("(A B A)")
|
|
assert( !(@wizard.equals(tree1, tree2)) )
|
|
end
|
|
|
|
def test_equals_with_mismatched_list_length
|
|
tree1 = @wizard.create("(A B C)")
|
|
tree2 = @wizard.create("(A B)")
|
|
assert( !(@wizard.equals(tree1, tree2)) )
|
|
end
|
|
|
|
def test_find_pattern
|
|
tree = @wizard.create("(A B C (A[foo] B[bar]) (D (A[big] B[dog])))")
|
|
subtrees = @wizard.find(tree, "(A B)").map { |t| t.to_s }
|
|
assert_equal(%w(foo big), subtrees)
|
|
end
|
|
|
|
def test_find_token_type
|
|
tree = @wizard.create("(A B C (A[foo] B[bar]) (D (A[big] B[dog])))")
|
|
subtrees = @wizard.find( tree, A ).map { |t| t.to_s }
|
|
assert_equal(%w(A foo big), subtrees)
|
|
end
|
|
end
|
|
|