blob: 1e4938ee4794337ecae358f1d5fffefa645014cd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2018 Open Canarias S.L. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Adolfo Sanchez-Barbudo Herrera (Open Canarias)- Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.lpg;
import java.util.ArrayList;
import lpg.runtime.ErrorToken;
import lpg.runtime.ILexStream;
import lpg.runtime.IToken;
import lpg.runtime.ParseErrorCodes;
import lpg.runtime.PrsStream;
/**
* This DerivedLexStream will be used in favour of the LpgLexStream for the
* OCLLexer, so that some customization are introduced and exploited by the
* generated OCLLexer.
*
* @since 3.0
*/
public class DerivedPrsStream extends PrsStream {
private BasicEnvironment environment;
public DerivedPrsStream(BasicEnvironment env, ILexStream iLexStream) {
super(iLexStream);
this.environment = env;
}
/**
* This function returns the index of the token element containing the
* offset specified. If such a token does not exist, it returns the negation
* of the index of the element immediately preceding the offset.
*
* @since 1.3
*/
public ErrorToken getErrorTokenAtCharacter(int offset) {
ErrorToken bestToken = null;
for (int i = getSize(); --i >= 0;) {
IToken token = getTokenAt(i);
if (!(token instanceof ErrorToken)) {
break;
}
IToken errorToken = ((ErrorToken) token).getErrorToken();
if (offset >= errorToken.getStartOffset()
&& offset <= errorToken.getEndOffset()) {
if ((bestToken == null)
|| ((bestToken.getStartOffset() <= errorToken
.getStartOffset()) && (token.getEndOffset() <= errorToken
.getEndOffset()))) {
bestToken = (ErrorToken) token;
}
}
}
return bestToken;
}
/**
* @since 1.3
*/
public int getErrorTokens() {
return getTokens().size() - getStreamLength();
}
/**
* Overridden to search only the non-Error nodes, which are the only tokens
* in monotonic order.
*/
@Override
public int getTokenIndexAtCharacter(int offset) {
int low = 0;
int high = getSize();
while (high > low) {
IToken highToken = getTokenAt(high - 1);
if (!(highToken instanceof ErrorToken)) {
break;
}
high--;
}
while (high > low) {
int mid = (high + low) / 2;
IToken mid_element = getTokenAt(mid);
if (offset >= mid_element.getStartOffset()
&& offset <= mid_element.getEndOffset()) {
return mid;
} else if (offset < mid_element.getStartOffset()) {
high = mid;
} else {
low = mid + 1;
}
}
return -(low - 1);
}
@Override
public int makeErrorToken(int firsttok, int lasttok, int errortok, int kind) {
@SuppressWarnings("unchecked")
ArrayList<IToken> tokens = getTokens();
int index = tokens.size(); // the next index
//
// Note that when creating an error token, we do not remap its kind.
// Since this is not a lexical operation, it is the responsibility of
// the calling program (a parser driver) to pass to us the proper kind
// that it wants for an error token.
//
IToken token = new ErrorToken(getIToken(firsttok), getIToken(lasttok),
getIToken(errortok), getStartOffset(firsttok),
getEndOffset(lasttok), kind) {
@Override
public String toString() {
if (getIPrsStream() == null) {
return "<toString>"; //$NON-NLS-1$
}
int startOffset = getStartOffset();
int length = getEndOffset() + 1 - startOffset;
if (length < 0) {
length = -length - 1;
startOffset = getEndOffset();
}
if ((startOffset + length) > getIPrsStream().getInputChars().length) {
return String.valueOf(IToken.EOF);
}
return new String(getIPrsStream().getInputChars(), startOffset,
length);
}
};
token.setTokenIndex(index);
tokens.add(token);
token.setAdjunctIndex(getAdjuncts().size());
return index;
}
/**
*
* @since 3.0
*/
@Override
public void reportError(int errorCode, int leftToken, int errorToken,
int rightToken, String[] errorInfo) {
if (environment == null) {
super.reportError(errorCode, leftToken, errorToken, rightToken, errorInfo);
} else {
// TODO Revise this. BasicEnvironment.parserError doesn't have a String[] argument
String tokenText = errorInfo.length > 0 ? errorInfo[0] : ""; //$NON-NLS-1$
if (errorCode == PrsStream.DELETION_CODE || errorCode == PrsStream.MISPLACED_CODE) {
tokenText = ""; //$NON-NLS-1$
}
environment.parserError(errorCode, leftToken, rightToken, tokenText);
}
}
/**
* Report error message for given error_token.
*
* @param error_token
* the error taken index
* @param msg
* the message to report
*
* @since 1.3
*/
public final void reportErrorTokenMessage(int error_token, String msg) {
int firsttok = super.getFirstRealToken(error_token);
int lasttok = super.getLastRealToken(error_token);
if (firsttok > lasttok) {
reportError(ParseErrorCodes.INSERTION_CODE, lasttok,
lasttok, msg);
} else {
reportError(ParseErrorCodes.SUBSTITUTION_CODE, firsttok,
lasttok, msg);
}
}
}