Documents of TEBA

TEBA演習: 第4回 TEBA の拡張

1 フィルタ

TEBA は、フィルタ型のアーキテクチャを採用し、 各解析機能をフィルタとして実現しています。機能拡張においては、 各フィルタを拡張したり、フィルタを追加します。フィルタを拡張する場合は、 可能であれば、拡張したい内容だけを実現するフィルタを作成して試したあと、 フィルタを統合すると安全に拡張することができます。

フィルタは、cparse.pl が出力する字句系列を入力として受け取り、 字句系列を書換えたら、その字句系列を出力します。 書換えたあとのソースコード自体が欲しいときは、 join-token.pl で結合するようにします。

フィルタを作成するには、構文要素がどう表現されているかを理解する必要がありますが、 TEBA では、それを解説した文書は用意されていません。 これは、知りたい構文要素について、簡単な断片を書いて確かめれば済むからです。 したがって、まずは小さいサンプルを作り、その結果を見ながらどう作れば良いか考えましょう。 また、入れ子の組み合わせや、異なる種類の文の並びなど、様々な条件を考えて、 サンプルを徐々に増やしていきましょう。

自習課題

1.1 練習問題1

前処理命令の条件命令である #ifdef と #endif のみの対応関係を明示できるよう、 各字句に識別記号を挿入するフィルタを作成しなさい。 (注意: #else への対応は次の問題)

1.2 練習問題2

前処理命令の #else にも対応関係を表す識別記号を付加するよう 練習問題1のフィルタを拡張しなさい。

1.3 練習問題3

前処理の条件命令の入れ子の最大の深さを求めるプログラムを作成しなさい。 ただし、属性付き字句系列を読み込み、深さのみを出力するプログラムであること。

2 演習問題

前処理で定義されるマクロを展開するフィルタを作成しなさい。フィルタには 引数にマクロ名を指定し、指定されたマクロだけを展開し、その他の部分は そのまま維持すること。機能的に制限がある場合には、それを明記すること。

ヒント

まずは、条件を限定して作ってみよう。

徐々に発展させていこう。

なお、#ifdef などの条件を考慮することも可能ですが、 かなり高等な技術が必要なので、そこまでは考えなくても構わないです。

超手抜きバージョンですが、この形が基本です。 まずは、プログラムを読んで文字列置換のところを書いて試してみましょう。

#!/usr/bin/env perl

# コマンド引数を一つ取り出す
my $name = shift ;

# マクロ名(らしきもの)が指定されているか確認
if ($name !~  /^[a-zA-Z_]\w*$/) {
    die "No valid macro name is specified.";
}

# 入力を読み取り、変数 $all にテキストとして格納
my $all = join('', <>);

# 引数なしマクロの定義部分のパターン
my $directive = q(
PRE_DEFINE\s+<#\s*define>
SP_B\s+<.*?>
ID_MC\s+<) . $name . q(>
SP_B\s+<.*?>
B_MCB\s+(#\w+)\s+<>
(.*\n)+E_MCB\s+\1\s+<>
);


#展開後の字句列を $ext に保存
my $ext;
if ($all =~ m/$directive/s) {
  $ext = ;
} else {
  die "No macro '$name' is defined.";
}

#!!ここにマクロの展開のための文字列置換を書く!!
#!!すなわち、$all の中の $name の識別子の字句を $ext で置き換える!!
#!!$name の識別子の字句のパターンは ID\w+\s+<$name>\n になる !!

#展開後の字句列を出力
print $all
Copyrighted by Atsushi Yoshida. atsu@nanzan-u.ac.jp
Contact: Yoshida Atsushi, atsu@nanzan-u.ac.jp
[Documents of TEBA]