Minishell
2025.02 – 2025.04Bashの仕様に基づくシェルの再実装
CShell
概要
Bashの仕様に基づいたシェルをC言語で再実装するプロジェクトを2人チームで取り組んだ。 入力文字列の字句解析(レキサー)、抽象構文木(AST)への構文解析(パーサー)、コマンド実行という3段階のパイプライン構造で設計し、パイプやリダイレクション、環境変数展開、シグナルハンドリング、ヒアドキュメントなどの基本機能を実装した。 Bashの挙動に準拠することを重視し、エラーコードや終了ステータスの扱いを含めた実際のシェルに近い動作を再現した。

担当範囲
- •レキサー:入力文字列のトークン化、クォート処理
- •パーサー:再帰下降構文解析による抽象構文木(AST)の構築
- •シグナルハンドリング:5つの状態に応じたシグナル制御
- •ヒアドキュメント:子プロセスによる入力収集
ポイント
- •再帰下降パーサーによるAST設計と構造化
- •unionを用いたC言語での擬似的なポリモーフィズムの実現
- •シグナル処理における状態管理
- •チーム開発における開発プロセス設計と運用
苦労・工夫した点
初めてのチーム開発であったため、開発プロセスの構築から着手した。GitHub Issueによるタスク管理とfeatureブランチによる並行開発フローを設計し、担当範囲とファイル境界を明確にすることでコンフリクトを最小限に抑えた。 パーサーの実装では、パイプライン構造を正しく表現できるAST設計に最も苦労した。トークン列を直接処理するのではなく、構文木として表現することで構造的な解釈が可能になると考え、再帰下降パーサーを採用した。 ASTのデータ構造は、CMDノードとPIPEノードをunionで統一し、C言語でもノードの種類を抽象化できる構造とした。この設計により、パイプラインの入れ子構造をシンプルに表現でき、後続の実行処理との分離も実現した。 シグナルハンドリングでは、プロンプト待機中・コマンド実行中・ヒアドキュメント入力中などの複数の状態で異なる挙動が求められ、状態管理が複雑になる課題があった。そこで、グローバル変数による状態共有とreadlineの制御(rl_done)を組み合わせることで、状態ごとの適切なシグナル処理を実現した。