File: cpp-runtime.html

package info (click to toggle)
antlr 2.7.7%2Bdfsg-10
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 9,956 kB
  • sloc: java: 54,649; cs: 12,537; makefile: 8,846; cpp: 7,359; pascal: 5,273; sh: 4,333; python: 4,299; lisp: 1,969; xml: 220; lex: 192; ansic: 127
file content (424 lines) | stat: -rw-r--r-- 13,357 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- tidied with tidy -cmiu -wrap 72 -->

<HTML>
  <HEAD>
    <TITLE>C++ Notes</TITLE>
<STYLE type="text/css">
 p.c7 {font-family: Arial; font-size: 80%}
 p.c6 {font-weight: bold}
 tt.c5 {font-style: italic}
 span.c4 {font-family: Courier New}
 small.c3 {font-family: Courier New}
 small.c2 {color: #000000; font-family: Arial}
 a.c1 {color: #000000; font-family: Arial}
</STYLE>
<STYLE type="text/css">
 td.c1 {font-weight: bold}
</STYLE>
  </HEAD>

  <BODY bgcolor="#FFFFFF" text="#000000">
          <H1><A name="_notes">C++ Notes</A></H1>
          <HR>

          <P>The C++ runtime and generated grammars look very much the
          same as the java ones. There are some subtle differences
          though, but more on this later.</P>

          <H2><A name="_buildruntime">Building the runtime</A></H2>

          <P>The following is a bit unix centric. For Windows some
          contributed project files can be found in lib/cpp/contrib. These
          may be slightly outdated.
          <P>The runtime files are located in the lib/cpp subdirectory
          of the ANTLR distribution. Building it is in general done via the
			 toplevel configure script and the Makefile generated by the configure
			 script. Before configuring please read INSTALL.txt in the toplevel directory. The file lib/cpp/README may contain some extra information on specific target machines.</P>
<PRE>
./configure --prefix=/usr/local
make
</PRE>

          <P>Installing ANTLR and the runtime is then done by typing</P>
<PRE>
make install
</PRE>
          This installs the runtime library libantlr.a in
          /usr/local/lib and the header files in
          /usr/local/include/antlr. Two convenience scripts antlr and
          antlr-config are also installed into /usr/local/bin. The first
          script takes care of invoking antlr and the other can be used to
          query the right options for your compiler to build files with
          antlr.

          <H2><A name="_usingruntime">Using the runtime</A></H2>
          Generally you will compile the ANTLR generated files with
          something similar to:
<PRE>
c++ -c MyParser.cpp -I/usr/local/include
</PRE>
          Linking is done with something similar to:
<PRE>
c++ -o MyExec &lt;your .o files&gt; -L/usr/local/lib -lantlr
</PRE>

          <H2><A name="_generatingcpp">Getting ANTLR to generate
          C++</A></H2>

          <P>To get ANTLR to generate C++ code you have to add</P>
<PRE>
language="Cpp";
</PRE>
          to the global options section. After that things are pretty
          much the same as in java mode except that a all token and AST
          classes are wrapped by a reference counting class (this to
          make live easier (in some ways and much harder in others)).
			 The reference counting class uses
<PRE>
operator-&gt;
</PRE>
          to reference the object it is wrapping. As a result of this
          you use -&gt; in C++ mode in stead of the '.' of java. See
          the examples in examples/cpp for some illustrations.

          <H2><A name="_changingasttype">AST types</A></H2>

			<P>New as of ANTLR 2.7.2 is that if you supply the
			<PRE>buildAST=true</PRE> option to a parser then you <b>have
			to</b> set and initialize an ASTFactory for the parser and
			treewalkers that use the resulting AST.
<PRE>
ASTFactory my_factory;	// generates CommonAST per default..
MyParser parser( some-lexer );
// Do setup from the AST factory repeat this for all parsers using the AST
parser.initializeASTFactory( my_factory );
parser.setASTFactory( &my_factory );
</PRE>
			 <P>In C++ mode it is also possible to override the AST type used
          by the code generated by ANTLR. To do this you have to do the
          following:

          <UL>
            <LI>
              Define a custom AST class like the following:
<PRE>
#ifndef __MY_AST_H__
#define __MY_AST_H__

#include &lt;antlr/CommonAST.hpp&gt;

class MyAST;

typedef ANTLR_USE_NAMESPACE(antlr)ASTRefCount&lt;MyAST&gt; RefMyAST;

/** Custom AST class that adds line numbers to the AST nodes.
 * easily extended with columns. Filenames will take more work since
 * you'll need a custom token class as well (one that contains the
 * filename)
 */
class MyAST : public ANTLR_USE_NAMESPACE(antlr)CommonAST {
public:
   // copy constructor
   MyAST( const MyAST& other )
   : CommonAST(other)
   , line(other.line)
   {
   }
   // Default constructor
   MyAST( void ) : CommonAST(), line(0) {}
   virtual ~MyAST( void ) {}
   // get the line number of the node (or try to derive it from the child node
   virtual int getLine( void ) const
   {
      // most of the time the line number is not set if the node is a
      // imaginary one. Usually this means it has a child. Refer to the
      // child line number. Of course this could be extended a bit.
      // based on an example by Peter Morling.
      if ( line != 0 )
         return line;
      if( getFirstChild() )
         return ( RefMyAST(getFirstChild())-&gt;getLine() );
      return 0;
   }
   virtual void setLine( int l )
   {
      line = l;
   }
   /** the initialize methods are called by the tree building constructs
    * depending on which version is called the line number is filled in.
    * e.g. a bit depending on how the node is constructed it will have the
    * line number filled in or not (imaginary nodes!).
    */
   virtual void initialize(int t, const ANTLR_USE_NAMESPACE(std)string& txt)
   {
      CommonAST::initialize(t,txt);
      line = 0;
   }
   virtual void initialize( ANTLR_USE_NAMESPACE(antlr)RefToken t )
   {
      CommonAST::initialize(t);
      line = t-&gt;getLine();
   }
   virtual void initialize( RefMyAST ast )
   {
      CommonAST::initialize(ANTLR_USE_NAMESPACE(antlr)RefAST(ast));
      line = ast-&gt;getLine();
   }
   // for convenience will also work without
   void addChild( RefMyAST c )
   {
      BaseAST::addChild( ANTLR_USE_NAMESPACE(antlr)RefAST(c) );
   }
   // for convenience will also work without
   void setNextSibling( RefMyAST c )
   {
      BaseAST::setNextSibling( ANTLR_USE_NAMESPACE(antlr)RefAST(c) );
   }
   // provide a clone of the node (no sibling/child pointers are copied)
   virtual ANTLR_USE_NAMESPACE(antlr)RefAST clone( void )
   {
      return ANTLR_USE_NAMESPACE(antlr)RefAST(new MyAST(*this));
   }
   static ANTLR_USE_NAMESPACE(antlr)RefAST factory( void )
   {
      return ANTLR_USE_NAMESPACE(antlr)RefAST(RefMyAST(new MyAST()));
   }
private:
   int line;
};
#endif
</PRE>
            </LI>

            <LI>
              Tell ANTLR's C++ codegenerator to use your RefMyAST by
              including the following in the options section of your grammars:
<PRE>
ASTLabelType = "RefMyAST";
</PRE>
              After that you only need to tell the parser before every
              invocation of a new instance that it should use the AST
              factory defined in your class. This is done like this:
<PRE>
// make factory with default type of MyAST
ASTFactory my_factory( "MyAST", MyAST::factory );
My_Parser parser(lexer);
// make sure the factory knows about all AST types in the parser..
parser.initializeASTFactory(my_factory);
// and tell the parser about the factory..
parser.setASTFactory( &my_factory );
</PRE>
<P>After these steps you can access methods/attributes of (Ref)MyAST
directly (without typecasting) in parser/treewalker productions.
<P>Forgetting to do a setASTFactory results in a nice SIGSEGV or you OS's
equivalent. The default constructor of ASTFactory initializes itself to
generate CommonAST objects.
<P>If you use a 'chain' of parsers/treewalkers then you have to make sure
they all share the same AST factory. Also if you add new definitions of
ASTnodes/tokens in downstream parsers/treewalkers you have to apply the
respective initializeASTFactory methods to this factory.
<P>This all is demonstrated in the examples/cpp/treewalk example.
            </LI>
          </UL>

          <H2><A name="_heteroast">Using Heterogeneous AST
          types</A></H2>

			 <P>This should now (as of 2.7.2) work in C++ mode. With probably some
			 caveats.
			 <P>The heteroAST example show how to set things up. A short excerpt:
<PRE>
ASTFactory ast_factory;

parser.initializeASTFactory(ast_factory);
parser.setASTFactory(&ast_factory);
</PRE>
			<P>A small excerpt from the generated initializeASTFactory method:
<PRE>
void CalcParser::initializeASTFactory( antlr::ASTFactory& factory )
{
   factory.registerFactory(4, "PLUSNode", PLUSNode::factory);
   factory.registerFactory(5, "MULTNode", MULTNode::factory);
   factory.registerFactory(6, "INTNode", INTNode::factory);
   factory.setMaxNodeType(11);
}
</PRE>
<P>After these steps ANTLR should be able to decide what factory to use at
what time.

          <H2><A name="_extras">Extra functionality in C++
          mode.</A></H2>
          In C++ mode ANTLR supports some extra functionality to make
          life a little easier.

          <H3>Inserting Code</H3>
          In C++ mode some extra control is supplied over the places
          where code can be placed in the gerenated files. These are
          extensions on the <B>header</B> directive. The syntax is:
<PRE>
header "&lt;identifier&gt;" { <CODE> }
</CODE>
</PRE>

          <TABLE summary="Overview of header id's">
            <TR>
              <TD class="c1">identifier</TD>

              <TD class="c1">where</TD>
            </TR>

            <TR>
              <TD><CODE>pre_include_hpp</CODE></TD>

              <TD>Code is inserted before ANTLR generated includes in
              the header file.</TD>
            </TR>

            <TR>
              <TD><CODE>post_include_hpp</CODE></TD>

              <TD>Code is inserted after ANTLR generated includes in
              the header file, but outside any generated namespace
              specifications.</TD>
            </TR>

            <TR>
              <TD><CODE>pre_include_cpp</CODE></TD>

              <TD>Code is inserted before ANTLR generated includes in
              the cpp file.</TD>
            </TR>

            <TR>
              <TD><CODE>post_include_cpp</CODE></TD>

              <TD>Code is inserted after ANTLR generated includes in
              the cpp file, but outside any generated namespace
              specifications.</TD>
            </TR>
          </TABLE>

          <H3>Pacifying the preprocessor</H3>

          <P>Sometimes various tree building constructs with '#'
          in them clash with the C/C++ preprocessor. ANTLR's
          preprocessor for actions is slightly extended in C++ mode to
          alleviate these pains.</P>
			 <P><B>NOTE:</B> At some point I plan to replace the '#' by
          something different that gives less trouble in C++.

          <P>The following preprocessor constructs are not
          touched. (And as a result you cannot use these as labels for
          AST nodes.</P>

          <UL>
            <LI><CODE>if</CODE></LI>

            <LI><CODE>define</CODE></LI>

            <LI><CODE>ifdef</CODE></LI>

            <LI><CODE>ifndef</CODE></LI>

            <LI><CODE>else</CODE></LI>

            <LI><CODE>elif</CODE></LI>

            <LI><CODE>endif</CODE></LI>

            <LI><CODE>warning</CODE></LI>

            <LI><CODE>error</CODE></LI>

            <LI><CODE>ident</CODE></LI>

            <LI><CODE>pragma</CODE></LI>

            <LI><CODE>include</CODE></LI>
          </UL>

          <P>As another extra it's possible to escape '#'-signs
          with a backslash e.g. "\#". As the action lexer sees these
          they get translated to simple '#' characters.</P>

          <H2><A name="_template">A template grammar file for
          C++</A></H2>
<PRE>
<CODE>header "pre_include_hpp" {
    // gets inserted before antlr generated includes in the header file
}
header "post_include_hpp" {
    // gets inserted after antlr generated includes in the header file
     // outside any generated namespace specifications
}

header "pre_include_cpp" {
    // gets inserted before the antlr generated includes in the cpp file
}

header "post_include_cpp" {
    // gets inserted after the antlr generated includes in the cpp file
}

header {
    // gets inserted after generated namespace specifications in the header
    // file. But outside the generated class.
}

options {
   language="Cpp";
    namespace="something";      // encapsulate code in this namespace
//  namespaceStd="std";         // cosmetic option to get rid of long defines
                                // in generated code
//  namespaceAntlr="antlr";     // cosmetic option to get rid of long defines
                                // in generated code
    genHashLines = true;        // generated #line's or turn it off.
}

{
   // global stuff in the cpp file
   ...
}
class MyParser extends Parser;
options {
   exportVocab=My;
}
{
   // additional methods and members
   ...
}
... rules ...

{
   // global stuff in the cpp file
   ...
}
class MyLexer extends Lexer;
options {
   exportVocab=My;
}
{
   // additional methods and members
   ...
}
... rules ...

{
   // global stuff in the cpp file
   ...
}
class MyTreeParser extends TreeParser;
options {
   exportVocab=My;
}
{
   // additional methods and members
   ...
}
... rules ...
</CODE>
</PRE>

</BODY>
</HTML>