267 lines
7.6 KiB
Plaintext
267 lines
7.6 KiB
Plaintext
|
|
================================================================================
|
|||
|
|
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<Expr>,
|
|||
|
|
arms: Vec<(Pattern, BlockOrExpr)>,
|
|||
|
|
else_arm: Box<BlockOrExpr>,
|
|||
|
|
},
|
|||
|
|
FnLiteral {
|
|||
|
|
params: Vec<String>,
|
|||
|
|
body: Block,
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
enum Stmt {
|
|||
|
|
// ...
|
|||
|
|
Continue,
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
【セマンティクス】
|
|||
|
|
- peekは式として値を返す
|
|||
|
|
- else必須のバリデーション追加
|
|||
|
|
- returnは最内関数スコープから脱出
|
|||
|
|
|
|||
|
|
================================================================================
|