Parse returns error instead of terminating with log.Fatalf - #19
Conversation
| select { | ||
| case err := <-l.Errors: | ||
| return nil,err | ||
| default : | ||
| return nil, err | ||
|
|
||
| } |
There was a problem hiding this comment.
I don't get it, why do we need to do this?
| | tBAREIDENT { v,err := bib.GetStringVar($1); if err != nil { bibtexlex.Error(fmt.Sprintf("%v",err)) } else {$$ = v} } | ||
| | longstring tPOUND tIDENT { $$ = NewBibComposite($1); $$.(*BibComposite).Append(NewBibConst($3))} | ||
| | longstring tPOUND tBAREIDENT { $$ = NewBibComposite($1); $$.(*BibComposite).Append(bib.GetStringVar($3)) } | ||
| | longstring tPOUND tBAREIDENT { $$ = NewBibComposite($1); v,err := bib.GetStringVar($3); if err != nil {bibtexlex.Error(fmt.Sprintf("%v",err))} else {$$.(*BibComposite).Append(v)} } |
There was a problem hiding this comment.
as above
| | longstring tPOUND tBAREIDENT { $$ = NewBibComposite($1); v,err := bib.GetStringVar($3); if err != nil {bibtexlex.Error(fmt.Sprintf("%v",err))} else {$$.(*BibComposite).Append(v)} } | |
| | longstring tPOUND tBAREIDENT { $$ = NewBibComposite($1); v, err := bib.GetStringVar($3); if err != nil { bibtexlex.Error(err.Error()) } else {$$.(*BibComposite).Append(v)} } |
|
|
||
| longstring : tIDENT { $$ = NewBibConst($1) } | ||
| | tBAREIDENT { $$ = bib.GetStringVar($1) } | ||
| | tBAREIDENT { v,err := bib.GetStringVar($1); if err != nil { bibtexlex.Error(fmt.Sprintf("%v",err)) } else {$$ = v} } |
There was a problem hiding this comment.
whitespaces and I'd probably use the Error() to convert to error to string than fmt it.
| | tBAREIDENT { v,err := bib.GetStringVar($1); if err != nil { bibtexlex.Error(fmt.Sprintf("%v",err)) } else {$$ = v} } | |
| | tBAREIDENT { v, err := bib.GetStringVar($1); if err != nil { bibtexlex.Error(err.Error()) } else {$$ = v} } |
| return nil, err | ||
| case err := <-l.ParseErrors: | ||
| return nil, err | ||
| case err := <-l.ParseErrors: //yacc errors |
There was a problem hiding this comment.
This isn't technically true I think? The error returned here now can be yacc (syntax) error or variable not found
|
Sorry for being unresponsive, I was on vacation. I Introduced the nested select because I noticed that the While using this PR in a project, I noticed two remaining issues that need to be addressed before this can get merged
func TestParser_NoDeadlockAnMultipleErrors(t *testing.T) {
//this entry raises multiple errors that lead to a deadlock on capacity one channels
badEntry := `@article{badEntry,
title={Bad Entry Title},
journal=should Be Quoted,
}`
_, err := Parse(strings.NewReader(badEntry))
if err == nil {
t.Fatal("Expected parser error got none")
}
}
// TestParser_ParseGoodEntryAfterBadEntry checks that parsing a bad entry does not influence further calls to parse
func TestParser_ParseGoodEntryAfterBadEntry(t *testing.T) {
goodEntry := `@article{goodEntry,
title={Good Entry Title},
}`
badEntry := `@article{badEntry,
title={Bad Entry Title},
journal=should Be Quoted,
}`
_, err := Parse(strings.NewReader(badEntry))
if err == nil {
t.Fatal("Expected parser error got none")
}
t.Logf("Done with badEntry")
_, err = Parse(strings.NewReader(goodEntry))
if err != nil {
t.Fatalf("Did not expect parser error but got %v", err)
}
}(Note that this requires you to either increase the |
The yacc generated parser don't return the idiomatic (token, error), which was why we set up a separate channel for error(s) for the lexer to return the error in a back-channel. I'm not against putting it in a slice though, it makes sense. |
|
I've updated the error reporting and handling -- if you wouldn't mind merging those changes here and see if that works with your change to return error 🙏 |
84ede81 to
26afbc3
Compare
|
Thanks. I merged your changes. I still need to figure out why the error state persists between parser runs though |
I don't necessarily think it's state persisting between parser runs. Even if you ignore the errors like |
This is my attempt at solving #18 . Feedback is welcome.
(I used the
golang.org/x/tools/cmd/goyaccversion of goyacc)