Package etch.compiler.ast

Source Code of etch.compiler.ast.Constant

/* $Id: Constant.java 742162 2009-02-08 20:54:34Z dixson $
*
* Copyright 2007-2008 Cisco Systems Inc.
*
* 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 etch.compiler.ast;

import java.util.Map;

import etch.compiler.Backend;
import etch.compiler.EtchGrammarConstants;
import etch.compiler.ParseException;
import etch.compiler.Token;

/**
* A named constant declaration from the etch idl.
*/
public class Constant extends Named<Service>
{
  /**
   * Constructs the Constant.
   *
   * @param intf
   * @param name
   * @param nOpts
   * @param type
   * @param value
   */
  public Constant( Service intf, Name name, Map<String, Opt> nOpts,
    TypeRef type, Token value )
  {
    super( intf, name, nOpts );
    this.type = type;
    this.value = value;
  }
 
  private final TypeRef type;
 
  private final Token value;
 
  /**
   * @return the type of this constant.
   */
  public TypeRef type()
  {
    return type;
  }
 
  /**
   * @return the value of this constant.
   */
  public Token value()
  {
    return value;
  }
 
  @Override
  public String vname( Backend helper )
  {
    return null;
  }
 
  @Override
  public String fqname()
  {
    return null;
  }
 
//  @Override
//  public Integer id()
//  {
//    return null;
//  }
 
  @Override
  public String toString()
  {
    return String.format( "const %s %s = %s", type, name().name, value );
  }

  @Override
  public void dump( String indent )
  {
    System.out.printf( "%sconst %s %s = %s\n", indent, type, name().name, value );
   
    String sIndent = indent+"  ";
   
    for (String s: descr())
      System.out.printf( "%sdescr %s\n", sIndent, s );
  }

  @Override
  public void check() throws ParseException
  {
    checkConstantName( name() );
   
    // types: boolean, byte, short, int, long, float, double, string
    // values: true, false, integer, octal, hex, binary, decimal, str
   
    switch (type.type().kind)
    {
      case EtchGrammarConstants.BOOLEAN:
        if (!isBoolean( value ))
          incompatValueForType( type, value );
        break;
      case EtchGrammarConstants.BYTE:
        if (!isByte( value ))
          incompatValueForType( type, value );
        break;
      case EtchGrammarConstants.SHORT:
        if (!isShort( value ))
          incompatValueForType( type, value );
        break;
      case EtchGrammarConstants.INT:
        if (!isInt( value ))
          incompatValueForType( type, value );
        break;
      case EtchGrammarConstants.LONG:
        if (!isLong( value ))
          incompatValueForType( type, value );
        break;
      case EtchGrammarConstants.FLOAT:
        if (!isFloat( value ))
          incompatValueForType( type, value );
        break;
      case EtchGrammarConstants.DOUBLE:
        if (!isDouble( value ))
          incompatValueForType( type, value );
        break;
      case EtchGrammarConstants.STRING:
        if (!isString( value ))
          incompatValueForType( type, value );
        break;
      default:
        throw new ParseException( "unknown type "+type.type() );
    }
  }

  private void incompatValueForType( TypeRef t, Token v ) throws ParseException
  {
    throw new ParseException( String.format(
      "incompatible value for type %s at line %d: %s",
      type.type(), value.beginLine, value ) );
  }

  private boolean isBoolean( Token v )
  {
    if (v.kind == EtchGrammarConstants.TRUE)
      return true;
    if (v.kind == EtchGrammarConstants.FALSE)
      return true;
    return false;
  }

  private boolean isByte( Token v )
  {
    if (v.kind == EtchGrammarConstants.INTEGER)
      return checkByte( v.image, 10 );
    if (v.kind == EtchGrammarConstants.OCTAL)
      return v.image.startsWith( "0" ) && checkByte( v.image.substring( 1 ), 8 );
    if (v.kind == EtchGrammarConstants.HEX)
      return v.image.toLowerCase().startsWith( "0x" ) && checkByte( v.image.substring( 2 ), 16 );
    if (v.kind == EtchGrammarConstants.BINARY)
      return v.image.toLowerCase().startsWith( "0b" ) && checkByte( v.image.substring( 2 ), 2 );
    return false;
  }

  private boolean checkByte( String s, int radix )
  {
    if (radix == 10)
      return checkNumber( s, radix, -128, 127 );
    return checkNumber( s, radix, 0, 255 );
  }

  private boolean isShort( Token v )
  {
    if (v.kind == EtchGrammarConstants.INTEGER)
      return checkShort( v.image, 10 );
    if (v.kind == EtchGrammarConstants.OCTAL)
      return v.image.startsWith( "0" ) && checkShort( v.image.substring( 1 ), 8 );
    if (v.kind == EtchGrammarConstants.HEX)
      return v.image.toLowerCase().startsWith( "0x" ) && checkShort( v.image.substring( 2 ), 16 );
    if (v.kind == EtchGrammarConstants.BINARY)
      return v.image.toLowerCase().startsWith( "0b" ) && checkShort( v.image.substring( 2 ), 2 );
    return false;
  }

  private boolean checkShort( String s, int radix )
  {
    if (radix == 10)
      return checkNumber( s, radix, -32768, 32767 );
    return checkNumber( s, radix, 0, 65535 );
  }

  private boolean isInt( Token v )
  {
    if (v.kind == EtchGrammarConstants.INTEGER)
      return checkInt( v.image, 10 );
    if (v.kind == EtchGrammarConstants.OCTAL)
      return v.image.startsWith( "0" ) && checkInt( v.image.substring( 1 ), 8 );
    if (v.kind == EtchGrammarConstants.HEX)
      return v.image.toLowerCase().startsWith( "0x" ) && checkInt( v.image.substring( 2 ), 16 );
    if (v.kind == EtchGrammarConstants.BINARY)
      return v.image.toLowerCase().startsWith( "0b" ) && checkInt( v.image.substring( 2 ), 2 );
    return false;
  }

  private boolean checkInt( String s, int radix )
  {
    if (radix == 10)
      return checkNumber( s, radix, -2147483648, 2147483647 );
    return checkNumber( s, radix, 0, 4294967295L );
  }

  private boolean isLong( Token v )
  {
    if (v.kind == EtchGrammarConstants.INTEGER)
      return checkLong( v.image, 10 );
    if (v.kind == EtchGrammarConstants.OCTAL)
      return v.image.startsWith( "0" ) && checkLong( v.image.substring( 1 ), 8 );
    if (v.kind == EtchGrammarConstants.HEX)
      return v.image.toLowerCase().startsWith( "0x" ) && checkLong( v.image.substring( 2 ), 16 );
    if (v.kind == EtchGrammarConstants.BINARY)
      return v.image.toLowerCase().startsWith( "0b" ) && checkLong( v.image.substring( 2 ), 2 );
    return false;
  }

  private boolean checkLong( String s, int radix )
  {
    if (radix == 10)
      return checkNumber( s, radix, -9223372036854775808L, 9223372036854775807L );
    return checkNumber( s, radix, 0, -1L );
  }

  private boolean checkNumber( String s, int radix, long min, long max )
  {
    // TODO this needs to work better for non-decimal radix
    try
    {
      long l = Long.parseLong( s, radix );
      return l >= min && l <= max;
    }
    catch ( NumberFormatException e )
    {
      return false;
    }
  }

  private boolean isFloat( Token v )
  {
    // TODO implement some sort of float value checking...
    if (v.kind == EtchGrammarConstants.INTEGER)
      return true;
    if (v.kind == EtchGrammarConstants.OCTAL)
      return true;
    if (v.kind == EtchGrammarConstants.HEX)
      return true;
    if (v.kind == EtchGrammarConstants.BINARY)
      return true;
    if (v.kind == EtchGrammarConstants.DECIMAL)
      return true;
    return false;
  }

  private boolean isDouble( Token v )
  {
    // TODO implement some sort of double value checking...
    if (v.kind == EtchGrammarConstants.INTEGER)
      return true;
    if (v.kind == EtchGrammarConstants.OCTAL)
      return true;
    if (v.kind == EtchGrammarConstants.HEX)
      return true;
    if (v.kind == EtchGrammarConstants.BINARY)
      return true;
    if (v.kind == EtchGrammarConstants.DECIMAL)
      return true;
    return false;
  }

  private boolean isString( Token v )
  {
    if (v.kind == EtchGrammarConstants.STR)
      return true;
    return false;
  }

  @Override
  public void treewalk( TreeWalker walker ) throws ParseException
  {
    walker.preConstant( this );
   
    type.treewalk( walker );
   
    walker.postConstant( this );
  }
}
TOP

Related Classes of etch.compiler.ast.Constant

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.