1. ast
Start data section to licences/ast_licence.txt[1
/1
]
1: The ast software
2: Copyright (c) 2002, Regents of the University of California
3: All rights reserved.
4:
5: Redistribution and use in source and binary forms, with or without
6: modification, are permitted provided that the following conditions are
7: met:
8:
9: * Redistributions of source code must retain the above copyright
10: notice, this list of conditions and the following disclaimer.
11:
12: * Redistributions in binary form must reproduce the above
13: copyright notice, this list of conditions and the following
14: disclaimer in the documentation and/or other materials provided
15: with the distribution.
16:
17: * Neither the name of the University of California, Berkeley nor
18: the names of its contributors may be used to endorse or promote
19: products derived from this software without specific prior
20: written permission.
21:
22: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33:
Start C section to elk/ast_ast.ast.h[1
/1
]
1: #line 39 "./lpsrc/ast.pak"
2: // ast.ast.h
3: // *** DO NOT EDIT ***
4: // generated automatically by astgen, from ast.ast
5:
6: #ifndef AST_AST_H
7: #define AST_AST_H
8:
9: #include "ast_asthelp.h"
10:
11: // fwd decls
12: class ASTSpecFile;
13: class ToplevelForm;
14: class TF_verbatim;
15: class TF_impl_verbatim;
16: class TF_class;
17: class TF_option;
18: class TF_enum;
19: class ASTClass;
20: class AccessMod;
21: class Annotation;
22: class UserDecl;
23: class CustomCode;
24: class CtorArg;
25: class BaseClass;
26:
27:
28: // *** DO NOT EDIT ***
29:
30: #include "sm_str.h"
31:
32: // this signals to ast.hand.cc that ast.ast.cc is nonempty,
33: // so none of the bootstrap code in ast.hand.cc should be used
34: #define GENERATED_AST_PRESENT
35:
36: // *** DO NOT EDIT ***
37: class ASTSpecFile {
38: public: // data
39: ASTList <ToplevelForm > forms;
40:
41: public: // funcs
42: ASTSpecFile(ASTList <ToplevelForm > *_forms) : forms(_forms) {
43: }
44: ~ASTSpecFile();
45:
46: char const *kindName() const { return "ASTSpecFile"; }
47:
48: ASTSpecFile *clone() const;
49:
50: void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
51:
52: };
53:
54:
55:
56: // *** DO NOT EDIT ***
57: class ToplevelForm {
58: public: // data
59:
60: public: // funcs
61: ToplevelForm() {
62: }
63: virtual ~ToplevelForm();
64:
65: enum Kind { TF_VERBATIM, TF_IMPL_VERBATIM, TF_CLASS, TF_OPTION, TF_ENUM, NUM_KINDS };
66: virtual Kind kind() const = 0;
67:
68: static char const * const kindNames[NUM_KINDS];
69: char const *kindName() const { return kindNames[kind()]; }
70:
71: DECL_AST_DOWNCASTS(TF_verbatim, TF_VERBATIM)
72: DECL_AST_DOWNCASTS(TF_impl_verbatim, TF_IMPL_VERBATIM)
73: DECL_AST_DOWNCASTS(TF_class, TF_CLASS)
74: DECL_AST_DOWNCASTS(TF_option, TF_OPTION)
75: DECL_AST_DOWNCASTS(TF_enum, TF_ENUM)
76:
77: virtual ToplevelForm *clone() const=0;
78:
79: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
80:
81: };
82:
83: class TF_verbatim : public ToplevelForm {
84: public: // data
85: sm_string code;
86:
87: public: // funcs
88: TF_verbatim(sm_string _code) : ToplevelForm(), code(_code) {
89: }
90: virtual ~TF_verbatim();
91:
92: virtual Kind kind() const { return TF_VERBATIM; }
93: enum { TYPE_TAG = TF_VERBATIM };
94:
95: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
96:
97: virtual TF_verbatim *clone() const;
98:
99: };
100:
101: class TF_impl_verbatim : public ToplevelForm {
102: public: // data
103: sm_string code;
104:
105: public: // funcs
106: TF_impl_verbatim(sm_string _code) : ToplevelForm(), code(_code) {
107: }
108: virtual ~TF_impl_verbatim();
109:
110: virtual Kind kind() const { return TF_IMPL_VERBATIM; }
111: enum { TYPE_TAG = TF_IMPL_VERBATIM };
112:
113: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
114:
115: virtual TF_impl_verbatim *clone() const;
116:
117: };
118:
119: class TF_class : public ToplevelForm {
120: public: // data
121: ASTClass *super;
122: ASTList <ASTClass > ctors;
123:
124: public: // funcs
125: TF_class(ASTClass *_super, ASTList <ASTClass > *_ctors) : ToplevelForm(), super(_super), ctors(_ctors) {
126: }
127: virtual ~TF_class();
128:
129: virtual Kind kind() const { return TF_CLASS; }
130: enum { TYPE_TAG = TF_CLASS };
131:
132: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
133:
134: virtual TF_class *clone() const;
135:
136: public: bool hasChildren() const { return ctors.isNotEmpty(); };
137: };
138:
139: class TF_option : public ToplevelForm {
140: public: // data
141: sm_string name;
142: ASTList <sm_string > args;
143:
144: public: // funcs
145: TF_option(sm_string _name, ASTList <sm_string > *_args) : ToplevelForm(), name(_name), args(_args) {
146: }
147: virtual ~TF_option();
148:
149: virtual Kind kind() const { return TF_OPTION; }
150: enum { TYPE_TAG = TF_OPTION };
151:
152: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
153:
154: virtual TF_option *clone() const;
155:
156: };
157:
158: class TF_enum : public ToplevelForm {
159: public: // data
160: sm_string name;
161: ASTList <sm_string > enumerators;
162:
163: public: // funcs
164: TF_enum(sm_string _name, ASTList <sm_string > *_enumerators) : ToplevelForm(), name(_name), enumerators(_enumerators) {
165: }
166: virtual ~TF_enum();
167:
168: virtual Kind kind() const { return TF_ENUM; }
169: enum { TYPE_TAG = TF_ENUM };
170:
171: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
172:
173: virtual TF_enum *clone() const;
174:
175: };
176:
177:
178:
179: // *** DO NOT EDIT ***
180: class ASTClass {
181: public: // data
182: sm_string name;
183: ASTList <CtorArg > args;
184: ASTList <BaseClass > bases;
185: ASTList <Annotation > decls;
186:
187: public: // funcs
188: ASTClass(sm_string _name, ASTList <CtorArg > *_args, ASTList <BaseClass > *_bases, ASTList <Annotation > *_decls) : name(_name), args(_args), bases(_bases), decls(_decls) {
189: }
190: ~ASTClass();
191:
192: char const *kindName() const { return "ASTClass"; }
193:
194: ASTClass *clone() const;
195:
196: void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
197:
198: public: sm_string classKindName() const;
199: };
200:
201:
202:
203: // *** DO NOT EDIT ***
204:
205: // specifies what kind of userdecl this is; pub/priv/prot are uninterpreted
206: // class members with the associated access control; ctor and dtor are
207: // code to be inserted into the ctor or dtor, respectively
208: enum AccessCtl {
209: AC_PUBLIC, // access
210: AC_PRIVATE, // control
211: AC_PROTECTED, // keywords
212: AC_CTOR, // insert into ctor
213: AC_DTOR, // insert into dtor
214: AC_PUREVIRT, // declare pure virtual in superclass, and impl in subclass
215: NUM_ACCESSCTLS
216: };
217:
218: // map the enum value to a sm_string like "public"
219: sm_string toString(AccessCtl acc); // defined in ast.cc
220:
221: // *** DO NOT EDIT ***
222: class AccessMod {
223: public: // data
224: AccessCtl acc;
225: ASTList <sm_string > mods;
226:
227: public: // funcs
228: AccessMod(AccessCtl _acc, ASTList <sm_string > *_mods) : acc(_acc), mods(_mods) {
229: }
230: ~AccessMod();
231:
232: char const *kindName() const { return "AccessMod"; }
233:
234: AccessMod *clone() const;
235:
236: void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
237:
238: public: bool hasMod(char const *mod) const;
239: };
240:
241:
242:
243: // *** DO NOT EDIT ***
244: class Annotation {
245: public: // data
246:
247: public: // funcs
248: Annotation() {
249: }
250: virtual ~Annotation();
251:
252: enum Kind { USERDECL, CUSTOMCODE, NUM_KINDS };
253: virtual Kind kind() const = 0;
254:
255: static char const * const kindNames[NUM_KINDS];
256: char const *kindName() const { return kindNames[kind()]; }
257:
258: DECL_AST_DOWNCASTS(UserDecl, USERDECL)
259: DECL_AST_DOWNCASTS(CustomCode, CUSTOMCODE)
260:
261: virtual Annotation *clone() const=0;
262:
263: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
264:
265: };
266:
267: class UserDecl : public Annotation {
268: public: // data
269: AccessMod *amod;
270: sm_string code;
271: sm_string init;
272:
273: public: // funcs
274: UserDecl(AccessMod *_amod, sm_string _code, sm_string _init) : Annotation(), amod(_amod), code(_code), init(_init) {
275: }
276: virtual ~UserDecl();
277:
278: virtual Kind kind() const { return USERDECL; }
279: enum { TYPE_TAG = USERDECL };
280:
281: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
282:
283: virtual UserDecl *clone() const;
284:
285: public: AccessCtl access() const { return amod->acc; };
286: };
287:
288: class CustomCode : public Annotation {
289: public: // data
290: sm_string qualifier;
291: sm_string code;
292:
293: public: // funcs
294: CustomCode(sm_string _qualifier, sm_string _code) : Annotation(), qualifier(_qualifier), code(_code) {
295: used=false;
296: }
297: virtual ~CustomCode();
298:
299: virtual Kind kind() const { return CUSTOMCODE; }
300: enum { TYPE_TAG = CUSTOMCODE };
301:
302: virtual void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
303:
304: virtual CustomCode *clone() const;
305:
306: public: bool used;
307: };
308:
309:
310:
311: // *** DO NOT EDIT ***
312: class CtorArg {
313: public: // data
314: bool isOwner;
315: sm_string type;
316: sm_string name;
317: sm_string defaultValue;
318:
319: public: // funcs
320: CtorArg(bool _isOwner, sm_string _type, sm_string _name, sm_string _defaultValue) : isOwner(_isOwner), type(_type), name(_name), defaultValue(_defaultValue) {
321: }
322: ~CtorArg();
323:
324: char const *kindName() const { return "CtorArg"; }
325:
326: CtorArg *clone() const;
327:
328: void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
329:
330: };
331:
332:
333:
334: // *** DO NOT EDIT ***
335: class BaseClass {
336: public: // data
337: AccessCtl access;
338: sm_string name;
339:
340: public: // funcs
341: BaseClass(AccessCtl _access, sm_string _name) : access(_access), name(_name) {
342: }
343: ~BaseClass();
344:
345: char const *kindName() const { return "BaseClass"; }
346:
347: BaseClass *clone() const;
348:
349: void debugPrint(std::ostream &os, int indent, char const *subtreeName = "tree") const;
350:
351: };
352:
353:
354:
355:
356: #endif // AST_AST_H
Start C section to elk/ast_ast.hand.h[1
/1
]
1: #line 396 "./lpsrc/ast.pak"
2: // ast.hand.h see license.txt for copyright and terms of use
3: // generated (by hand) from ast.ast
4:
5: #ifndef BOOTSTRAP
6: // in non-bootstrap mode, use the generated file
7: #include "ast_ast.ast.h"
8: #endif
9:
10: #ifndef GENERATED_AST_PRESENT
11: // use the code below if either:
12: // - BOOTSTRAP was defined
13: // - ast.gen.h was empty
14:
15: #ifndef AST_HAND_H
16: #define AST_HAND_H
17:
18: #include "ast_asthelp.h"
19:
20: // fwd decls
21: class ASTSpecFile;
22: class ToplevelForm;
23: class TF_verbatim;
24: class ASTClass;
25: class UserDecl;
26: class ASTCtor;
27: class CtorArg;
28:
29:
30: #include "sm_str.h"
31:
32: class ASTSpecFile {
33: public:
34: ASTList<ToplevelForm> forms;
35:
36: public:
37: ASTSpecFile(ASTList<ToplevelForm> *_forms) : forms(_forms) {}
38: ~ASTSpecFile() {}
39:
40: void debugPrint(std::ostream &os, int indent) const;
41: };
42:
43:
44: class ToplevelForm {
45: public:
46: ToplevelForm() {}
47: virtual ~ToplevelForm() {}
48:
49: enum Kind { TF_VERBATIM, ASTCLASS, NUM_KINDS };
50: virtual Kind kind() const = 0;
51:
52: DECL_AST_DOWNCASTS(TF_verbatim, TF_VERBATIM)
53: DECL_AST_DOWNCASTS(ASTClass, ASTCLASS)
54:
55: virtual void debugPrint(std::ostream &os, int indent) const;
56: };
57:
58: class TF_verbatim : public ToplevelForm {
59: public:
60: sm_string code;
61:
62: public:
63: TF_verbatim(sm_string _code)
64: : code(_code)
65: {}
66: virtual ~TF_verbatim() {}
67:
68: virtual Kind kind() const { return TF_VERBATIM; }
69: enum { TYPE_TAG = TF_VERBATIM };
70:
71: virtual void debugPrint(std::ostream &os, int indent) const;
72: };
73:
74: class ASTClass : public ToplevelForm {
75: public:
76: sm_string name;
77: ASTList<CtorArg> superCtor;
78: ASTList<UserDecl> decls;
79: ASTList<ASTCtor> ctors;
80:
81: public:
82: ASTClass(sm_string _name, ASTList<CtorArg> *_superCtor,
83: ASTList<UserDecl> *_decls, ASTList<ASTCtor> *_ctors) :
84: name(_name), superCtor(_superCtor), decls(_decls), ctors(_ctors)
85: {}
86: ~ASTClass() {}
87:
88: virtual Kind kind() const { return ASTCLASS; }
89: enum { TYPE_TAG = ASTCLASS };
90:
91: virtual void debugPrint(std::ostream &os, int indent) const;
92:
93: public: bool hasChildren() const { return ctors.isNotEmpty(); }
94: };
95:
96:
97: enum AccessCtl { AC_PUBLIC, AC_PRIVATE, AC_PROTECTED };
98: sm_string toString(AccessCtl acc); // defined in ast.cc
99:
100:
101: class UserDecl {
102: public:
103: AccessCtl access;
104: sm_string code;
105:
106: public:
107: UserDecl(AccessCtl _access, sm_string _code)
108: : access(_access), code(_code)
109: {}
110: ~UserDecl() {}
111:
112: void debugPrint(std::ostream &os, int indent) const;
113: };
114:
115:
116: class ASTCtor {
117: public:
118: sm_string name;
119: ASTList<CtorArg> args;
120: ASTList<UserDecl> decls;
121:
122: public:
123: ASTCtor(sm_string _name, ASTList<CtorArg> *_args, ASTList<UserDecl> *_decls)
124: : name(_name), args(_args), decls(_decls)
125: {}
126: ~ASTCtor() {}
127:
128: void debugPrint(std::ostream &os, int indent) const;
129:
130: public: sm_string kindName() const;
131: };
132:
133:
134: class CtorArg {
135: public:
136: bool owner;
137: sm_string type;
138: sm_string name;
139:
140: public:
141: CtorArg(bool _owner, sm_string _type, sm_string _name)
142: : owner(_owner),
143: type(_type),
144: name(_name)
145: {}
146: ~CtorArg() {}
147:
148: void debugPrint(std::ostream &os, int indent) const;
149: };
150:
151: #endif // AST_HAND_H
152:
153: #endif // !GENERATED_AST_PRESENT
Start C section to elk/ast_asthelp.h[1
/1
]
1: #line 550 "./lpsrc/ast.pak"
2: // asthelp.h see license.txt for copyright and terms of use
3: // included by generated ast code
4:
5: #ifndef ASTHELP_H
6: #define ASTHELP_H
7:
8: #include "sm_astlist.h"
9: #include "ast_fakelist.h"
10: #include "sm_str.h"
11: #include "ast_locstr.h"
12:
13: #include <iostream> // ostream
14:
15: // ----------------- downcasts --------------------
16: // the 'if' variants return NULL if the type isn't what's expected;
17: // the 'as' variants throw an exception in that case
18: #define DECL_AST_DOWNCASTS(type, tag) \
19: type const *if##type##C() const; \
20: type *if##type() \
21: { return const_cast<type*>(if##type##C()); } \
22: type const *as##type##C() const; \
23: type *as##type() \
24: { return const_cast<type*>(as##type##C()); } \
25: bool is##type() const \
26: { return kind() == tag; }
27:
28:
29: #define DEFN_AST_DOWNCASTS(superclass, type, tag)\
30: type const *superclass::if##type##C() const \
31: { \
32: if (kind() == tag) { \
33: return (type const*)this; \
34: } \
35: else { \
36: return NULL; \
37: } \
38: } \
39: \
40: type const *superclass::as##type##C() const \
41: { \
42: xassert(kind() == tag); \
43: return (type const*)this; \
44: }
45:
46:
47: // ------------------- const typecase --------------------
48: #define ASTSWITCHC(supertype, nodeptr) \
49: { \
50: supertype const *switch_nodeptr = (nodeptr); \
51: switch (switch_nodeptr->kind())
52:
53: #define ASTCASEC(type, var) \
54: case type::TYPE_TAG: { \
55: type const *var = switch_nodeptr->as##type##C();
56:
57: // the "1" versions mean "one argument", i.e. they
58: // do not bind a variable of the specified type
59: #define ASTCASEC1(type) \
60: case type::TYPE_TAG: {
61:
62: #define ASTNEXTC(type, var) \
63: break; \
64: } /* end previous case */ \
65: case type::TYPE_TAG: { \
66: type const *var = switch_nodeptr->as##type##C();
67:
68: #define ASTNEXTC1(type) \
69: break; \
70: } /* end previous case */ \
71: case type::TYPE_TAG: {
72:
73: // end a case, and add an empty 'default' construct
74: #define ASTENDCASECD \
75: break; \
76: } /* end final case */ \
77: default: ; /* silence warning */ \
78: } /* end scope started before switch */
79:
80: #define ASTDEFAULTC \
81: break; \
82: } /* end final case */ \
83: default: {
84:
85: // end a case where an explicit default was present, or
86: // there is no need to add one (e.g. because it was exhaustive)
87: #define ASTENDCASEC \
88: break; \
89: } /* end final case */ \
90: } /* end scope started before switch */
91:
92:
93: // ------------------- non-const typecase --------------------
94: #define ASTSWITCH(supertype, nodeptr) \
95: { \
96: supertype *switch_nodeptr = (nodeptr); \
97: switch (switch_nodeptr->kind())
98:
99: #define ASTCASE(type, var) \
100: case type::TYPE_TAG: { \
101: type *var = switch_nodeptr->as##type();
102:
103: #define ASTCASE1(type) \
104: case type::TYPE_TAG: {
105:
106: #define ASTNEXT(type, var) \
107: break; \
108: } /* end previous case */ \
109: case type::TYPE_TAG: { \
110: type *var = switch_nodeptr->as##type();
111:
112: #define ASTNEXT1(type) \
113: break; \
114: } /* end previous case */ \
115: case type::TYPE_TAG: {
116:
117: // end-of-switch behavior is same as in const case
118: #define ASTENDCASED ASTENDCASECD
119: #define ASTDEFAULT ASTDEFAULTC
120: #define ASTENDCASE ASTENDCASEC
121:
122:
123: // ------------------- debug print helpers -----------------
124: std::ostream &ind(std::ostream &os, int indent);
125:
126: // I occasionally want to see addresses, so I just throw this
127: // switch and recompile..
128: #if 1
129: // headers w/o addresses
130: #define PRINT_HEADER(subtreeName, clsname) \
131: ind(os, indent) << subtreeName << " = " #clsname ":\n"; \
132: indent += 2 /* user ; */
133: #else
134: // headers w/ addresses
135: #define PRINT_HEADER(subtreeName, clsname) \
136: ind(os, indent) << subtreeName << " = " #clsname " (" << ((void*)this) << "):\n"; \
137: indent += 2 /* user ; */
138: #endif
139:
140:
141: #define PRINT_STRING(var) \
142: debugPrintStr(var, #var, os, indent) /* user ; */
143:
144: void debugPrintStr(sm_string const &s, char const *name,
145: std::ostream &os, int indent);
146:
147:
148: #define PRINT_LIST(T, list) \
149: debugPrintList(list, #list, os, indent) /* user ; */
150:
151: template <class T>
152: void debugPrintList(ASTList<T> const &list, char const *name,
153: std::ostream &os, int indent)
154: {
155: ind(os, indent) << name << ":\n";
156: int ct=0;
157: {
158: FOREACH_ASTLIST(T, list, iter) {
159: iter.data()->debugPrint(os, indent+2,
160: sm_stringc << name << "[" << ct++ << "]");
161: }
162: }
163: }
164:
165: // provide explicit specialization for sm_strings
166: void debugPrintList(ASTList<sm_string> const &list, char const *name,
167: std::ostream &os, int indent);
168: void debugPrintList(ASTList<LocString> const &list, char const *name,
169: std::ostream &os, int indent);
170:
171:
172: #define PRINT_FAKE_LIST(T, list) \
173: debugPrintFakeList(list, #list, os, indent) /* user ; */
174:
175: template <class T>
176: void debugPrintFakeList(FakeList<T> const *list, char const *name,
177: std::ostream &os, int indent)
178: {
179: ind(os, indent) << name << ":\n";
180: int ct=0;
181: {
182: FAKELIST_FOREACH(T, list, iter) {
183: iter->debugPrint(os, indent+2,
184: sm_stringc << name << "[" << ct++ << "]");
185: }
186: }
187: }
188:
189: // note that we never make FakeLists of sm_strings, since of course
190: // sm_strings do not have a 'next' pointer
191:
192:
193: #define PRINT_SUBTREE(tree) \
194: if (tree) { \
195: (tree)->debugPrint(os, indent, #tree); \
196: } \
197: else { \
198: ind(os, indent) << #tree << " is null\n"; \
199: } /* user ; (optional) */
200:
201:
202: #define PRINT_GENERIC(var) \
203: ind(os, indent) << #var << " = " << ::toString(var) << "\n" /* user ; */
204:
205:
206: #define PRINT_BOOL(var) \
207: ind(os, indent) << #var << " = " << (var? "true" : "false") << "\n" /* user ; */
208:
209:
210: // ------------------- xml print helpers -----------------
211: // dsw: given above in the debug print section.
212: // ostream &ind(ostream &os, int indent);
213:
214: #define XMLPRINT_HEADER(clsname) \
215: ind(os, indent) << "<object type=\"" << #clsname "\">\n"; \
216: indent += 2 /* user ; */ \
217:
218: #define XMLPRINT_FOOTER(clsname) \
219: indent -= 2; \
220: ind(os, indent) << "</object>\n" /* user ; */
221:
222: #define XMLPRINT_STRING(var) \
223: xmlPrintStr(var, #var, os, indent) /* user ; */
224:
225: void xmlPrintStr(sm_string const &s, char const *name,
226: std::ostream &os, int indent);
227:
228:
229: #define XMLPRINT_LIST(T, list) \
230: xmlPrintList(list, #list, os, indent) /* user ; */
231:
232: template <class T>
233: void xmlPrintList(ASTList<T> const &list, char const *name,
234: std::ostream &os, int indent)
235: {
236: ind(os, indent) << "<member type=list name=\"" << name << "\">\n";
237: {
238: FOREACH_ASTLIST(T, list, iter) {
239: iter.data()->xmlPrint(os, indent+2);
240: }
241: }
242: ind(os, indent) << "</member>\n";
243: }
244:
245: // provide explicit specialization for sm_strings
246: void xmlPrintList(ASTList<sm_string> const &list, char const *name,
247: std::ostream &os, int indent);
248: void xmlPrintList(ASTList<LocString> const &list, char const *name,
249: std::ostream &os, int indent);
250:
251:
252: #define XMLPRINT_FAKE_LIST(T, list) \
253: xmlPrintFakeList(list, #list, os, indent) /* user ; */
254:
255: template <class T>
256: void xmlPrintFakeList(FakeList<T> const *list, char const *name,
257: std::ostream &os, int indent)
258: {
259: ind(os, indent) << "<member type=fakelist name=\"" << name << "\">\n";
260: {
261: FAKELIST_FOREACH(T, list, iter) {
262: iter->xmlPrint(os, indent+2);
263: }
264: }
265: ind(os, indent) << "</member>\n";
266: }
267:
268: // note that we never make FakeLists of sm_strings, since of course
269: // sm_strings do not have a 'next' pointer
270:
271:
272: #define XMLPRINT_SUBTREE(tree) \
273: if (tree) { \
274: (tree)->xmlPrint(os, indent); \
275: } \
276: else { \
277: xassert(0); /* dsw:not sure what to do here yet */ \
278: ind(os, indent) << #tree << " is null\n"; \
279: } /* user ; (optional) */
280:
281:
282: // dsw: there's no way this can work in general
283: #define XMLPRINT_GENERIC(var) \
284: ind(os, indent) << "<member type=generic name=\"" << #var << "\">\n"; \
285: ind(os, indent+2) << "<object type=generic val=\"" << ::toString(var) << "\" />\n"; \
286: ind(os, indent) << "</member>\n" /* user ; */
287:
288:
289: #define XMLPRINT_BOOL(var) \
290: ind(os, indent) << "<member type=bool name=\"" << #var << "\">\n"; \
291: ind(os, indent+2) << "<object type=bool val=\"" << (var? "true" : "false") << "\" />\n"; \
292: ind(os, indent) << "</member>\n" /* user ; */
293:
294:
295: // ---------------------- deep-copy ------------------
296: // returns a new'd list because the AST node ctors want
297: // to accept an owner ptr to a list
298: template <class T>
299: ASTList<T> * /*owner*/ cloneASTList(ASTList<T> const &src)
300: {
301: ASTList<T> *ret = new ASTList<T>;
302:
303: FOREACH_ASTLIST(T, src, iter) {
304: ret->append(iter.data()->clone());
305: }
306:
307: return ret;
308: }
309:
310:
311: // returns owner pointer to list of serfs.. using this isn't ideal
312: // because ASTList normally is owning, and probably deletes its
313: // elements in its destructor..
314: template <class T>
315: ASTList<T> * /*owner*/ shallowCloneASTList(ASTList<T> const &src)
316: {
317: ASTList<T> *ret = new ASTList<T>;
318:
319: FOREACH_ASTLIST(T, src, iter) {
320: // list backbone is const, but nodes' constness leaks away..
321: ret->append(const_cast<T*>(iter.data()));
322: }
323:
324: return ret;
325: }
326:
327:
328: // deep copy of a FakeList
329: template <class T>
330: FakeList<T> * /*owner*/ cloneFakeList(FakeList<T> const *src)
331: {
332: if (!src) {
333: return FakeList<T>::emptyList(); // base case of recursion
334: }
335:
336: // clone first element
337: T *head = src->firstC()->clone();
338: xassert(head->next == NULL); // it had better not copy the list tail itself!
339:
340: // attach to result of cloning the tail
341: FakeList<T> *tail = cloneFakeList(src->butFirstC());
342: return tail->prepend(head);
343: }
344:
345:
346: #endif // ASTHELP_H
Start C section to elk/ast_ccsstr.h[1
/1
]
1: #line 897 "./lpsrc/ast.pak"
2: // ccsstr.h see license.txt for copyright and terms of use
3: // C++ substrate for my parser
4:
5: #ifndef CCSSTR_H
6: #define CCSSTR_H
7:
8: #include "ast_embedded.h"
9:
10: class CCSubstrateTest;
11:
12: class CCSubstrate : public EmbeddedLang {
13: private:
14: enum State {
15: ST_NORMAL, // normal text
16: ST_STRING, // inside a sm_string literal
17: ST_CHAR, // inside a char literal
18: ST_SLASH, // from ST_NORMAL, just saw a slash
19: ST_C_COMMENT, // inside a C comment
20: ST_CC_COMMENT, // inside a C++ comment
21: NUM_STATES
22: } state;
23: int nesting; // depth of paren/bracket/brace nesting
24: bool backslash; // in ST_{STRING,CHAR}, just seen backslash?
25: bool star; // in ST_C_COMMENT, just seen '*'?
26:
27: // so test code can interrogate internal state
28: friend class CCSubstrateTest;
29:
30: public:
31: CCSubstrate(ReportError *err = NULL);
32: virtual ~CCSubstrate();
33:
34: // EmbeddedLang entry points (see gramlex.h for description
35: // of each function)
36: virtual void reset(int initNest = 0);
37: virtual void handle(char const *str, int len, char finalDelim);
38: virtual bool zeroNesting() const;
39: virtual sm_string getFuncBody() const;
40: virtual sm_string getDeclName() const;
41: };
42:
43: #endif // CCSSTR_H
Start C section to elk/ast_embedded.h[1
/1
]
1: #line 941 "./lpsrc/ast.pak"
2: // embedded.h see license.txt for copyright and terms of use
3: // interface to an embedded language processor
4:
5: #ifndef EMBEDDED_H
6: #define EMBEDDED_H
7:
8: #include "sm_str.h"
9: #include "ast_reporterr.h"
10:
11: class EmbeddedLang {
12: public:
13: // for reporting errors
14: ReportError *err;
15:
16: // all text processed so far; it collects the
17: // embedded code; clients will call 'handle' a
18: // bunch of times and then expect to retrieve
19: // the text from here
20: sm_stringBuilder text;
21:
22: // when true (set by the lexer), the 'text' is to
23: // be interpreted as an expression, rather than a
24: // complete function body; this affects what
25: // getFuncBody() returns
26: bool exprOnly;
27:
28: // when true the text is a declaration, so we have to
29: // add a single semicolon
30: bool isDeclaration;
31:
32: public:
33: EmbeddedLang(ReportError *err = NULL /*print to stdout*/);
34: virtual ~EmbeddedLang(); // silence warning
35:
36: // start from scratch
37: virtual void reset(int initNest = 0) = 0;
38:
39: // process the given sm_string of characters, as source text in
40: // the embedded language; 'finalDelim' is provided for printing
41: // informative error messages
42: virtual void handle(char const *str, int len, char finalDelim) = 0;
43:
44: // return true if we're at a nesting level of zero
45: // and not in a sm_string, etc. -- characters at this
46: // level have "usual" meaning
47: virtual bool zeroNesting() const = 0;
48:
49: // return the body of the embedded function; should
50: // always return a complete function body, even when
51: // exprOnly is true (by adding to 'text' if necessary)
52: virtual sm_string getFuncBody() const = 0;
53:
54: // return the name of the declared function, assuming
55: // that is the context in which 'text' was collected
56: virtual sm_string getDeclName() const = 0;
57: };
58:
59: #endif // EMBEDDED_H
Start C section to elk/ast_fakelist.h[1
/1
]
1: #line 1001 "./lpsrc/ast.pak"
2: // fakelist.h see license.txt for copyright and terms of use
3: // headerless list of nodes where each node has a 'next' field
4:
5: #ifndef FAKELIST_H
6: #define FAKELIST_H
7:
8: // idea: define a templatized class such that a pointer to
9: // this class appears to present access to a list of the
10: // underlying T objects; but in fact, the pointer is actually
11: // a T pointer, and T contains a field called 'next' which
12: // inductively defines the list contents. then such a pointer
13: // could be used to provide documentation of the presence of
14: // the list (and not just one node), and a uniform (with other
15: // list interfaces) syntactic interface, while hiding an
16: // efficient representation
17:
18: // why not just insist that all objects be derived from some
19: // base class, e.g. FakeListNode, that defines 'next'? because
20: // what is the type of 'next'? it has to be FakeListNode*, but
21: // then either it must be physically first, or else 'next' is
22: // a pointer to the interior and I have to worry about whether
23: // the casts to/from the outer type will be correctly offset; and
24: // then getting to the next node requires a cast (the usual
25: // problem with subtyping polymorphism)
26:
27: // for now, the list is non-owning (unless you call 'deallocNodes')
28:
29: class Some_undefined_class;
30:
31: template <class T>
32: class FakeList {
33: private:
34: // you can't create or delete one of these
35: FakeList();
36: ~FakeList();
37:
38: // silence a silly egcs-1.1.2 warning (this function isn't defined)
39: friend class Some_undefined_class;
40:
41: // this class has *no* data--an object of this type is
42: // never actually created! instead we play with pointers
43: // to this "type", and cast to T* as necessary
44:
45: public:
46: // this is as much of a constructor as there is
47: static FakeList<T> *makeList(T *node) { return (FakeList<T>*)node; }
48: static FakeList<T> *emptyList() { return NULL; }
49:
50: // this will deallocate all the nodes in the list; the list itself
51: // is, therefore, also deallocated and should not be used after this
52: void deallocNodes();
53:
54: // simple selectors
55: int count() const;
56: bool isEmpty() const { return this == NULL; }
57: bool isNotEmpty() const { return !isEmpty(); }
58:
59: // "car" in Lisp terminology
60: T *first() { return (T*)this; }
61: T const *firstC() const { return (T const*)this; }
62:
63: // "cdr" in Lisp terminology
64: FakeList<T> *butFirst() { return makeList(first()->next); }
65: FakeList<T> const *butFirstC() const { return makeList(firstC()->next); }
66:
67: // similar to "cons" in Lisp terminology (but this doesn't allocate)
68: FakeList<T> *prepend(T *newHead)
69: {
70: // I'm going to be surprised if this is ever not true.. it's
71: // a potential problem in cc.gr, since I'm assuming there that
72: // 'newHead' is not already on any other lists...
73: //
74: // update: This does occasionally get triggered, because a node
75: // might get yielded to two contexts. Failing this assertion is a
76: // symptom that the sharing needs to be more carefully managed.
77: // It's often the case that newHead->next in fact equals first()
78: // already, but if the client code wants to let that slide it's
79: // going to have to check itself; I don't want to silently allow
80: // accidental happens-to-not-change-anything overwriting down in
81: // this code.
82: xassert(newHead->next == NULL);
83:
84: newHead->next = first();
85: return makeList(newHead);
86: }
87:
88: // random access (linear time of course)
89: T const *nthC(int n) const;
90: T *nth(int n) { return const_cast<T*>(nthC(n)); }
91:
92: // don't add an 'append' method; I think if you're trying to append
93: // with FakeLists then you're probably misusing them
94:
95: // perhaps breaking the idea a little...
96: FakeList<T> *reverse();
97:
98: // this class is deliberately sparse on methods for now, since I'm
99: // not sure what kind of manipulations I'll want, given that this
100: // class's purpose is fairly specialized (AST lists)
101: };
102:
103:
104:
105: // I'm deliberately contradicting the convention elsewhere, where
106: // "FOREACH" comes first; I think it should have come second to begin
107: // with, and since this class isn't derived from any of the others
108: // with the opposite convention, this is as good a place as any to
109: // reverse it
110:
111: #define FAKELIST_FOREACH(NodeType, listPtr, nodePtrVar) \
112: for (NodeType const *nodePtrVar = listPtr->firstC(); \
113: nodePtrVar != NULL; \
114: nodePtrVar = nodePtrVar->next)
115:
116: #define FAKELIST_FOREACH_NC(NodeType, listPtr, nodePtrVar) \
117: for (NodeType *nodePtrVar = listPtr->first(); \
118: nodePtrVar != NULL; \
119: nodePtrVar = nodePtrVar->next)
120:
121:
122: template <class T>
123: void FakeList<T>::deallocNodes()
124: {
125: T *p = first();
126: while (p) {
127: T *next = p->next;
128:
129: // just in case T's destructor thinks it owns 'next',
130: // nullify it since I'm going to dealloc it myself
131: p->next = NULL;
132: delete p;
133:
134: p = next;
135: }
136: }
137:
138:
139: template <class T>
140: int FakeList<T>::count() const
141: {
142: int ct = 0;
143: FAKELIST_FOREACH(T, this, p) {
144: ct++;
145: }
146: return ct;
147: }
148:
149:
150: template <class T>
151: T const *FakeList<T>::nthC(int n) const
152: {
153: const FakeList<T> *p = this;
154: while (n > 0) {
155: p = p->butFirstC(); // segfaults if n is too small
156: n--;
157: }
158: return p->firstC();
159: }
160:
161:
162: template <class T>
163: FakeList<T> *FakeList<T>::reverse()
164: {
165: FakeList<T> *src = this;
166: FakeList<T> *dest = emptyList();
167:
168: while (src->isNotEmpty()) {
169: // remove first element of 'src'
170: T *first = src->first();
171: src = src->butFirst();
172: first->next = NULL;
173:
174: // put it at the head of 'dest'
175: dest = dest->prepend(first);
176: }
177:
178: return dest;
179: }
180:
181:
182: #endif // FAKELIST_H
Start C section to elk/ast_gramlex.h[1
/1
]
1: #line 1184 "./lpsrc/ast.pak"
2: // gramlex.h see license.txt for copyright and terms of use
3: // GrammarLexer: a c++ lexer class for use with Flex's generated c++ scanner
4: // this lexer class is used both for parsing both AST and grammar descriptions;
5: // they differ in their .lex description, but their lexing state is the same
6:
7: #ifndef __GRAMLEX_H
8: #define __GRAMLEX_H
9:
10:
11: // This included file is part of the Flex distribution. It is
12: // installed in /usr/include on my Linux machine. By including it, we
13: // get the declaration of the yyFlexLexer class. Note that the file
14: // that flex generates, gramlex.yy.cc, also #includes this file.
15: // Perhaps also worth mentioning: I'm developing this with flex 2.5.4.
16: //
17: // update: This approach was too problematic. I've taken to distributing
18: // FlexLexer.h myself.
19: #include "sm_flexlexer.h"
20:
21: #include <iostream> // istream
22:
23: // token code definitions
24: #define TOK_EOF 0 // better name
25: #define TOK_INCLUDE 1 // not seen by parser
26:
27:
28: // other includes
29: #include "sm_str.h"
30: #include "sm_objlist.h"
31: #include "sm_srcloc.h"
32: #include "ast_embedded.h"
33: #include "ast_strtable.h"
34:
35:
36: // this class just holds the lexer state so it is properly encapsulated
37: // (and therefore, among other things, re-entrant)
38: class GrammarLexer : public yyFlexLexer, public ReportError {
39: public: // types
40: enum Constants {
41: lexBufferSize = 4096, // size of new lex buffers
42: };
43:
44: // return true if the given token code is one of those representing
45: // embedded text
46: typedef bool (*isEmbedTok)(int tokCode);
47:
48: // error reporter that uses fileState instead of tokenStartLoc
49: class AltReportError : public ReportError {
50: GrammarLexer &lexer;
51:
52: public:
53: AltReportError(GrammarLexer &L) : lexer(L) {}
54:
55: virtual void reportError(char const *msg);
56: virtual void reportWarning(char const *msg);
57: };
58: friend class AltReportError;
59:
60: public: // data
61: // exposed so a user-provided 'embedded' can use it
62: AltReportError altReporter;
63:
64: private: // data
65: // state of a file we were or are lexing
66: struct FileState {
67: SourceLoc loc; // location in the file
68: std::istream *source; // (owner?) source stream
69: yy_buffer_state *bufstate; // (owner?) flex's internal buffer state
70:
71: public:
72: FileState(char const *filename, std::istream *source);
73: ~FileState();
74:
75: FileState(FileState const &obj);
76: FileState& operator= (FileState const &obj);
77: };
78:
79: FileState fileState; // state for file we're lexing now
80: ObjList<FileState> fileStack; // stack of files we will return to
81:
82: SourceLoc tokenStartLoc; // location of start of current token
83:
84: // support for embedded code
85: char embedStart; // if nonzero, punctuation that triggers
86: // embedded processing
87: char embedFinish; // which character ends the embedded section
88: int embedMode; // TOK_FUNDECL_BODY or TOK_FUN_BODY
89: EmbeddedLang *embedded; // (owner) the processor
90: isEmbedTok embedTokTest; // for printing diagnostics
91: bool allowInit; // true if embedded can have an initializer
92:
93: int prevState; // so /**/ doesn't change start state
94:
95: int prevToken; // last token code yielded (ugly hack)
96:
97: public: // data
98: // todo: can eliminate commentStartLine in favor of tokenStartLoc?
99: //int commentStartLine; // for reporting unterminated C comments
100: int integerLiteral; // to store number literal value
101: StringRef sm_stringLiteral; // sm_string in quotes, minus the quotes
102: StringRef includeFileName; // name in an #include directive
103:
104: // defined in the base class, FlexLexer:
105: // const char *YYText(); // start of matched text
106: // int YYLeng(); // number of matched characters
107:
108: StringTable &strtable; // sm_string table
109:
110: // count of errors encountered
111: int errors;
112:
113: private: // funcs
114: // disallowed
115: GrammarLexer(GrammarLexer const &);
116:
117: // called to advance the column count
118: void advCol(int n)
119: { fileState.loc = sourceLocManager->advCol(fileState.loc, n); }
120:
121: // called when a newline is encountered
122: void newLine()
123: { fileState.loc = sourceLocManager->advLine(fileState.loc); }
124:
125: // adds a sm_string with only the specified # of chars; writes (but
126: // then restores) a null terminator if necessary, so 'str' isn't const
127: StringRef addString(char *str, int len) const;
128:
129: // nominally true if 'ch' equals 'embedFinish', but with a niggle
130: bool embedFinishMatches(char ch) const;
131:
132: public: // funcs
133: // create a new lexer that will read from to named stream,
134: // or stdin if it is NULL
135: GrammarLexer(isEmbedTok embedTokTest,
136: StringTable &strtable,
137: char const *fname = "<stdin>",
138: std::istream * /*owner*/ source = NULL,
139: EmbeddedLang * /*owner*/ embedded = NULL /*i.e. assume C lexics*/);
140:
141: // clean up
142: ~GrammarLexer();
143:
144: // get current token as a sm_string
145: StringRef curToken() const;
146: int curLen() const { return const_cast<GrammarLexer*>(this)->YYLeng(); }
147:
148: // current token's embedded text
149: StringRef curFuncBody() const;
150: StringRef curDeclBody() const { return curFuncBody(); } // implementation artifact
151: StringRef curDeclName() const;
152:
153: // read the next token and return its code; returns TOK_EOF for end of file;
154: // this function is defined in flex's output source code; this one
155: // *does* return TOK_INCLUDE
156: virtual int yylex();
157:
158: // similar to yylex, but process TOK_INCLUDE internally
159: int yylexInc();
160:
161: // begin an embedded sequence
162: void beginEmbed(char finish, int mode, int initNest = 0)
163: {
164: embedded->reset(initNest);
165: embedFinish = finish;
166: embedMode = mode;
167: }
168:
169: // info about location of current token
170: char const *curFname() const
171: { return sourceLocManager->getFile(tokenStartLoc); }
172: int curLine() const
173: { return sourceLocManager->getLine(tokenStartLoc); }
174: int curCol() const
175: { return sourceLocManager->getCol(tokenStartLoc); }
176: SourceLoc curLoc() const { return tokenStartLoc; }
177: sm_string curLocStr() const; // sm_string with file/line/col
178:
179: // error reporting; called by the lexer code
180: void err(char const *msg) { reportError(msg); } // msg should not include a newline
181: void errorUnterminatedComment();
182: void errorMalformedInclude();
183: void errorIllegalCharacter(char ch);
184:
185: void printError(SourceLoc loc, char const *msg);
186: void printWarning(SourceLoc loc, char const *msg);
187:
188: // for processing includes
189: void recursivelyProcess(char const *fname, std::istream * /*owner*/ source);
190: void popRecursiveFile();
191: bool hasPendingFiles() const;
192:
193: // ReportError funcs
194: virtual void reportError(char const *msg);
195: virtual void reportWarning(char const *msg);
196: };
197:
198:
199: #endif // __GRAMLEX_H
Start C section to elk/ast_locstr.h[1
/1
]
1: #line 1384 "./lpsrc/ast.pak"
2: // locstr.h see license.txt for copyright and terms of use
3: // location & sm_string table reference
4:
5: #ifndef LOCSTR_H
6: #define LOCSTR_H
7:
8: #include <iostream> // ostream
9: #include <cstring> // strlen
10:
11: #include "ast_strtable.h"
12: #include "sm_srcloc.h"
13:
14: class LocString {
15: public: // data
16: SourceLoc loc;
17: StringRef str;
18:
19: public: // funcs
20: LocString();
21: LocString(LocString const &obj);
22: LocString(SourceLoc loc, StringRef str);
23:
24: LocString(Flatten&);
25: void xfer(Flatten &flat);
26:
27: // deallocates its argument; intended for convenient use in bison grammar files
28: EXPLICIT LocString(LocString *obj) { copyAndDel(obj); }
29: void copyAndDel(LocString *obj);
30:
31: // sometimes useful for generating arguments to the above ctor
32: LocString *clone() const;
33:
34: LocString& operator= (LocString const &obj)
35: { loc = obj.loc; str = obj.str; return *this; }
36:
37: // sm_string with location info
38: sm_string locString() const { return toString(loc); }
39:
40: // (read-only) sm_string-like behavior
41: friend std::ostream& operator<< (std::ostream &os, LocString const &loc)
42: { return os << loc.str; }
43: friend sm_stringBuilder& operator<< (sm_stringBuilder &sb, LocString const &loc)
44: { return sb << loc.str; }
45: StringRef strref() const { return str; }
46: operator StringRef () const { return str; }
47: char operator [] (int index) const { return str[index]; }
48: bool equals(char const *other) const; // sm_string comparison
49: int length() const { return strlen(str); }
50:
51: // experimenting with allowing 'str' to be null, which is convenient
52: // when the sm_string table isn't available
53: bool isNull() const { return str == NULL; }
54: bool isNonNull() const { return !isNull(); }
55:
56: bool validLoc() const { return loc != SL_UNKNOWN; }
57: };
58:
59: // yields simply the sm_string, no location info
60: sm_string toString(LocString const &s);
61:
62:
63: // useful for constructing literal sm_strings in source code
64: #define LITERAL_LOCSTRING(str) \
65: LocString(HERE_SOURCELOC, str)
66:
67:
68: #endif // LOCSTR_H
Start C section to elk/ast_reporterr.h[1
/1
]
1: #line 1453 "./lpsrc/ast.pak"
2: // reporterr.h see license.txt for copyright and terms of use
3: // interface for reporting errors and warnings
4:
5: #ifndef REPORTERR_H
6: #define REPORTERR_H
7:
8: class ReportError {
9: public:
10: // report an error; 'str' should not have a newline
11: virtual void reportError(char const *str)=0;
12:
13: // report a warning
14: virtual void reportWarning(char const *str)=0;
15: virtual ~ReportError(){}
16: };
17:
18:
19: // print messages to stdout with "error: " or "warning: " prepended
20: class SimpleReportError : public ReportError {
21: public:
22: virtual void reportError(char const *str);
23: virtual void reportWarning(char const *str);
24: };
25:
26: extern SimpleReportError simpleReportError;
27:
28:
29: // throw away messages
30: class SilentReportError : public ReportError {
31: public:
32: virtual void reportError(char const *str);
33: virtual void reportWarning(char const *str);
34: };
35:
36: extern SilentReportError silentReportError;
37:
38:
39:
40: #endif // REPORTERR_H
Start C section to elk/ast_strtable.h[1
/1
]
1: #line 1494 "./lpsrc/ast.pak"
2: // strtable.h see license.txt for copyright and terms of use
3: // implements a collection of immutable sm_strings with unique representatives
4:
5: #ifndef STRTABLE_H
6: #define STRTABLE_H
7:
8: #include "sm_strhash.h"
9:
10: // fwd
11: class Flatten;
12:
13: // global sm_string table for use during flattening/unflattening;
14: // it's up to clients to manage this ptr, as this module doesn't
15: // do anything besides define it into existence
16: // (this isn't the ideal solution..)
17: extern class StringTable *flattenStrTable;
18:
19:
20: // the type of references to sm_strings in a sm_string table; the pointer
21: // can be used directly in equality comparisons, because several calls
22: // to 'add' return the same pointer; and it points to the represented
23: // sm_string (null-terminated), so it can be printed directly, etc.
24: typedef char const *StringRef;
25:
26:
27: class StringTable {
28: private: // types
29: // constants
30: enum {
31: rackSize = 16000, // size of one rack
32: longThreshold = 1000, // minimum length of a "long" sm_string
33: };
34:
35: // some of the sm_strings stored in the table
36: struct Rack {
37: Rack *next; // (owner) next rack, if any; for deallocation
38: int usedBytes; // # of bytes of 'data' that are used
39: char data[rackSize]; // data where sm_strings are stored
40:
41: public:
42: Rack(Rack *n) : next(n), usedBytes(0) {}
43: int availBytes() const { return rackSize - usedBytes; }
44: char *nextByte() { return data + usedBytes; }
45: };
46:
47: // stores long sm_strings
48: struct LongString {
49: LongString *next; // (owner) next long sm_string
50: char *data; // (owner) sm_string data, any length (null terminated)
51:
52: public:
53: LongString(LongString *n, char *d) : next(n), data(d) {}
54: };
55:
56: private: // data
57: // hash table mapping sm_strings to pointers into one
58: // of the sm_string racks
59: StringHash hash;
60:
61: // linked list of racks; only walked at dealloc time; we add new
62: // sm_strings to the first rack, and prepend a new one if necessary;
63: // 'racks' is never null
64: Rack *racks;
65:
66: // similar for long sm_strings
67: LongString *longStrings;
68:
69: private: // funcs
70: // not allowed
71: StringTable(StringTable&);
72: void operator=(StringTable&);
73: void operator==(StringTable&);
74:
75: // for mapping data to keys, in the hashtable
76: static char const *identity(void *data);
77:
78: public: // funcs
79: StringTable();
80: ~StringTable();
81:
82: // throw away everything in this table
83: void clear();
84:
85: // add 'src' to the table, if it isn't already there; return a
86: // unique representative, such that multiple calls to 'add' with
87: // the same sm_string contents will always yield the same value
88: StringRef add(char const *src);
89:
90: // some syntactic sugar
91: StringRef operator() (char const *src) { return add(src); }
92:
93: // if 'src' is in the table, return its representative; if not,
94: // return NULL
95: StringRef get(char const *src) const;
96:
97: // similar functions for sm_strings with specified lengths
98: // this doesn't work because the underlying hash table interface needs null terminators..
99: //StringRef add(char const *src, int len);
100: //StringRef get(char const *src, int len) const;
101:
102: // read/write binary
103: void xfer(Flatten &flat, StringRef &ref);
104: };
105:
106:
107: #endif // STRTABLE_H
108:
Start cpp section to elk/ast_ast.ast.cpp[1
/1
]
1: #line 1603 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7:
8:
9:
10:
11: ASTSpecFile::~ASTSpecFile()
12: {
13: forms.deleteAll();
14: }
15:
16: void ASTSpecFile::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
17: {
18: PRINT_HEADER(subtreeName, ASTSpecFile);
19:
20: PRINT_LIST(ToplevelForm, forms);
21: }
22:
23: ASTSpecFile *ASTSpecFile::clone() const
24: {
25: ASTSpecFile *ret = new ASTSpecFile(
26: cloneASTList(forms)
27: );
28: return ret;
29: }
30:
31:
32:
33:
34: ToplevelForm::~ToplevelForm()
35: {
36: }
37:
38: char const * const ToplevelForm::kindNames[ToplevelForm::NUM_KINDS] = {
39: "TF_verbatim",
40: "TF_impl_verbatim",
41: "TF_class",
42: "TF_option",
43: "TF_enum",
44: };
45:
46: void ToplevelForm::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
47: {
48: }
49:
50: DEFN_AST_DOWNCASTS(ToplevelForm, TF_verbatim, TF_VERBATIM)
51:
52: TF_verbatim::~TF_verbatim()
53: {
54: }
55:
56: void TF_verbatim::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
57: {
58: PRINT_HEADER(subtreeName, TF_verbatim);
59:
60: ToplevelForm::debugPrint(os, indent, subtreeName);
61:
62: PRINT_STRING(code);
63: }
64:
65: TF_verbatim *TF_verbatim::clone() const
66: {
67: TF_verbatim *ret = new TF_verbatim(
68: code
69: );
70: return ret;
71: }
72:
73: DEFN_AST_DOWNCASTS(ToplevelForm, TF_impl_verbatim, TF_IMPL_VERBATIM)
74:
75: TF_impl_verbatim::~TF_impl_verbatim()
76: {
77: }
78:
79: void TF_impl_verbatim::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
80: {
81: PRINT_HEADER(subtreeName, TF_impl_verbatim);
82:
83: ToplevelForm::debugPrint(os, indent, subtreeName);
84:
85: PRINT_STRING(code);
86: }
87:
88: TF_impl_verbatim *TF_impl_verbatim::clone() const
89: {
90: TF_impl_verbatim *ret = new TF_impl_verbatim(
91: code
92: );
93: return ret;
94: }
95:
96: DEFN_AST_DOWNCASTS(ToplevelForm, TF_class, TF_CLASS)
97:
98: TF_class::~TF_class()
99: {
100: delete super;
101: ctors.deleteAll();
102: }
103:
104: void TF_class::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
105: {
106: PRINT_HEADER(subtreeName, TF_class);
107:
108: ToplevelForm::debugPrint(os, indent, subtreeName);
109:
110: PRINT_SUBTREE(super);
111: PRINT_LIST(ASTClass, ctors);
112: }
113:
114: TF_class *TF_class::clone() const
115: {
116: TF_class *ret = new TF_class(
117: super? super->clone() : NULL,
118: cloneASTList(ctors)
119: );
120: return ret;
121: }
122:
123: DEFN_AST_DOWNCASTS(ToplevelForm, TF_option, TF_OPTION)
124:
125: TF_option::~TF_option()
126: {
127: while (args.isNotEmpty()) {
128: args.removeFirst();
129: }
130: }
131:
132: void TF_option::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
133: {
134: PRINT_HEADER(subtreeName, TF_option);
135:
136: ToplevelForm::debugPrint(os, indent, subtreeName);
137:
138: PRINT_STRING(name);
139: PRINT_LIST(sm_string, args);
140: }
141:
142: TF_option *TF_option::clone() const
143: {
144: TF_option *ret = new TF_option(
145: name,
146: shallowCloneASTList(args)
147: );
148: return ret;
149: }
150:
151: DEFN_AST_DOWNCASTS(ToplevelForm, TF_enum, TF_ENUM)
152:
153: TF_enum::~TF_enum()
154: {
155: while (enumerators.isNotEmpty()) {
156: enumerators.removeFirst();
157: }
158: }
159:
160: void TF_enum::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
161: {
162: PRINT_HEADER(subtreeName, TF_enum);
163:
164: ToplevelForm::debugPrint(os, indent, subtreeName);
165:
166: PRINT_STRING(name);
167: PRINT_LIST(sm_string, enumerators);
168: }
169:
170: TF_enum *TF_enum::clone() const
171: {
172: TF_enum *ret = new TF_enum(
173: name,
174: shallowCloneASTList(enumerators)
175: );
176: return ret;
177: }
178:
179:
180:
181:
182: ASTClass::~ASTClass()
183: {
184: args.deleteAll();
185: bases.deleteAll();
186: decls.deleteAll();
187: }
188:
189: void ASTClass::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
190: {
191: PRINT_HEADER(subtreeName, ASTClass);
192:
193: PRINT_STRING(name);
194: PRINT_LIST(CtorArg, args);
195: PRINT_LIST(BaseClass, bases);
196: PRINT_LIST(Annotation, decls);
197: }
198:
199: ASTClass *ASTClass::clone() const
200: {
201: ASTClass *ret = new ASTClass(
202: name,
203: cloneASTList(args),
204: cloneASTList(bases),
205: cloneASTList(decls)
206: );
207: return ret;
208: }
209:
210:
211:
212:
213: AccessMod::~AccessMod()
214: {
215: while (mods.isNotEmpty()) {
216: mods.removeFirst();
217: }
218: }
219:
220: void AccessMod::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
221: {
222: PRINT_HEADER(subtreeName, AccessMod);
223:
224: PRINT_GENERIC(acc);
225: PRINT_LIST(sm_string, mods);
226: }
227:
228: AccessMod *AccessMod::clone() const
229: {
230: AccessMod *ret = new AccessMod(
231: acc,
232: shallowCloneASTList(mods)
233: );
234: return ret;
235: }
236:
237:
238:
239:
240: Annotation::~Annotation()
241: {
242: }
243:
244: char const * const Annotation::kindNames[Annotation::NUM_KINDS] = {
245: "UserDecl",
246: "CustomCode",
247: };
248:
249: void Annotation::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
250: {
251: }
252:
253: DEFN_AST_DOWNCASTS(Annotation, UserDecl, USERDECL)
254:
255: UserDecl::~UserDecl()
256: {
257: delete amod;
258: }
259:
260: void UserDecl::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
261: {
262: PRINT_HEADER(subtreeName, UserDecl);
263:
264: Annotation::debugPrint(os, indent, subtreeName);
265:
266: PRINT_SUBTREE(amod);
267: PRINT_STRING(code);
268: PRINT_STRING(init);
269: }
270:
271: UserDecl *UserDecl::clone() const
272: {
273: UserDecl *ret = new UserDecl(
274: amod? amod->clone() : NULL,
275: code,
276: init
277: );
278: return ret;
279: }
280:
281: DEFN_AST_DOWNCASTS(Annotation, CustomCode, CUSTOMCODE)
282:
283: CustomCode::~CustomCode()
284: {
285: }
286:
287: void CustomCode::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
288: {
289: PRINT_HEADER(subtreeName, CustomCode);
290:
291: Annotation::debugPrint(os, indent, subtreeName);
292:
293: PRINT_STRING(qualifier);
294: PRINT_STRING(code);
295: }
296:
297: CustomCode *CustomCode::clone() const
298: {
299: CustomCode *ret = new CustomCode(
300: qualifier,
301: code
302: );
303: return ret;
304: }
305:
306:
307:
308:
309: CtorArg::~CtorArg()
310: {
311: }
312:
313: void CtorArg::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
314: {
315: PRINT_HEADER(subtreeName, CtorArg);
316:
317: PRINT_BOOL(isOwner);
318: PRINT_STRING(type);
319: PRINT_STRING(name);
320: PRINT_STRING(defaultValue);
321: }
322:
323: CtorArg *CtorArg::clone() const
324: {
325: CtorArg *ret = new CtorArg(
326: isOwner,
327: type,
328: name,
329: defaultValue
330: );
331: return ret;
332: }
333:
334:
335:
336:
337: BaseClass::~BaseClass()
338: {
339: }
340:
341: void BaseClass::debugPrint(std::ostream &os, int indent, char const *subtreeName) const
342: {
343: PRINT_HEADER(subtreeName, BaseClass);
344:
345: PRINT_GENERIC(access);
346: PRINT_STRING(name);
347: }
348:
349: BaseClass *BaseClass::clone() const
350: {
351: BaseClass *ret = new BaseClass(
352: access,
353: name
354: );
355: return ret;
356: }
357:
358:
359:
360:
361:
362:
363:
364: sm_string toString(AccessCtl acc)
365: {
366: char const *arr[] = {
367: "public",
368: "private",
369: "protected",
370: "ctor",
371: "dtor",
372: "pure_virtual"
373: };
374: STATIC_ASSERT(TABLESIZE(arr) == NUM_ACCESSCTLS);
375: xassert((unsigned)acc < NUM_ACCESSCTLS);
376: return sm_string(arr[acc]);
377: }
378:
379: sm_string ASTClass::classKindName() const
380: {
381: sm_string ret = sm_stringToupper(name);
382: if (ret == name) {
383:
384:
385:
386:
387: ret &= "KIND_";
388: }
389: return ret;
390: }
391:
392: bool AccessMod::hasMod(char const *mod) const
393: {
394: FOREACH_ASTLIST(sm_string, mods, iter) {
395: if (iter.data()->equals(mod)) {
396: return true;
397: }
398: }
399: return false;
400: }
401:
402:
403:
Start cpp section to elk/ast_asthelp.cpp[1
/1
]
1: #line 2007 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7:
8:
9: std::ostream &ind(std::ostream &os, int indent)
10: {
11: while (indent--) {
12: os << " ";
13: }
14: return os;
15: }
16:
17:
18: void debugPrintStr(sm_string const &s, char const *name,
19: std::ostream &os, int indent)
20: {
21: ind(os, indent) << name << " = " << quoted(s) << "\n";
22: }
23:
24:
25: template <class STR>
26: void debugPrintStringList(ASTList<STR> const &list, char const *name,
27: std::ostream &os, int indent)
28: {
29: ind(os, indent) << name << ": ";
30: {
31: int ct=0;
32: FOREACH_ASTLIST(STR, list, iter) {
33: if (ct++ > 0) {
34: os << ", ";
35: }
36: os << quoted(*( iter.data() ));
37: }
38: }
39: os << "\n";
40: }
41:
42:
43: void debugPrintList(ASTList<sm_string> const &list, char const *name,
44: std::ostream &os, int indent)
45: {
46: debugPrintStringList(list, name, os, indent);
47: }
48:
49: void debugPrintList(ASTList<LocString> const &list, char const *name,
50: std::ostream &os, int indent)
51: {
52: debugPrintStringList(list, name, os, indent);
53: }
54:
55:
56:
57: void xmlPrintStr(sm_string const &s, char const *name,
58: std::ostream &os, int indent)
59: {
60: ind(os, indent) << "<member type=sm_string name = \"" << name << "\">\n";
61:
62: ind(os, indent+2) << "<value type=sm_string val=\"" << quoted(s) << "\" />\n";
63: ind(os, indent) << "</member>\n";
64: }
65:
66:
67: template <class STR>
68: void xmlPrintStringList(ASTList<STR> const &list, char const *name,
69: std::ostream &os, int indent)
70: {
71: ind(os, indent) << "<member type=sm_stringList name = \"" << name << "\">\n";
72: {
73: FOREACH_ASTLIST(STR, list, iter) {
74:
75: ind(os, indent+2) << "<object type=sm_string val=\"" << quoted(*( iter.data() )) << "\" />\n";
76: }
77: }
78: ind(os, indent) << "</member>\n";
79: }
80:
81:
82: void xmlPrintList(ASTList<sm_string> const &list, char const *name,
83: std::ostream &os, int indent)
84: {
85: xmlPrintStringList(list, name, os, indent);
86: }
87:
88: void xmlPrintList(ASTList<LocString> const &list, char const *name,
89: std::ostream &os, int indent)
90: {
91: xmlPrintStringList(list, name, os, indent);
92: }
Start cpp section to elk/ast_ccsstr.cpp[1
/1
]
1: #line 2100 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15: CCSubstrate::CCSubstrate(ReportError *err)
16: : EmbeddedLang(err)
17: {
18: reset();
19: }
20:
21: void CCSubstrate::reset(int initNest)
22: {
23: state = ST_NORMAL;
24: nesting = initNest;
25: backslash = false;
26: star = false;
27: text.setlength(0);
28: }
29:
30:
31: CCSubstrate::~CCSubstrate()
32: {}
33:
34:
35: void CCSubstrate::handle(char const *str, int len, char finalDelim)
36: {
37: text.append(str, len);
38:
39: for (; len>0; len--,str++) {
40: switch (state) {
41: case ST_NORMAL:
42: switch (*str) {
43: case '{':
44: case '(':
45: case '[':
46: nesting++;
47: break;
48:
49: case '}':
50: case ')':
51: case ']':
52: if (nesting == 0) {
53: err->reportError(sm_stringc
54: << "unexpected closing delimiter `" << *str
55: << "' -- probably due to missing `" << finalDelim << "'");
56: }
57: else {
58: nesting--;
59: }
60: break;
61:
62: case '\"':
63: state = ST_STRING;
64: break;
65:
66: case '\'':
67: state = ST_CHAR;
68: break;
69:
70: case '/':
71: state = ST_SLASH;
72: break;
73: }
74: break;
75:
76: case ST_STRING:
77: case ST_CHAR:
78: if (!backslash) {
79: if ((state == ST_STRING && *str == '\"') ||
80: (state == ST_CHAR && *str == '\'')) {
81: state = ST_NORMAL;
82: }
83: else if (*str == '\\') {
84: backslash = true;
85: }
86: else if (*str == '\n') {
87: err->reportError("unterminated sm_string or char literal");
88: }
89: }
90: else {
91: backslash = false;
92: }
93: break;
94:
95: case ST_SLASH:
96: if (*str == '*') {
97: state = ST_C_COMMENT;
98: }
99: else if (*str == '/') {
100: state = ST_CC_COMMENT;
101: }
102: else {
103: state = ST_NORMAL;
104: }
105: break;
106:
107: case ST_C_COMMENT:
108: if (!star) {
109: if (*str == '*') {
110: star = true;
111: }
112: }
113: else {
114: star = false;
115: if (*str == '/') {
116: state = ST_NORMAL;
117: }
118: }
119: break;
120:
121: case ST_CC_COMMENT:
122:
123:
124: if (*str == '\n') {
125: state = ST_NORMAL;
126: }
127: break;
128:
129: default:
130: xfailure("unknown state");
131: }
132: }
133: }
134:
135:
136: bool CCSubstrate::zeroNesting() const
137: {
138: return (state == ST_NORMAL || state == ST_SLASH) &&
139: nesting == 0;
140: }
141:
142:
143: sm_string CCSubstrate::getFuncBody() const
144: {
145: if (isDeclaration) {
146:
147:
148:
149: return text;
150: }
151: else if (exprOnly) {
152: return sm_stringc << "return " << text << ";";
153: }
154: else {
155: return text;
156: }
157: }
158:
159:
160: sm_string CCSubstrate::getDeclName() const
161: {
162:
163:
164: char const *start = text.pcharc();
165: char const *p = start;
166:
167:
168: while (*p && *p!='(') { p++; }
169: if (!*p) {
170: xformat("missing '('");
171: }
172: if (p == start) {
173: xformat("missing name");
174: }
175:
176:
177: p--;
178: while (p>=start && isspace(*p)) { p--; }
179: if (p<start) {
180: xformat("missing name");
181: }
182: char const *nameEnd = p+1;
183:
184:
185: while (p>=start &&
186: (isalnum(*p) || *p=='_'))
187: { p--; }
188: p++;
189:
190:
191: return sm_string(p, nameEnd-p);
192: }
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203: class Test {
204: public:
205: void feed(CC &cc, char const *src);
206: void test(char const *src, CC::State state, int nesting, bool flag);
207: void normal(char const *src, int nesting);
208: void str(char const *src, int nesting, bool bs);
209: void yes(char const *src);
210: void no(char const *src);
211: void name(char const *body, char const *n);
212: void badname(char const *body);
213: int main();
214: };
215:
216:
217:
218:
219: void Test::feed(CC &cc, char const *src)
220: {
221:
222: while (*src) {
223:
224: int len = min(strlen(src), 10);
225: cc.handle(src, len, '}');
226: src += len;
227: }
228: }
229:
230:
231: void Test::test(char const *src, CC::State state, int nesting, bool flag)
232: {
233: CC cc(&silentReportError);
234: feed(cc, src);
235:
236: if (!( cc.state == state &&
237: cc.nesting == nesting &&
238: (state==CC::ST_C_COMMENT? cc.star==flag :
239: cc.backslash==flag) )) {
240: xfailure(sm_stringc << "failed on src: " << src);
241: }
242: }
243:
244:
245: void Test::normal(char const *src, int nesting)
246: {
247: test(src, CC::ST_NORMAL, nesting, false);
248: }
249:
250: void Test::str(char const *src, int nesting, bool bs)
251: {
252: test(src, CC::ST_STRING, nesting, bs);
253:
254:
255: sm_string another = replace(src, "\"", "\'");
256: test(another, CC::ST_CHAR, nesting, bs);
257: }
258:
259:
260: void Test::yes(char const *src)
261: {
262: CC cc(&silentReportError);
263: feed(cc, src);
264:
265: xassert(cc.zeroNesting());
266: }
267:
268: void Test::no(char const *src)
269: {
270: CC cc(&silentReportError);
271: feed(cc, src);
272:
273: xassert(!cc.zeroNesting());
274: }
275:
276: void Test::name(char const *body, char const *n)
277: {
278: CC cc(&silentReportError);
279: feed(cc, body);
280: xassert(cc.getDeclName().equals(n));
281: }
282:
283: void Test::badname(char const *body)
284: {
285: CC cc(&silentReportError);
286: feed(cc, body);
287: try {
288: cc.getDeclName();
289: xfailure("got a name when it shoudn't have!");
290: }
291: catch (...)
292: {}
293: }
294:
295:
296: int Test::main()
297: {
298:
299: xBase::logExceptions = false;
300:
301: normal("int main()", 0);
302: normal("int main() { hi", 1);
303: normal("int main() { hi {", 2);
304: normal("int main() { hi { foo[5", 3);
305: normal("int main() { hi { foo[5] and ", 2);
306: normal("int main() { hi { foo[5] and } bar ", 1);
307: normal("int main() { hi { foo[5] and } bar } baz ", 0);
308:
309: normal("main() { printf(\"hello \\ world\"); ret", 1);
310:
311: normal("()[]{}([{}])", 0);
312: normal("{ ()[]{}([{}]) } ", 0);
313: normal("( ()[]{}([{}]) )", 0);
314: normal("[ ()[]{}([{}]) ]", 0);
315: normal("\"foo\" ()[]{}([{}])", 0);
316:
317: str("main() { printf(\"hello", 2, false);
318: str("main() { printf(\"hello \\", 2, true);
319: str("main() { printf(\"hello \\ world", 2, false);
320: str("main() { printf(\"hello \\ world\", \"hi", 2, false);
321:
322: test("\"a\" 'b' (", CC::ST_NORMAL, 1, false);
323:
324: yes("main() {}");
325: yes("main() { printf(\"foo\", 3, 4 /*yep{*/); }");
326: yes("some // junk {\n more");
327: yes("'\\''");
328: yes("\"\\\"\"");
329: yes("[][][][][]");
330: yes("\"[[[\"");
331: yes("*");
332: yes("/* [ /* [ */");
333:
334: no("\"");
335: no("(");
336: no(" ( /* ) */ ");
337:
338: name("int main()", "main");
339: name("int eval(Environment &env)", "eval");
340: name("man()", "man");
341: badname("(");
342: badname(" (");
343: badname(" ");
344: badname("");
345: badname(")");
346: badname("main");
347:
348: std::cout << "\nccsstr: all tests PASSED\n";
349:
350: return 0;
351: }
352:
353: int main()
354: {
355: Test t;
356: return t.main();
357: }
358:
359:
Start cpp section to elk/ast_embedded.cpp[1
/1
]
1: #line 2460 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7: EmbeddedLang::EmbeddedLang(ReportError *e)
8: : err(e? e : &simpleReportError),
9: text(),
10: exprOnly(false),
11: isDeclaration(false)
12: {}
13:
14: EmbeddedLang::~EmbeddedLang()
15: {}
Start cpp section to elk/ast_gramlex.cpp[1
/1
]
1: #line 2476 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17: ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
18: : NULL)
19:
20:
21:
22: #define yy_current_buffer YY_CURRENT_BUFFER
23: #endif
24:
25:
26:
27: void GrammarLexer::AltReportError::reportError(char const *msg)
28: {
29: lexer.printError(lexer.fileState.loc, msg);
30: }
31:
32: void GrammarLexer::AltReportError::reportWarning(char const *msg)
33: {
34: lexer.printWarning(lexer.fileState.loc, msg);
35: }
36:
37:
38:
39: GrammarLexer::FileState::FileState(char const *filename, std::istream *src)
40: : loc(sourceLocManager->encodeBegin(filename)),
41: source(src),
42: bufstate(NULL)
43: {}
44:
45:
46: GrammarLexer::FileState::~FileState()
47: {
48:
49:
50:
51: }
52:
53:
54: GrammarLexer::FileState::FileState(FileState const &obj)
55: {
56: *this = obj;
57: }
58:
59:
60: GrammarLexer::FileState &GrammarLexer::FileState::
61: operator= (FileState const &obj)
62: {
63: if (this != &obj) {
64: loc = obj.loc;
65: source = obj.source;
66: bufstate = obj.bufstate;
67: }
68: return *this;
69: }
70:
71:
72:
73: GrammarLexer::GrammarLexer(isEmbedTok test, StringTable &strtbl,
74: char const *fname, std::istream *source,
75: EmbeddedLang *userEmb)
76: : yyFlexLexer(source),
77: altReporter(*this),
78: fileState(fname, source),
79: fileStack(),
80: tokenStartLoc(SL_UNKNOWN),
81: embedStart(0),
82: embedFinish(0),
83: embedMode(0),
84: embedded(userEmb? userEmb : new CCSubstrate(&altReporter)),
85: embedTokTest(test),
86: allowInit(false),
87: prevState(0),
88: prevToken(0),
89: integerLiteral(0),
90: sm_stringLiteral(""),
91: includeFileName(""),
92: strtable(strtbl),
93: errors(0)
94: {
95: trace("tmp") << "source is " << source << std::endl;
96:
97:
98:
99:
100: fileState.bufstate = yy_current_buffer;
101: }
102:
103: GrammarLexer::~GrammarLexer()
104: {
105:
106:
107:
108:
109: while (hasPendingFiles()) {
110: popRecursiveFile();
111: }
112:
113:
114:
115:
116:
117:
118:
119:
120:
121: if (fileState.source &&
122: fileState.source != &std::cin) {
123:
124:
125: delete fileState.source;
126:
127: }
128:
129: delete embedded;
130: }
131:
132:
133: int GrammarLexer::yylexInc()
134: {
135:
136: int code = yylex();
137:
138:
139:
140:
141: prevToken = code;
142:
143:
144: if (code == TOK_INCLUDE) {
145: sm_string fname = includeFileName;
146:
147:
148: std::ifstream *in = new std::ifstream(fname);
149: if (!*in) {
150: err(sm_stringc << "unable to open include file `" << fname << "'");
151: }
152: else {
153: recursivelyProcess(fname, in);
154: }
155:
156:
157: return yylexInc();
158: }
159:
160: if (code == TOK_EOF && hasPendingFiles()) {
161: popRecursiveFile();
162: return yylexInc();
163: }
164:
165:
166:
167: if (embedTokTest(code)) {
168: trace("lex") << "yielding embedded (" << code << ") at "
169: << curLocStr() << ": "
170: << curFuncBody() << std::endl;
171: }
172: else {
173: trace("lex") << "yielding token (" << code << ") "
174: << curToken() << " at "
175: << curLocStr() << std::endl;
176: }
177:
178:
179:
180: return code;
181: }
182:
183:
184: StringRef GrammarLexer::curToken() const
185: {
186: return addString(yytext, yyleng);
187: }
188:
189: StringRef GrammarLexer::addString(char *str, int len) const
190: {
191:
192: char wasThere = str[len];
193: if (wasThere) {
194: str[len] = 0;
195: StringRef ret = strtable.add(str);
196: str[len] = wasThere;
197: return ret;
198: }
199: else {
200: return strtable.add(str);
201: }
202: }
203:
204:
205: bool GrammarLexer::embedFinishMatches(char ch) const
206: {
207: return ch == embedFinish ||
208: (allowInit && ch=='=');
209: }
210:
211:
212: StringRef GrammarLexer::curFuncBody() const
213: {
214: return strtable.add(embedded->getFuncBody());
215: }
216:
217:
218: StringRef GrammarLexer::curDeclName() const
219: {
220: return strtable.add(embedded->getDeclName());
221: }
222:
223:
224: sm_string GrammarLexer::curLocStr() const
225: {
226: return toString(curLoc());
227: }
228:
229:
230: void GrammarLexer::reportError(char const *msg)
231: {
232: printError(curLoc(), msg);
233: }
234:
235: void GrammarLexer::printError(SourceLoc loc, char const *msg)
236: {
237: errors++;
238: std::cerr << toString(loc) << ": error: " << msg << std::endl;
239: }
240:
241:
242: void GrammarLexer::reportWarning(char const *msg)
243: {
244: printWarning(curLoc(), msg);
245: }
246:
247: void GrammarLexer::printWarning(SourceLoc loc, char const *msg)
248: {
249: std::cerr << toString(loc) << ": warning: " << msg << std::endl;
250: }
251:
252:
253: void GrammarLexer::errorUnterminatedComment()
254: {
255: err(sm_stringc << "unterminated comment, beginning on line "
256: << sourceLocManager->getLine(tokenStartLoc));
257: }
258:
259: void GrammarLexer::errorMalformedInclude()
260: {
261: err(sm_stringc << "malformed include");
262: }
263:
264: void GrammarLexer::errorIllegalCharacter(char ch)
265: {
266: err(sm_stringc << "illegal character: `" << ch << "'");
267: }
268:
269:
270: void GrammarLexer::recursivelyProcess(char const *fname, std::istream *source)
271: {
272: trace("lex") << "recursively processing " << fname << std::endl;
273:
274:
275:
276: fileState.bufstate = yy_current_buffer;
277: xassert(fileState.bufstate);
278:
279:
280: fileStack.prepend(new FileState(fileState));
281:
282:
283: fileState = FileState(fname, source);
284:
285:
286:
287: fileState.bufstate = yy_create_buffer(source, lexBufferSize);
288:
289:
290: yy_switch_to_buffer(fileState.bufstate);
291: }
292:
293:
294: void GrammarLexer::popRecursiveFile()
295: {
296: trace("lex") << "done processing " <<
297: sourceLocManager->getFile(fileState.loc) << std::endl;
298:
299:
300:
301:
302: xassert(hasPendingFiles());
303:
304:
305: yy_delete_buffer(fileState.bufstate);
306: delete fileState.source;
307:
308:
309: FileState *st = fileStack.removeAt(0);
310: fileState = *st;
311: delete st;
312:
313:
314: yy_switch_to_buffer(fileState.bufstate);
315: }
316:
317:
318: bool GrammarLexer::hasPendingFiles() const
319: {
320: return fileStack.isNotEmpty();
321: }
322:
323:
324:
325: #ifdef TEST_GRAMLEX
326:
327:
328: bool isGramlexEmbed(int code);
329:
330: int main(int argc)
331: {
332: SourceLocManager mgr;
333: GrammarLexer lexer(isGramlexEmbed);
334: traceAddSys("lex");
335:
336: std::cout << "go!\n";
337:
338: while (1) {
339:
340: int code = argc==1? lexer.yylexInc() : lexer.yylex();
341: if (code == 0) {
342: break;
343: }
344:
345: else if (isGramlexEmbed(code)) {
346: std::cout << "embedded code at " << lexer.curLocStr()
347: << ": " << lexer.curFuncBody()
348: << std::endl;
349: }
350:
351: else if (code == TOK_INCLUDE) {
352:
353: std::cout << "include at " << lexer.curLocStr()
354: << ": filename is `" << lexer.includeFileName.pcharc()
355: << "'\n";
356: }
357:
358: else {
359: std::cout << "token at " << lexer.curLocStr()
360: << ": code=" << code
361: << ", text: " << lexer.curToken().pcharc()
362: << std::endl;
363: }
364: }
365:
366: return 0;
367: }
368:
369: #endif
Start cpp section to elk/ast_locstr.cpp[1
/1
]
1: #line 2846 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7: LocString::LocString()
8: : loc(SL_UNKNOWN),
9: str(NULL)
10: {}
11:
12: LocString::LocString(LocString const &obj)
13: : loc(obj.loc),
14: str(obj.str)
15: {}
16:
17: LocString::LocString(SourceLoc L, StringRef s)
18: : loc(L),
19: str(s)
20: {}
21:
22:
23: LocString::LocString(Flatten&)
24: : loc(SL_UNKNOWN), str(NULL)
25: {}
26:
27: void LocString::xfer(Flatten &flat)
28: {
29:
30:
31:
32:
33:
34:
35:
36: xassert(flattenStrTable);
37: flattenStrTable->xfer(flat, str);
38: }
39:
40:
41: void LocString::copyAndDel(LocString *obj)
42: {
43: loc = obj->loc;
44: str = obj->str;
45: delete obj;
46: }
47:
48: LocString *LocString::clone() const
49: {
50: return new LocString(*this);
51: }
52:
53:
54: bool LocString::equals(char const *other) const
55: {
56: if (!str) {
57: return !other;
58: }
59: else {
60: return other && 0==strcmp(str, other);
61: }
62: }
63:
64: sm_string toString(LocString const &s)
65: {
66: return sm_string(s.str);
67: }
Start cpp section to elk/ast_reporterr.cpp[1
/1
]
1: #line 2914 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7:
8:
9:
10:
11: void SimpleReportError::reportError(char const *str)
12: {
13: std::cout << "error: " << str << std::endl;
14: }
15:
16: void SimpleReportError::reportWarning(char const *str)
17: {
18: std::cout << "warning: " << str << std::endl;
19: }
20:
21: SimpleReportError simpleReportError;
22:
23:
24:
25: void SilentReportError::reportError(char const *str)
26: {}
27:
28: void SilentReportError::reportWarning(char const *str)
29: {}
30:
31: SilentReportError silentReportError;
32:
33:
34:
Start cpp section to elk/ast_strtable.cpp[1
/1
]
1: #line 2949 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12: StringTable *flattenStrTable = NULL;
13:
14:
15: STATICDEF char const *StringTable::identity(void *data)
16: {
17: return (char const*)data;
18: }
19:
20:
21: StringTable::StringTable()
22: : hash(identity),
23: racks(NULL),
24: longStrings(NULL)
25: {}
26:
27:
28: StringTable::~StringTable()
29: {
30: clear();
31: }
32:
33: void StringTable::clear()
34: {
35: hash.empty();
36:
37: while (racks != NULL) {
38: Rack *temp = racks;
39: racks = racks->next;
40: delete temp;
41: }
42:
43: while (longStrings != NULL) {
44: LongString *temp = longStrings;
45: longStrings = longStrings->next;
46: delete temp->data;
47: delete temp;
48: }
49: }
50:
51:
52: StringRef StringTable::add(char const *src)
53: {
54:
55: StringRef ret = get(src);
56: if (ret) {
57: return ret;
58: }
59:
60: int len = strlen(src)+1;
61:
62:
63: if (len >= longThreshold) {
64: char *d = new char[len];
65: ret = d;
66: memcpy(d, src, len);
67:
68:
69: longStrings = new LongString(longStrings, d);
70: }
71:
72: else {
73:
74: if (!racks || len > racks->availBytes()) {
75:
76: xassert(len <= rackSize);
77: racks = new Rack(racks);
78: }
79:
80:
81: ret = racks->nextByte();
82: memcpy(racks->nextByte(), src, len);
83: racks->usedBytes += len;
84: }
85:
86:
87: hash.add(ret, (void*)ret);
88:
89: return ret;
90: }
91:
92:
93: StringRef StringTable::get(char const *src) const
94: {
95: return (StringRef)hash.get(src);
96: }
97:
98:
99:
100: void StringTable::xfer(Flatten &flat, StringRef &ref)
101: {
102: if (flat.reading()) {
103:
104: char *str;
105: flat.xferCharString(str);
106:
107: if (str) {
108:
109: ref = add(str);
110:
111:
112: delete str;
113: }
114: else {
115:
116: ref = NULL;
117: }
118: }
119:
120: else {
121:
122:
123: flat.xferCharString(const_cast<char*&>(ref));
124: }
125: }
Start cpp section to elk/ast_towner.cpp[1
/1
]
1: #line 3075 "./lpsrc/ast.pak"
2:
3:
4:
5:
6:
7:
8: class Foo;
9: void someCrap(Foo *f)
10: {
11:
12:
13:
14:
15: }
16:
17:
18:
19: class Foo {
20: public:
21: static int count;
22: int x;
23:
24: public:
25: Foo(int a);
26: ~Foo();
27: };
28:
29: int Foo::count = 0;
30:
31: Foo::Foo(int ax)
32: : x(ax)
33: {
34: printf("created Foo at %p\n", this);
35: count++;
36: }
37:
38: Foo::~Foo()
39: {
40: printf("destroying Foo at %p\n", this);
41: count--;
42: }
43:
44:
45: void printFoo(Foo *f)
46: {
47: printf("Foo at %p, x=%d\n", f, f? f->x : 0);
48: }
49:
50: void printFooC(Foo const *f)
51: {
52: printf("const Foo at %p, x=%d\n", f, f? f->x : 0);
53: }
54:
55: void printInt(int x)
56: {
57: printf("int x is %d\n", x);
58: }
59:
60:
61:
62: void test1()
63: {
64: printf("----------- test1 -----------\n");
65: Owner<Foo> f;
66: f = new Foo(4);
67: }
68:
69:
70: void test2()
71: {
72: printf("----------- test2 -----------\n");
73: Owner<Foo> f(new Foo(6));
74:
75: printFoo(f);
76: (*f).x = 9;
77: f->x = 12;
78: }
79:
80:
81: void test3()
82: {
83: printf("----------- test3 -----------\n");
84: Owner<Foo> f(new Foo(8));
85: Owner<Foo> const &g = f;
86:
87: printFooC(g);
88: printInt((*g).x);
89: printInt(g->x);
90: }
91:
92:
93: void test4()
94: {
95: printf("----------- test4 -----------\n");
96:
97: Owner<Foo> f(new Foo(3));
98: Owner<Foo> g;
99: g = f;
100: printFoo(f);
101: f = g.xfr();
102: printFoo(g);
103: }
104:
105:
106: int main()
107: {
108: test1();
109: test2();
110: test3();
111: test4();
112:
113: printf("%d Foos leaked\n", Foo::count);
114: return Foo::count;
115: }
116: