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: 
End data section to licences/ast_licence.txt[1]
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
End C section to elk/ast_ast.ast.h[1]
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
End C section to elk/ast_ast.hand.h[1]
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
End C section to elk/ast_asthelp.h[1]
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
End C section to elk/ast_ccsstr.h[1]
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
End C section to elk/ast_embedded.h[1]
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
End C section to elk/ast_fakelist.h[1]
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
End C section to elk/ast_gramlex.h[1]
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
End C section to elk/ast_locstr.h[1]
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
End C section to elk/ast_reporterr.h[1]
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: 
End C section to elk/ast_strtable.h[1]
Start cpp section to elk/ast_ast.ast.cpp[1 /1 ]
     1: #line 1603 "./lpsrc/ast.pak"
     2: // ast.ast.cc
     3: // *** DO NOT EDIT ***
     4: // generated automatically by astgen, from ast.ast
     5: 
     6: #include "ast_ast.ast.h"
     7: 
     8: 
     9: // ------------------ ASTSpecFile -------------------
    10: // *** DO NOT EDIT ***
    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: // ------------------ ToplevelForm -------------------
    33: // *** DO NOT EDIT ***
    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: // ------------------ ASTClass -------------------
   181: // *** DO NOT EDIT ***
   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: // ------------------ AccessMod -------------------
   212: // *** DO NOT EDIT ***
   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: // ------------------ Annotation -------------------
   239: // *** DO NOT EDIT ***
   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: // ------------------ CtorArg -------------------
   308: // *** DO NOT EDIT ***
   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: // ------------------ BaseClass -------------------
   336: // *** DO NOT EDIT ***
   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: // *** DO NOT EDIT ***
   360: 
   361: 
   362: #include "sm_strutil.h"
   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:     // this simplemindedly avoids collisions with itself, and I think
   384:     // it even avoids collisions with other classes, since if they would
   385:     // collide with this, they'd collide with themselves too, and hence
   386:     // get an extra "KIND_" prepended..
   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;      // not found
   400: }
   401: 
   402: 
   403: 
End cpp section to elk/ast_ast.ast.cpp[1]
Start cpp section to elk/ast_asthelp.cpp[1 /1 ]
     1: #line 2007 "./lpsrc/ast.pak"
     2: // asthelp.cc            see license.txt for copyright and terms of use
     3: // code for what's declared in asthelp.h
     4: 
     5: #include "ast_asthelp.h"
     6: #include "sm_strutil.h"
     7: 
     8: // ----------- debugPrint helpers -----------------------
     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: // ----------- xmlPrint helpers -----------------------
    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:   // dsw: quoted might add another layer of quotes.
    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:       // dsw: quoted might add another layer of quotes.
    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: }
End cpp section to elk/ast_asthelp.cpp[1]
Start cpp section to elk/ast_ccsstr.cpp[1 /1 ]
     1: #line 2100 "./lpsrc/ast.pak"
     2: // ccsstr.cc            see license.txt for copyright and terms of use
     3: // code for ccsstr.h
     4: 
     5: #include "ast_ccsstr.h"
     6: #include "sm_xassert.h"
     7: #include "sm_exc.h"
     8: #include "sm_strutil.h"
     9: #include "ast_reporterr.h"
    10: 
    11: #include <iostream>    // std::cout
    12: #include <ctype.h>       // isspace
    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:         // I don't like the possibility of escaped newlines
   123:         // in C++ comments, so I don't support it (so there!)
   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:     // I used to be appending ';' here, but now I need the flexibility to
   147:     // add additional test before it, so I will rely on the caller to add
   148:     // semicolons where necessary
   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:   // go with the rather inelegant heuristic that the word
   163:   // just before the first '(' is the function's name
   164:   char const *start = text.pcharc();
   165:   char const *p = start;
   166: 
   167:   // find first '('
   168:   while (*p && *p!='(') { p++; }
   169:   if (!*p) {
   170:     xformat("missing '('");
   171:   }
   172:   if (p == start) {
   173:     xformat("missing name");
   174:   }
   175: 
   176:   // skip backward past any whitespace before the '('
   177:   p--;
   178:   while (p>=start && isspace(*p)) { p--; }
   179:   if (p<start) {
   180:     xformat("missing name");
   181:   }
   182:   char const *nameEnd = p+1;    // char just past last
   183: 
   184:   // move backward through the name
   185:   while (p>=start &&
   186:          (isalnum(*p) || *p=='_'))
   187:     { p--; }
   188:   p++;    // move back to most recent legal char
   189: 
   190:   // done
   191:   return sm_string(p, nameEnd-p);
   192: }
   193: 
   194: 
   195: // ------------------ test code -------------------
   196: #ifdef TEST_CCSSTR
   197: 
   198: #define CC CCSubstrate
   199: #define Test CCSubstrateTest
   200: 
   201: // test code is put into a class just so that CCSubstrate
   202: // can grant it access to private fields
   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: #define min(a,b) ((a)<(b)?(a):(b))
   218: 
   219: void Test::feed(CC &cc, char const *src)
   220: {
   221:   //std::cout << "trying: " << src << std::endl;
   222:   while (*src) {
   223:     // feed it in 10 char increments, to test split processing too
   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:   // repeat the test with single-tick
   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:   // quiet!
   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: #endif // TEST_CCSSTR
End cpp section to elk/ast_ccsstr.cpp[1]
Start cpp section to elk/ast_embedded.cpp[1 /1 ]
     1: #line 2460 "./lpsrc/ast.pak"
     2: // embedded.cc            see license.txt for copyright and terms of use
     3: // code for embedded.h
     4: 
     5: #include "ast_embedded.h"
     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: {}
End cpp section to elk/ast_embedded.cpp[1]
Start cpp section to elk/ast_gramlex.cpp[1 /1 ]
     1: #line 2476 "./lpsrc/ast.pak"
     2: // gramlex.cc            see license.txt for copyright and terms of use
     3: // code for gramlex.h
     4: 
     5: #include "ast_gramlex.h"
     6: #include "sm_trace.h"
     7: #include "ast_ccsstr.h"
     8: #include "sm_ckheap.h"
     9: 
    10: #include <fstream>     // std::cout, ifstream
    11: 
    12: 
    13: // workaround for flex-2.5.31
    14: #ifdef FLEX_STD    // detect later versions of flex
    15:   // copied from flex's output
    16:   #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
    17:                             ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
    18:                             : NULL)
    19: 
    20:   // the 'yy_current_buffer' field was replaced by the buffer stack
    21:   // alluded to above
    22:   #define yy_current_buffer YY_CURRENT_BUFFER
    23: #endif // FLEX_STD
    24: 
    25: 
    26: // ----------------- GrammarLexer::AltReportError ---------------
    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: // ----------------- GrammarLexer::FileState --------------------
    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:   // we let ~GrammarLexer take care of deletions here since we
    49:   // have to know what ~yyFlexLexer is going to do, and we
    50:   // don't have enough context here to know that
    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: // ---------------------- GrammarLexer --------------------------
    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),       // same as INITIAL, but this value isn't used
    88:     prevToken(0),       // hack..
    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:   // grab initial buffer object so we can restore it after
    98:   // processing an include file (turns out this doesn't work
    99:   // because it's NULL now; see recursivelyProcess())
   100:   fileState.bufstate = yy_current_buffer;
   101: }
   102: 
   103: GrammarLexer::~GrammarLexer()
   104: {
   105:   // ~yyFlexLexer deletes its current buffer, but not any
   106:   // of the istream sources it's been passed
   107: 
   108:   // first let's unpop any unpopped input files
   109:   while (hasPendingFiles()) {
   110:     popRecursiveFile();
   111:   }
   112: 
   113:   // now delete the original istream source
   114:   //
   115:   // 10/09/04: This used to say "fileState.source != std::cin", but that
   116:   // invokes std::cin.operator void*(), which always returns 0 or -1 in
   117:   // gcc-2.95.3's library.  I believe I intended to compare addresses,
   118:   // though at this point I'm not sure since I don't know where the
   119:   // call sites to the constructor are.  (I found this problem because
   120:   // at one point Elsa (erroneously) choked on this construction.)
   121:   if (fileState.source &&
   122:       fileState.source != &std::cin) {
   123:     //checkHeap();
   124:     //checkHeapNode(fileState.source);   // this is wrong b/c of virtual inheritance..
   125:     delete fileState.source;
   126:     //checkHeap();
   127:   }
   128: 
   129:   delete embedded;
   130: }
   131: 
   132: 
   133: int GrammarLexer::yylexInc()
   134: {
   135:   // get raw token
   136:   int code = yylex();
   137: 
   138:   // save this code for next time; part of what makes this hack
   139:   // problematic is that this assignment is only performed if the
   140:   // client calls 'yylexInc'..
   141:   prevToken = code;
   142: 
   143:   // include processing
   144:   if (code == TOK_INCLUDE) {
   145:     sm_string fname = includeFileName;
   146: 
   147:     // 'in' will be deleted in ~GrammarLexer
   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:     // go to next token (tail recursive)
   157:     return yylexInc();
   158:   }
   159: 
   160:   if (code == TOK_EOF  &&  hasPendingFiles()) {
   161:     popRecursiveFile();
   162:     return yylexInc();
   163:   }
   164: 
   165:   #if 1
   166:   // possible performance problem
   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:   #endif // 0/1
   178: 
   179:   // nothing special
   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:   // write a null terminator temporarily
   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=='=');     // to handle initial value syntax
   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 " //<< commentStartLine);
   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:   // grab current buffer; this is necessary because when we
   275:   // tried to grab it in the ctor it was NULL
   276:   fileState.bufstate = yy_current_buffer;
   277:   xassert(fileState.bufstate);
   278: 
   279:   // push current state
   280:   fileStack.prepend(new FileState(fileState));
   281: 
   282:   // reset current state
   283:   fileState = FileState(fname, source);
   284: 
   285:   // storing this in 'bufstate' is redundant because of the
   286:   // assignment above, but no big deal
   287:   fileState.bufstate = yy_create_buffer(source, lexBufferSize);
   288: 
   289:   // switch underlying lexer over to new file
   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:   // among other things, this prevents us from accidentally deleting
   300:   // flex's first buffer (which it presumably takes care of) or
   301:   // deleting 'std::cin'
   302:   xassert(hasPendingFiles());
   303: 
   304:   // close down stuff associated with current file
   305:   yy_delete_buffer(fileState.bufstate);
   306:   delete fileState.source;
   307: 
   308:   // pop stack
   309:   FileState *st = fileStack.removeAt(0);
   310:   fileState = *st;
   311:   delete st;
   312: 
   313:   // point flex at the new (old) buffer
   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: // defined in gramlex.lex
   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:     // any argument disables include processing
   340:     int code = argc==1? lexer.yylexInc() : lexer.yylex();
   341:     if (code == 0) {  // eof
   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:       // if I use yylexInc above, this is never reached
   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 // TEST_GRAMLEX
End cpp section to elk/ast_gramlex.cpp[1]
Start cpp section to elk/ast_locstr.cpp[1 /1 ]
     1: #line 2846 "./lpsrc/ast.pak"
     2: // locstr.cc            see license.txt for copyright and terms of use
     3: // code for locstr.h
     4: 
     5: #include "ast_locstr.h"
     6: 
     7: LocString::LocString()
     8:   : loc(SL_UNKNOWN),
     9:     str(NULL)           // problem with "" is we don't have the sm_string table here..
    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:   // doh.. flattening locs is hard.  I wasn't even doing
    30:   // it before.  issues:
    31:   //   - don't want to store the file name lots of times
    32:   //   - what if the file goes away, or we're in a different directory?
    33:   //   - what if the file is changed, what loc to use then?
    34:   // so for now I'm punting and not saving the loc at all...
    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;                            // equal if both null
    58:   }
    59:   else {
    60:     return other && 0==strcmp(str, other);    // or same contents
    61:   }
    62: }
    63: 
    64: sm_string toString(LocString const &s)
    65: {
    66:   return sm_string(s.str);
    67: }
End cpp section to elk/ast_locstr.cpp[1]
Start cpp section to elk/ast_reporterr.cpp[1 /1 ]
     1: #line 2914 "./lpsrc/ast.pak"
     2: // reporterr.cc            see license.txt for copyright and terms of use
     3: // code for reporterr.h
     4: 
     5: #include "ast_reporterr.h"
     6: 
     7: #include <iostream>       // std::cout
     8: 
     9: 
    10: // --------------------- SimpleReportError -------------------------
    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: // --------------------- SilentReportError -------------------------
    25: void SilentReportError::reportError(char const *str)
    26: {}
    27: 
    28: void SilentReportError::reportWarning(char const *str)
    29: {}
    30: 
    31: SilentReportError silentReportError;
    32: 
    33: 
    34: // EOF
End cpp section to elk/ast_reporterr.cpp[1]
Start cpp section to elk/ast_strtable.cpp[1 /1 ]
     1: #line 2949 "./lpsrc/ast.pak"
     2: // strtable.cc            see license.txt for copyright and terms of use
     3: // code for strtable.h
     4: 
     5: #include "ast_strtable.h"
     6: #include "sm_xassert.h"
     7: #include "sm_flatten.h"
     8: 
     9: #include <string.h>      // strlen
    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:   // see if it's already here
    55:   StringRef ret = get(src);
    56:   if (ret) {
    57:     return ret;
    58:   }
    59: 
    60:   int len = strlen(src)+1;     // include null terminator
    61: 
    62:   // is it a long sm_string?
    63:   if (len >= longThreshold) {
    64:     char *d = new char[len];
    65:     ret = d;
    66:     memcpy(d, src, len);
    67: 
    68:     // prepend a new long-sm_string entry
    69:     longStrings = new LongString(longStrings, d);
    70:   }
    71: 
    72:   else {
    73:     // see if we need a new rack
    74:     if (!racks || len > racks->availBytes()) {
    75:       // need a new rack
    76:       xassert(len <= rackSize);
    77:       racks = new Rack(racks);     // prepend new rack
    78:     }
    79: 
    80:     // add the sm_string to the last rack
    81:     ret = racks->nextByte();
    82:     memcpy(racks->nextByte(), src, len);
    83:     racks->usedBytes += len;
    84:   }
    85: 
    86:   // enter the intended location into the indexing structures
    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: // for now, just store each instance separately ...
   100: void StringTable::xfer(Flatten &flat, StringRef &ref)
   101: {
   102:   if (flat.reading()) {
   103:     // read the sm_string
   104:     char *str;
   105:     flat.xferCharString(str);
   106: 
   107:     if (str) {
   108:       // add to table
   109:       ref = add(str);
   110: 
   111:       // delete sm_string's storage
   112:       delete str;
   113:     }
   114:     else {
   115:       // was NULL
   116:       ref = NULL;
   117:     }
   118:   }
   119: 
   120:   else {
   121:     // copy it to disk
   122:     // since we're writing, the cast is ok
   123:     flat.xferCharString(const_cast<char*&>(ref));
   124:   }
   125: }
End cpp section to elk/ast_strtable.cpp[1]
Start cpp section to elk/ast_towner.cpp[1 /1 ]
     1: #line 3075 "./lpsrc/ast.pak"
     2: // towner.cc            see license.txt for copyright and terms of use
     3: // test owner stuff
     4: 
     5: #include "sm_owner.h"
     6: #include <stdio.h>    // printf
     7: 
     8: class Foo;
     9: void someCrap(Foo *f)
    10: {
    11:   //delete f;
    12:   // good -- egcs-1.1.2 doesn't allow this, so I won't accidentally
    13:   // get destructors missed because of forward decls (like could
    14:   // happen with Borland)
    15: }
    16: 
    17: 
    18: // a simple class to play with
    19: class Foo {
    20: public:
    21:   static int count;    // # of Foos there are
    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: // make it, forget to free it
    62: void test1()
    63: {
    64:   printf("----------- test1 -----------\n");
    65:   Owner<Foo> f;
    66:   f = new Foo(4);
    67: }
    68: 
    69: // access all of the operators as non-const
    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: // access all of the operators as const
    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);      // egcs-1.1.2 allows this for non-const operator fn!!!
    89:   printInt(g->x);
    90: }
    91: 
    92: // test exchange of ownership
    93: void test4()
    94: {
    95:   printf("----------- test4 -----------\n");
    96:   //Owner<Foo> f = new Foo(3);     // egcs-1.1.2 does the wrong thing here
    97:   Owner<Foo> f(new Foo(3));
    98:   Owner<Foo> g;
    99:   g = f;
   100:   printFoo(f);    // should be null
   101:   f = g.xfr();
   102:   printFoo(g);    // should be null
   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: 
End cpp section to elk/ast_towner.cpp[1]