Thread-safe ANTLR Go codegen

This commit is contained in:
Tristan Swadell 2020-05-01 01:57:54 -07:00
parent 8c50731894
commit 69ba58ecbe
4 changed files with 34 additions and 27 deletions

View File

@ -241,4 +241,5 @@ YYYY/MM/DD, github id, Full name, email
2020/02/10, julibert, Julián Bermúdez Ortega, julibert.dev@gmail.com
2020/02/21, StochasticTinkr, Daniel Pitts, github@coloraura.com
2020/03/17, XsongyangX, Song Yang, songyang1218@gmail.com
2020/04/07, deniskyashif, Denis Kyashif, denis.kyashif@gmail.com
2020/04/07, deniskyashif, Denis Kyashif, denis.kyashif@gmail.com
2020/04/30, TristonianJones, Tristan Swadell, tswadell@google.com

View File

@ -103,6 +103,8 @@ PositionAdjustingLexerDef() ::= ""
PositionAdjustingLexer() ::= <<
func (p *PositionAdjustingLexer) NextToken() antlr.Token {
if _, ok := p.Interpreter.(*PositionAdjustingLexerATNSimulator); !ok {
lexerDeserializer := antlr.NewATNDeserializer(nil)
lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
p.Interpreter = NewPositionAdjustingLexerATNSimulator(p, lexerAtn, p.Interpreter.DecisionToDFA(), p.Interpreter.SharedContextCache())
p.Virt = p
}

View File

@ -278,7 +278,8 @@ func (b *BaseLexer) inputStream() CharStream {
return b.input
}
func (b *BaseLexer) setInputStream(input CharStream) {
// SetInputStream resets the lexer input stream and associated lexer state.
func (b *BaseLexer) SetInputStream(input CharStream) {
b.input = nil
b.tokenFactorySourcePair = &TokenSourceCharStreamPair{b, b.input}
b.reset()

View File

@ -151,9 +151,6 @@ var parserATN = <atn>
var parserATN []uint16
<endif>
var deserializer = antlr.NewATNDeserializer(nil)
var deserializedATN = deserializer.DeserializeFromUInt16(parserATN)
<if(parser.literalNames)>
var literalNames = []string{
<parser.literalNames; null="\"\"", separator=", ", wrap>,
@ -179,21 +176,24 @@ var ruleNames = []string{
var ruleNames []string
<endif>
var decisionToDFA = make([]*antlr.DFA, len(deserializedATN.DecisionToState))
func init() {
for index, ds := range deserializedATN.DecisionToState {
decisionToDFA[index] = antlr.NewDFA(ds, index)
}
}
type <parser.name> struct {
<superClass; null="*antlr.BaseParser">
}
// New<parser.name> produces a new parser instance for the optional input antlr.TokenStream.
//
// The *<parser.name> instance produced may be reused by calling the SetInputStream method.
// The initial parser configuration is expensive to construct, and the object is not thread-safe;
// however, if used within a Golang sync.Pool, the construction cost amortizes well and the
// objects can be used in a thread-safe manner.
func New<parser.name>(input antlr.TokenStream) *<parser.name> {
this := new(<parser.name>)
deserializer := antlr.NewATNDeserializer(nil)
deserializedATN := deserializer.DeserializeFromUInt16(parserATN)
decisionToDFA := make([]*antlr.DFA, len(deserializedATN.DecisionToState))
for index, ds := range deserializedATN.DecisionToState {
decisionToDFA[index] = antlr.NewDFA(ds, index)
}
this.BaseParser = antlr.NewBaseParser(input)
this.Interpreter = antlr.NewParserATNSimulator(this, deserializedATN, decisionToDFA, antlr.NewPredictionContextCache())
@ -204,6 +204,11 @@ func New<parser.name>(input antlr.TokenStream) *<parser.name> {
return this
}
var (
lexer
)
<if(namedActions.members)>
<namedActions.members>
@ -1375,9 +1380,6 @@ var serializedLexerAtn []uint16
<endif>
var lexerDeserializer = antlr.NewATNDeserializer(nil)
var lexerAtn = lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
var lexerChannelNames = []string{
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"<if (lexer.channels)>, <lexer.channels:{c | "<c>"}; separator=", ", wrap><endif>,
}
@ -1412,7 +1414,6 @@ var lexerRuleNames = []string{
var lexerRuleNames []string
<endif>
type <lexer.name> struct {
*<if(superClass)><superClass><else>antlr.BaseLexer<endif>
channelNames []string
@ -1420,18 +1421,20 @@ type <lexer.name> struct {
// TODO: EOF string
}
var lexerDecisionToDFA = make([]*antlr.DFA, len(lexerAtn.DecisionToState))
func init() {
// New<lexer.name> produces a new lexer instance for the optional input antlr.CharStream.
//
// The *<lexer.name> instance produced may be reused by calling the SetInputStream method.
// The initial lexer configuration is expensive to construct, and the object is not thread-safe;
// however, if used within a Golang sync.Pool, the construction cost amortizes well and the
// objects can be used in a thread-safe manner.
func New<lexer.name>(input antlr.CharStream) *<lexer.name> {
l := new(<lexer.name>)
lexerDeserializer := antlr.NewATNDeserializer(nil)
lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
lexerDecisionToDFA := make([]*antlr.DFA, len(lexerAtn.DecisionToState))
for index, ds := range lexerAtn.DecisionToState {
lexerDecisionToDFA[index] = antlr.NewDFA(ds, index)
}
}
func New<lexer.name>(input antlr.CharStream) *<lexer.name> {
l := new(<lexer.name>)
l.BaseLexer = antlr.NewBaseLexer(input)
l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache())