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.
752 lines
15 KiB
752 lines
15 KiB
#!/usr/bin/ruby
|
|
# encoding: utf-8
|
|
|
|
require 'antlr3/test/functional'
|
|
|
|
|
|
class TestHeterogeneousNodeTypes < ANTLR3::Test::Functional
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar VToken;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
}
|
|
a : ID<V> ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TokenWithQualifiedType;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
}
|
|
a : ID<TokenWithQualifiedType.Parser.V> ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TokenWithLabel;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
}
|
|
a : x=ID<V> ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TokenWithListLabel;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
}
|
|
a : x+=ID<V> ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TokenRoot;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : ID<V>^ ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TokenRootWithListLabel;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : x+=ID<V>^ ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar FromString;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : 'begin'<V> ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar StringRoot;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : 'begin'<V>^ ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar RewriteToken;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : ID -> ID<V> ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar RewriteTokenWithArgs;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def initialize(*args)
|
|
case args.length
|
|
when 4
|
|
ttype, @x, @y, @z = args
|
|
token = ANTLR3::CommonToken.new(ttype, nil, '')
|
|
when 3
|
|
ttype, token, @x = args
|
|
@y = @z = 0
|
|
else raise ArgumentError, "invalid number of arguments: #{args.length} for 3-4"
|
|
end
|
|
super(token)
|
|
end
|
|
|
|
def to_s
|
|
(@token.text.to_s rescue '') << "<V>;\%d\%d\%d" \% [@x, @y, @z]
|
|
end
|
|
end
|
|
|
|
}
|
|
a : ID -> ID<V>[42,19,30] ID<V>[$ID,99];
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar RewriteTokenRoot;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : ID INT -> ^(ID<V> INT) ;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar RewriteString;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : 'begin' -> 'begin'<V> ;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar RewriteStringRoot;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : 'begin' INT -> ^('begin'<V> INT) ;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar RewriteRuleResults;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
tokens {LIST;}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
class W < ANTLR3::CommonTree
|
|
def initialize(tok, text)
|
|
tok.text = text
|
|
super(tok)
|
|
end
|
|
def to_s
|
|
return @token.text + "<W>"
|
|
end
|
|
end
|
|
|
|
}
|
|
a : id (',' id)* -> ^(LIST<W>["LIST"] id+);
|
|
id : ID -> ID<V>;
|
|
ID : 'a'..'z'+ ;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar CopySemanticsWithHetero;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def dup_node
|
|
return V.new(self)
|
|
end
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
}
|
|
a : type ID (',' ID)* ';' -> ^(type ID)+;
|
|
type : 'int'<V> ;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+;
|
|
WS : (' '|'\\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TreeParserRewriteFlatList;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
a : ID INT;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
tree grammar TreeParserRewriteFlatListWalker;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
ASTLabelType=CommonTree;
|
|
tokenVocab=TreeParserRewriteFlatList;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
class W < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<W>"
|
|
end
|
|
end
|
|
}
|
|
a : ID INT -> INT<V> ID<W>
|
|
;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TreeParserRewriteTree;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
a : ID INT;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
tree grammar TreeParserRewriteTreeWalker;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
ASTLabelType=CommonTree;
|
|
tokenVocab=TreeParserRewriteTree;
|
|
}
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
|
|
class W < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<W>"
|
|
end
|
|
end
|
|
}
|
|
a : ID INT -> ^(INT<V> ID<W>)
|
|
;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TreeParserRewriteImaginary;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
a : ID ;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
tree grammar TreeParserRewriteImaginaryWalker;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
ASTLabelType=CommonTree;
|
|
tokenVocab=TreeParserRewriteImaginary;
|
|
}
|
|
tokens { ROOT; }
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.name + "<V>"
|
|
end
|
|
end
|
|
}
|
|
a : ID -> ROOT<V> ID
|
|
;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TreeParserRewriteImaginaryWithArgs;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
a : ID ;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
tree grammar TreeParserRewriteImaginaryWithArgsWalker;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
ASTLabelType=CommonTree;
|
|
tokenVocab=TreeParserRewriteImaginaryWithArgs;
|
|
}
|
|
tokens { ROOT; }
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def initialize(token_type, x)
|
|
super(token_type)
|
|
@x = x
|
|
end
|
|
def to_s
|
|
return @token.name + "<V>;#@x"
|
|
end
|
|
end
|
|
}
|
|
a : ID -> ROOT<V>[42] ID
|
|
;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TreeParserRewriteImaginaryRoot;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
a : ID ;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
tree grammar TreeParserRewriteImaginaryRootWalker;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
ASTLabelType=CommonTree;
|
|
tokenVocab=TreeParserRewriteImaginaryRoot;
|
|
}
|
|
tokens { ROOT; }
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.name + "<V>"
|
|
end
|
|
end
|
|
}
|
|
a : ID -> ^(ROOT<V> ID)
|
|
;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TreeParserRewriteImaginaryFromReal;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
a : ID ;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
tree grammar TreeParserRewriteImaginaryFromRealWalker;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
ASTLabelType=CommonTree;
|
|
tokenVocab=TreeParserRewriteImaginaryFromReal;
|
|
}
|
|
tokens { ROOT; }
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def initialize(token, tree = nil)
|
|
if tree.nil? then super(token)
|
|
else
|
|
super(tree)
|
|
@token = TokenData::Token.from_token(@token)
|
|
@token.type = token.type
|
|
end
|
|
end
|
|
def to_s
|
|
return @token.name + "<V>@" + @token.line.to_s
|
|
end
|
|
end
|
|
}
|
|
a : ID -> ROOT<V>[$ID]
|
|
;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
grammar TreeParserAutoHeteroAST;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
}
|
|
a : ID ';' ;
|
|
ID : 'a'..'z'+ ;
|
|
INT : '0'..'9'+;
|
|
WS : (' '|'\n') {$channel=HIDDEN;} ;
|
|
END
|
|
|
|
|
|
inline_grammar( <<-'END' )
|
|
tree grammar TreeParserAutoHeteroASTWalker;
|
|
options {
|
|
language=Ruby;
|
|
output=AST;
|
|
ASTLabelType=CommonTree;
|
|
tokenVocab=TreeParserAutoHeteroAST;
|
|
}
|
|
tokens { ROOT; }
|
|
@members {
|
|
class V < ANTLR3::CommonTree
|
|
def to_s
|
|
return @token.text + "<V>"
|
|
end
|
|
end
|
|
}
|
|
|
|
a : ID<V> ';'<V>;
|
|
END
|
|
|
|
def parse( grammar_name, grammar_rule, input )
|
|
grammar_module = self.class.const_get( grammar_name.to_s )
|
|
lexer = grammar_module::Lexer.new( input )
|
|
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
|
parser = grammar_module::Parser.new( tokens )
|
|
r = parser.send( grammar_rule )
|
|
|
|
return( r.tree.inspect rescue '' )
|
|
end
|
|
|
|
def tree_parse( grammar_name, grammar_rule, tree_grammar_rule, input )
|
|
grammar_module = self.class.const_get( grammar_name.to_s )
|
|
tree_grammar_module = self.class.const_get( grammar_name.to_s + 'Walker' )
|
|
|
|
lexer = grammar_module::Lexer.new( input )
|
|
tokens = ANTLR3::CommonTokenStream.new( lexer )
|
|
parser = grammar_module::Parser.new( tokens )
|
|
r = parser.send( grammar_rule )
|
|
|
|
nodes = ANTLR3::CommonTreeNodeStream.new( r.tree )
|
|
nodes.token_stream = tokens
|
|
tree_parser = tree_grammar_module::TreeParser.new( nodes )
|
|
r = tree_parser.send( tree_grammar_rule )
|
|
|
|
return( r.tree.inspect rescue '' )
|
|
end
|
|
|
|
example "v token" do
|
|
result = parse( :VToken, :a, 'a' )
|
|
result.should == 'a<V>'
|
|
end
|
|
|
|
|
|
example "token with qualified type" do
|
|
result = parse( :TokenWithQualifiedType, :a, 'a' )
|
|
result.should == 'a<V>'
|
|
end
|
|
|
|
|
|
example "token with label" do
|
|
result = parse( :TokenWithLabel, :a, 'a' )
|
|
result.should == 'a<V>'
|
|
end
|
|
|
|
|
|
example "token with list label" do
|
|
result = parse( :TokenWithListLabel, :a, 'a' )
|
|
result.should == 'a<V>'
|
|
end
|
|
|
|
|
|
example "token root" do
|
|
result = parse( :TokenRoot, :a, 'a' )
|
|
result.should == 'a<V>'
|
|
end
|
|
|
|
|
|
example "token root with list label" do
|
|
result = parse( :TokenRootWithListLabel, :a, 'a' )
|
|
result.should == 'a<V>'
|
|
end
|
|
|
|
|
|
example "string" do
|
|
result = parse( :FromString, :a, 'begin' )
|
|
result.should == 'begin<V>'
|
|
end
|
|
|
|
|
|
example "string root" do
|
|
result = parse( :StringRoot, :a, 'begin' )
|
|
result.should == 'begin<V>'
|
|
end
|
|
|
|
|
|
example "rewrite token" do
|
|
result = parse( :RewriteToken, :a, 'a' )
|
|
result.should == 'a<V>'
|
|
end
|
|
|
|
|
|
example "rewrite token with args" do
|
|
result = parse( :RewriteTokenWithArgs, :a, 'a' )
|
|
result.should == '<V>;421930 a<V>;9900'
|
|
end
|
|
|
|
|
|
example "rewrite token root" do
|
|
result = parse( :RewriteTokenRoot, :a, 'a 2' )
|
|
result.should == '(a<V> 2)'
|
|
end
|
|
|
|
|
|
example "rewrite string" do
|
|
result = parse( :RewriteString, :a, 'begin' )
|
|
result.should == 'begin<V>'
|
|
end
|
|
|
|
|
|
example "rewrite string root" do
|
|
result = parse( :RewriteStringRoot, :a, 'begin 2' )
|
|
result.should == '(begin<V> 2)'
|
|
end
|
|
|
|
|
|
example "rewrite rule results" do
|
|
result = parse( :RewriteRuleResults, :a, 'a,b,c' )
|
|
result.should == '(LIST<W> a<V> b<V> c<V>)'
|
|
end
|
|
|
|
|
|
example "copy semantics with hetero" do
|
|
result = parse( :CopySemanticsWithHetero, :a, 'int a, b, c;' )
|
|
result.should == '(int<V> a) (int<V> b) (int<V> c)'
|
|
end
|
|
|
|
|
|
example "tree parser rewrite flat list" do
|
|
result = tree_parse( :TreeParserRewriteFlatList, :a, :a, 'abc 34' )
|
|
result.should == '34<V> abc<W>'
|
|
end
|
|
|
|
|
|
example "tree parser rewrite tree" do
|
|
result = tree_parse( :TreeParserRewriteTree, :a, :a, 'abc 34' )
|
|
result.should == '(34<V> abc<W>)'
|
|
end
|
|
|
|
|
|
example "tree parser rewrite imaginary" do
|
|
result = tree_parse( :TreeParserRewriteImaginary, :a, :a, 'abc' )
|
|
result.should == 'ROOT<V> abc'
|
|
end
|
|
|
|
|
|
example "tree parser rewrite imaginary with args" do
|
|
result = tree_parse( :TreeParserRewriteImaginaryWithArgs, :a, :a, 'abc' )
|
|
result.should == 'ROOT<V>;42 abc'
|
|
end
|
|
|
|
|
|
example "tree parser rewrite imaginary root" do
|
|
result = tree_parse( :TreeParserRewriteImaginaryRoot, :a, :a, 'abc' )
|
|
result.should == '(ROOT<V> abc)'
|
|
end
|
|
|
|
|
|
example "tree parser rewrite imaginary from real" do
|
|
result = tree_parse( :TreeParserRewriteImaginaryFromReal, :a, :a, 'abc' )
|
|
result.should == 'ROOT<V>@1'
|
|
end
|
|
|
|
|
|
example "tree parser auto hetero ast" do
|
|
result = tree_parse( :TreeParserAutoHeteroAST, :a, :a, 'abc;' )
|
|
result.should == 'abc<V> ;<V>'
|
|
end
|
|
|
|
end
|