CSSの記述テクニック 階層宣言コーディングから.エイプリルフールネタを掘り起こすのはどうかとも思いましたが,意外と便利そうな記述方法でしたので,コンバータを記述してみました.以下が,階層的CSSを解析するためのクラスのプロトタイプ宣言.
namespace clx { template < class CharT, class Traits = std::char_traits<CharT> > class basic_hierarchical_css { public: typedef CharT char_type; typedef unsigned int size_type; typedef std::basic_string<CharT, Traits> string_type; typedef std::vector<string_type> selector_list; typedef std::vector<string_type> declaration_list; basic_hierarchical_css(); template <class InputIterator> explicit basic_hierarchical_css(InputIterator first, InputIterator last); explicit basic_hierarchical_css(const char_type* filename); explicit basic_hierarchical_css(const string_type& filename); template <class InputIterator> basic_hierarchical_css& assign(InputIterator first, InputIterator last); basic_hierarchical_css& assign(const char_type* filename); basic_hierarchical_css& assign(const string_type& filename); size_type size() const; const string_type& selector(size_type i) const; const declaration_list& declarations(size_type i) const; }; typedef basic_hierarchical_css<char> hcss; }
コンストラクタ,またはassign()メソッドに,ファイル名,または入力ストリームのイテレータを渡すと階層的CSSの解析を行い,結果を配列(vector)に格納します.解析結果にアクセスするためのメソッドは,selector()およびdeclarations()メソッドで,それぞれ添え字に対応するセレクタおよび宣言リストを返します.declarations()で返されるのは配列(vector)であるため,さらにat()メソッドでそれぞれの宣言にアクセスします.
例外処理は今の所ごく簡易なもので,以下の場合のみ例外を投げます.
- 指定されたファイルが存在しない場合.
- コメント記号の対("/*","*/")の数が合わない場合.
- 中括弧の対("{","}")の数が合わない場合.
制限,その他注意事項としては,以下の通り(いくつかは修正するかも).
- @規則が存在すると解析に失敗する.
- コメントは全て読み捨てる.
- 中括弧(“{”,“}”),セミコロン(“;”),コメント記号(“/*”,“*/”)の直後に空白や改行文字が挿入されていないと,解析に失敗する.
さて,このクラスを使用した簡単なコンバータのプログラム例を書いてみました.
#include <cstdlib> #include <iostream> #include "hcss.h" int main(int argc, char* argv[]) { if (argc < 2) { std::cerr << "usage: hcssconv filename" << std::endl; std::exit(-1); } try { clx::hcss hc; hc.assign(argv[1]); // print for (size_t i = 0; i < hc.size(); i++) { if (hc.declarations(i).empty()) continue; std::cout << hc.selector(i) << " {" << std::endl; for (size_t j = 0; j < hc.declarations(i).size(); j++) { std::cout << " " << hc.declarations(i).at(j) << std::endl; } std::cout << '}' << std::endl; std::cout << std::endl; } } catch (std::runtime_error& e) { std::cerr << e.what() << std::endl; std::exit(-1); } return 0; }
このプログラムは引数としてファイル名を渡すと,そのファイル中に記述されている階層的CSSを解析し,結果を標準出力へ出力します.以下のサンプルで試してみます.尚,現在のところ,コンパイルはgccでのみ確認.
body { p.caution { color: red; font-weight: bold; } div.entry { background-color: #eee; p.caution { border: 1px solid green; margin: 1em; } } }
実行結果は,以下の通り.
p.caution { color: red; font-weight: bold; } div.entry { background-color: #eee; } div.entry p.caution { border: 1px solid green; margin: 1em; }
なかなか面白いかもしれません.hcss_20070406.tar.gz
追記
hcssクラスをもうすこし真面目に書き直したバージョン(with clx).最新の説明は,こちら.