forked from jasder/antlr
Added a new setting required by the C++ runtime.
In order to export generated classes in DLLs we need a way to specify the __declspec setting. This is is usually done via a macro that takes the import or export value. The new parameter (`-export-macro`) allows to specify this, which increases the flexibility of the generated classes. The C++ target documentation has been extended to describe build specific things, includig this new parameter.
This commit is contained in:
parent
50afb22068
commit
428ff28f35
|
@ -20,11 +20,13 @@ You will see that there are a whole bunch of files generated by this call. If vi
|
|||
|
||||
## Where can I get the runtime?
|
||||
|
||||
Once you've generated the lexer and/or parser code, you need to download or build the runtime. Prebuilt C++ runtime binaries for Windows (VS 2013 runtime), OSX and iOS are available on the ANTLR web site:
|
||||
Once you've generated the lexer and/or parser code, you need to download or build the runtime. Prebuilt C++ runtime binaries for Windows (Visual Studio 2013/2015), OSX/macOS and iOS are available on the ANTLR web site:
|
||||
|
||||
* http://www.antlr.org
|
||||
|
||||
Use CMake to build a Linux library (works also on OSX, however not for the iOS library). Building your own library on OSX or Windows is trivial, however. Just open the VS or XCode project, select target + arch and build it. Should work out of the box without any additional dependency.
|
||||
Use CMake to build a Linux library (works also on OSX, however not for the iOS library).
|
||||
|
||||
Instead of downloading a prebuilt binary you can also easily build your own library on OSX or Windows. Just use the provided projects for XCode or Visual Studio and build it. Should work out of the box without any additional dependency.
|
||||
|
||||
|
||||
## How do I run the generated lexer and/or parser?
|
||||
|
@ -76,6 +78,29 @@ This example assumes your grammar contains a parser rule named `key` for which t
|
|||
|
||||
There are a couple of things that only the C++ ANTLR target has to deal with. They are described here.
|
||||
|
||||
### Build Aspects
|
||||
The code generation (by running the ANTLR4 jar) allows to specify 2 values you might find useful for better integration of the generated files into your application (both are optional):
|
||||
|
||||
* A **namespace**: use the **`-package`** parameter to specify the namespace you want.
|
||||
* An **export macro**: especially in VC++ extra work is required to export your classes from a DLL. This is usually accomplished by a macro that has different values depending on whether you are creating the DLL or import it. The ANTLR4 runtime itself also uses one for its classes:
|
||||
|
||||
```c++
|
||||
#ifdef ANTLR4CPP_EXPORTS
|
||||
#define ANTLR4CPP_PUBLIC __declspec(dllexport)
|
||||
#else
|
||||
#ifdef ANTLR4CPP_STATIC
|
||||
#define ANTLR4CPP_PUBLIC
|
||||
#else
|
||||
#define ANTLR4CPP_PUBLIC __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
```
|
||||
Just like the `ANTLR4CPP_PUBLIC` macro here you can specify your own one for the generated classes using the **`-export-macro`** parameter.
|
||||
|
||||
In order to create a static lib in Visual Studio define the `ANTLR4CPP_STATIC` macro in addition to the project settings that must be set for a static library (if you compile the runtime yourself).
|
||||
|
||||
For gcc and clang it is possible to use the `-fvisibility=hidden` setting to hide all symbols except those that are made default-visible (which has been defined for all public classes in the runtime).
|
||||
|
||||
### Memory Management
|
||||
Since C++ has no built-in memory management we need to take extra care. For that we rely mostly on smart pointers, which however might cause time penalties or memory side effects (like cyclic references) if not used with care. Currently however the memory household looks very stable. Generally, when you see a raw pointer in code consider this as being managed elsewehere. You should never try to manage such a pointer (delete, assign to smart pointer etc.).
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ cppTypeInitMap ::= [
|
|||
LexerHeader(lexer, atn, actionFuncs, sempredFuncs, superClass = {antlr4::Lexer}) ::= <<
|
||||
<namedActions.context>
|
||||
|
||||
class <lexer.name> : public <superClass> {
|
||||
class <file.exportMacro> <lexer.name> : public <superClass> {
|
||||
public:
|
||||
<if (lexer.tokens)>
|
||||
enum {
|
||||
|
@ -266,7 +266,7 @@ bool <if (r.factory.g.lexer)><lexer.name><else><parser.name><endif>::<r.name>Sem
|
|||
ParserHeader(parser, funcs, atn, sempredFuncs, superClass = {antlr4::Parser}) ::= <<
|
||||
<namedActions.context>
|
||||
|
||||
class <parser.name> : public <superClass> {
|
||||
class <file.exportMacro> <parser.name> : public <superClass> {
|
||||
public:
|
||||
<if (parser.tokens)>
|
||||
enum {
|
||||
|
@ -526,7 +526,7 @@ LeftRecursiveRuleFunction(currentRule, args, code, locals, ruleCtx, altLabelCtxs
|
|||
>>
|
||||
|
||||
StructDeclHeader(struct, ctorAttrs, attrs, getters, dispatchMethods, interfaces, extensionMembers) ::= <<
|
||||
class <struct.name> : public <if (contextSuperClass)><contextSuperClass><else>antlr4::ParserRuleContext<endif><if(interfaces)>, <interfaces; separator=", "><endif> {
|
||||
class <file.exportMacro> <struct.name> : public <if (contextSuperClass)><contextSuperClass><else>antlr4::ParserRuleContext<endif><if(interfaces)>, <interfaces; separator=", "><endif> {
|
||||
public:
|
||||
<attrs: {a | <a>;}; separator="\n">
|
||||
<if (ctorAttrs)><struct.name>(antlr4::ParserRuleContext *parent, size_t invokingState);<endif>
|
||||
|
@ -578,7 +578,7 @@ void <parser.name>::<struct.name>::copyFrom(<struct.name> *ctx) {
|
|||
>>
|
||||
|
||||
AltLabelStructDeclHeader(struct, attrs, getters, dispatchMethods) ::= <<
|
||||
class <struct.name> : public <currentRule.name; format = "cap">Context {
|
||||
class <file.exportMacro> <struct.name> : public <currentRule.name; format = "cap">Context {
|
||||
public:
|
||||
<struct.name>(<currentRule.name; format = "cap">Context *ctx);
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace <file.genPackage> {
|
|||
* which can be extended to create a listener which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*/
|
||||
class <file.grammarName>BaseListener : public <file.grammarName>Listener {
|
||||
class <file.exportMacro> <file.grammarName>BaseListener : public <file.grammarName>Listener {
|
||||
public:
|
||||
<namedActions.baselistenerdeclarations>
|
||||
|
||||
|
@ -192,7 +192,7 @@ namespace <file.genPackage> {
|
|||
/**
|
||||
* This interface defines an abstract listener for a parse tree produced by <file.parserName>.
|
||||
*/
|
||||
class <file.grammarName>Listener : public antlr4::tree::ParseTreeListener {
|
||||
class <file.exportMacro> <file.grammarName>Listener : public antlr4::tree::ParseTreeListener {
|
||||
public:
|
||||
<namedActions.listenerdeclarations>
|
||||
|
||||
|
@ -248,7 +248,7 @@ namespace <file.genPackage> {
|
|||
* This class provides an empty implementation of <file.grammarName>Visitor, which can be
|
||||
* extended to create a visitor which only needs to handle a subset of the available methods.
|
||||
*/
|
||||
class <file.grammarName>BaseVisitor : public <file.grammarName>Visitor {
|
||||
class <file.exportMacro> <file.grammarName>BaseVisitor : public <file.grammarName>Visitor {
|
||||
public:
|
||||
<namedActions.basevisitordeclarations>
|
||||
|
||||
|
@ -304,7 +304,7 @@ VisitorFileHeader(file, header, namedActions) ::= <<
|
|||
* This class defines an abstract visitor for a parse tree
|
||||
* produced by <file.parserName>.
|
||||
*/
|
||||
class <file.grammarName>Visitor : public antlr4::tree::AbstractParseTreeVisitor {
|
||||
class <file.exportMacro> <file.grammarName>Visitor : public antlr4::tree::AbstractParseTreeVisitor {
|
||||
public:
|
||||
<namedActions.visitordeclarations>
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ public class Tool {
|
|||
public boolean gen_visitor = false;
|
||||
public boolean gen_dependencies = false;
|
||||
public String genPackage = null;
|
||||
public String exportMacro = null; // C++ specific, need to allow setting a macro to set declspec for generated classes for VC++.
|
||||
public Map<String, String> grammarOptions = null;
|
||||
public boolean warnings_are_errors = false;
|
||||
public boolean longMessages = false;
|
||||
|
@ -128,6 +129,7 @@ public class Tool {
|
|||
new Option("gen_visitor", "-visitor", "generate parse tree visitor"),
|
||||
new Option("gen_visitor", "-no-visitor", "don't generate parse tree visitor (default)"),
|
||||
new Option("genPackage", "-package", OptionArgType.STRING, "specify a package/namespace for the generated code"),
|
||||
new Option("exportMacro", "-export-macro", OptionArgType.STRING, "C++ only, specify a macro for import/export of generated classes"),
|
||||
new Option("gen_dependencies", "-depend", "generate file dependencies"),
|
||||
new Option("", "-D<option>=value", "set/override a grammar-level option"),
|
||||
new Option("warnings_are_errors", "-Werror", "treat warnings as errors"),
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Map;
|
|||
|
||||
public class LexerFile extends OutputFile {
|
||||
public String genPackage; // from -package cmd-line
|
||||
public String exportMacro; // from -export-macro cmd-line
|
||||
public boolean genListener; // from -listener cmd-line
|
||||
public boolean genVisitor; // from -visitor cmd-line
|
||||
@ModelElement public Lexer lexer;
|
||||
|
@ -21,6 +22,7 @@ public class LexerFile extends OutputFile {
|
|||
super(factory, fileName);
|
||||
namedActions = buildNamedActions(factory.getGrammar());
|
||||
genPackage = factory.getGrammar().tool.genPackage;
|
||||
exportMacro = factory.getGrammar().tool.exportMacro;
|
||||
genListener = factory.getGrammar().tool.gen_listener;
|
||||
genVisitor = factory.getGrammar().tool.gen_visitor;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Set;
|
|||
*/
|
||||
public class ListenerFile extends OutputFile {
|
||||
public String genPackage; // from -package cmd-line
|
||||
public String exportMacro; // from -export-macro cmd-line
|
||||
public String grammarName;
|
||||
public String parserName;
|
||||
/**
|
||||
|
@ -61,5 +62,6 @@ public class ListenerFile extends OutputFile {
|
|||
ActionAST ast = g.namedActions.get("header");
|
||||
if ( ast!=null ) header = new Action(factory, ast);
|
||||
genPackage = factory.getGrammar().tool.genPackage;
|
||||
exportMacro = factory.getGrammar().tool.exportMacro;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Map;
|
|||
/** */
|
||||
public class ParserFile extends OutputFile {
|
||||
public String genPackage; // from -package cmd-line
|
||||
public String exportMacro ; // from -export-macro cmd-line
|
||||
public boolean genListener; // from -listener cmd-line
|
||||
public boolean genVisitor; // from -visitor cmd-line
|
||||
@ModelElement public Parser parser;
|
||||
|
@ -28,6 +29,7 @@ public class ParserFile extends OutputFile {
|
|||
Grammar g = factory.getGrammar();
|
||||
namedActions = buildNamedActions(factory.getGrammar());
|
||||
genPackage = g.tool.genPackage;
|
||||
exportMacro = g.tool.exportMacro;
|
||||
// need the below members in the ST for Python, C++
|
||||
genListener = g.tool.gen_listener;
|
||||
genVisitor = g.tool.gen_visitor;
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Set;
|
|||
|
||||
public class VisitorFile extends OutputFile {
|
||||
public String genPackage; // from -package cmd-line
|
||||
public String exportMacro; // from -export-macro cmd-line
|
||||
public String grammarName;
|
||||
public String parserName;
|
||||
/**
|
||||
|
@ -58,5 +59,6 @@ public class VisitorFile extends OutputFile {
|
|||
ActionAST ast = g.namedActions.get("header");
|
||||
if ( ast!=null ) header = new Action(factory, ast);
|
||||
genPackage = factory.getGrammar().tool.genPackage;
|
||||
exportMacro = factory.getGrammar().tool.exportMacro;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue