123 lines
3.1 KiB
Plaintext
123 lines
3.1 KiB
Plaintext
package slangc.parser;
|
|
|
|
import slang.streams.SyncOutput;
|
|
import slang.streams.SyncInput;
|
|
|
|
public final class Branch extends Node {
|
|
private NodeType type;
|
|
private Node[] subnodes;
|
|
|
|
public Branch(NodeType type, Node... subnodes ) {
|
|
this.type = type;
|
|
this.subnodes = subnodes;
|
|
}
|
|
|
|
Branch(NodeType type, int nnodes) {
|
|
this.type = type;
|
|
subnodes = new Node[nnodes];
|
|
}
|
|
|
|
@Override
|
|
public NodeType getNodeType() {
|
|
return type;
|
|
}
|
|
|
|
private static byte[] outbuffer = new byte[7];
|
|
|
|
public static Branch loadBinary(Scan sc, NodeType typ, SyncInput<byte> inp) {
|
|
inp.readBuffer(outbuffer, 0, 1);
|
|
int len = ((int) outbuffer[0]) & 0xFF;
|
|
if (len == 255) {
|
|
inp.readBuffer(outbuffer, 0, 4);
|
|
int len = Token.decInt(outbuffer, 0);
|
|
//Log.line("Type " + typ.name() + " length " + len);
|
|
if (len < 0 || len > 1000) {
|
|
Log.line("WARNING: Unusual length in binary cache");
|
|
}
|
|
}
|
|
Branch b = new Branch(typ, len);
|
|
for (int i = 0; i < len; i++) {
|
|
b.subnodes[i] = Node.loadBinary(sc,inp);
|
|
}
|
|
return b;
|
|
}
|
|
|
|
public void dumpBinary(SyncOutput<byte> o) {
|
|
if (type.value > 1000) {
|
|
throw new Error("Too many node types for this simple format!");
|
|
}
|
|
outbuffer[0] = (byte) (type.value >> 8);
|
|
outbuffer[1] = (byte) (type.value);
|
|
if (subnodes.length > 200) {
|
|
outbuffer[2] = (byte) 255;
|
|
Token.encInt(outbuffer, 3, subnodes.length);
|
|
o.writeBuffer(outbuffer, 0, 7);
|
|
} else {
|
|
outbuffer[2] = (byte) subnodes.length;
|
|
o.writeBuffer(outbuffer, 0, 3);
|
|
}
|
|
for (int i = 0; i < subnodes.length; i++) {
|
|
if (subnodes[i] == null) {
|
|
//while(true){}
|
|
throw new Error("Can't encode nulls in parse dumps");
|
|
}
|
|
subnodes[i].dumpBinary(o);
|
|
}
|
|
//throw new Error("Can't dump AST nodes of type " + Type.of(this).fullName());
|
|
}
|
|
|
|
public void append(Node n) {
|
|
Node[] nsubnodes = new Node[subnodes.length + 1];
|
|
for (int i = 0; i < subnodes.length; i++) {
|
|
nsubnodes[i] = subnodes[i];
|
|
}
|
|
nsubnodes[nsubnodes.length - 1] = n;
|
|
subnodes = nsubnodes;
|
|
}
|
|
|
|
public int countSubnodes() {
|
|
return subnodes.length;
|
|
}
|
|
|
|
public Node getSubnode(int index) {
|
|
if (index < 0 || index >= subnodes.length) {
|
|
return null;
|
|
} else {
|
|
return subnodes[index];
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int countErrorsRecursively() {
|
|
if (!mightHaveErrors) {
|
|
return 0;
|
|
}
|
|
int result = super.countErrorsRecursively();
|
|
|
|
for (int i = 0; i < subnodes.length; i++) {
|
|
if (subnodes[i] == null) {
|
|
result++;
|
|
} else {
|
|
result += subnodes[i].countErrorsRecursively();
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public int deleteErrorsRecursively() {
|
|
int result = super.deleteErrorsRecursively();
|
|
|
|
for (int i = 0; i < subnodes.length; i++) {
|
|
if (subnodes[i] == null) {
|
|
result++;
|
|
} else {
|
|
result += subnodes[i].deleteErrorsRecursively();
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|