package org.jacorb.idl; /* * JacORB - a free Java ORB * * Copyright (C) 1997-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.util.Enumeration; /** * @author Gerald Brose */ public class Case extends IdlSymbol { /** the labels for this case */ public SymbolList case_label_list = null; /** only set after parsing */ private IdlSymbol[] labels; /** this case's element's type's spec */ public ElementSpec element_spec = null; /** the switch type's spec */ TypeSpec type_spec = null; public Case( int num ) { super( num ); } public void setPackage( String s ) { s = parser.pack_replace( s ); if( pack_name.length() > 0 ) pack_name = s + "." + pack_name; else pack_name = s; element_spec.setPackage( s ); Enumeration e = case_label_list.v.elements(); for( ; e.hasMoreElements(); ) { IdlSymbol sym = (IdlSymbol)e.nextElement(); if( sym != null ) sym.setPackage( s ); } if( type_spec != null ) type_spec.setPackage( s ); } /** * pass a reference to the containing union through * to the case elements, which pass it on */ public void setUnion( UnionType ut ) { element_spec.setUnion( ut ); } public void setEnclosingSymbol( IdlSymbol s ) { if( enclosing_symbol != null && enclosing_symbol != s ) throw new RuntimeException( "Compiler Error: trying to reassign container for " + name ); enclosing_symbol = s; element_spec.setEnclosingSymbol( s ); } public void setTypeSpec( TypeSpec s ) { type_spec = s; } private String enumTypeName() { // and enum type name if necessary if( type_spec.type_spec instanceof ConstrTypeSpec ) { return ( (ConstrTypeSpec)type_spec.type_spec ).full_name(); } else if( type_spec.type_spec instanceof ScopedName ) { TypeSpec ts = ( (ScopedName)type_spec.type_spec ).resolvedTypeSpec(); while( ts instanceof ScopedName || ts instanceof AliasTypeSpec ) { if( ts instanceof ScopedName ) ts = ( (ScopedName)ts ).resolvedTypeSpec(); if( ts instanceof AliasTypeSpec ) ts = ( (AliasTypeSpec)ts ).originalType(); } if( ts instanceof ConstrTypeSpec ) return ( (ConstrTypeSpec)ts ).c_type_spec.full_name(); } // all else return null; } public void parse() { element_spec.parse(); labels = new IdlSymbol[ case_label_list.v.size() ]; int label_idx = 0; for( Enumeration e = case_label_list.v.elements(); e.hasMoreElements(); ) { IdlSymbol sym = (IdlSymbol)e.nextElement(); // remember label names labels[ label_idx++ ] = sym; // check that no literals are used in case labels when // the switch type spec doesn't allow it (i.e. bool, int, char) TypeSpec ts = type_spec.typeSpec(); if( sym != null ) { // null means "default" label in union if( ( (ConstExpr)sym ).or_expr.xor_expr.and_expr.shift_expr.add_expr. mult_expr.unary_expr.primary_expr.symbol instanceof Literal ) { Literal literal = (Literal)( (ConstExpr)sym ).or_expr.xor_expr.and_expr.shift_expr.add_expr.mult_expr.unary_expr.primary_expr.symbol; if( ts instanceof ScopedName ) { while( ts instanceof ScopedName ) { ts = ( (ScopedName)type_spec.typeSpec() ).resolvedTypeSpec(); if( ts instanceof AliasTypeSpec ) ts = ( (AliasTypeSpec)ts ).originalType(); } } /* make sure that case label and discriminator value are compatible */ if( ( !( ts instanceof BooleanType || ts instanceof IntType || ts instanceof CharType || ( ts instanceof BaseType && ( (BaseType)ts ).isSwitchType() ) ) ) || ( ts instanceof BooleanType && !( literal.string.equals( "true" ) || literal.string.equals( "false" ) ) ) || ( ts instanceof CharType && !literal.string.startsWith( "'" ) ) ) { parser.error( "Illegal case label <" + literal.string + "> for switch type " + type_spec.typeName(), token ); return; // abort parsing the case here (we'd get other errors) } if( ts instanceof IntType ) { try { Integer.parseInt( literal.string ); } catch( NumberFormatException ne ) { parser.error( "Illegal case label <" + literal.string + "> for integral switch type " + type_spec.typeName(), token ); return; } } } } // if the switch type for the union we're part of // is an enumeration type, the enum type name has // been set. if( enumTypeName() == null ) { // no enum if( sym != null ) { // null means "default" label in union sym.parse(); } } else { // case label const expressions refer to enum values if( sym != null ) { // now, if this is not the default case label... // get the case label (a const expr) as a scoped name ScopedName sn = (ScopedName)( (ConstExpr)sym ).or_expr.xor_expr.and_expr. shift_expr.add_expr.mult_expr.unary_expr.primary_expr.symbol; // replace the original case label by a new, fully // scoped name for the enum type value int idx = case_label_list.v.indexOf( sym ); sym = new ScopedName( new_num() ); ( (ScopedName)sym ).setId( sn.typeName ); sym.setPackage( pack_name ); sym.parse(); case_label_list.v.setElementAt( sym, idx ); } } } // for } IdlSymbol[] getLabels() { if (labels == null) { throw new RuntimeException ("Case labels not initialized!" ); } return labels; } public void print( java.io.PrintWriter ps ) { element_spec.print( ps ); } }