File: cpp_parser_classes.rb

package info (click to toggle)
klayout 0.26.2-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 146,224 kB
  • sloc: cpp: 1,465,078; ruby: 35,220; xml: 19,003; python: 8,881; sh: 1,393; tcl: 210; perl: 107; makefile: 90; ansic: 42
file content (474 lines) | stat: -rw-r--r-- 9,868 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# 
# Copyright (C) 2006-2019 Matthias Koefferlein
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

class Treetop::Runtime::SyntaxNode

  # An alias which can be used inside a derived cpp implementation
  # The default implementation collects all objects emitted by the subnodes.
  def get_cpp
    a = elements && elements.collect { |e| e.cpp }.select { |e| e }.flatten
    (a && !a.empty?) ? a : nil
  end

  # Returns the CPP objects emitted by this node. 
  # This method delivers CPP objects or arrays of CPP objects.
  def cpp
    get_cpp
  end

  # Returns the single CPP object or nil
  def cpp_reduced
    a = self.cpp
    if a.is_a?(Array) 
      a.size == 1 || raise("Internal error: more than one syntax tree node")
      a = a[0]
    end
    a
  end

  # Note: this method is required because curly braces cannot be put
  # into parser conditions (treetop syntax flaw?) 
  def text_value_ends_with_curly_brace
    text_value =~ /\}$/
  end

end

# These are a couple of emitter extensions to SyntaxNode which produce the definition syntax tree
# through the "cpp" method:

module PTypeOf 
  def cpp
    CPPTypeOf::new(qid.cpp)
  end
end

def extract_signed(t)
  if t =~ /unsigned/
    :unsigned
  elsif t =~ /signed/
    :signed
  else
    nil
  end
end

def extract_length(t)
  if t =~ /long long/
    :longlong
  elsif t =~ /long/
    :long
  elsif t =~ /short/
    :short
  else
    nil
  end
end

module PIntType 
  def cpp
    CPPPOD::new(extract_signed(text_value), extract_length(text_value), :int)
  end
end

module PCharType 
  def cpp
    CPPPOD::new(extract_signed(text_value), nil, :char)
  end
end

module PBoolType
  def cpp
    CPPPOD::new(nil, nil, :bool)
  end
end

module PSpecialType
  def cpp
    # the special type produces an ID
    CPPQualifiedId::new(false, [ CPPId::new(id.text_value, nil) ])
  end
end

module PFloatType
  def cpp
    kind = text_value =~ /double/ ? :double : :float
    CPPPOD::new(nil, extract_length(text_value), kind)
  end
end

module PVoidType
  def cpp
    CPPPOD::new(nil, nil, :void)
  end
end

module PEnumSpec
  def cpp
    CPPEnumSpec::new(id.text_value, initspec.nonterminal? ? initspec.init.text_value : nil)
  end
end

module PEnumType
  def cpp
    name = id ? id.text_value : nil
    specs = bodyspec.nonterminal? ? bodyspec.body.cpp : nil
    CPPEnum::new(name, specs)
  end
end

module PConst
  def cpp
    CPPConst::new(text_value)
  end
end

module PTemplateArgs
  def cpp
    decl = self.get_cpp
    decl ? CPPTemplateArgs::new(decl) : nil
  end
end

module PId
  def cpp
    CPPId::new(id.text_value, taspec.nonterminal? ? taspec.ta.cpp_reduced : nil)
  end
end

module PQualifiedId
  def cpp
    CPPQualifiedId::new(globalspec.nonterminal?, self.get_cpp)
  end
end

module PBaseClass
  def cpp
    visibility = nil
    virtual = false
    at = attr.text_value
    if at =~ /private/
      visibility = :private
    elsif at =~ /public/
      visibility = :public
    elsif at =~ /protected/
      visibility = :protected
    end
    if at =~ /virtual/
      virtual = true
    end
    CPPBaseClass::new(visibility, virtual, cid.cpp_reduced)
  end
end

module PStructOrClassType

  def cpp

    kind = :class 
    if stype.text_value == "struct"
      kind = :struct
    elsif stype.text_value == "union"
      kind = :union
    end

    id = idspec.nonterminal? ? idspec.id.cpp_reduced : nil
    base_classes = bcspec.nonterminal? ? bcspec.bc.cpp : nil
    body_decl = bodyspec.nonterminal? ? bodyspec.body.cpp : nil

    CPPStruct::new(kind, id, base_classes, body_decl)

  end

end

module PCV
  def to_symbol
    return self.text_value == "const" ? :const : :volatile
  end
end

module PFriendDecl
  def cpp
    CPPFriendDecl::new(t.cpp)
  end
end

module PPointer
  def cpp
    CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, CPPPointer::new(itspec.nonterminal? ? itspec.it.cpp_reduced : CPPAnonymousId::new))
  end
end

module PReference
  def cpp
    CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, CPPReference::new(itspec.nonterminal? ? itspec.it.cpp_reduced : CPPAnonymousId::new))
  end
end

module PMemberPointer
  def cpp
    CPPMemberPointer::new(cspec.qid.cpp, itspec.nonterminal? ? itspec.it.cpp_reduced : CPPAnonymousId::new, cvspec.nonterminal? && cvspec.cv.to_symbol)
  end
end

module PArraySpec
  def cpp
    CPPArray::new(nil)
  end
end

module PFuncArgPart
  def cpp
    t.cpp_reduced
  end
end

module PFuncSpec
  def cpp
    CPPFunc::new(nil, (fa.nonterminal? && fa.text_value != "void") ? (fa.a.cpp || []) : [], cvspec.nonterminal? && cvspec.cv.to_symbol)
  end
end

module PInnerTypeWithCV
  def cpp
    CPPCV::wrap(cvspec.to_symbol, it.cpp_reduced)
  end
end

module PInnerType
  def cpp
    if pfx.nonterminal?
      pfx.elements.inject(it.cpp_reduced) do |r,e|
        ee = e.spec.cpp_reduced
        ee.inner = r
        ee
      end
    else
      it.cpp
    end
  end
end

module PStorageClass
  def cpp
    if text_value =~ /^static/
      return CPPAttr::new(:static)
    elsif text_value =~ /^extern/
      return CPPAttr::new(:extern)
    else
      return nil
    end
  end
end

module PVirtual
  def cpp 
    return CPPAttr::new(:virtual)
  end
end

module PInline
  def cpp 
    return CPPAttr::new(:inline)
  end
end

module PType

  def cpp
    # This is the class/struct/union/enum declaration if there is one
    d = ct.cpp
    if d.is_a?(Array)
      r = d.select { |i| i.is_a?(CPPStruct) || i.is_a?(CPPEnum) }
    elsif d.is_a?(CPPStruct) || d.is_a?(CPPEnum)
      r = [d]
    else
      r = []
    end
    # Create each declaration
    ot = CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, ct.cpp_reduced)
    if il.nonterminal? 
      r << CPPType::new(ot, il.t1.cpp_reduced, il.i1.nonterminal? ? il.i1.is1.text_value : nil)
      il.tt.elements.each do |t|
        r << CPPType::new(ot, t.t2.cpp_reduced, t.i2.nonterminal? ? t.i2.is2.text_value : nil) 
      end
    else
      r << CPPType::new(ot, CPPAnonymousId::new, pi.nonterminal? ? pi.is.text_value : nil)
    end
    r
  end

end

module PEllipsis
  def cpp
    CPPEllipsis::new
  end
end

module PTypeWoComma
  def cpp
    ot = CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, ct.cpp_reduced)
    if il.nonterminal?
      CPPType::new(ot, il.t.cpp_reduced, il.i.nonterminal? ? il.i.is.text_value : nil)
    else
      CPPType::new(ot, CPPAnonymousId::new, pi.nonterminal? ? pi.is.text_value : nil)
    end
  end
end

module PTypeForTemplate
  def cpp
    ot = CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, ct.cpp_reduced)
    CPPType::new(ot, il.nonterminal? ? il.t.cpp_reduced : CPPAnonymousId::new, nil)
  end
end

module PUsing
  def cpp
    CPPUsingSpec::new(id.cpp_reduced, :default)
  end
end

module PTypedef
  def cpp
    t.cpp.collect do |d|
      if d.is_a?(CPPStruct)
        CPPStructDeclaration::new(d, nil, :default)
      elsif d.is_a?(CPPEnum)
        CPPEnumDeclaration::new(d, :default)
      else
        CPPTypedef::new(d, :default)
      end
    end
  end
end

module PPrivateClassStructBodyDeclarations
  def cpp
    decl = d.cpp
    decl && decl.collect do |d| 
      if d.respond_to?(:visibility) 
        d.visibility = :private
      end
      d
    end
  end
end

module PProtectedClassStructBodyDeclarations
  def cpp
    decl = d.cpp
    decl && decl.collect do |d| 
      if d.respond_to?(:visibility) 
        d.visibility = :protected
      end
      d
    end
  end
end

module PPublicClassStructBodyDeclarations
  def cpp
    decl = d.cpp
    decl && decl.collect do |d| 
      if d.respond_to?(:visibility) 
        d.visibility = :public
      end
      d
    end
  end
end

module PTemplateDecl
  def cpp
    CPPTemplateDecl::new(self.get_cpp)
  end
end

module PClassTemplateArg
  def cpp
    CPPClassTemplateArg::new(id.text_value, dtspec.nonterminal? ? dtspec.cpp : nil)
  end
end

module PDirectTemplateArg
  def cpp
    CPPDirectTemplateArg::new(t.cpp, initspec.nonterminal? ? initspec.text_value : nil)
  end
end

module PDeclaration
  def cpp
    td = nil
    if template.nonterminal? 
      td = template.d.cpp
    end
    storage_class = nil
    virtual = nil
    inline = nil
    if attr.nonterminal? && attr.cpp
      attr.cpp.each do |d|
        if d.attr == :virtual
          virtual = true
        elsif d.attr == :inline
          inline = true
        elsif d.attr == :static
          storage_class = :static
        elsif d.attr == :extern
          storage_class = :extern
        end
      end
    end
    # TODO: abstract declaration determination should be based on initializers on the
    # inner types
    t.cpp.collect do |d|
      if d.is_a?(CPPStruct)
        CPPStructDeclaration::new(d, td, :default)
      elsif d.is_a?(CPPEnum)
        CPPEnumDeclaration::new(d, :default)
      else
        CPPDeclaration::new(d, td, :default, storage_class, virtual, inline)
      end
    end
  end
end

module PExternBlock
  def cpp
    self.get_cpp.collect do |d| 
      if d.is_a?(CPPDeclaration)
        d.storage_class = :extern
      end
      d
    end
  end
end

module PNamespace
  def cpp
    CPPNamespace::new(n.text_value, decls.cpp || [])
  end
end

module PModule
  def cpp
    CPPModule::new(self.get_cpp)
  end
end