Instaparseでパーサジェネレータ
Instaparseの位置づけ
InstaparseはClojure言語による パーサジェネレータ - Wikipedia である
これのルール記述はBNFの拡張であるEBNFが使われている。
EBNFで構造化言語のルールを記述する
さっそくだが、「<p>sample</p>」を読み取るBNFのルールを書いてみた。とは言え、HTMLの複雑なルールを最初から書くのは無理なので、とりあえずタグの開始と終了を読み取れるものを作る。
しかもこのルール記述、de.setf.xml/html-grammar.bnf at master · lisp/de.setf.xml · GitHub からコピーしてきたものである。
コードサンプル
(ns sample (:require [instaparse.core :as insta])) ;; ;; https://github.com/lisp/de.setf.xml/blob/master/bnf/html-grammar.bnf ;; (def as-and-bs (insta/parser "HtmlDocument ::= Root Root ::= ElementHtml ElementHtml ::= HtmlTag | ( STag ( '/>' | ( '>' #'\\w'++ ETag ) ) ) HtmlTag ::= '<' #'\\w'++ S* '>' STag ::= '<' #'\\w'++ S* ETag ::= '</' #'\\w'++ S* '>' S ::= (' ' | '\t' | '\r\n' | '\n')+ ")) (def fool-tags "<p>sample</p>") (defn fool-sample [] (println (as-and-bs fool-tags)))
出力
- sampleのデータがきっちり構造化されて戻ってきた
lein test html-template.test [:HtmlDocument [:Root [:ElementHtml [:STag < p] > s a m p l e [:ETag </ p >]]]]
後はこれに対して指定されたキーを使ってデータを取得したりすればいいのである。
パーサジェネレータについて調べた
パーサジェネレータの位置づけ
少しだけパーサジェネレータについて書く。パーサジェネレータとはパーサを生成できるソフトウェアのことである。
そもそもパーサとはなんだったか確認しよう。
パーサ(=構文解析器)
パーサとは 構文解析器 - Wikipedia である。
XMLを読み取るパーサの例としては Document Object Model - Wikipedia や Simple API for XML - Wikipedia。要はDOMやSaxである。Javaを書いたことがあればちょっとは使ったことがあるはず。最近はXMLからJavaに変換する時は Java Architecture for XML Binding - Wikipedia を使うかもしれない。
構造を持った入力テキストの処理をおこなうものはすべてパーサだと言える。
なぜテキストに構造を持たせなければいけないのか?それは データ記述言語 - Wikipedia に書かれている以下のような理由による:
データ記述言語は、以下の点に主眼を置いて作られた。
1.複雑なデータ構造をもつデータを格納する。
2.データの記述方法や個々のデータ要素へのアクセス方法の共通化をはかる。
3.データをテキスト形式で格納する。
ただのテキストファイルだと、日付や誰によって更新されたか、どの部分が列でどの部分が行か?わからない。そういったデータの格納の仕方を定めたXML, JSON, HTML, そしてCSVやTSVすべてデータ記述言語と言える。XMLがまどろっこしいのは別にプログラマーがマゾだからではなく、付与したい情報が多いからである。
パーサジェネレータの利点
パーサがデータ記述言語によって構造化されたデータを読み取れることはわかった。では、パーサジェネレータは何ができるのか?
パーサジェネレータは、なんとこのデータ記述言語のルールを記述するだけでパーサを作ってくれる。スゴイ!
次の記事でそれを実践していく:
パーサジェネレータの実装の種類
Wikipediaを見ると、以下のような手法があるようだ
AtCoder - AtCoder Beginner Contest 012 (バスと避けられない運命) を解いてみた
解法
Rubyによる解答 TLE
アルゴリズムは正しそうですが11個のテストケースでTLEしてしまいました。
Submission #1725365 - AtCoder Beginner Contest 012 | AtCoder
D言語による解答 AC!
しかしそんなことでは諦めない。もちろん俺らは抵抗するで?拳で*1
Submission #1728053 - AtCoder Beginner Contest 012 | AtCoder