PageRenderTime 21ms CodeModel.GetById 12ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/src/tools/wrappers-generator/name_converter.e

http://github.com/tybor/Liberty
Specman e | 297 lines | 203 code | 24 blank | 70 comment | 8 complexity | 9290cd4d821f192adf1bc5b1669d0dbd MD5 | raw file
  1deferred class NAME_CONVERTER
  2   -- Query features to dcover if a symbol name does comply to SmartEiffel's
  3   -- naming rules and to convert arbitrary C symbols into valid Eiffel names
  4   -- of classes or features.
  5
  6insert
  7   PLATFORM
  8   EXCEPTIONS
  9
 10feature {ANY} -- Auxiliary features
 11   eiffel_feature (a_name: ABSTRACT_STRING): STRING
 12         -- Translate `a_name' content into a proper feature name for the
 13         -- Gnu-Eiffel language.  "CamelCase" is translated into "camel_case",
 14         -- "ENOO" is translated into "enoo". Eventual underscores in front of
 15         -- `a_name' are removed: "__foo" becomes "foo"; symbols starting with
 16         -- underscores folloed by a number are prefixed with "a_"; reserved
 17         -- language names and names of features of class ANY are escaped.
 18         -- TODO: handle in a fairly
 19      require
 20         name_not_void: a_name /= Void
 21         name_not_empty: not a_name.is_empty
 22      do
 23         create Result.make_from_string(a_name)
 24         -- Remove header underscores.
 25         from
 26         until
 27            Result.first /= '_'
 28         loop
 29            Result.remove_first
 30         end
 31         -- If first character is a number prepend an `a_'
 32         if Result.first.is_digit then
 33            Result.prepend(once "a_")
 34         end
 35
 36         insert_underscores(Result)
 37         -- Remove spurious underscores and the end
 38         from
 39         until
 40            Result.last /= '_'
 41         loop
 42            Result.remove_last
 43         end
 44
 45         multiple_underscores_remover.substitute_all_in(Result)
 46         -- Deal with C++ names: turn lt<foo> into lt_of_foo
 47         -- TODO: queue<dock,deepspace::station> into queue_of_dock_and_deepspace_station
 48
 49         lt_translator.substitute_all_in(Result)
 50         gt_translator.substitute_all_in(Result)
 51         namespace_separator_translator.substitute_all_in(Result)
 52         Result.to_lower
 53         Result := adapt(Result, once "_external")
 54      end
 55
 56   eiffel_argument (a_name: ABSTRACT_STRING): STRING
 57         -- `a_name' content translated into a proper argument placeholder for
 58         -- the Gnu-Eiffel language.  "CamelCase" is translated into
 59         -- "a_camel_case", "ENOO" is translated into "an_enoo". Eventual
 60         -- underscores in front of `a_name' are removed: "__foo" becomes
 61         -- "a_foo". See also `eiffel_feature'.
 62      require
 63         name_not_void: a_name /= Void
 64      local
 65         e_feature, e_prefix: ABSTRACT_STRING
 66      do
 67         e_feature := eiffel_feature(a_name)
 68         inspect
 69            e_feature.first
 70         when 'a', 'e', 'o', 'i', 'u' then
 71            e_prefix := once "an_"
 72         else
 73            e_prefix := once "a_"
 74         end
 75         Result := e_prefix + e_feature
 76      end
 77
 78   insert_underscores (a_string: STRING)
 79         -- Insert an underscore ('_') before each uppercase letter following a lowercase one.
 80      require
 81         a_string /= Void
 82         not a_string.is_empty
 83      local
 84         i: INTEGER
 85      do
 86         from
 87            i := a_string.lower + 1
 88         until
 89            i > a_string.upper
 90         loop
 91            if a_string.item(i - 1).is_lower and a_string.item(i).is_upper then
 92               a_string.insert_character('_', i)
 93               i := i + 2
 94            else
 95               i := i + 1
 96            end
 97         end
 98      end
 99
100   camelcase_translator: REGULAR_EXPRESSION
101         -- Insert an underscore ('_') between any lowercase letter followed by an uppercase one
102      local
103         builder: REGULAR_EXPRESSION_BUILDER
104      once
105         Result := builder.convert_perl_pattern("([a-z])([A-Z])")
106         Result.prepare_substitution("\1_\2")
107      end
108
109   multiple_underscores_remover: REGULAR_EXPRESSION
110         -- Replace all multiple occurences of underscore "_" with a single one
111      local
112         builder: REGULAR_EXPRESSION_BUILDER
113      once
114         Result := builder.convert_perl_pattern("(\_\_+)")
115         Result.prepare_substitution("_")
116      end
117
118   lt_translator: REGULAR_EXPRESSION
119         -- Replace all occurences of "<" (shown as "&lt;") with "_of_"
120      local
121         builder: REGULAR_EXPRESSION_BUILDER
122      once
123         Result := builder.convert_perl_pattern("(&lt;)")
124         Result.prepare_substitution("_of_")
125      end
126
127   gt_translator: REGULAR_EXPRESSION
128         -- Remove all occurences of ">" (shown as "&gt;")
129      local
130         builder: REGULAR_EXPRESSION_BUILDER
131      once
132         Result := builder.convert_perl_pattern("(&gt;)")
133         Result.prepare_substitution("")
134      end
135
136   namespace_separator_translator: REGULAR_EXPRESSION
137         -- Replace all occurences of "::" (C++ namespace separator) with "_"
138      local
139         builder: REGULAR_EXPRESSION_BUILDER
140      once
141         Result := builder.convert_perl_pattern("(&gt;)")
142         Result.prepare_substitution("i")
143      end
144
145   is_public_name (a_name: ABSTRACT_STRING): BOOLEAN
146         -- Does `a_name' start with an alphabetical character? Names
147         -- starting with underscores or other strange characters are
148         -- usually considered private in C/C++ languages.
149      require
150         not_void: a_name /= Void
151         meaningful_length: a_name.count > 1
152      do
153         Result := a_name.first.is_letter
154      end
155
156   eiffel_class_name (a_string, a_suffix: ABSTRACT_STRING): STRING
157         -- An Eiffel class name derived from `a_string'. Trailing and tail
158         -- underscores are removed, dashes are turned into underscores,
159         -- `a_suffix' is added at the end if not void, all is made uppercase.
160      require
161         a_string /= Void
162      do
163         create Result.make_from_string(a_string)
164         -- Remove trailing underscores
165         from
166         until
167            Result.first /= '_'
168         loop
169            Result.remove_first
170         end
171
172         check
173            Result.last.code /= 0
174         end
175         -- Remove spurious underscores at the end
176         from
177         until
178            Result.last /= '_'
179         loop
180            Result.remove_last
181         end
182
183         check
184            Result.last.code /= 0
185         end
186         insert_underscores(Result)
187         if a_suffix /= Void then
188            Result.append(a_suffix)
189         end
190
191         check
192            Result.last.code /= 0
193            -- The reason of this check is not easy understandable here.
194            -- It's actually a poor's man test of a strange, old bug of STRING
195            -- shown by xml library that don't update capacity and actual
196            -- length with an off-by-one length error
197         end
198         Result.replace_all('-', '_')
199         Result.to_upper
200         -- print("'"+Result+"' last charcter code is: "+Result.last.code.to_string+"%N")
201         check
202            Result.last.code /= 0
203         end
204      ensure
205         Result /= Void
206         is_valid_class_name(Result)
207      end
208
209   is_valid_class_name (a_name: ABSTRACT_STRING): BOOLEAN
210         -- Does `a_name' represents a valid Eiffel class name? i.e. does it
211         -- start with an upper-case letter and contain only upper-case
212         -- letters, underscores and numbers?
213      require
214         a_name /= Void
215      local
216         iter: ITERATOR[CHARACTER]; c: CHARACTER
217      do
218         iter := a_name.new_iterator
219         from
220            iter.start
221            Result := iter.item.is_upper
222            iter.next
223         until
224            Result = False or else not iter.is_off
225         loop
226            c := iter.item
227            Result := c.is_upper or else c.is_digit and c /= '.' or else c = '_'
228            iter.next
229         end
230      end
231
232   adapt (a_name, a_suffix: ABSTRACT_STRING): STRING
233         -- A valid, adapted identifier for an Eiffel feature labelled
234         -- `a_name'. Can be either `a_name' itself or a new string
235         -- containing an adapatation. Reserved words and those of
236         -- features belonging to ANY are "escaped", appending `a_suffix'.
237      require
238         name_not_void: a_name /= Void
239         valid_name: a_name.first /= '_'
240         suffix_not_void: a_suffix /= Void
241         suffix_not_empty: not a_suffix.is_empty
242      do
243         if keywords.has(a_name) or else any_features.has(a_name) then
244            Result := a_name + a_suffix
245         elseif Result ?:= a_name then
246            Result ::= a_name
247         else
248            create Result.make_from_string(a_name)
249         end
250      ensure
251         Result /= Void
252      end
253
254feature {} -- Constants
255   keywords: HASHED_SET[ABSTRACT_STRING]
256      once
257         Result := {HASHED_SET[ABSTRACT_STRING] << "indexing"
258         -- Keywords:
259         -- related to classes
260         , "class", "deferred", "expanded", "separate", "end", "obsolete", "inherit" -- related to inheritance
261         , "insert", "creation", "feature", "rename", "redefine", "undefine", "select", "export", "require" -- design by contract
262         , "ensure", "check", "debug", "invariant", "variant", "rescue", "local" -- features body
263         , "do", "once", "alias", "external", "attribute", "if" -- control flow
264         , "then", "else", "elseif", "when", "from", "until", "loop", "and" -- boolean operators
265         , "or", "xor", "not", "implies" >> }
266      end
267
268   any_features: HASHED_SET[ABSTRACT_STRING]
269         -- The names of the features contained in class ANY.
270         -- The following "static" definition of the features of ANY
271         -- somehow unacceptable in a perfect world. Yet computing it each
272         -- and every time would enlarge the memory usage of the program
273         -- quite a lot, not counting the runtime requirements. We will do
274         -- it when we will cache compilation results.
275      once
276         -- The following "static" definition of the features of ANY
277         -- somehow unacceptable in a perfect world. Yet computing it each
278         -- and every time would enlarge the memory usage of the program
279         -- quite a lot, not counting the runtime requirements. We will do
280         -- it when we will cache compilation results.
281         Result := {HASHED_SET[ABSTRACT_STRING] << "generating", "generator", "same_dynamic_type", "_equal", "standard__equal", "_deep_equal", "twin", "copy", "standard_twin", "standard_copy", "deep_twin", "default", "_default", "print_on", "tagged_out", "out", "out_in_tagged_out_memory", "tagged_out_memory", "fill_tagged_out_memory", "to_pointer", "_basic_expanded_type", "object_size" >> }
282      end
283
284end -- class NAME_CONVERTER
285
286-- Copyright (C) 2008-2017: Paolo Redaelli
287
288-- wrappers-generator  is free software: you can redistribute it and/or modify it
289-- under the terms of the GNU General Public License as publhed by the Free
290-- Software Foundation, either version 2 of the License, or (at your option)
291-- any later version.
292-- wrappers-generator is distributed in the hope that it will be useful, but
293-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
294-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
295-- more details.
296-- You should have received a copy of the GNU General Public License along with
297-- th program.  If not, see <http://www.gnu.org/licenses/>.