diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/descriptors/CompositeParsers/ImportedRuleWithAction.txt b/runtime-testsuite/resources/org/antlr/v4/test/runtime/descriptors/CompositeParsers/ImportedRuleWithAction.txt index 628cb68418..2fff024817 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/descriptors/CompositeParsers/ImportedRuleWithAction.txt +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/descriptors/CompositeParsers/ImportedRuleWithAction.txt @@ -18,3 +18,6 @@ s [input] b +[skip] +Go + diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg index 524098a551..f629702ca8 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg @@ -19,13 +19,9 @@ AppendStr(a,b) ::= " + " Concat(a,b) ::= "" AssertIsList(v) ::= << -// A noddy range over the list will not compile if it is not getting a slice -// however, Go will not compile the generated code if the slice vs single value is wrong. -// Makes the Java based tests suite work though. -j1__ := make([]interface{}, len()) -j2__ := -for j3__ := range j2__ { - j1__[j3__] = j2__[j3__] +// Go will not compile this generated code if the slice vs single value is wrong. +for i := range localctx.(*ExpressionContext).GetArgs() { + _ = localctx.(*ExpressionContext).GetArgs()[i] } >> diff --git a/runtime/Go/antlr/v4/error_strategy.go b/runtime/Go/antlr/v4/error_strategy.go index 102dca2942..e84adb4595 100644 --- a/runtime/Go/antlr/v4/error_strategy.go +++ b/runtime/Go/antlr/v4/error_strategy.go @@ -119,7 +119,7 @@ func (d *DefaultErrorStrategy) ReportError(recognizer Parser, e RecognitionExcep // It reSynchronizes the parser by consuming tokens until we find one in the reSynchronization set - // loosely the set of tokens that can follow the current rule. func (d *DefaultErrorStrategy) Recover(recognizer Parser, _ RecognitionException) { - + if d.lastErrorIndex == recognizer.GetInputStream().Index() && d.lastErrorStates != nil && d.lastErrorStates.contains(recognizer.GetState()) { // uh oh, another error at same token index and previously-Visited @@ -206,7 +206,7 @@ func (d *DefaultErrorStrategy) Sync(recognizer Parser) { if d.SingleTokenDeletion(recognizer) != nil { return } - panic(NewInputMisMatchException(recognizer)) + recognizer.SetError(NewInputMisMatchException(recognizer)) case ATNStatePlusLoopBack, ATNStateStarLoopBack: d.ReportUnwantedToken(recognizer) expecting := NewIntervalSet() @@ -362,7 +362,8 @@ func (d *DefaultErrorStrategy) RecoverInline(recognizer Parser) Token { return d.GetMissingSymbol(recognizer) } // even that didn't work must panic the exception - panic(NewInputMisMatchException(recognizer)) + recognizer.SetError(NewInputMisMatchException(recognizer)) + return nil } // SingleTokenInsertion implements the single-token insertion inline error recovery @@ -685,7 +686,7 @@ func (b *BailErrorStrategy) Recover(recognizer Parser, e RecognitionException) { context = nil } } - panic(NewParseCancellationException()) // TODO: we don't emit e properly + recognizer.SetError(NewParseCancellationException()) // TODO: we don't emit e properly } // RecoverInline makes sure we don't attempt to recover inline if the parser diff --git a/runtime/Go/antlr/v4/errors.go b/runtime/Go/antlr/v4/errors.go index 74ae1b1919..1a4868e585 100644 --- a/runtime/Go/antlr/v4/errors.go +++ b/runtime/Go/antlr/v4/errors.go @@ -43,13 +43,13 @@ func NewBaseRecognitionException(message string, recognizer Recognizer, input In t.recognizer = recognizer t.input = input t.ctx = ctx - + // The current Token when an error occurred. Since not all streams // support accessing symbols by index, we have to track the {@link Token} // instance itself. // t.offendingToken = nil - + // Get the ATN state number the parser was in at the time the error // occurred. For NoViableAltException and LexerNoViableAltException exceptions, this is the // DecisionState number. For others, it is the state whose outgoing edge we couldn't Match. @@ -162,7 +162,7 @@ func NewNoViableAltException(recognizer Parser, input TokenStream, startToken To // Which configurations did we try at input.Index() that couldn't Match // input.LT(1) n.deadEndConfigs = deadEndConfigs - + // The token object at the start index the input stream might // not be buffering tokens so get a reference to it. // @@ -236,6 +236,21 @@ func (f *FailedPredicateException) formatMessage(predicate, message string) stri type ParseCancellationException struct { } +func (p ParseCancellationException) GetOffendingToken() Token { + //TODO implement me + panic("implement me") +} + +func (p ParseCancellationException) GetMessage() string { + //TODO implement me + panic("implement me") +} + +func (p ParseCancellationException) GetInputStream() IntStream { + //TODO implement me + panic("implement me") +} + func NewParseCancellationException() *ParseCancellationException { // Error.call(this) // Error.captureStackTrace(this, ParseCancellationException) diff --git a/runtime/Go/antlr/v4/parser.go b/runtime/Go/antlr/v4/parser.go index bdb11f2468..7d9184eb93 100644 --- a/runtime/Go/antlr/v4/parser.go +++ b/runtime/Go/antlr/v4/parser.go @@ -152,6 +152,9 @@ func (p *BaseParser) Match(ttype int) Token { p.Consume() } else { t = p.errHandler.RecoverInline(p) + if p.HasError() { + return nil + } if p.BuildParseTrees && t.GetTokenIndex() == -1 { // we must have conjured up a new token during single token diff --git a/runtime/Go/antlr/v4/parser_atn_simulator.go b/runtime/Go/antlr/v4/parser_atn_simulator.go index d143cbb2c5..db9e3ebfc8 100644 --- a/runtime/Go/antlr/v4/parser_atn_simulator.go +++ b/runtime/Go/antlr/v4/parser_atn_simulator.go @@ -74,7 +74,7 @@ func (p *ParserATNSimulator) reset() { } //goland:noinspection GoBoolExpressions -func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, outerContext ParserRuleContext) int { +func (p *ParserATNSimulator) AdaptivePredict(parser *BaseParser, input TokenStream, decision int, outerContext ParserRuleContext) int { if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim { fmt.Println("adaptivePredict decision " + strconv.Itoa(decision) + " exec LA(1)==" + p.getLookaheadName(input) + @@ -147,7 +147,8 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou p.atn.stateMu.Unlock() } - alt := p.execATN(dfa, s0, input, index, outerContext) + alt, re := p.execATN(dfa, s0, input, index, outerContext) + parser.SetError(re) if ParserATNSimulatorDebug { fmt.Println("DFA after predictATN: " + dfa.String(p.parser.GetLiteralNames(), nil)) } @@ -189,7 +190,7 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou // - conflict + predicates // //goland:noinspection GoBoolExpressions -func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, startIndex int, outerContext ParserRuleContext) int { +func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, startIndex int, outerContext ParserRuleContext) (int, RecognitionException) { if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim { fmt.Println("execATN decision " + strconv.Itoa(dfa.decision) + @@ -223,10 +224,10 @@ func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, input.Seek(startIndex) alt := p.getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousD.configs, outerContext) if alt != ATNInvalidAltNumber { - return alt + return alt, nil } - - panic(e) + p.parser.SetError(e) + return ATNInvalidAltNumber, e } if D.requiresFullContext && p.predictionMode != PredictionModeSLL { // IF PREDS, MIGHT RESOLVE TO SINGLE ALT => SLL (or syntax error) @@ -244,7 +245,7 @@ func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, if ParserATNSimulatorDebug { fmt.Println("Full LL avoided") } - return conflictingAlts.minValue() + return conflictingAlts.minValue(), nil } if conflictIndex != startIndex { // restore the index so Reporting the fallback to full @@ -258,12 +259,12 @@ func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, fullCtx := true s0Closure := p.computeStartState(dfa.atnStartState, outerContext, fullCtx) p.ReportAttemptingFullContext(dfa, conflictingAlts, D.configs, startIndex, input.Index()) - alt := p.execATNWithFullContext(dfa, D, s0Closure, input, startIndex, outerContext) - return alt + alt, re := p.execATNWithFullContext(dfa, D, s0Closure, input, startIndex, outerContext) + return alt, re } if D.isAcceptState { if D.predicates == nil { - return D.prediction + return D.prediction, nil } stopIndex := input.Index() input.Seek(startIndex) @@ -271,13 +272,13 @@ func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, switch alts.length() { case 0: - panic(p.noViableAlt(input, outerContext, D.configs, startIndex)) + return ATNInvalidAltNumber, p.noViableAlt(input, outerContext, D.configs, startIndex) case 1: - return alts.minValue() + return alts.minValue(), nil default: // Report ambiguity after predicate evaluation to make sure the correct set of ambig alts is Reported. p.ReportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D.configs) - return alts.minValue() + return alts.minValue(), nil } } previousD = D @@ -393,7 +394,7 @@ func (p *ParserATNSimulator) predicateDFAState(dfaState *DFAState, decisionState // comes back with reach.uniqueAlt set to a valid alt // //goland:noinspection GoBoolExpressions -func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 ATNConfigSet, input TokenStream, startIndex int, outerContext ParserRuleContext) int { +func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 ATNConfigSet, input TokenStream, startIndex int, outerContext ParserRuleContext) (int, RecognitionException) { if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim { fmt.Println("execATNWithFullContext " + s0.String()) @@ -419,14 +420,12 @@ func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 AT // ATN states in SLL implies LL will also get nowhere. // If conflict in states that dip out, choose min since we // will get error no matter what. - e := p.noViableAlt(input, outerContext, previous, startIndex) input.Seek(startIndex) alt := p.getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previous, outerContext) if alt != ATNInvalidAltNumber { - return alt + return alt, nil } - - panic(e) + return alt, p.noViableAlt(input, outerContext, previous, startIndex) } altSubSets := PredictionModegetConflictingAltSubsets(reach) if ParserATNSimulatorDebug { @@ -468,7 +467,7 @@ func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 AT // not SLL. if reach.GetUniqueAlt() != ATNInvalidAltNumber { p.ReportContextSensitivity(dfa, predictedAlt, reach, startIndex, input.Index()) - return predictedAlt + return predictedAlt, nil } // We do not check predicates here because we have checked them // on-the-fly when doing full context prediction. @@ -499,7 +498,7 @@ func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 AT p.ReportAmbiguity(dfa, D, startIndex, input.Index(), foundExactAmbig, reach.Alts(), reach) - return predictedAlt + return predictedAlt, nil } //goland:noinspection GoBoolExpressions @@ -1401,7 +1400,7 @@ func (p *ParserATNSimulator) getLookaheadName(input TokenStream) string { // it out for clarity now that alg. works well. We can leave p // "dead" code for a bit. func (p *ParserATNSimulator) dumpDeadEndConfigs(_ *NoViableAltException) { - + panic("Not implemented") // fmt.Println("dead end configs: ") diff --git a/runtime/Go/antlr/v4/recognizer.go b/runtime/Go/antlr/v4/recognizer.go index 467ba0b1c8..cd899f6e87 100644 --- a/runtime/Go/antlr/v4/recognizer.go +++ b/runtime/Go/antlr/v4/recognizer.go @@ -7,7 +7,7 @@ package antlr import ( "fmt" "strings" - + "strconv" ) @@ -15,10 +15,10 @@ type Recognizer interface { GetLiteralNames() []string GetSymbolicNames() []string GetRuleNames() []string - + Sempred(RuleContext, int, int) bool Precpred(RuleContext, int) bool - + GetState() int SetState(int) Action(RuleContext, int, int) @@ -26,16 +26,20 @@ type Recognizer interface { RemoveErrorListeners() GetATN() *ATN GetErrorListenerDispatch() ErrorListener + HasError() bool + GetError() RecognitionException + SetError(RecognitionException) } type BaseRecognizer struct { listeners []ErrorListener state int - + RuleNames []string LiteralNames []string SymbolicNames []string GrammarFileName string + SynErr RecognitionException } func NewBaseRecognizer() *BaseRecognizer { @@ -58,6 +62,18 @@ func (b *BaseRecognizer) checkVersion(toolVersion string) { } } +func (b *BaseRecognizer) SetError(err RecognitionException) { + b.SynErr = err +} + +func (b *BaseRecognizer) HasError() bool { + return b.SynErr != nil +} + +func (b *BaseRecognizer) GetError() RecognitionException { + return b.SynErr +} + func (b *BaseRecognizer) Action(_ RuleContext, _, _ int) { panic("action not implemented on Recognizer!") } @@ -114,7 +130,7 @@ func (b *BaseRecognizer) SetState(v int) { // // TODO: JI This is not yet implemented in the Go runtime. Maybe not needed. func (b *BaseRecognizer) GetRuleIndexMap() map[string]int { - + panic("Method not defined!") // var ruleNames = b.GetRuleNames() // if (ruleNames==nil) { @@ -204,7 +220,7 @@ func (b *BaseRecognizer) GetTokenErrorDisplay(t Token) string { s = strings.Replace(s, "\t", "\\t", -1) s = strings.Replace(s, "\n", "\\n", -1) s = strings.Replace(s, "\r", "\\r", -1) - + return "'" + s + "'" } diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Go/Go.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Go/Go.stg index 5e762e32ef..c11d2b5316 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Go/Go.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Go/Go.stg @@ -333,15 +333,11 @@ func (l *) Sempred(localctx antlr.RuleContext, ruleIndex, predIndex */ RuleActionFunction(r, actions) ::= << func (l *) _Action(localctx antlr.RuleContext*, actionIndex int) { - this := l - _ = this - switch actionIndex { : }; separator="\n\n"> - default: panic("No registered action for: " + fmt.Sprint(actionIndex)) @@ -354,9 +350,6 @@ func (l *) _Action(localctx ) _Sempred(localctx antlr.RuleContext, predIndex int) bool { - this := p - _ = this - switch predIndex { : @@ -381,9 +374,6 @@ RuleFunction(currentRule, args, code, locals, ruleCtx, altLabelCtxs, namedAction func (p *) ( }; separator=", ">) (localctx I) { - this := p - _ = this - localctx = New(p, p.GetParserRuleContext(), p.GetState()}>) p.EnterRule(localctx, , RULE_) @@ -393,30 +383,6 @@ func (p *) (}; separator="\n"> - - defer func() { - - - - p.ExitRule() - }() - - defer func() { - if err := recover(); err != nil { - - - - if v, ok := err.(antlr.RecognitionException); ok { - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - } else { - panic(err) - } - - } - }() - var _alt int @@ -436,7 +402,20 @@ func (p *) ( +errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + + + + p.ExitRule() return localctx + goto errorExit // Trick to prevent compiler error if the label is not used } >> @@ -457,10 +436,8 @@ func (p *) () (_p int }>) (localctx I) { - this := p - _ = this - var _parentctx antlr.ParserRuleContext = p.GetParserRuleContext() + _parentState := p.GetState() localctx = New(p, p.GetParserRuleContext(), _parentState}>) var _prevctx I = localctx @@ -474,26 +451,6 @@ func (p *) (_p int}; separator="\n"> - - defer func() { - - - - p.UnrollRecursionContexts(_parentctx) - }() - - defer func() { - if err := recover(); err != nil { - if v, ok := err.(antlr.RecognitionException); ok { - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - } else { - panic(err) - } - } - }() - var _alt int @@ -513,7 +470,20 @@ func (p *) (_p int + errorExit: + if p.HasError() { + v := p.GetError() + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + p.SetError(nil) + } + + + + p.UnrollRecursionContexts(_parentctx) return localctx + goto errorExit // Trick to prevent compiler error if the label is not used } >> @@ -542,6 +512,9 @@ CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= << LL1AltBlock(choice, preamble, alts, error) ::= << p.SetState() p.GetErrorHandler().Sync(p) +if p.HasError() { + goto errorExit +} = p.GetTokenStream().LT(1) @@ -568,7 +541,9 @@ default: LL1OptionalBlock(choice, alts, error) ::= << p.SetState() p.GetErrorHandler().Sync(p) - +if p.HasError() { + goto errorExit +} switch p.GetTokenStream().LA(1) { }; separator=", ">: @@ -587,6 +562,9 @@ p.SetState() But, see TestLeftRecursion.testJavaExpressions_10, 11 which fails with sync() !> p.GetErrorHandler().Sync(p) +if p.HasError() { + goto errorExit +} @@ -604,6 +582,9 @@ if { LL1StarBlockSingleAlt(choice, loopExpr, alts, preamble, iteration) ::= << p.SetState() p.GetErrorHandler().Sync(p) +if p.HasError() { + goto errorExit +} @@ -615,6 +596,9 @@ for { p.SetState() p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } @@ -624,6 +608,9 @@ for { LL1PlusBlockSingleAlt(choice, loopExpr, alts, preamble, iteration) ::= << p.SetState() p.GetErrorHandler().Sync(p) +if p.HasError() { + goto errorExit +} @@ -635,6 +622,9 @@ for ok := true; ok; ok = { p.SetState() p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } @@ -646,6 +636,10 @@ for ok := true; ok; ok = { AltBlock(choice, preamble, alts, error) ::= << p.SetState() p.GetErrorHandler().Sync(p) +if p.HasError() { + goto errorExit +} + = _input.LT(1) @@ -655,11 +649,13 @@ p.GetErrorHandler().Sync(p) -switch p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), , p.GetParserRuleContext()) { +switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), , p.GetParserRuleContext()) { : }; separator="\n\n"> +case antlr.ATNInvalidAltNumber: + goto errorExit } >> @@ -669,9 +665,10 @@ p.GetErrorHandler().Sync(p) -, p.GetParserRuleContext()) == +1 { +, p.GetParserRuleContext()) == +1 { -}; separator="} else "> + \} else if p.HasError() { // JIM + goto errorExit}; separator="} else "> } >> @@ -679,8 +676,13 @@ p.GetErrorHandler().Sync(p) StarBlock(choice, alts, Sync, iteration) ::= << p.SetState() p.GetErrorHandler().Sync(p) -_alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), , p.GetParserRuleContext()) - +if p.HasError() { + goto errorExit +} +_alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), , p.GetParserRuleContext()) +if p.HasError() { + goto errorExit +} for _alt != && _alt != antlr.ATNInvalidAltNumber { if _alt == 1+1 { @@ -692,13 +694,22 @@ for _alt != && _alt != antlr.ATNInvalidAltNumber { } p.SetState() p.GetErrorHandler().Sync(p) - _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), , p.GetParserRuleContext()) + if p.HasError() { + goto errorExit + } + _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), , p.GetParserRuleContext()) + if p.HasError() { + goto errorExit + } } >> PlusBlock(choice, alts, error) ::= << p.SetState() p.GetErrorHandler().Sync(p) +if p.HasError() { + goto errorExit +} _alt = 1+1 for ok := true; ok; ok = _alt != && _alt != antlr.ATNInvalidAltNumber { switch _alt { @@ -716,13 +727,19 @@ for ok := true; ok; ok = _alt != && _alt != antlr.ATNInvalidAlt p.SetState() p.GetErrorHandler().Sync(p) - _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), , p.GetParserRuleContext()) + _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), , p.GetParserRuleContext()) + if p.HasError() { + goto errorExit + } } >> Sync(s) ::= "Sync()" -ThrowNoViableAlt(t) ::= "panic(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil))" +ThrowNoViableAlt(t) ::= << +p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) +goto errorExit +>> TestSetInline(s) ::= << }; separator=" || "> @@ -788,6 +805,10 @@ MatchToken(m) ::= << p.Match() + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } } >> @@ -846,7 +867,8 @@ SemPred(p, chunks, failChunks) ::= << p.SetState() if !() { - panic(antlr.NewFailedPredicateException(p, , , , "")) + p.SetError(antlr.NewFailedPredicateException(p, , , , "")) + goto errorExit } >>