// подготавливает (если можно) узел к обработке "брата" private void FinalOperations(TBStack current) { if (inputStack.Count < 2) { if (!ToDrop()) output.V(current.tvalue); return; } TBStack previous = inputStack.ElementAt(1); int ic = inputStack.Count; // Вариантов использования значения три: 1) сбросить; 2) сбросить предыдущие и сбросить; // 3) вставить в родительское значение. // Если этот уровень последний, в котором можно формировать объектное значение, // или он следующий за тем, который породил последнюю скобку // то надо значение "сбросить" bool drop = ToDrop() || previous.dropped; // ic <= slevel + 1 || ic <= currentTreeDepth + 1; if (!drop) { // Проверка на невозможность принять значение в оперативную память if (previous.volume + 8 + current.volume > maxElementVolume //|| totalVolume + 8 > maxTotalVolume // эту возможность пока не будем использовать, чтобы не порождать новых ошибок ) { drop = true; // Сбросить предыдущее // Цикл по элементам стека for (int s_at = ic - currentTreeDepth - 1; s_at > 0; s_at--) // currentTreeDepth - 1 { TBStack ste = inputStack.ElementAt(s_at); long index = inputStack.ElementAt(s_at - 1).index; var tp = ste.nodeType; if (tp.Vid == PTypeEnumeration.record) { output.R(); if (ste.tvalue != null) { object[] values = (object[])ste.tvalue; for (int i = 0; i < index; i++) output.V(values[i]); } } else if (tp.Vid == PTypeEnumeration.sequence) { output.S(); if (ste.tvalue != null) { object[] values = (object[])ste.tvalue; for (int i = 0; i < index; i++) output.V(values[i]); } } else if (tp.Vid == PTypeEnumeration.union) { object[] values = (object[])ste.tvalue; output.U((int)values[0]); // подэлемент ТОЧНО не сформирован } ste.tvalue = null; ste.dropped = true; totalVolume -= ste.volume; } // Установим новое значение currentTreeDepth currentTreeDepth = ic - 1; } else { // Случай, если нет ограничения - записываем значение в позицию индекса if (previous.tvalue == null) previous.tvalue = new object[initialseqsize]; previous.tvalue = Set((object[])previous.tvalue, current.tvalue, current.index); previous.volume += 8 + current.volume; totalVolume += 8; current.tvalue = null; } } if ( drop ) { //object value = zstack[current.zposition].value; object value = current.tvalue; //long volume = zstack[current.zposition].volume; long volume = current.volume; //output.V(value, current.nodeType); output.V(value); totalVolume -= volume; current.volume = 0; } PrepareForBrothers(current); }
private void PrepareForBrothers(TBStack current) { if (inputStack.Count == 1) return; // младших братьев не будет // Фаза 2: Подготовка к приему "младших братьев" TBStack previous = inputStack.ElementAt(1); current.volume = 0; current.tvalue = null; if (previous.nodeType.Vid == PTypeEnumeration.record) { PTypeRecord mtr = (PTypeRecord)previous.nodeType; if (current.index < mtr.Fields.Length - 1) { current.index += 1; current.nodeType = mtr.Fields[current.index].Type; } //else throw new Exception("Err in serial flow: too many fileds"); // это не нужно } else if (previous.nodeType.Vid == PTypeEnumeration.sequence) { current.index += 1; } else if (previous.nodeType.Vid == PTypeEnumeration.union) { if (current.index == 1) { } // все в порядке else throw new Exception("Err in serial flow: more than 1 subvalue in union"); } }
public void U(int tag) { TBStack uni = inputStack.Peek(); if (uni.nodeType.Vid != PTypeEnumeration.union) throw new Exception("unexpected type"); PTypeUnion mtu = (PTypeUnion)uni.nodeType; PType tel = mtu.Variants[tag].Type; TBStack uni_el = new TBStack(tel); if (ToDrop()) { output.U(tag); uni.dropped = true; } else { // Надо породить массив и записать в него тег uni.dropped = false; uni.tvalue = new object[] { tag, null }; long v = 16 + 16; totalVolume += v; // Еще надо, чтобы индекс был 1, поскольку тег уже записан uni_el.index = 1; } inputStack.Push(uni_el); }