home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
fnb101.zip
/
Lib
/
site-packages
/
Fnorb
/
parser
/
IDLParser.py
< prev
next >
Wrap
Text File
|
1999-06-28
|
59KB
|
1,984 lines
#!/usr/bin/env python
#############################################################################
# Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1997, 1998, 1999
# All Rights Reserved.
#
# The software contained on this media is the property of the DSTC Pty
# Ltd. Use of this software is strictly in accordance with the
# license agreement in the accompanying LICENSE.HTML file. If your
# distribution of this software does not contain a LICENSE.HTML file
# then you have no rights to use this software in any manner and
# should contact DSTC at the address below to determine an appropriate
# licensing arrangement.
#
# DSTC Pty Ltd
# Level 7, GP South
# Staff House Road
# University of Queensland
# St Lucia, 4072
# Australia
# Tel: +61 7 3365 4310
# Fax: +61 7 3365 4311
# Email: enquiries@dstc.edu.au
#
# This software is being provided "AS IS" without warranty of any
# kind. In no event shall DSTC Pty Ltd be liable for damage of any
# kind arising out of or in connection with the use or performance of
# this software.
#
# Project: Fnorb
# File: $Source: /units/arch/src/Fnorb/parser/RCS/IDLParser.py,v $
# Version: @(#)$RCSfile: IDLParser.py,v $ $Revision: 1.12 $
#
#############################################################################
""" Parser for OMG IDL. """
# Standard/built-in modules.
import new, string, sys, types
# Fnorb modules.
from Fnorb.orb import CORBA, Fixed, Limits, Util
# Fnorb extension modules.
import bison
# Parser modules.
import Declarator, Prefix, Stack
class IDLParser:
""" Parser for OMG IDL.
This class implements the semantic actions for the IDL parser. The actual
parsing engine is implemented in 'C' using 'flex' and 'bison'.
"""
#########################################################################
# Parser interface.
#########################################################################
def parse(self, repository, filename, yyin):
""" Parse some IDL!
'repository' is the interface repository (IFR) to be populated.
'filename' is the filename of the top-level IDL file.
'yyin' is an open file object to read the IDL from.
"""
self.__repository = repository
self.__filename = filename
# Initialise the various data structures used during parsing.
self.__initialise()
# Do the parsing!
result = bison.yyparse(self, yyin)
# Clean up!
self.__cleanup()
return (result, self.__top_level_definitions)
def yyerror(self, message):
""" Error function called from the 'bison' parser. """
sys.stderr.write("Error: %s on line %d of %s\n" % \
(message, bison.yylineno(), self.__current_file))
return
def yywarning(self, message):
""" Warning function. """
sys.stderr.write("Warning: %s on line %d of %s\n" % \
(message, bison.yylineno(), self.__current_file))
return
#########################################################################
# Semantic actions (called from 'grammar.y').
#########################################################################
def specification_start(self):
""" specification: """
# The container stack initially contains just the repository.
self.__container_stack = Stack.Stack()
self.__container_stack.push(self.__repository)
return
def specification_end(self):
""" specification: definition_PLUS """
# Report an error for any interfaces that were 'forward' declared but
# not defined!
self.__check_forward_interfaces()
# Pop the repository from the container stack, and make sure that the
# stack really is empty!
self.__container_stack.pop()
assert(len(self.__container_stack) == 0)
return
def module_header(self, name):
""" MODULE IDENTIFIER """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
module = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new module.
if module is None:
# Currently the version is always "1.0"!
version = "1.0"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new module definition in the container.
module = container.create_module(ifr_id, name, version)
# If the module is defined at the global scope of the top-level IDL
# file then add it to our list of top-level definitions.
if self.__is_a_top_level_definition(module):
self.__top_level_definitions.append(module)
# Otherwise, a definition with this name already exists.
else:
# If it is a module definition then we just "re-open" it to allow
# more definitions to be added. If it is not a module definition
# then it is illegal!
if module._get_def_kind() != CORBA.dk_Module:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
# If the module is defined at the global scope of the top-level IDL
# file then add it to our list of top-level definitions.
#
# We have to do this here as the first occurence of the module may
# have been in a file that was '#included'.
if self.__is_a_top_level_definition(module):
self.__top_level_definitions.append(module)
# fixme: Check for ID compatability in the case of '#pragma ID'?
pass
# Push the module onto the container stack.
self.__container_stack.push(module)
# Push the new prefix onto the prefix stack.
self.__prefix_stack.push(self.__create_prefix(prefix, name))
return
def module_body(self):
""" '{' definition_STAR '}' """
# Pop the container and prefix from the stacks.
self.__container_stack.pop()
self.__prefix_stack.pop()
return
def interface_dcl_header(self, name, base_interfaces):
""" INTERFACE IDENTIFIER inheritance_spec_OPT """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
interface = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new interface.
if interface is None:
# Currently the version is always "1.0"!
version = "1.0"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new interface definition in the container.
interface = container.create_interface(ifr_id, name, version, [])
# If the interface is defined at the global scope of the top-level
# IDL file then add it to our list of top-level definitions.
if self.__is_a_top_level_definition(interface):
self.__top_level_definitions.append(interface)
# Otherwise, a definition with this name already exists.
else:
# If it is *not* an interface definition then it is definitely
# illegal!
if interface._get_def_kind() != CORBA.dk_Interface:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
# If it *is* an interface definition then it must be a forward
# declaration. If not then it is also illegal!
if interface._get_version() != 'forward':
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
# fixme: Check for ID compatability in the case of '#pragma ID'?
pass
# 'Move' the interface definition to the same container (this has
# the side-effect of placing it last in the containers list of
# contents ;^)
interface.move(container, name, "1.0")
# Delete the interface from the dictionary containing forward
# declared but undefined interfaces,
del self.__forward_interfaces[interface._get_id()]
# Check the base interfaces.
for base in base_interfaces:
# Make sure that the base interface is not a forward delcaration.
if base._get_version() == 'forward':
self.yyerror("Interface '%s' not defined" % base._get_name())
raise bison.YYERROR
# Make sure that some poor shmuck is not attempting to make the
# interface inherit from itself!
#
# fixme: Will this work in the presence of '#pragma ID'?
if base._get_id() == interface._get_id():
self.yyerror("Interface '%s' inherits from itself!" % name)
raise bison.YYERROR
# Update the list of base interfaces.
interface._set_base_interfaces(base_interfaces)
# Push the interface onto the container stack.
self.__container_stack.push(interface)
# Push a new prefix onto the prefix stack.
self.__prefix_stack.push(self.__create_prefix(prefix, name))
return interface
def interface_dcl_body(self, interface):
""" '{' export_STAR '}' """
# Get the interface description.
description = interface.describe_interface()
# Get the names of all of the interface's operations and attributes.
names = map(lambda o: o.name, description.operations)
names = names + map(lambda a: a.name, description.attributes)
# Add the interface to the interface dictionary.
self.__interfaces[interface._get_id()] = names
# Get the names of all inherited operations and attributes.
inherited = self.__get_inherited_operations(interface, [])
# Make sure there are no clashes!
if len(inherited) > 0:
for name in names:
if name in inherited:
self.yyerror("Overloaded operation/attribute '%s'" % name)
raise bison.YYERROR
# Pop the container and prefix from the stacks.
self.__container_stack.pop()
self.__prefix_stack.pop()
return
def foward_dcl(self, name):
""" forward_dcl: INTERFACE IDENTIFIER """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
interface = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new interface.
if interface is None:
# Currently the version is always "1.0"!
version = "1.0"
# Generate a repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new interface definition in the container and tag it
# with a version of "forward".
interface = container.create_interface(ifr_id, name, "forward", [])
# If the interface is defined at the global scope of the top-level
# IDL file then add it to our list of top-level definitions.
if self.__is_a_top_level_definition(interface):
self.__top_level_definitions.append(interface)
# Add the interface to the dictionary of forward declared but
# undefined interfaces.
self.__forward_interfaces[ifr_id] = (interface, bison.yylineno())
# Otherwise, a definition with this name already exists.
else:
# If it is *not* an interface definition then it is illegal!
if interface._get_def_kind() != CORBA.dk_Interface:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
# fixme: Check for ID compatability in the case of '#pragma ID'?
pass
return
def inheritance_spec_empty(self):
""" inheritance_spec: /* empty */ """
return [] # [InterfaceDef]
def inheritance_spec_full(self, scoped_names):
""" inheritance_spec: ':' scoped_name_CSV_PLUS """
# Get the container from the stack.
container = self.__container_stack.get()
# Find the interface definition for each scoped name.
base_interfaces = []
for scoped_name in scoped_names:
# Lookup the definition.
interface = self.__find_scoped_name(container, scoped_name)
if interface is None:
raise bison.YYERROR
# If it is *not* an interface definition then it is illegal!
if interface._get_def_kind() != CORBA.dk_Interface:
self.yyerror("'%s' is not an interface" % scoped_name)
raise bison.YYERROR
base_interfaces.append(interface)
return base_interfaces
def scoped_name_absolute(self, identifier):
""" scoped_name: SCOPE_DELIMITER IDENTIFIER """
return "::" + identifier
def scoped_name_relative(self, scoped_name, identifier):
""" scoped_name: scoped_name SCOPE_DELIMITER IDENTIFIER """
return scoped_name + "::" + identifier
def const_dcl(self, type_def, name, any):
""" const_dcl: CONST const_type IDENTIFIER '=' const_expr """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
constant = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new constant.
if constant is None:
# Make sure that the value is of the appropriate type.
if not self.__check_constant_type(type_def, any):
self.yyerror("Constant '%s' invalid value type" % name)
raise bison.YYERROR
# Make sure that the value is within the limits of the type, and
# coerce it if necessary.
(result, value) = self.__check_limits(type_def, any)
if not result:
self.yyerror("Constant '%s' out of range" % name)
raise bison.YYERROR
# Wrap the coerced value back in an 'Any' of the appropriate type.
any = CORBA.Any(type_def._get_type(), value)
# Currently the version is always "1.0"!
version = "1.0"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new constant definition in the container.
constant = container.create_constant(ifr_id, name, version,
type_def, any)
# If the constant is defined at the global scope of the top-level
# IDL file then add it to our list of top-level definitions.
if self.__is_a_top_level_definition(constant):
self.__top_level_definitions.append(constant)
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
return constant
# Valid types for constant expressions.
__CONST_TYPES = [CORBA.pk_short,
CORBA.pk_long,
CORBA.pk_ushort,
CORBA.pk_ulong,
CORBA.pk_char,
CORBA.pk_boolean,
CORBA.pk_float,
CORBA.pk_double,
CORBA.pk_string,
CORBA.pk_longlong,
CORBA.pk_ulonglong,
CORBA.pk_longdouble,
CORBA.pk_wchar,
CORBA.pk_wstring]
def const_type_scoped_name(self, scoped_name):
""" const_type: scoped_name """
# Get the container from the stack.
container = self.__container_stack.get()
# Lookup the definition referenced by the scoped name.
definition = self.__find_scoped_name(container, scoped_name)
# Unwind any 'typedef' chain.
definition = self.__unwind_typedef_chain(definition)
# Make sure that the definition is either:-
#
# 1) One of the following primitive types:-
#
# integer, char, wchar, boolean, floating point, string, wstring
#
# 2) Of type 'fixed'.
if definition._get_def_kind() == CORBA.dk_Primitive \
and definition._get_kind() in IDLParser.__CONST_TYPES:
pass
elif definition._get_def_kind() == CORBA.dk_Fixed:
pass
else:
self.yyerror("Invalid constant type '%s'" % scoped_name)
raise bison.YYERROR
return definition
# The arguments to constant expression operators are 'Any's, and the
# operations are implemented in the 'Any' module.
def or_expr(self, x, y):
""" or_expr: or_expr '|' xor_expr """
return x | y
def xor_expr(self, x, y):
""" xor_expr: xor_expr '^' and_expr """
return x ^ y
def and_expr(self, x, y):
""" and_expr: and_expr '&' shift_expr """
return x & y
def shift_expr_right(self, x, y):
""" shift_expr: shift_expr RIGHT_SHIFT add_expr """
return x >> y
def shift_expr_left(self, x, y):
""" shift_expr: shift_expr LEFT_SHIFT add_expr """
return x << y
def add_expr_add(self, x, y):
""" add_expr: add_expr '+' mult_expr """
return x + y
def add_expr_subtract(self, x, y):
""" add_expr: add_expr '-' mult_expr """
return x - y
def mult_expr_multiply(self, x, y):
""" mult_expr: mult_expr '*' unary_expr """
return x * y
def mult_expr_divide(self, x, y):
""" mult_expr: mult_expr '/' unary_expr """
return x / y
def mult_expr_mod(self, x, y):
""" mult_expr: mult_expr '%' unary_expr """
return x % y
def unary_expr_neg(self, x):
""" unary_expr: '-' primary_expr """
return -x
def unary_expr_pos(self, x):
""" unary_expr: '+' primary_expr """
return +x
def unary_expr_invert(self, x):
""" unary_expr: '~' primary_expr """
return ~x
def primary_expr_scoped_name(self, scoped_name):
""" primary_expr: scoped_name """
# Get the container from the stack.
container = self.__container_stack.get()
# Lookup the definition referenced by the scoped name.
definition = self.__find_scoped_name(container, scoped_name)
if definition is None:
raise bison.YYERROR
# If it is not a constant definition then it is illegal!
if definition._get_def_kind() != CORBA.dk_Constant:
self.yyerror("'%s' is not a constant expression" % scoped_name)
raise bison.YYERROR
# Return the constant's value (an 'Any').
return definition._get_value()
def literal_integer_literal(self, value):
""" literal: INTEGER_LITERAL """
# We get integer literals as the raw string token from the lexer.
#
# fixme: Should we do this for floating point literals as well?
# All integer literals are converted to Python *long* integers and then
# coerced back as appropriate.
return CORBA.Any(CORBA.TC_longlong, eval(value + "L"))
def literal_string_literal(self, value):
""" literal: STRING_LITERAL """
# Evaluate the string containing the string!
return CORBA.Any(CORBA.TC_string, eval(value))
def literal_character_literal(self, value):
""" literal: CHARACTER_LITERAL """
# Evaluate the string containing the character!
return CORBA.Any(CORBA.TC_char, eval(value))
def literal_fixed_pt_literal(self, value):
""" literal: FIXED_PT_LITERAL """
# Fixed point values are instances of the 'Fixed' class.
fixed = new.instance(Fixed.Fixed, {})
# Initialise the instance from the literal.
fixed._fnorb_from_literal(value)
return CORBA.Any(fixed._fnorb_typecode(), fixed)
def literal_floating_pt_literal(self, value):
""" literal: FLOATING_PT_LITERAL """
return CORBA.Any(CORBA.TC_double, value)
def boolean_literal_true(self):
""" boolean_literal: TRUE """
return CORBA.Any(CORBA.TC_boolean, 1)
def boolean_literal_false(self):
""" boolean_literal: FALSE """
return CORBA.Any(CORBA.TC_boolean, 0)
def positive_int_const(self, any):
""" positive_int_const: const_expr """
# Get the typecode's 'kind'.
kind = any.typecode().kind()
# Make sure that it really is a positive, integer ;^)
if kind not in IDLParser.__TK_INT or any.value() < 0:
self.yyerror("Positive integer value required")
raise bison.YYERROR
# Extract the value from the 'Any'.
return any.value()
def type_declarator(self, type_def, declarators):
""" type_declarator: type_spec declarators """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Create a 'typedef' definition for each declarator.
for declarator in declarators:
# Get the name of the declarator.
name = declarator.name()
# Does the container already contain a definition with this name?
definition = container.lookup(name)
# If there is *no* definition with this name then we can safely
# create a new 'typedef' definition.
if definition is None:
# Currently the version is always "1.0"!
version = "1.0"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# If this is an array declarator.
if isinstance(declarator, Declarator.ArrayDeclarator):
# Get the array dimensions.
dimensions = declarator.dimensions()
# Create the array type.
actual_type_def = self.__create_array(type_def, dimensions)
# Otherwise it is a simple declarator.
else:
actual_type_def = type_def
# Create a new 'typedef' definition in the container.
definition = container.create_alias(ifr_id, name, version,
actual_type_def)
# If the 'typedef' is defined at the global scope of the
# top-level IDL file then add it to our list of top-level
# definitions.
if self.__is_a_top_level_definition(definition):
self.__top_level_definitions.append(definition)
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
return
def simple_declarator(self, name):
""" simple_declarator: IDENTIFIER """
return Declarator.SimpleDeclarator(name)
def float_type(self):
""" floating_pt_type: FLOAT """
return self.__repository.get_primitive(CORBA.pk_float)
def double_type(self):
""" floating_pt_type: DOUBLE """
return self.__repository.get_primitive(CORBA.pk_double)
def longdouble_type(self):
""" floating_pt_type: LONG DOUBLE """
self.yywarning("'long double' not supported by Fnorb runtime")
return self.__repository.get_primitive(CORBA.pk_longdouble)
def signed_short_int(self):
""" signed_short_int: SHORT """
return self.__repository.get_primitive(CORBA.pk_short)
def signed_long_int(self):
""" signed_long_int: LONG """
return self.__repository.get_primitive(CORBA.pk_long)
def signed_longlong_int(self):
""" signed_longlong_int: LONG LONG"""
return self.__repository.get_primitive(CORBA.pk_longlong)
def unsigned_short_int(self):
""" unsigned_short_int: UNSIGNED SHORT """
return self.__repository.get_primitive(CORBA.pk_ushort)
def unsigned_long_int(self):
""" unsigned_long_int: UNSIGNED LONG """
return self.__repository.get_primitive(CORBA.pk_ulong)
def unsigned_longlong_int(self):
""" unsigned_longlong_int: UNSIGNED LONG LONG"""
return self.__repository.get_primitive(CORBA.pk_ulonglong)
def char_type(self):
""" char_type: CHAR """
return self.__repository.get_primitive(CORBA.pk_char)
def wide_char_type(self):
""" wide_char_type: WCHAR """
self.yywarning("'wchar' not supported by Fnorb runtime")
return self.__repository.get_primitive(CORBA.pk_wchar)
def boolean_type(self):
""" boolean_type: BOOLEAN """
return self.__repository.get_primitive(CORBA.pk_boolean)
def octet_type(self):
""" octet_type: OCTET """
return self.__repository.get_primitive(CORBA.pk_octet)
def any_type(self):
""" any_type: IDL_ANY """
return self.__repository.get_primitive(CORBA.pk_any)
def object_type(self):
""" object_type: OBJECT """
return self.__repository.get_primitive(CORBA.pk_objref)
def struct_type_header(self, name):
""" struct_type: STRUCT IDENTIFIER """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
struct = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new structure definition.
if struct is None:
# Set the version to "wip" (for Work In Progress) to allow the
# detection of recursive types.
version = "wip"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new structure definition in the container.
struct = container.create_struct(ifr_id, name, version, [])
# If the structure is defined at the global scope of the top-level
# IDL file then add it to our list of top-level definitions.
if self.__is_a_top_level_definition(struct):
self.__top_level_definitions.append(struct)
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
# Push the structure onto the container stack.
self.__container_stack.push(struct)
# Push a new prefix onto the prefix stack.
self.__prefix_stack.push(self.__create_prefix(prefix, name))
return struct
def struct_type_body(self, struct, members):
""" struct_type: '{' member_PLUS '}' """
# Make sure that all member names are unique.
dict = {}
for member in members:
if dict.has_key(member.name):
self.yyerror("Duplicate member name '%s'" % name)
raise bison.YYERROR
dict[member.name] = None
# Check for recursive members.
if self.__is_recursive_member(member.type_def):
# Get the repository id of the recursive structure.
ifr_id = member.type_def._get_element_type_def()._get_id()
# Find out how deep the recursion is.
offset = self.__get_recursion_depth(struct, ifr_id)
# Get the bound of the sequence type.
length = member.type.length()
# Replace the sequence typecode with a recursive sequence
# typecode.
member.type = CORBA.RecursiveSequenceTypeCode(length, offset)
# Fixup the version.
struct._set_version("1.0")
# Update the structure definition.
struct._set_members(members)
# Pop the container and prefix from the stacks.
self.__container_stack.pop()
self.__prefix_stack.pop()
return struct
def member(self, type_def, declarators):
""" member: type_spec declarators """
members = []
for declarator in declarators:
# If this is an array declarator.
if isinstance(declarator, Declarator.ArrayDeclarator):
# Get the array dimensions.
dimensions = declarator.dimensions()
# Create the array type.
actual_type_def = self.__create_array(type_def, dimensions)
# Otherwise it is a simple declarator.
else:
actual_type_def = type_def
# Create a 'StructMember' instance.
members.append(CORBA.StructMember(declarator.name(),
actual_type_def._get_type(),
actual_type_def))
return members
def union_type_header(self, name, type_def):
""" union_type: UNION IDENTIFIER SWITCH '(' switch_type_spec ')' """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
union = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new union.
if union is None:
# Set the version to "wip" (for Work In Progress) to allow the
# detection of recursive types.
version = "wip"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new union definition in the container.
union = container.create_union(ifr_id, name, version, type_def, [])
# If the union is defined at the global scope of the top-level IDL
# file then add it to our list of top-level definitions.
if self.__is_a_top_level_definition(union):
self.__top_level_definitions.append(union)
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
# Push the union onto the container stack.
self.__container_stack.push(union)
# Push a new prefix onto the prefix stack.
self.__prefix_stack.push(self.__create_prefix(prefix, name))
return union
def union_type_body(self, union, members):
""" union_type: '{' switch_body '}' """
# Get the union's discrimintator (aka switch) typecode and type
# definition.
typecode = union._get_discriminator_type()
type_def = union._get_discriminator_type_def()
# Make sure that all member names and label values are unique. This
# could take some time if some idiot has used, say an unsigned long as
# the discriminator type and a couple of billion cases ;^)
name_dict = {}
label_dict = {}
default_used = 0
for member in members:
# Ignore the default case.
if member.label.typecode().kind() == CORBA.tk_octet:
default_used = 1
else:
# Get the label value.
value = member.label.value()
# Make sure the label is the same type as the discriminant (or
# coercable to it).
if not self.__check_label_type(type_def, member.label):
self.yyerror("Invalid label value %s" % str(value))
raise bison.YYERROR
# Make sure that the value is within the limits of the type,
# and coerce it if necessary.
(result, value) = self.__check_limits(type_def, member.label)
if not result:
self.yyerror("Label value '%s' out of range" % str(value))
raise bison.YYERROR
# Wrap the coerced value back in an 'Any' of the appropriate
# type.
member.label = CORBA.Any(typecode, value)
# Name check.
if name_dict.has_key(member.name):
self.yyerror("Duplicate member name '%s'" % member.name)
raise bison.YYERROR
name_dict[member.name] = None
# Label check.
if label_dict.has_key(value):
self.yyerror("Duplicate case label %s" % str(value))
raise bison.YYERROR
label_dict[value] = None
# Check for recursive members.
if self.__is_recursive_member(member.type_def):
# Get the repository id of the recursive structure.
ifr_id = member.type_def._get_element_type_def()._get_id()
# Find out how deep the recursion is.
offset = self.__get_recursion_depth(union, ifr_id)
# Get the bound of the sequence type.
length = member.type.length()
# Replace the sequence typecode with a recursive sequence
# typecode.
member.type = CORBA.RecursiveSequenceTypeCode(length,
offset)
# If a default case has been specified, then make sure that the
# case labels for the specified type haven't been exhausted.
if default_used:
# Get the typecode kind.
kind = typecode.kind()
if kind == CORBA.tk_enum:
limit = typecode.member_count()
elif kind == CORBA.tk_short \
or typecode.kind() == CORBA.tk_ushort:
limit = 65536 # 2 ^ 16
elif kind == CORBA.tk_long \
or typecode.kind() == CORBA.tk_ulong:
limit = 4294967296L # 2 ^ 32
elif kind == CORBA.tk_longlong \
or typecode.kind() == CORBA.tk_ulonglong:
limit = 18446744073709551616L # 2 ^ 64
elif kind == CORBA.tk_char:
limit = 256 # 2 ^ 8
elif kind == CORBA.tk_boolean:
limit = 2 # 2 ;^)
if len(members) - 1 >= limit:
self.yyerror("All case labels exhausted")
raise bison.YYERROR
# Fixup the version.
union._set_version("1.0")
# Update the union definition.
union._set_members(members)
# Pop the container and prefix from the stacks.
self.__container_stack.pop()
self.__prefix_stack.pop()
return union
# Valid types for union switch specifications.
__SWITCH_TYPES = [CORBA.pk_short,
CORBA.pk_long,
CORBA.pk_longlong,
CORBA.pk_ushort,
CORBA.pk_ulong,
CORBA.pk_ulonglong,
CORBA.pk_char,
CORBA.pk_boolean]
def switch_type_spec_scoped_name(self, scoped_name):
""" switch_type_spec: scoped_name """
# Get the container from the stack.
container = self.__container_stack.get()
# Lookup the definition referenced by the scoped name.
definition = self.__find_scoped_name(container, scoped_name)
# Unwind any 'typedef' chain.
definition = self.__unwind_typedef_chain(definition)
# Make sure the definition type is either integer, char, boolean, or
# an enumeration.
if definition._get_def_kind() == CORBA.dk_Primitive:
if definition._get_kind() not in IDLParser.__SWITCH_TYPES:
self.yyerror("Invalid switch type '%s'" % scoped_name)
raise bison.YYERROR
elif definition._get_def_kind() != CORBA.dk_Enum:
self.yyerror("Invalid switch type '%s'" % scoped_name)
raise bison.YYERROR
return definition
def case(self, labels, (type_def, declarator)):
""" case: case_label_PLUS element_spec ';' """
typecode = type_def._get_type()
name = declarator.name()
members = []
for label in labels:
members.append(CORBA.UnionMember(name, label, typecode, type_def))
return members
def case_label_default(self):
""" case_label: DEFAULT ':' """
return CORBA.Any(CORBA.TC_octet, 0)
def element_spec(self, type_def, declarator):
""" element_spec: type_def declarator """
return (type_def, declarator)
def enum_type_header(self, name):
""" enum_type: ENUM IDENTIFIER """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
enum = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new enumeration.
if enum is None:
# Currently the version is always "1.0"!
version = "1.0"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new enumeration definition in the container.
enum = container.create_enum(ifr_id, name, version, [])
# If the enumeration is defined at the global scope of the
# top-level IDL file then add it to our list of top-level
# definitions.
if self.__is_a_top_level_definition(enum):
self.__top_level_definitions.append(enum)
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
return enum
def enum_type_body(self, enum, members):
""" enum_type: '{' enumerators '}' """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Create temporary constant definitions for each member.
for i in range(len(members)):
# Get the name of the member.
name = members[i]
# Does the container already contain a definition with this name?
constant = container.lookup(name)
# If there is *no* definition with this name then we can safely
# create a new constant.
if constant is None:
# Tag the enum member with a distinctive version ;^)
version = "Delete Me!"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create an Enum member instance.
any = CORBA.Any(enum._get_type(), Util.EnumMember(name, i))
# Create a new constant definition in the container.
constant = container.create_constant(ifr_id, name, version,
enum, any)
# Add the definition to our list of enumeration members to
# be cleaned up at the end.
self.__enum_members.append(constant)
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
# Update the enumeration definition.
enum._set_members(members)
return enum
def native_type_dcl(self, identifier):
""" type_dcl: NATIVE simple_declarator """
self.yywarning('No native types specified in the language mapping')
return
def sequence_type(self, element_type_def, bound=0):
""" sequence_type: SEQUENCE
'<' simple_type_spec ',' positive_int_const '>'
|
SEQUENCE '<' simple_type_spec '>'
"""
return self.__repository.create_sequence(bound, element_type_def)
def string_type(self, bound=0):
""" string_type: STRING '<' positive_int_const '>'
|
STRING
"""
if bound == 0:
definition = self.__repository.get_primitive(CORBA.pk_string)
else:
definition = self.__repository.create_string(bound)
return definition
def wide_string_type(self, bound=0):
""" wide_string_type: WSTRING '<' positive_int_const '>'
|
WSTRING
"""
self.yywarning("'wstring' not supported by Fnorb runtime")
if bound == 0:
definition = self.__repository.get_primitive(CORBA.pk_wstring)
else:
definition = self.__repository.create_wstring(bound)
return definition
def array_declarator(self, name, dimensions):
""" array_declarator: IDENTIFIER fixed_array_size_PLUS """
return Declarator.ArrayDeclarator(name, dimensions)
def fixed_array_size(self, dimension):
""" fixed_array_size: '[' positive_int_const ']' """
return dimension
def attr_dcl(self, mode, type_def, declarators):
""" attr_dcl: readonly_OPT ATTRIBUTE param_type_spec
simple_declarators
"""
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
for declarator in declarators:
# Get the name of the declarator.
name = declarator.name()
# Does the container already contain a definition with this name?
attribute = container.lookup(name)
# If there is *no* definition with this name then we can safely
# create a new attribute.
if attribute is None:
# Currently the version is always "1.0"!
version = "1.0"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new attribute definition in the container.
attribute = container.create_attribute(ifr_id, name, version,
type_def, mode)
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
return
def readonly_OPT_normal(self):
""" readonly_OPT: /* empty */ """
return CORBA.ATTR_NORMAL
def readonly_OPT_readonly(self):
""" readonly_OPT: READONLY """
return CORBA.ATTR_READONLY
def except_dcl_header(self, name):
""" EXCEPTION IDENTIFIER """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
exception = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new exception.
if exception is None:
# Currently the version is always "1.0"!
version = "1.0"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new exception definition in the container.
exception = container.create_exception(ifr_id, name, version, [])
# If the exception is defined at the global scope of the top-level
# IDL file then add it to our list of top-level definitions.
if self.__is_a_top_level_definition(exception):
self.__top_level_definitions.append(exception)
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
# Push the exception onto the container stack.
self.__container_stack.push(exception)
# Push a new prefix onto the prefix stack.
self.__prefix_stack.push(self.__create_prefix(prefix, name))
return exception
def except_dcl_body(self, exception, members):
""" except_dcl: '{' member_STAR '}' """
# The same as for structure definitions!
self.struct_type_body(exception, members)
return
def op_dcl_header(self, mode, result_type_def, name):
""" op_dcl: op_attribute_OPT op_type_spec IDENTIFER """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
prefix = self.__prefix_stack.get()
# Does the container already contain a definition with this name?
operation = container.lookup(name)
# If there is *no* definition with this name then we can safely create
# a new operation.
if operation is None:
# Currently the version is always "1.0"!
version = "1.0"
# Generate an interface repository id.
ifr_id = self.__create_ifr_id(prefix, name, version)
# Create a new operation definition in the container.
operation = container.create_operation(ifr_id, name, version,
result_type_def,
mode,
[], # Parameters.
[], # Exceptions.
[]) # Contexts.
# Otherwise, a definition with this name already exists.
else:
self.yyerror("Redefinition of name '%s'" % name)
raise bison.YYERROR
return operation
def op_dcl_body(self, operation, params, exceptions, contexts):
""" op_dcl: op_attribute_OPT op_type_spec IDENTIFER """
# Make sure that the parameter names are unique.
dict = {}
for param in params:
if dict.has_key(param.name):
self.yyerror("Duplicate parameter name '%s'" % param.name)
raise bison.YYERROR
dict[param.name] = None
# Update the operation definition.
operation._set_params(params)
operation._set_exceptions(exceptions)
operation._set_contexts(contexts)
return
def op_attribute_OPT_empty(self):
""" op_attribute_OPT: /* empty */ """
return CORBA.OP_NORMAL
def op_attribute_OPT_oneway(self):
""" op_attribute_OPT: ONEWAY """
return CORBA.OP_ONEWAY
def op_type_spec_void(self):
""" op_type_spec: VOID """
return self.__repository.get_primitive(CORBA.pk_void)
def parameter_dcls_empty(self):
""" parameter_dcls: '(' ')' """
return []
def param_dcl(self, mode, type_def, declarator):
""" param_dcl: param_attribute param_type_spec simple_declarator """
return CORBA.ParameterDescription(declarator.name(),
type_def._get_type(),
type_def,
mode)
def param_attribute_in(self):
""" param_attribute: IN """
return CORBA.PARAM_IN
def param_attribute_out(self):
""" param_attribute: OUT """
return CORBA.PARAM_OUT
def param_attribute_inout(self):
""" param_attribute: INOUT """
return CORBA.PARAM_INOUT
def raises_expr_OPT_empty(self):
""" raises_expr_OPT: /* empty */ """
return []
def raises_expr(self, scoped_names):
""" raises_expr: RAISES '(' scoped_name_CSV_PLUS ')' """
# Get the container and prefix from the stacks.
container = self.__container_stack.get()
# Make sure that all of the names refer to exceptions!
exceptions = []
for scoped_name in scoped_names:
# Lookup the definition referenced by the scoped name.
definition = self.__find_scoped_name(container, scoped_name)
if definition is None:
raise bison.YYERROR
# Make sure that it is an exception definition.
if definition._get_def_kind() != CORBA.dk_Exception:
self.yyerror("'%s' is not an exception" % scoped_name)
raise bison.YYERROR
exceptions.append(definition)
return exceptions
def context_expr_OPT_empty(self):
""" context_expr_OPT: /* empty */ """
return []
def context_expr(self, string_literals):
""" context_expr: CONTEXT '(' string_literal_CSV_PLUS ')' """
# fixme: Fnorb does not support contexts!
for string_literal in string_literals:
self.yywarning("%s context ignored" % string_literal)
return []
def fixed_pt_type(self, digits, scale):
""" fixed_pt_type: FIXED '<' positive_int_const ',' integer_literal '>'
The fixed point type is not yet implemented.
"""
self.yywarning("'fixed' not supported by Fnorb runtime")
# 'digits' is a positive integer constant and is returned as a Python
# long, and ;scale' is an integer literal which is returned as an
# 'Any'.
return self.__repository.create_fixed(digits, scale.value())
def fixed_pt_const_type(self):
""" fixed_pt_const_type: FIXED """
self.yywarning("'fixed' constants not supported by Fnorb runtime")
return self.__repository.create_fixed(0, 0)
#
# '#pragma' directives.
#
def pragma(self, yytext):
""" PRAGMA """
# Split the text of the directive on spaces.
components = string.split(yytext)
# Ignore any malformed directives.
if len(components) == 3:
if components[1] == 'prefix':
try:
# The prefix must be a quoted string.
pragma_prefix = eval(components[2])
if type(pragma_prefix) != types.StringType:
raise TypeError
# Get the current prefix from the stack.
prefix = self.__prefix_stack.get()
# Update the 'pragma' portion of the prefix.
prefix.set_pragma(pragma_prefix)
# Ignore any errors.
except:
self.yywarning("Malformed #pragma prefix")
elif len(components) == 4:
if components[1] == 'ID':
try:
# Get the name of the definition.
name = components[2]
# The id must be a quoted string.
ifr_id = eval(components[3])
if type(ifr_id) != types.StringType:
raise TypeError
# Get the container from the stacks.
container = self.__container_stack.get()
# Lookup the definition referenced by the scoped name.
definition = self.__find_scoped_name(container, name)
if definition is None:
raise bison.YYERROR
# Update the definition's interface repository id.
definition._set_id(ifr_id)
# Ignore any errors.
except:
self.yywarning("Malformed #pragma ID")
elif components[1] == 'version':
try:
# Get the name of the definition.
name = components[2]
# The version is used as a string, but must be in the
# format <major>.<minor>
version = components[3]
if type(eval(version)) != types.FloatType:
raise TypeError
# Get the container from the stacks.
container = self.__container_stack.get()
# Lookup the definition referenced by the scoped name.
definition = self.__find_scoped_name(container, name)
if definition is None:
raise bison.YYERROR
# Update the definition's version.
definition._set_version(version)
# Ignore any errors.
except:
self.yywarning("Malformed #pragma version")
return
def line_directive(self, yytext):
""" Parse line/file pre-processor directives.
This method is called from the lexer (see the file 'lexer.l').
"""
line = None
file = None
# Split the text on spaces.
components = string.split(yytext)
# If this a '# line' directive.
if components[1] == 'line':
# e.g. '# line 1'
line = eval(components[2])
# e.g. '# line 1 "filename.idl"
if len(components) >= 4:
file = eval(components[3])
# Otherwise this is a pre-processor inserted line.
else:
# e.g. '# 1'
line = eval(components[1])
# e.g. '# 1 "filename.idl"
if len(components) >= 3:
file = eval(components[2])
# Update the line number.
if line is not None:
bison.yylineno(line)
# Update the file.
if file is not None:
# Get the prefix stack for this file.
try:
self.__prefix_stack = self.__prefix_stacks[file]
# If there is no prefix stack for this file then create one!
except KeyError:
# The prefix stack initially contains just an empty prefix.
self.__prefix_stack = Stack.Stack()
self.__prefix_stack.push(Prefix.Prefix())
self.__prefix_stacks[file] = self.__prefix_stack
# Update the current filename.
self.__current_file = file
return
#
# Generic actions.
#
def list_empty(self):
""" Generic empty list. """
return []
def list_insert(self, item, list):
""" Generic list insert. """
if type(item) == types.ListType:
list = item + list
else:
list.insert(0, item)
return list
def idl_type_scoped_name(self, scoped_name):
""" Check that the scoped name references an IDL type definition. """
# Get the container from the stack.
container = self.__container_stack.get()
# Lookup the definition referenced by the scoped name.
definition = self.__find_scoped_name(container, scoped_name)
if definition is None:
raise bison.YYERROR
# If it is not an 'IDLType' definition then it is illegal.
if not definition._is_a("IDL:omg.org/CORBA/IDLType:1.0"):
self.yyerror("'%s' is not a type name" % scoped_name)
raise bison.YYERROR
return definition
#########################################################################
# Private interface.
#########################################################################
def __initialise(self):
""" Initialise the various data structures used during parsing. """
# The name of the IDL file currently being parsed.
self.__current_file = self.__filename
# A dictionary of prefix stacks - keyed on filename.
self.__prefix_stacks = {} # {Filename: Stack<Prefix>}
# The prefix stack initially contains just an empty prefix.
self.__prefix_stack = Stack.Stack()
self.__prefix_stack.push(Prefix.Prefix())
self.__prefix_stacks[self.__filename] = self.__prefix_stack
# A list of all definitions at the global scope of the top-level IDL
# file.
self.__top_level_definitions = []
# A dictionary of all interfaces along with the names of their
# operations and attributes.
self.__interfaces = {} # {RepositoryId: [NamesofOpsAndAttributes]}
# A dictionary of forward declared but undefined interfaces.
self.__forward_interfaces = {} # {RepositoryId: (InterfaceDef, LineNo)}
# A list of the temporary constant definitions created for members of
# enumerations.
self.__enum_members = []
return
def __cleanup(self):
""" Cleanup after parsing. """
# Get rid of the temporary contant definitions created for members of
# enumerations.
for enum_member in self.__enum_members:
enum_member.destroy()
return
def __create_prefix(self, prefix, name):
""" Create a new prefix. """
new_prefix = "%s%s/" % (prefix.get_prefix(), name)
return Prefix.Prefix(prefix.get_pragma(), new_prefix)
def __create_ifr_id(self, prefix, name, version):
""" Create an interface repository id. """
return "IDL:%s%s:%s" % (str(prefix), name, version)
def __find_scoped_name(self, container, scoped_name):
""" Find the definition for the scoped name. """
if scoped_name == "TypeCode":
definition = self.__repository.get_primitive(CORBA.pk_TypeCode)
elif scoped_name == "Principal":
definition = self.__repository.get_primitive(CORBA.pk_Principal)
else:
# If the container is an interface then we look first in
# the interface itself, and then recursively through its base
# interfaces.
if container._get_def_kind() == CORBA.dk_Interface:
definition = self.__find_inherited(container, scoped_name)
# Otherwise, we start by searching the current container, and then
# its enclosing scopes.
else:
definition = container.lookup(scoped_name)
# While the definition is not found.
while definition is None:
# Is the container also 'contained'?
if container._is_a("IDL:omg.org/CORBA/Contained:1.0"):
# Get the container's container ;^)
container = container._get_defined_in()
# Look in there!
definition = container.lookup(scoped_name)
else:
self.yyerror("Undeclared scoped name '%s'" % scoped_name)
break
return definition
def __find_inherited(self, container, scoped_name):
""" Find the definition for the scoped name. """
# Lookup the name in the interface first.
definition = container.lookup(scoped_name)
if definition is None:
# Look through all base interfaces.
for base in container._get_base_interfaces():
# Lookup the name in the base's base interfaces!
definition = self.__find_inherited(base, scoped_name)
if definition is not None:
break
return definition
def __create_array(self, type_def, dims):
""" Create an array type definition. """
# Single dimension
if len(dims) == 1:
array_type_def = self.__repository.create_array(dims[0], type_def)
# Multi-dimension
else:
# Create the 'slice' type.
slice_type_def = self.__repository.create_array(dims[-1], type_def)
# Recursively create the array type.
array_type_def = self.__create_array(slice_type_def, dims[:-1])
return array_type_def
def __is_a_top_level_definition(self, definition):
""" Is the defn at the global scope of the top-level IDL file? """
if self.__current_file == self.__filename \
and definition._get_defined_in() == self.__repository:
result = 1
else:
# Include any global scope definitions that are not modules!
if definition._get_defined_in() == self.__repository \
and definition._get_def_kind() != CORBA.dk_Module:
result = 1
else:
result = 0
return result
# Integer typecode kinds.
__TK_INT = [CORBA.tk_short,
CORBA.tk_long,
CORBA.tk_longlong,
CORBA.tk_ushort,
CORBA.tk_ulong,
CORBA.tk_ulonglong]
# Floating point typecode kinds.
__TK_FP = [CORBA.tk_float,
CORBA.tk_double,
CORBA.tk_longdouble]
def __check_constant_type(self, type_def, any):
""" Make sure that the value is of the specified type. """
# Get the typecode 'kind's.
type_def_kind = type_def._get_type().kind()
any_kind = any.typecode().kind()
if type_def_kind in IDLParser.__TK_INT \
and any_kind in IDLParser.__TK_INT:
result = 1
elif type_def_kind in IDLParser.__TK_FP \
and any_kind in IDLParser.__TK_FP:
result = 1
elif type_def_kind == any_kind:
result = 1
else:
result = 0
return result
def __check_limits(self, type_def, any):
""" Make sure that the value is within the limits of the type. """
# Get the typecode 'kind'.
type_def_kind = type_def._get_type().kind()
# Get the value out of the any.
value = any.value()
if type_def_kind == CORBA.tk_short:
if value < Limits.MIN_SHORT or value > Limits.MAX_SHORT:
result = 0
else:
result = 1
value = int(value)
elif type_def_kind == CORBA.tk_ushort:
if value < Limits.MIN_USHORT or value > Limits.MAX_USHORT:
result = 0
else:
result = 1
value = int(value)
elif type_def_kind == CORBA.tk_long:
if value < Limits.MIN_LONG or value > Limits.MAX_LONG:
result = 0
else:
result = 1
value = int(value)
elif type_def_kind == CORBA.tk_ulong:
if value < Limits.MIN_ULONG or value > Limits.MAX_ULONG:
result = 0
else:
result = 1
elif type_def_kind == CORBA.tk_longlong:
if value < Limits.MIN_LONGLONG or value > Limits.MAX_LONGLONG:
result = 0
else:
result = 1
elif type_def_kind == CORBA.tk_ulonglong:
if value < Limits.MIN_ULONGLONG or value > Limits.MAX_ULONGLONG:
result = 0
else:
result = 1
# fixme: This should not be here!!!
elif type_def_kind == CORBA.tk_fixed:
any_typecode = any.typecode()
type_def._set_digits(any_typecode.fixed_digits())
type_def._set_scale(any_typecode.fixed_scale())
result = 1
else:
result = 1
return (result, value)
def __check_label_type(self, type_def, any):
""" Make sure that the value is of the specified type. """
# Get the typecode 'kind's.
type_def_kind = type_def._get_type().kind()
any_kind = any.typecode().kind()
if type_def_kind in IDLParser.__TK_INT \
and any_kind in IDLParser.__TK_INT:
result = 1
elif type_def_kind == any_kind:
# If the union is switched on an enumeration then make sure that
# the value is a valid element of the same enumeration!
if type_def_kind == CORBA.tk_enum:
if type_def._get_type().id() == any.typecode().id():
result = 1
else:
result = 0
else:
result = 1
else:
result = 0
return result
def __check_forward_interfaces(self):
""" Make sure that all forward declared interfaces were defined. """
if len(self.__forward_interfaces) > 0:
for (interface, yylineno) in self.__forward_interfaces.values():
# Set the line number for error reporting.
bison.yylineno(yylineno)
# Report the error.
self.yyerror("Interface '%s' declared but not defined" % \
interface._get_name())
raise bison.YYERROR
return
def __get_inherited_operations(self, interface, visited):
""" Get all operations and attributes inherited by an interface. """
names = []
for base in interface._get_base_interfaces():
# Get the interface repository id of the interface.
ifr_id = base._get_id()
# Only include the operations and attributes for the interface
# once!
if ifr_id not in visited:
# Add the interface's operations and attributes to the list.
names = names + self.__interfaces[ifr_id]
# Add the interface repository id of the interface to the list
# of those already visited.
visited.append(ifr_id)
# Do it recursively!
names = names + self.__get_inherited_operations(base, visited)
# Check for duplicates!
tmp = {}
for name in names:
if tmp.has_key(name):
self.yyerror("Overloaded operation/attribute '%s'" % name)
raise bison.YYERROR
else:
tmp[name] = None
return names
def __unwind_typedef_chain(self, definition):
""" Unwind any 'typedef' chain! """
# fixme: Which will it be? dk_Typedef or dk_Alias?!?!?!?!?! My bet is
# on dk_Alias!
while definition._get_def_kind() == CORBA.dk_Typedef \
or definition._get_def_kind() == CORBA.dk_Alias:
definition = definition._get_original_type_def()
return definition
def __is_recursive_member(self, type_def):
""" Determine whether or not this is a recursive member. """
if type_def._get_def_kind() == CORBA.dk_Sequence:
element_type_def = type_def._get_element_type_def()
if element_type_def._get_def_kind() == CORBA.dk_Struct or \
element_type_def._get_def_kind() == CORBA.dk_Union:
if element_type_def._get_version() == "wip":
return 1
return 0
def __get_recursion_depth(self, type_def, ifr_id, depth=1):
""" Find the depth (or 'offset') of a recursive type. """
if type_def._get_id() == ifr_id:
return depth
else:
return self.__get_recursion_depth(type_def._get_defined_in(),
ifr_id,
depth + 1)
return
#############################################################################