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:
ansi-funcdecl-cont syntax;
defun-block-intro and
comment-intro syntax (16);
c syntax;
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;
string syntax;
label syntax;
block-open syntax;
cpp-macro syntax;
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.