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
] == '#') pos
++;
141 bib_fields (string s
, int& pos
, string ce
, string tag
, tree
& fields
) {
142 if (!bib_ok (s
, pos
)) return;
145 while (bib_ok (s
, pos
) && s
[pos
] == ',') {
149 while (bib_ok (s
, pos
) && !bib_is_in (s
[pos
], ce
)) {
153 bib_until (s
, pos
, string ("={( \t\n\r"), param
);
154 if (bib_ok (s
, pos
) && (s
[pos
]=='{' || s
[pos
]=='(')) {
159 bib_char (s
, pos
, '=');
161 bib_arg (s
, pos
, ce
, arg
);
162 if (tag
== "bib-field") param
= locase_all (param
);
163 arg
= simplify_correct (arg
);
164 fields
<< compound (tag
, param
, arg
);
166 while (bib_ok (s
, pos
) && s
[pos
] == ',') {
174 bib_string (string s
, int& pos
, tree
& t
) {
175 if (!bib_ok (s
, pos
)) return;
176 tree fields
= tree (DOCUMENT
);
177 string cs
= ", \t\n\r";
180 case '{': cend
= '}'; break;
181 case '(': cend
= ')'; break;
182 default: pos
= -1; return;
189 bib_fields (s
, pos
, ce
, string ("bib-assign"), fields
);
191 bib_char (s
, pos
, cend
);
196 bib_preamble (string s
, int& pos
, tree
& t
) {
197 if (!bib_ok (s
, pos
)) return;
201 case '{': cend
= '}'; break;
202 case '(': cend
= ')'; break;
203 default: pos
= -1; return;
208 while (bib_ok (s
, pos
) && s
[pos
] == ',') {
212 while (bib_ok (s
, pos
) && s
[pos
] != cend
) {
215 bib_arg (s
, pos
, cs
, arg
);
216 arg
= simplify_correct (arg
);
217 t
<< compound ("bib-latex", arg
);
219 while (bib_ok (s
, pos
) && s
[pos
] == ',') {
225 bib_char (s
, pos
, cend
);
229 bib_entry (string s
, int& pos
, tree type
, tree
& t
) {
230 if (!bib_ok (s
, pos
)) return;
232 tree fields
= tree (DOCUMENT
);
233 string cs
= ", \t\n\r";
236 case '{': cend
= '}'; break;
237 case '(': cend
= ')'; break;
238 default: pos
= -1; return;
244 bib_until (s
, pos
, cs
, tag
);
248 bib_fields (s
, pos
, ce
, string ("bib-field"), fields
);
250 bib_char (s
, pos
, cend
);
251 entry
= compound ("bib-entry");
252 entry
<< type
<< tag
<< fields
;
257 bib_list (string s
, int& pos
, tree
& t
) {
258 if (!bib_ok (s
, pos
)) return;
259 tree
tentry (DOCUMENT
);
260 tree
tpreamble (DOCUMENT
);
261 tree
tstring (DOCUMENT
);
265 while (bib_ok (s
, pos
)) {
267 if (!bib_ok (s
, pos
)) break;
270 tree tc
= tree (DOCUMENT
);
271 bib_comment (s
, pos
, tc
);
272 tentry
<< compound ("bib-comment", tc
);
283 bib_until (s
, pos
, string ("{(= \t\n\r"), type
);
285 if (bib_ok (s
, pos
) && s
[pos
] == '=') {
286 tree
fields (DOCUMENT
);
288 bib_fields (s
, pos
, string (")}@"), string ("bib-field"), tentry
);
290 if (bib_ok (s
, pos
) && (s
[pos
]==')' || s
[pos
]=='}')) {
291 if (N(tpreamble
) != 0) t
<< compound ("bib-preamble", tpreamble
);
292 if (N(tstring
) != 0) t
<< compound ("bib-string", tstring
);
298 string stype
= locase_all (type
);
299 if (stype
== "string") {
301 if (comment
) ts
= tree (DOCUMENT
);
303 bib_string (s
, pos
, ts
);
305 if (N(ts
) == 1) tstring
<< compound ("bib-comment", ts
[0]);
306 else tstring
<< compound ("bib-comment", ts
);
309 else if (stype
== "preamble") {
311 if (comment
) tp
= tree (DOCUMENT
);
313 bib_preamble (s
, pos
, tp
);
315 if (N(tp
) == 1) tpreamble
<< compound ("bib-comment", tp
[0]);
316 else tpreamble
<< compound ("bib-comment", tp
);
321 if (comment
) te
= tree (DOCUMENT
);
323 bib_entry (s
, pos
, stype
, te
);
325 if (N(te
) == 1) tentry
<< compound ("bib-comment", te
[0]);
326 else tentry
<< compound ("bib-comment", te
);
335 // cerr << "ENTRIES: " << tentry << "\n";
336 // cerr << "PREAMBLE: " << tpreamble << "\n";
337 // cerr << "STRING: " << tstring << "\n";
338 // if (N(tpreamble) != 0) t << compound ("bib-preamble", tpreamble);
339 // if (N(tstring) != 0) t << compound ("bib-string", tstring);
341 hashmap
<string
,string
> dict
=
342 bib_strings_dict (tree (DOCUMENT
, compound ("bib-string", tstring
)));
343 t
<< A(bib_subst_vars (tentry
, dict
));
344 bib_parse_fields (t
);
348 parse_bib (string s
) {
351 bib_list (s
, pos
, r
);
352 if (N(s
) == 0 || N(r
) == 0) return tree ();
354 cerr
<< "TeXmacs] Error: failed to load BibTeX file.\n";