protected void parse() {
	if (DEBUG) System.out.println("-- ENTER INSIDE PARSE METHOD --");  //$NON-NLS-1$

	if (DEBUG_AUTOMATON) {
		System.out.println("- Start --------------------------------");  //$NON-NLS-1$
	}

	boolean isDietParse = this.diet;
	int oldFirstToken = getFirstToken();
	this.hasError = false;

	this.hasReportedError = false;
	boolean insertedSemicolon = false;
	int prevAct = START_STATE,
		prevToken = getFirstToken(),
		prevPos = scanner.startPosition;

	int act = START_STATE;
	this.stateStackTop = -1;
	this.currentToken = getFirstToken();
	ProcessTerminals : for (;;) {
		int stackLength = this.stack.length;
		if (++this.stateStackTop >= stackLength) {
			System.arraycopy(
				this.stack, 0,
				this.stack = new int[stackLength + StackIncrement], 0,
				stackLength);
		}
		this.stack[this.stateStackTop] = act;

		if (DEBUG)
			System.out.println("action="+act+ ((term_check[base_action[act]+this.currentToken] == this.currentToken)?"":" - take default") ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		prevAct=act;

		if (optionalSemicolonState[act])
		{
			if (term_check[base_action[act]+this.currentToken] != this.currentToken)
			{
				if (isErrorState(act))
				{
				  if (!insertedSemicolon && shouldInsertSemicolon(prevPos, prevToken) )
				  {
					currentToken = TokenNameSEMICOLON;
					this.insertedSemicolonPosition=prevPos;
					scanner.pushBack();
					insertedSemicolon = true;

				  }
				}
			}
		}

		act = tAction(act, this.currentToken);
		if (act == ERROR_ACTION || this.restartRecovery) {
//			if ( act == ERROR_ACTION &&
//					!insertedSemicolon &&
//					shouldInsertSemicolon(prevPos, prevToken)
//					) {
//					act = prevAct;
//					--stateStackTop;
//					currentToken = TokenNameSEMICOLON;
//					scanner.pushBack();
//					insertedSemicolon = true;
//					continue ProcessTerminals;
//				}

			if (DEBUG_AUTOMATON) {
				if (this.restartRecovery) {
					System.out.println("Restart      - "); //$NON-NLS-1$
				} else {
					System.out.println("Error        - "); //$NON-NLS-1$
				}
			}

			int errorPos = this.scanner.currentPosition;
			if (!this.hasReportedError) {
				this.hasError = true;
			}
 			if (resumeOnSyntaxError()) {
				if (act == ERROR_ACTION) this.lastErrorEndPosition = errorPos;
				act = START_STATE;
				this.stateStackTop = -1;
				this.currentToken = getFirstToken();
				if (DEBUG) System.out.println("!! Resume on syntax error"); //$NON-NLS-1$
				continue ProcessTerminals;
			}
			act = ERROR_ACTION;
			break ProcessTerminals;
		}
		if (act <= NUM_RULES) {
			insertedSemicolon = false;
			this.stateStackTop--;

			if (DEBUG_AUTOMATON) {
				System.out.print("Reduce       - "); //$NON-NLS-1$
			}

		} else if (act > ERROR_ACTION) { /* shift-reduce */
			if (DEBUG) System.out.println("<<shift-reduce consume Token: "+scanner.toStringAction(this.currentToken)); //$NON-NLS-1$
			consumeToken(this.currentToken);
			if (this.currentElement != null) this.recoveryTokenCheck();
			try {
				prevPos = scanner.currentPosition;
				prevToken = currentToken;
				insertedSemicolon = false;
				this.currentToken = this.scanner.getNextToken();
				if (DEBUG) System.out.println(">>shift-reduce Next Token: "+scanner.dumpCurrent()); //$NON-NLS-1$
			} catch(InvalidInputException e){
				if (!this.hasReportedError){
					this.problemReporter().scannerError(this, e.getMessage());
					this.hasReportedError = true;
				}
				this.lastCheckPoint = this.scanner.currentPosition;
				this.restartRecovery = true;
			}
			if(this.statementRecoveryActivated) {
				this.jumpOverType();
			}
			act -= ERROR_ACTION;

			if (DEBUG_AUTOMATON) {
				System.out.print("Shift/Reduce - (" + name[terminal_index[this.currentToken]]+") ");  //$NON-NLS-1$  //$NON-NLS-2$
			}

		} else {
		    if (act < ACCEPT_ACTION) { /* shift */
				if (DEBUG) System.out.println("<<shift consume Token: "+scanner.toStringAction(this.currentToken)); //$NON-NLS-1$
				consumeToken(this.currentToken);
				if (this.currentElement != null) this.recoveryTokenCheck();
				try{
					prevPos = scanner.currentPosition;
					prevToken = currentToken;
					insertedSemicolon = false;
					this.currentToken = this.scanner.getNextToken();
					if (DEBUG) System.out.println(">>shift next Token: "+scanner.dumpCurrent()); //$NON-NLS-1$
				} catch(InvalidInputException e){
					if (!this.hasReportedError){
						this.problemReporter().scannerError(this, e.getMessage());
						this.hasReportedError = true;
					}
					this.lastCheckPoint = this.scanner.currentPosition;
					this.restartRecovery = true;
				}
				if(this.statementRecoveryActivated) {
					this.jumpOverType();
				}
				if (DEBUG_AUTOMATON) {
					System.out.println("Shift        - (" + name[terminal_index[this.currentToken]]+")");  //$NON-NLS-1$  //$NON-NLS-2$
				}
				continue ProcessTerminals;
			}
			break ProcessTerminals;
		}

		// ProcessNonTerminals :
		do { /* reduce */

			if (DEBUG_AUTOMATON) {
				System.out.println(name[non_terminal_index[lhs[act]]]);
			}

			consumeRule(act);
			this.stateStackTop -= (rhs[act] - 1);
			act = ntAction(this.stack[this.stateStackTop], lhs[act]);
			if (DEBUG_AUTOMATON && act <= NUM_RULES) {
				System.out.print("             - ");  //$NON-NLS-1$
				}

		} while (act <= NUM_RULES);
		if (DEBUG_AUTOMATON) {
			System.out.println("----------------------------------------");  //$NON-NLS-1$
		}
	}
	if (DEBUG_AUTOMATON) {
		System.out.println("- End ----------------------------------");  //$NON-NLS-1$
	}

	endParse(act);
	// record all nls tags in the corresponding compilation unit
	final NLSTag[] tags = this.scanner.getNLSTags();
	if (tags != null) {
		this.compilationUnit.nlsTags = tags;
	}

	this.scanner.checkNonExternalizedStringLiterals = false;
	if (this.reportSyntaxErrorIsRequired && this.hasError && !(this.statementRecoveryActivated && DO_DIET_PARSE)) {
		if(!this.options.performStatementsRecovery) {
			reportSyntaxErrors(isDietParse, oldFirstToken);
		} else {
			RecoveryScannerData data = this.referenceContext.compilationResult().recoveryScannerData;

			if(this.recoveryScanner == null) {
				this.recoveryScanner = new RecoveryScanner(this.scanner, data);
			} else {
				this.recoveryScanner.setData(data);
			}

			this.recoveryScanner.setSource(scanner.source);
			this.recoveryScanner.lineEnds = this.scanner.lineEnds;
			this.recoveryScanner.linePtr = this.scanner.linePtr;

			reportSyntaxErrors(isDietParse, oldFirstToken);

			if(data == null) {
				this.referenceContext.compilationResult().recoveryScannerData =
					this.recoveryScanner.getData();
			}

			if (this.methodRecoveryActivated && this.options.performStatementsRecovery && !this.enteredRecoverStatements) {
				this.methodRecoveryActivated = false;
				this.enteredRecoverStatements=true;
				this.recoverStatements();
				this.methodRecoveryActivated = true;

				this.lastAct = ERROR_ACTION;
			}
		}
	}

	if (DEBUG) System.out.println("-- EXIT FROM PARSE METHOD --");  //$NON-NLS-1$
}