/*
* Copyright (C) 2011 Laurent Caillette
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.novelang.parser.antlr;
import java.util.List;
import com.google.common.collect.Lists;
import org.antlr.runtime.tree.Tree;
import org.novelang.common.Location;
import org.novelang.common.SimpleTree;
import org.novelang.common.SyntacticTree;
import org.novelang.parser.NodeKind;
/**
* Converts a {@link org.antlr.runtime.tree.Tree} into a {@link org.novelang.common.SyntacticTree}.
* This helps using lighter objects than those created by ANTLR, which keep a backpointer
* to the parent tree.
*
* @author Laurent Caillette
*/
public class TreeConverter {
private TreeConverter() {}
public static SyntacticTree convert(
final Tree antlrTree,
final TokenNameProvider tokenNameProvider
) {
final String originalText = antlrTree.getText() ;
final String treeText ;
final NodeKind treeKind ;
final Location location ;
final String childText ;
final List< SyntacticTree > children ;
if( antlrTree instanceof CustomTree ) { // Need to check because of ANTLR error nodes.
final CustomTree customTree = ( CustomTree ) antlrTree ;
childText = customTree.getChildText() ;
location = customTree.getLocation() ;
} else {
childText = null ;
location = null ;
}
if( antlrTree.getChildCount() > 0 ) {
children = Lists.newArrayList() ;
if( childText != null ) {
children.add( new SimpleTree( childText ) ) ;
}
for( int childIndex = 0 ; childIndex < antlrTree.getChildCount() ; childIndex ++ ) {
children.add( convert( antlrTree.getChild( childIndex ), tokenNameProvider ) ) ;
}
} else if( childText == null ) {
children = null ;
} else {
children = Lists.newArrayList() ;
children.add( new SimpleTree( childText ) ) ;
}
if( antlrTree.getType() >= 0 && antlrTree instanceof CustomTree ) {
treeText = null ;
treeKind = NodeKind.valueOf( tokenNameProvider.getTokenName( antlrTree.getType() ) ) ;
} else {
treeText = originalText ;
treeKind = null ;
}
// TODO pool punctuation signs and whitespaces.
if( children == null ) {
return treeKind == null ?
new SimpleTree( treeText, location ) :
new SimpleTree( treeKind, location )
;
} else {
return treeKind == null ?
new SimpleTree( treeText, location, children ) :
new SimpleTree( treeKind, location, children )
;
}
}
}