Using the ANTLR3 C Target


Using the ANTLR3 C Target

The ANTLR3 C language target has been designed such that where ever possible it models the Java target. Nevertheless, because Java is an Object Oriented Language, and C is not, there are some subtle differences that you must be aware of.

This documentation is NOT a tutorial on how to use ANTLR, and it is not for beginner C programmers. If you find that you do not follow the documentation too well, you may need to first consult the general ANTLR v3 documentation and most especially, you will find the ANTLR 3 book, The Definitive ANTLR Reference: Building domain-specific languages extremely valuable.

This documentation assumes that you have read enough documentation on ANTLR v3 that you are ready to learn how to use ANTLR generated C recognizers.

Jim Idle |jimi|at|temporal-wave|dott|com   http://www.linkedin.com/in/jimidle - May 2007

Finding Example Grammars

If you are looking for the example projects, visit the downloads section of the main ANTLR page. Half way down the page is the examples tar/zip. Download this and expand it. In there is a subdirectory 'C' with VS2005 projects (also easy to build manually on UNIX).

Building the C Runtime Libraries

The C runtime is generally provided as a source code distribution, and you can either use the standard configure script to build and install the binaries, or, on Windows systems utilize the VS2005 .sln file to build the libraries. The source can be built with earlier versions of the Visual Studio system if required, but at this point in time, no VS2003 .sln is provided. It should not be difficult to create it though, should you need it. The configure and VS2005 .sln allow you to target 32 or 64 bit builds as appropriate and produce archive and shared object/DLL versions of the libraries, which you can then link with as appropriate.

Finding the Source Code

The source code distribution should be available on the main ANTLR 3 download page (navigate from the main www.antlr.org web site). However the the very latest .tgz distribution file is always available from the FishEye source code browser for ANTLR3 using this page: Latest C runtime Distribution.

Building in UNIX Style Environments

The source code should be expanded in a directory of your choice (probably your working directory) using the command:

gzip -dc antlrtgzname.tar.gz | tar xvf -

Or, using gnu tar:

tar xvzf antlrtgzname.tar.gz

Where: antlrtgzname.tar.gz is of course the name of the tar when you downloaded it. You should find a configure script in the sub directory thus created.

The configure script accepts the usual options, such as --prefix= but the default is to build in the source directory and to place libraries in /usr/local/lib and include files (for building your recognizers) in /usr/local/include. There are also a number of antlr specific options, which you may wish to utilize. The command:

./configure --help

Will document the latest incarnations of these options in case this documentation is ever out of date. At this time the options are:

  --enable-debuginfo   Compiles debug info into the library (default no)
  --enable-64bit          Turns on flags that produce 64 bit object code if
                                any are required (default no)

The libraries are generally built for 32 bit systems and without debug information, adding one of the above options will change these defaults.

On some systems, notably AIX, shared libraries have the same suffix as archive libraries. When this is the case the configure script will, by default, build only the shared versions of the libraries. On platforms that do not have conflicting suffixes for shred and archive libraries, both versions of the libraries will be built. You can influence these choices with:

  --enable-shared[=PKGS]  build shared libraries [default=yes]
  --enable-static[=PKGS]    build static libraries [default=yes]

Unless you need 64 bit builds, or a change in library types, you will generally use the configure command without options:

[jimi@localhost dist]$ tar zvxf libantlr3c-3.0.0-rc8.tar.gz
libantlr3c-3.0.0-rc8/
libantlr3c-3.0.0-rc8/antlr3config.h
libantlr3c-3.0.0-rc8/src/
libantlr3c-3.0.0-rc8/src/antlr3stringstream.c
...
libantlr3c-3.0.0-rc8/antlr3config.h.in
[jimi@localhost dist]$ cd libantlr3c-3.0.0-rc [jimi@localhost libantlr3c-3.0.0-rc8]$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for xlc... no
checking for aCC... no
checking for gcc... gcc
...
checking for strdup... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating antlr3config.h
config.status: antlr3config.h is unchanged
config.status: executing depfiles commands

Having configured the library successfully, you need only make it, and install it:

[jimi@localhost libantlr3c-3.0.0-rc8]$ make
make  all-am
make[1]: Entering directory `/home/jimi/antlrsrc/code/antlr/main/runtime/C/dist/libantlr3c-3.0.0-rc8'
/bin/sh ./libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -Iinclude -Iinclude    -O2  -MT antlr3baserecognizer.lo -MD -MP -MF ...
...
gcc  -shared  .libs/antlr3baserecognizer.o .libs/antlr3basetree.o .libs/antlr3basetreeadaptor.o ...
ar cru .libs/libantlr3c.a  antlr3baserecognizer.o antlr3basetree.o antlr3basetreeadaptor.o ...
ranlib .libs/libantlr3c.a
creating libantlr3c.la
(cd .libs && rm -f libantlr3c.la && ln -s ../libantlr3c.la libantlr3c.la)
make[1]: Leaving directory `/home/jimi/antlrsrc/code/antlr/main/runtime/C/dist/libantlr3c-3.0.0-rc8' [jimi@localhost libantlr3c-3.0.0-rc8]$ sudo make install
make[1]: Entering directory `/home/jimi/antlrsrc/code/antlr/main/runtime/C/dist/libantlr3c-3.0.0-rc8'
test -z "/usr/local/lib" || /bin/mkdir -p "/usr/local/lib"
 /bin/sh ./libtool --mode=install /usr/bin/install -c  'libantlr3c.la' '/usr/local/lib/libantlr3c.la'
/usr/bin/install -c .libs/libantlr3c.so /usr/local/lib/libantlr3c.so
/usr/bin/install -c .libs/libantlr3c.lai /usr/local/lib/libantlr3c.la
/usr/bin/install -c .libs/libantlr3c.a /usr/local/lib/libantlr3c.a
...
 /usr/bin/install -c -m 644 'include/antlr3stringstream.h' '/usr/local/include/antlr3stringstream.h'
...
 /usr/bin/install -c -m 644 'antlr3config.h' '/usr/local/include/antlr3config.h'
make[1]: Leaving directory `/home/jimi/antlrsrc/code/antlr/main/runtime/C/dist/libantlr3c-3.0.0-rc8'
[jimi@localhost libantlr3c-3.0.0-rc8]$

You are now ready to generate C recognizers and compile and link them with the ANTLR 3 C Runtime.

Building on Windows Systems

If you are building using Cygwin, or a similar UNIX on Windows System, follow the UNIX instructions above.

If you wish to build the binaries for Windows using Visual Studio 2005, you may either open the C.sln file and select batch Build from the Build menu, select all configurations and press the build button.

If you wish or have a need to build the libraries from the command line, then you can use the following command, (assuming that you are using a Windows command shell configure for access to VS2005 compilers, such as the one that is started from Start->Microsoft Visual Studio 2005->Visual Studio Tools->Visual Studio 2005 Command Prompt.

There appears to be no way to build all targets at once in a batch mode from the command line, so you may build one or all of the following:

C:\antlrsrc\code\antlr\main\runtime\C>DEVENV C.sln /Build ReleaseDLL
C:\antlrsrc\code\antlr\main\runtime\C>DEVENV C.sln /Build Release
C:\antlrsrc\code\antlr\main\runtime\C>DEVENV C.sln /Build DebugDLL
C:\antlrsrc\code\antlr\main\runtime\C>DEVENV C.sln /Build Debug

After the build is complete you will find the .DLL and .LIB files under the directory containing C.sln, in a subdirectory named after the /Build target.

In Release and Debug targets, you will find that there is only a .LIB archive file, which you can link directly into your own projects if you wish to avoid the DLL, in ReleaseDLL and DebugDLL you will find both a .LIB file which you should link your projects with and a DLL. The library and names on Windows are as follows:

ReleaseDLL  ANTLR3C.DLL   ANTLR3C_DLL.LIB
DebugDLL    ANTLR3CD.DLL  ANTLR3CD_DLL.LIB
Release     ANTLR3C.LIB
Debug       ANTLR3CD.LIB

(info) Note that the Visual Studio projects can also build 64 bit libraries and that UNIX 64 bit can be enable with a configure option (see configure --help).

There currently no .msi modules or other installs built for Windows, so you must place the DLLs in a directory referenced by the PATH environment variable and make the include directory available to your project configurations.

Generating C

 Before discussing how we compile or call the generated C code, we need to know how to invoke the C code generator. This is achieved within the grammar file itself, using the language option:

options 
{
    language = C;

    // If generating an AST (output=AST; option) or specifying a tree walker then
    // also add the following line
    //
    ASTLabelType=pANTLR3_BASE_TREE;
    
}

The code generator consists of a single .java file within the standard ANTLR tool jar, and a code generation template, used by the StringTemplate engine, which drives code generation for all language targets. In fact you can make copies of the C.stg and AST.stg templates and make changes to them (though you are encouraged not to, as it is better to provide bug fixes or enhancements which I am happy to receive and will do my best to incorporate.

Visual Studio Rules

If you are working in the Windows environment, with Visual Studio 2005 or later, you may wish to utilize the custom .rules files provided in the C source code distribution. If you are using a pre-built library then you can also download this rule file directly from the FishEye source code browser for ANTLR3. In order to use the .rules files,

When integrating with Makefiles, utilize the -depend option of the Antlr tool, which should tell your Makefile what the grammar files generate.

Building Your Recognizer

Generated Files

The antlr tool jar, run against a grammar file that targets the C language, will generate the following files according to whether your grammar file contains a lexer, parser, combined or treeparser specification. Your grammar file name and the subject of the grammar line in your file are expected to match. Here the generic name G is used:

lexer grammar G;        -> G.c G.h
parser grammar G;       -> G.c G.h
grammar G;              -> GLexer.c GLexer.h GParser.c GParser.h
tree parser grammar G;  -> G.c G.h

The generated .c files reference the .h files using <G.h>, so you must use -I. on your compiler command line (or include the current directory in your include paths in Visual Studio). Additionally, the generated .h files reference <antlr3.h>, so you must use -I/path/to/antlr/include (E.g. -I /usr/local/include) to reference the standard ANTLR include files.

In order to reference the library file at compile time (you can/should only reference one) you need to use the -L/path/to/antlr/lib (E.g. -L /usr/local/lib) on Unix, or add the path to your "Additional Library Path" in Visual Stuido. You also need to specifiy the library using -l on Unix (E.g. -L /usr/local/lib -l antlr3c) or add antlr3c_dll.lib to your Addtional Library Dependencies in Visual Studio.

In case it isn't obvious, the generated files may be used to produce either a library or an executable (.EXE on Windows) file.

If you use the shared version of the libraries, DLL or .so/.so/.a then you must ship the library with your application must run in an environment whereby the library can be found by the runtime linker/loader. This usually involves specifying the directory in which the library lives to an environment variable. On Windows, X:{yourwininstalldir}\system32 will be searched automatically. The variables for common operating systems are listed here (ksh/bash assumed for *nix):

Operating System

Environment Variable

Command/Value

Windows

PATH

Add the directory where the DLL lives to the PATH environment variable at install time, or, install the DLL in the same directory as your application

Linux / Solaris / Tru64 / SVR4 Derivatives

LD_LIBRARY_PATH

export LD_LIBRARY_PATH=/your/lib/path:${LD_LIBRARY_PATH}

HPUX

SHLIB_PATH

export SHLIB_PATH=/your/lib/path:${SHLIB_PATH}

AIX

LIBPATH

export LIBPATH=/your/lib/path:${LIBPATH}

----Previous: Code Generation Targets   Next: Invoking your C Recognizer