1
0
mirror of synced 2024-12-03 18:57:16 +01:00

Memo preamble parsing

This commit is contained in:
Stepland 2020-06-08 01:56:10 +02:00
parent 9af51d54c4
commit b48550d828
5 changed files with 108 additions and 2 deletions

View File

@ -16,6 +16,8 @@ from .memon import (
ALIASES = {
"memon": "memon:v0.2.0",
"ichi-retsu": "mono-column",
"memo": "memo2",
}
# Loaders deserialize a folder or a file to a Song object

View File

@ -0,0 +1,10 @@
"""
memo is a vague term refering to several legacy formats.
They were originally derived from the (somewhat) human-readable format choosen
by websites storing official jubeat charts in text form as a memory aid.
The machine-readable variants are partially documented (in japanese)
on these pages :
- http://yosh52.web.fc2.com/jubeat/fumenformat.html
- http://yosh52.web.fc2.com/jubeat/holdmarker.html
"""

View File

@ -0,0 +1,79 @@
"""
Useful things to parse the preamble of analyser-like formats
"""
from decimal import Decimal
from typing import List, Tuple, Union
from parsimonious import Grammar, NodeVisitor
from parsimonious.expressions import Node
preamble_line_grammar = Grammar(
r"""
raw_line = line comment?
line = command? ws
command = hash_command / simple_command
hash_command = "#" key "=" value
key = ~"[a-z]+"
value = value_in_quotes / number
value_in_quotes = "\"" quoted_value "\""
quoted_value = ~"[^\"]+"
number = ~"\d+"
simple_command = letter "=" value
letter = ~"\w"
ws = ~"[\t ]*"
comment = ~"//.*"
"""
)
class PreambleLineVisitor(NodeVisitor):
"""Returns a (key, value) tuple or None if the line contains no useful
information for the parser (a comment or an empty line)"""
def _as_text(self, node, visited_children):
return node.text
def visit_raw_line(self, node, visited_children):
value, _ = visited_children
return value
def visit_line(self, node, visited_children):
command, _ = visited_children
value = list(command)
return value[0] if value else None
visit_command = NodeVisitor.lift_child
def visit_hash_command(self, node, visited_children):
_, key, _, value = visited_children
return (key, value)
visit_key = _as_text
visit_value = NodeVisitor.lift_child
def visit_value_in_quotes(self, node, visited_children):
_, value, _ = visited_children
return value
visit_quoted_value = _as_text
def visit_number(self, node, visited_children):
return Decimal(node.text)
def visit_simple_command(self, node, visited_children):
letter, _, value = visited_children
return (letter, value)
visit_letter = _as_text
def generic_visit(self, node, visited_children):
return visited_children or node
_preamble_line_visitor = PreambleLineVisitor()
def load_preamble_line(line: str) -> Union[Tuple[str, Union[str, Decimal]], None]:
_preamble_line_visitor.visit(preamble_line_grammar.parse(line))

18
poetry.lock generated
View File

@ -108,6 +108,17 @@ version = "20.4"
pyparsing = ">=2.0.2"
six = "*"
[[package]]
category = "main"
description = "(Soon to be) the fastest pure-Python PEG parser I could muster"
name = "parsimonious"
optional = false
python-versions = "*"
version = "0.8.1"
[package.dependencies]
six = ">=1.9.0"
[[package]]
category = "main"
description = "A module wrapper for os.path"
@ -205,7 +216,7 @@ python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*"
version = "3.17.0"
[[package]]
category = "dev"
category = "main"
description = "Python 2 and 3 compatibility utilities"
name = "six"
optional = false
@ -237,7 +248,7 @@ python-versions = "*"
version = "0.1.9"
[metadata]
content-hash = "b55c6b2244d11c0356dc49e32615244f2b964ac0b903d8613a5e0e453557643f"
content-hash = "a07afd18095d3d59ba9a855d90c797920c63fd004b7e1cb134a5ec981e7e16b8"
python-versions = "^3.8"
[metadata.files]
@ -296,6 +307,9 @@ packaging = [
{file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
{file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
]
parsimonious = [
{file = "parsimonious-0.8.1.tar.gz", hash = "sha256:3add338892d580e0cb3b1a39e4a1b427ff9f687858fdd61097053742391a9f6b"},
]
path = [
{file = "path-14.0.1-py3-none-any.whl", hash = "sha256:ed305ab0629859795863afdcd2ff8950af9c1d703527cb8b8aec3b6a425a80ba"},
{file = "path-14.0.1.tar.gz", hash = "sha256:aedf5be64bcfe34dcc17b2bcf379e86f8f5e4d06588b3697e1bba4a1563794b4"},

View File

@ -12,6 +12,7 @@ click = "^7.1.2"
path = "^14.0.1"
simplejson = "^3.17.0"
marshmallow = "^3.6.0"
parsimonious = "^0.8.1"
[tool.poetry.dev-dependencies]
pytest = "^5.2"