Browse Source

Add line number to AST elements

First step for #121
pull/175/head
Louis 9 years ago
parent
commit
70f17b8a0f
  1. 11
      patacrep/songs/chordpro/ast.py
  2. 19
      patacrep/songs/chordpro/syntax.py

11
patacrep/songs/chordpro/ast.py

@ -64,6 +64,10 @@ class AST:
"""Generic object representing elements of the song.""" """Generic object representing elements of the song."""
_template = None _template = None
inline = False inline = False
lexer = None
def __init__(self):
self.lineno = self.lexer.lineno
def template(self): def template(self):
"""Return the template to be used to render this object.""" """Return the template to be used to render this object."""
@ -140,6 +144,7 @@ class ChordList(LineElement):
_template = "chordlist" _template = "chordlist"
def __init__(self, *chords): def __init__(self, *chords):
super().__init__()
self.chords = chords self.chords = chords
class Chord(AST): class Chord(AST):
@ -148,7 +153,7 @@ class Chord(AST):
_template = "chord" _template = "chord"
def __init__(self, chord): def __init__(self, chord):
# pylint: disable=too-many-arguments super().__init__()
self.chord = chord self.chord = chord
@property @property
@ -218,7 +223,7 @@ class Song(AST):
"tag": "add_cumulative", "tag": "add_cumulative",
} }
def __init__(self, filename): def __init__(self, filename, directives):
super().__init__() super().__init__()
self.content = [] self.content = []
self.meta = OrderedDict() self.meta = OrderedDict()
@ -226,6 +231,8 @@ class Song(AST):
self._titles = [] self._titles = []
self._subtitles = [] self._subtitles = []
self.filename = filename self.filename = filename
for directive in directives:
self.add(directive)
def add(self, data): def add(self, data):
"""Add an element to the song""" """Add an element to the song"""

19
patacrep/songs/chordpro/syntax.py

@ -19,28 +19,30 @@ class ChordproParser(Parser):
def __init__(self, filename=None): def __init__(self, filename=None):
super().__init__() super().__init__()
self.tokens = tokens self.tokens = tokens
self.song = ast.Song(filename)
self.filename = filename self.filename = filename
self._directives = []
self.parser = yacc.yacc( self.parser = yacc.yacc(
module=self, module=self,
debug=0, debug=0,
write_tables=0, write_tables=0,
) )
def parse(self, *args, **kwargs): def parse(self, content):
"""Parse file """Parse file
This is a shortcut to `yacc.yacc(...).parse()`. The arguments are This is a shortcut to `yacc.yacc(...).parse()`. The arguments are
transmitted to this method. transmitted to this method.
""" """
return self.parser.parse(*args, **kwargs) lexer = ChordProLexer(filename=self.filename).lexer
ast.AST.lexer = lexer
return self.parser.parse(content, lexer=lexer)
def p_song(self, symbols): def p_song(self, symbols):
"""song : block song """song : block song
| empty | empty
""" """
if len(symbols) == 2: if len(symbols) == 2:
symbols[0] = self.song symbols[0] = ast.Song(self.filename, self._directives)
else: else:
symbols[0] = symbols[2].add(symbols[1]) symbols[0] = symbols[2].add(symbols[1])
@ -158,14 +160,14 @@ class ChordproParser(Parser):
) )
symbols[0] = ast.Error() symbols[0] = ast.Error()
return return
self.song.add(define) self._directives.append(define)
else: else:
directive = ast.Directive(keyword, argument) directive = ast.Directive(keyword, argument)
if directive.inline: if directive.inline:
symbols[0] = directive symbols[0] = directive
else: else:
self.song.add(directive) self._directives.append(directive)
@staticmethod @staticmethod
@ -312,7 +314,4 @@ class ChordproParser(Parser):
def parse_song(content, filename=None): def parse_song(content, filename=None):
"""Parse song and return its metadata.""" """Parse song and return its metadata."""
return ChordproParser(filename).parse( return ChordproParser(filename).parse(content)
content,
lexer=ChordProLexer(filename=filename).lexer,
)

Loading…
Cancel
Save