前回は、入力された数式を「意味のある塊」に分けるLexerを実装しました。 次に必要なのは、その塊が「定数なのか、関数なのか」を判断するための辞書です。
今回は、TOMLファイルを使って誰でも簡単に関数を拡張できる Definitions(定義管理) 機能を実装します。
前回 Lexerの実装 : 【Rust】自作計算機エンジンへの道:Lexer(字句解析)で数式をトークンに分解する #2

1. tomlで読み込ませたいもの
普通の電卓なら標準関数(sin, cosなど)があれば十分ですが、この電卓のコンセプトは 「自分専用の環境構築」 です。
- 物理定数(
pi,e,eVなど)を自由に追加したい - よく使う独自の計算式(畳み込みのサイズ計算など)を関数として登録したい
- コードを書き換えずに、設定ファイルを追加するだけで機能を増やしたい
これらを実現するために、Rustと親和性の高いTOMLを採用しました。

2. 実装 Definitions : Serdeを使い倒す
Definitionsのとれる値は数値か、関数になります。
pub struct Definitions {
pub constants: HashMap<String, f64>,
pub functions: HashMap<String, FunctionDef>,
}tomlのロード自体は、 toml::from_str(&content)?; といった感じで、tomlのパサーをそのまま利用しました。
pub fn load_from_file<P: AsRef<Path>>(path: P) -> Result<Self, Box<dyn std::error::Error>> {
let content = fs::read_to_string(path)?;
let defs: Definitions = toml::from_str(&content)?;
Ok(defs)
}柔軟な定義を可能にする #[serde(untagged)]
このほかちょっと工夫したところとして、TOMLをある程度自由に書けるようにserde(untagged) をつかっています。これを使うことで、エイリアス風の記述と、変数定義からするしっかりとした記述両方拾えるようになっています。また、読み込みの深さをデフォルトで32にしており、再帰読み込みのバグなどで固まるのを防ぐようにしています。
// 関数定義構造体
#[derive(Debug, Deserialize, Clone)]
#[serde(untagged)]
pub enum FunctionDef {
Simple(String),
Complex {
args: Vec<String>,
expr: String,
#[serde(default)]
memoize: bool,
#[serde(default = "default_depth")]
max_depth: usize,
},
}
fn default_depth() -> usize { 32 }標準 definitions.toml
基本的なものは、definitions.tomlに記入していくことにしています。ユーザ定義のものは user.tomlとかの別ファイルで定義し、tomlの入っているフォルダを自動的に走査して読み込めるようにする予定です。
[constants]
pi = 3.1415926535
e = 2.71828
[functions]
# 式というかエイリアスの定義
golden_ratio = "1.61803"
# 引数を明示する定義にしています
conv = { args = ["W", "K"], expr = "W - K + 1" }definitions.tomlに記入した例
3. 読み込めているか検証
出力部分を、前回のlexerの出力トークンを今回作成した Definitionsに渡し、解析できたかどうかを出力するように改変し、動かしてみました。


tomlで定義した piが読み込めていることを確認。
次に、関数の読み込みができるか検証してみました。

解析できているようです。
ホットリロード機能を実装しているので動くかどうかも検証してみました。tomlを編集し、”eV = 1.602″というのを追記、そのごF5でリロードし読み込めているか検証します。


ホットリロード成功
さいごに
ここまでに、数式の解析→関数に定義したものの読み込みができたので、次回は、数式全体を構造木といして解析する仕組みを作っていこうと思います。
次回 Parser (構文解析)ASTにする:関連記事は、2026年4月29日に公開予定 (あと7時間)
ここまで読んでいただきありがとうございます。
では、次の記事で。 lumenHero
関連記事
初回 構想編 :【Rustで作る】ターミナル関数電卓を設計する(アーキテクチャ編) #1
前回 Lexer実装:【Rust】自作計算機エンジンへの道:Lexer(字句解析)で数式をトークンに分解する #2