yhara.jp

Recent Posts

言語実装tips:複数の式をまとめる

2024-12-17
Tech

このエントリは言語実装 - Qiita Advent Calendar 2024 - Qiitaの17日目の記事です。

今日は処理系実装上のTipsを一つ紹介します。

例:if式

たとえばC言語みたいに、

  if (a) {
    b
    c
  } else {
    d
  }

のようなif式をもつ言語を作りたいとします。文と式が分かれている言語にする場合、Rustで実装するとこんな感じになるでしょうか。

struct Stmt {
  ...
  ExprStmt(Box<Expr>)  //いわゆる式文。
}
struct Expr {
  IntLiteral(usize),
  ...
  If {
    cond_expr: Box<Expr>,
    then_clause: Vec<Stmt>,
    else_clause: Vec<Stmt>,
  }
}

一方、すべてが式の言語にする場合はどうでしょうか。なんとなく

struct Expr {
  IntLiteral(usize),
  ...
  If {
    cond_expr: Box<Expr>,
    then_clause: Vec<Expr>,
    else_clause: Vec<Expr>,
  }
}

みたいにthenとelseが複数のExprを持つ感じにしたくなりますが、ここに複文(ならぬ、複式?)を導入して

struct Expr {
  IntLiteral(usize),
  ...
  Stmts(Vec<Expr>) //連続した式を順に評価する。最後に評価した値をStmts全体の値とする。
  If {
    cond_expr: Box<Expr>,
    then_clause: Box<Expr>,  //単一の式、またはStmtsが入る
    else_clause: Box<Expr>,  //単一の式、またはStmtsが入る
  }
}

のようにするとわりと取り回しが良いです(良かったです)。

注意点

上記の場合、空のStmtsの扱いに注意する必要があります。簡単なのは何からの「ゼロ値」を導入し(C言語のnull、LispやRubyのnil、的な)、空のStmtsを作ろうとしたときは自動的にそれを挿入することです。

この場合意味論としては、例えば

  if (x) {
    print(x)
  } else {
  }

というif式は

  if (x) {
    print(x)
  } else {
    nil
  }

と等価になります。

More posts

Posts

(more...)

Articles

(more...)

Category

Ads

About

About the author