<s> package org . eclipse . jdt . internal . compiler . parser . diagnose ; import org . eclipse . jdt . core . compiler . CharOperation ; import org . eclipse . jdt . internal . compiler . impl . CompilerOptions ; import org . eclipse . jdt . internal . compiler . parser . Parser ; import org . eclipse . jdt . internal . compiler . parser . ParserBasicInformation ; import org . eclipse . jdt . internal . compiler . parser . RecoveryScanner ; import org . eclipse . jdt . internal . compiler . parser . ScannerHelper ; import org . eclipse . jdt . internal . compiler . parser . TerminalTokens ; import org . eclipse . jdt . internal . compiler . problem . ProblemReporter ; import org . eclipse . jdt . internal . compiler . util . Util ; public class DiagnoseParser implements ParserBasicInformation , TerminalTokens { private static final boolean DEBUG = false ; private boolean DEBUG_PARSECHECK = false ; private static final int STACK_INCREMENT = 256 ; private static final int BEFORE_CODE = 2 ; private static final int INSERTION_CODE = 3 ; private static final int INVALID_CODE = 4 ; private static final int SUBSTITUTION_CODE = 5 ; private static final int DELETION_CODE = 6 ; private static final int MERGE_CODE = 7 ; private static final int MISPLACED_CODE = 8 ; private static final int SCOPE_CODE = 9 ; private static final int SECONDARY_CODE = 10 ; private static final int EOF_CODE = 11 ; private static final int BUFF_UBOUND = 31 ; private static final int BUFF_SIZE = 32 ; private static final int MAX_DISTANCE = 30 ; private static final int MIN_DISTANCE = 3 ; private CompilerOptions options ; private LexStream lexStream ; private int errorToken ; private int errorTokenStart ; private int currentToken = 0 ; private int stackLength ; private int stateStackTop ; private int [ ] stack ; private int [ ] locationStack ; private int [ ] locationStartStack ; private int tempStackTop ; private int [ ] tempStack ; private int prevStackTop ; private int [ ] prevStack ; private int nextStackTop ; private int [ ] nextStack ; private int scopeStackTop ; private int [ ] scopeIndex ; private int [ ] scopePosition ; int [ ] list = new int [ NUM_SYMBOLS + 1 ] ; int [ ] buffer = new int [ BUFF_SIZE ] ; private static final int NIL = - 1 ; int [ ] stateSeen ; int statePoolTop ; StateInfo [ ] statePool ; private Parser parser ; private RecoveryScanner recoveryScanner ; private boolean reportProblem ; private static class RepairCandidate { public int symbol ; public int location ; public RepairCandidate ( ) { this . symbol = 0 ; this . location = 0 ; } } private static class PrimaryRepairInfo { public int distance ; public int misspellIndex ; public int code ; public int bufferPosition ; public int symbol ; public PrimaryRepairInfo ( ) { this . distance = 0 ; this . misspellIndex = 0 ; this . code = 0 ; this . bufferPosition = 0 ; this . symbol = 0 ; } public PrimaryRepairInfo copy ( ) { PrimaryRepairInfo c = new PrimaryRepairInfo ( ) ; c . distance = this . distance ; c . misspellIndex = this . misspellIndex ; c . code = this . code ; c . bufferPosition = this . bufferPosition ; c . symbol = this . symbol ; return c ; } } static class SecondaryRepairInfo { public int code ; public int distance ; public int bufferPosition ; public int stackPosition ; public int numDeletions ; public int symbol ; boolean recoveryOnNextStack ; } private static class StateInfo { int state ; int next ; public StateInfo ( int state , int next ) { this . state = state ; this . next = next ; } } public DiagnoseParser ( Parser parser , int firstToken , int start , int end , CompilerOptions options ) { this ( parser , firstToken , start , end , Util . EMPTY_INT_ARRAY , Util . EMPTY_INT_ARRAY , Util . EMPTY_INT_ARRAY , options ) ; } public DiagnoseParser ( Parser parser , int firstToken , int start , int end , int [ ] intervalStartToSkip , int [ ] intervalEndToSkip , int [ ] intervalFlagsToSkip , CompilerOptions options ) { this . parser = parser ; this . options = options ; this . lexStream = new LexStream ( BUFF_SIZE , parser . scanner , intervalStartToSkip , intervalEndToSkip , intervalFlagsToSkip , firstToken , start , end ) ; this . recoveryScanner = parser . recoveryScanner ; } private ProblemReporter problemReporter ( ) { return this . parser . problemReporter ( ) ; } private void reallocateStacks ( ) { int old_stack_length = this . stackLength ; this . stackLength += STACK_INCREMENT ; if ( old_stack_length == 0 ) { this . stack = new int [ this . stackLength ] ; this . locationStack = new int [ this . stackLength ] ; this . locationStartStack = new int [ this . stackLength ] ; this . tempStack = new int [ this . stackLength ] ; this . prevStack = new int [ this . stackLength ] ; this . nextStack = new int [ this . stackLength ] ; this . scopeIndex = new int [ this . stackLength ] ; this . scopePosition = new int [ this . stackLength ] ; } else { System . arraycopy ( this . stack , 0 , this . stack = new int [ this . stackLength ] , 0 , old_stack_length ) ; System . arraycopy ( this . locationStack , 0 , this . locationStack = new int [ this . stackLength ] , 0 , old_stack_length ) ; System . arraycopy ( this . locationStartStack , 0 , this . locationStartStack = new int [ this . stackLength ] , 0 , old_stack_length ) ; System . arraycopy ( this . tempStack , 0 , this . tempStack = new int [ this . stackLength ] , 0 , old_stack_length ) ; System . arraycopy ( this . prevStack , 0 , this . prevStack = new int [ this . stackLength ] , 0 , old_stack_length ) ; System . arraycopy ( this . nextStack , 0 , this . nextStack = new int [ this . stackLength ] , 0 , old_stack_length ) ; System . arraycopy ( this . scopeIndex , 0 , this . scopeIndex = new int [ this . stackLength ] , 0 , old_stack_length ) ; System . arraycopy ( this . scopePosition , 0 , this . scopePosition = new int [ this . stackLength ] , 0 , old_stack_length ) ; } return ; } public void diagnoseParse ( boolean record ) { this . reportProblem = true ; boolean oldRecord = false ; if ( this . recoveryScanner != null ) { oldRecord = this . recoveryScanner . record ; this . recoveryScanner . record = record ; } try { this . lexStream . reset ( ) ; this . currentToken = this . lexStream . getToken ( ) ; int prev_pos ; int pos ; int next_pos ; int act = START_STATE ; reallocateStacks ( ) ; this . stateStackTop = 0 ; this . stack [ this . stateStackTop ] = act ; int tok = this . lexStream . kind ( this . currentToken ) ; this . locationStack [ this . stateStackTop ] = this . currentToken ; this . locationStartStack [ this . stateStackTop ] = this . lexStream . start ( this . currentToken ) ; boolean forceRecoveryAfterLBracketMissing = false ; do { prev_pos = - 1 ; this . prevStackTop = - 1 ; next_pos = - 1 ; this . nextStackTop = - 1 ; pos = this . stateStackTop ; this . tempStackTop = this . stateStackTop - 1 ; for ( int i = 0 ; i <= this . stateStackTop ; i ++ ) this . tempStack [ i ] = this . stack [ i ] ; act = Parser . tAction ( act , tok ) ; while ( act <= NUM_RULES ) { do { this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; act = Parser . ntAction ( this . tempStack [ this . tempStackTop ] , Parser . lhs [ act ] ) ; } while ( act <= NUM_RULES ) ; if ( this . tempStackTop + 1 >= this . stackLength ) reallocateStacks ( ) ; pos = pos < this . tempStackTop ? pos : this . tempStackTop ; this . tempStack [ this . tempStackTop + 1 ] = act ; act = Parser . tAction ( act , tok ) ; } while ( act > ERROR_ACTION || act < ACCEPT_ACTION ) { this . nextStackTop = this . tempStackTop + 1 ; for ( int i = next_pos + 1 ; i <= this . nextStackTop ; i ++ ) this . nextStack [ i ] = this . tempStack [ i ] ; for ( int i = pos + 1 ; i <= this . nextStackTop ; i ++ ) { this . locationStack [ i ] = this . locationStack [ this . stateStackTop ] ; this . locationStartStack [ i ] = this . locationStartStack [ this . stateStackTop ] ; } if ( act > ERROR_ACTION ) { act -= ERROR_ACTION ; do { this . nextStackTop -= ( Parser . rhs [ act ] - 1 ) ; act = Parser . ntAction ( this . nextStack [ this . nextStackTop ] , Parser . lhs [ act ] ) ; } while ( act <= NUM_RULES ) ; pos = pos < this . nextStackTop ? pos : this . nextStackTop ; } if ( this . nextStackTop + 1 >= this . stackLength ) reallocateStacks ( ) ; this . tempStackTop = this . nextStackTop ; this . nextStack [ ++ this . nextStackTop ] = act ; next_pos = this . nextStackTop ; this . currentToken = this . lexStream . getToken ( ) ; tok = this . lexStream . kind ( this . currentToken ) ; act = Parser . tAction ( act , tok ) ; while ( act <= NUM_RULES ) { do { int lhs_symbol = Parser . lhs [ act ] ; if ( DEBUG ) { System . out . println ( Parser . name [ Parser . non_terminal_index [ lhs_symbol ] ] ) ; } this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; act = ( this . tempStackTop > next_pos ? this . tempStack [ this . tempStackTop ] : this . nextStack [ this . tempStackTop ] ) ; act = Parser . ntAction ( act , lhs_symbol ) ; } while ( act <= NUM_RULES ) ; if ( this . tempStackTop + 1 >= this . stackLength ) reallocateStacks ( ) ; next_pos = next_pos < this . tempStackTop ? next_pos : this . tempStackTop ; this . tempStack [ this . tempStackTop + 1 ] = act ; act = Parser . tAction ( act , tok ) ; } if ( act != ERROR_ACTION ) { this . prevStackTop = this . stateStackTop ; for ( int i = prev_pos + 1 ; i <= this . prevStackTop ; i ++ ) this . prevStack [ i ] = this . stack [ i ] ; prev_pos = pos ; this . stateStackTop = this . nextStackTop ; for ( int i = pos + 1 ; i <= this . stateStackTop ; i ++ ) this . stack [ i ] = this . nextStack [ i ] ; this . locationStack [ this . stateStackTop ] = this . currentToken ; this . locationStartStack [ this . stateStackTop ] = this . lexStream . start ( this . currentToken ) ; pos = next_pos ; } } if ( act == ERROR_ACTION ) { RepairCandidate candidate = errorRecovery ( this . currentToken , forceRecoveryAfterLBracketMissing ) ; forceRecoveryAfterLBracketMissing = false ; if ( this . parser . reportOnlyOneSyntaxError ) { return ; } if ( this . parser . problemReporter ( ) . options . maxProblemsPerUnit < this . parser . compilationUnit . compilationResult . problemCount ) { if ( this . recoveryScanner == null || ! this . recoveryScanner . record ) return ; this . reportProblem = false ; } act = this . stack [ this . stateStackTop ] ; if ( candidate . symbol == 0 ) { break ; } else if ( candidate . symbol > NT_OFFSET ) { int lhs_symbol = candidate . symbol - NT_OFFSET ; if ( DEBUG ) { System . out . println ( Parser . name [ Parser . non_terminal_index [ lhs_symbol ] ] ) ; } act = Parser . ntAction ( act , lhs_symbol ) ; while ( act <= NUM_RULES ) { this . stateStackTop -= ( Parser . rhs [ act ] - 1 ) ; act = Parser . ntAction ( this . stack [ this . stateStackTop ] , Parser . lhs [ act ] ) ; } this . stack [ ++ this . stateStackTop ] = act ; this . currentToken = this . lexStream . getToken ( ) ; tok = this . lexStream . kind ( this . currentToken ) ; this . locationStack [ this . stateStackTop ] = this . currentToken ; this . locationStartStack [ this . stateStackTop ] = this . lexStream . start ( this . currentToken ) ; } else { tok = candidate . symbol ; this . locationStack [ this . stateStackTop ] = candidate . location ; this . locationStartStack [ this . stateStackTop ] = this . lexStream . start ( candidate . location ) ; } } } while ( act != ACCEPT_ACTION ) ; } finally { if ( this . recoveryScanner != null ) { this . recoveryScanner . record = oldRecord ; } } return ; } private static char [ ] displayEscapeCharacters ( char [ ] tokenSource , int start , int end ) { StringBuffer tokenSourceBuffer = new StringBuffer ( ) ; for ( int i = 0 ; i < start ; i ++ ) { tokenSourceBuffer . append ( tokenSource [ i ] ) ; } for ( int i = start ; i < end ; i ++ ) { char c = tokenSource [ i ] ; switch ( c ) { case '\r' : tokenSourceBuffer . append ( "\\r" ) ; break ; case '\n' : tokenSourceBuffer . append ( "\\n" ) ; break ; case '\b' : tokenSourceBuffer . append ( "\\b" ) ; break ; case '\t' : tokenSourceBuffer . append ( "t" ) ; break ; case '\f' : tokenSourceBuffer . append ( "\\f" ) ; break ; case '\"' : tokenSourceBuffer . append ( "\\\"" ) ; break ; case '\'' : tokenSourceBuffer . append ( "\\'" ) ; break ; case '\\' : tokenSourceBuffer . append ( "\\\\" ) ; break ; default : tokenSourceBuffer . append ( c ) ; } } for ( int i = end ; i < tokenSource . length ; i ++ ) { tokenSourceBuffer . append ( tokenSource [ i ] ) ; } return tokenSourceBuffer . toString ( ) . toCharArray ( ) ; } private RepairCandidate errorRecovery ( int error_token , boolean forcedError ) { this . errorToken = error_token ; this . errorTokenStart = this . lexStream . start ( error_token ) ; int prevtok = this . lexStream . previous ( error_token ) ; int prevtokKind = this . lexStream . kind ( prevtok ) ; if ( forcedError ) { int name_index = Parser . terminal_index [ TokenNameLBRACE ] ; reportError ( INSERTION_CODE , name_index , prevtok , prevtok ) ; RepairCandidate candidate = new RepairCandidate ( ) ; candidate . symbol = TokenNameLBRACE ; candidate . location = error_token ; this . lexStream . reset ( error_token ) ; this . stateStackTop = this . nextStackTop ; for ( int j = 0 ; j <= this . stateStackTop ; j ++ ) { this . stack [ j ] = this . nextStack [ j ] ; } this . locationStack [ this . stateStackTop ] = error_token ; this . locationStartStack [ this . stateStackTop ] = this . lexStream . start ( error_token ) ; return candidate ; } RepairCandidate candidate = primaryPhase ( error_token ) ; if ( candidate . symbol != 0 ) { return candidate ; } candidate = secondaryPhase ( error_token ) ; if ( candidate . symbol != 0 ) { return candidate ; } if ( this . lexStream . kind ( error_token ) == EOFT_SYMBOL ) { reportError ( EOF_CODE , Parser . terminal_index [ EOFT_SYMBOL ] , prevtok , prevtok ) ; candidate . symbol = 0 ; candidate . location = error_token ; return candidate ; } while ( this . lexStream . kind ( this . buffer [ BUFF_UBOUND ] ) != EOFT_SYMBOL ) { candidate = secondaryPhase ( this . buffer [ MAX_DISTANCE - MIN_DISTANCE + 2 ] ) ; if ( candidate . symbol != 0 ) { return candidate ; } } int i ; for ( i = BUFF_UBOUND ; this . lexStream . kind ( this . buffer [ i ] ) == EOFT_SYMBOL ; i -- ) { } reportError ( DELETION_CODE , Parser . terminal_index [ prevtokKind ] , error_token , this . buffer [ i ] ) ; candidate . symbol = 0 ; candidate . location = this . buffer [ i ] ; return candidate ; } private RepairCandidate primaryPhase ( int error_token ) { PrimaryRepairInfo repair = new PrimaryRepairInfo ( ) ; RepairCandidate candidate = new RepairCandidate ( ) ; int i = ( this . nextStackTop >= 0 ? 3 : 2 ) ; this . buffer [ i ] = error_token ; for ( int j = i ; j > 0 ; j -- ) this . buffer [ j - 1 ] = this . lexStream . previous ( this . buffer [ j ] ) ; for ( int k = i + 1 ; k < BUFF_SIZE ; k ++ ) this . buffer [ k ] = this . lexStream . next ( this . buffer [ k - 1 ] ) ; if ( this . nextStackTop >= 0 ) { repair . bufferPosition = 3 ; repair = checkPrimaryDistance ( this . nextStack , this . nextStackTop , repair ) ; } PrimaryRepairInfo new_repair = repair . copy ( ) ; new_repair . bufferPosition = 2 ; new_repair = checkPrimaryDistance ( this . stack , this . stateStackTop , new_repair ) ; if ( new_repair . distance > repair . distance || new_repair . misspellIndex > repair . misspellIndex ) { repair = new_repair ; } if ( this . prevStackTop >= 0 ) { new_repair = repair . copy ( ) ; new_repair . bufferPosition = 1 ; new_repair = checkPrimaryDistance ( this . prevStack , this . prevStackTop , new_repair ) ; if ( new_repair . distance > repair . distance || new_repair . misspellIndex > repair . misspellIndex ) { repair = new_repair ; } } if ( this . nextStackTop >= 0 ) { if ( secondaryCheck ( this . nextStack , this . nextStackTop , 3 , repair . distance ) ) { return candidate ; } } else if ( secondaryCheck ( this . stack , this . stateStackTop , 2 , repair . distance ) ) { return candidate ; } repair . distance = repair . distance - repair . bufferPosition + 1 ; if ( repair . code == INVALID_CODE || repair . code == DELETION_CODE || repair . code == SUBSTITUTION_CODE || repair . code == MERGE_CODE ) { repair . distance -- ; } if ( repair . distance < MIN_DISTANCE ) { return candidate ; } if ( repair . code == INSERTION_CODE ) { if ( this . buffer [ repair . bufferPosition - 1 ] == 0 ) { repair . code = BEFORE_CODE ; } } if ( repair . bufferPosition == 1 ) { this . stateStackTop = this . prevStackTop ; for ( int j = 0 ; j <= this . stateStackTop ; j ++ ) { this . stack [ j ] = this . prevStack [ j ] ; } } else if ( this . nextStackTop >= 0 && repair . bufferPosition >= 3 ) { this . stateStackTop = this . nextStackTop ; for ( int j = 0 ; j <= this . stateStackTop ; j ++ ) { this . stack [ j ] = this . nextStack [ j ] ; } this . locationStack [ this . stateStackTop ] = this . buffer [ 3 ] ; this . locationStartStack [ this . stateStackTop ] = this . lexStream . start ( this . buffer [ 3 ] ) ; } return primaryDiagnosis ( repair ) ; } private int mergeCandidate ( int state , int buffer_position ) { char [ ] name1 = this . lexStream . name ( this . buffer [ buffer_position ] ) ; char [ ] name2 = this . lexStream . name ( this . buffer [ buffer_position + 1 ] ) ; int len = name1 . length + name2 . length ; char [ ] str = CharOperation . concat ( name1 , name2 ) ; for ( int k = Parser . asi ( state ) ; Parser . asr [ k ] != 0 ; k ++ ) { int l = Parser . terminal_index [ Parser . asr [ k ] ] ; if ( len == Parser . name [ l ] . length ( ) ) { char [ ] name = Parser . name [ l ] . toCharArray ( ) ; if ( CharOperation . equals ( str , name , false ) ) { return Parser . asr [ k ] ; } } } return 0 ; } private PrimaryRepairInfo checkPrimaryDistance ( int stck [ ] , int stack_top , PrimaryRepairInfo repair ) { int i , j , k , next_state , max_pos , act , root , symbol , tok ; PrimaryRepairInfo scope_repair = scopeTrial ( stck , stack_top , repair . copy ( ) ) ; if ( scope_repair . distance > repair . distance ) repair = scope_repair ; if ( this . buffer [ repair . bufferPosition ] != 0 && this . buffer [ repair . bufferPosition + 1 ] != 0 ) { symbol = mergeCandidate ( stck [ stack_top ] , repair . bufferPosition ) ; if ( symbol != 0 ) { j = parseCheck ( stck , stack_top , symbol , repair . bufferPosition + 2 ) ; if ( ( j > repair . distance ) || ( j == repair . distance && repair . misspellIndex < 10 ) ) { repair . misspellIndex = 10 ; repair . symbol = symbol ; repair . distance = j ; repair . code = MERGE_CODE ; } } } j = parseCheck ( stck , stack_top , this . lexStream . kind ( this . buffer [ repair . bufferPosition + 1 ] ) , repair . bufferPosition + 2 ) ; if ( this . lexStream . kind ( this . buffer [ repair . bufferPosition ] ) == EOLT_SYMBOL && this . lexStream . afterEol ( this . buffer [ repair . bufferPosition + 1 ] ) ) { k = 10 ; } else { k = 0 ; } if ( j > repair . distance || ( j == repair . distance && k > repair . misspellIndex ) ) { repair . misspellIndex = k ; repair . code = DELETION_CODE ; repair . distance = j ; } next_state = stck [ stack_top ] ; max_pos = stack_top ; this . tempStackTop = stack_top - 1 ; tok = this . lexStream . kind ( this . buffer [ repair . bufferPosition ] ) ; this . lexStream . reset ( this . buffer [ repair . bufferPosition + 1 ] ) ; act = Parser . tAction ( next_state , tok ) ; while ( act <= NUM_RULES ) { do { this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; symbol = Parser . lhs [ act ] ; act = ( this . tempStackTop > max_pos ? this . tempStack [ this . tempStackTop ] : stck [ this . tempStackTop ] ) ; act = Parser . ntAction ( act , symbol ) ; } while ( act <= NUM_RULES ) ; max_pos = max_pos < this . tempStackTop ? max_pos : this . tempStackTop ; this . tempStack [ this . tempStackTop + 1 ] = act ; next_state = act ; act = Parser . tAction ( next_state , tok ) ; } root = 0 ; for ( i = Parser . asi ( next_state ) ; Parser . asr [ i ] != 0 ; i ++ ) { symbol = Parser . asr [ i ] ; if ( symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL ) { if ( root == 0 ) { this . list [ symbol ] = symbol ; } else { this . list [ symbol ] = this . list [ root ] ; this . list [ root ] = symbol ; } root = symbol ; } } if ( stck [ stack_top ] != next_state ) { for ( i = Parser . asi ( stck [ stack_top ] ) ; Parser . asr [ i ] != 0 ; i ++ ) { symbol = Parser . asr [ i ] ; if ( symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL && this . list [ symbol ] == 0 ) { if ( root == 0 ) { this . list [ symbol ] = symbol ; } else { this . list [ symbol ] = this . list [ root ] ; this . list [ root ] = symbol ; } root = symbol ; } } } i = this . list [ root ] ; this . list [ root ] = 0 ; root = i ; symbol = root ; while ( symbol != 0 ) { if ( symbol == EOLT_SYMBOL && this . lexStream . afterEol ( this . buffer [ repair . bufferPosition ] ) ) { k = 10 ; } else { k = 0 ; } j = parseCheck ( stck , stack_top , symbol , repair . bufferPosition ) ; if ( j > repair . distance ) { repair . misspellIndex = k ; repair . distance = j ; repair . symbol = symbol ; repair . code = INSERTION_CODE ; } else if ( j == repair . distance && k > repair . misspellIndex ) { repair . misspellIndex = k ; repair . distance = j ; repair . symbol = symbol ; repair . code = INSERTION_CODE ; } symbol = this . list [ symbol ] ; } symbol = root ; if ( this . buffer [ repair . bufferPosition ] != 0 ) { while ( symbol != 0 ) { if ( symbol == EOLT_SYMBOL && this . lexStream . afterEol ( this . buffer [ repair . bufferPosition + 1 ] ) ) { k = 10 ; } else { k = misspell ( symbol , this . buffer [ repair . bufferPosition ] ) ; } j = parseCheck ( stck , stack_top , symbol , repair . bufferPosition + 1 ) ; if ( j > repair . distance ) { repair . misspellIndex = k ; repair . distance = j ; repair . symbol = symbol ; repair . code = SUBSTITUTION_CODE ; } else if ( j == repair . distance && k > repair . misspellIndex ) { repair . misspellIndex = k ; repair . symbol = symbol ; repair . code = SUBSTITUTION_CODE ; } i = symbol ; symbol = this . list [ symbol ] ; this . list [ i ] = 0 ; } } for ( i = Parser . nasi ( stck [ stack_top ] ) ; Parser . nasr [ i ] != 0 ; i ++ ) { symbol = Parser . nasr [ i ] + NT_OFFSET ; j = parseCheck ( stck , stack_top , symbol , repair . bufferPosition + 1 ) ; if ( j > repair . distance ) { repair . misspellIndex = 0 ; repair . distance = j ; repair . symbol = symbol ; repair . code = INVALID_CODE ; } j = parseCheck ( stck , stack_top , symbol , repair . bufferPosition ) ; if ( ( j > repair . distance ) || ( j == repair . distance && repair . code == INVALID_CODE ) ) { repair . misspellIndex = 0 ; repair . distance = j ; repair . symbol = symbol ; repair . code = INSERTION_CODE ; } } return repair ; } private RepairCandidate primaryDiagnosis ( PrimaryRepairInfo repair ) { int name_index ; int prevtok = this . buffer [ repair . bufferPosition - 1 ] ; int curtok = this . buffer [ repair . bufferPosition ] ; switch ( repair . code ) { case INSERTION_CODE : case BEFORE_CODE : { if ( repair . symbol > NT_OFFSET ) name_index = getNtermIndex ( this . stack [ this . stateStackTop ] , repair . symbol , repair . bufferPosition ) ; else name_index = getTermIndex ( this . stack , this . stateStackTop , repair . symbol , repair . bufferPosition ) ; int t = ( repair . code == INSERTION_CODE ? prevtok : curtok ) ; reportError ( repair . code , name_index , t , t ) ; break ; } case INVALID_CODE : { name_index = getNtermIndex ( this . stack [ this . stateStackTop ] , repair . symbol , repair . bufferPosition + 1 ) ; reportError ( repair . code , name_index , curtok , curtok ) ; break ; } case SUBSTITUTION_CODE : { if ( repair . misspellIndex >= 6 ) name_index = Parser . terminal_index [ repair . symbol ] ; else { name_index = getTermIndex ( this . stack , this . stateStackTop , repair . symbol , repair . bufferPosition + 1 ) ; if ( name_index != Parser . terminal_index [ repair . symbol ] ) repair . code = INVALID_CODE ; } reportError ( repair . code , name_index , curtok , curtok ) ; break ; } case MERGE_CODE : { reportError ( repair . code , Parser . terminal_index [ repair . symbol ] , curtok , this . lexStream . next ( curtok ) ) ; break ; } case SCOPE_CODE : { for ( int i = 0 ; i < this . scopeStackTop ; i ++ ) { reportError ( repair . code , - this . scopeIndex [ i ] , this . locationStack [ this . scopePosition [ i ] ] , prevtok , Parser . non_terminal_index [ Parser . scope_lhs [ this . scopeIndex [ i ] ] ] ) ; } repair . symbol = Parser . scope_lhs [ this . scopeIndex [ this . scopeStackTop ] ] + NT_OFFSET ; this . stateStackTop = this . scopePosition [ this . scopeStackTop ] ; reportError ( repair . code , - this . scopeIndex [ this . scopeStackTop ] , this . locationStack [ this . scopePosition [ this . scopeStackTop ] ] , prevtok , getNtermIndex ( this . stack [ this . stateStackTop ] , repair . symbol , repair . bufferPosition ) ) ; break ; } default : { reportError ( repair . code , Parser . terminal_index [ ERROR_SYMBOL ] , curtok , curtok ) ; } } RepairCandidate candidate = new RepairCandidate ( ) ; switch ( repair . code ) { case INSERTION_CODE : case BEFORE_CODE : case SCOPE_CODE : { candidate . symbol = repair . symbol ; candidate . location = this . buffer [ repair . bufferPosition ] ; this . lexStream . reset ( this . buffer [ repair . bufferPosition ] ) ; break ; } case INVALID_CODE : case SUBSTITUTION_CODE : { candidate . symbol = repair . symbol ; candidate . location = this . buffer [ repair . bufferPosition ] ; this . lexStream . reset ( this . buffer [ repair . bufferPosition + 1 ] ) ; break ; } case MERGE_CODE : { candidate . symbol = repair . symbol ; candidate . location = this . buffer [ repair . bufferPosition ] ; this . lexStream . reset ( this . buffer [ repair . bufferPosition + 2 ] ) ; break ; } default : { candidate . location = this . buffer [ repair . bufferPosition + 1 ] ; candidate . symbol = this . lexStream . kind ( this . buffer [ repair . bufferPosition + 1 ] ) ; this . lexStream . reset ( this . buffer [ repair . bufferPosition + 2 ] ) ; break ; } } return candidate ; } private int getTermIndex ( int stck [ ] , int stack_top , int tok , int buffer_position ) { int act = stck [ stack_top ] , max_pos = stack_top , highest_symbol = tok ; this . tempStackTop = stack_top - 1 ; this . lexStream . reset ( this . buffer [ buffer_position ] ) ; act = Parser . tAction ( act , tok ) ; while ( act <= NUM_RULES ) { do { this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; int lhs_symbol = Parser . lhs [ act ] ; act = ( this . tempStackTop > max_pos ? this . tempStack [ this . tempStackTop ] : stck [ this . tempStackTop ] ) ; act = Parser . ntAction ( act , lhs_symbol ) ; } while ( act <= NUM_RULES ) ; max_pos = max_pos < this . tempStackTop ? max_pos : this . tempStackTop ; this . tempStack [ this . tempStackTop + 1 ] = act ; act = Parser . tAction ( act , tok ) ; } this . tempStackTop ++ ; int threshold = this . tempStackTop ; tok = this . lexStream . kind ( this . buffer [ buffer_position ] ) ; this . lexStream . reset ( this . buffer [ buffer_position + 1 ] ) ; if ( act > ERROR_ACTION ) { act -= ERROR_ACTION ; } else { this . tempStack [ this . tempStackTop + 1 ] = act ; act = Parser . tAction ( act , tok ) ; } while ( act <= NUM_RULES ) { do { this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; if ( this . tempStackTop < threshold ) { return ( highest_symbol > NT_OFFSET ? Parser . non_terminal_index [ highest_symbol - NT_OFFSET ] : Parser . terminal_index [ highest_symbol ] ) ; } int lhs_symbol = Parser . lhs [ act ] ; if ( this . tempStackTop == threshold ) highest_symbol = lhs_symbol + NT_OFFSET ; act = ( this . tempStackTop > max_pos ? this . tempStack [ this . tempStackTop ] : stck [ this . tempStackTop ] ) ; act = Parser . ntAction ( act , lhs_symbol ) ; } while ( act <= NUM_RULES ) ; this . tempStack [ this . tempStackTop + 1 ] = act ; act = Parser . tAction ( act , tok ) ; } return ( highest_symbol > NT_OFFSET ? Parser . non_terminal_index [ highest_symbol - NT_OFFSET ] : Parser . terminal_index [ highest_symbol ] ) ; } private int getNtermIndex ( int start , int sym , int buffer_position ) { int highest_symbol = sym - NT_OFFSET , tok = this . lexStream . kind ( this . buffer [ buffer_position ] ) ; this . lexStream . reset ( this . buffer [ buffer_position + 1 ] ) ; this . tempStackTop = 0 ; this . tempStack [ this . tempStackTop ] = start ; int act = Parser . ntAction ( start , highest_symbol ) ; if ( act > NUM_RULES ) { this . tempStack [ this . tempStackTop + 1 ] = act ; act = Parser . tAction ( act , tok ) ; } while ( act <= NUM_RULES ) { do { this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; if ( this . tempStackTop < 0 ) return Parser . non_terminal_index [ highest_symbol ] ; if ( this . tempStackTop == 0 ) highest_symbol = Parser . lhs [ act ] ; act = Parser . ntAction ( this . tempStack [ this . tempStackTop ] , Parser . lhs [ act ] ) ; } while ( act <= NUM_RULES ) ; this . tempStack [ this . tempStackTop + 1 ] = act ; act = Parser . tAction ( act , tok ) ; } return Parser . non_terminal_index [ highest_symbol ] ; } private int misspell ( int sym , int tok ) { char [ ] name = Parser . name [ Parser . terminal_index [ sym ] ] . toCharArray ( ) ; int n = name . length ; char [ ] s1 = new char [ n + 1 ] ; for ( int k = 0 ; k < n ; k ++ ) { char c = name [ k ] ; s1 [ k ] = ScannerHelper . toLowerCase ( c ) ; } s1 [ n ] = '\0' ; char [ ] tokenName = this . lexStream . name ( tok ) ; int len = tokenName . length ; int m = len < MAX_NAME_LENGTH ? len : MAX_NAME_LENGTH ; char [ ] s2 = new char [ m + 1 ] ; for ( int k = 0 ; k < m ; k ++ ) { char c = tokenName [ k ] ; s2 [ k ] = ScannerHelper . toLowerCase ( c ) ; } s2 [ m ] = '\0' ; if ( n == 1 && m == 1 ) { if ( ( s1 [ 0 ] == ';' && s2 [ 0 ] == ',' ) || ( s1 [ 0 ] == ',' && s2 [ 0 ] == ';' ) || ( s1 [ 0 ] == ';' && s2 [ 0 ] == ':' ) || ( s1 [ 0 ] == ':' && s2 [ 0 ] == ';' ) || ( s1 [ 0 ] == '.' && s2 [ 0 ] == ',' ) || ( s1 [ 0 ] == ',' && s2 [ 0 ] == '.' ) || ( s1 [ 0 ] == '\'' && s2 [ 0 ] == '\"' ) || ( s1 [ 0 ] == '\"' && s2 [ 0 ] == '\'' ) ) { return 3 ; } } int count = 0 ; int prefix_length = 0 ; int num_errors = 0 ; int i = 0 ; int j = 0 ; while ( ( i < n ) && ( j < m ) ) { if ( s1 [ i ] == s2 [ j ] ) { count ++ ; i ++ ; j ++ ; if ( num_errors == 0 ) { prefix_length ++ ; } } else if ( s1 [ i + 1 ] == s2 [ j ] && s1 [ i ] == s2 [ j + 1 ] ) { count += 2 ; i += 2 ; j += 2 ; num_errors ++ ; } else if ( s1 [ i + 1 ] == s2 [ j + 1 ] ) { i ++ ; j ++ ; num_errors ++ ; } else { if ( ( n - i ) > ( m - j ) ) { i ++ ; } else if ( ( m - j ) > ( n - i ) ) { j ++ ; } else { i ++ ; j ++ ; } num_errors ++ ; } } if ( i < n || j < m ) num_errors ++ ; if ( num_errors > ( ( n < m ? n : m ) / 6 + 1 ) ) count = prefix_length ; return ( count * 10 / ( ( n < len ? len : n ) + num_errors ) ) ; } private PrimaryRepairInfo scopeTrial ( int stck [ ] , int stack_top , PrimaryRepairInfo repair ) { this . stateSeen = new int [ this . stackLength ] ; for ( int i = 0 ; i < this . stackLength ; i ++ ) this . stateSeen [ i ] = NIL ; this . statePoolTop = 0 ; this . statePool = new StateInfo [ this . stackLength ] ; scopeTrialCheck ( stck , stack_top , repair , 0 ) ; this . stateSeen = null ; this . statePoolTop = 0 ; repair . code = SCOPE_CODE ; repair . misspellIndex = 10 ; return repair ; } private void scopeTrialCheck ( int stck [ ] , int stack_top , PrimaryRepairInfo repair , int indx ) { if ( indx > 20 ) return ; int act = stck [ stack_top ] ; for ( int i = this . stateSeen [ stack_top ] ; i != NIL ; i = this . statePool [ i ] . next ) { if ( this . statePool [ i ] . state == act ) return ; } int old_state_pool_top = this . statePoolTop ++ ; if ( this . statePoolTop >= this . statePool . length ) { System . arraycopy ( this . statePool , 0 , this . statePool = new StateInfo [ this . statePoolTop * 2 ] , 0 , this . statePoolTop ) ; } this . statePool [ old_state_pool_top ] = new StateInfo ( act , this . stateSeen [ stack_top ] ) ; this . stateSeen [ stack_top ] = old_state_pool_top ; next : for ( int i = 0 ; i < SCOPE_SIZE ; i ++ ) { act = stck [ stack_top ] ; this . tempStackTop = stack_top - 1 ; int max_pos = stack_top ; int tok = Parser . scope_la [ i ] ; this . lexStream . reset ( this . buffer [ repair . bufferPosition ] ) ; act = Parser . tAction ( act , tok ) ; while ( act <= NUM_RULES ) { do { this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; int lhs_symbol = Parser . lhs [ act ] ; act = ( this . tempStackTop > max_pos ? this . tempStack [ this . tempStackTop ] : stck [ this . tempStackTop ] ) ; act = Parser . ntAction ( act , lhs_symbol ) ; } while ( act <= NUM_RULES ) ; if ( this . tempStackTop + 1 >= this . stackLength ) return ; max_pos = max_pos < this . tempStackTop ? max_pos : this . tempStackTop ; this . tempStack [ this . tempStackTop + 1 ] = act ; act = Parser . tAction ( act , tok ) ; } if ( act != ERROR_ACTION ) { int j , k ; k = Parser . scope_prefix [ i ] ; for ( j = this . tempStackTop + 1 ; j >= ( max_pos + 1 ) && Parser . in_symbol ( this . tempStack [ j ] ) == Parser . scope_rhs [ k ] ; j -- ) { k ++ ; } if ( j == max_pos ) { for ( j = max_pos ; j >= 1 && Parser . in_symbol ( stck [ j ] ) == Parser . scope_rhs [ k ] ; j -- ) { k ++ ; } } int marked_pos = ( max_pos < stack_top ? max_pos + 1 : stack_top ) ; if ( Parser . scope_rhs [ k ] == 0 && j < marked_pos ) { int stack_position = j ; for ( j = Parser . scope_state_set [ i ] ; stck [ stack_position ] != Parser . scope_state [ j ] && Parser . scope_state [ j ] != 0 ; j ++ ) { } if ( Parser . scope_state [ j ] != 0 ) { int previous_distance = repair . distance ; int distance = parseCheck ( stck , stack_position , Parser . scope_lhs [ i ] + NT_OFFSET , repair . bufferPosition ) ; if ( ( distance - repair . bufferPosition + 1 ) < MIN_DISTANCE ) { int top = stack_position ; act = Parser . ntAction ( stck [ top ] , Parser . scope_lhs [ i ] ) ; while ( act <= NUM_RULES ) { if ( Parser . rules_compliance [ act ] > this . options . sourceLevel ) { continue next ; } top -= ( Parser . rhs [ act ] - 1 ) ; act = Parser . ntAction ( stck [ top ] , Parser . lhs [ act ] ) ; } top ++ ; j = act ; act = stck [ top ] ; stck [ top ] = j ; scopeTrialCheck ( stck , top , repair , indx + 1 ) ; stck [ top ] = act ; } else if ( distance > repair . distance ) { this . scopeStackTop = indx ; repair . distance = distance ; } if ( this . lexStream . kind ( this . buffer [ repair . bufferPosition ] ) == EOFT_SYMBOL && repair . distance == previous_distance ) { this . scopeStackTop = indx ; repair . distance = MAX_DISTANCE ; } if ( repair . distance > previous_distance ) { this . scopeIndex [ indx ] = i ; this . scopePosition [ indx ] = stack_position ; return ; } } } } } } private boolean secondaryCheck ( int stck [ ] , int stack_top , int buffer_position , int distance ) { int top , j ; for ( top = stack_top - 1 ; top >= 0 ; top -- ) { j = parseCheck ( stck , top , this . lexStream . kind ( this . buffer [ buffer_position ] ) , buffer_position + 1 ) ; if ( ( ( j - buffer_position + 1 ) > MIN_DISTANCE ) && ( j > distance ) ) return true ; } PrimaryRepairInfo repair = new PrimaryRepairInfo ( ) ; repair . bufferPosition = buffer_position + 1 ; repair . distance = distance ; repair = scopeTrial ( stck , stack_top , repair ) ; if ( ( repair . distance - buffer_position ) > MIN_DISTANCE && repair . distance > distance ) return true ; return false ; } private RepairCandidate secondaryPhase ( int error_token ) { SecondaryRepairInfo repair = new SecondaryRepairInfo ( ) ; SecondaryRepairInfo misplaced = new SecondaryRepairInfo ( ) ; RepairCandidate candidate = new RepairCandidate ( ) ; int i , j , k , top ; int next_last_index = 0 ; int last_index ; candidate . symbol = 0 ; repair . code = 0 ; repair . distance = 0 ; repair . recoveryOnNextStack = false ; misplaced . distance = 0 ; misplaced . recoveryOnNextStack = false ; if ( this . nextStackTop >= 0 ) { int save_location ; this . buffer [ 2 ] = error_token ; this . buffer [ 1 ] = this . lexStream . previous ( this . buffer [ 2 ] ) ; this . buffer [ 0 ] = this . lexStream . previous ( this . buffer [ 1 ] ) ; for ( k = 3 ; k < BUFF_UBOUND ; k ++ ) this . buffer [ k ] = this . lexStream . next ( this . buffer [ k - 1 ] ) ; this . buffer [ BUFF_UBOUND ] = this . lexStream . badtoken ( ) ; for ( next_last_index = MAX_DISTANCE - 1 ; next_last_index >= 1 && this . lexStream . kind ( this . buffer [ next_last_index ] ) == EOFT_SYMBOL ; next_last_index -- ) { } next_last_index = next_last_index + 1 ; save_location = this . locationStack [ this . nextStackTop ] ; int save_location_start = this . locationStartStack [ this . nextStackTop ] ; this . locationStack [ this . nextStackTop ] = this . buffer [ 2 ] ; this . locationStartStack [ this . nextStackTop ] = this . lexStream . start ( this . buffer [ 2 ] ) ; misplaced . numDeletions = this . nextStackTop ; misplaced = misplacementRecovery ( this . nextStack , this . nextStackTop , next_last_index , misplaced , true ) ; if ( misplaced . recoveryOnNextStack ) misplaced . distance ++ ; repair . numDeletions = this . nextStackTop + BUFF_UBOUND ; repair = secondaryRecovery ( this . nextStack , this . nextStackTop , next_last_index , repair , true ) ; if ( repair . recoveryOnNextStack ) repair . distance ++ ; this . locationStack [ this . nextStackTop ] = save_location ; this . locationStartStack [ this . nextStackTop ] = save_location_start ; } else { misplaced . numDeletions = this . stateStackTop ; repair . numDeletions = this . stateStackTop + BUFF_UBOUND ; } this . buffer [ 3 ] = error_token ; this . buffer [ 2 ] = this . lexStream . previous ( this . buffer [ 3 ] ) ; this . buffer [ 1 ] = this . lexStream . previous ( this . buffer [ 2 ] ) ; this . buffer [ 0 ] = this . lexStream . previous ( this . buffer [ 1 ] ) ; for ( k = 4 ; k < BUFF_SIZE ; k ++ ) this . buffer [ k ] = this . lexStream . next ( this . buffer [ k - 1 ] ) ; for ( last_index = MAX_DISTANCE - 1 ; last_index >= 1 && this . lexStream . kind ( this . buffer [ last_index ] ) == EOFT_SYMBOL ; last_index -- ) { } last_index ++ ; misplaced = misplacementRecovery ( this . stack , this . stateStackTop , last_index , misplaced , false ) ; repair = secondaryRecovery ( this . stack , this . stateStackTop , last_index , repair , false ) ; if ( misplaced . distance > MIN_DISTANCE ) { if ( misplaced . numDeletions <= repair . numDeletions || ( misplaced . distance - misplaced . numDeletions ) >= ( repair . distance - repair . numDeletions ) ) { repair . code = MISPLACED_CODE ; repair . stackPosition = misplaced . stackPosition ; repair . bufferPosition = 2 ; repair . numDeletions = misplaced . numDeletions ; repair . distance = misplaced . distance ; repair . recoveryOnNextStack = misplaced . recoveryOnNextStack ; } } if ( repair . recoveryOnNextStack ) { this . stateStackTop = this . nextStackTop ; for ( i = 0 ; i <= this . stateStackTop ; i ++ ) this . stack [ i ] = this . nextStack [ i ] ; this . buffer [ 2 ] = error_token ; this . buffer [ 1 ] = this . lexStream . previous ( this . buffer [ 2 ] ) ; this . buffer [ 0 ] = this . lexStream . previous ( this . buffer [ 1 ] ) ; for ( k = 3 ; k < BUFF_UBOUND ; k ++ ) this . buffer [ k ] = this . lexStream . next ( this . buffer [ k - 1 ] ) ; this . buffer [ BUFF_UBOUND ] = this . lexStream . badtoken ( ) ; this . locationStack [ this . nextStackTop ] = this . buffer [ 2 ] ; this . locationStartStack [ this . nextStackTop ] = this . lexStream . start ( this . buffer [ 2 ] ) ; last_index = next_last_index ; } if ( repair . code == SECONDARY_CODE || repair . code == DELETION_CODE ) { PrimaryRepairInfo scope_repair = new PrimaryRepairInfo ( ) ; scope_repair . distance = 0 ; for ( scope_repair . bufferPosition = 2 ; scope_repair . bufferPosition <= repair . bufferPosition && repair . code != SCOPE_CODE ; scope_repair . bufferPosition ++ ) { scope_repair = scopeTrial ( this . stack , this . stateStackTop , scope_repair ) ; j = ( scope_repair . distance == MAX_DISTANCE ? last_index : scope_repair . distance ) ; k = scope_repair . bufferPosition - 1 ; if ( ( j - k ) > MIN_DISTANCE && ( j - k ) > ( repair . distance - repair . numDeletions ) ) { repair . code = SCOPE_CODE ; i = this . scopeIndex [ this . scopeStackTop ] ; repair . symbol = Parser . scope_lhs [ i ] + NT_OFFSET ; repair . stackPosition = this . stateStackTop ; repair . bufferPosition = scope_repair . bufferPosition ; } } } if ( repair . code == 0 && this . lexStream . kind ( this . buffer [ last_index ] ) == EOFT_SYMBOL ) { PrimaryRepairInfo scope_repair = new PrimaryRepairInfo ( ) ; scope_repair . bufferPosition = last_index ; scope_repair . distance = 0 ; for ( top = this . stateStackTop ; top >= 0 && repair . code == 0 ; top -- ) { scope_repair = scopeTrial ( this . stack , top , scope_repair ) ; if ( scope_repair . distance > 0 ) { repair . code = SCOPE_CODE ; i = this . scopeIndex [ this . scopeStackTop ] ; repair . symbol = Parser . scope_lhs [ i ] + NT_OFFSET ; repair . stackPosition = top ; repair . bufferPosition = scope_repair . bufferPosition ; } } } if ( repair . code == 0 ) return candidate ; secondaryDiagnosis ( repair ) ; switch ( repair . code ) { case MISPLACED_CODE : candidate . location = this . buffer [ 2 ] ; candidate . symbol = this . lexStream . kind ( this . buffer [ 2 ] ) ; this . lexStream . reset ( this . lexStream . next ( this . buffer [ 2 ] ) ) ; break ; case DELETION_CODE : candidate . location = this . buffer [ repair . bufferPosition ] ; candidate . symbol = this . lexStream . kind ( this . buffer [ repair . bufferPosition ] ) ; this . lexStream . reset ( this . lexStream . next ( this . buffer [ repair . bufferPosition ] ) ) ; break ; default : candidate . symbol = repair . symbol ; candidate . location = this . buffer [ repair . bufferPosition ] ; this . lexStream . reset ( this . buffer [ repair . bufferPosition ] ) ; break ; } return candidate ; } private SecondaryRepairInfo misplacementRecovery ( int stck [ ] , int stack_top , int last_index , SecondaryRepairInfo repair , boolean stack_flag ) { int previous_loc = this . buffer [ 2 ] ; int stack_deletions = 0 ; for ( int top = stack_top - 1 ; top >= 0 ; top -- ) { if ( this . locationStack [ top ] < previous_loc ) { stack_deletions ++ ; } previous_loc = this . locationStack [ top ] ; int j = parseCheck ( stck , top , this . lexStream . kind ( this . buffer [ 2 ] ) , 3 ) ; if ( j == MAX_DISTANCE ) { j = last_index ; } if ( ( j > MIN_DISTANCE ) && ( j - stack_deletions ) > ( repair . distance - repair . numDeletions ) ) { repair . stackPosition = top ; repair . distance = j ; repair . numDeletions = stack_deletions ; repair . recoveryOnNextStack = stack_flag ; } } return repair ; } private SecondaryRepairInfo secondaryRecovery ( int stck [ ] , int stack_top , int last_index , SecondaryRepairInfo repair , boolean stack_flag ) { int previous_loc ; int stack_deletions = 0 ; previous_loc = this . buffer [ 2 ] ; for ( int top = stack_top ; top >= 0 && repair . numDeletions >= stack_deletions ; top -- ) { if ( this . locationStack [ top ] < previous_loc ) { stack_deletions ++ ; } previous_loc = this . locationStack [ top ] ; for ( int i = 2 ; i <= ( last_index - MIN_DISTANCE + 1 ) && ( repair . numDeletions >= ( stack_deletions + i - 1 ) ) ; i ++ ) { int j = parseCheck ( stck , top , this . lexStream . kind ( this . buffer [ i ] ) , i + 1 ) ; if ( j == MAX_DISTANCE ) { j = last_index ; } if ( ( j - i + 1 ) > MIN_DISTANCE ) { int k = stack_deletions + i - 1 ; if ( ( k < repair . numDeletions ) || ( j - k ) > ( repair . distance - repair . numDeletions ) || ( ( repair . code == SECONDARY_CODE ) && ( j - k ) == ( repair . distance - repair . numDeletions ) ) ) { repair . code = DELETION_CODE ; repair . distance = j ; repair . stackPosition = top ; repair . bufferPosition = i ; repair . numDeletions = k ; repair . recoveryOnNextStack = stack_flag ; } } for ( int l = Parser . nasi ( stck [ top ] ) ; l >= 0 && Parser . nasr [ l ] != 0 ; l ++ ) { int symbol = Parser . nasr [ l ] + NT_OFFSET ; j = parseCheck ( stck , top , symbol , i ) ; if ( j == MAX_DISTANCE ) { j = last_index ; } if ( ( j - i + 1 ) > MIN_DISTANCE ) { int k = stack_deletions + i - 1 ; if ( k < repair . numDeletions || ( j - k ) > ( repair . distance - repair . numDeletions ) ) { repair . code = SECONDARY_CODE ; repair . symbol = symbol ; repair . distance = j ; repair . stackPosition = top ; repair . bufferPosition = i ; repair . numDeletions = k ; repair . recoveryOnNextStack = stack_flag ; } } } } } return repair ; } private void secondaryDiagnosis ( SecondaryRepairInfo repair ) { switch ( repair . code ) { case SCOPE_CODE : { if ( repair . stackPosition < this . stateStackTop ) { reportError ( DELETION_CODE , Parser . terminal_index [ ERROR_SYMBOL ] , this . locationStack [ repair . stackPosition ] , this . buffer [ 1 ] ) ; } for ( int i = 0 ; i < this . scopeStackTop ; i ++ ) { reportError ( SCOPE_CODE , - this . scopeIndex [ i ] , this . locationStack [ this . scopePosition [ i ] ] , this . buffer [ 1 ] , Parser . non_terminal_index [ Parser . scope_lhs [ this . scopeIndex [ i ] ] ] ) ; } repair . symbol = Parser . scope_lhs [ this . scopeIndex [ this . scopeStackTop ] ] + NT_OFFSET ; this . stateStackTop = this . scopePosition [ this . scopeStackTop ] ; reportError ( SCOPE_CODE , - this . scopeIndex [ this . scopeStackTop ] , this . locationStack [ this . scopePosition [ this . scopeStackTop ] ] , this . buffer [ 1 ] , getNtermIndex ( this . stack [ this . stateStackTop ] , repair . symbol , repair . bufferPosition ) ) ; break ; } default : { reportError ( repair . code , ( repair . code == SECONDARY_CODE ? getNtermIndex ( this . stack [ repair . stackPosition ] , repair . symbol , repair . bufferPosition ) : Parser . terminal_index [ ERROR_SYMBOL ] ) , this . locationStack [ repair . stackPosition ] , this . buffer [ repair . bufferPosition - 1 ] ) ; this . stateStackTop = repair . stackPosition ; } } } private int parseCheck ( int stck [ ] , int stack_top , int first_token , int buffer_position ) { int max_pos ; int indx ; int ct ; int act ; act = stck [ stack_top ] ; if ( first_token > NT_OFFSET ) { this . tempStackTop = stack_top ; if ( this . DEBUG_PARSECHECK ) { System . out . println ( this . tempStackTop ) ; } max_pos = stack_top ; indx = buffer_position ; ct = this . lexStream . kind ( this . buffer [ indx ] ) ; this . lexStream . reset ( this . lexStream . next ( this . buffer [ indx ] ) ) ; int lhs_symbol = first_token - NT_OFFSET ; act = Parser . ntAction ( act , lhs_symbol ) ; if ( act <= NUM_RULES ) { do { this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; if ( this . DEBUG_PARSECHECK ) { System . out . print ( this . tempStackTop ) ; System . out . print ( " (" ) ; System . out . print ( - ( Parser . rhs [ act ] - 1 ) ) ; System . out . print ( ") [max:" ) ; System . out . print ( max_pos ) ; System . out . print ( "" ) ; System . out . print ( act ) ; System . out . print ( "t" ) ; System . out . print ( Parser . name [ Parser . non_terminal_index [ Parser . lhs [ act ] ] ] ) ; System . out . println ( ) ; } if ( Parser . rules_compliance [ act ] > this . options . sourceLevel ) { return 0 ; } lhs_symbol = Parser . lhs [ act ] ; act = ( this . tempStackTop > max_pos ? this . tempStack [ this . tempStackTop ] : stck [ this . tempStackTop ] ) ; act = Parser . ntAction ( act , lhs_symbol ) ; } while ( act <= NUM_RULES ) ; max_pos = max_pos < this . tempStackTop ? max_pos : this . tempStackTop ; } } else { this . tempStackTop = stack_top - 1 ; if ( this . DEBUG_PARSECHECK ) { System . out . println ( this . tempStackTop ) ; } max_pos = this . tempStackTop ; indx = buffer_position - 1 ; ct = first_token ; this . lexStream . reset ( this . buffer [ buffer_position ] ) ; } process_terminal : for ( ; ; ) { if ( this . DEBUG_PARSECHECK ) { System . out . print ( this . tempStackTop + 1 ) ; System . out . print ( " (+1) [max:" ) ; System . out . print ( max_pos ) ; System . out . print ( "" ) ; System . out . print ( ct ) ; System . out . print ( "t" ) ; System . out . print ( Parser . name [ Parser . terminal_index [ ct ] ] ) ; System . out . println ( ) ; } if ( ++ this . tempStackTop >= this . stackLength ) return indx ; this . tempStack [ this . tempStackTop ] = act ; act = Parser . tAction ( act , ct ) ; if ( act <= NUM_RULES ) { this . tempStackTop -- ; if ( this . DEBUG_PARSECHECK ) { System . out . print ( this . tempStackTop ) ; System . out . print ( " (-1) [max:" ) ; System . out . print ( max_pos ) ; System . out . print ( "]treduce" ) ; System . out . println ( ) ; } } else if ( act < ACCEPT_ACTION || act > ERROR_ACTION ) { if ( indx == MAX_DISTANCE ) return indx ; indx ++ ; ct = this . lexStream . kind ( this . buffer [ indx ] ) ; this . lexStream . reset ( this . lexStream . next ( this . buffer [ indx ] ) ) ; if ( act > ERROR_ACTION ) { act -= ERROR_ACTION ; if ( this . DEBUG_PARSECHECK ) { System . out . print ( this . tempStackTop ) ; System . out . print ( "" ) ; System . out . println ( ) ; } } else { if ( this . DEBUG_PARSECHECK ) { System . out . println ( "tshift" ) ; } continue process_terminal ; } } else if ( act == ACCEPT_ACTION ) { return MAX_DISTANCE ; } else { return indx ; } do { this . tempStackTop -= ( Parser . rhs [ act ] - 1 ) ; if ( this . DEBUG_PARSECHECK ) { System . out . print ( this . tempStackTop ) ; System . out . print ( " (" ) ; System . out . print ( - ( Parser . rhs [ act ] - 1 ) ) ; System . out . print ( ") [max:" ) ; System . out . print ( max_pos ) ; System . out . print ( "" ) ; System . out . print ( act ) ; System . out . print ( "t" ) ; System . out . print ( Parser . name [ Parser . non_terminal_index [ Parser . lhs [ act ] ] ] ) ; System . out . println ( ) ; } if ( act <= NUM_RULES ) { if ( Parser . rules_compliance [ act ] > this . options . sourceLevel ) { return 0 ; } } int lhs_symbol = Parser . lhs [ act ] ; act = ( this . tempStackTop > max_pos ? this . tempStack [ this . tempStackTop ] : stck [ this . tempStackTop ] ) ; act = Parser . ntAction ( act , lhs_symbol ) ; } while ( act <= NUM_RULES ) ; max_pos = max_pos < this . tempStackTop ? max_pos : this . tempStackTop ; } } private void reportError ( int msgCode , int nameIndex , int leftToken , int rightToken ) { reportError ( msgCode , nameIndex , leftToken , rightToken , 0 ) ; } private void reportError ( int msgCode , int nameIndex , int leftToken , int rightToken , int scopeNameIndex ) { int lToken = ( leftToken > rightToken ? rightToken : leftToken ) ; if ( lToken < rightToken ) { reportSecondaryError ( msgCode , nameIndex , lToken , rightToken , scopeNameIndex ) ; } else { reportPrimaryError ( msgCode , nameIndex , rightToken , scopeNameIndex ) ; } } private void reportPrimaryError ( int msgCode , int nameIndex , int token , int scopeNameIndex ) { String name ; if ( nameIndex >= 0 ) { name = Parser . readableName [ nameIndex ] ; } else { name = Util . EMPTY_STRING ; } int errorStart = this . lexStream . start ( token ) ; int errorEnd = this . lexStream . end ( token ) ; int currentKind = this . lexStream . kind ( token ) ; String errorTokenName = Parser . name [ Parser . terminal_index [ this . lexStream . kind ( token ) ] ] ; char [ ] errorTokenSource = this . lexStream . name ( token ) ; if ( currentKind == TerminalTokens . TokenNameStringLiteral ) { errorTokenSource = displayEscapeCharacters ( errorTokenSource , 1 , errorTokenSource . length - 1 ) ; } int addedToken = - 1 ; if ( this . recoveryScanner != null ) { if ( nameIndex >= 0 ) { addedToken = Parser . reverse_index [ nameIndex ] ; } } switch ( msgCode ) { case BEFORE_CODE : if ( this . recoveryScanner != null ) { if ( addedToken > - 1 ) { this . recoveryScanner . insertToken ( addedToken , - 1 , errorStart ) ; } else { int [ ] template = getNTermTemplate ( - addedToken ) ; if ( template != null ) { this . recoveryScanner . insertTokens ( template , - 1 , errorStart ) ; } } } if ( this . reportProblem ) problemReporter ( ) . parseErrorInsertBeforeToken ( errorStart , errorEnd , currentKind , errorTokenSource , errorTokenName , name ) ; break ; case INSERTION_CODE : if ( this . recoveryScanner != null ) { if ( addedToken > - 1 ) { this . recoveryScanner . insertToken ( addedToken , - 1 , errorEnd ) ; } else { int [ ] template = getNTermTemplate ( - addedToken ) ; if ( template != null ) { this . recoveryScanner . insertTokens ( template , - 1 , errorEnd ) ; } } } if ( this . reportProblem ) problemReporter ( ) . parseErrorInsertAfterToken ( errorStart , errorEnd , currentKind , errorTokenSource , errorTokenName , name ) ; break ; case DELETION_CODE : if ( this . recoveryScanner != null ) { this . recoveryScanner . removeTokens ( errorStart , errorEnd ) ; } if ( this . reportProblem ) problemReporter ( ) . parseErrorDeleteToken ( errorStart , errorEnd , currentKind , errorTokenSource , errorTokenName ) ; break ; case INVALID_CODE : if ( name . length ( ) == 0 ) { if ( this . recoveryScanner != null ) { this . recoveryScanner . removeTokens ( errorStart , errorEnd ) ; } if ( this . reportProblem ) problemReporter ( ) . parseErrorReplaceToken ( errorStart , errorEnd , currentKind , errorTokenSource , errorTokenName , name ) ; } else { if ( this . recoveryScanner != null ) { if ( addedToken > - 1 ) { this . recoveryScanner . replaceTokens ( addedToken , errorStart , errorEnd ) ; } else { int [ ] template = getNTermTemplate ( - addedToken ) ; if ( template != null ) { this . recoveryScanner . replaceTokens ( template , errorStart , errorEnd ) ; } } } if ( this . reportProblem ) problemReporter ( ) . parseErrorInvalidToken ( errorStart , errorEnd , currentKind , errorTokenSource , errorTokenName , name ) ; } break ; case SUBSTITUTION_CODE : if ( this . recoveryScanner != null ) { if ( addedToken > - 1 ) { this . recoveryScanner . replaceTokens ( addedToken , errorStart , errorEnd ) ; } else { int [ ] template = getNTermTemplate ( - addedToken ) ; if ( template != null ) { this . recoveryScanner . replaceTokens ( template , errorStart , errorEnd ) ; } } } if ( this . reportProblem ) problemReporter ( ) . parseErrorReplaceToken ( errorStart , errorEnd , currentKind , errorTokenSource , errorTokenName , name ) ; break ; case SCOPE_CODE : StringBuffer buf = new StringBuffer ( ) ; int [ ] addedTokens = null ; int addedTokenCount = 0 ; if ( this . recoveryScanner != null ) { addedTokens = new int [ Parser . scope_rhs . length - Parser . scope_suffix [ - nameIndex ] ] ; } for ( int i = Parser . scope_suffix [ - nameIndex ] ; Parser . scope_rhs [ i ] != 0 ; i ++ ) { buf . append ( Parser . readableName [ Parser . scope_rhs [ i ] ] ) ; if ( Parser . scope_rhs [ i + 1 ] != 0 ) buf . append ( ' ' ) ; if ( addedTokens != null ) { int tmpAddedToken = Parser . reverse_index [ Parser . scope_rhs [ i ] ] ; if ( tmpAddedToken > - 1 ) { int length = addedTokens . length ; if ( addedTokenCount == length ) { System . arraycopy ( addedTokens , 0 , addedTokens = new int [ length * 2 ] , 0 , length ) ; } addedTokens [ addedTokenCount ++ ] = tmpAddedToken ; } else { int [ ] template = getNTermTemplate ( - tmpAddedToken ) ; if ( template != null ) { for ( int j = 0 ; j < template . length ; j ++ ) { int length = addedTokens . length ; if ( addedTokenCount == length ) { System . arraycopy ( addedTokens , 0 , addedTokens = new int [ length * 2 ] , 0 , length ) ; } addedTokens [ addedTokenCount ++ ] = template [ j ] ; } } else { addedTokenCount = 0 ; addedTokens = null ; } } } } if ( addedTokenCount > 0 ) { System . arraycopy ( addedTokens , 0 , addedTokens = new int [ addedTokenCount ] , 0 , addedTokenCount ) ; int completedToken = - 1 ; if ( scopeNameIndex != 0 ) { completedToken = - Parser . reverse_index [ scopeNameIndex ] ; } this . recoveryScanner . insertTokens ( addedTokens , completedToken , errorEnd ) ; } if ( scopeNameIndex != 0 ) { if ( this . reportProblem ) problemReporter ( ) . parseErrorInsertToComplete ( errorStart , errorEnd , buf . toString ( ) , Parser . readableName [ scopeNameIndex ] ) ; } else { if ( this . reportProblem ) problemReporter ( ) . parseErrorInsertToCompleteScope ( errorStart , errorEnd , buf . toString ( ) ) ; } break ; case EOF_CODE : if ( this . reportProblem ) problemReporter ( ) . parseErrorUnexpectedEnd ( errorStart , errorEnd ) ; break ; case MERGE_CODE : if ( this . recoveryScanner != null ) { if ( addedToken > - 1 ) { this . recoveryScanner . replaceTokens ( addedToken , errorStart , errorEnd ) ; } else { int [ ] template = getNTermTemplate ( - addedToken ) ; if ( template != null ) { this . recoveryScanner . replaceTokens ( template , errorStart , errorEnd ) ; } } } if ( this . reportProblem ) problemReporter ( ) . parseErrorMergeTokens ( errorStart , errorEnd , name ) ; break ; case MISPLACED_CODE : if ( this . recoveryScanner != null ) { this . recoveryScanner . removeTokens ( errorStart , errorEnd ) ; } if ( this . reportProblem ) problemReporter ( ) . parseErrorMisplacedConstruct ( errorStart , errorEnd ) ; break ; default : if ( name . length ( ) == 0 ) { if ( this . recoveryScanner != null ) { this . recoveryScanner . removeTokens ( errorStart , errorEnd ) ; } if ( this . reportProblem ) problemReporter ( ) . parseErrorNoSuggestion ( errorStart , errorEnd , currentKind , errorTokenSource , errorTokenName ) ; } else { if ( this . recoveryScanner != null ) { if ( addedToken > - 1 ) { this . recoveryScanner . replaceTokens ( addedToken , errorStart , errorEnd ) ; } else { int [ ] template = getNTermTemplate ( - addedToken ) ; if ( template != null ) { this . recoveryScanner . replaceTokens ( template , errorStart , errorEnd ) ; } } } if ( this . reportProblem ) problemReporter ( ) . parseErrorReplaceToken ( errorStart , errorEnd , currentKind , errorTokenSource , errorTokenName , name ) ; } break ; } } private void reportSecondaryError ( int msgCode , int nameIndex , int leftToken , int rightToken , int scopeNameIndex ) { String name ; if ( nameIndex >= 0 ) { name = Parser . readableName [ nameIndex ] ; } else { name = Util . EMPTY_STRING ; } int errorStart = - 1 ; if ( this . lexStream . isInsideStream ( leftToken ) ) { if ( leftToken == 0 ) { errorStart = this . lexStream . start ( leftToken + 1 ) ; } else { errorStart = this . lexStream . start ( leftToken ) ; } } else { if ( leftToken == this . errorToken ) { errorStart = this . errorTokenStart ; } else { for ( int i = 0 ; i <= this . stateStackTop ; i ++ ) { if ( this . locationStack [ i ] == leftToken ) { errorStart = this . locationStartStack [ i ] ; } } } if ( errorStart == - 1 ) { errorStart = this . lexStream . start ( rightToken ) ; } } int errorEnd = this . lexStream . end ( rightToken ) ; int addedToken = - 1 ; if ( this . recoveryScanner != null ) { if ( nameIndex >= 0 ) { addedToken = Parser . reverse_index [ nameIndex ] ; } } switch ( msgCode ) { case MISPLACED_CODE : if ( this . recoveryScanner != null ) { this . recoveryScanner . removeTokens ( errorStart , errorEnd ) ; } if ( this . reportProblem ) problemReporter ( ) . parseErrorMisplacedConstruct ( errorStart , errorEnd ) ; break ; case SCOPE_CODE : errorStart = this . lexStream . start ( rightToken ) ; StringBuffer buf = new StringBuffer ( ) ; int [ ] addedTokens = null ; int addedTokenCount = 0 ; if ( this . recoveryScanner != null ) { addedTokens = new int [ Parser . scope_rhs . length - Parser . scope_suffix [ - nameIndex ] ] ; } for ( int i = Parser . scope_suffix [ - nameIndex ] ; Parser . scope_rhs [ i ] != 0 ; i ++ ) { buf . append ( Parser . readableName [ Parser . scope_rhs [ i ] ] ) ; if ( Parser . scope_rhs [ i + 1 ] != 0 ) buf . append ( ' ' ) ; if ( addedTokens != null ) { int tmpAddedToken = Parser . reverse_index [ Parser . scope_rhs [ i ] ] ; if ( tmpAddedToken > - 1 ) { int length = addedTokens . length ; if ( addedTokenCount == length ) { System . arraycopy ( addedTokens , 0 , addedTokens = new int [ length * 2 ] , 0 , length ) ; } addedTokens [ addedTokenCount ++ ] = tmpAddedToken ; } else { int [ ] template = getNTermTemplate ( - tmpAddedToken ) ; if ( template != null ) { for ( int j = 0 ; j < template . length ; j ++ ) { int length = addedTokens . length ; if ( addedTokenCount == length ) { System . arraycopy ( addedTokens , 0 , addedTokens = new int [ length * 2 ] , 0 , length ) ; } addedTokens [ addedTokenCount ++ ] = template [ j ] ; } } else { addedTokenCount = 0 ; addedTokens = null ; } } } } if ( addedTokenCount > 0 ) { System . arraycopy ( addedTokens , 0 , addedTokens = new int [ addedTokenCount ] , 0 , addedTokenCount ) ; int completedToken = - 1 ; if ( scopeNameIndex != 0 ) { completedToken = - Parser . reverse_index [ scopeNameIndex ] ; } this . recoveryScanner . insertTokens ( addedTokens , completedToken , errorEnd ) ; } if ( scopeNameIndex != 0 ) { if ( this . reportProblem ) problemReporter ( ) . parseErrorInsertToComplete ( errorStart , errorEnd , buf . toString ( ) , Parser . readableName [ scopeNameIndex ] ) ; } else { if ( this . reportProblem ) problemReporter ( ) . parseErrorInsertToCompletePhrase ( errorStart , errorEnd , buf . toString ( ) ) ; } break ; case MERGE_CODE : if ( this . recoveryScanner != null ) { if ( addedToken > - 1 ) { this . recoveryScanner . replaceTokens ( addedToken , errorStart , errorEnd ) ; } else { int [ ] template = getNTermTemplate ( - addedToken ) ; if ( template != null ) { this . recoveryScanner . replaceTokens ( template , errorStart , errorEnd ) ; } } } if ( this . reportProblem ) problemReporter ( ) . parseErrorMergeTokens ( errorStart , errorEnd , name ) ; break ; case DELETION_CODE : if ( this . recoveryScanner != null ) { this . recoveryScanner . removeTokens ( errorStart , errorEnd ) ; } if ( this . reportProblem ) problemReporter ( ) . parseErrorDeleteTokens ( errorStart , errorEnd ) ; break ; default : if ( name . length ( ) == 0 ) { if ( this . recoveryScanner != null ) { this . recoveryScanner . removeTokens ( errorStart , errorEnd ) ; } if ( this . reportProblem ) problemReporter ( ) . parseErrorNoSuggestionForTokens ( errorStart , errorEnd ) ; } else { if ( this . recoveryScanner != null ) { if ( addedToken > - 1 ) { this . recoveryScanner . replaceTokens ( addedToken , errorStart , errorEnd ) ; } else { int [ ] template = getNTermTemplate ( - addedToken ) ; if ( template != null ) { this . recoveryScanner . replaceTokens ( template , errorStart , errorEnd ) ; } } } if ( this . reportProblem ) problemReporter ( ) . parseErrorReplaceTokens ( errorStart , errorEnd , name ) ; } } return ; } private int [ ] getNTermTemplate ( int sym ) { int templateIndex = Parser . recovery_templates_index [ sym ] ; if ( templateIndex > 0 ) { int [ ] result = new int [ Parser . recovery_templates . length ] ; int count = 0 ; for ( int j = templateIndex ; Parser . recovery_templates [ j ] != 0 ; j ++ ) { result [ count ++ ] = Parser . recovery_templates [ j ] ; } System . arraycopy ( result , 0 , result = new int [ count ] , 0 , count ) ; return result ; } else { return null ; } } public String toString ( ) { StringBuffer res = new StringBuffer ( ) ; res . append ( this . lexStream . toString ( ) ) ; return res . toString ( ) ; } } </s>