Browse Source

[chordpro] Parsing of {define: FOO} works (some TODOs are left for error handling)

pull/79/head
Louis 9 years ago
parent
commit
47e4f96099
  1. 2
      patacrep/data/examples/example-all.sb
  2. 5
      patacrep/data/examples/songs/chords.sgc
  3. 50
      patacrep/songs/chordpro/ast.py
  4. 25
      patacrep/songs/chordpro/data/latex/content_chord.tex
  5. 6
      patacrep/songs/chordpro/data/latex/content_chordlist.tex
  6. 24
      patacrep/songs/chordpro/data/latex/content_define.tex
  7. 59
      patacrep/songs/chordpro/syntax.py
  8. 2
      patacrep/songs/chordpro/test/customchords.sgc
  9. 3
      patacrep/songs/chordpro/test/customchords.txt

2
patacrep/data/examples/example-all.sb

@ -1,6 +1,6 @@
{
"bookoptions" : [
"importantdiagramonly",
"diagram",
"repeatchords",
"lilypond",
"pictures"

5
patacrep/data/examples/songs/chords.sgc

@ -3,6 +3,11 @@
{title: Chords testing}
{subtitle: Test of the chords specification and LaTeX translation}
{define: E5 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -}
{define: A frets x 0 2 2 2 0 fingers - - 1 2 3 -}
{define: C#sus4 base-fret 4 frets x x 3 3 4 1}
{define: Bb frets x 1 3 3 3 1}
[A]Simple
[Bb]Bémol
[C#]Dièse

50
patacrep/songs/chordpro/ast.py

@ -119,7 +119,7 @@ class Space(LineElement):
class ChordList(LineElement):
"""A list of chords."""
_template = "chord"
_template = "chordlist"
def __init__(self, *chords):
self.chords = chords
@ -129,9 +129,11 @@ class ChordList(LineElement):
[str(chord) for chord in self.chords]
))
class Chord:
class Chord(AST):
"""A chord."""
_template = "chord"
def __init__(
self,
key,
@ -164,6 +166,50 @@ class Chord:
text += self.bassalteration
return text
class Define(AST):
"""A chord definition.
Attributes:
.. attribute:: key
The key, as a :class:`Chord` object.
.. attribute:: basefret
The base fret, as an integer. Can be `None` if no base fret is defined.
.. attribute:: frets
The list of frets, as a list of integers, or `None`, if this fret is not to be played.
.. attribute:: fingers
The list of fingers to use on frets, as a list of integers, or `None`
if no information is given (this string is not played, or is played
open). Can be `None` if not defined.
"""
_template = "define"
inline = True
def __init__(self, key, basefret, frets, fingers):
self.key = key
self.basefret = basefret # Can be None
self.frets = frets
self.fingers = fingers # Can be None
def __str__(self):
text = str(self.key)
if self.basefret is not None:
text += " base-fret " + str(self.basefret)
text += " frets"
for fret in self.frets:
if fret is None:
text += " x"
else:
text += " " + str(fret)
if self.fingers:
text += " fingers"
for finger in self.fingers:
if finger is None:
text += " -"
else:
text += " " + str(finger)
return "{{define: {}}}".format(text)
class Verse(AST):
"""A verse (or bridge, or chorus)"""
_template = "verse"

25
patacrep/songs/chordpro/data/latex/content_chord.tex

@ -1,16 +1,11 @@
\[
(*- for chord in content.chords -*)
(* if not loop.first *) (* endif *)
((- chord.key -))
(* if chord.alteration == '#' *)#(* endif -*)
(* if chord.alteration == 'b' *)&(* endif -*)
(* if chord.modifier *)((chord.modifier))(* endif -*)
(* if chord.add_note *)((chord.add_note))(* endif -*)
(* if chord.basskey -*)
((- content.key -))
(* if content.alteration == '#' *)#(* endif -*)
(* if content.alteration == 'b' *)&(* endif -*)
(* if content.modifier *)((content.modifier))(* endif -*)
(* if content.addnote *)((content.addnote))(* endif -*)
(* if content.basskey -*)
/
((- chord.basskey -))
(* if chord.bassalteration == '#' *)#(* endif -*)
(* if chord.bassalteration == 'b' *)&(* endif -*)
(* endif -*)
(* endfor -*)
]
((- content.basskey -))
(* if content.bassalteration == '#' *)#(* endif -*)
(* if content.bassalteration == 'b' *)&(* endif -*)
(* endif -*)

6
patacrep/songs/chordpro/data/latex/content_chordlist.tex

@ -0,0 +1,6 @@
\[
(*- for chord in content.chords -*)
(* if not loop.first *) (* endif -*)
(( render(chord) -))
(* endfor -*)
]

24
patacrep/songs/chordpro/data/latex/content_define.tex

@ -0,0 +1,24 @@
\gtab{
((- render(content.key) -))
}{
(*- if content.basefret -*)
((content.basefret)):
(*- endif -*)
(*- for string in content.frets -*)
(*- if string is none -*)
X
(*- else -*)
(( string -))
(* endif -*)
(* endfor -*)
(* if content.fingers -*)
:
(*- for finger in content.fingers -*)
(* if finger is none -*)
0
(*- else -*)
(( finger -))
(* endif -*)
(* endfor -*)
(* endif -*)
}

59
patacrep/songs/chordpro/syntax.py

@ -36,6 +36,50 @@ def _parse_chords(string):
TODO
yield ast.Chord(**match.groupdict())
def _parse_define(key, basefret, frets, fingers):
"""Parse a `{define: KEY base-fret BASE frets FRETS fingers FINGERS}` directive
Return a :class:`ast.Define` object.
"""
# pylint: disable=too-many-branches
key = list(_parse_chords(key))
if len(key) != 1:
TODO
else:
processed_key = key[0]
if basefret is None:
processed_basefret = None
else:
processed_basefret = int(basefret)
if frets is None:
processed_frets = None
else:
processed_frets = []
for fret in frets.split():
if fret == "x":
processed_frets.append(None)
else:
processed_frets.append(int(fret))
if fingers is None:
processed_fingers = None
else:
processed_fingers = []
for finger in fingers.split():
if finger == '-':
processed_fingers.append(None)
else:
processed_fingers.append(int(finger))
return ast.Define(
key=processed_key,
basefret=processed_basefret,
frets=processed_frets,
fingers=processed_fingers,
)
class ChordproParser(Parser):
"""ChordPro parser class"""
# pylint: disable=too-many-public-methods
@ -91,6 +135,21 @@ class ChordproParser(Parser):
else:
symbols[4].keyword = symbols[3]
symbols[0] = symbols[4]
if symbols[0].keyword == 'define':
match = re.compile(
r"""
(?P<key>[^\ ]*)\ *
(base-fret\ *(?P<basefret>[2-9]))?\ *
frets\ *(?P<frets>((\d+|x)\ *)+)\ *
(fingers\ *(?P<fingers>(([0-4-])\ *)*))?
""",
re.VERBOSE
).match(symbols[0].argument)
if match is None:
TODO
symbols[0] = _parse_define(**match.groupdict())
@staticmethod
def p_directive_next(symbols):

2
patacrep/songs/chordpro/test/customchords.sgc

@ -0,0 +1,2 @@
{define: E4 base-fret 7 frets 0 1 3 3 x x}
{define: E5 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -}

3
patacrep/songs/chordpro/test/customchords.txt

@ -0,0 +1,3 @@
========
{define: E4 base-fret 7 frets 0 1 3 3 x x}
{define: E5 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -}
Loading…
Cancel
Save