C::Tokenize - reduce a C file to a series of tokens
# Remove all C preprocessor instructions from a C program: my $c = <<EOF; #define X Y #ifdef X int X; #endif EOF use C::Tokenize '$cpp_re'; $c =~ s/$cpp_re//g; print "$c\n";
produces output
int X;
(This example is included as synopsis-cpp.pl in the distribution.)
# Print all the comments in a C program: my $c = <<EOF; /* This is the main program. */ int main () { int i; /* Increment i by 1. */ i++; // Now exit with zero status. return 0; } EOF use C::Tokenize '$comment_re'; while ($c =~ /($comment_re)/g) { print "$1\n"; }
/* This is the main program. */ /* Increment i by 1. */ // Now exit with zero status.
(This example is included as synopsis-comment.pl in the distribution.)
This documents version 0.18 of C::Tokenize corresponding to git commit cac6e4c67b2ddcd7b3fb030ebb367f124a33057c released on Thu Feb 22 13:47:15 2018 +0900.
This module provides a tokenizer, "tokenize", which breaks C source code into its smallest meaningful components, and the regexes which match each of these components. For example, "$comment_re" matches a C comment.
As well as components of C, it supplies regexes for local include statements, "$include_local", and C variables, "$cvar_re", as well as extra functions, like "decomment" to remove the comment syntax of traditional C comments, and "strip_comments", which removes all comments from a C program.
The following regular expressions can be imported from this module using, for example,
use C::Tokenize '$cpp_re'
to import $cpp_re.
$cpp_re
The following regular expressions do not capture, except where noted. To capture, add your own parentheses around the regular expression.
Match /* */ comments.
/* */
Match // comments.
//
Match both /* */ and // comments.
See also "decomment" for converting a comment to a string, and "strip_comments" for removing all comments from a program.
Match all C preprocessor instructions, such as #define, #include, #endif, and so on. A multiline preprocessor instruction is matched as #one piece.
Match an include statement which uses double quotes, like #include "some.c".
#include "some.c"
This captures the entire statement in $1 and the file name in $2.
$1
$2
This was added in version 0.10 of C::Tokenize.
Match any include statement, like #include <stdio.h>.
#include <stdio.h>
use C::Tokenize '$include'; my $c = <<EOF; #include <this.h> #include "that.h" EOF while ($c =~ /$include/g) { print "Include statement $1 includes file $2.\n"; }
Include statement #include <this.h> includes file this.h. Include statement #include "that.h" includes file that.h.
(This example is included as includes.pl in the distribution.)
This was added in version 0.12 of C::Tokenize.
Match an octal number, which is a number consisting of the digits 0 to 7 only which begins with a leading zero.
Match a hexadecimal number, a number with digits 0 to 9 and letters A to F, case insensitive, with a leading 0x or 0X and an optional trailing L or l for long.
Match a decimal number, either integer or floating point.
Match any number, either integer, floating point, hexadecimal, or octal.
Match a character constant, such as 'a' or '\-'.
'a'
'\-'
Match a single C string constant such as "this".
"this"
Match a full-blown C string constant, including compound strings "like" "this".
"like" "this"
Match an operator such as + or --.
+
--
Match a word, such as a function or variable name or a keyword of the language. Use "$reserved_re" to match only reserved words.
Match non-operator syntactic characters such as { or [.
{
[
Match a C reserved word like auto or goto. Use "$word_re" to match non-reserved words.
auto
goto
Match a C variable, for example anything which may be an lvalue or a function argument. It does not capture the result.
use C::Tokenize '$cvar_re'; my $c = 'func (x->y, & z, ** a, & q);'; while ($c =~ /[,\(]\s*($cvar_re)/g) { print "$1 is a C variable.\n"; }
x->y is a C variable. & z is a C variable. ** a is a C variable. & q is a C variable.
(This example is included as cvar.pl in the distribution.)
Because in theory this can contain very complex things, this regex is somewhat heuristic and there are edge cases where it is known to fail. See t/cvar_re.t in the distribution for examples.
This was added in version 0.11 of C::Tokenize.
The exported variable @fields contains a list of all the fields which are extracted by "tokenize".
my $out = decomment ('/* comment */'); # $out = " comment ";
Remove the traditional C comment marks /* and */ from the beginning and end of a string, leaving only the comment contents. The string has to begin and end with comment marks.
/*
*/
my $tokens = tokenize ($text);
Convert the C program code $text into a series of tokens. The return value is an array reference which contains hash references. Each hash reference corresponds to one token in the C text. Each token contains the following keys:
$text
Any whitespace which comes before the token (called "leading whitespace").
The type of the token, which may be
A comment, like
/* This */
or
// this.
A C preprocessor instruction like
#define THIS 1
#include "That.h".
A character constant, like '\0' or 'a'.
'\0'
A piece of C "grammar", like { or ] or ->.
]
->
A number such as 42,
42
A word, which may be a variable name or a function.
A string, like "this", or even "like" "this".
A C reserved word, like auto or goto.
All of the fields which may be captured are available in the variable "@fields" which can be exported from the module:
use C::Tokenize '@fields';
The value of the type. For example, if $token->{name} equals 'comment', then the value of the type is in $token->{comment}.
$token->{name}
$token->{comment}
if ($token->{name} eq 'string') { my $c_string = $token->{string}; }
The line number of the C file where the token occured. For a multi-line comment or preprocessor instruction, the line number refers to the final line.
my $no_comment = strip_comments ($c);
This removes all comments from its input while preserving line breaks.
use C::Tokenize 'strip_comments'; my $c = <<EOF; char * not_comment = "/* This is not a comment */"; int/* The X coordinate. */x; /* The Y coordinate. See https://en.wikipedia.org/wiki/Cartesian_coordinates. */ int y; // The Z coordinate. int z; EOF print strip_comments ($c);
char * not_comment = "/* This is not a comment */"; int x; int y; int z;
(This example is included as strip-comments.pl in the distribution.)
This function was moved to this module from XS::Check in version 0.14.
This function can also be used to strip C-style comments from JSON without removing string contents:
use C::Tokenize 'strip_comments'; my $json =<<EOF; { /* Comment comment comment */ "/* not comment */":"/* not comment */", "value":["//not comment"] // Comment } EOF print strip_comments ($json);
{ "/* not comment */":"/* not comment */", "value":["//not comment"] }
(This example is included as strip-json.pl in the distribution.)
Nothing is exported by default.
use C::Tokenize ':all';
exports all the regular expressions and functions from the module, and also "@fields".
The regular expressions contained in this module are shown at this web page.
This example of use of this module demonstrates using C::Tokenize (version 0.12) to remove unnecessary header inclusions from C files.
There is a C to HTML converter in the examples subdirectory of the distribution called c2html.pl.
No handling of trigraphs.
This is issue 4.
This module uses named captures in regular expressions, so it requires Perl 5.10 or more.
The line numbers provided by "tokenize" do not respect C line directives.
This is issue 11.
The module has been used somewhat, but the included tests do not exercise many of the features of C.
The C language does not impose a requirement that included file names end in .h. You can include a file with any name. However, the regexes "$include" and "$include_local" insist on a final .h.
See the discussion under "$cvar_re".
Ben Bullock, <bkb@cpan.org>
This package and associated files are copyright (C) 2012-2018 Ben Bullock.
You can use, copy, modify and redistribute this package and associated files under the Perl Artistic Licence or the GNU General Public Licence.
To install C::Tokenize, copy and paste the appropriate command in to your terminal.
cpanm
cpanm C::Tokenize
CPAN shell
perl -MCPAN -e shell install C::Tokenize
For more information on module installation, please visit the detailed CPAN module installation guide.