~ubuntu-branches/ubuntu/trusty/c++-annotations/trusty

« back to all changes in this revision

Viewing changes to yo/concrete/poly2/sembase/sembase.h

  • Committer: Package Import Robot
  • Author(s): tony mancill, Frank B. Brokken, tony mancill
  • Date: 2012-02-28 00:50:21 UTC
  • mfrom: (1.1.19)
  • Revision ID: package-import@ubuntu.com-20120228005021-sz7nnodntkvgh7qf
Tags: 9.2.1-1
[ Frank B. Brokken ]
* New upstream release (using flexc++, reauthored polymorphic semantic
  values and unrestricted unions). Upstream release 9.2.0 is implied by
  this release.

[ tony mancill ]
* Set Standards-Version to 3.9.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef INCLUDED_SEMBASE_
 
2
#define INCLUDED_SEMBASE_
 
3
 
 
4
#include <type_traits>
 
5
#include <memory>
 
6
#include <vector>
 
7
#include <iosfwd>
 
8
 
 
9
class SemBase;
 
10
 
 
11
//TAG
 
12
enum class Tag          // defines the various semantic values
 
13
{                       // Tags are used to instantiate the proper
 
14
    INT,                // Semantic type, deriving from a polymorphic base
 
15
    TEXT,               // class
 
16
    VECTOR,
 
17
};
 
18
//=
 
19
 
 
20
    // In separate anonymous namespace sections parts of the various semantic
 
21
    // types are defined. Sections labeled 'IUO' are `Internal Use Only' and
 
22
    // contain no serviceable parts
 
23
 
 
24
namespace {     // IUO
 
25
//MUTABLE
 
26
    struct Mutable                          // Semantic values may or may
 
27
    {                                       // not be mutable. By deriving
 
28
        enum: bool { isMutable = true };    // BasicTrait, below, from
 
29
    };                                      // either Mutable or Immutable
 
30
                                            // this trait is associated with
 
31
    struct Immutable                        // a semantic value BasicTrait.
 
32
    {
 
33
        enum: bool { isMutable = false };
 
34
    };
 
35
//=
 
36
 
 
37
    // For each semantic value type define a TagTrait specialization which
 
38
    // is either derived from Immutable (in which case the Parser cannot
 
39
    // change the semantic value) or from Mutable (In which case changing the
 
40
    // semantic value on the semantic value stack *is* allowed)
 
41
    // In addition, define the data type to use, as received in the
 
42
    // initialization (e.g., int, std::string, vector<spSemBase>).
 
43
//TRAITTAG
 
44
    template <Tag tag>
 
45
    struct TagTrait;
 
46
 
 
47
    template <>
 
48
    struct TagTrait<Tag::INT>: public Immutable
 
49
    {
 
50
        typedef int DataType;
 
51
    };
 
52
 
 
53
    template <>
 
54
    struct TagTrait<Tag::TEXT>: public Immutable
 
55
    {
 
56
        typedef std::string DataType;
 
57
    };
 
58
 
 
59
    template <>
 
60
    struct TagTrait<Tag::VECTOR>: public Mutable
 
61
    {
 
62
        typedef std::vector<std::shared_ptr<SemBase const>> DataType;
 
63
    };
 
64
//=
 
65
 
 
66
    // In this section of the anonymous namespace it is determined whether a
 
67
    // semantic value type is a basic type (in which case the return type of
 
68
    // the Semantic class's conversion operator can be equal to the type
 
69
    // itself) or a class-type (in which case a reference is returned).
 
70
   /// Its logic is based on two function templates 'test' expecting either
 
71
    // any type of argument or expecting a pointer to a member function of the
 
72
    // type provided to the template. Since basic types have no members, the
 
73
    // `any argument' variant is selected by the compiler for basic
 
74
    // types. These two functions return values having different sizes,
 
75
    // allowing the template to determine whether the type is a basic type or
 
76
    // not. The enum value 'isBasicType' is initialized accordingly.
 
77
   /// For the ReturnType (i.e., the conversion operator's return type the
 
78
    // std::conditional template meta programming function is used). For a
 
79
    // mutable data type a reference to the Semantic class's data memebr is
 
80
    // returned, for an immutable basic data type a copy of the data member's
 
81
    // value is returned, otherwise a const & is returned.
 
82
//CLASSTRAIT
 
83
    struct C2
 
84
    {
 
85
        char _[2];
 
86
    };
 
87
 
 
88
    struct C1
 
89
    {
 
90
        char _;
 
91
    };
 
92
 
 
93
    template <typename T>
 
94
    C1 test(...);
 
95
 
 
96
    template <typename T>
 
97
    C2 test(void (T::*)());
 
98
 
 
99
    template <Tag tg_>
 
100
    struct Trait: public TagTrait<tg_>
 
101
    {
 
102
        typedef typename Trait<tg_>::DataType DataType;
 
103
        enum: bool
 
104
        {
 
105
            isMutable = Trait<tg_>::isMutable,
 
106
            isBasicType = sizeof(test<DataType>(0)) == sizeof(C1)
 
107
        };
 
108
 
 
109
        typedef typename
 
110
            std::conditional<
 
111
                isMutable,
 
112
                    DataType &,
 
113
                    typename std::conditional<
 
114
                        isBasicType,
 
115
                            DataType,
 
116
                            DataType const &
 
117
                    >::type
 
118
            >::type ReturnType;
 
119
    };
 
120
//=
 
121
}
 
122
 
 
123
   /// The implementation of the polymorphic semantic value in fact implements
 
124
    // a type-safe polymorphic semantic union. This is a non-existing data
 
125
    // type in C++, but the parser may handle semantic values as unions: it
 
126
    // always knows the actual type of semantic value that's used at a
 
127
    // particular point in the grammar, and if not, it can inspect the
 
128
    // SemBase's tag fields. Since the parser knows, or can determine what the
 
129
    // actual semantic type is, it can always perform a downcast, resulting in
 
130
    // a *very* lightweight SemBase base class: there's only a virtual
 
131
    // destructor. No other virtual members are required. Downcasting itself
 
132
    // is encapsulated in its 'as' member, allowing constructions like
 
133
   ///      $1->as<Tag::STRING>()
 
134
   /// to downcast the $1 SemBase to a Semantic<Tag::STRING>, and then,
 
135
    // usually by implication, to a std::string, using the Semantic's
 
136
    // conversion operator.
 
137
//SEMBASE
 
138
class SemBase
 
139
{
 
140
    Tag d_tag;
 
141
 
 
142
    public:
 
143
        SemBase(SemBase const &other) = delete;
 
144
        virtual ~SemBase();
 
145
        Tag tag() const;
 
146
 
 
147
        template <Tag tg_>
 
148
        typename Trait<tg_>::ReturnType as() const;
 
149
 
 
150
    protected:
 
151
        SemBase(Tag tag);
 
152
};
 
153
//=
 
154
inline Tag SemBase::tag() const
 
155
{
 
156
    return d_tag;
 
157
}
 
158
 
 
159
inline SemBase::SemBase(Tag tag)
 
160
:
 
161
    d_tag(tag)
 
162
{}
 
163
 
 
164
 
 
165
    // The Semantic class template is derived from SemBase. It always defines
 
166
    // its data member as mutable (I can't do this under template control, but
 
167
    // I could define, e.g., two anonymous structs holding, respectively, a
 
168
    // mutable and non-mutable DataType data member, but Semantic isn't doing
 
169
    // anything with d_data anyway, so by always declaring d_data as mutable
 
170
    // it can be returned from the conversion operator, which itself is a
 
171
    // const member.
 
172
   /// Again: Semantic is extremely light-weight. Only initialization and
 
173
    // conversion to the embedded data member need to be supported.
 
174
//SEMANTIC
 
175
template <Tag tg_>
 
176
class Semantic: public SemBase
 
177
{
 
178
    typedef typename Trait<tg_>::DataType DataType;
 
179
    enum: bool { isMutable = Trait<tg_>::isMutable };
 
180
 
 
181
    mutable DataType d_data;
 
182
 
 
183
    public:
 
184
        typedef typename Trait<tg_>::ReturnType ReturnType;
 
185
 
 
186
        Semantic(DataType const &data);
 
187
        operator ReturnType() const;
 
188
};
 
189
 
 
190
template <Tag tg_>
 
191
Semantic<tg_>::Semantic(DataType const &data)
 
192
:
 
193
    SemBase(tg_),
 
194
    d_data(data)
 
195
{}
 
196
 
 
197
template <Tag tg_>
 
198
Semantic<tg_>::operator ReturnType() const
 
199
{
 
200
    return d_data;
 
201
}
 
202
//=
 
203
 
 
204
    // The 'as' member simply performs the required downcast. It is
 
205
    // implemented here, since it refers to Semantic<Tag>. Since this class
 
206
    // has just been defined, no forward declaration is required anymore.
 
207
//AS
 
208
template <Tag tg_>
 
209
inline   typename Trait<tg_>::ReturnType   SemBase::as() const
 
210
{
 
211
    return dynamic_cast<Semantic<tg_> const &>(*this);
 
212
}
 
213
//=
 
214
 
 
215
#endif