Go to the first, previous, next, last section, table of contents.

# Syntactic Symbols

The complete list of recognized syntactic symbols is described in the `c-offsets-alist` variable. This chapter will provide some examples to help clarify these symbols.

Most syntactic symbol names follow a general naming convention. When a line begins with an open or close brace, the syntactic symbol will contain the suffix `-open` or `-close` respectively.

Usually, a distinction is made between the first line that introduces a construct and lines that continue a construct, and the syntactic symbols that represent these lines will contain the suffix `-intro` or `-cont` respectively. As a sub-classification of this scheme, a line which is the first of a particular brace block construct will contain the suffix `-block-intro`.

Let's look at some examples to understand how this works. Remember that you can check the syntax of any line by using `C-c C-s`.

      1: void
      2: swap( int& a, int& b )
      3: {
      4:     int tmp = a;
      5:     a = b;
      6:     b = tmp;
      7:     int ignored =
      8:         a + b;
      9: }

Line 1 shows a `topmost-intro` since it is the first line that introduces a top-level construct. Line 2 is a continuation of the top-level construct introduction so it has the syntax `topmost-intro-cont`. Line 3 shows a `defun-open` since it is the brace that opens a top-level function definition. Line 9 is a `defun-close` since it contains the brace that closes the top-level function definition. Line 4 is a `defun-block-intro`, i.e. it is the first line of a brace-block, which happens to be enclosed in a top-level function definition.

Lines 5, 6, and 7 are all given `statement` syntax since there isn't much special about them. Note however that line 8 is given `statement-cont` syntax since it continues the statement begun on the previous line.

Here's another example, which illustrates some C++ class syntactic symbols:

       1: class Bass
       2:     : public Guitar,
       3:       public Amplifiable
       4: {
       5: public:
       6:     Bass()
       7:         : eString( new BassString( 0.105 )),
       8:           aString( new BassString( 0.085 )),
       9:           dString( new BassString( 0.065 )),
      10:           gString( new BassString( 0.045 ))
      11:     {
      12:         eString.tune( 'E' );
      13:         aString.tune( 'A' );
      14:         dString.tune( 'D' );
      15:         gString.tune( 'G' );
      16:     }
      17: }

As in the previous example, line 1 has the `topmost-intro` syntax. Here however, the brace that opens a C++ class definition on line 4 is assigned the `class-open` syntax. Note that in C++, structs and unions are essentially equivalent syntactically (and are very similar semantically), so replacing the `class` keyword in the example above with `struct` or `union` would still result in a syntax of `class-open` for line 4 (13). Similarly, line 17 is assigned `class-close` syntax.

Line 2 introduces the inheritance list for the class so it is assigned the `inher-intro` syntax, and line 3, which continues the inheritance list is given `inher-cont` syntax.

Things get interesting at line 5. The primary syntactic symbol for this line is `access-label` since this a label keyword that specifies access protection in C++. However, this line actually shows two syntactic symbols when you hit `C-c C-s`. This is because it is also a top-level construct inside a class definition. Thus the other syntactic symbol assigned to this line is `inclass`. Similarly, line 6 is given both `inclass` and `topmost-intro` syntax.

Line 7 introduces a C++ member initialization list and as such is given `member-init-intro` syntax. Note that in this case it is not assigned `inclass` since this is not considered a top-level construct. Lines 8 through 10 are all assigned `member-init-cont` since they continue the member initialization list started on line 7.

Line 11 is assigned `inline-open` because it opens an in-class C++ inline method definition. This is distinct from, but related to, the C++ notion of an inline function in that its definition occurs inside an enclosing class definition, which in C++ implies that the function should be inlined. For example, if the definition of the `Bass` constructor appeared outside the class definition, line 11 would be given the `defun-open` syntax, even if the keyword `inline` appeared before the method name, as in:

    class Bass
        : public Guitar,
          public Amplifiable
    {
    public:
        Bass();
    }

    inline
    Bass::Bass()
        : eString( new BassString( 0.105 )),
          aString( new BassString( 0.085 )),
          dString( new BassString( 0.065 )),
          gString( new BassString( 0.045 ))
    {
        eString.tune( 'E' );
        aString.tune( 'A' );
        dString.tune( 'D' );
        gString.tune( 'G' );
    }

Similarly, line 16 is given `inline-close` syntax.

As in the first example above, line 12 is given `defun-block-open` syntax and lines 13 through 15 are all given `statement` syntax.

Here is another (totally contrived) example which illustrates how syntax is assigned to various conditional constructs:

       1: void spam( int index )
       2: {
       3:     for( int i=0; i<index; i++ )
       4:     {
       5:         if( i == 10 )
       6:         {
       7:             do_something_special();
       8:         }
       9:         else
      10:             do_something( i );
      11:     }
      12:     do {
      13:         another_thing( i-- );
      14:     }
      15:     while( i > 0 );
      16: }

Only the lines that illustrate new syntactic symbols will be discussed.

Line 4 has a brace which opens a conditional's substatement block. It is thus assigned `substatement-open` syntax, and since line 5 is the first line in the substatement block, it is assigned `substatement-block-intro` syntax. Lines 6 and 7 are assigned similar syntax. Line 8 contains the brace that closes the inner substatement block. It is given the generic syntax `block-close`, as are lines 11 and 14.

Line 9 is a little different -- since it contains the keyword `else` matching the `if` statement introduced on line 5; it is given the `else-clause` syntax. Note also that line 10 is slightly different too. Because `else` is considered a conditional introducing keyword (14), and because the following substatement is not a brace block, line 10 is assigned the `substatement` syntax.

One other difference is seen on line 15. The `while` construct that closes a `do` conditional is given the special syntax `do-while-closure` if it appears on a line by itself. Note that if the `while` appeared on the same line as the preceding close brace, that line would have been assigned `block-close` syntax instead.

Switch statements have their own set of syntactic symbols. Here's an example:

       1: void spam( enum Ingredient i )
       2: {
       3:     switch( i ) {
       4:     case Ham:
       5:         be_a_pig();
       6:         break;
       7:     case Salt:
       8:         drink_some_water();
       9:         break;
      10:     default:
      11:         {
      12:             what_is_it();
      13:             break;
      14:         }
      15:     }
      14: }

Here, lines 4, 7, and 10 are all assigned `case-label` syntax, while lines 5 and 8 are assigned `statement-case-intro`. Line 11 is treated slightly differently since it contains a brace that opens a block -- it is given `statement-case-open` syntax.

There are a set of syntactic symbols that are used to recognize constructs inside of brace lists. A brace list is defined as an `enum` or aggregate initializer list, such as might statically initialize an array of structs. For example:

      1: static char* ingredients[] =
      2: {
      3:     "Ham",
      4:     "Salt",
      5:     NULL
      6: }

Following convention, line 2 in this example is assigned `brace-list-open` syntax, and line 3 is assigned `brace-list-intro` syntax. Likewise, line 6 is assigned `brace-list-close` syntax. Lines 4 and 5 however, are assigned `brace-list-entry` syntax, as would all subsequent lines in this initializer list.

A number of syntactic symbols are associated with parenthesis lists, a.k.a argument lists, as found in function declarations and function calls. This example illustrates these:

       1: void a_function( int line1,
       2:                  int line2 );
       3:
       4: void a_longer_function(
       5:     int line1,
       6:     int line2
       7:     );
       8:
       9: void call_them( int line1, int line2 )
      10: {
      11:     a_function(
      12:         line1,
      13:         line2
      14:         );
      15:
      16:     a_longer_function( line1,
      17:                        line2 );
      18: }

Lines 5 and 12 are assigned `arglist-intro` syntax since they are the first line following the open parenthesis, and lines 7 and 14 are assigned `arglist-close` syntax since they contain the parenthesis that closes the argument list.

The other lines with relevant syntactic symbols include lines 2 and 17 which are assigned `arglist-cont-nonempty` syntax. What this means is that they continue an argument list, but that the line containing the parenthesis that opens the list is non-empty following the open parenthesis. Contrast this against lines 6 and 13 which are assigned `arglist-cont` syntax. This is because the parenthesis that opens their argument lists is the last character on that line (15).

Note that there is no `arglist-open` syntax. This is because any parenthesis that opens an argument list, appearing on a separate line, is assigned the `statement-cont` syntax instead.

A few miscellaneous syntactic symbols that haven't been previously covered are illustrated by this example:

       1: void Bass::play( int volume )
       2: const
       3: {
       4:     /* this line starts a multi-line
       5:      * comment.  This line should get `c' syntax */
       6:
       7:     char* a_long_multiline_string = "This line starts a multi-line \
       8: string.  This line should get `string' syntax.";
       9:
      10:   note:
      11:     {
      12: #ifdef LOCK
      13:         Lock acquire();
      14: #endif // LOCK
      15:         slap_pop();
      16:         cout << "I played "
      17:              << "a note\n";
      18:     }
      19: }

The lines to note in this example include:

- line 2 which is assigned the `ansi-funcdecl-cont` syntax;
- line 4 which is assigned both `defun-block-intro` and `comment-intro` syntax (16);
- line 5 which is assigned `c` syntax;
- line 6 which, even though it contains nothing but whitespace, is assigned `defun-block-intro`. Note that the appearance of the comment on lines 4 and 5 do not cause line 6 to be assigned `statement` syntax because comments are considered to be syntactic whitespace, which are essentially ignored when analyzing code;
- line 8 which is assigned `string` syntax;
- line 10 which is assigned `label` syntax;
- line 11 which is assigned `block-open` syntax;
- lines 12 and 14 which are assigned `cpp-macro` syntax;
- line 17 which is assigned `stream-op` syntax (17).

In Objective-C buffers, there are three additional syntactic symbols assigned to various message calling constructs. Here's an example illustrating these:

      1: - (void)setDelegate:anObject
      2:           withStuff:stuff
      3: {
      4:     [delegate masterWillRebind:self
      5:               toDelegate:anObject
      6:               withExtraStuff:stuff];
      7: }

Here, line 1 is assigned `objc-method-intro` syntax, and line 2 is assigned `objc-method-args-cont` syntax. Lines 5 and 6 are both assigned `objc-method-call-cont` syntax.

Other syntactic symbols may be recognized by `cc-mode`, but these are more obscure and so I haven't included examples of them. These include: `knr-argdecl-intro`, `knr-argdecl`, and the `friend` modifier.

Go to the first, previous, next, last section, table of contents.