blob: 928c14fe638917370893e2e1c5a48fcc973a6048 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.intellij.schema.utils;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.tree.IElementType;
import java.util.Arrays;
import java.util.stream.Collectors;
/** A collection of tokens with a current index. */
public class Tokens {
private final ASTNode[] nodes;
private int i = 0;
private Tokens(PsiElement element) {
nodes = element.getNode().getChildren(null);
}
/**
* Advances to the next token, if it is of the given type.
*
* @return true if the current token was of the given type and we advanced it, false
* if it was not and nothing was changed
*/
public boolean skip(IElementType... tokenTypes) {
if (current() == null) return false;
boolean is = is(tokenTypes);
if (is)
i++;
return is;
}
/**
* Advances beyond the next token, if it is whitespace.
*
* @return true if the current token was of the given type and we advanced it, false
* if it was not and nothing was changed
*/
public boolean skipWhitespace() {
if (current() == null) return false;
boolean is = isWhitespace();
if (is)
i++;
return is;
}
/** Returns whether the current token is of the given type */
public boolean is(IElementType... tokenTypes) {
if (current() == null) return false;
for (IElementType type : tokenTypes)
if (current().getElementType() == type) return true;
return false;
}
/** Returns whether the current token is whitespace */
public boolean isWhitespace() {
if (current() == null) return false;
return current().getPsi() instanceof PsiWhiteSpace;
}
/** Returns whether the current token is an element */
public boolean isElement() {
if (current() == null) return false;
return current() instanceof LeafPsiElement;
}
/** Returns the current token if it is of the required type and throws otherwise. */
public ASTNode require(IElementType... tokenTypes) {
if (!is(tokenTypes))
throw new IllegalArgumentException("Expected " + toString(tokenTypes) + " but got " + current());
ASTNode current = current();
i++;
return current;
}
/** Returns the current token if it is any element and throws otherwise. */
public ASTNode requireElement() {
if (!isElement())
throw new IllegalArgumentException("Expected an element but got " + current().getClass());
ASTNode current = current();
i++;
return current;
}
public void requireWhitespace() {
if (!isWhitespace())
throw new IllegalArgumentException("Expected whitespace, but got " + current());
i++;
}
/** Returns the current token (AST node), or null if we have reached the end. */
public ASTNode current() {
if (i >= nodes.length) return null;
return nodes[i];
}
private String toString(IElementType[] tokens) {
return Arrays.stream(tokens).map(token -> token.getDebugName()).collect(Collectors.joining(", "));
}
public static Tokens of(PsiElement element) {
return new Tokens(element);
}
/** For debugging: Prints the remaining to standard out. */
public void dump() {
for (int j = i; j < nodes.length; j++)
System.out.println(nodes[j]);
}
}
|