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 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 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]; } } }