org.netbeans.api.languages.ASTNode Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.api.languages;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Represents one AST node.
*
* @author Jan Jancura
*/
public class ASTNode extends ASTItem {
/**
* Creates new ASTNode.
*
* @param mimeType MIME type
* @param nt right side of grammar rule
* @param rule rule id
* @param children list of tokens (ASTToken) and subnodes (ASTNode)
* @param offset start offset of this AST node
*
* @return returns new instance of AST node
*/
public static ASTNode createCompoundASTNode (
Language language,
String nt,
List children,
int offset
) {
return new CompoundNode (language, nt, offset, children);
}
/**
* Creates new ASTNode.
*
* @param mimeType MIME type
* @param nt right side of grammar rule
* @param rule rule id
* @param children list of tokens (ASTToken) and subnodes (ASTNode)
* @param offset start offset of this AST node
*
* @return returns new instance of AST node
*/
public static ASTNode create (
Language language,
String nt,
List children,
int offset
) {
return new ASTNode (language, nt, offset, children);
}
/**
* Creates new ASTNode.
*
* @param mimeType MIME type
* @param nt right side of grammar rule
* @param rule rule id
* @param offset start offset of this AST node
*
* @return returns new instance of AST node
*/
public static ASTNode create (
Language language,
String nt,
int offset
) {
return new ASTNode (language, nt, offset, Collections.emptyList ());
}
private String nt;
private ASTNode (
Language language,
String nt,
int offset,
List children
) {
super (language, offset, -1, children);
if ( (!getClass ().equals (ASTNode.class)) &&
(!getClass ().equals (CompoundNode.class))
) throw new IllegalArgumentException ("Do not extend ASTNode!");
this.nt = nt;
}
/**
* Returns the name of non terminal.
*
* @return name of non terminal
*/
public String getNT () {
return nt;
}
/**
* Finds path to the first token defined by type and identifier or null.
*
* @param type a type of token or null
* @param identifier a value of token or null
*
* @return path to the first token defined by type and identifier or null
*/
// public ASTPath findToken (String type, String identifier) {
// List path = new ArrayList ();
// findToken (type, identifier, path);
// if (path.isEmpty ()) return null;
// return ASTPath.create (path);
// }
//
// private boolean findToken (String type, String identifier, List path) {
// path.add (this);
// Iterator it = getChildren ().iterator ();
// while (it.hasNext ()) {
// Object e = it.next ();
// if (e instanceof ASTToken) {
// ASTToken t = (ASTToken) e;
// if (type != null && !type.equals (t.getType ())) continue;
// if (identifier != null && !identifier.equals (t.getIdentifier ())) continue;
// return true;
// } else
// if (((ASTNode) e).findToken (type, identifier, path))
// return true;
// }
// path.remove (path.size () - 1);
// return false;
// }
/**
* Returns top-most subnode of this node on given offset with given
* non terminal name.
*
* @param nt name of non terminal
* @param offset offset of node
*
* @return MIME top-most subnode of this node on given offset
* with given non terminal name
*/
public ASTNode findNode (String nt, int offset) {
if (nt.equals (getNT ())) return this;
Iterator it = getChildren ().iterator ();
while (it.hasNext ()) {
ASTItem e = it.next ();
if (e instanceof ASTNode) {
ASTNode node = (ASTNode) e;
if (node.getOffset () <= offset &&
offset < node.getEndOffset ()
)
return node.findNode (nt, offset);
}
}
return null;
}
/**
* Returns identifier of some subtoken with given type.
*
* @param type type of subtoken to be returned
*
* @return identifier of some subtoken with given type
*/
public String getTokenTypeIdentifier (String type) {
ASTToken token = getTokenType (type);
if (token == null) return null;
return token.getIdentifier ();
}
/**
* Returns some subtoken with given type.
*
* @param type type of subtoken to be returned
*
* @return some subtoken with given type
*/
public ASTToken getTokenType (String type) {
ASTNode node = this;
int i = type.lastIndexOf ('.');
if (i >= 0)
node = getNode (type.substring (0, i));
if (node == null) return null;
Object o = node.getChild ("token-type-" + type.substring (i + 1));
if (o == null) return null;
if (!(o instanceof ASTToken)) return null;
return (ASTToken) o;
}
/**
* Returns child node of this node with given path ("foo.goo.boo").
*
* @param path "foo.goo.boo" like path to some subnode
*
* @return child node of this node with given path
*/
public ASTNode getNode (String path) {
ASTNode node = this;
int s = 0, e = path.indexOf ('.');
while (e >= 0) {
node = (ASTNode) node.getChild ("node-" + path.substring (s, e));
if (node == null) return null;
s = e + 1;
e = path.indexOf ('.', s);
}
return (ASTNode) node.getChild ("node-" + path.substring (s));
}
/**
* Adds child to the end of list of children.
*
* @param item a child to be added
*/
@Override
public void addChildren (ASTItem item) {
super.addChildren (item);
if (nameToChild != null)
if (item instanceof ASTToken) {
ASTToken t = (ASTToken) item;
nameToChild.put ("token-type-" + t.getTypeName (), t);
} else {
nameToChild.put (
"node-" + ((ASTNode) item).getNT (),
item
);
}
}
/**
* Removes child.
*
* @param item a child to be added
*/
@Override
public void removeChildren (ASTItem item) {
super.removeChildren (item);
if (nameToChild != null)
if (item instanceof ASTToken) {
ASTToken t = (ASTToken) item;
nameToChild.remove ("token-type-" + t.getTypeName ());
} else {
nameToChild.remove (
"node-" + ((ASTNode) item).getNT ()
);
}
}
/**
* Removes child.
*
* @param item a child to be added
*/
@Override
public void setChildren (int index, ASTItem item) {
ASTItem old = getChildren ().get (index);
if (nameToChild != null)
if (old instanceof ASTToken) {
ASTToken t = (ASTToken) old;
nameToChild.remove ("token-type-" + t.getTypeName ());
} else {
nameToChild.remove (
"node-" + ((ASTNode) old).getNT ()
);
}
super.setChildren (index, item);
if (nameToChild != null)
if (item instanceof ASTToken) {
ASTToken t = (ASTToken) item;
nameToChild.put ("token-type-" + t.getTypeName (), item);
} else {
nameToChild.put (
"node-" + ((ASTNode) item).getNT (),
item
);
}
}
private Map nameToChild = null;
private Object getChild (String name) {
if (nameToChild == null) {
nameToChild = new HashMap ();
Iterator it = getChildren ().iterator ();
while (it.hasNext ()) {
ASTItem item = it.next ();
if (item instanceof ASTToken) {
ASTToken t = (ASTToken) item;
nameToChild.put ("token-type-" + t.getTypeName (), t);
} else {
nameToChild.put (
"node-" + ((ASTNode) item).getNT (),
item
);
}
}
}
return nameToChild.get (name);
}
/**
* Returns text representation of this node.
*
* @return text representation of this node
*/
public String print () {
return print ("");
}
private String print (String indent) {
StringBuilder sb = new StringBuilder ();
sb.append (indent).append ("ASTNode ").append (getNT ()).append (' ').
append (getOffset ()).append ('-').append (getEndOffset ());
indent = " " + indent;
Iterator it = getChildren ().iterator ();
while (it.hasNext ()) {
Object elem = it.next ();
if (elem instanceof ASTNode) {
sb.append ('\n').append (((ASTNode) elem).print (indent));
} else
sb.append ('\n').append (indent).append (elem);
}
return sb.toString ();
}
/**
* Returns text content of this node.
*
* @return text content of this node
*/
public String getAsText () {
StringBuilder sb = new StringBuilder ();
Iterator it = getChildren ().iterator ();
while (it.hasNext ()) {
Object elem = it.next ();
if (elem instanceof ASTNode)
sb.append (((ASTNode) elem).getAsText ());
else
sb.append (((ASTToken) elem).getIdentifier ());
}
return sb.toString ();
}
/**
* Returns string representation of this object.
*
* @return string representation of this object
*/
@Override
public String toString () {
StringBuilder sb = new StringBuilder ();
sb.append ("ASTNode ").append (getNT ()).append (' ').
append (getOffset ()).append ('-').append (getEndOffset ());
Iterator it = getChildren ().iterator ();
while (it.hasNext ()) {
Object elem = it.next ();
if (elem instanceof ASTNode)
sb.append ("\n ").append (((ASTNode) elem).getNT () + "...");
else
sb.append ("\n ").append (elem);
}
return sb.toString ();
}
// innerclasses ............................................................
private static final class CompoundNode extends ASTNode {
CompoundNode (Language language, String nt, int offset, List children) {
super (language, nt, offset, children);
}
/**
* Returns path from this item to the item on given offset.
*
* @param offset offset
*
* @return path from this item to the item on given offset
*/
@Override
public ASTPath findPath (int offset) {
ASTPath result = null;
Iterator it = getChildren ().iterator ();
while (it.hasNext ()) {
ASTItem item = it.next ();
if (offset < item.getEndOffset () &&
item.getOffset () <= offset
) {
List p = new ArrayList ();
p.add (this);
ASTPath path = item.findPath (p, offset);
if (result == null ||
path.getLeaf ().getLength () < result.getLeaf ().getLength ()
)
result = path;
}
}
if (result == null)
result = ASTPath.create (this);
return result;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy