mirror of https://github.com/patacrep/patacrep.git
Louis
10 years ago
4 changed files with 184 additions and 103 deletions
@ -1,88 +0,0 @@ |
|||
# -*- coding: utf-8 -*- |
|||
"""ChordPro parser""" |
|||
|
|||
import logging |
|||
import ply.yacc as yacc |
|||
|
|||
from patacrep.songs.chordpro.lexer import tokens, ChordProLexer |
|||
from patacrep.songs.chordpro import ast |
|||
from patacrep.errors import SongbookError |
|||
|
|||
LOGGER = logging.getLogger() |
|||
|
|||
class ParsingError(SongbookError): |
|||
"""Parsing error.""" |
|||
|
|||
def __init__(self, message): |
|||
super().__init__(self) |
|||
self.message = message |
|||
|
|||
def __str__(self): |
|||
return self.message |
|||
|
|||
|
|||
class Parser: |
|||
"""ChordPro parser class""" |
|||
|
|||
def __init__(self, filename=None): |
|||
self.tokens = tokens |
|||
self.filename = filename |
|||
|
|||
@staticmethod |
|||
def __find_column(token): |
|||
"""Return the column of ``token``.""" |
|||
last_cr = token.lexer.lexdata.rfind('\n', 0, token.lexpos) |
|||
if last_cr < 0: |
|||
last_cr = 0 |
|||
column = (token.lexpos - last_cr) + 1 |
|||
return column |
|||
|
|||
def p_error(self, token): |
|||
"""Manage parsing errors.""" |
|||
LOGGER.error("Error in file {}, line {}:{}.".format( |
|||
str(self.filename), |
|||
token.lineno, |
|||
self.__find_column(token), |
|||
) |
|||
) |
|||
|
|||
@staticmethod |
|||
def p_expression(symbols): |
|||
"""expression : brackets expression |
|||
| braces expression |
|||
| command expression |
|||
| NEWLINE expression |
|||
| word expression |
|||
| SPACE expression |
|||
| empty |
|||
""" |
|||
if len(symbols) == 3: |
|||
if symbols[2] is None: |
|||
symbols[0] = ast.Expression(symbols[1]) |
|||
else: |
|||
symbols[0] = symbols[2].prepend(symbols[1]) |
|||
else: |
|||
symbols[0] = None |
|||
|
|||
@staticmethod |
|||
def p_empty(__symbols): |
|||
"""empty :""" |
|||
return None |
|||
|
|||
@staticmethod |
|||
def p_brackets(symbols): |
|||
"""brackets : LBRACKET expression RBRACKET""" |
|||
symbols[0] = symbols[2] |
|||
|
|||
@staticmethod |
|||
def p_braces(symbols): |
|||
"""braces : LBRACE expression COLON expression RBRACE""" |
|||
symbols[0] = symbols[2] |
|||
|
|||
|
|||
def parsesong(string, filename=None): |
|||
"""Parse song and return its metadata.""" |
|||
return yacc.yacc(module=Parser(filename)).parse( |
|||
string, |
|||
lexer=ChordProLexer().lexer, |
|||
) |
@ -0,0 +1,136 @@ |
|||
# -*- coding: utf-8 -*- |
|||
"""ChordPro parser""" |
|||
|
|||
import logging |
|||
import ply.yacc as yacc |
|||
|
|||
from patacrep.songs.chordpro.lexer import tokens, ChordProLexer |
|||
from patacrep.songs.chordpro import ast |
|||
from patacrep.errors import SongbookError |
|||
|
|||
LOGGER = logging.getLogger() |
|||
|
|||
class ParsingError(SongbookError): |
|||
"""Parsing error.""" |
|||
|
|||
def __init__(self, message): |
|||
super().__init__(self) |
|||
self.message = message |
|||
|
|||
def __str__(self): |
|||
return self.message |
|||
|
|||
|
|||
class Parser: |
|||
"""ChordPro parser class""" |
|||
|
|||
def __init__(self, filename=None): |
|||
self.tokens = tokens |
|||
self.filename = filename |
|||
|
|||
@staticmethod |
|||
def __find_column(token): |
|||
"""Return the column of ``token``.""" |
|||
last_cr = token.lexer.lexdata.rfind('\n', 0, token.lexpos) |
|||
if last_cr < 0: |
|||
last_cr = 0 |
|||
column = (token.lexpos - last_cr) + 1 |
|||
return column |
|||
|
|||
def p_error(self, token): |
|||
"""Manage parsing errors.""" |
|||
if token: # TODO remove this test |
|||
LOGGER.error("Error in file {}, line {}:{}.".format( |
|||
str(self.filename), |
|||
token.lineno, |
|||
self.__find_column(token), |
|||
) |
|||
) |
|||
|
|||
@staticmethod |
|||
def p_song(symbols): |
|||
"""song : block song |
|||
| empty |
|||
""" |
|||
if len(symbols) == 2: |
|||
symbols[0] = ('song') |
|||
else: |
|||
symbols[0] = ('song', symbols[1], symbols[2]) |
|||
|
|||
@staticmethod |
|||
def p_block(symbols): |
|||
"""block : directive NEWLINE newlines |
|||
| stanza NEWLINE newlines |
|||
""" |
|||
symbols[0] = ('block', symbols[1]) |
|||
|
|||
@staticmethod |
|||
def p_newlines(symbols): |
|||
"""newlines : NEWLINE newlines |
|||
| empty""" |
|||
symbols[0] = ('newlines') |
|||
|
|||
@staticmethod |
|||
def p_directive(symbols): |
|||
"""directive : LBRACE WORD RBRACE""" |
|||
symbols[0] = ('directive', symbols[1]) |
|||
|
|||
@staticmethod |
|||
def p_line(symbols): |
|||
"""line : WORD line_next |
|||
| CHORD line_next |
|||
| SPACE line_next |
|||
""" |
|||
symbols[0] = ('line', symbols[1], symbols[2]) |
|||
|
|||
@staticmethod |
|||
def p_line_next(symbols): |
|||
"""line_next : WORD line_next |
|||
| SPACE line_next |
|||
| CHORD line_next |
|||
| empty |
|||
""" |
|||
if len(symbols) == 2: |
|||
symbols[0] = ('line-next') |
|||
else: |
|||
symbols[0] = ('line-next', symbols[1], symbols[2]) |
|||
|
|||
@staticmethod |
|||
def p_stanza(symbols): |
|||
"""stanza : line NEWLINE stanza_next |
|||
""" |
|||
symbols[0] = ('stanza', symbols[1], symbols[3]) |
|||
|
|||
@staticmethod |
|||
def p_stanza_next(symbols): |
|||
"""stanza_next : line NEWLINE stanza_next |
|||
| empty |
|||
""" |
|||
if len(symbols) == 2: |
|||
symbols[0] = ('stanza-next') |
|||
else: |
|||
symbols[0] = ('stanza-next', symbols[1], symbols[3]) |
|||
|
|||
#@staticmethod |
|||
#def p_braces(symbols): |
|||
# """braces : LBRACE expression COLON expression RBRACE""" |
|||
# symbols[0] = symbols[2] |
|||
|
|||
@staticmethod |
|||
def p_empty(symbols): |
|||
"""empty :""" |
|||
symbols[0] = None |
|||
|
|||
#@staticmethod |
|||
#def p_comment(symbols): |
|||
# """comment : COMMENT""" |
|||
# symbols[0] = ('comment', symbols[1]) |
|||
|
|||
|
|||
|
|||
def parse_song(content, filename=None): |
|||
"""Parse song and return its metadata.""" |
|||
return yacc.yacc(module=Parser(filename)).parse( |
|||
content, |
|||
lexer=ChordProLexer().lexer, |
|||
) |
Loading…
Reference in new issue