⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpp5.y

📁 用于lex和yacc的c++及c语言的文法,可用来构造C++语言的编译器
💻 Y
📖 第 1 页 / 共 5 页
字号:
        declaration_qualifier_list   TYPEDEFname
        | declaration_qualifier_list global_or_scoped_typedefname

        | typedef_type_specifier       storage_class
        | TYPEDEFname                  storage_class
        | global_or_scoped_typedefname storage_class

        | typedef_declaration_specifier declaration_qualifier
        ;

typedef_type_specifier:              /* typedef types */
        type_qualifier_list      TYPEDEFname
        | type_qualifier_list    global_or_scoped_typedefname

        | TYPEDEFname                  type_qualifier
        | global_or_scoped_typedefname type_qualifier

        | typedef_type_specifier type_qualifier
        ;


/*  There  are  really  several distinct sets of storage_classes. The 
sets vary depending on whether the declaration is at file scope, is a 
declaration within a struct/class, is within a function body, or in a 
function declaration/definition (prototype  parameter  declarations).  
They   are   grouped  here  to  simplify  the  grammar,  and  can  be 
semantically checked.  Note that this  approach  tends  to  ease  the 
syntactic restrictions in the grammar slightly, but allows for future 
language  development,  and tends to provide superior diagnostics and 
error recovery (i_e.: a syntax error does not disrupt the parse).


                File    File    Member  Member  Local   Local  Formal
                Var     Funct   Var     Funct   Var     Funct  Params
TYPEDEF         x       x       x       x       x       x
EXTERN          x       x                       x       x
STATIC          x       x       x       x       x
AUTO                                            x              x
REGISTER                                        x              x
FRIEND                                  x
OVERLOAD                x               x               x
INLINE                  x               x               x
VIRTUAL                                 x               x
*/

storage_class:
        EXTERN
        | TYPEDEF
        | STATIC
        | AUTO
        | REGISTER
        | FRIEND   /* C++, not ANSI C */
        | OVERLOAD /* C++, not ANSI C */
        | INLINE   /* C++, not ANSI C */
        | VIRTUAL  /* C++, not ANSI C */
        ;

basic_type_name:
        INT
        | CHAR
        | SHORT
        | LONG
        | FLOAT
        | DOUBLE
        | SIGNED
        | UNSIGNED
        | VOID
        ;

elaborated_type_name_elaboration:
        aggregate_name_elaboration
        | enum_name_elaboration
        ;

elaborated_type_name:
        aggregate_name
        | enum_name
        ;


    /* Since the expression "new type_name" MIGHT use  an  elaborated 
    type  and a derivation, it MIGHT have a ':'.  This fact conflicts 
    with the requirement that a new expression can be placed  between 
    a '?' and a ':' in a conditional expression (at least it confuses 
    LR(1)   parsers).   Hence   the   aggregate_name_elaboration   is 
    responsible for a series of SR conflicts on ':'.*/

    /* The intermediate actions {}  represent  points  at  which  the 
    database  of  typedef  names  must  be  updated  in C++.  This is 
    critical to the lexer, which must begin to tokenize based on this 
    new information. */

aggregate_name_elaboration:
        aggregate_name derivation_opt  '{' member_declaration_list_opt '}'
        | aggregate_key derivation_opt '{' member_declaration_list_opt '}'
        ;


    /* We distinguish between the above, which  support  elaboration, 
    and  this  set  of  productions  so  that  we can provide special 
    declaration specifiers for operator_new_type, and for  conversion 
    functions.  Note that without this restriction a large variety of 
    conflicts  appear  when  processing  operator_new and conversions 
    operators (which can be  followed  by  a  ':'  in  a  ternary  ?: 
    expression) */

    /*  Note that at the end of each of the following rules we should 
    be sure that the tag name is  in,  or  placed  in  the  indicated 
    scope.   If  no  scope  is  specified, then we must add it to our 
    current scope IFF it cannot  be  found  in  an  external  lexical 
    scope. */

aggregate_name:
                             aggregate_key tag_name
        | global_scope scope aggregate_key tag_name
        | global_scope       aggregate_key tag_name
        | scope              aggregate_key tag_name
        ;

derivation_opt:
        /* nothing */
        | ':' derivation_list
        ;

derivation_list:
        parent_class
        | derivation_list ',' parent_class
        ;

parent_class:
                                       global_opt_scope_opt_typedefname
        | VIRTUAL access_specifier_opt global_opt_scope_opt_typedefname
        | access_specifier virtual_opt global_opt_scope_opt_typedefname
        ;

virtual_opt:
        /* nothing */
        | VIRTUAL
        ;

access_specifier_opt:
        /* nothing */
        | access_specifier
        ;

access_specifier:
        PUBLIC
        | PRIVATE
        | PROTECTED
        ;

aggregate_key:
        STRUCT
        | UNION
        | CLASS /* C++, not ANSI C */
        ;


    /* Note that an empty list is ONLY allowed under C++. The grammar 
    can  be modified so that this stands out.  The trick is to define 
    member_declaration_list, and have that referenced for non-trivial 
    lists. */

member_declaration_list_opt:
        /* nothing */
        | member_declaration_list_opt member_declaration
        ;

member_declaration:
        member_declaring_list ';'
        | member_default_declaring_list ';'

        | access_specifier ':'               /* C++, not ANSI C */

        | new_function_definition            /* C++, not ANSI C */
        | constructor_function_in_class      /* C++, not ANSI C */

        | sue_type_specifier             ';' /* C++, not ANSI C */
        | sue_type_specifier_elaboration ';' /* C++, not ANSI C */
        | identifier_declarator          ';' /* C++, not ANSI C
                                                access modification
                                                conversion functions,
                                                unscoped destructors */

        | typedef_declaration_specifier ';' /* friend T */       /* C++, not ANSI C */
        | sue_declaration_specifier ';'     /* friend class C*/  /* C++, not ANSI C */
        ;

member_default_declaring_list:        /* doesn't redeclare typedef*/
        type_qualifier_list
                identifier_declarator member_pure_opt

        | declaration_qualifier_list
                identifier_declarator member_pure_opt /* C++, not ANSI C */

        | member_default_declaring_list ','
                identifier_declarator member_pure_opt

        | type_qualifier_list                bit_field_identifier_declarator
        | declaration_qualifier_list         bit_field_identifier_declarator /* C++, not ANSI C */
        | member_default_declaring_list ','  bit_field_identifier_declarator
        ;


    /* There is a conflict when "struct A" is used as  a  declaration 
    specifier,  and  there  is a chance that a bit field name will be 
    provided.  To fix this syntactically would require distinguishing 
    non_elaborating_declaration_specifiers   the   way   I    handled 
    non_elaborating_type_specifiers.   I   think  this  should  be  a 
    constraint error anyway :-). */

member_declaring_list:        /* Can possibly redeclare typedefs */
        type_specifier                 declarator member_pure_opt
        | basic_type_name              declarator member_pure_opt

        | global_or_scoped_typedefname declarator member_pure_opt
        | member_conflict_declaring_item
        | member_declaring_list ','    declarator member_pure_opt

        | type_specifier                bit_field_declarator
        | basic_type_name               bit_field_declarator
        | TYPEDEFname                   bit_field_declarator
        | global_or_scoped_typedefname  bit_field_declarator
        | declaration_specifier         bit_field_declarator /* constraint violation: storage class used */
        | member_declaring_list ','     bit_field_declarator
        ;


    /* The following conflict with constructors-
      member_conflict_declaring_item:
        TYPEDEFname             declarator member_pure_opt
        | declaration_specifier declarator member_pure_opt /* C++, not ANSI C * /
        ;
    so we inline expand declarator to get the following productions...
    */
member_conflict_declaring_item:
        TYPEDEFname             identifier_declarator            member_pure_opt
        | TYPEDEFname           parameter_typedef_declarator     member_pure_opt
        | TYPEDEFname           simple_paren_typedef_declarator  member_pure_opt

        | declaration_specifier identifier_declarator            member_pure_opt
        | declaration_specifier parameter_typedef_declarator     member_pure_opt
        | declaration_specifier simple_paren_typedef_declarator  member_pure_opt

        | member_conflict_paren_declaring_item
        ;


    /* The following still conflicts with constructors-
      member_conflict_paren_declaring_item:
        TYPEDEFname             paren_typedef_declarator     member_pure_opt
        | declaration_specifier paren_typedef_declarator     member_pure_opt
        ;
    so paren_typedef_declarator is expanded inline to get...*/

member_conflict_paren_declaring_item:
        TYPEDEFname   asterisk_or_ampersand
                '(' simple_paren_typedef_declarator ')' member_pure_opt
        | TYPEDEFname unary_modifier
                '(' simple_paren_typedef_declarator ')' member_pure_opt
        | TYPEDEFname asterisk_or_ampersand
                '(' TYPEDEFname ')'                     member_pure_opt
        | TYPEDEFname unary_modifier
                '(' TYPEDEFname ')'                     member_pure_opt
        | TYPEDEFname asterisk_or_ampersand
                 paren_typedef_declarator               member_pure_opt
        | TYPEDEFname unary_modifier
                 paren_typedef_declarator               member_pure_opt

        | declaration_specifier asterisk_or_ampersand
                '(' simple_paren_typedef_declarator ')' member_pure_opt
        | declaration_specifier unary_modifier
                '(' simple_paren_typedef_declarator ')' member_pure_opt
        | declaration_specifier asterisk_or_ampersand
                '(' TYPEDEFname ')'                     member_pure_opt
        | declaration_specifier unary_modifier
                '(' TYPEDEFname ')'                     member_pure_opt
        | declaration_specifier asterisk_or_ampersand
                paren_typedef_declarator                member_pure_opt
        | declaration_specifier unary_modifier
                paren_typedef_declarator                member_pure_opt

        | member_conflict_paren_postfix_declaring_item
        ;


    /* but we still have the following conflicts with constructors-
   member_conflict_paren_postfix_declaring_item:
      TYPEDEFname             postfix_paren_typedef_declarator member_pure_opt
      | declaration_specifier postfix_paren_typedef_declarator member_pure_opt
      ;
    so we expand paren_postfix_typedef inline and get...*/

member_conflict_paren_postfix_declaring_item:
        TYPEDEFname     '(' paren_typedef_declarator ')'
                                                           member_pure_opt
        | TYPEDEFname   '(' simple_paren_typedef_declarator
                        postfixing_abstract_declarator ')' member_pure_opt
        | TYPEDEFname   '(' TYPEDEFname
                        postfixing_abstract_declarator ')' member_pure_opt
        | TYPEDEFname   '(' paren_typedef_declarator ')'
                        postfixing_abstract_declarator     member_pure_opt

        | declaration_specifier '(' paren_typedef_declarator ')'
                                                           member_pure_opt
        | declaration_specifier '(' simple_paren_typedef_declarator
                        postfixing_abstract_declarator ')' member_pure_opt
        | declaration_specifier '(' TYPEDEFname
                        postfixing_abstract_declarator ')' member_pure_opt
        | declaration_specifier '(' paren_typedef_declarator ')'
                        postfixing_abstract_declarator     member_pure_opt
        ;
    /* ...and we are done.  Now all  the  conflicts  appear  on  ';', 
    which can be semantically evaluated/disambiguated */


member_pure_opt:
        /* nothing */
        | '=' OCTALconstant /* C++, not ANSI C */ /* Pure function*/
        ;


    /*  Note  that  bit  field  names, where redefining TYPEDEFnames, 
    cannot be parenthesized in C++ (due to  ambiguities),  and  hence 
    this  part of the grammar is simpler than ANSI C. :-) The problem 
    occurs because:

         TYPEDEFname ( TYPEDEFname) : .....

    doesn't look like a bit field, rather it looks like a constructor 
    definition! */

bit_field_declarator:
        bit_field_identifier_declarator
        | TYPEDEFname {} ':' constant_expression
        ;


    /* The actions taken in the "{}" above and below are intended  to 
    allow  the  symbol  table  to  be  updated when the declarator is 
    complete.  It is critical for code like:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -