slcom/slangc/parser/Node.sauce

174 lines
4.9 KiB
Plaintext

package slangc.parser;
import slang.streams.SyncOutput;
import slang.streams.SyncInput;
import slang.data.SimpleEnum;
public abstract class Node {
public Object userdata;
Annotation[] annotations = null;
Node() {
// TODO Auto-generated constructor stub
}
public abstract NodeType getNodeType();
public abstract String toString();
private static byte[] inbuffer = new byte[1];
static SimpleEnum[] toknums = TokenType.values(TokenType.class);
static SimpleEnum[] nnums = NodeType.values(NodeType.class);
public static Node loadBinary(Scan sc, SyncInput<byte> inp) {
inp.readBuffer(inbuffer, 0, 1);
if (((int) inbuffer[0]) < 0) {
int toknum = (-(int)inbuffer[0]) - 1;
//Log.line("Read number " + inbuffer[0] + " as " + toknum);
if (toknum == 127) {
inp.readBuffer(inbuffer, 0, 1);
toknum = (-(int)inbuffer[0]) - 1;
TokenType tt = (TokenType)toknums[toknum]; //TokenType.lookup(TokenType.class, toknum);
return Token.loadBinaryLong(sc, tt, inp);
} else {
TokenType tt = (TokenType)toknums[toknum]; //TokenType.lookup(TokenType.class, toknum);
return Token.loadBinaryShort(sc, tt, inp);
}
} else {
int top = (int)(inbuffer[0] & 0xFF);
inp.readBuffer(inbuffer, 0, 1);
int nnum = (top << 8) | (int)(inbuffer[0] & 0xFF);
NodeType nt = (NodeType)nnums[nnum]; //NodeType.lookup(NodeType.class, nnum);
return Branch.loadBinary(sc, nt, inp);
}
}
public abstract void dumpBinary(SyncOutput<byte> o) {
throw new Error("Can't dump AST nodes of type " + Type.of(this).fullName());
}
public int countAnnotations() {
if (annotations == null) {
return 0;
} else {
return annotations.length;
}
}
public Annotation[] getAnnotations(AnnotationType type) {
Annotation[] result = new Annotation[0];
for (int i = 0; i < countAnnotations(); i++) {
Annotation a = getAnnotation(i);
if (a.getAnnotationType() == type) {
Annotation[] nresult = new Annotation[result.length + 1];
for (int j = 0; j < result.length; j++) {
nresult[j] = result[j];
}
nresult[nresult.length - 1] = a;
result = nresult;
}
}
return result;
}
public int deleteAnnotations(AnnotationType type) {
int ndeleted = 0;
Annotation[] result = new Annotation[0];
for (int i = 0; i < countAnnotations(); i++) {
Annotation a = getAnnotation(i);
if (a.getAnnotationType() == type) {
ndeleted++;
} else {
Annotation[] nresult = new Annotation[result.length + 1];
for (int j = 0; j < result.length; j++) {
nresult[j] = result[j];
}
nresult[nresult.length - 1] = a;
result = nresult;
}
}
annotations = result;
return result.length;
}
public int countAnnotations(AnnotationType type) {
return getAnnotations(type).length;
}
public int countErrorsHere() {
return countAnnotations(AnnotationType.ERROR);
}
public int deleteErrorsHere() {
return deleteAnnotations(AnnotationType.ERROR);
}
public int countErrorsRecursively() {
return countErrorsHere();
}
public int deleteErrorsRecursively() {
return deleteErrorsHere();
}
public Node annotate(ErrorType e) {
return annotate(new ErrorAnnotation(e));
}
public Node annotate(ErrorType e, String n) {
ErrorAnnotation a = new ErrorAnnotation(e);
a.annotate(n);
return annotate(a);
}
public Node annotate(WarningType w) {
return annotate(new WarningAnnotation(w));
}
public Node annotate(WarningType w, String n) {
WarningAnnotation a = new WarningAnnotation(w);
a.annotate(n);
return annotate(a);
}
public Node annotate(String note) {
return annotate(new NoteAnnotation(note));
}
/* As a special optimisation, we set a global flag when an error is found.
* This means that if no errors have been found in this run, looking for/counting errors in
* the tree can be avoided entirely!
*/
public static boolean mightHaveErrors = true;
public static boolean mightHaveWarnings = false;
public Node annotate(Annotation n) {
if (n instanceof ErrorAnnotation) {
mightHaveErrors = true;
}
if (n instanceof WarningAnnotation) {
mightHaveWarnings = true;
}
if (annotations == null || annotations.length < 1) {
annotations = new Annotation[] {n};
return this;
}
Annotation[] nsubnodes = new Annotation[annotations.length + 1];
for (int i = 0; i < annotations.length; i++) {
nsubnodes[i] = annotations[i];
}
nsubnodes[nsubnodes.length - 1] = n;
annotations = nsubnodes;
return this;
}
public Annotation getAnnotation(int i) {
if (i < 0 || i >= countAnnotations()) {
return null;
} else {
return annotations[i];
}
}
}