import string




def GenerateMasterODLFile():

    #From the BGEN This function is basically the inverse of PostProcess (Yikes)
    global g_interfaceCtr
    g_interfaceCtr = 0
    lines = GetSpecification(1)


    #Replace the internal idents
    ctr = 0

    for lctr in range(len(lines)):
        l = lines[lctr]
        index = string.find(l,"%%INTERNAL_IDENTIFIER%%")
        while index != -1:
            l = string.replace(l,"%%INTERNAL_IDENTIFIER%%","internal%d" % ctr,1)
            ctr = ctr + 1
            index = string.find(l,"%%INTERNAL_IDENTIFIER%%")

        lines[lctr] = l

    return string.join(lines,'')

# (1) specification ::= definition
#                     | definition specification

def GetSpecification(deep,indent = ''):
    rt = GetDefinition(deep,indent)
    if deep:
        rt = rt + GetSpecification(0,indent = indent)
    return rt

# (2) definition ::= type_dcl ';'
#                  | const_dcl ';'
#                  | except_dcl ';'
#                  | interface ';'
#                  | module ';'
#                  | class ';'
def GetDefinition(deep,indent):

    #Generate a Type Declaration
    print "Finish Definition"
    rt = []
    if deep:
        rt.extend(GetTypeDcl(deep,indent))

    #Generate a Const DEclartation
    if deep:
        rt = rt + GetConstDcl(deep,indent)
    #Generate an exception Declaration
    if deep:
        rt = rt + GetExceptDcl(deep,indent)
    #Generate an interface Declaration
    if deep:
        rt = rt + GetInterface(deep,indent)
    #Generate an module Declaration
    if deep:
        rt = rt + GetModule(deep,indent)
##    #Generate an class Declaration
##    rt = rt + GenerateClass()

    res = []
    for r in rt:
        res.append(r + ';\n')
    return res

### (2a) class ::= class_dcl
###              | class_forward_dcl
##def ProcessClass(db, klass, parent):
##    if klass[0]['TYPE'] == 'CLASS_DCL':
##        ProcessClassDcl(db, klass[0], parent)
##    elif klass[0]['TYPE'] == 'CLASS_FORWARD_DCL':
##        ProcessClassForwardDcl(db, klass[0], parent)

### (2b) class_dcl ::= class_header '{' interface_body '}'
##def ProcessClassDcl(db, klass, parent):
##    #A class is pretty simple, it can have a header and a body.  That's it
##    name, extender, inherits, propList = ProcessClassHeader(db, klass[0], parent)

##    #See if this was forward declared
##    absoluteName = '%s::%s' % (parent.absolute_name(), name)
    
##    c = g_forwards.get(absoluteName)
##    if c:
##        #This has been declared before, use it and fill in the new information
##        if inherits:
##            for i in inherits:
##                c.add_inherits(i)
##        if extender:
##            c.form_extender(extender)
##    else:
##        c = parent.add_class(name, inherits, extender)

##    # Allows for multiple forward declarations
##    g_forwards[absoluteName] = None

##    (extent, keys) = propList
        
##    if extent:
##        c.extents.insert_element(extent)

##    for k in keys:
##        c.keys.insert_element(k)

##    ProcessInterfaceBody(db,klass[2],c)

##    return

### (2c) class_forward_dcl ::= "class" IDENTIFIER
##def ProcessClassForwardDcl(db, forward, parent):

##    #Create a new instance of a class so it can be used later
##    name = forward[1]
##    absoluteName = '%s::%s' % (parent.absolute_name(), name)
##    if not g_forwards.has_key(absoluteName):
##        klass = parent.add_class(name, None, None)
##        g_forwards[absoluteName] = klass


### (2d) class_header ::= "class" IDENTIFIER
###                     | "class" IDENTIFIER "extends" scoped_name
###                     | "class" IDENTIFIER "extends" scoped_name inheritance_spec
###                     | "class" IDENTIFIER "extends" scoped_name type_property_list
###                     | "class" IDENTIFIER "extends" scoped_name inheritance_spec type_property_list
###                     | "class" IDENTIFIER inheritance_spec
###                     | "class" IDENTIFIER inheritance_spec type_property_list
###                     | "class" IDENTIFIER type_property_list
##def ProcessClassHeader(db, header, parent):
##    #This is one of the most complex definitions in the system
##    #a class header in logical form is (extends ext_name)? (inheritance_spec)? (type_property_list)?

##    #FIXME we do not support extends, inheritance, or type lists
##    extends = None
##    inherits = None
##    propList = (None,[])
##    pos = 2
##    if header.get(pos) == 'extends':
##        extends = ProcessScopedName(db, header[3], parent)
##        # skip scope_name
##        pos = pos + 2
        
##    argument = header.get(pos)
##    if argument and argument['TYPE'] == 'INHERITANCE_SPEC':
##         inherits = ProcessInheritanceSpec(db, argument, parent)
##         # possibly followed by type_property_list
##         argument = header.get(pos+1)
##    if argument and argument['TYPE'] == 'TYPE_PROPERTY_LIST':
##        propList = ProcessTypePropertyList(db, argument, parent)

##    name = header[1]
##    return name, extends, inherits, propList


### (2e) type_property_list ::= '(' ')'
###                           | '(' extent_spec ')'
###                           | '(' key_spec ')'
###                           | '(' extent_spec key_spec ')'
##def ProcessTypePropertyList(db, tpl, parent):

##    #NOTE the spec says there can be 2 of these, we only support 1
##    extent = None
##    keys = []

##    argument = tpl.get(2) and tpl[1]
##    if argument and argument['TYPE'] == 'EXTENT_SPEC':
##        extent = ProcessExtentSpec(db, argument, parent)
##        argument = tpl.get(3) and tpl[2]
##    if argument and argument['TYPE'] == 'KEY_SPEC':
##        keys = ProcessKeySpec(db,tpl[curCtr],parent)
##    return extent, keys

### (2f) extent_spec ::= "extent" IDENTIFIER
##def ProcessExtentSpec(db, extent_spec, parent):
##    return extent_spec[1]

### (2g) key_spec ::= "key" key_list
###                 | "keys" key_list
##def ProcessKeySpec(db, key_spec, parent):
##    raise FtodsUnsupportedError("Key Specification")

### (2h) key_list ::= key
###                 | key ',' key_list
##def ProcessKeyList(db, key_list, parent):
##    raise FtodsUnsupportedError("Key List")

### (2i) key ::= property_name
###            | '(' property_list ')'
##def ProcessKey(db, key, parent):
##    raise FtodsUnsupportedError("Key")

### (2j) property_list ::= property_name
###                      | property_name ',' property_list
##def ProcessPropertyList(db, property_list, parent):
##    raise FtodsUnsupportedError("Property List")

### (2k) property_name ::= IDENTIFIER
##def ProcessPropertyName(db, property_name, parent):
##    return property_name[0]

# (3) module ::= "module" IDENTIFIER '{' specification '}'
def GetModule(deep,indent):
    #Simple wrapper around a specification list
    specs = GetSpecification(0,indent = indent + '  ')
    res = indent + "module {\n%s%s}" % (string.join(specs,''),indent)
    return [res]

# (4) interface ::= interface_dcl | interface_forward_dcl
def GetInterface(deep,indent):
    global g_interfaceCtr
    ident = "%%INTERFACE-%d" % g_interfaceCtr
    g_interfaceCtr = g_interfaceCtr + 1

    return GetInterfaceForwardDcl(ident,indent) + GetInterfaceDcl(deep,ident,indent)

# (5) interface_dcl ::= interface_header { [ interface_body ] }
def GetInterfaceDcl(deep,ident,indent):
    ihs = GetInterfaceHeaders(deep,ident,indent)
    ibs = GetInterfaceBody(deep,indent)
    rt = []
    for h in ihs:
        for b in ibs:
            rt.append("%s { \n%s%s}" % (h,b,indent))
    return rt

# (6) interface_forward_dcl ::= interface ident
def GetInterfaceForwardDcl(ident,indent):
    return [indent + "interface %s" % ident]

# (7) interface_headers ::= interface ident [inheritance_spec]
def GetInterfaceHeaders(deep,ident,indent):
    rt = [ident + "interface %s" % ident]
    if deep:
        print "Finihs IS"
##        ihs = GetInheritanceSpec()
##        for i in ihs:
##            rt.append(ident + "interface %s %s" % (ident,i))

    return rt

# (8) interface_body ::= export
#                      | export interface_body
def GetInterfaceBody(deep,indent):
    exps = GetExport(deep,indent + '  ')
    return [string.join(exps,'')]

# (9) export ::= type_dcl ';'
#              | const_dcl ';'
#              | except_dcl ';'
#              | attr_dcl ';'
#              | rel_dcl ';'
#              | op_dcl ';'
def GetExport(deep,indent):
    rt = []
    print "Finish Exprt"
    if deep:
        rt = rt + GetTypeDcl(0,indent)
    if deep:
        rt = rt + GetConstDcl(0,indent)
    if deep:
        rt = rt + GetExceptDcl(0,indent)
    rt = rt + GetAttrDcl(deep,indent)
##    if deep:
##        rt = rt + GetRelDcl(deep,indent)
##    if deep:
##        rt = rt + GetOpDcl(deep,indent)
    res = []
    for r in rt:
        res.append("%s;\n" % r)
    return res

# (11) scoped_name ::= IDENTIFIER
#                    | "::" IDENTIFIER
#                    | scoped_name "::" IDENTIFIER
def GetScopedName():
    return ["%%SCOPED_NAME%%"]



# (12) const_dcl ::= "const" const_type IDENTIFIER '=' const_exp
def GetConstDcl(deep,indent):
    ct = GetConstType(deep)
    rt = []
    for t in ct:
        for e in GetConstExp(deep,t):
            rt.append(indent + "const " + t + " %%IDENTIFIER%% = " + ' ' + e)
    return rt


# (13) const_type ::= interger_type
#                   | char_type
#                   | boolean_type
#                   | floating_pt_type
#                   | string_type
#                   | scoped_name
def GetConstType(deep):
    rt = GetIntegerType()
    if not deep:
        return [rt[0]]
    rt.extend(GetCharType())
    rt.extend(GetBooleanType())
    rt.extend(GetFloatingPtType())
    rt.extend(GetStringType())
    rt.extend(GetScopedName())
    return rt

# (14) const_exp ::= or_expr
def GetConstExp(deep,typ):
    return GetOrExpr(deep,typ)

# (15) or_expr ::= xor_expr
#                | or_expr '|' xor_expr
def GetOrExpr(deep,typ):
    if typ in GetIntegerType() + GetBooleanType():
        #We can deal with it
        ands = GetXorExpr(deep,typ)[:100]
        if not deep:
            ands = [ands[0]]
        rt = []
        for a in ands:
            rt.append("%s" % (a))
            for r in ands:
                rt.append("%s | %s" % (a,r))
        return rt
    return GetXorExpr(deep,typ)

# (16) xor_expr ::= and_expr
#                 | xor_expr '^' and_expr
def GetXorExpr(deep,typ):
    if typ in GetIntegerType() + GetBooleanType():
        #We can deal with it
        ands = GetAndExpr(deep,typ)[:100]
        rt = []
        for a in ands:
            rt.append("%s" % (a))
            for r in ands:
                rt.append("%s ^ %s" % (a,r))
        return rt
    return GetAndExpr(deep,typ)


# (17) and_expr ::= shift_expr
#                 | and_expr '&' shift_expr
def GetAndExpr(deep,typ):
    if typ in GetIntegerType() + GetBooleanType():
        #We can deal with it
        sub = GetShiftExpr(deep,typ)[:100]
        rt = []
        for s in sub:
            rt.append("%s" % (s))
            for r in sub:
                rt.append("%s & %s" % (s,r))
        return rt
    return GetShiftExpr(deep,typ)


# (18) shift_expr ::= add_expr
#                   | shift_expr ">>" add_expr
#                   | shift_expr "<<" add_expr
def GetShiftExpr(deep,typ):
    if typ in GetIntegerType() + GetBooleanType():
        #We can deal with it
        sub = GetAddExpr(deep,typ)[:100]
        rt = []
        for s in sub:
            rt.append("%s" % (s))
            for r in sub:
                rt.append("%s << %s" % (s,r))
                rt.append("%s >> %s" % (s,r))
        return rt
    return GetAddExpr(deep,typ)



# (19) add_expr ::= mult_expr
#                 | add_expr '+' mult_expr
#                 | add_expr '-' mult_expr
def GetAddExpr(deep,typ):
    if typ in GetIntegerType() + GetBooleanType() + GetFloatingPtType():
        #We can deal with it
        sub = GetMultExpr(deep,typ)[:100]
        rt = []
        for s in sub:
            rt.append("%s" % (s))
            for r in sub:
                rt.append("%s + %s" % (s,r))
                rt.append("%s - %s" % (s,r))
        return rt
    return GetMultExpr(deep,typ)


# (20) mult_expr ::= unary_expr
#                  | mult_expr '*' unary_expr
#                  | mult_expr '/' unary_expr
#                  | mult_expr '%' unary_expr
def GetMultExpr(deep,typ):
    if typ in GetIntegerType() + GetBooleanType() + GetFloatingPtType():
        #We can deal with it
        sub = GetUnaryExpr(deep,typ)[:100]
        rt = []
        for s in sub:
            rt.append("%s" % (s))
            for r in sub:
                rt.append("%s * %s" % (s,r))
                rt.append("%s / %s" % (s,r))
                rt.append("%s %% %s" % (s,r))
        return rt
    return GetUnaryExpr(deep,typ)


# (21) unary_expr ::= unary_operator primary_expr
#                   | primary_expr
# (22) unary_operator ::= '+' | '-' | '~'
def GetUnaryExpr(deep,typ):
    if typ in GetIntegerType() + GetBooleanType() + GetFloatingPtType():
        #We can deal with it
        sub = GetPrimaryExpr(deep,typ)[:100]
        rt = []
        for s in sub:
            rt.append("%s" % (s))
            rt.append("+ %s" % (s))
            rt.append("- %s" % (s))
            rt.append("~ %s" % (s))
        return rt
    return GetPrimaryExpr(deep,typ)

# (23) primary_expr ::= scoped_name
#                     | literal
#                     | '(' const_exp ')'
def GetPrimaryExpr(deep,typ):
    rt = GetLiteral(deep,typ)
    if not deep:
        if not rt:
            print typ
        return [rt[0]]
    rt.extend(GetScopedName())
    rt.extend(map(lambda x:'('+x+')',GetConstExp(0,typ)))
    return rt
    
# (24) literal ::= integer_literal
#                | string_literal
#                | character_literal
#                | floating_pt_literal
#                | boolean_literal
def GetLiteral(deep,typ):
    if typ == '%%SCOPED_NAME%%':
        return [typ]
    rt = GetIntegerLiteral(deep,typ)
    rt.extend(GetStringLiteral(deep,typ))
    rt.extend(GetCharacterLiteral(deep,typ))
    rt.extend(GetFloatingPtLiteral(deep,typ))
    rt.extend(GetBooleanLiteral(deep,typ))
    return rt

# (25) boolean_literal ::= "true" | "false"

def GetIntegerLiteral(deep,typ):
    rt = []
    if typ in GetIntegerType():
        rt = ['100']
        if deep:
            rt.append('-100')
    return rt

def GetStringLiteral(deep,typ):
    rt = []
    if typ in GetStringType():
        rt = ['"A String"']
    return rt

def GetCharacterLiteral(deep,typ):
    rt = []
    if typ in GetCharType():
        rt = ["'A'"]
    return rt

def GetFloatingPtLiteral(deep,typ):
    rt = []
    if typ in GetFloatingPtType():
        rt = ['3.14']
        if deep:
            rt.append('-3.14')

    return rt

def GetBooleanLiteral(deep,typ):
    rt = []
    if typ in GetBooleanType():
        rt = ['TRUE']
        if deep:
            rt.append('FALSE')

    return rt


# (27) type_dcl ::= "typedef" type_declarator
#                 | struct_type
#                 | union_type
#                 | enum_type
def GetTypeDcl(deep,indent):

    types,declarators = GetTypeDeclarator(deep)
    rt = []
    for t in types:
        for dcls in declarators:
            rt.append(indent  + 'typedef %s %s' % (t,dcls))
    if not deep:
        return rt

##    elif type_dcl[0]['TYPE'] == 'ENUM_TYPE':
##        dcl = ProcessEnumType(db, type_dcl[0], parent)
##    elif type_dcl[0]['TYPE'] == 'STRUCT_TYPE':
##        dcl = ProcessStructType(db, type_dcl[0], parent)
##    elif type_dcl[0]['TYPE'] == 'UNION_TYPE':
##        dcl = ProcessUnionType(db, type_dcl[0], parent)
##    else:
##        #FIXME don't support rest of type dcls
##        raise FtodsUnsupportedError(type_dcl[0]['TYPE'])

    #Create a type for this td
    return rt

# (28) type_declarator ::= type_spec declarators
def GetTypeDeclarator(deep):
    types = GetTypeSpec(deep)
    declarators = GetDeclarators(deep)
    return types,declarators

# (29) type_spec ::= simple_type_spec
#                  | constr_type_spec
def GetTypeSpec(deep):
    rt = GetSimpleTypeSpec(deep)
    if deep:
        rt.extend(GetConstrTypeSpec())
    return rt

# (30) simple_type_spec ::= base_type_spec
#                         | tempalte_type_spec
#                         | scoped_name
def GetSimpleTypeSpec(deep):
    rt = GetBaseTypeSpec()
    if deep:
        rt.extend(GetTemplateTypeSpec())
        rt.extend(GetScopedName())
    return rt

# (31) base_type_spec ::= floating_pt_type
#                       | integer_type
#                       | char_type
#                       | boolean_type
#                       | octet_type
#                       | date_type
#                       | time_type
#                       | interval_type
#                       | timestamp_type
#                       | blob_type
def GetBaseTypeSpec():
    rt = GetFloatingPtType()
    rt.extend(GetIntegerType())
    rt.extend(GetCharType())
    rt.extend(GetBooleanType())
    rt.extend(GetOctetType())
    rt.extend(GetDateType())
    rt.extend(GetIntervalType())
    rt.extend(GetTimestampType())
    rt.extend(GetBlobType())
    return rt

# (31a) date_type ::= "date"

def GetDateType():
    return ['date']
    

# (31b) time_type ::= "time"
def GetTimeType():
    return ['time']


# (31c) interval_type ::= "interval"
def GetIntervalType():
    return ['interval']



# (31d) timestamp_type ::= "timestamp"
def GetTimestampType():
    return ['timestamp']


# (31-ft) blob_type ::= "blob"
def GetBlobType():
    return ['blob']

# (32) template_type_spec ::= array_type
#                           | string_type
#                           | coll_type
def GetTemplateTypeSpec():
    rt = GetArrayTypeSpec()
    rt.extend(GetStringType())
    rt.extend(GetCollType())
    return rt


# (32a) coll_type ::= coll_spec '<' simple_type_spec '>'
#                   | "dictionary" '<' simple_type_spec ',' simple_type_spec '>'
def GetCollType():
    rt = []
    cs = GetCollSpec()
    for c in cs:
        for t in GetSimpleTypeSpec(0):
            rt.append("%s < %s >" % (c,t))
    for k in GetSimpleTypeSpec(0):
        for v in GetSimpleTypeSpec(0):
            rt.append("dictionary < %s , %s >" % (k,v))
    return rt

# (32b) coll_spec ::= "set" | "list" | "bag"
def GetCollSpec():
    return ['set','list','bag']


# (33) constr_type_spec ::= struct_type
#                         | union_type
#                         | enum_type
def GetConstrTypeSpec():
    rt = GetStructType()
    rt.extend(GetUnionType())
    rt.extend(GetEnumType())
    return rt

# (34) declarators ::= declarator
#                    | declarator ',' declarators
def GetDeclarators(deep):
    return GetDeclarator(deep)

# (35) declarator ::= simple_declarator
#                   | complex_declarator
def GetDeclarator(deep):
    rt = GetSimpleDeclarator()
    if deep:
        rt.extend(GetComplexDeclarator())
    return rt

# (36) simple_declarator ::= IDENTIFIER
def GetSimpleDeclarator():
    return ["%%INTERNAL_IDENTIFIER%%"]

# (37) complex_declarator ::= array_declarator
def GetComplexDeclarator():
    print "Finish"
    return []

# (38) floating_pt_type ::= "float" | "double"
def GetFloatingPtType():
    return ['float','double']


# (39) integer_type ::= signed_int
#                     | unsigned_int
def GetIntegerType():
    return GetSignedIntType() + GetUnsignedIntType()

# (40) signed_int ::= signed_long_int
#                   | signed_long_long_int
#                   | signed_shoft_int
def GetSignedIntType():
    return ['long','long long','short']


### (43) unsigned_int ::= unsigned_long_int
###                     | unsigned_short_int
def GetUnsignedIntType():
    return ['unsigned long','unsigned short']


# (46) char_type ::= "char"
def GetCharType():
    return ['char']

# (47) boolean_type ::= "boolean"
def GetBooleanType():
    return ['boolean']


### (48) octet_type ::= "octet"
def GetOctetType():
    return ['octet']

### carried over from CORBA IDL
### (49) any_type ::= "any"

# (50) struct_type ::= "struct" INDENTIFIER '{' member_list '}'
def GetStructType():
    mlist = GetMemberList()
    rt = []
    for m in mlist:
        rt.append("struct %%IDENTIFIER%% { " + m + " } ")
    return rt

# (51) member_list ::= member
#                    | member member_list
def GetMemberList():
    rt = []
    members = GetMember()
    rt.append(members[0])
    for m in members[1:]:
        rt.append("%s %s" % (m,members[0]))
    return rt
              

# (52) member ::= type_spec declarators ';'
def GetMember():
    tps = GetTypeSpec(0)
    rt = []
    for t in tps:
        rt.append(t+" %%INTERNAL_IDENTIFIER%%;")
    return rt
        

# (53) union_type ::= "union" IDENTIFIER "switch" '(' switch_type_spec ')' '{' switch_body '}'
def GetUnionType():
    rt = []
    sts = GetSwitchTypeSpec()
    for t in sts:
        for body in GetSwitchBody(t):
            rt.append("union %%INDETIFIER%% switch ( %s ) { %s }" % (t,body))
    return rt

# (54) switch_type_spec ::= integer_type
#                         | char_type
#                         | boolean_type
#                         | enum_type
#                         | scoped_name

def GetSwitchTypeSpec():
    rt = GetIntegerType()
    rt.extend(GetCharType())
    rt.extend(GetEnumType())
    rt.extend(GetScopedName())
    return rt


# (55) switch_body ::= case
#                    | case switch_body

def GetSwitchBody(t):
    cases = GetCase(t)
    return [cases[0], string.join(cases,' ')]

# (56) case ::= case_label_list element_spec ';'
def GetCase(switchType):
    return ["Finish",'More Finish']
    labels = GetCaseLabelList()
    es = GetElementSpec()
    rt = []
    for l in labels:
        for e in es:
            rt.append("%s %s" % (l,e))

    return rt

# (56a) case_label_list ::= case_label
#                        | case_label case_label_list
def ProcessCaseLabelList(db,caseLabelList,parent,switchType):
    caseLabels = [ProcessCaseLabel(db,caseLabelList[0],parent,switchType)]
    if caseLabelList.get(1):
        caseLabels.extend(ProcessCaseLabelList(db,caseLabelList[1],parent,switchType))
    return caseLabels
                          
                  

### (57) case_label ::= "case" const_exp ':'
###                   | "default" ':'
##def ProcessCaseLabel(db,caseLabel,parent,switchType):
##    if caseLabel[0] == 'case':
##        if switchType.meta_kind == MetaKind.mk_enumeration:
##            #Could be a special case where they reference a enum element without the full path
##            #try:
##            if 1:
##                return ProcessConstExp(db,caseLabel[1],switchType)
##        return ProcessConstExp(db,caseLabel[1],parent)
##    return None

### (58) element_spec ::= type_spec declarator
##def ProcessElementSpec(db,elementSpec,parent):
##    return ProcessTypeSpec(db,elementSpec[0],parent),ProcessDeclarator(db,elementSpec[1],parent)

# (59) enum_type ::= "enum" IDENTIFIER '{' enumerator_list '}'
def GetEnumType():
    return ['enum %%IDENTIFIER%% {%%INTERNAL_IDENTIFIER%%}','enum %%IDENTIFIER%% {%%INTERNAL_IDENTIFIER%%, %%INTERNAL_IDENTIFIER%%}']




# (61) array_type ::= array_spec '<' simple_type_spec ',' positive_int_const '>'
#                   | array_spec '<' simple_type_spec '>'

def GetArrayTypeSpec():
    types = GetSimpleTypeSpec(0)
    rt = []
    for a in GetArraySpec():
        for t in types:
            rt.append("%s < %s, 3>" % (a,t))
            rt.append("%s < %s>" % (a,t))
    return rt
            
# (61a) array_spec ::= "array" | "sequence"
def GetArraySpec():
    return ['array','sequence']

# (62) string_type ::= "string" '<' positive_int_const '>'
#                    | "string"
def GetStringType():
    return ['string','string <3>']

        
### (63) array_declarator ::= IDENTIFIER array_size_list

### (63a) array_size_list ::= fixed_array_size
###                         | fixed_array_size array_size_list

### (64) fixed_array_size ::= '[' positive_int_const ']'

# (65) attr_dcl ::= "attribute" domain_type attr_list
#                 | "readonly" "attribute" domain_type attr_list
def GetAttrDcl(deep,indent):

    dts = GetDomainType(deep)
    ctr = 0
    rt = []
    for t in dts:
        for a in GetAttrList(deep,ctr):
            rt.append(indent + "attribute %s %s" % (t,a))
            rt.append(indent + "readonly attribute %s %s" % (t,a))
        ctr = ctr + 1
    return rt


# (65a) attr_list ::= attribute_name
#                   | attribute_name fixed_array_size
#                   | attribute_name ',' attr_list
#                   | attribute_name fixed_array_size ',' attr_list
# (65b) attribute_name ::= IDENTIFIER
def GetAttrList(deep,ctr):

    rt = ['attr%d' % ctr]
    if not deep:
        return rt

    rt.append('attr%dfas [3]' % ctr)
    rt.append('attr%dlist0, attr%dlist1' % (ctr,ctr))

    rt.append('attr%dlist2 [3], attr%dlist3' % (ctr,ctr))
    rt.append('attr%dlist4 [3], attr%dlist5 [3]' % (ctr,ctr))
    return rt

# (65c) domain_type ::= simple_type_spec
#                     | struct_type
#                     | enum_type
def GetDomainType(deep):

    rt = GetSimpleTypeSpec(deep)
    if not deep:
        return [rt[0]]
    rt.extend(GetStructType())
    rt.extend(GetEnumType())
    return rt
              

### (65d) rel_dcl ::= "relationship" target_of_path IDENTIFIER "inverse" inverse_traversal_path
##def ProcessRelDcl(db, rel_dcl, parent):
##    #2 cases?
##    #1 this is the first side of the relationship: inwhich we store in the list
##    #2 this is the second side, inwhich we get the inverse from the list

##    ident = rel_dcl[2]

##    #Get the target (it is a type)
##    type = ProcessTargetOfPath(db, rel_dcl[1], parent)
##    if type == None:
##        raise "Unknown type for relationship %s" % ident

##    target, inverse_name = ProcessInverseTraversalPath(db, rel_dcl[4], parent)
##    if target == None:
##        raise "No target for relationship %s" % ident

##    #We have to lose the type def on relationships.  We just gotta
##    uTarget = OdlUtil.NormalizeTypeDefinition(target)

##    #See if the inverse rel exists
##    global g_relationships
##    if g_relationships.has_key((uTarget,inverse_name)):
##        #Case 2 the other side was already defined
##        inverse_type = g_relationships[(uTarget, inverse_name)]
##        parent.add_relationship(ident, type, uTarget, inverse_name, inverse_type)
##        del g_relationships[(uTarget, inverse_name)]
##    else:
##        #Case1 the other side was not declared.
##        #Set up to be called later
##        g_relationships[(parent, ident)] = type

### (65e) target_of_path ::= scoped_name
###                        | coll_spec '<' scoped_name '>'
##def ProcessTargetOfPath(db, target_of_path, parent):
##    if target_of_path.get(1):
##        # This is a collection
##        type_spec = ProcessCollSpec(db, target_of_path[0], parent)
##        subtype = ProcessScopedName(db, target_of_path[2], parent)
##        type_spec.form_subtype(subtype)
##        return type_spec
##    else:
##        return ProcessScopedName(db, target_of_path[0], parent)

### (65f) inverse_traversal_path ::= scoped_name "::" IDENTIFIER
##def ProcessInverseTraversalPath(db, inverse_traversal_path, path):
##    target = ProcessScopedName(db, inverse_traversal_path[0], path)
##    return target, inverse_traversal_path[2]


# (66) except_dcl ::= "exception" IDENTIFIER '{' '}'
#                   | "exception" IDENTIFIER '{' member_list '}'
def GetExceptDcl(deep,indent):

    rt = [indent + "exception %%IDENTIFIER%% {}"]
    if deep:
        for m in GetMemberList():
            rt.append("exception %%%%IDENTIFIER%%%% { %s } " % m)
    
    return rt


### (67) op_dcl ::= op_type_spec IDENTIFIER parameter_dcls
###               | op_attribute op_type_spec IDENTIFIER parameter_dcls
###               | op_type_spec IDENTIFIER parameter_dcls raises_expr
###               | op_attribute op_type_spec IDENTIFIER parameter_dcls raises_expr
###               | op_type_spec IDENTIFIER parameter_dcls context_expr
###               | op_attribute op_type_spec IDENTIFIER parameter_dcls context_expr
###               | op_type_spec IDENTIFIER parameter_dcls raises_expr context_expr
###               | op_attribute op_type_spec IDENTIFIER parameter_dcls raises_expr context_expr
##def ProcessOpDcl(db,opdcl,parent):

##    ctr = 0
##    if opdcl[0]['TYPE'] == 'OP_ATTRIBUTE':
##        oneway = 1
##        ctr = 1
##    else:
##        oneway = 0

##    ots = ProcessOpTypeSpec(db,opdcl[ctr],parent)
##    ctr = ctr + 1
##    name = opdcl[ctr]
##    ctr = ctr + 1
##    params = ProcessParameterDcls(db,opdcl[ctr],parent)
##    ctr = ctr + 1
##    if opdcl.get(ctr) and opdcl[ctr]['TYPE'] == 'RAISES_EXPR':
##        exceptions = ProcessRaisesExpr(db,opdcl[ctr],parent)
##        ctr = ctr + 1
##    else:
##        exceptions = []
    
##    if opdcl.get(ctr) and opdcl[ctr]['TYPE'] == 'CONTEXT_EXPR':
##        raise FtodsUnsupportedError("Context Expression On Operations")

##    op = Operation.Operation(db,None)
##    op.name = name
##    if not oneway:
##        op.form_result(ots)
##    for p in params:
##        op.add_signature(p)

##    for e in exceptions:
##        op.add_exceptions(e)

##    return op

    
### (68) op_attribute ::= "oneway"

### (69) op_type_spec ::= simple_type_spec
###                     | "void"

##def ProcessOpTypeSpec(db,ots,parent):
##    if ots[0] == 'void':
##        return db.schema().resolve(PrimitiveKind.pk_void._n)
##    else:
##        return ProcessSimpleTypeSpec(db,ots[0],parent)

### (70) parameter_dcls ::= '(' ')'
###                       | '(' param_dcl_list ')'

##def ProcessParameterDcls(db,pdcls,parent):
##    if pdcls.get(2):
##        return ProcessParamDclList(db,pdcls[1],parent)
##    return []

### (70a) param_dcl_list ::= param_dcl
###                        | param_dcl ',' param_dcl_list
##def ProcessParamDclList(db,pdcll,parent):
##    l = [ProcessParamDcl(db,pdcll[0],parent)]
##    if pdcll.get(1):
##        l.extend(ProcessParamDclList(db,pdcll[2],parent))
##    return l
    
    
### (71) param_dcl ::= param_attribute simple_type_spec declarator
##def ProcessParamDcl(db,pdcl,parent):
##    attr = ProcessParamAttribute(db,pdcl[0],parent)
##    sts = ProcessSimpleTypeSpec(db,pdcl[1],parent)
##    decl = ProcessDeclarator(db,pdcl[2],parent)

##    p = Parameter.Parameter(db,None,parameter_mode = attr)
##    p.name = decl
##    p.form_type(sts)
##    return p
    

### (72) param_attribute ::= "in" | "out" | "inout"
##def ProcessParamAttribute(db,pa,parent):
##    if pa[0] == 'in':
##        return Direction.mode_in
##    elif pa[0] == 'out':
##        return Direction.mode_out
##    return Direction.mode_inout

### (73) raises_expr ::= "raises" '(' scoped_name_list ')'
##def ProcessRaisesExpr(db,raises,parent):
##    return ProcessScopedNameList(db,raises[2],parent)

### (73a) scoped_name_list ::= scoped_name
###                          | scoped_name ',' scoped_name_list
##def ProcessScopedNameList(db,snl,parent):
##    res = [ProcessScopedName(db,snl[0],parent)]
##    if snl.get(1):
##        res.extend(ProcessScopedNameList(db,snl[2],parent))
##    return res
                  
           
### (74) context_expr ::= "context" '(' string_literal_list ')'

### (74a) string_literal_list ::= string_literal
###                             | string_literal ',' string_literal_list

##from Ft.Ods.MetaData import Scope
##from Ft.Ods import Database
##def ResolveName(db, name, scope):
##    #A name can reference something in 2 places:
##    #1 the scope of  scope's parent
##    #2 the root module ODLMetaObjects
##    noGlob = 0
##    if name[0] == ':':
##        name = name[2:]
##        noGlob = 1

##    if not noGlob:
##        #First try parent's current scope
##        p = scope.parent()
##        if p:
##            try:
##                n = p.resolve(name)
##                return n
##            except Scope.Scope.NameNotFound, e:
##                pass
##        #try at current scope
##        try:
##            n = scope.resolve(name)
##            return n
##        except Scope.Scope.NameNotFound, e:
##            pass

##    #Now try at the ODLMetaObject module.
##    try:
##        n = db.schema().resolve("ODLMetaObjects").resolve(name)
##        return n
##    except Scope.Scope.NameNotFound, e:
##        pass

##    #Now try at the Repository module.
##    try:
##        n = db.schema().resolve(name)
##        return n
##    except Scope.Scope.NameNotFound, e:
##        pass

##    return None

    
    





if __name__ == '__main__':
    print GenerateMasterODLFile()



