Memo preamble parsing
This commit is contained in:
parent
9af51d54c4
commit
b48550d828
@ -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
|
||||
|
10
jubeatools/formats/memo/__init__.py
Normal file
10
jubeatools/formats/memo/__init__.py
Normal 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
|
||||
"""
|
79
jubeatools/formats/memo/preamble.py
Normal file
79
jubeatools/formats/memo/preamble.py
Normal 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
18
poetry.lock
generated
@ -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"},
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user