Warm tip: This article is reproduced from serverfault.com, please click

C++ import-keyword, module-keyword and, export-keyword

发布于 2020-11-28 06:25:25

Introduction

In the C++ draft standard in:

There are mentions of these terms import-keyword, module-keyword and, export-keyword.

Confusion

In the grammer section I'm not really sure how its possible that as per A.1 General

"the grammar described here accepts a superset of valid C++ constructs."

It seems like the grammer for these isn't defined in this appendix.

Question

It may be addressed here:

4 In all three forms of pp-import, the import and export (if it exists) preprocessing tokens are replaced by the import-keyword and export-keyword preprocessing tokens respectively.

But I don't really know what that means in terms of grammer... What does that mean?

Related

Some of the relevant grammer is here (hopefully I can help somebody get the nessary information without having to go all over the standard).

 preprocessing-token:
    header-name
    import-keyword
    module-keyword
    export-keyword
    identifier
    pp-number
    character-literal
    user-defined-character-literal
    string-literal
    user-defined-string-literal
    preprocessing-op-or-punc
    each non-whitespace character that cannot be one of the above 
 keyword:
    any identifier listed in Table 5
    import-keyword
    module-keyword
    export-keyword 
module-import-declaration:
    import-keyword module-name attribute-specifier-seqopt ;
    import-keyword module-partition attribute-specifier-seqopt ;
    import-keyword header-name attribute-specifier-seqopt ;
control-line:
    # include pp-tokens new-line pp-import
    # define identifier replacement-list new-line
    # define identifier lparen identifier-listopt ) replacement-list new-line
    # define identifier lparen ... ) replacement-list new-line
pp-import:
    exportopt import header-name pp-tokensopt ; new-line
    exportopt import header-name-tokens pp-tokensopt ; new-line
    exportopt import pp-tokens ; new-line
Questioner
David Ledger
Viewed
0
Nicol Bolas 2020-11-28 22:49:54

You have all of the pieces there; you're just not looking at it correctly. Probably because of the term "keyword".

So let's start with pp-import is not part of the grammar. This is not really C++ grammar per-se; it starts with "pp" because it's part of the preprocessor. The preprocessor is a thing that happens before the rest of the C++ grammar is applied to the text.

So pp-import is a preprocessor directive, much like a macro definition (as is module-file and its derivatives). Preprocessor directives usually govern the sequence of tokens generated for C++, and the module preprocessor directives are no different.

Section [cpp.import] defines what pp-import looks like and what tokens it generates. So before preprocessing, you would have a sequence of text that looks like this: import "some_module.name". When the preprocessor recognizes this text as pp-import, it will then generate the token sequence, import-keyword "some_module.name".

import-keyword is the name of a specific token, just like if or struct. But unlike most such tokens, this token does not have a textual analog. That is, if is the keyword generated when the compiler sees the text "if" in your code. That's not the case for import-keyword. This token is only generated by the C++ preprocessor, and only from pp-import preprocessing directives.

So the preprocessing directive pp-import basically replaces the "import" text with the import-keyword token. And the main C++ grammar recognizes the import-keyword token, even though you can't write the text for that token.

But... why? Why all of this rigamarole of preprocessing directives and keywords that you can't type? Why not just make import and module work like any other keyword?

There are two reasons.

  1. The words "module" and "import" are very frequently used as identifiers. By having the preprocessor convert module headers and import directives to use the non-human-writable tokens module-keyword and import-keyword, any uses of "module" and "import" outside of those directives allow them to just be identifiers. And thus, C++20 doesn't break tons and tons of code.

    Or would you rather have to write co_module ;)

  2. In a modular build system, you need a way to look at a file and quickly know what module it defines and which ones it imports. And you would rather not have to write a whole C++ parser just to do that, let alone take the time to run it on the entire text (which will be difficult, since you'll need to import all of those modules to make sense of it). By making module statements preprocessor directives first instead of just regular C++ grammar, you can simply use a C++ preprocessor to extract them all.