Browse Source

[WIP] First draft to chords parsing and rendering

pull/79/head
Louis 9 years ago
parent
commit
8980576139
  1. 17
      patacrep/data/examples/songs/chords.sgc
  2. 22
      patacrep/songs/chordpro/ast.py
  3. 14
      patacrep/songs/chordpro/data/latex/content_chord.tex
  4. 12
      patacrep/songs/chordpro/lexer.py
  5. 46
      patacrep/songs/chordpro/syntax.py
  6. 12
      patacrep/songs/chordpro/test/chords.sgc
  7. 15
      patacrep/songs/chordpro/test/chords.txt

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

@ -0,0 +1,17 @@
{language: english}
{columns: 1}
{title: Chords testing}
{subtitle: Test of the chords specification and LaTeX translation}
[A]Simple
[Bb]Bémol
[C#]Dièse
[Adim]dim
[Dmaj]maj
[Em3]m chiffre
[G4]Nombre
[Emaj3]maj et nombre
[Absus8]bémol, sus et nombre
[A/A]Deux notes
[F/Fb]Deux notes, bémol
[B/C#]Deux notes, dièse

22
patacrep/songs/chordpro/ast.py

@ -122,12 +122,28 @@ class Chord(LineElement):
_template = "chord" _template = "chord"
def __init__(self, value): def __init__(self, todo_note, todo_diesebemol, todo_mdimmajsus, todo_chiffre, todo_chordbis):
super().__init__() super().__init__()
self.value = value self.todo_note = todo_note
self.todo_diesebemol = todo_diesebemol
self.todo_mdimmajsus = todo_mdimmajsus
self.todo_chiffre = todo_chiffre
self.todo_chordbis = todo_chordbis
def __str__(self): def __str__(self):
return "[{}]".format(self.value) text = ""
text += self.todo_note
if self.todo_diesebemol is not None:
text += self.todo_diesebemol
if self.todo_mdimmajsus is not None:
text += self.todo_mdimmajsus
if self.todo_chiffre is not None:
text += str(self.todo_chiffre)
if self.todo_chordbis is not None:
text += "/" + self.todo_chordbis[0]
if self.todo_chordbis[1] is not None:
text += self.todo_chordbis[1]
return "[{}]".format(text)
class Verse(AST): class Verse(AST):
"""A verse (or bridge, or chorus)""" """A verse (or bridge, or chorus)"""

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

@ -1 +1,13 @@
\[(( content.value ))] \[
((- content.todo_note -))
(* if content.todo_diesebemol == '#' *)#(* endif -*)
(* if content.todo_diesebemol == 'b' *)&(* endif -*)
(* if content.todo_mdimmajsus *)((content.todo_mdimmajsus))(* endif -*)
(* if content.todo_chiffre *)((content.todo_chiffre))(* endif -*)
(* if content.todo_chordbis -*)
/
((- content.todo_chordbis[0] -))
(* if content.todo_chordbis[1] == '#' *)#(* endif -*)
(* if content.todo_chordbis[1] == 'b' *)&(* endif -*)
(* endif -*)
]

12
patacrep/songs/chordpro/lexer.py

@ -9,7 +9,11 @@ LOGGER = logging.getLogger()
tokens = ( tokens = (
'LBRACE', 'LBRACE',
'RBRACE', 'RBRACE',
'CHORD', 'TODONOTE',
'TODODIESEBEMOL',
'TODOMDIMMAJSUS',
'TODOCHIFFRE',
'TODOSLASH',
'NEWLINE', 'NEWLINE',
'COLON', 'COLON',
'WORD', 'WORD',
@ -39,7 +43,11 @@ class ChordProLexer:
t_SPACE = r'[ \t]+' t_SPACE = r'[ \t]+'
t_chord_CHORD = r'[A-G7#m]+' t_chord_TODONOTE = r'[A-G]'
t_chord_TODODIESEBEMOL = r'[#b]'
t_chord_TODOMDIMMAJSUS = r'(maj|dim|m|sus)'
t_chord_TODOCHIFFRE = r'[2-9]'
t_chord_TODOSLASH = r'/'
t_directive_SPACE = r'[ \t]+' t_directive_SPACE = r'[ \t]+'
t_directive_KEYWORD = r'[a-zA-Z_]+' t_directive_KEYWORD = r'[a-zA-Z_]+'

46
patacrep/songs/chordpro/syntax.py

@ -11,6 +11,7 @@ LOGGER = logging.getLogger()
class ChordproParser(Parser): class ChordproParser(Parser):
"""ChordPro parser class""" """ChordPro parser class"""
# pylint: disable=too-many-public-methods
start = "song" start = "song"
@ -23,7 +24,6 @@ class ChordproParser(Parser):
"""song : block song """song : block song
| empty | empty
""" """
#if isinstance(symbols[1], str):
if len(symbols) == 2: if len(symbols) == 2:
symbols[0] = ast.Song(self.filename) symbols[0] = ast.Song(self.filename)
else: else:
@ -108,8 +108,48 @@ class ChordproParser(Parser):
@staticmethod @staticmethod
def p_chord(symbols): def p_chord(symbols):
"""chord : CHORD""" """chord : TODONOTE chordtododiesebemol chordtodomdimmajsus chordtodochiffre chordtodoautre"""
symbols[0] = ast.Chord(symbols[1]) symbols[0] = ast.Chord(
symbols[1],
symbols[2],
symbols[3],
symbols[4],
symbols[5],
)
@staticmethod
def p_chordtododiesebemol(symbols):
"""chordtododiesebemol : TODODIESEBEMOL
| empty
"""
symbols[0] = symbols[1]
@staticmethod
def p_chordtodomdimmajsus(symbols):
"""chordtodomdimmajsus : TODOMDIMMAJSUS
| empty
"""
symbols[0] = symbols[1]
@staticmethod
def p_chordtodochiffre(symbols):
"""chordtodochiffre : TODOCHIFFRE
| empty
"""
if symbols[1] is None:
symbols[0] = symbols[1]
else:
symbols[0] = int(symbols[1])
@staticmethod
def p_chordtodoautre(symbols):
"""chordtodoautre : TODOSLASH TODONOTE chordtododiesebemol
| empty
"""
if len(symbols) == 2:
symbols[0] = None
else:
symbols[0] = (symbols[2], symbols[3])
@staticmethod @staticmethod
def p_chorus(symbols): def p_chorus(symbols):

12
patacrep/songs/chordpro/test/chords.sgc

@ -0,0 +1,12 @@
[A]Simple
[Bb]Bémol
[C#]Dièse
[Adim]dim
[Dmaj]maj
[Em3]m chiffre
[G4]Nombre
[Emaj3]maj et nombre
[Absus8]bémol, sus et nombre
[A/A]Deux notes
[F/Fb]Deux notes, bémol
[B/C#]Deux notes, dièse

15
patacrep/songs/chordpro/test/chords.txt

@ -0,0 +1,15 @@
========
{start_of_verse}
[A]Simple
[Bb]Bémol
[C#]Dièse
[Adim]dim
[Dmaj]maj
[Em3]m chiffre
[G4]Nombre
[Emaj3]maj et nombre
[Absus8]bémol, sus et nombre
[A/A]Deux notes
[F/Fb]Deux notes, bémol
[B/C#]Deux notes, dièse
{end_of_verse}
Loading…
Cancel
Save