ROSE 0.11.145.192
|
Rosebud is a tool to generate abstract syntax trees.
The Rosebud tool (rosebud
command) reads class definitions for abstract syntax tree (AST) vertex types and generates C++ source code.
The definition language is C++-like, enabling any C++ programmer to author or modify AST vertex classes. The C++-like language means the input is natively understood by integrated development environments (IDEs) and code editors. Rosebud aims to make common class definitions easy, and more complex definitions possible. The language supports Doxygen-style comments, delayed-decision conditional compilation, independent AST class hierarchies, abstract classes with pure virtual member functions, read-only properties, and more.
The Rosebud tool uses modern translation techniques such as referential lexical tokens and partial parsing. Rosebud can process the 400 "SgAsm" AST definitions and generate code in a fraction of a second. Its diagnostic messages (warnings and errors) follow the LLVM style, are readable by almost all IDEs, include the input source line and position indicators, and are colorized. Rosebud's AST for its intermediate representation is self hosted and fully documented.
Depending on which backend is chosen, the generated code uses modern C++ features such as reference counted pointers for clearly documented vertex ownership and safe, automatic deletion; exception safe adjustment to the tree edges (vertex connectivity); immediate tree consistency checks with violations reported by exceptions; and automatic, read-only parent pointers. Generated definitions make heavy use of automatically-generated forward declarations to achieve efficient compilation (although this is currently heavily counteracted by the policy that all ROSE source code includes the huge "sage3basic.h" or "rose.h" header files).
The input language is a subset of the C preprocessor and C++. As such, the input easily understood by experienced C++ programmers and can be operated on in almost any integrated development environment or code editor.
The various code-generation backends have slightly different rules for what they support. The documentation below indicates which backends support which input language features when support is not universal. The "yaml" backend supports everything since it simply emits the AST as a YAML document.
Each AST vertex class definition appears in its own header file. The header file name reflects the name of the class, and the directory path [reflects the namespace containing the class (Sawyer)] [is chosen based on the set of rosebud
command-line options that are needed (ROSETTA)]. These files are typically named with a ".h" extension so that IDEs and code editors can recognize them as C++ without any special configuration. For instance, the [Rose::Sarif::Log class is defined in "src/AstNodes/Rose/Sarif/Log.h"] [SgAsmGenericSection
class is defined in "src/AstNodes/BinaryAnalysis" (ROSETTA)].
rosebud
command-line. (ROSETTA)] [If a class is to be conditionally compiled, then all necessary preprocessor directivies must be specified. (Sawyer)]#ifdef ROSE_IMPL
(Sawyer)] [is copied verbatim to the generated header (ROSETTA)].namespace
specifiers around the class definition and the choice of directory path should mirror the namespace hierarchy. (Sawyer)] [All class definitions are assumed to exist within the root namespace. (ROSETTA)]A Rosebud class definition is similar to a C++ class definition. The class is introduced by a Doxygen double-asterisk C-style comment, followed by an optional list of C++ attributes (some of which are special Rosebud attributes), followed by the word "class", the class name, an optional base class list, an opening curly brace, member specifications, a closing curly brace, and the terminating semi-colon.
The following Rosebud class attributes are understood:
Rosebud::abstract
attribute indicates that the class cannot be instantiated. This is useful for base classes where one wants to be able to only instantiate its derived classes. [The ROSETTA backend only partially honors this: the last argument of NEW_NONTERMINAL_MACRO
is set to false, but the generated class can still be instantiated. In fact, adding a pure virtual function to the class to force it to never be instantiated causes compilation errors in generated code. (ROSETTA)]Rosebud::no_constructors
attribute prevents the backend from generating certain kinds of constructors. This is useful when the user wants to define his own constructors. [Although the usual C++ constructors are generated, no instance
allocating constructors are generated. (Sawyer)]Rosebud::no_destructor
attribute [prevents the generation of a destructor so the user can define his own destructor (Sawyer)] [is ignored and a destructor is always generated (ROSETTA)].Rosebud::serialize
attribute takes a single argument which is a symbol that will form the first part of a user-defined function to call in order to serialize or deserialize non-property, user-defined data members. The actual name of the function is formed by appending the name of the serializer. For instance, if the argument is "userSerialize" then the function that is called for the Boost::Serialization serializer is named "userSerializeBoost". The arguments passed to the function depend on the serializer, and are usually an input or output archive. The default is that no user-defined serializer is called, but serialization will still be performed for any properties that need it.Rosebud::small_header
attribute [is ignored since all headers are small (Sawyer)] [causes ROSETTA to generate a header file that contains only this single class definition (ROSETTA)].Rosebud::suppress
attribute prevents the backend from generating any code at all for this class. This is useful when Rosebud needs to know the class definition in order to generate code for subclasses, but should not generate the base class.Rosebud::tag
attribute takes a single argument which is a symbol to use as the ROSETTA-generated type tag when it needs to be different than the automatically generated tag. The auto-generated take is the type name without the leading "Sg" and with a "Tag" suffix. For instance, the tag for the class SgAsmInstruction
would default to AsmInstructionTag
. (ROSETTA)]A property is a ROSE IR feature where a value is stored in an object and is accessed and modified with special generated functions. The Rosebud syntax for a property looks like a C++ data member. It consists of the Doxygen documentation comment, the list of C++ attributes one or more of which must be a Rosebud attribute, the data member type, the data member name, the optional initialization constexpr, and the terminating semicolon.
public
, protected
, or private
), if present, must appear before the Doxygen comment. [They are ignored. (ROSETTA)] [They influence the generated accessors and mutators, but not the generated data member. (Sawyer)]. In the generated code, the property is always stored in a [private (ROSETTA)] [hidden (Sawyer)] data member.The only thing that sets a property apart from a normal data member is the presence of at least one Rosebud attribute. The following Rosebud attributes are understood:
Rosebud::property
attribute marks what would otherwise appear to be a data member declaration as a property declaration. Since the presence of any Rosebud attribute is sufficient, the "property" attribute is only necessary when no other Rosebud attribute is specified.Rosebud::data
attribute takes exactly one argument which is a symbol naming the data member that will be declared to store the property value. [This attribute has no user-visible effect since all property data members are hidden anyway. (Sawyer)]Rosebud::accessors
attribute, which requires an argument list even if it's empty, specifies the symbols to use as the accessor member function names. The default accessor name is [the same as the property name (Sawyer)] [formed by prepending "get_" to the property name, resulting in an unusual combination of snake- and camel-case (ROSETTA)]. If the attribute argument list is empty, then no accessor functions are generated, [making for a rather useless attribute since there's no other way to access it. (Sawyer)] [but the attribute can still be accessed directly through its data member name (ROSETTA)].Rosebud::mutators
attribute, which requires an argument list even if it's empty, specifies the symbols to use as the mutator member function names. The default accessor name is [the same as the property name (Sawyer)] [formed by prepending "set_" to the property name, resulting in an unusual combination of snake- and camel-case (ROSETTA)]. If the attribute argument list is empty, then no mutator functions are generated, but the property might still be modifiable through a non-const accessor (see Rosebud::large
).Rosebud::ctor_arg
means that the property's value will be passed to a generated constructor. Rosebud generates a C++ constructor that takes arguments (possibly empty) for all the ctor_arg
properties in the current class and all base classes. [If the user doesn't want this constructor, use the class Rosebud::no_constructor
attribute. (Sawyer)] [Rosebud also generates a default constructor and a constructor that takes arguments only for the ctor_args
properties for the current class (no base classes) and the unspecified properties are initialized to their default values (ROSETTA)]. Additional constructors can be defined by the user in the typical C++ manner.Rosebud::cloneptr
attribute [causes the copy
member function to allocate a new instance of the pointed object using the compile-time type of that object and its copy constructor] [is not supported (Sawyer)]. This is intended to be a temporary attribute since it can easily be done directly in C++ in many ways.Rosebud::serialize
attribute, which requires an argument list even if it's empty, specifies the base name for alternate serialization and deserialization functions. If the argument list is empty, then the property is not serialized or deserialized. Otherwise serialization and deserialization function names are created by appending the strings "Serialize" and "Deserialize". The user must define these functions so that the serialization function takes the property as an argument and returns a new value that should be serialized by the default method, while the deserialization function takes an argument that is the same type returned by the serialize function and returns a value to be assigned to the property. If this attribute isn't specified, then the property is serialzied and deserialized directly.Rosebud::large
attribute indicates that the property value is large and expensive to copy. Therefore, in addition to any other mutators, the accessors will be overloaded to return a non-const reference to the property's data member. Use this sparingly because it will not be compatible with all planned Rosebud backends (e.g., it is not possible to generate property observers or thread safe code if the property value can be modified directly through a reference.Rosebud::not_null
attribute [indicates that the property value cannot be a null pointer and any attempt to assign a null pointer will result in an exception being thrown (Sawyer)] [is ignored (ROSETTA)].Rosebud::rosetta
attribute [indicates that the property should be generated in a manner compatible with ROSETTA-generated properties (ROSETTA)] [is ignored (Sawyer)].Rosebud::traverse
attribute [indicates that a property is a pointer to another AST vertex and that the edge formed by the pointer is part of a tree data structure, i.e., the pointee's parent pointer is assumed to point back to the object that points to that pointee (ROSETTA)] [is ignored except it produces an error diagnostic if the property's type is not Edge<T>
or EdgeVector<T>
(Sawyer)].The rosebud
tool parses the definitions from the input files (described above) to create an intermediate representation (AST) and then one or more "backends" traverse the AST to emit C++ source code or other information. The three main backends are:
--backend=yaml
produces a structured YAML document describing the intermediate representation. This output can be easily parsed by other stand-alone translators. For instance, a translator to generate the alphabetical list of class names is a single line shell script using the free yq
tool.--backend=rosetta
produces input for the ROSETTA translator. Although ROSETTA has a number of problems (detailed below), it is also not feasible to entirely replace it in one fell swoop. Therefore, our plan is to use this backend to incrementally rewrite the ROSETTA definitions as Rosebud definitions, and have Rosebud produce the ROSETTA input. To this end, all the binary analysis AST vertex types (about 400 in total) have been converted. It is proving challenging to translate other ROSETTA classes due to their heavy use of ROSETTA macros instead of C++ language features, and the impedance mismatch in how ROSETTA and C++ define class hierarchies (bottom up versus top down).--backend=sawyer
produces C++ source code that uses the more modern Sawyer::Tree API and is an experimental backend that provides reference counted AST vertices using smart pointers; automatic, read-only parent pointers and immediate tree consistency checks; multiple, independent AST class hierarchies; traversals that can use lambda functions; exception safety; hidden data members; complete documentation; and unit tests. Eventually we hope to support more exotic features like signals and slots, thread safety, and user-defined class invariants. This backend is used by the Rose::Sarif API and Rosebud itself.The ROSETTA backend does not use a special type to indicate that a pointer data member is also an edge in the tree. Instead, the data member is marked with the Rosebud::traverse
attribute, like this:
The accessor and mutator functions are, by default, named by prepending "get_" and "set_". However, much code in ROSE accesses the property data members directly by prepending "p_". This is a bad practice since it bypasses any other actions (such as invariant checking, mutex aquisition, signaling, etc) that might also need to occur when a property is modified.
Each vertex class has an automatically generated parent
pointer that must be manually adjusted so the child points back to the parent, like this:
Detaching a node is similarly difficult:
Failing to set the child's parent pointer correctly is a detectable runtime error, but the check is delayed until the user remembers to call the appropriate whole-tree checking function at a later tmie. Similarly for other programming errors such as creating a cycle or having multiple vertices pointing to the same child–checks are delayed until some point at which the user remembers to check the tree consistency.
A ROSETTA-generated type should not have edges that point to individual children intermixed with vectors that point to many children. In order to do that reliably one must create an intermediate type to hold the vector:
Since ROSETTA uses raw pointers, it is up to the user to know when an object is no longer part of any tree and no longer pointed to by anything else in ROSE. Sometimes an analysis will cache its results, and thus have pointers into the AST. The best practice with ROSETTA-generated code is to never free any AST vertex.
The Sawyer backend generates AST vertex classes that inherit from Sawyer::Tree::Vertex, and it uses smart pointers. The smart pointer types have the names Ptr
and ConstPtr
both as members of the vertex class and by appending those names to the name of the class. The latter are useful in places like header files where one doesn't want the compiler to spend time parsing the class definition and only incomplete types are needed. Unlike the ROSETTA backend, the smart pointer data members do not need to be explicitly initialized to nullptr (their constructors take care of that). An AST edge is indicated with the type Edge
, like this:
The accessor and mutator functions are, by default, named the same thing as the property. The data members for the properties are effectively hidden by being given names that include a random string. Therefore the bad practice of setting the data member directly is no longer possible–all property modifications must go through the generated mutators.
Each vertex class has an automatically generated parent
pointer. Unlike ROSETTA, this pointer does not need to be adjusted explicitly, and trying to do so is a compile-time error.
Detaching a node is similarly easy:
Failing to set the parent correctly is not possible like it is with the ROSETTA backend. Also, the Sawyer backend immediately checks that the tree is not malformed in these ways, which are all exception safe:
NDEBUG
symbol is undefined).The Sawyer backend supports mixing scalar and vector edge types within a single AST vertex class. Unlike the ROSETTA backend, there is no need to define an intermediate class to hold the vector.
Since Sawyer uses reference counting pointers, objects that are no longer part of a tree and which are no longer pointed to by anything else in the program are automatically and immediately deleted. The user should not evern explicitly delete AST vertices. However, the user must be careful not to introduce self-referential data structures since cycles will prevent the objects from being deleted even if there are no other pointers to the data structure. This backend does not yet support weak pointers.
Rosebud is distributed as part of the ROSE library source code under the same license. It is built and installed automatically as part of building and installing the ROSE library.
The ROSE library has a number of AST class hierarchies that are generated by Rosebud. Some of these are also passed through the ROSETTA CxxGrammarMetaProgram
tool using Rosebud's --backend=rosetta
switch, and others are translated to C++ directly using Rosebud's --backend=sawyer
switch. Other switches are also necessary in certain situations. The generate
script makes sure the correct rosebud
commands are run to produce all generated files. The generated files are currently checked into the ROSE library source repository for improved stability while Rosebud is being developed.
To regenerate files, go to the "src/Rosebud" directory in the build tree and build the rosebud
executable by running your preferred build system. Then generate files by running this command from that same directory, replacing "$ROSE_SOURCE" with the top-level directory of the ROSE library repository:
You may need to add the --source=$ROSE_SOURCE
switch before "./rosebud" if the script cannot determine the locaton of the ROSE source directory.
The following directories are used:
rosebud
command, its backends, and this documentation.rosebud
command. These files are organized into directories according to either the namespace (for the Sawyer backend) or "Sg" prefix (for the ROSETTA backend).rosebud
. The ROSETTA backend also modifies the CxxGrammarMetaProgram
source code in the $ROSE_SOURCE/src/ROSETTA/src directory, and thus ROSETTA needs to be recompiled and re-run after any changes are made to Rosebud inputs.ROSETTA is/was the previous AST vertex class definition mechanism and is still used for most parts of the main AST. It has served well for many years, but its main drawbacks are:
CxxGrammarMetaProgram
command) seldom indicate the location of the problem, are often sent to standard output instead of standard error, and are typically ungracefully handled by a call assert(0)
, an infinite loop, or a segmentation fault. The generated accessors, mutators, and data members are named with unconventional combination of snake- and camel-case.Namespaces | |
namespace | Ast |
Abstract syntax tree. | |
Classes | |
class | BoostSerializer |
Class serializer using Boost Serialization. More... | |
class | CerealSerializer |
Class serializer producing JSON. More... | |
class | CxxGenerator |
Base class for generators that produce C++ code. More... | |
class | Generator |
Base class for backend code generators. More... | |
struct | HierarchyKey |
Key for ordering classes in the class hierarchy. More... | |
class | NoneGenerator |
Generator that produces a YAML description of the input. More... | |
class | NoneSerializer |
Class serializer using None Serialization. More... | |
class | RosettaGenerator |
Generator that produces ROSETTA output. More... | |
class | SawyerGenerator |
Generator that produces Sawyer::Tree class hierarchies. More... | |
class | Serializer |
Base class for serialization generators. More... | |
struct | Settings |
Command-line settings for the rosebud tool. More... | |
class | YamlGenerator |
Generator that produces a YAML description of the input. More... | |
Typedefs | |
using | Token = Sawyer::Language::Clexer::Token |
A token parsed from the input file. | |
using | TokenStream = Sawyer::Language::Clexer::TokenStream |
A stream of tokens from the input file. | |
using | GeneratorPtr = std::shared_ptr< Generator > |
Shared-ownership pointer to a Generator. | |
using | SerializerPtr = std::shared_ptr< Serializer > |
Shared-ownership pointer to a Serializer. | |
using | Hierarchy = Sawyer::Container::Graph< Ast::ClassPtr, Sawyer::Nothing, HierarchyKey > |
Class hierarchy. | |
using | Classes = std::vector< Ast::ClassPtr > |
Ordered sequence of classes. | |
Enumerations | |
enum class | Expand { NONE , INTER , PRIOR } |
How to obtain text when converting a sequence of tokens to a string. More... | |
enum class | When { NEVER , ALWAYS , AUTO } |
When something should be done. More... | |
enum class | Access { PRIVATE , PROTECTED , PUBLIC , DEFAULT } |
Kinds of access. More... | |
enum class | CamelCase { LOWER , UPPER , UNCHANGED } |
What to do with the first letter of the return value. More... | |
Functions | |
std::vector< std::string > | splitIntoLines (const std::string &) |
Split a multi-line string into one string per line. | |
void | eraseBlankLines (std::vector< std::string > &) |
Remove lines that are empty or contain only white space. | |
void | trimBlankLines (std::vector< std::string > &) |
Trim leading, trailing, and internal blank lines and trailing white space. | |
size_t | editDistance (const std::string &src, const std::string &tgt) |
Compute the Damerau-Levenshtein edit distance between two strings. | |
double | relativeDifference (const std::string &src, const std::string &tgt) |
Compute the relative difference between two strings. | |
std::string | bestMatch (const std::vector< std::string > &candidates, const std::string &sample) |
Returns the best match. | |
std::string | toString (Access) |
Convert an access enum to a C++ string. | |
std::string | camelCase (const std::string &, CamelCase=CamelCase::LOWER) |
Convert snake case to camelCase. | |
std::string | pascalCase (const std::string &) |
Convert a symbol to PascalCase. | |
std::string | bourneEscape (const std::string &) |
Quote string to make it shell safe. | |
std::string | withLeadSpace (const std::string &) |
String with one leading space. | |
std::string | accessSpecifier (Access) |
Return an access specifier with colon and trailing linefeed. | |
boost::filesystem::path | findRoseRootDir (const boost::filesystem::path &) |
Find the root of the ROSE source tree. | |
boost::filesystem::path | relativeToRoseSource (const boost::filesystem::path &) |
Convert a file path to a ROSE-relative path. | |
boost::filesystem::path | toPath (const std::string &symbol, const std::string &extension) |
Convert a qualified C++ name to a relative path. | |
std::string | appendToDoxygen (const std::string &existingComment, const std::string &newText) |
Append text to a Doxygen comment. | |
bool | usingColor () |
True if we're using color output for diagnostics. | |
std::string | messageString (Sawyer::Message::Importance, const std::string &mesg) |
Convert an importance level and message to an error output string. | |
Hierarchy | classHierarchy (const Classes &) |
Generate the class hierarchy from the specified class definitions. | |
void | checkClassHierarchy (Hierarchy &) |
Check for problems such as cycles in the class hiearchy and report them as errors. | |
Classes | topDown (Hierarchy &) |
Return all the class definitions so that base classes are before derived classes. | |
Classes | bottomUp (Hierarchy &) |
Return all the class definitions so that derived classes appear before base classes. | |
Classes | derivedClasses (const Ast::ClassPtr &, const Hierarchy &) |
Return all known subclasses. | |
bool | isBaseClass (const Ast::ClassPtr &, const Hierarchy &) |
True if the class is a base class of some other class. | |
std::vector< Ast::PropertyPtr > | allConstructorArguments (const Ast::ClassPtr &, const Hierarchy &) |
Properties that form constructor arguments. | |
std::string | firstPublicBaseClass (const Ast::ClassPtr &) |
Name of first public base class. | |
std::string | constRef (const std::string &type) |
Turn a type into a const reference to the type. | |
std::string | removeVolatileMutable (const std::string &type) |
Rmove "volatile" and "mutable" from the beginning of a type string. | |
std::string | toCppSymbol (const std::string &) |
Convert a C++ qualified name to a CPP symbol. | |
std::vector< std::string > | extractCpp (std::string &, const std::regex &, size_t capture) |
Extract all matching C preprocessor directives from the text. | |
std::string | matching (const std::string &) |
Return the matching opening or closing construct. | |
char | matching (char) |
Return the matching opening or closing construct. | |
std::string | prefixLines (const std::string &s, const std::string &prefix) |
Add a prefix to every line. | |
void | prefixLines (std::vector< std::string > &lines, const std::string &prefix) |
Add a prefix to every line. | |
std::string | cEscape (char ch, char context='\'') |
Escape as if in C single or double quotes. | |
std::string | cEscape (const std::string &, char context='"') |
Escape as if in C single or double quotes. | |
std::string | makeBlockComment (const std::string &text, const std::string &opening) |
Make a block comment. | |
std::vector< std::string > | makeBlockComment (const std::vector< std::string > &textLines, const std::string &opening) |
Make a block comment. | |
std::string | makeTitleComment (const std::string &multiLine, const std::string &prefix, char bar, size_t width) |
Make a title comment that spans the entire width of the source code. | |
std::vector< std::string > | makeTitleComment (const std::vector< std::string > &lines, const std::string &prefix, char bar, size_t width) |
Make a title comment that spans the entire width of the source code. | |
void | message (Sawyer::Message::Importance, const Ast::FilePtr &, const Token &, const std::string &mesg) |
Print a diagnostic message to standard error. | |
void | message (Sawyer::Message::Importance, const Ast::FilePtr &, const Token &begin, const Token &focus, const Token &end, const std::string &mesg) |
Print a diagnostic message to standard error. | |
void | message (Sawyer::Message::Importance, const Ast::FilePtr &, const std::vector< Token > &, const std::string &mesg) |
Print a diagnostic message to standard error. | |
void | message (Sawyer::Message::Importance, const std::string &mesg) |
Print a diagnostic message to standard error. | |
void | message (Sawyer::Message::Importance, const Ast::FilePtr &, const std::string &mesg) |
Print a diagnostic message to standard error. | |
std::string | locationDirective (size_t line, const std::string &file) |
Input location information. | |
std::string | locationDirective (const Ast::NodePtr &, const Token &) |
Input location information. | |
Variables | |
Settings | settings |
Command-line settings for the rosebud tool. | |
size_t | nErrors |
Number of error messages reported. | |
using Rosebud::Token = typedef Sawyer::Language::Clexer::Token |
A token parsed from the input file.
Definition at line 466 of file Rosebud/BasicTypes.h.
using Rosebud::TokenStream = typedef Sawyer::Language::Clexer::TokenStream |
A stream of tokens from the input file.
Definition at line 469 of file Rosebud/BasicTypes.h.
using Rosebud::GeneratorPtr = typedef std::shared_ptr<Generator> |
Shared-ownership pointer to a Generator.
Definition at line 486 of file Rosebud/BasicTypes.h.
using Rosebud::SerializerPtr = typedef std::shared_ptr<Serializer> |
Shared-ownership pointer to a Serializer.
Definition at line 488 of file Rosebud/BasicTypes.h.
using Rosebud::Hierarchy = typedef Sawyer::Container::Graph<Ast::ClassPtr, Sawyer::Nothing, HierarchyKey> |
Class hierarchy.
The vertices are pointers to AST class nodes. The edges point from base classes to derived classes.
Definition at line 248 of file ud/Utility.h.
using Rosebud::Classes = typedef std::vector<Ast::ClassPtr> |
Ordered sequence of classes.
Definition at line 251 of file ud/Utility.h.
|
strong |
How to obtain text when converting a sequence of tokens to a string.
Enumerator | |
---|---|
NONE | Each token's [begin,end) individually. |
INTER | From first token's begin to last token's end. |
PRIOR | From first token's prior to last token's end. |
Definition at line 472 of file Rosebud/BasicTypes.h.
|
strong |
When something should be done.
Enumerator | |
---|---|
NEVER | Never do it. |
ALWAYS | Always do it. |
AUTO | Sometimes do it. |
Definition at line 479 of file Rosebud/BasicTypes.h.
|
strong |
Kinds of access.
Enumerator | |
---|---|
PRIVATE | Like C++ |
PROTECTED | Like C++ |
PUBLIC | Like C++ |
DEFAULT | Use whatever access is already present. |
Definition at line 20 of file ud/Utility.h.
|
strong |
What to do with the first letter of the return value.
Enumerator | |
---|---|
LOWER | Make the first character lower case. |
UPPER | Make the first character upper case. |
UNCHANGED | Leave the first character as it is in the input. |
Definition at line 95 of file ud/Utility.h.
std::string Rosebud::matching | ( | const std::string & | ) |
Return the matching opening or closing construct.
E.g., if input is "{" then output is "}" and vice versa.
char Rosebud::matching | ( | char | ) |
Return the matching opening or closing construct.
E.g., if input is "{" then output is "}" and vice versa.
std::vector< std::string > Rosebud::splitIntoLines | ( | const std::string & | ) |
Split a multi-line string into one string per line.
Splits the input string at its line termination characters and return a vector of the resulting lines without their line termination characters. Since ROSE source code is prohibited from using carriage returns, we only have to worry about line feeds.
void Rosebud::trimBlankLines | ( | std::vector< std::string > & | ) |
Trim leading, trailing, and internal blank lines and trailing white space.
double Rosebud::relativeDifference | ( | const std::string & | src, |
const std::string & | tgt | ||
) |
Compute the relative difference between two strings.
Computes the editDistance as a ratio of the string length, returning a value between zero and one.
std::string Rosebud::bestMatch | ( | const std::vector< std::string > & | candidates, |
const std::string & | sample | ||
) |
Returns the best match.
Given a list of candidate strings and a sample, return the candidate that is most similar to the sample.
boost::filesystem::path Rosebud::findRoseRootDir | ( | const boost::filesystem::path & | ) |
Find the root of the ROSE source tree.
Given the name of a file inside the ROSE source tree, return the absolute name of the root directory of the ROSE source tree. If the root directory cannot be found (e.g., the specified file is not inside the ROSE source tree), then return an empty path. The file need not exist.
boost::filesystem::path Rosebud::relativeToRoseSource | ( | const boost::filesystem::path & | ) |
Convert a file path to a ROSE-relative path.
If the specified file name is inside the ROSE source tree, then return the name of the file relative to the root of the ROSE source tree. Returns the empty path if the file is not inside the ROSE source tree. The file need not exist.
boost::filesystem::path Rosebud::toPath | ( | const std::string & | symbol, |
const std::string & | extension | ||
) |
Convert a qualified C++ name to a relative path.
The return value is a relative path of components separated by the system's path component separator ("/" on POSIX systems). The components of the path are the components of the C++ qualified name that are separated by "::". The file name extension is appended to the result before returning.
std::string Rosebud::makeBlockComment | ( | const std::string & | text, |
const std::string & | opening | ||
) |
Make a block comment.
The string is split into lines. The first line is prefixed with the opening text and the prefix for the following lines is created automatically from the opening text. This works for both C-style and C++-style comments. If the opening contains neither a C-style nor C++-style comment opening, then C-style is assumed and the opening is used as-is for the prefix for all lines. The closing token for C-style comments hangs on the last line of text. If there is no text, then the return value is similarly empty.
std::vector< std::string > Rosebud::makeBlockComment | ( | const std::vector< std::string > & | textLines, |
const std::string & | opening | ||
) |
Make a block comment.
The string is split into lines. The first line is prefixed with the opening text and the prefix for the following lines is created automatically from the opening text. This works for both C-style and C++-style comments. If the opening contains neither a C-style nor C++-style comment opening, then C-style is assumed and the opening is used as-is for the prefix for all lines. The closing token for C-style comments hangs on the last line of text. If there is no text, then the return value is similarly empty.
std::string Rosebud::makeTitleComment | ( | const std::string & | multiLine, |
const std::string & | prefix, | ||
char | bar, | ||
size_t | width | ||
) |
Make a title comment that spans the entire width of the source code.
This is similar to the wide //////... comments in this header file.
std::vector< std::string > Rosebud::makeTitleComment | ( | const std::vector< std::string > & | lines, |
const std::string & | prefix, | ||
char | bar, | ||
size_t | width | ||
) |
Make a title comment that spans the entire width of the source code.
This is similar to the wide //////... comments in this header file.
std::string Rosebud::appendToDoxygen | ( | const std::string & | existingComment, |
const std::string & | newText | ||
) |
Append text to a Doxygen comment.
Given a Doxygen block comment (or nothing), append the specified multi-line text to the end of the comment. The new text should not include start or end with C-style comment delimiters or contain C++-style or box decorations at the start of each line of new text; these will be added automatically.
std::string Rosebud::messageString | ( | Sawyer::Message::Importance | , |
const std::string & | mesg | ||
) |
Convert an importance level and message to an error output string.
The returned string may have ANSI color codes and will have line termination.
void Rosebud::message | ( | Sawyer::Message::Importance | , |
const Ast::FilePtr & | , | ||
const Token & | , | ||
const std::string & | mesg | ||
) |
Print a diagnostic message to standard error.
Messages contain the following parts:
The message will include the name of the input file, the position in the input file, and a copy of the relevant part of the input file
void Rosebud::message | ( | Sawyer::Message::Importance | , |
const Ast::FilePtr & | , | ||
const Token & | begin, | ||
const Token & | focus, | ||
const Token & | end, | ||
const std::string & | mesg | ||
) |
Print a diagnostic message to standard error.
Messages contain the following parts:
The message will include the name of the input file, the position in the input file, and a copy of the relevant part of the input file
void Rosebud::message | ( | Sawyer::Message::Importance | , |
const Ast::FilePtr & | , | ||
const std::vector< Token > & | , | ||
const std::string & | mesg | ||
) |
Print a diagnostic message to standard error.
Messages contain the following parts:
The message will include the name of the input file, the position in the input file, and a copy of the relevant part of the input file
void Rosebud::message | ( | Sawyer::Message::Importance | , |
const std::string & | mesg | ||
) |
Print a diagnostic message to standard error.
Messages contain the following parts:
The message will include the name of the input file, the position in the input file, and a copy of the relevant part of the input file
void Rosebud::message | ( | Sawyer::Message::Importance | , |
const Ast::FilePtr & | , | ||
const std::string & | mesg | ||
) |
Print a diagnostic message to standard error.
Messages contain the following parts:
The message will include the name of the input file, the position in the input file, and a copy of the relevant part of the input file
Generate the class hierarchy from the specified class definitions.
The edges in the graph point from base classes to derived classes.
std::string Rosebud::constRef | ( | const std::string & | type | ) |
Turn a type into a const reference to the type.
std::string Rosebud::locationDirective | ( | size_t | line, |
const std::string & | file | ||
) |
Input location information.
This returns a C preprocessor #line directive with line termintion that resets source information as specified. If location information is disabled, then the empty string is returned.
std::string Rosebud::locationDirective | ( | const Ast::NodePtr & | , |
const Token & | |||
) |
Input location information.
This returns a C preprocessor #line directive with line termintion that resets source information as specified. If location information is disabled, then the empty string is returned.
std::string Rosebud::toCppSymbol | ( | const std::string & | ) |
Convert a C++ qualified name to a CPP symbol.
This is done by replacing all the "::" with "_". Leading underscores are removed. A leading "Rose_" string is replaced with "ROSE_".
std::vector< std::string > Rosebud::extractCpp | ( | std::string & | , |
const std::regex & | , | ||
size_t | capture | ||
) |
Extract all matching C preprocessor directives from the text.
Modifies the string in place and returns one preprocessor directive per vector element. If capture is non-zero, then it refers to a parenthetical capture group in the regular expression, and just that group is saved in the return vector.