visit
Psyche-C is a C compiler frontend that is designed for the implementation of static analysis tools. It provides a clean separation between syntax and semantics (with algorithmic- and heuristic-based syntax disambiguation), tolerance against #include
failures—which is supported by the type inference of struct
, union
, enum
, and typedef
—, and API inspired by that of the .
Psyche-C’s main use is through a C++ library. Specifically, by any tool that wishes to implement static analysis on C programs. But Psyche-C may as well be used as an ordinary C parser via the cnippet driver. In this little article, I will provide you with a glimpse of the AST () that Psyche-C produces as the result of parsing a C program. But first, a quick illustration on how to invoke cnippet with the cnip
command.
void f()
{
int a
}
int v, f(int d);
int f(int p)
{
if (p == v)
return(p - 1);
return 0;
}
Now, consider the Clang produced AST for that same C program.
What's the difference between the two?
Psyche-C's AST is a bit closer to the grammar of C. For instance, you can't see declarators in Clang's AST, as they are absorbed by their containing declarations.
int v, f(int d);
In Clang's AST, v
is represented by a VarDecl
and f
by a FunctionDecl
; both these nodes inherit from DeclaratorDecl
(i.e., a declaration with a declarator). However, in pedantic terms, that representation isn't quite correct, given that only a single declaration — starting at int
and ending at ;
— exists in that snippet.
In Psyche-C’s AST, a single VariableAndOrFunctionDeclaration
is created (like in Clang, this node inherits from DeclaratorDeclaration
) with two child nodes: an IdentifierDeclarator
, designating object v
of type int
, and a FunctionDeclarator
, designating function f
whose return type is int
. This is a finer-grained representation of the program syntax and one that enables an accurate rewrite of an AST—a characteristic of prime importance for static analysis tools that perform source code refactoring.