1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
/* $Id: bib.pl,v 1.1.1.1 1994/06/27 13:17:20 jan Exp $
Part of XPCE
Designed and implemented by Anjo Anjewierden and Jan Wielemaker
E-mail: jan@swi.psy.uva.nl
Copyright (C) 1994 University of Amsterdam. All rights reserved.
*/
:- module(pce_bibtex, []).
:- use_module(library(pce)).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
This library file defines a parser for BibTeX database files. It is
intended as an example for using XPCE's text-manipulation and data
representation techniques and may be used as a starting point for
implementing a BibTeX database manager program.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*******************************
* DATABASE *
*******************************/
:- pce_begin_class(bibtex_db, hash_table, "BibTeX DataBase").
variable(strings, sheet, get, "Table of strings").
variable(file, file*, get, "File it was loaded from").
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
A BibTeX database is represented by a hash_table mapping keys onto
bibtex_entry objects. A bibtex_entry is subclass of class sheet.
The database as a whole also stores a sheet for the defined
string-constants as well as a reference to the file it was loaded from
(if any).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
initialise(DB, File:[file]*) :->
"Create BibTeX database from file"::
send(DB, send_super, initialise),
send(DB, slot, strings, new(sheet)),
( File \== @default
-> send(DB, slot, file, File),
send(DB, load, File)
).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The database is parsed using a text_buffer. This allows us to easily
exploit the regular-expression capabilities of XPCE implemented by class
regex.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
load(DB, File:file) :->
"Load entries from file"::
new(TB, text_buffer),
send(TB, insert_file, 0, File),
send(DB, parse, TB),
free(TB).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Toplevel loop to parse a BibTeX file. First of all, the syntax-table of
the text_buffer is modified to treat the newline as white_space,
allowing the '\s ' operator in regular expressions to include newlines.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
parse(DB, TB:text_buffer) :->
"Parse all entries from given text-buffer"::
new(Here, number(0)),
get(TB, size, Size),
send(TB, syntax, new(S, syntax_table)),
send(S, add_syntax, '\n', white_space),
repeat,
send(DB, parse_entry, TB, Here),
get(Here, value, Size), !.
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Regular expression constants for the various fields of a BibTeX file.
Note that GNU-regular expression define `syntax categories': '\s ' means
`any white character (as defined by the syntax table)', '\w' means `any
word character'. '\S ' and '\W' are negations. See class regex for a
full description.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- pce_global(@bibtex_head_regex,
new(regex('@\(\w+\){'))).
:- pce_global(@bibtex_key_regex,
new(regex('\s *\(\S +\)\s *,'))).
:- pce_global(@bibtex_att_regex,
new(regex('\s *\(\w+\)\s *=\s *\("\(\\"\|[^"]\)*"\|\w+\|[^,]+\)\s *,?'))).
:- pce_global(@bibtex_end_attr_regex,
new(regex('\s *}\s *'))).
parse_entry(DB, TB:text_buffer, Here:number) :->
"Parse 1 entry"::
send(@bibtex_head_regex, search, TB, Here), !,
get(@bibtex_head_regex, register_value, TB, 1, name, T0),
send(Here, value, @bibtex_head_regex?register_end),
get(T0, downcase, Type),
( Type == string
-> ( send(@bibtex_att_regex, match, TB, Here)
-> get(@bibtex_att_regex, register_value, TB, 1, name, SName),
get(@bibtex_att_regex, register_value, TB, 2, SValue),
send(DB?strings, value, SName, SValue),
send(Here, value, @bibtex_att_regex?register_end)
; send(TB, report, error, 'Illegal string at %d', Here),
fail
)
; send(@bibtex_key_regex, match, TB, Here),
get(@bibtex_key_regex, register_value, TB, 1, name, Key),
send(DB, append, Key, new(E, bibtex_entry(Type, Key))),
send(Here, value, @bibtex_key_regex?register_end),
repeat,
( send(E, parse_attribute, TB, Here)
-> ( send(@bibtex_end_attr_regex, match, TB, Here)
-> !,
send(Here, value, @bibtex_end_attr_regex?register_end)
; fail
)
; !,
send(TB, report, error, 'Cannot parse attribute at %d', Here),
fail
)
).
:- pce_end_class.
/*******************************
* ENTRY *
*******************************/
:- pce_begin_class(bibtex_entry, sheet).
initialise(E, Type:name, Key:name) :->
send(E, send_super, initialise),
send(E, value, type, Type),
send(E, value, key, Key).
parse_attribute(E, TB:text_buffer, Here:number) :->
"Parse attribute-value pair"::
send(@bibtex_att_regex, match, TB, Here),
get(@bibtex_att_regex, register_value, TB, 1, name, AName),
get(@bibtex_att_regex, register_value, TB, 2, AValue),
send(E, value, AName, AValue),
send(Here, value, @bibtex_att_regex?register_end).
:- pce_end_class.
|