Dislocations between Beastie and BibTeX

Beastie is not intended to be a complete and exact replacement for BibTeX, and certainly not ‘bug-compatible’. It should be broadly compatible with BibTeX in ‘normal’ use (for most values of ‘normal’), but may treat edge cases differently.

In particular, there is a (2007) list of ‘BibTeX Tips and FAQ’ at the CTAN package page, which describes a fairly arcane set of tricks and workarounds to deal with the wide variation in names across the world. Some of these are very specific to the way that bibtex-the-program implements its (sometimes rather ill-defined) rules for parsing names, and few of them are situations authors are likely to encounter frequently. If Beastie behaves differently from BibTeX in similar cases, I do not intend to immediately class that as a bug.

Deviations from BibTeX behaviour, and other anomalies

Parsing .bib files

Citation keys and field names

Beastie has a slightly narrower definition of legal entry and citation keys, than BibTeX has. BibTeX appears to accept just about any characters (or even any bytes) here that aren't syntactically special to that program. That's agreeably laid-back, but not perhaps very friendly to parser-writers. It also meant that, if people used non-ASCII characters here, the keys would potentially have different values depending on the assumed coding of the .bib file. Beastie restricts the keys here a little more than Nelson Beebe's proposal: the goal is to accept most of what I've seen in the wild, as it were, while ruling out characters that seem to be asking for trouble. These prescriptions explicitly include sets of Unicode codepoints.

The ‘word characters’ here are those characters that may conventionally be regarded as part of a word. There isn't a formal definition of this set in Unicode, but a conventional definition is Unicode ‘alphabetic’ characters, plus diacritics, extender characters and join-control characters (characters, that is, which possess the Unicode properties Alphabetic (which overlaps with ASCII [A-Za-z]), Diacritic, Extender and Join_Control – see the Unicode Character Database (UCD) for intricate details). The Beastie uchar-alphabetic? and uchar-word-character? predicates test for these.

Beastie currently restricts each of these predicates to the Base Multiligual Plane (BMP) only (ie, codepoints up to U+FFFF); non-BMP characters are fine in strings.

A grammar for .bib files

input: opt_interentry_text list_of_stanzas opt_interentry_text

list_of_stanzas: stanza
  | list_of_stanzas opt_interentry_text stanza

opt_interentry_text: /* empty */
  | opt_interentry_text INTERENTRYTEXT

stanza: entry
  | atpreamble | atstring
  | atcomment  | atinclude

entry: ENTRYTYPE '{' NAME \
        ',' list_of_fields '}'
  | ENTRYTYPE '{' NAME '}'
  | ENTRYTYPE '{' NAME ',' '}'
    /* at most one trailing comma */

list_of_fields: field
  | list_of_fields ',' field
  | list_of_fields ',' /* ditto */

field: NAME '=' string

atpreamble: ATPREAMBLE '{' string '}'

atstring: ATSTRING '{' NAME '=' string '}'

atinclude: ATINCLUDE '{' NAME '}'

atcomment: ATCOMMENT string

string: STRINGVALUE
  | NAME
  | string '#' STRINGVALUE
  | string '#' NAME

The terminals in this grammar are ENTRYTYPE, representing @article and the like; terminals representing the standard @preamble, @string and @comment forms, and a further terminal representing the extension @include form (all case-insensitive); NAME represents a entry key or field, STRINGVALUE a field value "..." or {...}, and INTERENTRYTEXT any other text between entries.

In fact, Beastie uses a slightly different (non-yacc) grammar framework to do its work, but it should be equivalent to this one. The lexer produces terminals ',', '=', '#', '{' and '}' after having stripped surrounding whitespace, and the latter two can be produced by the corresponding characters, or by '(' or ')', in a modest concession to Scribe's continuing legacy in extant .bib files.

.bst and btxhak

The ‘standard’ here is the btxhak.pdf document at CTAN. Unfortunately, that document is a little vague in places. Nicolas Markey's Tame the BeaST document is an account of the whole BibTeX ecosystem, including a description of the .bst language.

btx anomalies

Parsing names

Beyond the individual puzzles above, there is also a problem, easy to miss but hard to ignore, that BibTeX's conventions for structuring a name into first-von-last-junior parts, though elegant, may be insufficient for a fully international bibliographic solution, and the wide range of ways in which real names must be sliced up and reassembled.

One systematic approach to this is the section of the Unicode CLDR devoted to person names. This describes a structure for recording names which doesn't have to go very far beyond BibTeX's four-part division. It can't accommodate everything (arabic names, for example, have notably intricate structure, discussed illuminatingly in a LanguageHat blogpost and in A.F.L Beeston’s ‘Arabic Nomenclature’, and the W3C document mentions some of the variation possible), but it can accommodate the practical basics of naming structures in a wide variety of locales. The OASIS ‘Extensible Name Language’, OASIS-xNL, is broadly similar to the CLDR one, as an internationalised schema for describing names. And the Citation Style Language includes a structure for names very similar to BibTeX's, but with five parts rather than four (it distinguishes von-parts which do and don't disappear when only a surname is shown). The W3C, and the Dublin Core consortium, have published helpfully wide-ranging discussions of the names problem: their advice to keep things as simple as possible is practical in general, but too simple for our bibliographic problem.

The CLDR's framework seems both a feasible increment on BibTeX's framework, and as comprehensive as a BibTeX successor needs to be.

Possible other sources: The Chicago Manual of Style, chapter 8, gives some detailed and explicit suggestions in this area; I'm sure they're entertainingly disputed wherever and whenever copy-editors are wont to gather for recreation purposes (though they are quite extensive, they don't seem to resolve the ‘J.P’ vs. ‘J.-P.’ question above; the CLDR document suggests the correct practice here might be locale-dependent). Butcher's copy-editing (CUP, 2012) includes much useful general information, but doesn't really address name-parsing. ‘BS 5605:1990 – Recommendations for citing and referencing published material’ might be of interest, but it gives only general suggestions about formatting of bibliographies.

The library community seems less helpful here than one might initially guess, since their concern with names is both more specific (locating objects by author name) and more general (doing so through all of recorded history): the librarians' MARC, and associated standards, are more concerned to identify canonical versions of names (the process of ‘authority control’), than to analyse them. The Anglo-American Cataloguing Rules, though now superseded, provide a link to successor standards in this particular area.

Summary: names are hard (quoth falsehoods, ob-xkcd, and lots more).

Enhancements and changes to the .bst language

Deviations from bibtex behaviour:

This seems to be an opportunity to add a couple of minor enhancements to the .bst language, in the form of additional built-in functions. These are documented in the bst module documentation, and include:

The excellent ‘Tame the BeaST’ document describes, and implements a number of useful extension functions. Several of these would be excellent candidates for implementation as new primitives in Beastie. It can be usefully supplemented by the observations and suggestions in Shell and Hoadley's BibTeX FAQ. The BibTeXu documentation describes some additional and some extended primitive functions. Would anyone be interested in regexps in .bst?

Grammars

A grammar for .bst files

For completeness, the grammar I have used for .bst files is as follows.

input: list.of.commands

list.of.commands:
    command
  | list.of.commands command

command:
    CMD_ENTRY braced.list.of.tokens braced.list.of.tokens braced.list.of.tokens
  | CMD_EXECUTE '{' TOKEN '}'
  | CMD_FUNCTION '{' TOKEN '}' function.body
  | CMD_INTEGERS braced.list.of.tokens
  | CMD_ITERATE '{' TOKEN '}'
  | CMD_MACRO '{' TOKEN '}' '{' STRING '}'
  | CMD_READ
  | CMD_REVERSE '{' TOKEN '}'
  | CMD_SORT
  | CMD_STRINGS braced.list.of.tokens

function.body: braced.list.of.tokens

braced.list.of.tokens:
    '{' '}'
  | '{' list.of.tokens '}'

list.of.tokens:
    token
  | braced.list.of.tokens
  | list.of.tokens token
  | list.of.tokens braced.list.of.tokens

token:
    TOKEN
  | NUMBER
  | STRING
  | QUOTE TOKEN
  | ':='
  | '>'
  | '<'
  | '='
  | '+'
  | '-'
  | '*'

The terminals are:

White space is permitted between all of the lexical elements, apart from after the QUOTE terminal (Beastie warns if it finds a space here, but accepts it).

The Beastie lexer discards everything from a % to the end of line, regarding it as whitespace.

A grammar for author-format-strings

The btxhak document, in its final section, implies a grammar for the format-strings used by format.name$. I believe it is equivalent to the following:

input: list.of.specs

list.of.specs:
    string.or.piece
  | list.of.specs string.or.piece

/* a 'piece' is a brace-level-1 element like {f}, which must include a FMTSYM */
piece: '{' list.nonalpha.or.tie fmt list.nonalpha.or.tie '}'

list.nonalpha.or.tie:
    /* empty */
  | nonalpha.or.tie
  | list.nonalpha.or.tie nonalpha.or.tie

fmt:
    FMTSYM
  | FMTSYM '{' maybe.string '}'

string.or.piece: STRING | piece

nonalpha.or.tie: NONALPHA | '~' | '~~'

maybe.string:
    /* empty */
  | STRING

Terminals:

The grammar here requires that the underlying lexer is sensitive to the brace-level, and will produce tokens FMTSYM, NONALPHA, ~ and ~~ only within brace-level 1, and that it will additionally object to any letters other than [fvlj] at brace-level 1.

Norman
2026 August 02