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 >
Text File  |  1999-06-28  |  59KB  |  1,984 lines

  1. #!/usr/bin/env python
  2. #############################################################################
  3. # Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1997, 1998, 1999
  4. # All Rights Reserved.
  5. #
  6. # The software contained on this media is the property of the DSTC Pty
  7. # Ltd.  Use of this software is strictly in accordance with the
  8. # license agreement in the accompanying LICENSE.HTML file.  If your
  9. # distribution of this software does not contain a LICENSE.HTML file
  10. # then you have no rights to use this software in any manner and
  11. # should contact DSTC at the address below to determine an appropriate
  12. # licensing arrangement.
  13. #      DSTC Pty Ltd
  14. #      Level 7, GP South
  15. #      Staff House Road
  16. #      University of Queensland
  17. #      St Lucia, 4072
  18. #      Australia
  19. #      Tel: +61 7 3365 4310
  20. #      Fax: +61 7 3365 4311
  21. #      Email: enquiries@dstc.edu.au
  22. # This software is being provided "AS IS" without warranty of any
  23. # kind.  In no event shall DSTC Pty Ltd be liable for damage of any
  24. # kind arising out of or in connection with the use or performance of
  25. # this software.
  26. #
  27. # Project:      Fnorb
  28. # File:         $Source: /units/arch/src/Fnorb/parser/RCS/IDLParser.py,v $
  29. # Version:      @(#)$RCSfile: IDLParser.py,v $ $Revision: 1.12 $
  30. #
  31. #############################################################################
  32. """ Parser for OMG IDL. """
  33.  
  34.  
  35. # Standard/built-in modules.
  36. import new, string, sys, types
  37.  
  38. # Fnorb modules.
  39. from Fnorb.orb import CORBA, Fixed, Limits, Util
  40.  
  41. # Fnorb extension modules.
  42. import bison
  43.  
  44. # Parser modules.
  45. import Declarator, Prefix, Stack
  46.  
  47.  
  48. class IDLParser:
  49.     """ Parser for OMG IDL.
  50.  
  51.     This class implements the semantic actions for the IDL parser. The actual
  52.     parsing engine is implemented in 'C' using 'flex' and 'bison'. 
  53.  
  54.     """
  55.  
  56.     #########################################################################
  57.     # Parser interface.
  58.     #########################################################################
  59.  
  60.     def parse(self, repository, filename, yyin):
  61.     """ Parse some IDL!
  62.  
  63.     'repository' is the interface repository (IFR) to be populated.
  64.     'filename'   is the filename of the top-level IDL file.
  65.     'yyin'       is an open file object to read the IDL from.
  66.  
  67.     """
  68.     self.__repository = repository
  69.     self.__filename = filename
  70.  
  71.     # Initialise the various data structures used during parsing.
  72.     self.__initialise()
  73.  
  74.     # Do the parsing!
  75.     result = bison.yyparse(self, yyin)
  76.  
  77.     # Clean up!
  78.     self.__cleanup()
  79.  
  80.     return (result, self.__top_level_definitions)
  81.  
  82.     def yyerror(self, message):
  83.     """ Error function called from the 'bison' parser. """
  84.  
  85.     sys.stderr.write("Error: %s on line %d of %s\n" % \
  86.              (message, bison.yylineno(), self.__current_file))
  87.     return
  88.  
  89.     def yywarning(self, message):
  90.     """ Warning function. """
  91.  
  92.     sys.stderr.write("Warning: %s on line %d of %s\n" % \
  93.              (message, bison.yylineno(), self.__current_file))
  94.     return
  95.  
  96.     #########################################################################
  97.     # Semantic actions (called from 'grammar.y').
  98.     #########################################################################
  99.  
  100.     def specification_start(self):
  101.     """ specification: """
  102.  
  103.     # The container stack initially contains just the repository.
  104.     self.__container_stack = Stack.Stack()
  105.     self.__container_stack.push(self.__repository)
  106.  
  107.     return
  108.  
  109.     def specification_end(self):
  110.     """ specification: definition_PLUS """
  111.  
  112.     # Report an error for any interfaces that were 'forward' declared but
  113.     # not defined!
  114.     self.__check_forward_interfaces()
  115.  
  116.     # Pop the repository from the container stack, and make sure that the
  117.     # stack really is empty!
  118.     self.__container_stack.pop()
  119.     assert(len(self.__container_stack) == 0)
  120.  
  121.     return
  122.  
  123.     def module_header(self, name):
  124.     """ MODULE IDENTIFIER """
  125.  
  126.     # Get the container and prefix from the stacks.
  127.     container = self.__container_stack.get()
  128.     prefix = self.__prefix_stack.get()
  129.  
  130.     # Does the container already contain a definition with this name?
  131.     module = container.lookup(name)
  132.  
  133.     # If there is *no* definition with this name then we can safely create
  134.     # a new module.
  135.     if module is None:
  136.         # Currently the version is always "1.0"!
  137.         version = "1.0"
  138.  
  139.         # Generate an interface repository id.
  140.         ifr_id = self.__create_ifr_id(prefix, name, version)
  141.  
  142.         # Create a new module definition in the container.
  143.         module = container.create_module(ifr_id, name, version)
  144.  
  145.         # If the module is defined at the global scope of the top-level IDL
  146.         # file then add it to our list of top-level definitions.
  147.         if self.__is_a_top_level_definition(module):
  148.         self.__top_level_definitions.append(module)
  149.  
  150.     # Otherwise, a definition with this name already exists.
  151.     else:
  152.         # If it is a module definition then we just "re-open" it to allow
  153.         # more definitions to be added.  If it is not a module definition
  154.         # then it is illegal!
  155.         if module._get_def_kind() != CORBA.dk_Module:
  156.         self.yyerror("Redefinition of name '%s'" % name)
  157.         raise bison.YYERROR
  158.  
  159.         # If the module is defined at the global scope of the top-level IDL
  160.         # file then add it to our list of top-level definitions.
  161.         #
  162.         # We have to do this here as the first occurence of the module may
  163.         # have been in a file that was '#included'.
  164.         if self.__is_a_top_level_definition(module):
  165.         self.__top_level_definitions.append(module)
  166.  
  167.         # fixme: Check for ID compatability in the case of '#pragma ID'?
  168.         pass
  169.  
  170.     # Push the module onto the container stack.
  171.     self.__container_stack.push(module)
  172.  
  173.     # Push the new prefix onto the prefix stack.
  174.     self.__prefix_stack.push(self.__create_prefix(prefix, name))    
  175.  
  176.     return
  177.  
  178.     def module_body(self):
  179.     """ '{' definition_STAR '}' """
  180.     
  181.     # Pop the container and prefix from the stacks.
  182.     self.__container_stack.pop()
  183.     self.__prefix_stack.pop()
  184.     
  185.     return
  186.  
  187.     def interface_dcl_header(self, name, base_interfaces):
  188.     """ INTERFACE IDENTIFIER inheritance_spec_OPT """
  189.  
  190.     # Get the container and prefix from the stacks.
  191.     container = self.__container_stack.get()
  192.     prefix = self.__prefix_stack.get()
  193.  
  194.     # Does the container already contain a definition with this name?
  195.     interface = container.lookup(name)
  196.  
  197.     # If there is *no* definition with this name then we can safely create
  198.     # a new interface.
  199.     if interface is None:
  200.         # Currently the version is always "1.0"!
  201.         version = "1.0"
  202.  
  203.         # Generate an interface repository id.
  204.         ifr_id = self.__create_ifr_id(prefix, name, version)
  205.  
  206.         # Create a new interface definition in the container.
  207.         interface = container.create_interface(ifr_id, name, version, [])
  208.  
  209.         # If the interface is defined at the global scope of the top-level
  210.         # IDL file then add it to our list of top-level definitions.
  211.         if self.__is_a_top_level_definition(interface):
  212.         self.__top_level_definitions.append(interface)
  213.  
  214.     # Otherwise, a definition with this name already exists.
  215.     else:
  216.         # If it is *not* an interface definition then it is definitely
  217.         # illegal!
  218.         if interface._get_def_kind() != CORBA.dk_Interface:
  219.         self.yyerror("Redefinition of name '%s'" % name)
  220.         raise bison.YYERROR
  221.  
  222.         # If it *is* an interface definition then it must be a forward
  223.         # declaration. If not then it is also illegal!
  224.         if interface._get_version() != 'forward':
  225.         self.yyerror("Redefinition of name '%s'" % name)
  226.         raise bison.YYERROR
  227.  
  228.         # fixme: Check for ID compatability in the case of '#pragma ID'?
  229.         pass
  230.  
  231.         # 'Move' the interface definition to the same container (this has
  232.         # the side-effect of placing it last in the containers list of
  233.         # contents ;^)
  234.         interface.move(container, name, "1.0")
  235.  
  236.         # Delete the interface from the dictionary containing forward
  237.         # declared but undefined interfaces,
  238.         del self.__forward_interfaces[interface._get_id()]
  239.  
  240.     # Check the base interfaces.
  241.     for base in base_interfaces:
  242.         # Make sure that the base interface is not a forward delcaration.
  243.         if base._get_version() == 'forward':
  244.         self.yyerror("Interface '%s' not defined" % base._get_name())
  245.         raise bison.YYERROR
  246.  
  247.         # Make sure that some poor shmuck is not attempting to make the 
  248.         # interface inherit from itself!
  249.         #
  250.         # fixme: Will this work in the presence of '#pragma ID'?
  251.         if base._get_id() == interface._get_id():
  252.         self.yyerror("Interface '%s' inherits from itself!" % name)
  253.         raise bison.YYERROR
  254.  
  255.     # Update the list of base interfaces.
  256.     interface._set_base_interfaces(base_interfaces)
  257.         
  258.     # Push the interface onto the container stack.
  259.     self.__container_stack.push(interface)
  260.  
  261.     # Push a new prefix onto the prefix stack.
  262.     self.__prefix_stack.push(self.__create_prefix(prefix, name))    
  263.  
  264.     return interface
  265.  
  266.     def interface_dcl_body(self, interface):
  267.     """ '{' export_STAR '}' """
  268.  
  269.     # Get the interface description.
  270.     description = interface.describe_interface()
  271.  
  272.     # Get the names of all of the interface's operations and attributes.
  273.     names = map(lambda o: o.name, description.operations)
  274.     names = names + map(lambda a: a.name, description.attributes)
  275.  
  276.     # Add the interface to the interface dictionary.
  277.     self.__interfaces[interface._get_id()] = names
  278.  
  279.     # Get the names of all inherited operations and attributes.
  280.     inherited = self.__get_inherited_operations(interface, [])
  281.  
  282.     # Make sure there are no clashes!
  283.     if len(inherited) > 0:
  284.         for name in names:
  285.         if name in inherited:
  286.             self.yyerror("Overloaded operation/attribute '%s'" % name)
  287.             raise bison.YYERROR
  288.  
  289.     # Pop the container and prefix from the stacks.
  290.     self.__container_stack.pop()
  291.     self.__prefix_stack.pop()
  292.     
  293.     return
  294.  
  295.     def foward_dcl(self, name):
  296.     """ forward_dcl: INTERFACE IDENTIFIER """
  297.  
  298.     # Get the container and prefix from the stacks.
  299.     container = self.__container_stack.get()
  300.     prefix = self.__prefix_stack.get()
  301.  
  302.     # Does the container already contain a definition with this name?
  303.     interface = container.lookup(name)
  304.  
  305.     # If there is *no* definition with this name then we can safely create
  306.     # a new interface.
  307.     if interface is None:
  308.         # Currently the version is always "1.0"!
  309.         version = "1.0"
  310.  
  311.         # Generate a repository id.
  312.         ifr_id = self.__create_ifr_id(prefix, name, version)
  313.  
  314.         # Create a new interface definition in the container and tag it
  315.         # with a version of "forward".
  316.         interface = container.create_interface(ifr_id, name, "forward", [])
  317.  
  318.         # If the interface is defined at the global scope of the top-level
  319.         # IDL file then add it to our list of top-level definitions.
  320.         if self.__is_a_top_level_definition(interface):
  321.         self.__top_level_definitions.append(interface)
  322.  
  323.         # Add the interface to the dictionary of forward declared but
  324.         # undefined interfaces.
  325.         self.__forward_interfaces[ifr_id] = (interface, bison.yylineno())
  326.  
  327.     # Otherwise, a definition with this name already exists.
  328.     else:
  329.         # If it is *not* an interface definition then it is illegal!
  330.         if interface._get_def_kind() != CORBA.dk_Interface:
  331.         self.yyerror("Redefinition of name '%s'" % name)
  332.         raise bison.YYERROR
  333.  
  334.         # fixme: Check for ID compatability in the case of '#pragma ID'?
  335.         pass
  336.  
  337.     return
  338.  
  339.     def inheritance_spec_empty(self):
  340.     """ inheritance_spec: /* empty */ """
  341.  
  342.     return [] # [InterfaceDef]
  343.  
  344.     def inheritance_spec_full(self, scoped_names):
  345.     """ inheritance_spec: ':' scoped_name_CSV_PLUS """
  346.  
  347.     # Get the container from the stack.
  348.     container = self.__container_stack.get()
  349.  
  350.     # Find the interface definition for each scoped name.
  351.     base_interfaces = []
  352.     for scoped_name in scoped_names:
  353.         # Lookup the definition.
  354.         interface = self.__find_scoped_name(container, scoped_name)
  355.         if interface is None:
  356.         raise bison.YYERROR
  357.  
  358.         # If it is *not* an interface definition then it is illegal!
  359.         if interface._get_def_kind() != CORBA.dk_Interface:
  360.         self.yyerror("'%s' is not an interface" % scoped_name)
  361.         raise bison.YYERROR
  362.  
  363.         base_interfaces.append(interface)
  364.  
  365.     return base_interfaces
  366.  
  367.     def scoped_name_absolute(self, identifier):
  368.     """ scoped_name: SCOPE_DELIMITER IDENTIFIER """
  369.  
  370.     return "::" + identifier
  371.  
  372.     def scoped_name_relative(self, scoped_name, identifier):
  373.     """ scoped_name: scoped_name SCOPE_DELIMITER IDENTIFIER """
  374.  
  375.     return scoped_name + "::" + identifier
  376.  
  377.     def const_dcl(self, type_def, name, any):
  378.     """ const_dcl: CONST const_type IDENTIFIER '=' const_expr """
  379.  
  380.     # Get the container and prefix from the stacks.
  381.     container = self.__container_stack.get()
  382.     prefix = self.__prefix_stack.get()
  383.  
  384.     # Does the container already contain a definition with this name?
  385.     constant = container.lookup(name)
  386.  
  387.     # If there is *no* definition with this name then we can safely create
  388.     # a new constant.
  389.     if constant is None:
  390.         # Make sure that the value is of the appropriate type.
  391.         if not self.__check_constant_type(type_def, any):
  392.         self.yyerror("Constant '%s' invalid value type" % name)
  393.         raise bison.YYERROR
  394.  
  395.         # Make sure that the value is within the limits of the type, and
  396.         # coerce it if necessary.
  397.         (result, value) = self.__check_limits(type_def, any)
  398.         if not result:
  399.         self.yyerror("Constant '%s' out of range" % name)
  400.         raise bison.YYERROR
  401.  
  402.         # Wrap the coerced value back in an 'Any' of the appropriate type.
  403.         any = CORBA.Any(type_def._get_type(), value)
  404.  
  405.         # Currently the version is always "1.0"!
  406.         version = "1.0"
  407.  
  408.         # Generate an interface repository id.
  409.         ifr_id = self.__create_ifr_id(prefix, name, version)
  410.  
  411.         # Create a new constant definition in the container.
  412.         constant = container.create_constant(ifr_id, name, version,
  413.                          type_def, any)
  414.  
  415.         # If the constant is defined at the global scope of the top-level
  416.         # IDL file then add it to our list of top-level definitions.
  417.         if self.__is_a_top_level_definition(constant):
  418.         self.__top_level_definitions.append(constant)
  419.  
  420.     # Otherwise, a definition with this name already exists.
  421.     else:
  422.         self.yyerror("Redefinition of name '%s'" % name)
  423.         raise bison.YYERROR
  424.  
  425.     return constant
  426.  
  427.     # Valid types for constant expressions.
  428.     __CONST_TYPES = [CORBA.pk_short,
  429.              CORBA.pk_long,
  430.              CORBA.pk_ushort,
  431.              CORBA.pk_ulong,
  432.              CORBA.pk_char,
  433.              CORBA.pk_boolean,
  434.              CORBA.pk_float,
  435.              CORBA.pk_double,
  436.              CORBA.pk_string,
  437.              CORBA.pk_longlong,
  438.              CORBA.pk_ulonglong,
  439.              CORBA.pk_longdouble,
  440.              CORBA.pk_wchar,
  441.              CORBA.pk_wstring]
  442.  
  443.     def const_type_scoped_name(self, scoped_name):
  444.     """ const_type: scoped_name """
  445.  
  446.     # Get the container from the stack.
  447.     container = self.__container_stack.get()
  448.  
  449.     # Lookup the definition referenced by the scoped name.
  450.     definition = self.__find_scoped_name(container, scoped_name)
  451.  
  452.     # Unwind any 'typedef' chain.
  453.     definition = self.__unwind_typedef_chain(definition)
  454.  
  455.     # Make sure that the definition is either:-
  456.     #
  457.     # 1) One of the following primitive types:-
  458.     #
  459.     #    integer, char, wchar, boolean, floating point, string, wstring
  460.     #
  461.     # 2) Of type 'fixed'.
  462.     if definition._get_def_kind() == CORBA.dk_Primitive \
  463.        and definition._get_kind() in IDLParser.__CONST_TYPES:
  464.         pass
  465.  
  466.     elif definition._get_def_kind() == CORBA.dk_Fixed:
  467.         pass
  468.  
  469.     else:
  470.         self.yyerror("Invalid constant type '%s'" % scoped_name)
  471.          raise bison.YYERROR
  472.  
  473.     return definition
  474.  
  475.     # The arguments to constant expression operators are 'Any's, and the
  476.     # operations are implemented in the 'Any' module.
  477.     def or_expr(self, x, y):
  478.     """ or_expr: or_expr '|' xor_expr """
  479.  
  480.     return x | y
  481.  
  482.     def xor_expr(self, x, y):
  483.     """ xor_expr: xor_expr '^' and_expr """
  484.  
  485.     return x ^ y
  486.  
  487.     def and_expr(self, x, y):
  488.     """ and_expr: and_expr '&' shift_expr """
  489.  
  490.     return x & y
  491.  
  492.     def shift_expr_right(self, x, y):
  493.     """ shift_expr: shift_expr RIGHT_SHIFT add_expr """
  494.  
  495.     return x >> y
  496.  
  497.     def shift_expr_left(self, x, y):
  498.     """ shift_expr: shift_expr LEFT_SHIFT add_expr """
  499.  
  500.     return x << y
  501.  
  502.     def add_expr_add(self, x, y):
  503.     """ add_expr: add_expr '+' mult_expr """
  504.  
  505.     return x + y
  506.  
  507.     def add_expr_subtract(self, x, y):
  508.     """ add_expr: add_expr '-' mult_expr """
  509.  
  510.     return x - y
  511.  
  512.     def mult_expr_multiply(self, x, y):
  513.     """ mult_expr: mult_expr '*' unary_expr """
  514.  
  515.     return x * y
  516.  
  517.     def mult_expr_divide(self, x, y):
  518.     """ mult_expr: mult_expr '/' unary_expr """
  519.  
  520.     return x / y
  521.  
  522.     def mult_expr_mod(self, x, y):
  523.     """ mult_expr: mult_expr '%' unary_expr """
  524.  
  525.     return x % y
  526.  
  527.     def unary_expr_neg(self, x):
  528.     """ unary_expr: '-' primary_expr """
  529.  
  530.     return -x
  531.  
  532.     def unary_expr_pos(self, x):
  533.     """ unary_expr: '+' primary_expr """
  534.  
  535.     return +x
  536.  
  537.     def unary_expr_invert(self, x):
  538.     """ unary_expr: '~' primary_expr """
  539.  
  540.     return ~x
  541.  
  542.     def primary_expr_scoped_name(self, scoped_name):
  543.     """ primary_expr: scoped_name """
  544.  
  545.     # Get the container from the stack.
  546.     container = self.__container_stack.get()
  547.  
  548.     # Lookup the definition referenced by the scoped name.
  549.     definition = self.__find_scoped_name(container, scoped_name)
  550.     if definition is None:
  551.         raise bison.YYERROR
  552.  
  553.     # If it is not a constant definition then it is illegal!
  554.     if definition._get_def_kind() != CORBA.dk_Constant:
  555.         self.yyerror("'%s' is not a constant expression" % scoped_name)
  556.         raise bison.YYERROR
  557.  
  558.     # Return the constant's value (an 'Any').
  559.     return definition._get_value()
  560.  
  561.     def literal_integer_literal(self, value):
  562.     """ literal: INTEGER_LITERAL """
  563.  
  564.     # We get integer literals as the raw string token from the lexer.
  565.     #
  566.     # fixme: Should we do this for floating point literals as well?
  567.  
  568.     # All integer literals are converted to Python *long* integers and then
  569.     # coerced back as appropriate.
  570.     return CORBA.Any(CORBA.TC_longlong, eval(value + "L"))
  571.  
  572.     def literal_string_literal(self, value):
  573.     """ literal: STRING_LITERAL """
  574.  
  575.     # Evaluate the string containing the string!
  576.     return CORBA.Any(CORBA.TC_string, eval(value))
  577.  
  578.     def literal_character_literal(self, value):
  579.     """ literal: CHARACTER_LITERAL """
  580.  
  581.     # Evaluate the string containing the character!
  582.     return CORBA.Any(CORBA.TC_char, eval(value))
  583.  
  584.     def literal_fixed_pt_literal(self, value):
  585.     """ literal: FIXED_PT_LITERAL """
  586.  
  587.     # Fixed point values are instances of the 'Fixed' class.
  588.     fixed = new.instance(Fixed.Fixed, {})
  589.  
  590.     # Initialise the instance from the literal.
  591.     fixed._fnorb_from_literal(value)
  592.  
  593.     return CORBA.Any(fixed._fnorb_typecode(), fixed)
  594.  
  595.     def literal_floating_pt_literal(self, value):
  596.     """ literal: FLOATING_PT_LITERAL """
  597.  
  598.     return CORBA.Any(CORBA.TC_double, value)
  599.  
  600.     def boolean_literal_true(self):
  601.     """ boolean_literal: TRUE """
  602.     
  603.     return CORBA.Any(CORBA.TC_boolean, 1)
  604.  
  605.     def boolean_literal_false(self):
  606.     """ boolean_literal: FALSE """
  607.     
  608.     return CORBA.Any(CORBA.TC_boolean, 0)
  609.     
  610.     def positive_int_const(self, any):
  611.     """ positive_int_const: const_expr """
  612.  
  613.     # Get the typecode's 'kind'.
  614.     kind = any.typecode().kind()
  615.  
  616.     # Make sure that it really is a positive, integer ;^)
  617.     if kind not in IDLParser.__TK_INT or any.value() < 0:
  618.         self.yyerror("Positive integer value required")
  619.         raise bison.YYERROR
  620.  
  621.     # Extract the value from the 'Any'.
  622.     return any.value()
  623.  
  624.     def type_declarator(self, type_def, declarators):
  625.     """ type_declarator: type_spec declarators """
  626.  
  627.     # Get the container and prefix from the stacks.
  628.     container = self.__container_stack.get()
  629.     prefix = self.__prefix_stack.get()
  630.  
  631.     # Create a 'typedef' definition for each declarator.
  632.     for declarator in declarators:
  633.         # Get the name of the declarator.
  634.         name = declarator.name()
  635.  
  636.         # Does the container already contain a definition with this name?
  637.         definition = container.lookup(name)
  638.  
  639.         # If there is *no* definition with this name then we can safely
  640.         # create a new 'typedef' definition.
  641.         if definition is None:
  642.         # Currently the version is always "1.0"!
  643.         version = "1.0"
  644.  
  645.         # Generate an interface repository id.
  646.         ifr_id = self.__create_ifr_id(prefix, name, version)
  647.  
  648.         # If this is an array declarator.
  649.         if isinstance(declarator, Declarator.ArrayDeclarator):
  650.             # Get the array dimensions.
  651.             dimensions = declarator.dimensions()
  652.  
  653.             # Create the array type.
  654.             actual_type_def = self.__create_array(type_def, dimensions)
  655.  
  656.         # Otherwise it is a simple declarator.
  657.         else:
  658.             actual_type_def = type_def
  659.  
  660.         # Create a new 'typedef' definition in the container.
  661.         definition = container.create_alias(ifr_id, name, version,
  662.                             actual_type_def)
  663.  
  664.         # If the 'typedef' is defined at the global scope of the
  665.         # top-level IDL file then add it to our list of top-level
  666.         # definitions.
  667.         if self.__is_a_top_level_definition(definition):
  668.             self.__top_level_definitions.append(definition)
  669.  
  670.         # Otherwise, a definition with this name already exists.
  671.         else:
  672.         self.yyerror("Redefinition of name '%s'" % name)
  673.         raise bison.YYERROR
  674.         
  675.     return
  676.  
  677.     def simple_declarator(self, name):
  678.     """ simple_declarator: IDENTIFIER """
  679.  
  680.     return Declarator.SimpleDeclarator(name)
  681.  
  682.     def float_type(self):
  683.     """ floating_pt_type: FLOAT """
  684.  
  685.     return self.__repository.get_primitive(CORBA.pk_float)
  686.  
  687.     def double_type(self):
  688.     """ floating_pt_type: DOUBLE """
  689.  
  690.     return self.__repository.get_primitive(CORBA.pk_double)
  691.  
  692.     def longdouble_type(self):
  693.     """ floating_pt_type: LONG DOUBLE """
  694.  
  695.     self.yywarning("'long double' not supported by Fnorb runtime")
  696.     return self.__repository.get_primitive(CORBA.pk_longdouble)
  697.  
  698.     def signed_short_int(self):
  699.     """ signed_short_int: SHORT """
  700.  
  701.     return self.__repository.get_primitive(CORBA.pk_short)
  702.  
  703.     def signed_long_int(self):
  704.     """ signed_long_int: LONG """
  705.  
  706.     return self.__repository.get_primitive(CORBA.pk_long)
  707.  
  708.     def signed_longlong_int(self):
  709.     """ signed_longlong_int: LONG LONG"""
  710.  
  711.     return self.__repository.get_primitive(CORBA.pk_longlong)
  712.  
  713.     def unsigned_short_int(self):
  714.     """ unsigned_short_int: UNSIGNED SHORT """
  715.  
  716.     return self.__repository.get_primitive(CORBA.pk_ushort)
  717.  
  718.     def unsigned_long_int(self):
  719.     """ unsigned_long_int: UNSIGNED LONG """
  720.  
  721.     return self.__repository.get_primitive(CORBA.pk_ulong)
  722.  
  723.     def unsigned_longlong_int(self):
  724.     """ unsigned_longlong_int: UNSIGNED LONG LONG"""
  725.  
  726.     return self.__repository.get_primitive(CORBA.pk_ulonglong)
  727.  
  728.     def char_type(self):
  729.     """ char_type: CHAR """
  730.  
  731.     return self.__repository.get_primitive(CORBA.pk_char)
  732.  
  733.     def wide_char_type(self):
  734.     """ wide_char_type: WCHAR """
  735.  
  736.     self.yywarning("'wchar' not supported by Fnorb runtime")
  737.     return self.__repository.get_primitive(CORBA.pk_wchar)
  738.  
  739.     def boolean_type(self):
  740.     """ boolean_type: BOOLEAN """
  741.  
  742.     return self.__repository.get_primitive(CORBA.pk_boolean)
  743.  
  744.     def octet_type(self):
  745.     """ octet_type: OCTET """
  746.  
  747.     return self.__repository.get_primitive(CORBA.pk_octet)
  748.  
  749.     def any_type(self):
  750.     """ any_type: IDL_ANY """
  751.  
  752.     return self.__repository.get_primitive(CORBA.pk_any)
  753.  
  754.     def object_type(self):
  755.     """ object_type: OBJECT """
  756.  
  757.     return self.__repository.get_primitive(CORBA.pk_objref)
  758.  
  759.     def struct_type_header(self, name):
  760.     """ struct_type: STRUCT IDENTIFIER """
  761.  
  762.     # Get the container and prefix from the stacks.
  763.     container = self.__container_stack.get()
  764.     prefix = self.__prefix_stack.get()
  765.  
  766.     # Does the container already contain a definition with this name?
  767.     struct = container.lookup(name)
  768.  
  769.     # If there is *no* definition with this name then we can safely create
  770.     # a new structure definition.
  771.     if struct is None:
  772.         # Set the version to "wip" (for Work In Progress) to allow the
  773.         # detection of recursive types.
  774.         version = "wip"
  775.         
  776.         # Generate an interface repository id.
  777.         ifr_id = self.__create_ifr_id(prefix, name, version)
  778.  
  779.         # Create a new structure definition in the container.
  780.         struct = container.create_struct(ifr_id, name, version, [])
  781.  
  782.         # If the structure is defined at the global scope of the top-level
  783.         # IDL file then add it to our list of top-level definitions.
  784.         if self.__is_a_top_level_definition(struct):
  785.         self.__top_level_definitions.append(struct)
  786.  
  787.     # Otherwise, a definition with this name already exists.
  788.     else:
  789.         self.yyerror("Redefinition of name '%s'" % name)
  790.         raise bison.YYERROR
  791.  
  792.     # Push the structure onto the container stack.
  793.     self.__container_stack.push(struct)
  794.  
  795.     # Push a new prefix onto the prefix stack.
  796.     self.__prefix_stack.push(self.__create_prefix(prefix, name))    
  797.  
  798.     return struct
  799.  
  800.     def struct_type_body(self, struct, members):
  801.     """ struct_type: '{'  member_PLUS '}' """
  802.  
  803.     # Make sure that all member names are unique.
  804.     dict = {}
  805.     for member in members:
  806.         if dict.has_key(member.name):
  807.         self.yyerror("Duplicate member name '%s'" % name)
  808.         raise bison.YYERROR
  809.  
  810.         dict[member.name] = None
  811.  
  812.          # Check for recursive members.
  813.          if self.__is_recursive_member(member.type_def):
  814.          # Get the repository id of the recursive structure.
  815.          ifr_id = member.type_def._get_element_type_def()._get_id()
  816.  
  817.          # Find out how deep the recursion is.
  818.          offset = self.__get_recursion_depth(struct, ifr_id)
  819.  
  820.          # Get the bound of the sequence type.
  821.          length = member.type.length()
  822.  
  823.          # Replace the sequence typecode with a recursive sequence
  824.          # typecode.
  825.          member.type = CORBA.RecursiveSequenceTypeCode(length, offset)
  826.  
  827.     # Fixup the version.
  828.     struct._set_version("1.0")
  829.  
  830.     # Update the structure definition.
  831.     struct._set_members(members)
  832.  
  833.     # Pop the container and prefix from the stacks.
  834.     self.__container_stack.pop()
  835.     self.__prefix_stack.pop()
  836.     
  837.     return struct
  838.  
  839.     def member(self, type_def, declarators):
  840.     """ member: type_spec declarators """
  841.  
  842.     members = []
  843.     for declarator in declarators:
  844.         # If this is an array declarator.
  845.         if isinstance(declarator, Declarator.ArrayDeclarator):
  846.         # Get the array dimensions.
  847.         dimensions = declarator.dimensions()
  848.  
  849.         # Create the array type.
  850.         actual_type_def = self.__create_array(type_def, dimensions)
  851.  
  852.         # Otherwise it is a simple declarator.
  853.         else:
  854.         actual_type_def = type_def
  855.  
  856.         # Create a 'StructMember' instance.
  857.         members.append(CORBA.StructMember(declarator.name(),
  858.                           actual_type_def._get_type(),
  859.                           actual_type_def))
  860.     return members
  861.  
  862.     def union_type_header(self, name, type_def):
  863.     """ union_type: UNION IDENTIFIER SWITCH '(' switch_type_spec ')' """
  864.  
  865.     # Get the container and prefix from the stacks.
  866.     container = self.__container_stack.get()
  867.     prefix = self.__prefix_stack.get()
  868.  
  869.     # Does the container already contain a definition with this name?
  870.     union = container.lookup(name)
  871.  
  872.     # If there is *no* definition with this name then we can safely create
  873.     # a new union.
  874.     if union is None:
  875.         # Set the version to "wip" (for Work In Progress) to allow the
  876.         # detection of recursive types.
  877.         version = "wip"
  878.  
  879.         # Generate an interface repository id.
  880.         ifr_id = self.__create_ifr_id(prefix, name, version)
  881.  
  882.         # Create a new union definition in the container.
  883.         union = container.create_union(ifr_id, name, version, type_def, [])
  884.  
  885.         # If the union is defined at the global scope of the top-level IDL
  886.         # file then add it to our list of top-level definitions.
  887.         if self.__is_a_top_level_definition(union):
  888.         self.__top_level_definitions.append(union)
  889.  
  890.     # Otherwise, a definition with this name already exists.
  891.     else:
  892.         self.yyerror("Redefinition of name '%s'" % name)
  893.         raise bison.YYERROR
  894.  
  895.     # Push the union onto the container stack.
  896.     self.__container_stack.push(union)
  897.  
  898.     # Push a new prefix onto the prefix stack.
  899.     self.__prefix_stack.push(self.__create_prefix(prefix, name))    
  900.  
  901.     return union
  902.  
  903.     def union_type_body(self, union, members):
  904.     """ union_type: '{' switch_body '}' """
  905.  
  906.     # Get the union's discrimintator (aka switch) typecode and type
  907.     # definition.
  908.     typecode = union._get_discriminator_type()
  909.     type_def = union._get_discriminator_type_def()
  910.  
  911.     # Make sure that all member names and label values are unique. This
  912.     # could take some time if some idiot has used, say an unsigned long as
  913.     # the discriminator type and a couple of billion cases ;^)
  914.     name_dict = {}
  915.     label_dict = {}
  916.     default_used = 0
  917.  
  918.     for member in members:
  919.         # Ignore the default case.
  920.         if member.label.typecode().kind() == CORBA.tk_octet:
  921.         default_used = 1
  922.  
  923.         else:
  924.         # Get the label value.
  925.         value = member.label.value()
  926.  
  927.         # Make sure the label is the same type as the discriminant (or
  928.         # coercable to it).
  929.         if not self.__check_label_type(type_def, member.label):
  930.             self.yyerror("Invalid label value %s" % str(value))
  931.             raise bison.YYERROR
  932.  
  933.         # Make sure that the value is within the limits of the type,
  934.         # and coerce it if necessary.
  935.         (result, value) = self.__check_limits(type_def, member.label)
  936.         if not result:
  937.             self.yyerror("Label value '%s' out of range" % str(value))
  938.             raise bison.YYERROR
  939.  
  940.         # Wrap the coerced value back in an 'Any' of the appropriate
  941.         # type.
  942.         member.label = CORBA.Any(typecode, value)
  943.  
  944.         # Name check.
  945.         if name_dict.has_key(member.name):
  946.             self.yyerror("Duplicate member name '%s'" % member.name)
  947.             raise bison.YYERROR
  948.  
  949.         name_dict[member.name] = None
  950.  
  951.         # Label check.
  952.         if label_dict.has_key(value):
  953.             self.yyerror("Duplicate case label %s" % str(value))
  954.             raise bison.YYERROR
  955.  
  956.         label_dict[value] = None
  957.  
  958.         # Check for recursive members.
  959.         if self.__is_recursive_member(member.type_def):
  960.             # Get the repository id of the recursive structure.
  961.             ifr_id = member.type_def._get_element_type_def()._get_id()
  962.  
  963.             # Find out how deep the recursion is.
  964.             offset = self.__get_recursion_depth(union, ifr_id)
  965.  
  966.             # Get the bound of the sequence type.
  967.             length = member.type.length()
  968.  
  969.             # Replace the sequence typecode with a recursive sequence
  970.             # typecode.
  971.             member.type = CORBA.RecursiveSequenceTypeCode(length,
  972.                                   offset)
  973.  
  974.     # If a default case has been specified, then make sure that the
  975.     # case labels for the specified type haven't been exhausted.
  976.     if default_used:
  977.         # Get the typecode kind.
  978.         kind = typecode.kind()
  979.  
  980.         if kind == CORBA.tk_enum:
  981.         limit = typecode.member_count()
  982.         
  983.         elif kind == CORBA.tk_short \
  984.          or typecode.kind() == CORBA.tk_ushort:
  985.         limit = 65536 # 2 ^ 16
  986.  
  987.         elif kind == CORBA.tk_long \
  988.              or typecode.kind() == CORBA.tk_ulong:
  989.         limit = 4294967296L # 2 ^ 32
  990.  
  991.         elif kind == CORBA.tk_longlong \
  992.              or typecode.kind() == CORBA.tk_ulonglong:
  993.         limit = 18446744073709551616L # 2 ^ 64
  994.  
  995.         elif kind == CORBA.tk_char:
  996.         limit = 256 # 2 ^ 8
  997.  
  998.         elif kind == CORBA.tk_boolean:
  999.         limit = 2 # 2 ;^)
  1000.  
  1001.         if len(members) - 1 >= limit:
  1002.         self.yyerror("All case labels exhausted")
  1003.         raise bison.YYERROR
  1004.  
  1005.     # Fixup the version.
  1006.     union._set_version("1.0")
  1007.  
  1008.     # Update the union definition.
  1009.     union._set_members(members)
  1010.  
  1011.     # Pop the container and prefix from the stacks.
  1012.     self.__container_stack.pop()
  1013.     self.__prefix_stack.pop()
  1014.     
  1015.     return union
  1016.  
  1017.     # Valid types for union switch specifications.
  1018.     __SWITCH_TYPES = [CORBA.pk_short,
  1019.               CORBA.pk_long,
  1020.               CORBA.pk_longlong,
  1021.               CORBA.pk_ushort,
  1022.               CORBA.pk_ulong,
  1023.               CORBA.pk_ulonglong,
  1024.               CORBA.pk_char,
  1025.               CORBA.pk_boolean]
  1026.  
  1027.     def switch_type_spec_scoped_name(self, scoped_name):
  1028.     """ switch_type_spec: scoped_name """
  1029.  
  1030.     # Get the container from the stack.
  1031.     container = self.__container_stack.get()
  1032.  
  1033.     # Lookup the definition referenced by the scoped name.
  1034.     definition = self.__find_scoped_name(container, scoped_name)
  1035.  
  1036.     # Unwind any 'typedef' chain.
  1037.     definition = self.__unwind_typedef_chain(definition)
  1038.  
  1039.     # Make sure the definition type is either integer, char, boolean, or
  1040.     # an enumeration.
  1041.     if definition._get_def_kind() == CORBA.dk_Primitive:
  1042.         if definition._get_kind() not in IDLParser.__SWITCH_TYPES:
  1043.         self.yyerror("Invalid switch type '%s'" % scoped_name)
  1044.         raise bison.YYERROR
  1045.  
  1046.     elif definition._get_def_kind() != CORBA.dk_Enum:
  1047.         self.yyerror("Invalid switch type '%s'" % scoped_name)
  1048.         raise bison.YYERROR
  1049.        
  1050.     return definition
  1051.  
  1052.     def case(self, labels, (type_def, declarator)):
  1053.     """ case: case_label_PLUS element_spec ';' """
  1054.  
  1055.     typecode = type_def._get_type()
  1056.     name = declarator.name()
  1057.  
  1058.     members = []
  1059.     for label in labels:
  1060.         members.append(CORBA.UnionMember(name, label, typecode, type_def))
  1061.     
  1062.     return members
  1063.  
  1064.     def case_label_default(self):
  1065.     """ case_label: DEFAULT ':' """
  1066.  
  1067.     return CORBA.Any(CORBA.TC_octet, 0)
  1068.  
  1069.     def element_spec(self, type_def, declarator):
  1070.     """ element_spec: type_def declarator """
  1071.  
  1072.     return (type_def, declarator)
  1073.  
  1074.     def enum_type_header(self, name):
  1075.     """ enum_type: ENUM IDENTIFIER """
  1076.  
  1077.     # Get the container and prefix from the stacks.
  1078.     container = self.__container_stack.get()
  1079.     prefix = self.__prefix_stack.get()
  1080.  
  1081.     # Does the container already contain a definition with this name?
  1082.     enum = container.lookup(name)
  1083.  
  1084.     # If there is *no* definition with this name then we can safely create
  1085.     # a new enumeration.
  1086.     if enum is None:
  1087.         # Currently the version is always "1.0"!
  1088.         version = "1.0"
  1089.  
  1090.         # Generate an interface repository id.
  1091.         ifr_id = self.__create_ifr_id(prefix, name, version)
  1092.  
  1093.         # Create a new enumeration definition in the container.
  1094.         enum = container.create_enum(ifr_id, name, version, [])
  1095.  
  1096.         # If the enumeration is defined at the global scope of the
  1097.         # top-level IDL file then add it to our list of top-level
  1098.         # definitions.
  1099.         if self.__is_a_top_level_definition(enum):
  1100.         self.__top_level_definitions.append(enum)
  1101.  
  1102.     # Otherwise, a definition with this name already exists.
  1103.     else:
  1104.         self.yyerror("Redefinition of name '%s'" % name)
  1105.         raise bison.YYERROR
  1106.  
  1107.     return enum
  1108.  
  1109.     def enum_type_body(self, enum, members):
  1110.     """ enum_type: '{' enumerators '}' """
  1111.  
  1112.     # Get the container and prefix from the stacks.
  1113.     container = self.__container_stack.get()
  1114.     prefix = self.__prefix_stack.get()
  1115.  
  1116.     # Create temporary constant definitions for each member.
  1117.     for i in range(len(members)):
  1118.         # Get the name of the member.
  1119.         name = members[i]
  1120.  
  1121.         # Does the container already contain a definition with this name?
  1122.         constant = container.lookup(name)
  1123.  
  1124.         # If there is *no* definition with this name then we can safely
  1125.         # create a new constant.
  1126.         if constant is None:
  1127.         # Tag the enum member with a distinctive version ;^)
  1128.         version = "Delete Me!"
  1129.  
  1130.         # Generate an interface repository id.
  1131.         ifr_id = self.__create_ifr_id(prefix, name, version)
  1132.  
  1133.         # Create an Enum member instance.
  1134.         any = CORBA.Any(enum._get_type(), Util.EnumMember(name, i))
  1135.  
  1136.         # Create a new constant definition in the container.
  1137.         constant = container.create_constant(ifr_id, name, version,
  1138.                              enum, any)
  1139.  
  1140.             # Add the definition to our list of enumeration members to
  1141.         # be cleaned up at the end.
  1142.         self.__enum_members.append(constant)
  1143.  
  1144.         # Otherwise, a definition with this name already exists.
  1145.         else:
  1146.         self.yyerror("Redefinition of name '%s'" % name)
  1147.         raise bison.YYERROR
  1148.  
  1149.     # Update the enumeration definition.
  1150.     enum._set_members(members)
  1151.  
  1152.     return enum
  1153.  
  1154.     def native_type_dcl(self, identifier):
  1155.     """ type_dcl: NATIVE simple_declarator """
  1156.     
  1157.     self.yywarning('No native types specified in the language mapping')
  1158.     return
  1159.  
  1160.     def sequence_type(self, element_type_def, bound=0):
  1161.     """ sequence_type: SEQUENCE
  1162.                           '<' simple_type_spec ',' positive_int_const '>'
  1163.                           |
  1164.                           SEQUENCE '<' simple_type_spec '>'
  1165.         """
  1166.         return self.__repository.create_sequence(bound, element_type_def)
  1167.  
  1168.     def string_type(self, bound=0):
  1169.     """ string_type: STRING '<' positive_int_const '>'
  1170.                          |
  1171.                          STRING
  1172.         """
  1173.     if bound == 0:
  1174.         definition = self.__repository.get_primitive(CORBA.pk_string)
  1175.  
  1176.     else:
  1177.         definition = self.__repository.create_string(bound)
  1178.  
  1179.     return definition
  1180.  
  1181.     def wide_string_type(self, bound=0):
  1182.     """ wide_string_type: WSTRING '<' positive_int_const '>'
  1183.                               |
  1184.                               WSTRING
  1185.         """
  1186.     self.yywarning("'wstring' not supported by Fnorb runtime")
  1187.     if bound == 0:
  1188.         definition = self.__repository.get_primitive(CORBA.pk_wstring)
  1189.  
  1190.     else:
  1191.         definition = self.__repository.create_wstring(bound)
  1192.  
  1193.     return definition
  1194.  
  1195.     def array_declarator(self, name, dimensions):
  1196.     """ array_declarator: IDENTIFIER fixed_array_size_PLUS """
  1197.  
  1198.     return Declarator.ArrayDeclarator(name, dimensions)
  1199.  
  1200.     def fixed_array_size(self, dimension):
  1201.     """ fixed_array_size: '[' positive_int_const ']' """
  1202.  
  1203.     return dimension
  1204.  
  1205.     def attr_dcl(self, mode, type_def, declarators):
  1206.     """ attr_dcl: readonly_OPT ATTRIBUTE param_type_spec
  1207.                       simple_declarators
  1208.  
  1209.     """
  1210.     # Get the container and prefix from the stacks.
  1211.     container = self.__container_stack.get()
  1212.     prefix = self.__prefix_stack.get()
  1213.  
  1214.     for declarator in declarators:
  1215.         # Get the name of the declarator.
  1216.         name = declarator.name()
  1217.  
  1218.         # Does the container already contain a definition with this name?
  1219.         attribute = container.lookup(name)
  1220.  
  1221.         # If there is *no* definition with this name then we can safely
  1222.         # create a new attribute.
  1223.         if attribute is None:
  1224.         # Currently the version is always "1.0"!
  1225.         version = "1.0"
  1226.  
  1227.         # Generate an interface repository id.
  1228.         ifr_id = self.__create_ifr_id(prefix, name, version)
  1229.  
  1230.         # Create a new attribute definition in the container.
  1231.         attribute = container.create_attribute(ifr_id, name, version,
  1232.                                type_def, mode)
  1233.  
  1234.         # Otherwise, a definition with this name already exists.
  1235.         else:
  1236.         self.yyerror("Redefinition of name '%s'" % name)
  1237.         raise bison.YYERROR
  1238.  
  1239.     return
  1240.  
  1241.     def readonly_OPT_normal(self):
  1242.     """ readonly_OPT: /* empty */ """
  1243.  
  1244.     return CORBA.ATTR_NORMAL
  1245.  
  1246.     def readonly_OPT_readonly(self):
  1247.     """ readonly_OPT: READONLY """
  1248.  
  1249.     return CORBA.ATTR_READONLY
  1250.  
  1251.     def except_dcl_header(self, name):
  1252.     """ EXCEPTION IDENTIFIER """
  1253.     
  1254.     # Get the container and prefix from the stacks.
  1255.     container = self.__container_stack.get()
  1256.     prefix = self.__prefix_stack.get()
  1257.  
  1258.     # Does the container already contain a definition with this name?
  1259.     exception = container.lookup(name)
  1260.  
  1261.     # If there is *no* definition with this name then we can safely create
  1262.     # a new exception.
  1263.     if exception is None:
  1264.         # Currently the version is always "1.0"!
  1265.         version = "1.0"
  1266.  
  1267.         # Generate an interface repository id.
  1268.         ifr_id = self.__create_ifr_id(prefix, name, version)
  1269.  
  1270.         # Create a new exception definition in the container.
  1271.         exception = container.create_exception(ifr_id, name, version, [])
  1272.  
  1273.         # If the exception is defined at the global scope of the top-level
  1274.         # IDL file then add it to our list of top-level definitions.
  1275.         if self.__is_a_top_level_definition(exception):
  1276.         self.__top_level_definitions.append(exception)
  1277.  
  1278.     # Otherwise, a definition with this name already exists.
  1279.     else:
  1280.         self.yyerror("Redefinition of name '%s'" % name)
  1281.         raise bison.YYERROR
  1282.  
  1283.     # Push the exception onto the container stack.
  1284.     self.__container_stack.push(exception)
  1285.  
  1286.     # Push a new prefix onto the prefix stack.
  1287.     self.__prefix_stack.push(self.__create_prefix(prefix, name))    
  1288.  
  1289.     return exception
  1290.  
  1291.     def except_dcl_body(self, exception, members):
  1292.     """ except_dcl: '{' member_STAR '}' """
  1293.     
  1294.     # The same as for structure definitions!
  1295.     self.struct_type_body(exception, members)
  1296.     return
  1297.  
  1298.     def op_dcl_header(self, mode, result_type_def, name):
  1299.     """ op_dcl: op_attribute_OPT op_type_spec IDENTIFER """
  1300.  
  1301.     # Get the container and prefix from the stacks.
  1302.     container = self.__container_stack.get()
  1303.     prefix = self.__prefix_stack.get()
  1304.  
  1305.     # Does the container already contain a definition with this name?
  1306.     operation = container.lookup(name)
  1307.  
  1308.     # If there is *no* definition with this name then we can safely create
  1309.     # a new operation.
  1310.     if operation is None:
  1311.         # Currently the version is always "1.0"!
  1312.         version = "1.0"
  1313.  
  1314.         # Generate an interface repository id.
  1315.         ifr_id = self.__create_ifr_id(prefix, name, version)
  1316.  
  1317.         # Create a new operation definition in the container.
  1318.         operation = container.create_operation(ifr_id, name, version,
  1319.                            result_type_def,
  1320.                            mode,
  1321.                            [], # Parameters.
  1322.                            [], # Exceptions.
  1323.                            []) # Contexts.
  1324.  
  1325.     # Otherwise, a definition with this name already exists.
  1326.     else:
  1327.         self.yyerror("Redefinition of name '%s'" % name)
  1328.         raise bison.YYERROR
  1329.  
  1330.     return operation
  1331.  
  1332.     def op_dcl_body(self, operation, params, exceptions, contexts):
  1333.     """ op_dcl: op_attribute_OPT op_type_spec IDENTIFER """
  1334.  
  1335.     # Make sure that the parameter names are unique.
  1336.     dict = {}
  1337.     for param in params:
  1338.         if dict.has_key(param.name):
  1339.         self.yyerror("Duplicate parameter name '%s'" % param.name)
  1340.         raise bison.YYERROR
  1341.  
  1342.         dict[param.name] = None
  1343.  
  1344.     # Update the operation definition.
  1345.     operation._set_params(params)
  1346.     operation._set_exceptions(exceptions)
  1347.     operation._set_contexts(contexts)
  1348.  
  1349.     return
  1350.  
  1351.     def op_attribute_OPT_empty(self):
  1352.     """ op_attribute_OPT: /* empty */ """
  1353.  
  1354.     return CORBA.OP_NORMAL
  1355.  
  1356.     def op_attribute_OPT_oneway(self):
  1357.     """ op_attribute_OPT: ONEWAY """
  1358.  
  1359.     return CORBA.OP_ONEWAY
  1360.  
  1361.     def op_type_spec_void(self):
  1362.     """ op_type_spec: VOID """
  1363.  
  1364.     return self.__repository.get_primitive(CORBA.pk_void)
  1365.  
  1366.     def parameter_dcls_empty(self):
  1367.     """ parameter_dcls: '(' ')' """
  1368.  
  1369.     return []
  1370.  
  1371.     def param_dcl(self, mode, type_def, declarator):
  1372.     """ param_dcl: param_attribute param_type_spec simple_declarator """
  1373.  
  1374.     return CORBA.ParameterDescription(declarator.name(),
  1375.                       type_def._get_type(),
  1376.                       type_def,
  1377.                       mode)
  1378.     def param_attribute_in(self):
  1379.     """ param_attribute: IN """
  1380.  
  1381.     return CORBA.PARAM_IN
  1382.  
  1383.     def param_attribute_out(self):
  1384.     """ param_attribute: OUT """
  1385.  
  1386.     return CORBA.PARAM_OUT
  1387.  
  1388.     def param_attribute_inout(self):
  1389.     """ param_attribute: INOUT """
  1390.  
  1391.     return CORBA.PARAM_INOUT
  1392.  
  1393.     def raises_expr_OPT_empty(self):
  1394.     """ raises_expr_OPT: /* empty */ """
  1395.  
  1396.     return []
  1397.  
  1398.     def raises_expr(self, scoped_names):
  1399.     """ raises_expr: RAISES '(' scoped_name_CSV_PLUS ')' """
  1400.  
  1401.     # Get the container and prefix from the stacks.
  1402.     container = self.__container_stack.get()
  1403.  
  1404.     # Make sure that all of the names refer to exceptions!
  1405.     exceptions = []
  1406.     for scoped_name in scoped_names:
  1407.         # Lookup the definition referenced by the scoped name.
  1408.         definition = self.__find_scoped_name(container, scoped_name)
  1409.         if definition is None:
  1410.         raise bison.YYERROR
  1411.  
  1412.         # Make sure that it is an exception definition.
  1413.         if definition._get_def_kind() != CORBA.dk_Exception:
  1414.         self.yyerror("'%s' is not an exception" % scoped_name)
  1415.         raise bison.YYERROR
  1416.  
  1417.         exceptions.append(definition)
  1418.  
  1419.     return exceptions
  1420.  
  1421.     def context_expr_OPT_empty(self):
  1422.     """ context_expr_OPT: /* empty */ """
  1423.  
  1424.     return []
  1425.  
  1426.     def context_expr(self, string_literals):
  1427.     """ context_expr: CONTEXT '(' string_literal_CSV_PLUS ')' """
  1428.  
  1429.     # fixme: Fnorb does not support contexts!
  1430.     for string_literal in string_literals:
  1431.         self.yywarning("%s context ignored" % string_literal)
  1432.  
  1433.     return []
  1434.  
  1435.     def fixed_pt_type(self, digits, scale):
  1436.     """ fixed_pt_type: FIXED '<' positive_int_const ',' integer_literal '>'
  1437.  
  1438.         The fixed point type is not yet implemented.
  1439.  
  1440.         """
  1441.     self.yywarning("'fixed' not supported by Fnorb runtime")
  1442.  
  1443.     # 'digits' is a positive integer constant and is returned as a Python
  1444.     # long, and ;scale' is an integer literal which is returned as an
  1445.     # 'Any'.
  1446.     return self.__repository.create_fixed(digits, scale.value())
  1447.  
  1448.     def fixed_pt_const_type(self):
  1449.     """ fixed_pt_const_type: FIXED """
  1450.  
  1451.     self.yywarning("'fixed' constants not supported by Fnorb runtime")
  1452.     return self.__repository.create_fixed(0, 0)
  1453.     #
  1454.     # '#pragma' directives.
  1455.     #
  1456.     def pragma(self, yytext):
  1457.     """ PRAGMA """
  1458.  
  1459.     # Split the text of the directive on spaces.
  1460.     components = string.split(yytext)
  1461.  
  1462.     # Ignore any malformed directives.
  1463.     if len(components) == 3:
  1464.         if components[1] == 'prefix':
  1465.         try:
  1466.             # The prefix must be a quoted string.
  1467.             pragma_prefix = eval(components[2])
  1468.             if type(pragma_prefix) != types.StringType:
  1469.             raise TypeError
  1470.  
  1471.             # Get the current prefix from the stack.
  1472.             prefix = self.__prefix_stack.get()    
  1473.  
  1474.             # Update the 'pragma' portion of the prefix.
  1475.             prefix.set_pragma(pragma_prefix)
  1476.             
  1477.         # Ignore any errors.
  1478.             except:
  1479.             self.yywarning("Malformed #pragma prefix")
  1480.  
  1481.     elif len(components) == 4:
  1482.         if components[1] == 'ID':
  1483.         try:
  1484.             # Get the name of the definition.
  1485.             name = components[2]
  1486.  
  1487.             # The id must be a quoted string.
  1488.             ifr_id = eval(components[3])
  1489.             if type(ifr_id) != types.StringType:
  1490.             raise TypeError
  1491.  
  1492.             # Get the container from the stacks.
  1493.             container = self.__container_stack.get()
  1494.  
  1495.             # Lookup the definition referenced by the scoped name.
  1496.             definition = self.__find_scoped_name(container, name)
  1497.             if definition is None:
  1498.             raise bison.YYERROR
  1499.  
  1500.             # Update the definition's interface repository id.
  1501.             definition._set_id(ifr_id)
  1502.             
  1503.         # Ignore any errors.
  1504.             except:
  1505.             self.yywarning("Malformed #pragma ID")
  1506.  
  1507.         elif components[1] == 'version':
  1508.         try:
  1509.             # Get the name of the definition.
  1510.             name = components[2]
  1511.  
  1512.             # The version is used as a string, but must be in the
  1513.             # format <major>.<minor>
  1514.             version = components[3]
  1515.             if type(eval(version)) != types.FloatType:
  1516.             raise TypeError
  1517.             
  1518.             # Get the container from the stacks.
  1519.             container = self.__container_stack.get()
  1520.  
  1521.             # Lookup the definition referenced by the scoped name.
  1522.             definition = self.__find_scoped_name(container, name)
  1523.             if definition is None:
  1524.             raise bison.YYERROR
  1525.  
  1526.             # Update the definition's version.
  1527.             definition._set_version(version)
  1528.             
  1529.         # Ignore any errors.
  1530.             except:
  1531.             self.yywarning("Malformed #pragma version")
  1532.  
  1533.     return
  1534.  
  1535.     def line_directive(self, yytext):
  1536.     """ Parse line/file pre-processor directives.
  1537.     
  1538.     This method is called from the lexer (see the file 'lexer.l').
  1539.  
  1540.     """
  1541.     line = None
  1542.     file = None
  1543.  
  1544.     # Split the text on spaces.
  1545.     components = string.split(yytext)
  1546.  
  1547.     # If this a '# line' directive.
  1548.     if components[1] == 'line':
  1549.         # e.g. '# line 1'
  1550.         line = eval(components[2])
  1551.         
  1552.         # e.g. '# line 1 "filename.idl"
  1553.         if len(components) >= 4:
  1554.         file = eval(components[3])
  1555.  
  1556.     # Otherwise this is a pre-processor inserted line.
  1557.         else:
  1558.         # e.g. '# 1'
  1559.         line = eval(components[1])
  1560.             
  1561.         # e.g. '# 1 "filename.idl"
  1562.         if len(components) >= 3:
  1563.         file = eval(components[2])
  1564.  
  1565.     # Update the line number.
  1566.     if line is not None:
  1567.         bison.yylineno(line)
  1568.         
  1569.     # Update the file.
  1570.     if file is not None:
  1571.         # Get the prefix stack for this file.
  1572.         try:
  1573.         self.__prefix_stack = self.__prefix_stacks[file]
  1574.  
  1575.         # If there is no prefix stack for this file then create one!
  1576.         except KeyError:
  1577.         # The prefix stack initially contains just an empty prefix.
  1578.         self.__prefix_stack = Stack.Stack()
  1579.         self.__prefix_stack.push(Prefix.Prefix())
  1580.         self.__prefix_stacks[file] = self.__prefix_stack
  1581.  
  1582.         # Update the current filename.
  1583.         self.__current_file = file
  1584.         
  1585.     return
  1586.     #
  1587.     # Generic actions.
  1588.     #
  1589.     def list_empty(self):
  1590.     """ Generic empty list. """
  1591.  
  1592.     return []
  1593.  
  1594.     def list_insert(self, item, list):
  1595.     """ Generic list insert. """
  1596.  
  1597.     if type(item) == types.ListType:
  1598.         list = item + list
  1599.  
  1600.     else:
  1601.         list.insert(0, item)
  1602.  
  1603.     return list
  1604.  
  1605.     def idl_type_scoped_name(self, scoped_name):
  1606.     """ Check that the scoped name references an IDL type definition. """
  1607.  
  1608.     # Get the container from the stack.
  1609.     container = self.__container_stack.get()
  1610.  
  1611.     # Lookup the definition referenced by the scoped name.
  1612.     definition = self.__find_scoped_name(container, scoped_name)
  1613.     if definition is None:
  1614.         raise bison.YYERROR
  1615.  
  1616.     # If it is not an 'IDLType' definition then it is illegal.
  1617.     if not definition._is_a("IDL:omg.org/CORBA/IDLType:1.0"):
  1618.         self.yyerror("'%s' is not a type name" % scoped_name)
  1619.         raise bison.YYERROR
  1620.  
  1621.     return definition
  1622.  
  1623.     #########################################################################
  1624.     # Private interface.
  1625.     #########################################################################
  1626.  
  1627.     def __initialise(self):
  1628.     """ Initialise the various data structures used during parsing. """
  1629.  
  1630.     # The name of the IDL file currently being parsed.
  1631.     self.__current_file = self.__filename
  1632.  
  1633.     # A dictionary of prefix stacks - keyed on filename.
  1634.     self.__prefix_stacks = {} # {Filename: Stack<Prefix>}
  1635.  
  1636.     # The prefix stack initially contains just an empty prefix.
  1637.     self.__prefix_stack = Stack.Stack()
  1638.     self.__prefix_stack.push(Prefix.Prefix())
  1639.     self.__prefix_stacks[self.__filename] = self.__prefix_stack
  1640.  
  1641.     # A list of all definitions at the global scope of the top-level IDL
  1642.     # file.
  1643.     self.__top_level_definitions = []
  1644.  
  1645.     # A dictionary of all interfaces along with the names of their
  1646.     # operations and attributes.
  1647.     self.__interfaces = {} # {RepositoryId: [NamesofOpsAndAttributes]}
  1648.  
  1649.     # A dictionary of forward declared but undefined interfaces.
  1650.     self.__forward_interfaces = {} # {RepositoryId: (InterfaceDef, LineNo)}
  1651.  
  1652.     # A list of the temporary constant definitions created for members of 
  1653.     # enumerations.
  1654.     self.__enum_members = []
  1655.  
  1656.     return
  1657.  
  1658.     def __cleanup(self):
  1659.     """ Cleanup after parsing. """
  1660.  
  1661.     # Get rid of the temporary contant definitions created for members of
  1662.     # enumerations.
  1663.     for enum_member in self.__enum_members:
  1664.         enum_member.destroy()
  1665.  
  1666.     return
  1667.  
  1668.     def __create_prefix(self, prefix, name):
  1669.     """ Create a new prefix. """
  1670.  
  1671.     new_prefix = "%s%s/" % (prefix.get_prefix(), name)
  1672.     return Prefix.Prefix(prefix.get_pragma(), new_prefix)
  1673.  
  1674.     def __create_ifr_id(self, prefix, name, version):
  1675.     """ Create an interface repository id. """
  1676.  
  1677.     return "IDL:%s%s:%s" % (str(prefix), name, version)
  1678.  
  1679.     def __find_scoped_name(self, container, scoped_name):
  1680.     """ Find the definition for the scoped name. """
  1681.  
  1682.     if scoped_name == "TypeCode":
  1683.         definition = self.__repository.get_primitive(CORBA.pk_TypeCode)
  1684.  
  1685.     elif scoped_name == "Principal":
  1686.         definition = self.__repository.get_primitive(CORBA.pk_Principal)
  1687.  
  1688.     else:
  1689.         # If the container is an interface then we look first in
  1690.         # the interface itself, and then recursively through its base
  1691.         # interfaces.
  1692.         if container._get_def_kind() == CORBA.dk_Interface:
  1693.         definition = self.__find_inherited(container, scoped_name)
  1694.  
  1695.         # Otherwise, we start by searching the current container, and then
  1696.         # its enclosing scopes.
  1697.         else:
  1698.         definition = container.lookup(scoped_name)
  1699.  
  1700.         # While the definition is not found.
  1701.         while definition is None:
  1702.         # Is the container also 'contained'?
  1703.         if container._is_a("IDL:omg.org/CORBA/Contained:1.0"):
  1704.             # Get the container's container ;^)
  1705.             container = container._get_defined_in()
  1706.  
  1707.             # Look in there!
  1708.             definition = container.lookup(scoped_name)
  1709.  
  1710.         else:
  1711.             self.yyerror("Undeclared scoped name '%s'" % scoped_name)
  1712.             break
  1713.  
  1714.     return definition
  1715.  
  1716.     def __find_inherited(self, container, scoped_name):
  1717.     """ Find the definition for the scoped name. """
  1718.  
  1719.     # Lookup the name in the interface first.
  1720.     definition = container.lookup(scoped_name)
  1721.     if definition is None:
  1722.         # Look through all base interfaces.
  1723.         for base in container._get_base_interfaces():
  1724.         # Lookup the name in the base's base interfaces!
  1725.         definition = self.__find_inherited(base, scoped_name)
  1726.         if definition is not None:
  1727.             break
  1728.  
  1729.     return definition
  1730.  
  1731.     def __create_array(self, type_def, dims):
  1732.     """ Create an array type definition. """
  1733.  
  1734.     # Single dimension
  1735.     if len(dims) == 1:
  1736.         array_type_def = self.__repository.create_array(dims[0], type_def)
  1737.  
  1738.     # Multi-dimension
  1739.     else:
  1740.         # Create the 'slice' type.
  1741.         slice_type_def = self.__repository.create_array(dims[-1], type_def)
  1742.  
  1743.         # Recursively create the array type.
  1744.         array_type_def = self.__create_array(slice_type_def, dims[:-1])
  1745.  
  1746.     return array_type_def
  1747.  
  1748.     def __is_a_top_level_definition(self, definition):
  1749.     """ Is the defn at the global scope of the top-level IDL file? """
  1750.  
  1751.     if self.__current_file == self.__filename \
  1752.        and definition._get_defined_in() == self.__repository:
  1753.         result = 1
  1754.     
  1755.     else:
  1756.         # Include any global scope definitions that are not modules!
  1757.         if definition._get_defined_in() == self.__repository \
  1758.            and definition._get_def_kind() != CORBA.dk_Module:
  1759.         result = 1
  1760.  
  1761.         else:
  1762.         result = 0
  1763.  
  1764.     return result
  1765.  
  1766.     # Integer typecode kinds.
  1767.     __TK_INT = [CORBA.tk_short,
  1768.         CORBA.tk_long,
  1769.         CORBA.tk_longlong,
  1770.         CORBA.tk_ushort,
  1771.         CORBA.tk_ulong,
  1772.         CORBA.tk_ulonglong]
  1773.  
  1774.     # Floating point typecode kinds.
  1775.     __TK_FP = [CORBA.tk_float,
  1776.            CORBA.tk_double,
  1777.            CORBA.tk_longdouble]
  1778.  
  1779.     def __check_constant_type(self, type_def, any):
  1780.     """ Make sure that the value is of the specified type. """
  1781.  
  1782.     # Get the typecode 'kind's.
  1783.     type_def_kind = type_def._get_type().kind()
  1784.     any_kind = any.typecode().kind()
  1785.  
  1786.     if type_def_kind in IDLParser.__TK_INT \
  1787.        and any_kind in IDLParser.__TK_INT:
  1788.         result = 1
  1789.  
  1790.     elif type_def_kind in IDLParser.__TK_FP \
  1791.          and any_kind in IDLParser.__TK_FP:
  1792.         result = 1
  1793.  
  1794.     elif type_def_kind == any_kind:
  1795.         result = 1
  1796.  
  1797.     else:
  1798.         result = 0
  1799.  
  1800.     return result
  1801.  
  1802.     def __check_limits(self, type_def, any):
  1803.     """ Make sure that the value is within the limits of the type. """
  1804.  
  1805.     # Get the typecode 'kind'.
  1806.     type_def_kind = type_def._get_type().kind()
  1807.  
  1808.     # Get the value out of the any.
  1809.     value = any.value()
  1810.  
  1811.     if type_def_kind == CORBA.tk_short:
  1812.         if value < Limits.MIN_SHORT or value > Limits.MAX_SHORT:
  1813.         result = 0
  1814.         
  1815.         else:
  1816.         result = 1
  1817.         value = int(value)
  1818.  
  1819.     elif type_def_kind == CORBA.tk_ushort:
  1820.         if value < Limits.MIN_USHORT or value > Limits.MAX_USHORT:
  1821.         result = 0
  1822.  
  1823.         else:
  1824.         result = 1
  1825.         value = int(value)
  1826.  
  1827.     elif type_def_kind == CORBA.tk_long:
  1828.         if value < Limits.MIN_LONG or value > Limits.MAX_LONG:
  1829.         result = 0
  1830.  
  1831.         else:
  1832.         result = 1
  1833.         value = int(value)
  1834.  
  1835.     elif type_def_kind == CORBA.tk_ulong:
  1836.         if value < Limits.MIN_ULONG or value > Limits.MAX_ULONG:
  1837.         result = 0
  1838.  
  1839.         else:
  1840.         result = 1
  1841.  
  1842.     elif type_def_kind == CORBA.tk_longlong:
  1843.         if value < Limits.MIN_LONGLONG or value > Limits.MAX_LONGLONG:
  1844.         result = 0
  1845.  
  1846.         else:
  1847.         result = 1
  1848.  
  1849.     elif type_def_kind == CORBA.tk_ulonglong:
  1850.         if value < Limits.MIN_ULONGLONG or value > Limits.MAX_ULONGLONG:
  1851.         result = 0
  1852.  
  1853.         else:
  1854.         result = 1
  1855.         
  1856.     # fixme: This should not be here!!!
  1857.     elif type_def_kind == CORBA.tk_fixed:
  1858.         any_typecode = any.typecode()
  1859.         type_def._set_digits(any_typecode.fixed_digits())
  1860.         type_def._set_scale(any_typecode.fixed_scale())
  1861.  
  1862.         result = 1
  1863.  
  1864.     else:
  1865.         result = 1
  1866.  
  1867.     return (result, value)
  1868.  
  1869.     def __check_label_type(self, type_def, any):
  1870.     """ Make sure that the value is of the specified type. """
  1871.  
  1872.     # Get the typecode 'kind's.
  1873.     type_def_kind = type_def._get_type().kind()
  1874.     any_kind = any.typecode().kind()
  1875.  
  1876.     if type_def_kind in IDLParser.__TK_INT \
  1877.        and any_kind in IDLParser.__TK_INT:
  1878.         result = 1
  1879.  
  1880.     elif type_def_kind == any_kind:
  1881.         # If the union is switched on an enumeration then make sure that
  1882.         # the value is a valid element of the same enumeration!
  1883.         if type_def_kind == CORBA.tk_enum:
  1884.         if type_def._get_type().id() == any.typecode().id():
  1885.             result = 1
  1886.  
  1887.         else:
  1888.             result = 0
  1889.         else:
  1890.         result = 1
  1891.  
  1892.     else:
  1893.         result = 0
  1894.  
  1895.     return result
  1896.  
  1897.     def __check_forward_interfaces(self):
  1898.     """ Make sure that all forward declared interfaces were defined. """
  1899.  
  1900.     if len(self.__forward_interfaces) > 0:
  1901.         for (interface, yylineno) in self.__forward_interfaces.values():
  1902.         # Set the line number for error reporting.
  1903.         bison.yylineno(yylineno)
  1904.  
  1905.         # Report the error.
  1906.         self.yyerror("Interface '%s' declared but not defined" % \
  1907.                  interface._get_name())
  1908.         
  1909.         raise bison.YYERROR
  1910.  
  1911.     return
  1912.  
  1913.     def __get_inherited_operations(self, interface, visited):
  1914.     """ Get all operations and attributes inherited by an interface. """
  1915.  
  1916.     names = []
  1917.     for base in interface._get_base_interfaces():
  1918.         # Get the interface repository id of the interface.
  1919.         ifr_id = base._get_id()
  1920.         
  1921.         # Only include the operations and attributes for the interface
  1922.         # once!
  1923.         if ifr_id not in visited:
  1924.         # Add the interface's operations and attributes to the list.
  1925.         names = names + self.__interfaces[ifr_id]
  1926.  
  1927.         # Add the interface repository id of the interface to the list
  1928.         # of those already visited.
  1929.         visited.append(ifr_id)
  1930.  
  1931.         # Do it recursively!
  1932.         names = names + self.__get_inherited_operations(base, visited)
  1933.  
  1934.     # Check for duplicates!
  1935.     tmp = {}
  1936.     for name in names:
  1937.         if tmp.has_key(name):
  1938.         self.yyerror("Overloaded operation/attribute '%s'" % name)
  1939.         raise bison.YYERROR
  1940.  
  1941.         else:
  1942.         tmp[name] = None
  1943.  
  1944.     return names
  1945.  
  1946.     def __unwind_typedef_chain(self, definition):
  1947.     """ Unwind any 'typedef' chain! """
  1948.  
  1949.     # fixme: Which will it be? dk_Typedef or dk_Alias?!?!?!?!?! My bet is
  1950.     # on dk_Alias!
  1951.     while definition._get_def_kind() == CORBA.dk_Typedef \
  1952.           or definition._get_def_kind() == CORBA.dk_Alias:
  1953.         definition = definition._get_original_type_def()
  1954.  
  1955.     return definition
  1956.  
  1957.     def __is_recursive_member(self, type_def):
  1958.     """ Determine whether or not this is a recursive member. """
  1959.  
  1960.     if type_def._get_def_kind() == CORBA.dk_Sequence:
  1961.         element_type_def = type_def._get_element_type_def()
  1962.         if element_type_def._get_def_kind() == CORBA.dk_Struct or \
  1963.            element_type_def._get_def_kind() == CORBA.dk_Union:
  1964.         if element_type_def._get_version() == "wip":
  1965.             return 1
  1966.             
  1967.     return 0
  1968.  
  1969.     def __get_recursion_depth(self, type_def, ifr_id, depth=1):
  1970.     """ Find the depth (or 'offset') of a recursive type. """
  1971.  
  1972.     if type_def._get_id() == ifr_id:
  1973.         return depth
  1974.  
  1975.     else:
  1976.         return self.__get_recursion_depth(type_def._get_defined_in(),
  1977.                           ifr_id,
  1978.                           depth + 1)
  1979.     return
  1980.  
  1981. #############################################################################
  1982.