// ast.ast see license.txt for copyright and terms of use // ast definition for an ast definition verbatim { #include "str.h" // string // this signals to ast.hand.cc that ast.ast.cc is nonempty, // so none of the bootstrap code in ast.hand.cc should be used #define GENERATED_AST_PRESENT } // the entire specification class ASTSpecFile (ASTList forms); class ToplevelForm { // code to be copied verbatim into the generated .h file -> TF_verbatim(string code); // code to be copied verbatim into the generated .cc file -> TF_impl_verbatim(string code); // a superclass, and a list of subclasses ("constructors") -> TF_class(ASTClass super, ASTList ctors) { public bool hasChildren() const { return ctors.isNotEmpty(); }; } // a generic option: first word specifies the kind of option, and // additional words (if any) are arguments -> TF_option(string name, ASTList args); // generic custom/verbatim code -> TF_custom(CustomCode cust); // enumeration (at one point I had support for explicit enumerator // values, but decided that if the user wants that, they should put // the enum in a 'verbatim' section instead) -> TF_enum(string name, ASTList enumerators); } // a definition of a grammar terminal or nonterminal class ASTClass (string name, ASTList args, ASTList lastArgs, // only for nonterminal ASTList bases, ASTList decls) { // the name of the enum constant denoting this ctor, as distinguished // from its sibling ctors public string classKindName() const; } verbatim { // specifies what kind of userdecl this is; pub/priv/prot are uninterpreted // class members with the associated access control; ctor and dtor are // code to be inserted into the ctor or dtor, respectively enum AccessCtl { AC_PUBLIC, // access AC_PRIVATE, // control AC_PROTECTED, // keywords AC_CTOR, // insert into ctor AC_DTOR, // insert into dtor AC_PUREVIRT, // declare pure virtual in superclass, and impl in subclass NUM_ACCESSCTLS }; // map the enum value to a string like "public" string toString(AccessCtl acc); // defined in ast.cc } // an access control keyword with optional modifier list class AccessMod(AccessCtl acc, ASTList mods) { // true if the given modifier is present public bool hasMod(char const *mod) const; // true if the given modifier prefix is present as a prefix of a modifier public bool hasModPrefix(char const *mod) const; // get the suffix after the given prefix of the (first) modifier it matches public string getModSuffixFromPrefix(char const *mod) const; } // additional user annotations class Annotation { // verbatim declarations, plus an access qualifier, to be // copied into the a class declaration; also has an optional // initializer (might be "") -> UserDecl (AccessMod amod, string code, string init) { public AccessCtl access() const { return amod->acc; }; } // verbatim code to be inserted somewhere; exactly where depends // on the qualifier string -> CustomCode (string qualifier, string code) { // keep track of whether it gets used public bool used; ctor used=false; } } // something that has to be passed to create a constructor class CtorArg (bool isOwner, string type, string name, string defaultValue); // designate a class that one of the ASTClasses should inherit; for // AST subclasses, this inheritance is in addition to inheriting the // corresponding AST superclass class BaseClass (AccessCtl access, string name); // ------------------- extra implementation helpers ------------------ impl_verbatim { #include "strutil.h" // stringToupper string toString(AccessCtl acc) { char const *arr[] = { "public", "private", "protected", "ctor", "dtor", "pure_virtual" }; STATIC_ASSERT(TABLESIZE(arr) == NUM_ACCESSCTLS); xassert((unsigned)acc < NUM_ACCESSCTLS); return string(arr[acc]); } string ASTClass::classKindName() const { string ret = stringToupper(name); if (ret == name) { // this simplemindedly avoids collisions with itself, and I think // it even avoids collisions with other classes, since if they would // collide with this, they'd collide with themselves too, and hence // get an extra "KIND_" prepended.. ret &= "KIND_"; } return ret; } bool AccessMod::hasMod(char const *mod) const { FOREACH_ASTLIST(string, mods, iter) { if (iter.data()->equals(mod)) { return true; } } return false; // not found } bool AccessMod::hasModPrefix(char const *mod) const { string mod0(mod); FOREACH_ASTLIST(string, mods, iter) { rostring i = *iter.data(); if (prefixEquals(i, mod0)) { return true; } } return false; // not found } string AccessMod::getModSuffixFromPrefix(char const *mod) const { string mod0(mod); string ret; bool found = false; FOREACH_ASTLIST(string, mods, iter) { rostring s = *iter.data(); if (prefixEquals(s, mod0)) { if (found) { xfailure(stringc << "two modifiers with this prefix found " << mod); } int len = strlen(mod); ret = s.substring(len, s.length()-len); found = true; } } if (!found) { xfailure(stringc << "no such prefix found " << mod); } return ret; } } // end impl_verbatim