From 7249ca3a6fdf51f6b7ea66ac6854edd5e02ae5ec Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Wed, 15 Jul 2026 20:00:24 +0900 Subject: feat: MMLパーサーと意味解析を厳格化 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ppmckの終端分岐付きリピートとL制御トラックを実装 - case、構文構造、音長、エフェクト値域の検証を強化 - Pyxel拡張コマンドのarityと参照検証を追加 - リピート展開上限と構文・意味エラー時の合成停止を追加 - BNF、設計書、適合監査、回帰テストを更新 --- doc/MML_BNF.md | 102 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 37 deletions(-) (limited to 'doc/MML_BNF.md') diff --git a/doc/MML_BNF.md b/doc/MML_BNF.md index 0c3f3b0..6093911 100644 --- a/doc/MML_BNF.md +++ b/doc/MML_BNF.md @@ -12,8 +12,9 @@ ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ::= + -/* 音符名(Lexer で正規化: ppmck は小文字、pyxel は大文字 → 内部は小文字) */ - ::= "c" | "d" | "e" | "f" | "g" | "a" | "b" +/* 音符名(case-sensitive。受理後のASTでは小文字へ正規化) */ + ::= "c" | "d" | "e" | "f" | "g" | "a" | "b" + ::= "C" | "D" | "E" | "F" | "G" | "A" | "B" /* 変化記号 */ ::= "+" | "#" @@ -43,6 +44,8 @@ ::= " " | "\t" | "\r" | "\n" ``` +``は字句間の区切りであり、statementやASTノードではない。`#`はppmckの行頭ヘッダー開始、または両モードで音符名の直後に置くsharpとしてのみ有効である。 + --- ## 2. ppmck モード @@ -50,7 +53,7 @@ ### 2.1 全体構造 ```bnf - ::= * * + ::= * * * ::= "#" ? ::= "TITLE" | "COMPOSER" | "PROGRAMER" | "OCTAVE-REV" @@ -58,15 +61,30 @@ | "EFFECT-INCLUDE" ::= "\"" "\"" - ::= * - ::= "A" | "B" | "T" | "N" | "L" + + ::= | | + | | + + ::= | + ::= * + + ::= "A" | "B" | "T" | "N" + ::= "L" * + ::= | | | +::= | | + ::= "[" * ("|" *)? "]" ? ``` +グローバル定義は全トラック共通である。既存入力との互換性のため、同じ定義を音声トラック内の``として置くこともできる。`L`は音声を生成しない制御トラックで、0回または1回だけ記述できる。 + ### 2.2 ステートメント ```bnf - ::= - | + ::= | | + + + ::= + | | | | @@ -76,14 +94,10 @@ | | | - | - | - | | - | - ::= ? - ::= "r" + ::= ? + ::= "r" ::= "o" /* o0 〜 o7 */ | @@ -96,12 +110,18 @@ ::= "q" /* q1 〜 q8 */ ::= "t" /* t1 〜 */ - ::= "^" ( | ) - ::= "&" ( | | ) + ::= "^" ( | ) + ::= "&" ( | | ) ::= ";" + + + ::= | + ::= "[" * ("|" *)? "]" ? ``` +`[本体]N`は本体をN回再生する。`[前半|後半]N`は`前半+後半`をN−1回、最後に前半だけを再生する。`N=1`では前半だけとなる。`|`は現在のリピート階層で高々1個で、ネストした`|`は内側に所属する。リピート外の`|`は小節線である。回数省略は無限を表し、IRプレビューでは`前半+後半`を2回展開して`repeat_count=0`を保持する。 + ### 2.3 合成拡張コマンド ```bnf @@ -123,27 +143,27 @@ | - ::= "v+" ? /* 1 〜 15 */ - | "v-" ? /* 1 〜 15 */ + ::= "v+" ? /* 省略時1、1 〜 15 */ + | "v-" ? /* 省略時1、1 〜 15 */ ::= "D" /* -127 〜 126 */ ::= "s" "," -::= "@v" "=" "{" "|" ? "}" +::= "@v" "=" "{" ("|" ?)? "}" ::= "@v" -::= "@" "=" "{" "|" ? "}" +::= "@" "=" "{" ("|" ?)? "}" ::= "@@" ::= "@MP" "=" "{" "," "," "," "}" ::= "MP" ::= "MPOF" - ::= "@EP" "=" "{" "|" ? "}" + ::= "@EP" "=" "{" ("|" ?)? "}" ::= "EP" ::= "EPOF" - ::= "@EN" "=" "{" "|" ? "}" + ::= "@EN" "=" "{" ("|" ?)? "}" ::= "EN" ::= "ENOF" @@ -158,13 +178,10 @@ ```bnf ::= - | | | - ::= ? "%" - - ::= "[" + "]" ? + ::= ? "%" ::= "K" ::= "m" @@ -182,14 +199,14 @@ ::= * - ::= ":" /* 0: 1: 2: 3: */ + ::= "0:" | "1:" | "2:" | "3:" ``` ### 3.2 ステートメント ```bnf - ::= - | + ::= + | | | | @@ -199,14 +216,12 @@ | | | - | - | + | | | - | - ::= ? - ::= "R" + ::= ? + ::= "R" ::= "O" /* O0 〜 O7 */ | @@ -221,24 +236,29 @@ ::= "K" /* 半音単位 */ ::= "Y" /* セント単位 */ - ::= ( | | ) + ::= ( | | ) + ::= "[" * "]" ? ``` +Pyxelリピートはネストできる。指定回数は1以上で、回数省略は無限を表す。IRプレビューでは本体を2回展開し、`repeat_count=0`を保持する。Pyxelの`|`は常に小節線であり、終端分岐ではない。 + ### 3.3 合成拡張コマンド ```bnf ::= | | ::= "@ENV" ? - ::= + + ::= ( )* ::= "@VIB" ? - ::= + + ::= ::= "@GLI" ? - ::= + + ::= ``` +slot 0は解除専用で、パラメータを指定できない。slot 1以上ではパラメータ付きの初出を定義、パラメータなしを既定義slotの選択として扱う。Pyxel公式の波括弧、カンマ、負数、`*`を使う拡張形式は本受理文法に含めない。 + --- ## 4. トラック・チャンネル対応 @@ -259,6 +279,8 @@ |---|---|---|---|---| | `o` / `O` | 両方 | 0 〜 7 | 4 | | | `l` / `L` | 両方 | 1 〜 192 | 4 | | +| 音符・休符の明示音長 | 両方 | 1 〜 192 | 現在の`l`/`L` | | +| タイ対象の音長 | 両方 | 1 〜 192 | — | | | `v` | ppmck | 0 〜 15 | 15 | | | `V` | pyxel | 0 〜 127 | 100 | | | `v+` / `v-` | ppmck | 1 〜 15 | 1 | 相対音量(0〜15へクランプ) | @@ -274,8 +296,14 @@ | `@MP` / `MP` / `MPOF` | ppmck | 0 〜 255 | — | 三角LFO | | `@EP` / `EP` / `EPOF` | ppmck | 0 〜 255 | — | cent単位ピッチエンベロープ | | `@EN` / `EN` / `ENOF` | ppmck | 0 〜 255 | — | 絶対半音オフセット列 | +| ppmck envelope slot | ppmck | 0 〜 255 | — | 全定義・参照共通 | +| volume envelope要素 | ppmck | 0 〜 15 | — | | +| duty envelope要素 | ppmck | 0 〜 3 | — | | +| pitch/note envelope要素 | ppmck | -127 〜 126 | — | | +| `@MP`要素 | ppmck | delay 0〜255, period 1〜255, depth 0〜255, 第4値0 | — | | | `K` | pyxel | -127 〜 127 | 0 | トランスポーズ(半音) | | `Y` | pyxel | -127 〜 127 | 0 | ディチューン(セント) | +| リピート回数 | 両方 | 1以上、または省略(無限) | 省略 | 展開後は各トラック100,000イベント以下 | --- -- cgit v1.2.3