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.