/** * Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.codesourcery.jasm16.ast; import de.codesourcery.jasm16.compiler.ICompilationContext; import de.codesourcery.jasm16.compiler.ISymbolTable; import de.codesourcery.jasm16.exceptions.ParseException; import de.codesourcery.jasm16.lexer.IToken; import de.codesourcery.jasm16.lexer.TokenType; import de.codesourcery.jasm16.parser.IParseContext; import de.codesourcery.jasm16.parser.Operator; import de.codesourcery.jasm16.utils.ITextRegion; import de.codesourcery.jasm16.utils.NumberLiteralHelper; import de.codesourcery.jasm16.utils.TextRegion; /** * An AST node that represents a number literal. * * @author tobias.gierke@code-sourcery.de */ public class NumberNode extends ConstantValueNode { private long value; public NumberNode() { } public NumberNode(long value,ITextRegion range) { super( new TextRegion( range ) ); this.value = value; } @Override protected NumberNode parseInternal(IParseContext context) throws ParseException { final boolean isNegativeNumber; final IToken nextToken = context.peek(); if ( ! nextToken.hasType( TokenType.NUMBER_LITERAL) ) { if ( ! nextToken.hasType( TokenType.OPERATOR) || Operator.fromString( nextToken.getContents() ) != Operator.MINUS ) { throw new ParseException("Expected a number literal",nextToken); } mergeWithAllTokensTextRegion( context.read() ); isNegativeNumber = true; } else { isNegativeNumber = false; } final int offset = context.currentParseIndex(); final IToken token = context.read( "Expected a number",TokenType.NUMBER_LITERAL ); try { this.value = NumberLiteralHelper.parseValue( token.getContents() ); if ( isNegativeNumber ) { this.value = this.value * -1; } } catch(ParseException e) { throw new ParseException( e.getMessage() , offset + e.getTextRegion().getStartingOffset() , e.getTextRegion().getLength() ); } mergeWithAllTokensTextRegion( token ); return this; } @Override public boolean equals(Object obj) { if ( obj == this ) { return true; } if ( obj instanceof NumberNode) { return value == ((NumberNode) obj).value; } return false; } public int getAsByte() throws ParseException { if ( value < Byte.MIN_VALUE | value > 255 ) { throw new ParseException("8-bit value expected but found: "+value,getTextRegion() ); } return (int) value; } public long getValue() { return value; } public int getAsWord() throws ParseException { if ( value < Short.MIN_VALUE || value > 65535 ) { throw new ParseException("16-bit value expected but found: "+value,getTextRegion()); } return (int) value; } public void convertToNegativeNumber() { value = value * -1; } @Override public NumberNode reduce(ICompilationContext context) { return (NumberNode) createCopy( false ); } @Override public boolean isNumberLiteral() { return true; } @Override protected NumberNode copySingleNode() { final NumberNode result = new NumberNode(); result.value = value; return result; } @Override public Long getNumericValue(ISymbolTable context) { return value; } @Override public String toString() { return Long.toString( value ); } @Override public boolean supportsChildNodes() { return false; } @Override public Long calculate(ISymbolTable symbolTable) { return value; } }