We modify the original paper's grammar to simplify the sharps and flats, and then extend the set of quality shorthands
<chord> ::= <nochord>
| <note> [<extension>] [<inversion>]
<nochord> ::= N
<extension> ::= ":" <shorthand> ["(" <degree-list> ")"]
| ":" "(" <degree-list> ")"
<inversion> ::= ["/" <degree>]
<note> ::= <natural> <sharp> | <natural> <flat> | <natural>
<natural> ::= A | B | C | D | E | F | G
<sharp> ::= <sharp> # | #
<flat> ::= <flat> b | b
<degree-list> ::= ["*"] <degree> ["," <degree-list>]
<degree> ::= <interval> | <modifier> <degree>
<interval> ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13
<shorthand> ::= maj | min | dim | aug | maj7 | min7 | 7 | dim7 | hdim7
| minmaj7 | maj6 | min6 | 9 | maj9 | min9 | sus4 | sus2
| 1 | 5 | 13
import re
T = {}
# Simple expressions for terminals
T['nochord'] = r'N'
T['note'] = r'[A-G](b*|#*)'
T['interval'] = r'[1-9]|1[0-3]?'
T['shorthand'] = r'|'.join(['maj', 'min', 'dim', 'aug', 'maj7', 'min7', '7', 'dim7', 'hdim7',
'minmaj7', 'maj6', 'min6', '9', 'maj9', 'min9', 'sus4', 'sus2',
'1', '5', '13'])
# More advanced experssions built from the above
T['degree'] = r'[b#]*({interval})'.format(**T)
T['degree_list'] = r'\*?({degree})(,\*?({degree}))*'.format(**T)
T['inversion'] = r'(/({degree}))?'.format(**T)
T['extension'] = (r'|'.join([r'(:({shorthand})(\(({degree_list})\))?)', r'(:\(({degree_list})\))'])).format(**T)
# Top-level expression
chord = (r'|'.join([r'({nochord})', r'(({note})({extension})?({inversion})?)'])).format(**T)
P = re.compile(r'^({chord})$'.format(chord=chord))
P.pattern
'^((N)|(([A-G](b*|#*))((:(maj|min|dim|aug|maj7|min7|7|dim7|hdim7|minmaj7|maj6|min6|9|maj9|min9|sus4|sus2|1|5|13)(\\((\\*?([b#]*([1-9]|1[0-3]?))(,\\*?([b#]*([1-9]|1[0-3]?)))*)\\))?)|(:\\((\\*?([b#]*([1-9]|1[0-3]?))(,\\*?([b#]*([1-9]|1[0-3]?)))*)\\)))?((/([b#]*([1-9]|1[0-3]?)))?)?))$'
!echo "{P.pattern}" >> /home/bmcfee/git/jams/schema/namespaces/chord/chord.re
print P.match('G#:maj9(*3,*9)/b13')
<_sre.SRE_Match object at 0x2c029f0>