Skip to content

Conversation

vinoski
Copy link
Contributor

@vinoski vinoski commented Jan 22, 2020

Change the setTokenFactory template function in the Lexer, Parser, and
TokenSource classes to be parameterized by Factory type rather than by
token type. Change the setTokenFactory signature to require the
function argument to be a Ref of the Factory template parameter type
so it can be correctly converted and assigned to the token factory
member. The type of that member is Ref<TokenFactory>,
which implies that the Factory template parameter must be of a type
convertible to TokenFactory.

this->_factory = factory;
template<typename Factory>
void setTokenFactory(Ref<Factory> const& factory) {
this->_factory = std::static_pointer_cast<TokenFactory<CommonToken>>(factory);
Copy link
Member

@mike-lischke mike-lischke Jan 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid this is the wrong approach. Look at the Java source code, which uses public void setTokenFactory(TokenFactory<?> factory), so it's clear the token class must be templated, not the token factory class. And your cast wouldn't work if something else but a CommonTokenFactory is passed in.

This part of the C++ runtime is a bit tricky, as there's no simple equivalent for the Java generic used for it (C++ cannot directly define templated member variables). The correct approach to use here is a simple pointer. This is also what is used in the other classes (e.g. see setInterpreter and addErrorListener in Recognizer.h, which all just use a plain object pointer). The caller of setTokenFactory is reponsible to manage the memory used by the factory instance. This works also well with the factory function for token factories (see TokenFactory::create, which creates a unique pointer).

The default factory also should be declared with a unique pointer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks for this guidance. There were a number of ways to go here; I went with one that preserved the current type of the Lexer::_factory member. Your feedback clarifies that changing the type of that member is ok, and I can see the rest will flow from that. I'll post a revision here shortly.

Change the setTokenFactory template functions and the getTokenFactory
functions to use a plain pointer rather than a Ref. This makes the
caller of setTokenFactory responsible for managing the lifetime and
memory of the token factory instance they pass in. Change
CommonTokenFactory::DEFAULT to be a unique_ptr, and correct all places
using it as a Ref.
@vinoski vinoski force-pushed the cpp-set-token-factory branch from 64a4747 to 38200b6 Compare January 24, 2020 13:59
Copy link
Member

@mike-lischke mike-lischke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@parrt C++ changes only, ready to be merged

@parrt parrt merged commit 2d7f727 into antlr:master Jan 24, 2020
@parrt parrt added this to the 4.9 milestone Nov 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants