================================================================================ Nyash文法改革 - 技術仕様書(パーサー実装向け) 2025-09-03 ================================================================================ 1. トークン定義 ================================================================================ 【予約語(Keywords)】15個 - box, new, me, public, if, else, loop, break, continue - peek, return, import, from, birth, fn 【演算子・記号(Operators/Symbols)】 - 算術: + - * / % - 比較: == != < > <= >= - 論理: and or not - 代入: = - アクセス: . (ドット) [ ] (インデックス) - 関数: ( ) { } - 区切り: , ; - 型注釈: : - peekアーム: => - 親メソッド: :: - コメント: // /* */ 【リテラル(Literals)】 - 整数: /[0-9]+/ - 浮動小数: /[0-9]+\.[0-9]+/ - 文字列: /"([^"\\]|\\.)*"/ - 真偽値: true false - null値: null 【識別子(Identifier)】 - /[a-zA-Z_][a-zA-Z0-9_]*/ - 予約語と衝突しない 【空白・改行】 - 改行は文の区切り(セミコロン自動挿入規則適用) - インデント: 意味を持たない(Python風ではない) - 行継続: \ で明示的に次行へ続く ================================================================================ 2. 式構文(Expression Grammar) ================================================================================ 【優先順位(高→低)】 1. リテラル、識別子、(式) 2. 関数呼び出し: expr(args) 3. メンバアクセス: expr.member 4. インデックス: expr[index] 5. 単項演算: not expr, -expr 6. 乗除: * / % 7. 加減: + - 8. 比較: < > <= >= == != 9. 論理積: and 10. 論理和: or 11. peek式: peek expr { ... } 【結合規則】 - 算術演算子: 左結合 - 比較演算子: 非結合(a < b < c は不可) - 論理演算子: 左結合 【式の種類】 ``` Expression ::= | Literal | Identifier | "me" | Expression "." Identifier // メンバアクセス | Expression "[" Expression "]" // インデックス | Expression "(" ExprList? ")" // 関数呼び出し | "new" Identifier "(" ExprList? ")" // インスタンス生成 | "fn" "(" ParamList? ")" Block // 関数Box | PeekExpression | BinaryOp | UnaryOp | "(" Expression ")" ``` 【peek式】 ``` PeekExpression ::= "peek" Expression "{" PeekArm* "else" "=>" (Expression | Block) "}" PeekArm ::= Pattern "=>" (Expression | Block) Pattern ::= | Literal // 現在はリテラルのみ | Pattern "|" Pattern // 将来: 複数パターン ``` ================================================================================ 3. 文構文(Statement Grammar) ================================================================================ ``` Statement ::= | Expression // 式文 | "local" IdentList ("=" ExprList)? // 変数宣言 | Identifier "=" Expression // 代入 | "if" Expression Block ("else" (Block | Statement))? | "loop" "(" Expression ")" Block | "break" | "continue" | "return" Expression? | BoxDeclaration | FunctionDeclaration | "import" StringLiteral ("as" Identifier)? Block ::= "{" Statement* "}" BoxDeclaration ::= "box" Identifier ("from" IdentList)? "{" FieldDeclaration* MethodDeclaration* "}" FieldDeclaration ::= ("public")? Identifier ":" Identifier ("=" Expression)? MethodDeclaration ::= ("public")? (Identifier | "birth") "(" ParamList? ")" Block ``` ================================================================================ 4. 名前解決規則 ================================================================================ 【スコープ】 1. グローバルスコープ(box、関数定義) 2. Box内スコープ(フィールド、メソッド) 3. 関数スコープ(引数、local変数) 4. ブロックスコープ({}内のlocal) 【シャドーイング】 - 内側のスコープが外側を隠蔽 - 同一スコープ内での再定義は不可 【meの解決】 - Box内: 現在のBoxインスタンス - fn{}内: 関数Box自身 - それ以外: エラー 【from Parent.method()の解決】 - 現在のBoxがParentにデリゲートしているか確認 - Parent::method()も同様 ================================================================================ 5. 曖昧性と解決策 ================================================================================ 【左再帰なし】 - 全て右再帰または反復で記述 【最長一致】 - トークナイザーレベルで最長一致 - 例: ">=" は2文字演算子として認識 【バックトラック不要】 - LL(1)またはLL(2)で解析可能 - peekトークンで次の構文要素を判別 【曖昧箇所】 1. 関数呼び出し vs 変数 - 解決: "("の有無で判別 2. {} がブロックか関数Boxか - 解決: 直前のfnキーワードで判別 3. セミコロン自動挿入 - 改行時に次が中置演算子でない場合挿入 - 例外: 行末が不完全な式の場合は挿入しない ================================================================================ 6. エラー処理 ================================================================================ 【期待トークンエラー】 ``` Expected 'token' but found 'actual' at line X, column Y ``` 【回復戦略】 1. 文レベル: 次の文開始トークンまでスキップ 2. ブロックレベル: 対応する}までスキップ 3. Box/関数レベル: 次のbox/fnまでスキップ 【行・列の追跡】 - 各トークンに位置情報を付与 - エラー時は該当箇所を表示 【エラーメッセージ例】 ``` Error: Missing 'else' in peek expression --> program.nyash:10:5 | 10 | peek value { | ^^^^ peek expression requires 'else' branch ``` ================================================================================ 7. 将来拡張の余地 ================================================================================ 【予約済み位置】 - @ 記号: 将来の属性用 - # 記号: 将来のマクロ用 - ` 記号: 将来のテンプレート用 【拡張可能な構文】 - Pattern: 現在はリテラルのみ、将来は構造体パターン等 - 型注釈: 現在は : Type のみ、将来はジェネリクス等 【前方互換性】 - 未知の @ で始まる行は読み飛ばし - box内の未知セクションは警告のみ ================================================================================ 8. 既存実装への差分最小化 ================================================================================ 【tokenizer.rs への変更】 1. 予約語リストにpeek, continue, birthを追加 2. => を2文字演算子として追加 3. :: を2文字演算子として追加 【parser.rs への変更】 1. parse_when() → parse_peek() に改名 2. parse_field_declaration() を追加(name: Type形式) 3. parse_fn_literal() を追加(fn式のため) 4. continue文の処理追加 5. birthキーワードの特殊処理 【AST変更】 ```rust // 追加 enum Expr { // ... Peek { scrutinee: Box, arms: Vec<(Pattern, BlockOrExpr)>, else_arm: Box, }, FnLiteral { params: Vec, body: Block, }, } enum Stmt { // ... Continue, } ``` 【セマンティクス】 - peekは式として値を返す - else必須のバリデーション追加 - returnは最内関数スコープから脱出 ================================================================================