Browse Source

[chordpro] Chords parsing is less strict

pull/79/head
Louis 9 years ago
parent
commit
821030dba5
  1. 19
      patacrep/songs/chordpro/ast.py
  2. 11
      patacrep/songs/chordpro/data/chordpro/content_chord
  3. 13
      patacrep/songs/chordpro/data/latex/content_chord
  4. 2
      patacrep/songs/chordpro/lexer.py
  5. 48
      patacrep/songs/chordpro/syntax.py
  6. 2
      patacrep/songs/chordpro/test/invalid_chord.sgc
  7. 4
      patacrep/songs/chordpro/test/invalid_chord.source
  8. 2
      patacrep/songs/chordpro/test/invalid_chord.tex
  9. 6
      patacrep/songs/chordpro/test/invalid_customchord.source

19
patacrep/songs/chordpro/ast.py

@ -145,24 +145,9 @@ class Chord(AST):
_template = "chord" _template = "chord"
def __init__( def __init__(self, chord):
self,
key,
alteration=None,
modifier=None,
addnote=None,
basskey=None,
bassalteration=None,
star=None,
):
# pylint: disable=too-many-arguments # pylint: disable=too-many-arguments
self.key = key self.chord = chord
self.alteration = alteration
self.modifier = modifier
self.addnote = addnote
self.basskey = basskey
self.bassalteration = bassalteration
self.star = star
class Verse(AST): class Verse(AST):
"""A verse (or bridge, or chorus)""" """A verse (or bridge, or chorus)"""

11
patacrep/songs/chordpro/data/chordpro/content_chord

@ -1,10 +1 @@
((- content.key -)) ((- content.chord -))
(* if content.alteration *)(( content.alteration ))(* endif -*)
(* if content.modifier *)((content.modifier))(* endif -*)
(* if content.addnote *)((content.addnote))(* endif -*)
(* if content.basskey -*)
/
((- content.basskey -))
(* if content.bassalteration *)(( content.bassalteration ))(* endif -*)
(* if content.star *)*(* endif -*)
(* endif -*)

13
patacrep/songs/chordpro/data/latex/content_chord

@ -1,12 +1 @@
((- content.key -)) ((- content.chord|replace("b", "&") -))
(* if content.alteration == '#' *)#(* endif -*)
(* if content.alteration == 'b' *)&(* endif -*)
(* if content.modifier *)((content.modifier))(* endif -*)
(* if content.addnote *)((content.addnote))(* endif -*)
(* if content.basskey -*)
/
((- content.basskey -))
(* if content.bassalteration == '#' *)#(* endif -*)
(* if content.bassalteration == 'b' *)&(* endif -*)
(* if content.star *)*(* endif -*)
(* endif -*)

2
patacrep/songs/chordpro/lexer.py

@ -39,7 +39,7 @@ class ChordProLexer:
t_SPACE = r'[ \t]+' t_SPACE = r'[ \t]+'
t_chord_CHORD = r'[A-G#bmajdisus+*2-9/ ]+' t_chord_CHORD = 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_]+'

48
patacrep/songs/chordpro/syntax.py

@ -7,24 +7,6 @@ from patacrep.songs.syntax import Parser
from patacrep.songs.chordpro import ast from patacrep.songs.chordpro import ast
from patacrep.songs.chordpro.lexer import tokens, ChordProLexer from patacrep.songs.chordpro.lexer import tokens, ChordProLexer
CHORD_RE = re.compile(
r"""
^
(?P<key>[A-G])
(?P<alteration>[b#])?
(?P<modifier>(maj|sus|dim|m|\+))?
(?P<addnote>[2-9])?
(
/
(?P<basskey>[A-G])
(?P<bassalteration>[b#])?
)?
(?P<star>\*)?
$
""",
re.VERBOSE
)
class ChordproParser(Parser): class ChordproParser(Parser):
"""ChordPro parser class""" """ChordPro parser class"""
# pylint: disable=too-many-public-methods # pylint: disable=too-many-public-methods
@ -69,17 +51,17 @@ class ChordproParser(Parser):
""" """
symbols[0] = None symbols[0] = None
def _parse_define(self, groups, *, symbols): @staticmethod
def _parse_define(groups):
"""Parse a `{define: KEY base-fret BASE frets FRETS fingers FINGERS}` directive """Parse a `{define: KEY base-fret BASE frets FRETS fingers FINGERS}` directive
Return a :class:`ast.Define` object. Return a :class:`ast.Define` object.
""" """
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
key = list(self._parse_chords(groups['key'], symbols=symbols)) if not groups['key'].strip():
if len(key) != 1:
return None return None
else: else:
key = key[0] key = ast.Chord(groups['key'].strip())
if groups['basefret'] is None: if groups['basefret'] is None:
basefret = None basefret = None
@ -151,7 +133,7 @@ class ChordproParser(Parser):
symbols[0] = ast.Error() symbols[0] = ast.Error()
return return
symbols[0] = self._parse_define(match.groupdict(), symbols=symbols) symbols[0] = self._parse_define(match.groupdict())
if symbols[0] is None: if symbols[0] is None:
self.error( self.error(
line=symbols.lexer.lineno, line=symbols.lexer.lineno,
@ -207,24 +189,10 @@ class ChordproParser(Parser):
"""space : SPACE""" """space : SPACE"""
symbols[0] = ast.Space() symbols[0] = ast.Space()
def _parse_chords(self, string, *, symbols): @staticmethod
"""Parse a list of chords. def p_chord(symbols):
Iterate over :class:`ast.Chord` objects.
"""
for chord in string.split():
match = CHORD_RE.match(chord)
if match is None:
self.error(
line=symbols.lexer.lineno,
message="Invalid chord '{}'.".format(chord),
)
continue
yield ast.Chord(**match.groupdict())
def p_chord(self, symbols):
"""chord : CHORD""" """chord : CHORD"""
symbols[0] = ast.ChordList(*list(self._parse_chords(symbols[1], symbols=symbols))) symbols[0] = ast.ChordList(*[ast.Chord(chord) for chord in symbols[1].split()])
@staticmethod @staticmethod
def p_chorus(symbols): def p_chorus(symbols):

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

@ -2,6 +2,4 @@
{start_of_verse} {start_of_verse}
This is invalid. This is invalid.
This [A]too.
And []as well.
{end_of_verse} {end_of_verse}

4
patacrep/songs/chordpro/test/invalid_chord.source

@ -1,3 +1 @@
This is [H] invalid. This is [] invalid.
This [A@]too.
And [Amm]as well.

2
patacrep/songs/chordpro/test/invalid_chord.tex

@ -8,8 +8,6 @@
\begin{verse} \begin{verse}
This is invalid. This is invalid.
This \[A]too.
And as well.
\end{verse} \end{verse}
\endsong \endsong

6
patacrep/songs/chordpro/test/invalid_customchord.source

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

Loading…
Cancel
Save