BibTeX で関数を間接的に呼び出す (文字列を使用)

BibTeX で関数を間接的に呼び出す (文字列を使用)

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>1nCase nOther cases{ Case n } <string n>{ 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}

関連情報