2 /******************************************************************************
3 * MODULE : parsebib.cpp
4 * DESCRIPTION: conversion of bibtex strings into logical bibtex trees
5 * COPYRIGHT : (C) 2010 David MICHEL
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
12 #include "convert.hpp"
13 #include "analyze.hpp"
15 #include "tree_traverse.hpp"
16 #include "Bibtex/bibtex_functions.hpp"
19 bib_ok (string s
, int pos
) {
20 return 0 <= pos
&& pos
< N(s
);
24 bib_char (string s
, int& pos
, char c
) {
25 if (!bib_ok (s
, pos
)) return;
26 if (s
[pos
] == c
) pos
++;
28 cerr
<< "TeXmacs] Error: invalid BibTeX file.\n";
29 if (c
) cerr
<< "TeXmacs] Invalid char: \'" << s
[pos
]
30 << "\', expected \'" << c
<< "\'\n";
36 bib_is_in (char c
, string cs
) {
38 while (i
< N(cs
) && cs
[i
] != c
) i
++;
43 bib_blank (string s
, int& pos
) {
44 if (!bib_ok (s
, pos
)) return;
46 while (bib_ok (s
, pos
) && bib_is_in (s
[pos
], cs
)) pos
++;
50 bib_within (string s
, int& pos
, char cbegin
, char cend
, string
& content
) {
51 if (!bib_ok (s
, pos
)) return;
53 bib_char (s
, pos
, cbegin
);
54 while (bib_ok (s
, pos
) && (s
[pos
] != cend
|| depth
> 0)) {
56 if (s
[pos
] == cbegin
) depth
++;
57 else if (s
[pos
] == cend
) depth
--;
59 if (s
[pos
] == '\\' && bib_ok (s
, pos
+1)) {
66 bib_char (s
, pos
, cend
);
70 bib_until (string s
, int& pos
, string cs
, string
& content
) {
71 if (!bib_ok (s
, pos
)) return;
72 while (bib_ok (s
, pos
) && !bib_is_in (s
[pos
], cs
)) {
79 bib_comment (string s
, int& pos
, tree
& t
) {
80 if (!bib_ok (s
, pos
)) return;
82 while (bib_ok (s
, pos
) && s
[pos
] == '%') {
83 bib_char (s
, pos
, '%');
84 while (bib_ok (s
, pos
) && s
[pos
] != '\n') {
88 t
<< compound ("bib-line", content
);
94 void bib_atomic_arg (string s
, int& pos
, string ce
, tree
& a
) {
95 if (!bib_ok (s
, pos
)) return;
100 bib_within (s
, pos
, '\"', '\"', sa
);
105 bib_within (s
, pos
, '{', '}', sa
);
110 string cs
= ", \t\n\r";
112 if (!is_digit (s
[pos
])) {
113 bib_until (s
, pos
, cs
, sa
);
114 a
= compound ("bib-var", sa
);
117 bib_until (s
, pos
, cs
, sa
);
126 bib_arg (string s
, int& pos
, string ce
, tree
& arg
) {
127 if (!bib_ok (s
, pos
)) return;
130 while (bib_ok (s
, pos
) && !bib_is_in (s
[pos
], cs
)) {
132 bib_atomic_arg (s
, pos
, ce
, a
);
135 if (bib_ok (s
, pos
) && s
[pos
] == '#') {
144 bib_fields (string s
, int& pos
, string ce
, string tag
, tree
& fields
) {
145 if (!bib_ok (s
, pos
)) return;
148 while (bib_ok (s
, pos
) && s
[pos
] == ',') {
152 while (bib_ok (s
, pos
) && !bib_is_in (s
[pos
], ce
)) {
156 bib_until (s
, pos
, string ("={( \t\n\r"), param
);
157 if (bib_ok (s
, pos
) && (s
[pos
]=='{' || s
[pos
]=='(')) {
162 bib_char (s
, pos
, '=');
164 bib_arg (s
, pos
, ce
, arg
);
165 if (tag
== "bib-field") param
= locase_all (param
);
166 arg
= simplify_correct (arg
);
167 fields
<< compound (tag
, param
, arg
);
171 while (bib_ok (s
, pos
) && !bib_is_in (s
[pos
], cend
)) pos
++;
172 while (bib_ok (s
, pos
) && s
[pos
] == ',') {
180 bib_string (string s
, int& pos
, tree
& t
) {
181 if (!bib_ok (s
, pos
)) return;
182 tree fields
= tree (DOCUMENT
);
183 string cs
= ", \t\n\r";
186 case '{': cend
= '}'; break;
187 case '(': cend
= ')'; break;
188 default: pos
= -1; return;
195 bib_fields (s
, pos
, ce
, string ("bib-assign"), fields
);
197 bib_char (s
, pos
, cend
);
202 bib_preamble (string s
, int& pos
, tree
& t
) {
203 if (!bib_ok (s
, pos
)) return;
207 case '{': cend
= '}'; break;
208 case '(': cend
= ')'; break;
209 default: pos
= -1; return;
214 while (bib_ok (s
, pos
) && s
[pos
] == ',') {
218 while (bib_ok (s
, pos
) && s
[pos
] != cend
) {
221 bib_arg (s
, pos
, cs
, arg
);
222 arg
= simplify_correct (arg
);
223 t
<< compound ("bib-latex", arg
);
225 while (bib_ok (s
, pos
) && s
[pos
] == ',') {
231 bib_char (s
, pos
, cend
);
235 bib_entry (string s
, int& pos
, tree type
, tree
& t
) {
236 if (!bib_ok (s
, pos
)) return;
238 tree fields
= tree (DOCUMENT
);
239 string cs
= ",\t\n\r";
242 case '{': cend
= '}'; break;
243 case '(': cend
= ')'; break;
244 default: pos
= -1; return;
250 bib_until (s
, pos
, cs
, tag
);
254 bib_fields (s
, pos
, ce
, string ("bib-field"), fields
);
256 bib_char (s
, pos
, cend
);
257 entry
= compound ("bib-entry");
258 entry
<< type
<< tag
<< fields
;
263 bib_list (string s
, int& pos
, tree
& t
) {
264 if (!bib_ok (s
, pos
)) return;
265 tree
tentry (DOCUMENT
);
266 tree
tpreamble (DOCUMENT
);
267 tree
tstring (DOCUMENT
);
271 while (bib_ok (s
, pos
)) {
273 if (!bib_ok (s
, pos
)) break;
276 tree tc
= tree (DOCUMENT
);
277 bib_comment (s
, pos
, tc
);
278 tentry
<< compound ("bib-comment", tc
);
289 bib_until (s
, pos
, string ("{(= \t\n\r"), type
);
291 if (bib_ok (s
, pos
) && s
[pos
] == '=') {
292 tree
fields (DOCUMENT
);
294 bib_fields (s
, pos
, string (")}@"), string ("bib-field"), tentry
);
296 if (bib_ok (s
, pos
) && (s
[pos
]==')' || s
[pos
]=='}')) {
297 if (N(tpreamble
) != 0) t
<< compound ("bib-preamble", tpreamble
);
298 if (N(tstring
) != 0) t
<< compound ("bib-string", tstring
);
304 string stype
= locase_all (type
);
305 if (stype
== "string") {
307 if (comment
) ts
= tree (DOCUMENT
);
309 bib_string (s
, pos
, ts
);
311 if (N(ts
) == 1) tstring
<< compound ("bib-comment", ts
[0]);
312 else tstring
<< compound ("bib-comment", ts
);
315 else if (stype
== "preamble") {
317 if (comment
) tp
= tree (DOCUMENT
);
319 bib_preamble (s
, pos
, tp
);
321 if (N(tp
) == 1) tpreamble
<< compound ("bib-comment", tp
[0]);
322 else tpreamble
<< compound ("bib-comment", tp
);
327 if (stype
== "comment") comment
= true;
328 if (comment
) te
= tree (DOCUMENT
);
330 bib_entry (s
, pos
, stype
, te
);
332 if (N(te
) == 1) tentry
<< compound ("bib-comment", te
[0]);
333 else tentry
<< compound ("bib-comment", te
);
342 // cerr << "ENTRIES: " << tentry << "\n";
343 // cerr << "PREAMBLE: " << tpreamble << "\n";
344 // cerr << "STRING: " << tstring << "\n";
345 // if (N(tpreamble) != 0) t << compound ("bib-preamble", tpreamble);
346 // if (N(tstring) != 0) t << compound ("bib-string", tstring);
348 hashmap
<string
,string
> dict
=
349 bib_strings_dict (tree (DOCUMENT
, compound ("bib-string", tstring
)));
350 t
<< A(bib_subst_vars (tentry
, dict
));
351 bib_parse_fields (t
);
355 parse_bib (string s
) {
358 bib_list (s
, pos
, r
);
359 if (N(s
) == 0 || N(r
) == 0) return tree ();
361 cerr
<< "TeXmacs] Error: failed to load BibTeX file.\n";