1 /**
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are
4 * met :
5 *
6 * . Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 *
9 * . Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * . The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 package cpptools.preprocessor;
30
31 import java.io.Reader;
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.Stack;
35 import cppast.JavaCharStream;
36 import cppast.ParserTokenManager;
37 import cppast.Token;
38
39 /**
40 * Adapts the two token management systems.
41 *
42 * @author Mathieu Champlon
43 */
44 public final class PreProcessor extends ParserTokenManager implements TokenProvider
45 {
46 private final List<TokenFilter> filters = new ArrayList<TokenFilter>();
47 private final Stack<Token> buffer = new Stack<Token>();
48
49 /**
50 * Create an adapter.
51 */
52 public PreProcessor()
53 {
54 super( null );
55 }
56
57 /**
58 * Set a new input.
59 *
60 * @param reader the input reader
61 */
62 public void reset( final Reader reader )
63 {
64 buffer.clear();
65 ReInit( new JavaCharStream( reader ) );
66 }
67
68 /**
69 * {@inheritDoc}
70 */
71 public Token next()
72 {
73 return super.getNextToken();
74 }
75
76 /**
77 * {@inheritDoc}
78 */
79 public Token getNextToken()
80 {
81 if( !buffer.empty() )
82 return buffer.pop();
83 final Token token = next();
84 if( filter( token ) )
85 return getNextToken();
86 return token;
87 }
88
89 private boolean filter( final Token token )
90 {
91 for( TokenFilter filter : filters )
92 if( filter.process( token ) )
93 return true;
94 return false;
95 }
96
97 /**
98 * Add a define.
99 *
100 * @param name the name of the symbol
101 * @param value the value of the symbol
102 */
103 public void addDefine( final String name, final String value )
104 {
105 register( name, new Define( buffer, name, value ) );
106 }
107
108 /**
109 * Add a macro.
110 *
111 * @param name the name of the symbol
112 * @param value the value of the symbol
113 */
114 public void addMacro( final String name, final String value )
115 {
116 register( name, new Macro( this, buffer, name, value ) );
117 }
118
119 private void register( final String name, final TokenFilter macro )
120 {
121 for( TokenFilter filter : filters )
122 if( filter.matches( name ) )
123 throw new RuntimeException( "macro redefinition '" + name + "'" );
124 filters.add( macro );
125 }
126 }