%20%D0%B2%20BibTeX.png)
Возможно ли делать косвенные вызовы функций в стилях BibTeX, т. е. получать имя функции из поля в .bib
? EXECUTE
это можно сделать, но эти операторы не работают внутри функций(?).
Мой текущий обходной путь — извлечь имя поля, сравнить его со строковым литералом и вызвать соответствующую функцию, если оно совпадает. Это работает, но это ужасно (так что, наверное, правильно, поскольку это .bst
? :)
Например:
FUNCTION {format.thesis.type}
{ this.to.prev.status
this.status.std
type empty$
{
% Leave warnings to callers
""
}
{
type "bthesis" =
{
bbl.bthesis
}
{
type "mthesis" =
{
bbl.mthesis
}
{
type "phdthesis" =
{
bbl.phdthesis
}
{
type "Unknown thesis type " swap$ * ", printing it verbatim" * warning$
type
}
if$
}
if$
}
if$
}
if$
cap.status.std
}
решение1
Как вы догадались, это невозможно.
BibTeX, как и TeX, сохраняет функции в хэш-таблице. TeX должен \csname<control-sequence>\endcsname
извлечь запись хэш-таблицы, которая соответствует строковому литералу <control-sequence>
.
BibTeX этого не делает :-)
Чтобы это реализовать, вам придется добавить эту функциональность в сам BibTeX (что может оказаться не самой веселой задачей).
В качестве утешительного приза предлагаем вам strcase
функцию, которая, возможно, сделает эту задачу менее скучной.
Синтаксис следующий:
{ Other cases } "{OTHERWISE}"
{ Case n } <string n>
...
{ Case 2 } <string 2>
{ Case 1 } <string 1>
<string> strcase
Функция strcase
будет сравнивать <string>
с каждым <string n>
(от 1
до n
: это обратная польская запись, поэтому она будет читать элементы в обратном порядке), и как только совпадение будет найдено, код для Case n
будет выполнен, а остальное будет отброшено (даже если совпадений не найдено несколько строк). Если совпадений не найдено, код Other cases
будет выполнен. Вы можете использовать столько { Case n } <string n>
пар, сколько захотите, но final { Other cases } "{OTHERWISE}"
является обязательным, чтобы функция знала, где остановиться.
Ваш случай можно записать следующим образом (с предварительной проверкой) type missing$
:
FUNCTION {format.thesis.type}
{ this.to.prev.status
this.status.std
type missing$
{
% Do something when type is not given
}
{
{ "Unknown thesis type " type ", printing it verbatim" * * warning$ }
"{OTHERWISE}"
{ bbl.bthesis } "bthesis"
{ bbl.mthesis } "mthesis"
{ bbl.phdthesis } "phdthesis"
type strcase
}
if$
cap.status.std
}
Вот пример компилируемого кода .bst
:
\begin{filecontents*}{test.bst}
ENTRY { type name } { } { }
INTEGERS { strcase.next } % the code requires an integer
STRINGS { s t } % and two strings
FUNCTION { not }
{ { #0 }
{ #1 }
if$
}
FUNCTION { pop.next } { swap$ pop$ }
FUNCTION { strcase.end }
{ #0 'strcase.next :=
#1
swap$
'skip$
if$
}
FUNCTION { strcase }
{ #1 'strcase.next :=
{ strcase.next }
{ 's :=
't :=
s t =
{ { swap$ "{OTHERWISE}" = not }
{ pop.next }
while$
pop.next
strcase.end
}
{ "{OTHERWISE}" t =
{ strcase.end }
{ pop$ s }
if$
}
if$
}
while$
}
FUNCTION { thesis }
{
type missing$
{ "Type missing for entry " cite$ * warning$ }
{
{ "Unknown thesis type " type ", printing it verbatim" * * warning$ }
"{OTHERWISE}"
{ "This is a bachelor thesis" warning$ } "bthesis"
{ "This is a master thesis" warning$ } "mthesis"
{ "This is a doctor thesis" warning$ } "phdthesis"
type strcase
}
if$
}
READ
ITERATE {call.type$}
\end{filecontents*}
\begin{filecontents*}{test.bib}
@thesis{bach, type = {bthesis}}
@thesis{mast, type = {mthesis}}
@thesis{doct, type = {phdthesis}}
@thesis{unkn, type = {unknown}}
@thesis{void, name = {me}}
\end{filecontents*}
\documentclass{article}
\begin{document}
\nocite*
\bibliography{test}
\bibliographystyle{test}
\end{document}