primaryPhase method
Implementation
RepairCandidate primaryPhase(int error_token) {
//
// Initialize the buffer.
//
var i = (nextStackTop >= 0 ? 3 : 2);
buffer[i] = error_token;
for (var j = i; j > 0; j--) {
buffer[j - 1] = tokStream.getPrevious(buffer[j]);
}
for (var k = i + 1; k < BUFF_SIZE; k++) {
buffer[k] = tokStream.getNext(buffer[k - 1]);
}
//
// If NEXT_STACK_TOP > 0 then the parse was successful on CURRENT_TOKEN
// and the error was detected on the successor of CURRENT_TOKEN. In
// that case, first check whether or not primary recovery is
// possible on next_stack ...
//
var repair = PrimaryRepairInfo();
if (nextStackTop >= 0) {
repair.bufferPosition = 3;
checkPrimaryDistance(repair, nextStack, nextStackTop);
}
//
// ... Try primary recovery on the current token and compare
// the quality of this recovery to the one on the next token...
//
var base_repair = PrimaryRepairInfo(repair);
base_repair.bufferPosition = 2;
checkPrimaryDistance(base_repair, stateStack, stateStackTop);
if (base_repair.distance > repair.distance ||
base_repair.misspellIndex > repair.misspellIndex) repair = base_repair;
//
// Finally, if prev_stack_top >= 0 try primary recovery on
// the prev_stack configuration and compare it to the best
// recovery computed thus far.
//
if (prevStackTop >= 0) {
var prev_repair = PrimaryRepairInfo(repair);
prev_repair.bufferPosition = 1;
checkPrimaryDistance(prev_repair, prevStack, prevStackTop);
if (prev_repair.distance > repair.distance ||
prev_repair.misspellIndex > repair.misspellIndex) {
repair = prev_repair;
}
}
//
// Before accepting the best primary phase recovery obtained,
// ensure that we cannot do better with a similar secondary
// phase recovery.
//
var candidate = RepairCandidate();
if (nextStackTop >= 0) // next_stack available
{
if (secondaryCheck(nextStack, nextStackTop, 3, repair.distance)) {
return candidate;
}
} else if (secondaryCheck(stateStack, stateStackTop, 2, repair.distance)) {
return candidate;
}
//
// First, adjust distance if the recovery is on the error token;
// it is important that the adjustment be made here and not at
// each primary trial to prevent the distance tests from being
// biased in favor of deferred recoveries which have access to
// more input tokens...
//
repair.distance = repair.distance - repair.bufferPosition + 1;
//
// ...Next, adjust the distance if the recovery is a deletion or
// (some form of) substitution...
//
if (repair.code == INVALID_CODE ||
repair.code == DELETION_CODE ||
repair.code == SUBSTITUTION_CODE ||
repair.code == MERGE_CODE) repair.distance--;
//
// ... After adjustment, check if the most successful primary
// recovery can be applied. If not, continue with more radical
// recoveries...
//
if (repair.distance < MIN_DISTANCE) return candidate;
//
// When processing an insertion error, if the token preceeding
// the error token is not available, we change the repair code
// into a BEFORE_CODE to instruct the reporting routine that it
// indicates that the repair symbol should be inserted before
// the error token.
//
if (repair.code == INSERTION_CODE) {
if (tokStream.getKind(buffer[repair.bufferPosition - 1]) == 0) {
repair.code = BEFORE_CODE;
}
}
//
// Select the proper sequence of states on which to recover,
// update stack accordingly and call diagnostic routine.
//
if (repair.bufferPosition == 1) {
stateStackTop = prevStackTop;
ArrayList.copy(prevStack, 0, stateStack, 0, stateStackTop + 1);
} else if (nextStackTop >= 0 && repair.bufferPosition >= 3) {
stateStackTop = nextStackTop;
ArrayList.copy(nextStack, 0, stateStack, 0, stateStackTop + 1);
locationStack[stateStackTop] = buffer[3];
}
return primaryDiagnosis(repair);
}