/*******************************************************************************
* Copyright (c) 2015 Bruno Medeiros and other Contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.tooling.parser.lexer;
import melnorme.lang.utils.parse.ICharacterReader;
import melnorme.utilbox.misc.NumberUtil;
public abstract class NumberLexingRule implements IPredicateLexingRule {
public NumberLexingRule() {
super();
}
@Override
public boolean doEvaluate(ICharacterReader reader) {
int radix = 10;
if(reader.tryConsume('0')) {
if(reader.tryConsume('b')) {
radix = 2;
}
else if(reader.tryConsume('o')) {
radix = 8;
}
else if(reader.tryConsume('x')) {
radix = 16;
}
} else {
if(!consumeDigit(reader, radix)) {
return false;
}
}
consumeDigits(reader, radix, true);
if (consumeIntSuffix(reader)) {
return true;
}
tryConsumeFractionalPart(reader, radix);
return true;
}
protected boolean consumeDigits(ICharacterReader reader, int radix, boolean allowUnderScore) {
boolean consumedAny = false;
while(consumeDigit(reader, radix) || (allowUnderScore && reader.tryConsume('_'))) {
consumedAny = true;
}
return consumedAny;
}
protected abstract boolean consumeIntSuffix(ICharacterReader reader);
protected void tryConsumeFractionalPart(ICharacterReader reader, int radix) {
boolean hasPrefix = radix != 10;
if(!hasPrefix) {
consumeFractionalPart(reader, radix);
}
}
protected void consumeFractionalPart(ICharacterReader reader, int radix) {
if(reader.lookahead() != '.' || !isAllowedAfterFractionDot(reader.lookahead(1))) {
return;
}
reader.consume(); // Consume dot
boolean hasFractionalDigits = tryConsumeFractionalPartDigits(reader, radix);
if(hasFractionalDigits && (reader.tryConsume('e') || reader.tryConsume('E'))) {
if(reader.tryConsume('+') || reader.tryConsume('-')) {
}
consumeDigits(reader, 10, true);
}
consumeFloatSuffix(reader);
}
protected boolean isAllowedAfterFractionDot(int afterDot) {
return afterDot == -1 || !(afterDot == '.' || afterDot == '_' || Character.isLetter(afterDot));
}
protected boolean tryConsumeFractionalPartDigits(ICharacterReader reader, int radix) {
if(consumeDigit(reader, radix)) {
consumeDigits(reader, radix, true);
return true;
}
return false;
}
protected static boolean consumeDigit(ICharacterReader reader, int radix) {
if(reader.hasCharAhead() && NumberUtil.isDigit(reader.lookaheadChar(), radix)) {
reader.consume();
return true;
}
return false;
}
protected abstract boolean consumeFloatSuffix(ICharacterReader reader);
}