/******************************************************************************* * 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); }