1//
2// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
8#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
9
10#include <cassert>
11#include <memory>
12#include <vector>
13
14#include "Lexer.h"
15#include "Macro.h"
16#include "pp_utils.h"
17
18namespace pp
19{
20
21class Diagnostics;
22
23class MacroExpander : public Lexer
24{
25  public:
26    MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics);
27    virtual ~MacroExpander();
28
29    virtual void lex(Token *token);
30
31  private:
32    PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);
33
34    void getToken(Token *token);
35    void ungetToken(const Token &token);
36    bool isNextTokenLeftParen();
37
38    bool pushMacro(const Macro &macro, const Token &identifier);
39    void popMacro();
40
41    bool expandMacro(const Macro &macro,
42                     const Token &identifier,
43                     std::vector<Token> *replacements);
44
45    typedef std::vector<Token> MacroArg;
46    bool collectMacroArgs(const Macro &macro,
47                          const Token &identifier,
48                          std::vector<MacroArg> *args);
49    void replaceMacroParams(const Macro &macro,
50                            const std::vector<MacroArg> &args,
51                            std::vector<Token> *replacements);
52
53    struct MacroContext
54    {
55        const Macro *macro;
56        std::size_t index;
57        std::vector<Token> replacements;
58
59        MacroContext()
60            : macro(0),
61              index(0)
62        {
63        }
64        bool empty() const
65        {
66            return index == replacements.size();
67        }
68        const Token &get()
69        {
70            return replacements[index++];
71        }
72        void unget()
73        {
74            assert(index > 0);
75            --index;
76        }
77    };
78
79    Lexer *mLexer;
80    MacroSet *mMacroSet;
81    Diagnostics *mDiagnostics;
82
83    std::auto_ptr<Token> mReserveToken;
84    std::vector<MacroContext *> mContextStack;
85};
86
87}  // namespace pp
88#endif  // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
89
90