/******************************************************************************* * Copyright (c) 2016 ARM Ltd. and others * 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: * QNX Software Systems - initial API and implementation * Wind River Systems, Inc. - bug fixes * ARM Ltd and ARM Germany GmbH - application-specific implementation *******************************************************************************/ package com.arm.cmsis.parser; import org.eclipse.jface.text.rules.ICharacterScanner; import org.eclipse.jface.text.rules.IRule; import org.eclipse.jface.text.rules.IToken; import org.eclipse.jface.text.rules.Token; /** * Recognizes positive integer numbers. */ public class NumberRule implements IRule { private IToken token; public NumberRule(IToken token) { super(); this.token = token; } @Override public IToken evaluate(ICharacterScanner scanner) { scanner.unread(); int prevCh = scanner.read(); int startCh = scanner.read(); int ch; int unreadCount = 1; if (isNumberStart(startCh)) { ch = startCh; if ((prevCh >= 'A' && prevCh <= 'Z') || (prevCh >= 'a' && prevCh <= 'z') || prevCh == '_') { while (isValidIdentifierChar((char) ch)) { ch = scanner.read(); } return Token.UNDEFINED; } if (startCh == '-') { ch = scanner.read(); ++unreadCount; } if (ch == '0') { int xCh = scanner.read(); if (xCh == 'x' || xCh == 'X' || xCh == 'b' || xCh == 'B') { // hex/bin number do { ch = scanner.read(); } while (isHexNumberPart((char) ch)); scanner.unread(); if (!isValidIdentifierChar((char) ch)) { return token; } return Token.UNDEFINED; } scanner.unread(); // assert ch == '0'; } else if (ch == '.') { ch = scanner.read(); ++unreadCount; } if (Character.isDigit((char) ch)) { // need at least one digit do { ch = scanner.read(); } // while (Character.isDigit((char)ch)); while (isHexNumberPart((char) ch)); if (!isNumberSuffix((char) ch)) { scanner.unread(); } return token; } } do { scanner.unread(); } while (--unreadCount > 0); return Token.UNDEFINED; } /** * Checks if start of number. * * @param ch * @return true if it is number start. */ private boolean isNumberStart(int ch) { return ch == '-' || Character.isDigit((char) ch); } /** * Checks if part of hex number; * * @param ch * @return true if it is part of a hex number */ private boolean isHexNumberPart(int ch) { return Character.isDigit((char) ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); } private boolean isNumberSuffix(char ch) { return ch == 'b' || ch == 'B' || ch == 'h' || ch == 'H' || ch == 'd' || ch == 'D' || ch == 'o' || ch == 'O' || ch == 'q' || ch == 'Q'; } private boolean isValidIdentifierChar(char ch) { return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_'; } }