ABC 1.6 in BNF format

According to ABNF as described in http://www.ietf.org/rfc/rfc2234.txt.
There is also a short description of BNF as used in this file here.
By Henrik Norbeck 1 May 1997.
Corrected 6 September 1997 after comments from Laurie Griffiths
Also available as a text file.
Proposed extensions to Abc

abc-file ::= *(abc-tune / comment / linefeed / tex-command / file-fields)
; Actually this means that abc files may not contain uncommented
; text between tunes, which many files today do. Maybe this should
; be allowed.

file-fields ::= field-file / field-book / field-group / field-history / field-information / field-meter / field-origin / field-rhythm
field-file ::= "F:" text end-of-line


abc-tune ::= abc-header abc-music

abc-header ::= field-number *comment 1*field-title *other-fields field-key
; In practice, many tunes are e-mailed without field-number, ; so those wishing to implement an abc parser should treat this ; field as optional.

field-number ::= "X:" 1*DIGIT end-of-line
field-title ::= "T:" text end-of-line
other-fields ::= field-area / field-book / field-composer / field-discography / field-elemskip / field-group / field-history / field-information / field-default-length / field-meter / field-notes / field-origin / field-parts / field-tempo / field-rhythm / field-source / field-transcrnotes / comment
; field-file and field-words may not be in header (?)
field-area ::= "A:" text end-of-line
; maybe some of these field definitions should include an optional space, e.g.:
; field-area ::= "A:" [" "] text end-of-line

field-book ::= "B:" text end-of-line
field-composer ::= "C:" text end-of-line
field-discography ::= "D:" text end-of-line
field-elemskip ::= "E:" text end-of-line
field-group ::= "G:" text end-of-line
field-history ::= "H:" 1*(text end-of-line)
field-information ::= "I:" text end-of-line
field-default-length ::= "L:" note-length-strict end-of-line
field-meter ::= "M:" meter end-of-line
field-notes ::= "N:" text end-of-line
field-origin ::= "O:" text end-of-line
field-parts ::= "P:" parts end-of-line
field-tempo ::= "Q:" tempo end-of-line
field-rhythm ::= "R:" text end-of-line
field-source ::= "S:" text end-of-line
field-transcrnotes ::= "Z:" text end-of-line
field-key ::= "K:" key end-of-line

key ::= key-spec / "HP" / "Hp"
key-spec ::= keynote [mode-spec] *(" " global-accidental)
keynote ::= basenote [key-accidental]
key-accidental ::= "#" / "b"
mode-spec ::= [" "] mode [extratext]
mode ::= mode-minor / mode-major / mode-lydian / mode-ionian / mode-mixolydian / mode-dorian / mode-aeolian / mode-phrygian / mode-locrian
extratext ::= *ALPHA
global-accidental ::= accidental basenote
mode-minor ::= ("m"/"M") [("i"/"I") ("n"/"N")]
mode-major ::= ("m"/"M") ("a"/"A") ("j"/"J")
mode-lydian ::= ("l"/"L") ("y"/"Y") ("d"/"D")
mode-ionian ::= ("i"/"I") ("o"/"O") ("n"/"N")
mode-mixolydian ::= ("m"/"M") ("i"/"I") ("x"/"X")
mode-dorian ::= ("d"/"D") ("o"/"O") ("r"/"R")
mode-aeolian ::= ("a"/"A") ("e"/"E") ("o"/"O")
mode-phrygian ::= ("p"/"P") ("h"/"H") ("r"/"R")
mode-locrian ::= ("l"/"L") ("o"/"O") ("c"/"C")

meter ::= "C" / "C|" / meter-fraction
meter-fraction ::= 1*DIGIT "/" 1*DIGIT
; If we allow complex time signatures:
; meter-fraction ::= 1*DIGIT *("+" 1*DIGIT) "/" 1*DIGIT

tempo ::= 1*DIGIT / ("C" [note-length] "=" 1*DIGIT) / (note-length-strict "=" 1*DIGIT)

note-length-strict ::= 1*DIGIT "/" 1*DIGIT

parts ::= 1*part-spec
part-spec ::= (part / ( "(" 1*part-spec ")" ) ) *DIGIT
part ::= "A" / "B" / "C" / "D" / "E" / "F" / "G" / "H" / "I" / "J" / "K" / "L" / "M" / "N" / "O" / "P" / "Q" / "R" / "S" / "T" / "U" / "V" / "X" / "Y" / "Z"

end-of-line ::= *(" " / HTAB) ["%" text] linefeed


abc-music ::= 1*abc-line linefeed
abc-line ::= (1*element line-ender) / mid-tune-field / tex-command
element ::= note-element / tuplet-element / barline / nth-repeat / begin-slur / end-slur / space / user-defined
line-ender ::= comment / linefeed / line-break / no-line-break

tuplet-element ::= tuplet-spec 1*note-element
tuplet-spec ::= "(" DIGIT [":" [DIGIT] [":" [DIGIT]]]

note-element ::= note-stem [broken-rhythm]
note-stem ::= [guitar-chord] [grace-notes] *gracings (note / multi-note)
multi-note ::= "[" 1*note "]"
note ::= note-or-rest [note-length] [tie]
note-or-rest ::= pitch / rest
pitch ::= [accidental] basenote [octave]
octave ::= (1*"'") / (1*",")
note-length ::= [1*DIGIT] ["/" [1*DIGIT]]
accidental ::= "^" / "^^" / "_" / "__" / "="
basenote ::= "C" / "D" / "E" / "F" / "G" / "A" / "B" / "c" / "d" / "e" / "f" / "g" / "a" / "b"
rest ::= "z"
broken-rhythm ::= 1*"<" / 1*">"
tie ::= "-"
gracings ::= "~" / "." / "v" / "u"
grace-notes ::= "{" 1*pitch "}"

guitar-chord ::= <"> (text <"> / formal-chord
formal-chord ::= basenote [chord-type] ["/" basenote]
chord-type ::= "m" / "7" / "m7" / "0" / "o" / "+" / "mb5" / "sus" / "sus4" / "maj7" / "mmaj7" / "7sus4" / "dim" / "dim7" / "7b5" / "m7b5" / "6" / "b6" / "m6" / "mb6" / "46" / "maj9" / "9" / "add9" / "7b9" / "m9"
; There are more chord types that could be understood

barline ::= "|" / "||" / "[|" / "|]" / ":|" / "|:" / "::"
nth-repeat ::= "[1" / "[2" / "|1" / ":|2"

begin-slur ::= "("
end-slur ::= ")"

mid-tune-field ::= tune-field
tune-field ::= field-elemskip / field-key / field-default-length / field-meter / field-part / field-tempo / field-title / field-words
; field-rhythm may not be in tune (?) field-voice not defined yet
field-part ::= "P:" part end-of-line
field-words ::= "W:" text end-of-line

user-defined ::= "H" / "I" / "J" / "K" / "I" / "J" / "K" / "L" / "M" / "N"
/ "O" / "P" / "Q" / "R" / "S" / "T" / "U" / "V" / "W" / "X" / "Y" / "Z"

tex-command ::= "\" text linefeed
space ::= " " / HTAB
comment ::= "%" text (linefeed / no-line-break / line-break)
line-break ::= "!" linefeed
no-line-break ::= "\" linefeed
linefeed ::= CRLF / LF

text ::= *text-char
text-char ::= ALPHA / DIGIT / " " / HTAB / <"> / "!" / "#" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "<" / "=" / ">" / "?" / "@" / "[" / "\" / "]" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
; "%" is not included here (on purpose)!


BNF format

BNF (Backus-Naur Format) is a way to describe the syntax of file formats. It consists of definitions of the form

identifier ::= definition

The identifier is a word which describes this part of the syntax.
The ::= should be interpreted as "consists of".
The definition is a list of what this part of the syntax may contain. This may be other identifiers, or literal strings (enclosed in ""). For example, a simple sentence may be defined as

simple-sentence ::= (thenoun / pronoun) " " verb [" " adverb] "."
thenoun ::= "The" noun
noun ::= "cat" / "dog"
pronoun ::= "He" / "She" / "It"
verb ::= "runs" / "bites"
adverb ::= "quickly" / "fast"

* before an element means that it can be repeated 0 or more times.
1* before an element means that it can be repeated 1 or more times.
[] around an element means that it is optional.
/ between elements mean that you may choose any of the elements.
() can be used to group elements.

So legal "simple sentences" according to the definition above are, for example, "The cat runs.", "It bites quickly.", "He runs fast.", "The dog bites.".

Some special words are pre-defined:
DIGITAny digit 0-9
ALPHAAny letter a-z, A-Z
HTABA horizontal tab character
CRLFCarriage return character + linefeed character
LFLinefeed character

There is also a special case of literal string: If you want a quote mark, you have to write <">

A more complete description of BNF can be found at http://www.ietf.org/rfc/rfc2234.txt.