1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "Preprocessor.h"
16
17#include <cassert>
18
19#include "DiagnosticsBase.h"
20#include "DirectiveParser.h"
21#include "Macro.h"
22#include "MacroExpander.h"
23#include "Token.h"
24#include "Tokenizer.h"
25
26namespace pp
27{
28
29struct PreprocessorImpl
30{
31 Diagnostics *diagnostics;
32 MacroSet macroSet;
33 Tokenizer tokenizer;
34 DirectiveParser directiveParser;
35 MacroExpander macroExpander;
36
37 PreprocessorImpl(Diagnostics *diag,
38 DirectiveHandler *directiveHandler,
39 const PreprocessorSettings &settings)
40 : diagnostics(diag),
41 tokenizer(diag),
42 directiveParser(&tokenizer, &macroSet, diag, directiveHandler, settings.maxMacroExpansionDepth),
43 macroExpander(&directiveParser, &macroSet, diag, false, settings.maxMacroExpansionDepth)
44 {
45 }
46};
47
48Preprocessor::Preprocessor(Diagnostics *diagnostics,
49 DirectiveHandler *directiveHandler,
50 const PreprocessorSettings &settings)
51{
52 mImpl = new PreprocessorImpl(diagnostics, directiveHandler, settings);
53}
54
55Preprocessor::~Preprocessor()
56{
57 delete mImpl;
58}
59
60bool Preprocessor::init(size_t count, const char *const string[], const int length[])
61{
62 static const int kDefaultGLSLVersion = 100;
63
64 // Add standard pre-defined macros.
65 predefineMacro("__LINE__", 0);
66 predefineMacro("__FILE__", 0);
67 predefineMacro("__VERSION__", kDefaultGLSLVersion);
68 predefineMacro("GL_ES", 1);
69
70 return mImpl->tokenizer.init(count, string, length);
71}
72
73void Preprocessor::predefineMacro(const char *name, int value)
74{
75 PredefineMacro(&mImpl->macroSet, name, value);
76}
77
78void Preprocessor::lex(Token *token)
79{
80 bool validToken = false;
81 while (!validToken)
82 {
83 mImpl->macroExpander.lex(token);
84 switch (token->type)
85 {
86 // We should not be returning internal preprocessing tokens.
87 // Convert preprocessing tokens to compiler tokens or report
88 // diagnostics.
89 case Token::PP_HASH:
90 assert(false);
91 break;
92 case Token::PP_NUMBER:
93 mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER,
94 token->location, token->text);
95 break;
96 case Token::PP_OTHER:
97 mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER,
98 token->location, token->text);
99 break;
100 default:
101 validToken = true;
102 break;
103 }
104 }
105}
106
107void Preprocessor::setMaxTokenSize(size_t maxTokenSize)
108{
109 mImpl->tokenizer.setMaxTokenSize(maxTokenSize);
110}
111
112} // namespace pp
113