idl_parser ::=
        #ignore(C++)
        #continue
        [
                '#' #!ignore ->'\n'
            |
                // à ce niveau, toutes les déclarations sont
                // placées dans la racine
                declaration(this)
        ]*
        #empty
        ;

// la déclaration sera contenue sous le noeud 'parent' passé
// en paramètre
declaration(parent : node::=
        #readIdentifier:sDecl
        declaration<sDecl>(parent)
        ;

declaration<"struct">(parent : node::=
        #continue
        identifier:sName
        => insert parent.structures[sName].name = sName;
        '{'
        [attribute_declaration(parent.structures[sName])]*
        '}'
        ';'
        ;

declaration<"typedef">(parent : node::=
            "sequence"
            '<'
            => local theType;
            type_name(theType)
            '>'
            identifier:sAlias
            ';'
            // arrivé au point-virgule, on est sûr d'avoir atteint la
            // fin de la séquence ;
            // recopie du sous-graphe du type
            => setall parent.sequences[sAlias] = theType;
        |
            ->';'
        ;
declaration<"interface">(parent : node::=
        #continue
        identifier:sName
        => insert parent.interfaces[sName].name = sName;
        // gardons une référence sur l'interface, cela facilitera
        // l'écriture du reste de la règle de production
        => localref interface = parent.interfaces[sName];
        [
            ':' #continue
            identifier:interface.inheritance
        ]?

        '{'
        [member_declaration(interface)]*
        '}'
        ';'
        ;

member_declaration(parent : node::= attribute_declaration(parent) | method_declaration(parent);

attribute_declaration(parent : node::=
        // la variable 'bReadonly' doit être déclarée à l'extérieur des
        // crochets, si l'on désire que sa portée les dépasse, et qu'elle
        // soit visible à la fin de la règle (la dernière ligne)
        => local bReadonly;
        [#readIdentifier:"readonly":bReadonly]?
        => local theType;
        type_name(theType)
        identifier:sName
        ';'
        => insert parent.attributes[sName].name = sName;
        // recopie du sous-graphe du type
        => setall parent.attributes[sName].type = theType;
        => if bReadonly insert parent.attributes[sName].readonly = bReadonly;
        ;

method_declaration(parent : node::=
        => local returnType; // là encore, cette variable doit se déclarer à l'extérieur des crochets
        [type_name(returnType) | #readIdentifier:"void"]
        identifier:sName
        '('
        #continue
        => insert parent.methods[sName].name = sName;
        => localref method = parent.methods[sName];
        // recopie du sous-graphe du type
        => setall method.type = returnType;
        [
            parameter(method)
            [',' #continue parameter(method)]*
        ]?
        ')'
        ';'
        ;

parameter(parent : node::=
        // autre façon de construire le graphe de parsing :
        // on alimente tout d'abord un graphe local puis,
        // si la règle de production s'avère valide, on
        // le recopie dans le graphe de parsing
        => local param;
        #readIdentifier:{"in""inout""out"}:param.mode
        type_name(param.type)
        identifier:param.name
        // on recopie tout le graphe local
        => setall parent.parameters[param.name] = param;
        ;

type_name(theType : node::=
        #readIdentifier:sType
        [
                // est-ce un type de base parmi ceux que l'on veut bien reconnaître ?
                #check(sType in {"boolean""double""long""string"})
                => insert theType = sType;
            |
                // est-ce une interface ?
                #check(this.interfaces.findElement(sType))
                => insert theType = sType;
                => insert theType.is_interface = true;
            |
                // est-ce une structure ?
                #check(this.structures.findElement(sType))
                => insert theType = sType;
                => insert theType.is_structure = true;
            |
                // est-ce une séquence ?
                #check(this.sequences.findElement(sType))
                => {
                    // type faisant l'objet de la séquence, que l'on recopie
                    // dans la description de l'élément
                    setall theType.element = this.sequences[sType];
                    // ce type est une séquence
                    insert theType.is_sequence = true;
                }
        ]

        ;

identifier:value ::=
        #readIdentifier:identifier
        #check(!(identifier in {"abstract""any""attribute""boolean""case""char""component""const""consults",
                         "context""custom""default""double""emits""enum""eventtype""exception""factory",
                         "FALSE""finder""fixed""float""getraises""home""import""in""inout""interface",
                         "local""long""manages""module""multiple""native""Object""octet""oneway""out",
                         "primarykey""private""provides""public""publishes""raises""readonly""sequence",
                         "setraises""short""string""struct""supports""switch""TRUE""truncatable""typedef",
                         "typeid""typeprefix""union""unsigned""uses""ValueBase""valuetype""wchar""wstring"}))
        ;

Generated by CodeWorker v3.8.1 from CWscript2HTML.cwp.