io.deephaven.lang.generated.Node Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of deephaven-open-api-lang-parser Show documentation
Show all versions of deephaven-open-api-lang-parser Show documentation
The 'open-api-lang-parser' project
/* Generated By:JJTree: Do not edit this line. Node.java Version 7.0 */
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=Chunker,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package io.deephaven.lang.generated;
/* All AST nodes must implement this interface. It provides basic
machinery for constructing the parent and child relationships
between nodes. */
import io.deephaven.lang.api.IsScope;
import io.deephaven.lang.parse.LspTools;
import io.deephaven.proto.backplane.script.grpc.DocumentRange;
import io.deephaven.proto.backplane.script.grpc.Position;
import io.deephaven.proto.backplane.script.grpc.PositionOrBuilder;
import io.deephaven.web.shared.fu.LinkedIterable;
import java.util.List;
import static java.util.Collections.singletonList;
public interface Node {
/** This method is called after the node has been made the current
node. It indicates that child nodes can now be added to it. */
void jjtOpen();
/** This method is called after all the child nodes have been
added. */
void jjtClose();
/** This pair of methods are used to inform the node of its
parent. */
void jjtSetParent(Node n);
Node jjtGetParent();
/** This method tells the node to add its argument to the node's
list of children. */
void jjtAddChild(Node n, int i);
/** This method inserts the specified node at the given index, shifting any existing items to the right. */
void jjtInsertChild(Node n, int i);
/** This method returns a child node. The children are numbered
from zero, left to right. */
Node jjtGetChild(int i);
/** Return the number of children the node has. */
int jjtGetNumChildren();
int getId();
Token jjtGetFirstToken();
void jjtSetFirstToken(Token token);
Token jjtGetLastToken();
void jjtSetLastToken(Token token);
default LinkedIterable tokens(boolean strict) {
return new LinkedIterable<>(jjtGetFirstToken(), jjtGetLastToken(), true, strict, Token::next);
}
default LinkedIterable tokensReversed(boolean strict) {
return new LinkedIterable<>(jjtGetLastToken(), jjtGetFirstToken(), true, strict, Token::prev);
}
default void addToken(Token token) {
addToken(token, null);
}
void addToken(Token token, Node anchor);
default Node rescope(List scope) {
if (scope != null) {
addScope(scope);
}
return this;
}
default void setScope(List scope) {
throw new UnsupportedOperationException(getClass() + " does not support scope!");
}
/** Accept the visitor. **/
Object jjtAccept(ChunkerVisitor visitor, Object data);
void adopt(Node node);
default boolean containsIndex(int i) {
return getStartIndex() <= i &&
getEndIndex() > i;
}
default boolean isChildOf(Node best) {
for (Node parent : new LinkedIterable<>(Node.this, Node::jjtGetParent)) {
if (parent == best) {
return true;
}
}
return false;
}
Token addJunk(Token junk);
default String toSource() {
// Return exactly to the original source;
// we turn all tokens into nodes, including whitespace,
// so this should be a 1:1 mapping of original source.
// When we perform autocompletion, we may want to adjust some values,
// like "strings " + " that are appended" into a single entity, w/ adjusted cursor,
// ...though that likely won't happen until we run out of more useful things to do.
StringBuilder b = new StringBuilder();
Token next = jjtGetFirstToken();
while (next != jjtGetLastToken()) {
append(b, next);
if (next == next.next) {
break;
}
next = next.next;
}
append(b, next);
return b.toString();
}
default /*private*/ void append(StringBuilder b, Token tok) {
if (tok.specialToken != null) {
append(b, tok.specialToken);
}
b.append(tok.image);
}
default int getEndIndex() {
final Token lastToken = jjtGetLastToken();
if (lastToken.kind == ChunkerConstants.EOF) {
// document ended with a comment; use said comment as the end index.
return lastToken.getEndIndex() + lastToken.specialTokenLength();
}
return lastToken.getEndIndex();
}
default int getStartIndex() {
Token firstToken = jjtGetFirstToken();
int ind = firstToken.getStartIndex();
return ind;
}
List getChildren();
/**
* Overridden manually for nodes who can "have a cursor on them" with respect to autocomplete.
*
* If any part of an ast node collects tokens that are "leaf nodes" (i.e. there are cursor positions
* where your ast node will be the most derived child found), then it is a candidate to be a terminal autocomplete source.
*
* When encountering whitespace or . or , we might search left or right for interesting nodes,
* and those ast nodes who are autocomplete terminal will be preferred over their children.
*
* The normal search algorithm is a standard binary tree search, where the next-leftmost|rightmost leaf node is transversed.
* When an `isAutocompleteTerminal() == true` node is found, however, we stop there to continue searches.
*
* @return true for nodes that the visitor in ChunkerCompleter will visit and generate results.
*
* This is not needed for always-terminal nodes, like ChunkerNum or ChunkerIdent, but is needed by terminal-nodes-with-children,
* like ChunkerInvoke or ChunkerNew.
*
*/
default boolean isAutocompleteTerminal() {
return false;
}
boolean isWellFormed();
default void addChild(Node child) {
if (jjtGetFirstToken() == null) {
jjtSetFirstToken(child.jjtGetFirstToken());
}
addChild(child, jjtGetNumChildren());
}
default void addChild(Node child, int index) {
child.maybeDetach();
child.jjtSetParent(this);
jjtAddChild(child, index);
}
default void insertChild(Node child, int index) {
child.maybeDetach();
child.jjtSetParent(this);
jjtInsertChild(child, index);
if (index == 0) {
jjtSetFirstToken(child.jjtGetFirstToken());
} else if (index == jjtGetNumChildren()) {
jjtSetLastToken(child.jjtGetLastToken());
}
}
default void addScope(IsScope scope) {
addScope(singletonList(scope));
}
default void addScope(List scope) {
// no need to do anything _right now_,
// but in a future refactor, we will need to make
// existing scope handling accept more than ChunkerIdent,
// so we can use a generic source node as a scope
// (e.g: `thing[1] = 2` has an array access scope, not an ident.
throw new UnsupportedOperationException(getClass() +" must implement addScope(List)");
}
default void maybeDetach() {
final Node parent = jjtGetParent();
if (parent != null) {
parent.removeChild(this);
}
}
void removeChild(Node node);
int indexOf(Node node);
default DocumentRange.Builder asRange() {
return DocumentRange.newBuilder()
.setStart(jjtGetFirstToken().positionStart())
.setEnd(jjtGetLastToken().positionEnd());
}
default boolean containsLines(int winStartLine, int winEndLine) {
return jjtGetLastToken().endLine >= winEndLine && jjtGetFirstToken().beginLine <= winStartLine;
}
default boolean contains(Position pos) {
final Position.Builder startPos = jjtGetFirstToken().positionStart();
if (LspTools.greaterThan(startPos, pos)) {
// if we start after this position, we don't contain it
return false;
}
// we start before or after the query pos
final Position.Builder endPos = jjtGetLastToken().positionEnd();
// we contain the position if we also end after it.
return LspTools.greaterOrEqual(endPos, pos);
}
default Token findToken(PositionOrBuilder requested) {
final Position.Builder start = jjtGetFirstToken().positionStart();
Token candidate = null;
if (LspTools.lessOrEqual(start, requested)) {
final Position.Builder end = jjtGetLastToken().positionEnd();
if (LspTools.greaterOrEqual(end, requested)) {
// we contain the position, iterate our own tokens to pick a winner.
for (Token token : tokens(true)) {
if (token.containsPosition(requested)) {
candidate = token;
} else if (candidate != null) {
return candidate;
}
}
} else {
// the position is after our end.
for (Token token : jjtGetLastToken().to(null)) {
if (token.containsPosition(requested)) {
candidate = token;
} else if (candidate != null){
return candidate;
}
assert LspTools.lessThan(token.positionStart(), requested) : "Could not find " + requested + " after " + jjtGetLastToken();
}
}
} else {
// we start after requested, look backwards
for (Token token : jjtGetFirstToken().toReverse(null)) {
if (token.containsPosition(requested)) {
candidate = token;
continue;
} else if (candidate != null) {
return candidate;
}
assert LspTools.greaterThan(token.positionEnd(), requested) : "Could not find " + requested + " before " + jjtGetFirstToken();
}
}
if (candidate == null) {
throw new IllegalArgumentException("Cannot find " + requested + " from " + this);
}
return candidate;
}
default int distanceTo(int offset) {
int start = Math.abs(jjtGetFirstToken().startIndex - offset);
int end = Math.abs(jjtGetLastToken().endIndex - offset);
return Math.min(start, end);
}
}
/* JavaCC - OriginalChecksum=8bee7910cdc54c0d060ca939cc170eb0 (do not edit this line) */