blob: 4de0568837f947181cc7922d4448fc7d5911ac9b [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Mark Sleee9ce01c2007-05-16 02:29:53 +000019
Mark Slee31985722006-05-24 21:45:31 +000020#ifndef T_GENERATOR_H
21#define T_GENERATOR_H
22
23#include <string>
24#include <iostream>
David Reiss39aa00d2009-03-26 08:40:18 +000025#include <fstream>
Mark Sleee8540632006-05-30 09:24:40 +000026#include <sstream>
Mark Slee31985722006-05-24 21:45:31 +000027#include "parse/t_program.h"
Mark Slee0e0ff7e2007-01-18 22:59:59 +000028#include "globals.h"
Bryan Duxburye0ac3ab2010-07-29 16:24:41 +000029#include "t_generator_registry.h"
Mark Slee31985722006-05-24 21:45:31 +000030
31/**
32 * Base class for a thrift code generator. This class defines the basic
33 * routines for code generation and contains the top level method that
34 * dispatches code generation across various components.
35 *
Mark Slee31985722006-05-24 21:45:31 +000036 */
37class t_generator {
38 public:
Mark Sleef0712dc2006-10-25 19:03:57 +000039 t_generator(t_program* program) {
Mark Sleef5377b32006-10-10 01:42:59 +000040 tmp_ = 0;
Mark Sleef0712dc2006-10-25 19:03:57 +000041 indent_ = 0;
42 program_ = program;
43 program_name_ = get_program_name(program);
David Reiss82e6fc02009-03-26 23:32:36 +000044 escape_['\n'] = "\\n";
45 escape_['\r'] = "\\r";
46 escape_['\t'] = "\\t";
47 escape_['"'] = "\\\"";
48 escape_['\\'] = "\\\\";
Mark Sleef5377b32006-10-10 01:42:59 +000049 }
50
Mark Slee31985722006-05-24 21:45:31 +000051 virtual ~t_generator() {}
52
53 /**
54 * Framework generator method that iterates over all the parts of a program
55 * and performs general actions. This is implemented by the base class and
David Reissb4d7b892008-03-27 21:40:01 +000056 * should not normally be overwritten in the subclasses.
Mark Slee31985722006-05-24 21:45:31 +000057 */
David Reissb4d7b892008-03-27 21:40:01 +000058 virtual void generate_program();
Mark Slee31985722006-05-24 21:45:31 +000059
kholst76f2c882008-01-16 02:47:41 +000060 const t_program* get_program() const { return program_; }
61
David Reiss39aa00d2009-03-26 08:40:18 +000062 void generate_docstring_comment(std::ofstream& out,
63 const std::string& comment_start,
64 const std::string& line_prefix,
65 const std::string& contents,
66 const std::string& comment_end);
David Reiss82e6fc02009-03-26 23:32:36 +000067
68 /**
Bryan Duxbury681f5ea2010-08-20 16:42:04 +000069 * check whether sub-namespace declaraction is used by generator.
David Reisse3ba3492010-08-26 21:49:45 +000070 * e.g. allow
Bryan Duxbury681f5ea2010-08-20 16:42:04 +000071 * namespace py.twisted bar
72 * to specify namespace to use when -gen py:twisted is specified.
73 * Will be called with subnamespace, i.e. is_valid_namespace("twisted")
74 * will be called for the above example.
75 */
Roger Meier3b771a12010-11-17 22:11:26 +000076 static bool is_valid_namespace(const std::string& sub_namespace) {
77 (void) sub_namespace;
78 return false;
79 }
Bryan Duxbury681f5ea2010-08-20 16:42:04 +000080
81 /**
David Reiss82e6fc02009-03-26 23:32:36 +000082 * Escape string to use one in generated sources.
83 */
84 virtual std::string escape_string(const std::string &in) const;
85
86 std::string get_escaped_string(t_const_value* constval) {
87 return escape_string(constval->get_string());
88 }
89
Mark Slee31985722006-05-24 21:45:31 +000090 protected:
Mark Sleef5377b32006-10-10 01:42:59 +000091
92 /**
93 * Optional methods that may be imlemented by subclasses to take necessary
94 * steps at the beginning or end of code generation.
95 */
Mark Sleee8540632006-05-30 09:24:40 +000096
Mark Sleef0712dc2006-10-25 19:03:57 +000097 virtual void init_generator() {}
98 virtual void close_generator() {}
Mark Slee31985722006-05-24 21:45:31 +000099
Mark Sleeaa7671d2006-11-29 03:19:31 +0000100 virtual void generate_consts(std::vector<t_const*> consts);
101
Mark Sleef5377b32006-10-10 01:42:59 +0000102 /**
103 * Pure virtual methods implemented by the generator subclasses.
104 */
Mark Sleee8540632006-05-30 09:24:40 +0000105
Mark Slee9cb7c612006-09-01 22:17:45 +0000106 virtual void generate_typedef (t_typedef* ttypedef) = 0;
107 virtual void generate_enum (t_enum* tenum) = 0;
Roger Meier3b771a12010-11-17 22:11:26 +0000108 virtual void generate_const (t_const* tconst) {
109 (void) tconst;
110 }
Mark Slee9cb7c612006-09-01 22:17:45 +0000111 virtual void generate_struct (t_struct* tstruct) = 0;
Mark Sleef5377b32006-10-10 01:42:59 +0000112 virtual void generate_service (t_service* tservice) = 0;
Mark Slee9cb7c612006-09-01 22:17:45 +0000113 virtual void generate_xception (t_struct* txception) {
Mark Sleef5377b32006-10-10 01:42:59 +0000114 // By default exceptions are the same as structs
Mark Slee9cb7c612006-09-01 22:17:45 +0000115 generate_struct(txception);
116 }
Mark Slee31985722006-05-24 21:45:31 +0000117
Mark Sleef5377b32006-10-10 01:42:59 +0000118 /**
119 * Method to get the program name, may be overridden
120 */
Mark Sleee8540632006-05-30 09:24:40 +0000121 virtual std::string get_program_name(t_program* tprogram) {
122 return tprogram->get_name();
123 }
124
Mark Sleef5377b32006-10-10 01:42:59 +0000125 /**
126 * Method to get the service name, may be overridden
127 */
Mark Sleee8540632006-05-30 09:24:40 +0000128 virtual std::string get_service_name(t_service* tservice) {
129 return tservice->get_name();
130 }
131
Mark Sleef5377b32006-10-10 01:42:59 +0000132 /**
dweatherford65b70752007-10-31 02:18:14 +0000133 * Get the current output directory
134 */
135 virtual std::string get_out_dir() const {
136 return program_->get_out_path() + out_dir_base_ + "/";
137 }
138
139 /**
Mark Sleef5377b32006-10-10 01:42:59 +0000140 * Creates a unique temporary variable name, which is just "name" with a
141 * number appended to it (i.e. name35)
142 */
Mark Sleee8540632006-05-30 09:24:40 +0000143 std::string tmp(std::string name) {
144 std::ostringstream out;
145 out << name << tmp_++;
146 return out.str();
147 }
148
Mark Sleef5377b32006-10-10 01:42:59 +0000149 /**
150 * Indentation level modifiers
151 */
Mark Sleee8540632006-05-30 09:24:40 +0000152
Mark Sleef5377b32006-10-10 01:42:59 +0000153 void indent_up(){
154 ++indent_;
155 }
Mark Slee31985722006-05-24 21:45:31 +0000156
Mark Sleef5377b32006-10-10 01:42:59 +0000157 void indent_down() {
158 --indent_;
159 }
160
161 /**
162 * Indentation print function
163 */
Mark Slee31985722006-05-24 21:45:31 +0000164 std::string indent() {
165 std::string ind = "";
166 int i;
167 for (i = 0; i < indent_; ++i) {
168 ind += " ";
169 }
170 return ind;
171 }
172
Mark Sleef5377b32006-10-10 01:42:59 +0000173 /**
174 * Indentation utility wrapper
175 */
Mark Slee31985722006-05-24 21:45:31 +0000176 std::ostream& indent(std::ostream &os) {
177 return os << indent();
178 }
David Reiss3429b6a2007-08-15 00:55:41 +0000179
iproctor9a41a0c2007-07-16 21:59:24 +0000180 /**
181 * Capitalization helpers
182 */
183 std::string capitalize(std::string in) {
184 in[0] = toupper(in[0]);
185 return in;
186 }
187 std::string decapitalize(std::string in) {
188 in[0] = tolower(in[0]);
189 return in;
190 }
Mark Sleee02ab332007-11-28 04:17:49 +0000191 std::string lowercase(std::string in) {
192 for (size_t i = 0; i < in.size(); ++i) {
193 in[i] = tolower(in[i]);
194 }
195 return in;
196 }
Todd Lipconb6f4e562010-01-19 05:18:55 +0000197 /**
198 * Transforms a camel case string to an equivalent one separated by underscores
199 * e.g. aMultiWord -> a_multi_word
200 * someName -> some_name
201 * CamelCase -> camel_case
202 * name -> name
203 * Name -> name
204 */
Kevin Clark19f8d1f2009-04-07 19:09:28 +0000205 std::string underscore(std::string in) {
206 in[0] = tolower(in[0]);
207 for (size_t i = 1; i < in.size(); ++i) {
208 if (isupper(in[i])) {
209 in[i] = tolower(in[i]);
210 in.insert(i, "_");
211 }
212 }
213 return in;
214 }
Todd Lipconb6f4e562010-01-19 05:18:55 +0000215 /**
216 * Transforms a string with words separated by underscores to a camel case equivalent
217 * e.g. a_multi_word -> aMultiWord
218 * some_name -> someName
219 * name -> name
220 */
221 std::string camelcase(std::string in) {
222 std::ostringstream out;
223 bool underscore = false;
224
225 for (size_t i = 0; i < in.size(); i++) {
226 if (in[i] == '_') {
227 underscore = true;
228 continue;
229 }
230 if (underscore) {
231 out << (char) toupper(in[i]);
232 underscore = false;
233 continue;
234 }
235 out << in[i];
236 }
237
238 return out.str();
239 }
Mark Slee31985722006-05-24 21:45:31 +0000240
David Reiss3429b6a2007-08-15 00:55:41 +0000241 /**
242 * Get the true type behind a series of typedefs.
243 */
244 static t_type* get_true_type(t_type* type) {
David Reiss41d30582010-10-05 16:39:29 +0000245 return type->get_true_type();
David Reiss3429b6a2007-08-15 00:55:41 +0000246 }
247
Mark Sleee8540632006-05-30 09:24:40 +0000248 protected:
Mark Sleef5377b32006-10-10 01:42:59 +0000249 /**
Mark Sleef0712dc2006-10-25 19:03:57 +0000250 * The program being generated
251 */
252 t_program* program_;
253
254 /**
Mark Sleef5377b32006-10-10 01:42:59 +0000255 * Quick accessor for formatted program name that is currently being
256 * generated.
257 */
Mark Sleee8540632006-05-30 09:24:40 +0000258 std::string program_name_;
259
Mark Sleef5377b32006-10-10 01:42:59 +0000260 /**
261 * Quick accessor for formatted service name that is currently being
262 * generated.
263 */
Mark Sleee8540632006-05-30 09:24:40 +0000264 std::string service_name_;
265
dweatherford65b70752007-10-31 02:18:14 +0000266 /**
267 * Output type-specifc directory name ("gen-*")
268 */
269 std::string out_dir_base_;
270
David Reiss82e6fc02009-03-26 23:32:36 +0000271 /**
272 * Map of characters to escape in string literals.
273 */
274 std::map<char, std::string> escape_;
275
Mark Slee31985722006-05-24 21:45:31 +0000276 private:
Mark Sleef5377b32006-10-10 01:42:59 +0000277 /**
278 * Current code indentation level
279 */
Mark Slee31985722006-05-24 21:45:31 +0000280 int indent_;
281
Mark Sleef5377b32006-10-10 01:42:59 +0000282 /**
283 * Temporary variable counter, for making unique variable names
284 */
Mark Sleee8540632006-05-30 09:24:40 +0000285 int tmp_;
Mark Slee31985722006-05-24 21:45:31 +0000286};
287
Mark Slee31985722006-05-24 21:45:31 +0000288#endif