Skip to content

Commit 928663e

Browse files
authored
Merge pull request #26 from anthonygam/silent-parse-error
Extending comment scanning to resolve #24
2 parents da329ed + c1a0943 commit 928663e

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

bibtex_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,35 @@ func TestParser(t *testing.T) {
8282
}
8383
}
8484

85+
// Test bug (Issue #24) where there is no parse error, but fields are missing
86+
func TestTextOutsideEntries(t *testing.T) {
87+
// Re-create the exact failing scenario
88+
expected := NewBibTex()
89+
entry := NewBibEntry("article", "CitekeyArticle")
90+
entry.AddField("author", NewBibConst("John Doe"))
91+
entry.AddField("title", NewBibConst("The independence of the continuum hypothesis"))
92+
entry.AddField("journal", NewBibConst("Proceedings of the National Academy of Sciences"))
93+
entry.AddField("year", NewBibConst("1963"))
94+
entry.AddField("volume", NewBibConst("50"))
95+
entry.AddField("number", NewBibConst("6"))
96+
entry.AddField("pages", NewBibConst("1143--1148"))
97+
expected.AddEntry(entry)
98+
99+
// Parse file with same data as above, also with text in between the entries
100+
ex := "example/text-outside-entries.bib"
101+
b, err := os.ReadFile(ex)
102+
if err != nil {
103+
t.Errorf("Cannot read %s: %v", ex, err)
104+
}
105+
s, err := Parse(bytes.NewReader(b))
106+
if err != nil {
107+
t.Errorf("Cannot parse valid bibtex file %s: %v", ex, err)
108+
}
109+
110+
// Check equality
111+
AssertEntryListsEqual(t, expected.Entries, s.Entries)
112+
}
113+
85114
// Tests that multiple parse returns different instances of the parsed BibTex.
86115
// Otherwise the number of entries will pile up. (Issue #4)
87116
func TestMultiParse(t *testing.T) {

example/text-outside-entries.bib

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
% Encoding: UTF-8
2+
@article{CitekeyArticle,
3+
author = "John Doe",
4+
title = "The independence of the continuum hypothesis",
5+
journal = "Proceedings of the National Academy of Sciences",
6+
year = 1963,
7+
volume = "50",
8+
number = "6",
9+
pages = "1143--1148",
10+
}

example/text-outside-entries2.bib

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
% Encoding: UTF-8
2+
@article{CitekeyArticle,
3+
author = "John Doe",
4+
title = "The independence of the continuum hypothesis",
5+
journal = "Proceedings of the National Academy of Sciences",
6+
year = 1963,
7+
volume = "50",
8+
number = "6",
9+
pages = "1143--1148",
10+
}
11+
% Same entry again
12+
@article{CitekeyArticle2,
13+
author = "John Doe",
14+
title = "The independence of the continuum hypothesis",
15+
journal = "Proceedings of the National Academy of Sciences",
16+
year = 1963,
17+
volume = "50",
18+
number = "6",
19+
pages = "1143--1148",
20+
}

scanner.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ var parseField bool
1212

1313
// scanner is a lexical scanner
1414
type scanner struct {
15-
commentMode bool
16-
r *bufio.Reader
17-
pos tokenPos
15+
commentMode bool
16+
outsideEntry bool
17+
r *bufio.Reader
18+
pos tokenPos
1819
}
1920

2021
// newScanner returns a new instance of scanner.
2122
func newScanner(r io.Reader) *scanner {
22-
return &scanner{r: bufio.NewReader(r), pos: tokenPos{Char: 0, Lines: []int{}}}
23+
return &scanner{outsideEntry: true, r: bufio.NewReader(r), pos: tokenPos{Char: 0, Lines: []int{}}}
2324
}
2425

2526
// read reads the next rune from the buffered reader.
@@ -51,6 +52,11 @@ func (s *scanner) unread() {
5152

5253
// Scan returns the next token and literal value.
5354
func (s *scanner) Scan() (tok token, lit string, err error) {
55+
if s.outsideEntry {
56+
// Ordinary comment scanning, but without generating a token
57+
s.scanCommentBody()
58+
s.outsideEntry = false
59+
}
5460
ch := s.read()
5561
if isWhitespace(ch) {
5662
s.ignoreWhitespace()
@@ -91,6 +97,7 @@ func (s *scanner) Scan() (tok token, lit string, err error) {
9197
case '}':
9298
if parseField { // reset parseField if reached end of entry.
9399
parseField = false
100+
s.outsideEntry = true
94101
}
95102
return tRBRACE, string(ch), nil
96103
case '#':

0 commit comments

Comments
 (0)