diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-07-12 17:58:19 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-07-12 17:59:16 +0900 |
| commit | bf36a773918959eeb6ffe7dae2fb8b0874438eb4 (patch) | |
| tree | da7ff0037ea923fea255d2ed69ed2fb51395d9b9 /tests/test_lexer.py | |
| parent | f1cd4d7d16f6e75a50bb0c587c0f759f7cf710cd (diff) | |
feat(ppmck): mckc準拠の構文拡張とIR保持コマンド追加
- @をデューティ比、qをクオンタイズに修正(mckc原本準拠)
- ^タイ、Dディチューン、sスイープ、v+/v-相対音量を追加
- @v/@@/@MP/@EP/@EN エンベロープ・LFO系を構文解析してIR保持
- 上記IR保持コマンドは合成未対応を SEMANTIC_UNSUPPORTED_FEATURE で警告
- Design.md / MML_BNF.md を更新
- 全200テスト + ruff チェック通過
Diffstat (limited to 'tests/test_lexer.py')
| -rw-r--r-- | tests/test_lexer.py | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/tests/test_lexer.py b/tests/test_lexer.py index 64fa17c..1d7f8e7 100644 --- a/tests/test_lexer.py +++ b/tests/test_lexer.py @@ -4,12 +4,13 @@ from mml_composemusic_mcp.lexer import TokenType, tokenize def test_ppmck_tokens(): - source = "A t150 l8 o4 v15 q2\nc d e f" + source = "A t150 l8 o4 v15 @2\nc d e f" tokens = tokenize(source, "ppmck") types = [t.type for t in tokens] assert TokenType.TRACK_HEADER in types assert TokenType.TEMPO in types assert TokenType.NOTE in types + assert TokenType.DUTY in types def test_pyxel_tokens(): @@ -35,3 +36,74 @@ def test_ppmck_invalid_token(): def test_pyxel_invalid_token(): tokens = tokenize("0: T120 L4 O4 X C", "pyxel") assert any(t.type == TokenType.INVALID for t in tokens) + + +def test_ppmck_at_duty(): + tokens = tokenize("A @2 c", "ppmck") + assert any(t.type == TokenType.DUTY for t in tokens) + + +def test_ppmck_quantize(): + tokens = tokenize("A q4 c", "ppmck") + assert any(t.type == TokenType.QUANTIZE for t in tokens) + + +def test_ppmck_tie_cmd(): + tokens = tokenize("A c4 ^4", "ppmck") + assert any(t.type == TokenType.TIE_CMD for t in tokens) + + +def test_ppmck_detune(): + tokens = tokenize("A D10 c", "ppmck") + assert any(t.type == TokenType.DETUNE for t in tokens) + + +def test_ppmck_sweep(): + tokens = tokenize("A s1,2 c", "ppmck") + assert any(t.type == TokenType.SWEEP for t in tokens) + + +def test_ppmck_rel_vol(): + tokens = tokenize("A v+5 v-3 c", "ppmck") + assert any(t.type == TokenType.REL_VOL_UP for t in tokens) + assert any(t.type == TokenType.REL_VOL_DOWN for t in tokens) + + +def test_ppmck_vol_env(): + tokens = tokenize("A @v0 c", "ppmck") + assert any(t.type == TokenType.VOL_ENV for t in tokens) + + +def test_ppmck_vol_env_def(): + tokens = tokenize("@v0 = { 15, 10, | 5 }", "ppmck") + assert any(t.type == TokenType.VOL_ENV for t in tokens) + assert any(t.type == TokenType.BRACE_OPEN for t in tokens) + assert any(t.type == TokenType.BRACE_CLOSE for t in tokens) + + +def test_ppmck_lfo_def(): + tokens = tokenize("@MP0 = { 0, 10, 5, 0 }", "ppmck") + assert any(t.type == TokenType.LFO_DEF for t in tokens) + + +def test_ppmck_lfo_use_off(): + tokens = tokenize("A MP1 MPOF c", "ppmck") + assert any(t.type == TokenType.LFO_USE for t in tokens) + assert any(t.type == TokenType.LFO_OFF for t in tokens) + + +def test_ppmck_pitch_env(): + tokens = tokenize("A EP1 EPOF c", "ppmck") + assert any(t.type == TokenType.PITCH_ENV_USE for t in tokens) + assert any(t.type == TokenType.PITCH_ENV_OFF for t in tokens) + + +def test_ppmck_note_env(): + tokens = tokenize("A EN1 ENOF c", "ppmck") + assert any(t.type == TokenType.NOTE_ENV_USE for t in tokens) + assert any(t.type == TokenType.NOTE_ENV_OFF for t in tokens) + + +def test_ppmck_duty_env_use(): + tokens = tokenize("A @@0 c", "ppmck") + assert any(t.type == TokenType.DUTY_ENV_USE for t in tokens) |
