An action is enclosed in a double-</double-> pair. << >> and is placed after the regular expression describing the token:
#token K_BEGIN "begin" << printf("Action.\n"); >>
Actions can contain any C or C++ source code that can be placed directly into a C or C++ source file, and may contain multiple lines of text:
#token NL "\n"
<< printf("Found a newline.\n");
zzline++;
>>
In the previous example, zzline was used to count the number of newlines. This variable is defined if the following line is included in a top-level action which precedes the lexclass:
#define ZZCOL
You can add your own variables by declaring them in a top-level action preceding the lexclass:
<<
int numtokens = 0;
>>
#lexclass START
#token WS "[\ \t]*"
#token ALLELSE "~[\ \t]*" << numtokens++; >>
#token ENDOFFILE "@"
<<
printf ( "Total tokens: %d\n", numtokens );
>>
There is a special top-level action called the "header", which is included in each of the C files generated during the building of a PCCTS based compiler. Because of this, you should NOT put variable declarations which will allocate space in the header action. You should, however, put extern declarations for variables, typedefs, and struct descriptions which are used throughout the compiler in the header action. Allocating declarations for these items should then be placed in a non-header action:
#header
<<
#define ZZCOL
extern int numtokens;
>>
<<
int numtokens = 0;
main (int argc, char *argv[])
{
ANTLR (prog(), stdin);
return(0);
}
>>
#lexclass START
#token WS "[\ \t]*"
#token ALLELSE "~[\ \t]*" << numtokens++; >>
#token ENDOFFILE "@"
<<
printf ( "Total tokens: %d\n", numtokens );
>>
Of course, placing an "extern" declaration in a file doesn't hurt, so you may
want to place extern declarations in the header just to be sure the item is
declared everywhere it is needed.
Here are a few excerpts from table 16 in Terence Parr's Book Language Translation Using PCCTS and C++:
int zzline
#define ZZCOL
to use zzline.
zzmore (void)
zzskip (void)
zzadvance (void)
int zzchar
char *zzlextext
zzmore()
and
zzskip()
.
ZZCOL
zzmode (int m)
#lexclass
directive.
void (*zzerr) (char *)
zzerr
to point to a routine of your choosing
to handle lexical errors (e.g., when the input does not match any
regular expression).