主な成果: - TypeBox(型情報をBoxとして扱う)による統合ABI設計 - C ABI + Nyash ABIの完全統合仕様書作成 - 3大AI専門家(Gemini/Codex/ChatGPT5)による検証済み - ChatGPT5の10個の安全性改善提案を反映 - README.mdのドキュメント更新(全起点から到達可能) MapBox拡張: - string型キーサポート(従来のi64に加えて) - remove/clear/getOr/keysStr/valuesStr/toJson実装 - keys()/values()のランタイムシムサポート(TypeBox待ち) その他の改善: - Phase 11.9(文法統一化)ドキュメント追加 - Phase 16(FoldLang)ドキュメント追加 - 非同期タイムアウトテスト追加 - 各種ビルド警告(未使用import等)は次のリファクタリングで対応予定 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
398 lines
11 KiB
Plaintext
398 lines
11 KiB
Plaintext
================================================================================
|
||
Phase 11.9: 文法統一化 実装計画
|
||
================================================================================
|
||
|
||
【実装の優先順位と依存関係】
|
||
|
||
1. 基礎インフラ(必須・最優先)
|
||
└→ 2. 文法定義ローダー
|
||
└→ 3. 既存コンポーネント統合
|
||
└→ 4. AI機能追加
|
||
|
||
================================================================================
|
||
Step 1: 基礎インフラ構築(3日)
|
||
================================================================================
|
||
|
||
■ ディレクトリ構造
|
||
src/
|
||
├── grammar/
|
||
│ ├── mod.rs # メインモジュール
|
||
│ ├── definition.rs # 文法定義構造体
|
||
│ ├── loader.rs # YAML読み込み
|
||
│ ├── validator.rs # 検証ロジック
|
||
│ └── export.rs # AI向けエクスポート
|
||
│
|
||
grammar/
|
||
└── nyash-grammar-v1.yaml # 文法定義ファイル
|
||
|
||
■ 基本構造体設計
|
||
```rust
|
||
// src/grammar/definition.rs
|
||
use serde::{Deserialize, Serialize};
|
||
use std::collections::HashMap;
|
||
|
||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||
pub struct GrammarDefinition {
|
||
pub version: String,
|
||
pub language: String,
|
||
pub keywords: HashMap<String, KeywordCategory>,
|
||
pub syntax_rules: HashMap<String, SyntaxRule>,
|
||
pub ai_common_mistakes: Vec<CommonMistake>,
|
||
pub ancp_mappings: AncpMappings,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||
pub struct KeywordDef {
|
||
pub token: String,
|
||
pub category: String,
|
||
pub semantic: String,
|
||
pub syntax: Option<String>,
|
||
pub example: Option<String>,
|
||
pub deprecated_aliases: Vec<String>,
|
||
pub ai_hint: String,
|
||
}
|
||
```
|
||
|
||
■ Cargo.toml追加
|
||
```toml
|
||
[dependencies]
|
||
serde = { version = "1.0", features = ["derive"] }
|
||
serde_yaml = "0.9"
|
||
once_cell = "1.19" # グローバルシングルトン用
|
||
```
|
||
|
||
================================================================================
|
||
Step 2: 文法定義ローダー実装(2日)
|
||
================================================================================
|
||
|
||
■ シングルトンローダー
|
||
```rust
|
||
// src/grammar/loader.rs
|
||
use once_cell::sync::Lazy;
|
||
use std::sync::Arc;
|
||
|
||
pub static NYASH_GRAMMAR: Lazy<Arc<NyashGrammar>> = Lazy::new(|| {
|
||
Arc::new(NyashGrammar::load().expect("Failed to load grammar"))
|
||
});
|
||
|
||
impl NyashGrammar {
|
||
fn load() -> Result<Self, Error> {
|
||
let yaml_path = concat!(
|
||
env!("CARGO_MANIFEST_DIR"),
|
||
"/grammar/nyash-grammar-v1.yaml"
|
||
);
|
||
let yaml_str = std::fs::read_to_string(yaml_path)?;
|
||
let def: GrammarDefinition = serde_yaml::from_str(&yaml_str)?;
|
||
|
||
Ok(Self::from_definition(def))
|
||
}
|
||
}
|
||
```
|
||
|
||
■ キャッシュ付き検証
|
||
```rust
|
||
// src/grammar/validator.rs
|
||
pub struct KeywordValidator {
|
||
valid_keywords: HashSet<&'static str>,
|
||
deprecated_map: HashMap<&'static str, &'static str>,
|
||
}
|
||
|
||
impl KeywordValidator {
|
||
pub fn validate(&self, word: &str) -> KeywordValidation {
|
||
if self.valid_keywords.contains(word) {
|
||
KeywordValidation::Valid
|
||
} else if let Some(&correct) = self.deprecated_map.get(word) {
|
||
KeywordValidation::Deprecated {
|
||
correct,
|
||
hint: self.get_hint(word)
|
||
}
|
||
} else {
|
||
KeywordValidation::Unknown
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
================================================================================
|
||
Step 3: Tokenizer統合(3日)
|
||
================================================================================
|
||
|
||
■ 最小限の変更で統合
|
||
```rust
|
||
// src/tokenizer.rs の修正
|
||
use crate::grammar::NYASH_GRAMMAR;
|
||
|
||
impl NyashTokenizer {
|
||
fn read_keyword_or_identifier(&mut self) -> TokenType {
|
||
let word = self.read_identifier_string();
|
||
|
||
// 文法定義ベースの判定に切り替え
|
||
match NYASH_GRAMMAR.validate_keyword(&word) {
|
||
KeywordValidation::Valid(token_type) => token_type,
|
||
KeywordValidation::Deprecated { correct, .. } => {
|
||
// 警告を出しつつ、正しいトークンを返す
|
||
self.warnings.push(Warning::DeprecatedKeyword {
|
||
used: word.clone(),
|
||
correct: correct.to_string(),
|
||
line: self.line,
|
||
});
|
||
NYASH_GRAMMAR.get_token_type(correct)
|
||
}
|
||
KeywordValidation::Unknown => {
|
||
TokenType::IDENTIFIER(word)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
■ 互換性維持
|
||
```rust
|
||
// 既存のmatch文を段階的に置き換え
|
||
// Phase 1: 並行実行して差分チェック
|
||
#[cfg(debug_assertions)]
|
||
{
|
||
let old_result = self.old_keyword_match(&word);
|
||
let new_result = NYASH_GRAMMAR.validate_keyword(&word);
|
||
debug_assert_eq!(old_result, new_result, "Grammar mismatch: {}", word);
|
||
}
|
||
```
|
||
|
||
================================================================================
|
||
Step 4: Parser統合(3日)
|
||
================================================================================
|
||
|
||
■ 構文ルールの適用
|
||
```rust
|
||
// src/parser/mod.rs
|
||
impl Parser {
|
||
fn parse_box_definition(&mut self) -> Result<ASTNode, ParseError> {
|
||
// 文法ルールを取得
|
||
let rule = NYASH_GRAMMAR.get_syntax_rule("box_definition")?;
|
||
|
||
// ルールに基づいて解析
|
||
self.consume(TokenType::BOX)?;
|
||
let name = self.parse_identifier()?;
|
||
|
||
// 親クラスの解析(文法定義に従う)
|
||
let extends = if self.match_token(&TokenType::FROM) {
|
||
self.parse_delegation_list()?
|
||
} else {
|
||
vec![]
|
||
};
|
||
|
||
// 制約チェック
|
||
self.check_constraints(&rule, &parsed_node)?;
|
||
|
||
Ok(parsed_node)
|
||
}
|
||
}
|
||
```
|
||
|
||
================================================================================
|
||
Step 5: AI機能実装(4日)
|
||
================================================================================
|
||
|
||
■ エクスポートツール
|
||
```rust
|
||
// tools/export-grammar.rs
|
||
use nyash::grammar::NYASH_GRAMMAR;
|
||
|
||
fn main() {
|
||
// 1. 基本文法JSON
|
||
let json = NYASH_GRAMMAR.export_as_json();
|
||
std::fs::write("nyash-grammar.json", json)?;
|
||
|
||
// 2. AI用プロンプト
|
||
let prompt = generate_ai_prompt(&NYASH_GRAMMAR);
|
||
std::fs::write("ai-prompt.txt", prompt)?;
|
||
|
||
// 3. VSCode snippets
|
||
let snippets = generate_vscode_snippets(&NYASH_GRAMMAR);
|
||
std::fs::write("nyash.code-snippets", snippets)?;
|
||
}
|
||
```
|
||
|
||
■ AIコード検証器
|
||
```rust
|
||
// src/grammar/ai_validator.rs
|
||
pub struct AiCodeValidator {
|
||
grammar: Arc<NyashGrammar>,
|
||
mistake_patterns: Vec<CompiledPattern>,
|
||
}
|
||
|
||
impl AiCodeValidator {
|
||
pub fn validate_code(&self, code: &str) -> Vec<CodeIssue> {
|
||
let mut issues = vec![];
|
||
|
||
// 1. よくある間違いパターンをチェック
|
||
for pattern in &self.mistake_patterns {
|
||
if let Some(matches) = pattern.find_in(code) {
|
||
issues.push(CodeIssue::CommonMistake {
|
||
pattern: pattern.name.clone(),
|
||
correction: pattern.correction.clone(),
|
||
locations: matches,
|
||
});
|
||
}
|
||
}
|
||
|
||
// 2. パース可能かチェック
|
||
match NyashParser::parse(code) {
|
||
Ok(ast) => {
|
||
// AST検証
|
||
issues.extend(self.validate_ast(&ast));
|
||
}
|
||
Err(e) => {
|
||
issues.push(CodeIssue::ParseError(e));
|
||
}
|
||
}
|
||
|
||
issues
|
||
}
|
||
}
|
||
```
|
||
|
||
================================================================================
|
||
Step 6: ANCP統合(3日)
|
||
================================================================================
|
||
|
||
■ 文法aware圧縮
|
||
```rust
|
||
// src/ancp/grammar_aware.rs
|
||
impl GrammarAwareTranscoder {
|
||
pub fn new() -> Self {
|
||
let grammar = NYASH_GRAMMAR.clone();
|
||
let mappings = &grammar.ancp_mappings;
|
||
|
||
Self {
|
||
grammar,
|
||
keyword_map: build_keyword_map(mappings),
|
||
reverse_map: build_reverse_map(mappings),
|
||
}
|
||
}
|
||
|
||
pub fn compress(&self, token: &Token) -> String {
|
||
// 文法定義のマッピングを使用
|
||
if let Some(compressed) = self.keyword_map.get(&token.text) {
|
||
compressed.clone()
|
||
} else {
|
||
token.text.clone()
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
================================================================================
|
||
テスト戦略
|
||
================================================================================
|
||
|
||
■ 単体テスト
|
||
```rust
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_grammar_loading() {
|
||
let grammar = NyashGrammar::load().unwrap();
|
||
assert_eq!(grammar.version, "1.0");
|
||
}
|
||
|
||
#[test]
|
||
fn test_keyword_validation() {
|
||
let grammar = NYASH_GRAMMAR.clone();
|
||
|
||
// 正しいキーワード
|
||
assert!(matches!(
|
||
grammar.validate_keyword("me"),
|
||
KeywordValidation::Valid(_)
|
||
));
|
||
|
||
// 非推奨キーワード
|
||
assert!(matches!(
|
||
grammar.validate_keyword("this"),
|
||
KeywordValidation::Deprecated { correct: "me", .. }
|
||
));
|
||
}
|
||
}
|
||
```
|
||
|
||
■ 統合テスト
|
||
```rust
|
||
// tests/grammar_integration.rs
|
||
#[test]
|
||
fn test_tokenizer_parser_consistency() {
|
||
let code = "box Cat from Animal { me.name = 'Fluffy' }";
|
||
|
||
// Tokenize with grammar
|
||
let tokens = tokenize_with_grammar(code);
|
||
|
||
// Parse with grammar
|
||
let ast = parse_with_grammar(&tokens);
|
||
|
||
// Validate consistency
|
||
assert!(ast.is_ok());
|
||
}
|
||
```
|
||
|
||
■ スナップショットテスト
|
||
```rust
|
||
#[test]
|
||
fn test_ai_export_stability() {
|
||
let export = NYASH_GRAMMAR.export_for_ai();
|
||
insta::assert_json_snapshot!(export);
|
||
}
|
||
```
|
||
|
||
================================================================================
|
||
CI/CD統合
|
||
================================================================================
|
||
|
||
■ GitHub Actions追加
|
||
```yaml
|
||
- name: Validate Grammar
|
||
run: |
|
||
cargo run --bin validate-grammar -- grammar/nyash-grammar-v1.yaml
|
||
|
||
- name: Generate AI Artifacts
|
||
run: |
|
||
cargo run --bin export-grammar
|
||
# アーティファクトとして保存
|
||
|
||
- name: Test Grammar Integration
|
||
run: |
|
||
cargo test --test grammar_integration
|
||
```
|
||
|
||
================================================================================
|
||
移行計画
|
||
================================================================================
|
||
|
||
1. **既存コードの互換性維持**
|
||
- 古いキーワードも一時的に受け入れ
|
||
- 警告を出しながら段階的に厳格化
|
||
|
||
2. **ドキュメント更新**
|
||
- 言語リファレンスを文法定義から自動生成
|
||
- VSCode拡張に統合
|
||
|
||
3. **コミュニティへの告知**
|
||
- 変更点の明確な説明
|
||
- 移行ツールの提供
|
||
|
||
================================================================================
|
||
成果物チェックリスト
|
||
================================================================================
|
||
|
||
□ grammar/nyash-grammar-v1.yaml
|
||
□ src/grammar/mod.rs(実装完了)
|
||
□ Tokenizer統合(警告付き動作)
|
||
□ Parser統合(制約チェック)
|
||
□ export-grammar ツール
|
||
□ AIコード検証器
|
||
□ ANCP統合
|
||
□ 包括的テストスイート
|
||
□ ドキュメント更新
|
||
□ CI/CD統合
|
||
|
||
================================================================================ |