Re: C++ Grammar - Update

Michael Spencer <michael_spencer@btclick.com>
13 May 2001 01:14:02 -0400

          From comp.compilers

Related articles
C++ Grammar - Update mike@dimmick.demon.co.uk (Mike Dimmick) (2001-04-26)
Re: C++ Grammar - Update loewis@informatik.hu-berlin.de (Martin von Loewis) (2001-04-30)
Re: C++ Grammar - Update idbaxter@semdesigns.com (Ira D. Baxter) (2001-05-03)
Re: C++ Grammar - Update mike@dimmick.demon.co.uk (Mike Dimmick) (2001-05-03)
Re: C++ Grammar - Update gahide@lil.univ-littoral.fr (Patrice Gahide) (2001-05-03)
Re: C++ Grammar - Update michael_spencer@btclick.com (Michael Spencer) (2001-05-07)
Re: C++ Grammar - Update michael_spencer@btclick.com (Michael Spencer) (2001-05-13)
Re: C++ Grammar - Update loewis@informatik.hu-berlin.de (Martin von Loewis) (2001-05-13)
| List of all articles for this month |
From: Michael Spencer <michael_spencer@btclick.com>
Newsgroups: comp.compilers,comp.compilers.tools.pccts
Date: 13 May 2001 01:14:02 -0400
Organization: Compilers Central
References: 01-04-141 01-04-155 01-05-008
Keywords: C++, parse
Posted-Date: 13 May 2001 01:14:02 EDT

Mike Dimmick wrote:
> Therefore, the two declarations
>
> int i = 0;
>
> virtual int i() = 0;
>
> conflict, as for the first we get
>
> decl-specifiers = 'int'
> declarator = 'i'
> initialiser(constant-expression) = '0'
>
> and the second
>
> decl-specifiers = 'virtual int'
> declarator = 'i()'
> initialiser(pure-specifier) = '0'
>
> But the parser can't tell, without using context information, that a
> virtual function is being declared. This is because 'virtual' is just
> a decl-specifier, it isn't a different form of declaration in its own
> right. The second could equally be written
>
> int virtual i() = 0;
>
> with the same semantic meaning. Therefore pure-specifier and
> constant-expression conflict, and the only thing to do is to perform
> resolution at a later stage.


One trick you might consider: don't use the virtual specifier to
interpret the '= 0'. Instead, write two forms of a declarator:


    declarator -> object-declarator
    declarator -> function-declarator


Then '= 0' (or '= expr' really) following an object declarator is an
initializer, and '= 0' following a function declarator is a pure
specifier. You can check later that the virtual specifier is used
with the the pure specifier.


This also makes it easy to enforce the declarator rule in function
definitions (from 8.4p1 in the C++ Standard):


    The declarator in a function-definition shall have the form
        D1 ( parameter-declaration-clause ) cv-qualifier-seq-opt exception-specification-opt


Just write your function definition rule with the function declarator.


But the grammar is a bit more complicated. The rules have to be
written so that when object-declarator and function-declarator are
used together no conflicts arise. Here's my very stripped down
version of the grammar (very simple BNF, tokens in upper case):


    # start rule
    start -> dcl


    # declarator (object with initializer, function with pure specifier)
    dcl -> obj-dcl ASGN ZERO
    dcl -> func-dcl ASGN ZERO


    # object declarator
    obj-dcl -> obj-a-dcl


    obj-a-dcl -> ptr-oper obj-a-dcl
    obj-a-dcl -> obj-a-direct-dcl


    obj-b-dcl -> ptr-oper obj-a-dcl
    obj-b-dcl -> obj-b-direct-dcl


    obj-a-direct-dcl -> obj-b-direct-dcl
    obj-a-direct-dcl -> obj-dcl-id


    obj-b-direct-dcl -> obj-b-direct-dcl LPAREN RPAREN
    obj-b-direct-dcl -> obj-a-direct-dcl LBRACK RBRACK
    obj-b-direct-dcl -> LPAREN obj-b-dcl RPAREN


    obj-dcl-id -> obj-id
    obj-dcl-id -> LPAREN obj-dcl-id RPAREN


    # function declarator
    func-dcl -> ptr-oper func-dcl
    func-dcl -> func-a-direct-dcl


    func-a-direct-dcl -> func-b-direct-dcl LPAREN RPAREN
    func-a-direct-dcl -> func-a-direct-dcl LPAREN RPAREN
    func-a-direct-dcl -> func-a-direct-dcl LBRACK RBRACK
    func-a-direct-dcl -> LPAREN func-dcl RPAREN


    func-b-direct-dcl -> obj-dcl-id
    func-b-direct-dcl -> func-dcl-id


    func-dcl-id -> func-id
    func-dcl-id -> LPAREN func-dcl-id RPAREN


    obj-id -> IDENT
    func-id -> OPERATOR


    # pointer operator
    ptr-oper -> TIMES


Here, func-id is just OPERATOR ... this is just a placeholder for
operator and conversion function names, and dtors and ctors. ptr-oper
is also very simplified. And, all non-relevant nonterminals in the
direct declarator I removed.


This grammar is LR(1). 46 states
(http://home.clara.net/mikespencer/dcl_states.txt).


(This grammar also enforces function declarator syntax with function
names.)


Mike
http://www.lazycplusplus.com


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.