nDiki : 文法

1999年1月31日 (日)

flex文法定義を読む (定義節/parse.y)

字句解析系生成プログラム作成のために、flex-2.5.4a.tar.gz の文法定義を読んでみる。 まずここでは、定義節 (definitions section) を読むことにする。

トークンの定義は scan.l で、構文の定義は parse.y でなされている。 まずは parse.y から見ていこう。 以下の引用部はすべて parse.y である。 行頭には行番号を付加してある。 また説明に不要な部分は省略してある。

以下はでのトークン名の宣言である。

     3	%token CHAR NUMBER SECTEND SCDECL XSCDECL NAME PREVCCL EOF_OP
     4	%token OPTION_OP OPT_OUTFILE OPT_PREFIX OPT_YYCLASS
     5
     6	%token CCE_ALNUM CCE_ALPHA CCE_BLANK CCE_CNTRL CCE_DIGIT CCE_GRAPH
     7	%token CCE_LOWER CCE_PRINT CCE_PUNCT CCE_SPACE CCE_UPPER CCE_XDIGIT

また以下は定義節に関係するルールの部分である。

   112	goal		:  initlex sect1 sect1end sect2 initforrule
   139			;
   141	initlex		:
   147			;
   149	sect1		:  sect1 startconddecl namelist1
   150			|  sect1 options
   151			|
   152			|  error
   154			;
   156	sect1end	:  SECTEND
   162			;
   164	startconddecl	:  SCDECL
   167			|  XSCDECL
   169			;
   171	namelist1	:  namelist1 NAME
   174			|  NAME
   177			|  error
   179			;
   181	options		:  OPTION_OP optionlist
   182			;
   183
   184	optionlist	:  optionlist option
   185			|
   186			;
   188	option		:  OPT_OUTFILE '=' NAME
   193			|  OPT_PREFIX '=' NAME
   195			|  OPT_YYCLASS '=' NAME
   197			;

goal (112行目) は開始記号である。 ここで字句解析仕様記述全体の構造を定義している。 ここでは sect1end までを見ることにする。

   141	initlex		:
   147			;

initlex (141行目) は仕様記述の先頭の部分で還元される。 ここで初期化処理が行われる。

   156	sect1end	:  SECTEND
   162			;

sect1end (156行目) トークン SECTEND を導出する。

 SECTEND は scan.l 119行目の

^"%%".* のパターンで定義されるものである。 つまり、行頭の %% で 定義節が終了することを示す。

   149	sect1		:  sect1 startconddecl namelist1
   150			|  sect1 options
   151			|
   152			|  error
   154			;

定義節の中身は sect1 によって導出される。 定義節は、開始条件の宣言(startconddecl namelist1 または オプション指令 options の任意個の繰り返しを導出する。

   164	startconddecl	:  SCDECL
   167			|  XSCDECL
   169			;

startconddecl はトークン SCDECL または XSCDECL である。 SCDECL は scan.l 108行目の ^"%s"{NAME}? で定義され、 XSCDECL は109行目の ^"%x"{NAME}? である。 よって行頭から始まる %s または %x (名前として使える文字列が続いてもよい) によって始まる行が開始条件の宣言ということになる。

   171	namelist1	:  namelist1 NAME
   174			|  NAME
   177			|  error
   179			;

SCDECL または XSCDECL の次には namelist1 が次に導出される。 namelist、トークン NAME の1回以上の繰り返しである。

   181	options		:  OPTION_OP optionlist
   182			;

一方 sect1 は options も導出する。 options は、トークン OPTION_OP の後に optionlist が続くとなっている。 OPTION_OP は scan.l 131行目にある ^"%option" にマッチした時返されるトークンである。 つまりオプション指令は行頭から始まる %option によって始まることを示している。

   184	optionlist	:  optionlist option
   185			|
   186			;

そして optionlist (181行目) は option の 0回以上の繰り返しである。

   188	option		:  OPT_OUTFILE '=' NAME
   193			|  OPT_PREFIX '=' NAME
   195			|  OPT_YYCLASS '=' NAME
   197			;

その option は トークン OPT_OUTFILE, OPT_PREFIX, OPT_YYCLASS のどれかの後に '=' が続き、そしてその後に NAME がくるといいうものである。OPT_OUTFILE, OPT_PREFIX, OPT_YYCLASS はそれぞれ文字列 outfile, prefix, yyclass が対応する。

これだけでは定義節のすべての文法を網羅していない。実は他の多くの部分は、字句解析で処理してしまっている。次回はscan.l についてもうすこし詳しく見てみよう。

スポンサード リンク
[ 1月31日全て ]

2001年10月14日 (日)

[ 日記 ] 20:45 レイアウト修正

毎度見ていただく人にはウザいであろう「ページトップの説明や、カレンダー」を下部に。

適当に修正を繰り返してきたので、HTML文法チェッカを通すと結構ぼろぼろ。 きちんと整理せねば……

[ 10月14日全て ]

2003年12月2日 (火)

EPIC

Windows XPEclipse 3M5 + EPIC を入れて Perlプログラムの編集をしてみる。 例よってCVSが便利なのはよしとして、リアルタイムの文法チェックもそこそこいけるかなという感じ。 ビルドやテスト等を考えると、Linux 上での Emacs で開発した方がまだまだ上。

Windows 関連のPerlコードを書く時や、気分転換にはいいかもしれぬ。

[ 12月2日全て ]

2004年2月10日 (火)

[ WiKicker ] WiKicker脚注機能追加

WiKicker スタイルで日記を記述するにあたり欠けている機能として「脚注」がある。 Wiki としては必須でないので WiKicker には導入していないのだが、日記としては無いと困る。 脚注が使えると文を書く時に正直手を抜ける。 またハイパー日記システム上の旧記事をコンバートする時にも無いといろいろ面倒だし。

ということで実装。

インラインブロック

さてどうしたものか。 WiKickerWRI (BracketName 等を含む識別子)としての実装なら、parser の変更もなく新しいWRI scheme の追加と対応するクラスを書くだけですむ。 しかし WRI は終端記号なので、そうすると脚注の中でWRIを使えなくなる。 それは困る。

ということで、やはり非終端記号が必要。 悩んだあげく、

 {{scheme: ... }}

という「インラインブロック非終端記号」を導入。 {{..}} というのは確かいくつかの WikiEngineプラグイン呼び出しで使っている記法だったような。

  • 一般的な文章中には現れず、
  • かといって文章中に混ぜてもそれほど違和感なく(wiki ではこれが重要)
  • これ以上文法を追加したくないので、今後機能追加の際に利用できるように scheme 指定できる

といった点から、このようにしてみた。 2番目の点で合格点の出せる記法かどうかは微妙だが、まぁ許せる範囲かな。

{{ }} は、1行中に現れる必要有り。 「...」は scheme specific part だが、今のところ scheme によらず、InlineParser で解析されて部分木になるため、WRI とか ... とかも書ける。 InlineParser では正規表現を使っていて括弧の数は数えないので、今のところ {{ }} の中に {{ }} は書けないが、まぁ問題ないでしょう。

脚注記法

脚注は、

 {{fn: ...}}

となる。 普通。

実装

  • InlineParser の拡張
  • InlineBlockNode クラスの追加
  • 各 Visitor に visit_InlineBlockNode を追加。
  • HtmlFragmentVisitor に fn: の処理を追加。

いざ実装してみると、ちょこっとのコードで実現。 脚注番号の降り方とか、今後改良する点はあるけど、大枠は完成。

Wiki文法の標準化

今まで触れなかったが、やはり文法拡張する際は気になる存在。

各方面で出ている賛否どちらの意見もうなずける点が多く、自分の思いつく点もだいたいどこかで語られている感じ。

私が最初に Wiki の存在を知ったのは、やまだ君からだった。 当然「記法(文法)は?」というのがまず気になった点だったが、その時すでに「Wiki文法WikiEngine毎に異なる」という事だった。

WiKicker という新しい WikiEngine を作る際には、もちろん各 Wiki文法を調べたのだが、それはもう様々で。 「見出し」記号など単純に流派的なものと、ブロックプラグインなど設計思想に依存するものがあって、特に後者はどれかを統一して選択するのは難しいと感じた。

WiKicker では(もともと利用していた) YukiWiki2 に emacs-wiki の [[A][B]] を加え、その他の文法要素と表記は、

  • 見やすさ
  • メジャー度
  • WiKicker のベースの文法と衝突しない
  • 行指向を採用(行を越えた、開始・終了を利用者が明記しないで済むように)
  • 構文解析しやすい (実装の容易性は、高速化・独自ツール作成時に重要)

あたりをポイントに決めた。

将来標準(ができたとして)に準拠する?

多分しないな。 面倒だし。

[ 2月10日全て ]

2004年2月11日 (水)

[ DiKicker ] ハイパー日記システム(hns) からのコンバータ作成開始

DiKicker のコードを書いている途中に「やっぱ先にデータがある程度ないとな」ということで、hns からのコンバータを作り始める。

hnf文法は非常にシンプルなのでコンバータの作成が簡単(RTをのぞく)。 あらためて感心。

RT のスパン記号

||、== で上、左のセルと結合できるのか。 WiKicker にも欲しいな(| はセル区切りに使っているで、別の記号にする必要があるけど)。

[ 2月11日全て ]

2004年5月11日 (火)

文法の動的変更可能な言語

昔研究していたネタ。 やまだ君のまわりで同じようなネタでちょっぴり盛り上がっているらしい。

実用度はかなり微妙だが、できると結構楽しい言語になると思うんだけどな。

動的変更可能な言語仕様記述言語で「言語仕様記述言語を動的に変更しつつ」「動的に変更可能な言語を定義する」といったことも当時考えていたっけか。

[ 5月11日全て ]

2005年5月10日 (火)

iモードHTMLシミュレータ Version 7.2

iモード向けの簡単なCGI プログラムの開発を社内で頼まれているので、動作・レイアウト確認用にシミュレータを探してみる。

あら、NTTドコモで配ってらっしゃる。 ということでダウンロード。昔633S用につくったiモード向けページなどを閲覧してみる。

機種別のプロファイルのようなものはなくて、自分で画面サイズやiモード対応HTMLバージョンの選択をしてあげる必要があるけれど、HTTPヘッダのチェックやHTMLのソース表示、文法チェック機能などがあり今回はこれで十分いけそうだ。

[ 5月10日全て ]

2005年9月13日 (火)

[ WiKicker ] hell mode - HTMLタグ付けブロックの導入

WiKicker では、直接 WikiPageHTMLタグを記述して表示に反映させる機能を提供していない。

HTMLタグ付けを許すのは嫌だ

HTMLタグ付けを許すと

  • 入力ミスによるトラブル
  • 悪意ある入力によるトラブル

が起きやすくなるし、ページのソースの単純さが大きく失われてしまう。 レンダリングしてHTMLにした時に、正しいHTMLを出力されることを保証することが困難になるとともに、HTML以外へのレンダリング/コンバートもかなり難しくなる。

この機能を導入すると、Wiki の良さの半分(あるいはもうちょっと沢山か、もうちょっと少なめ)が失われてしまう。

でも

とはいえ欲しいという声があることも事実。 オープンな WikiForum では全くお勧めできないが、閉じたユーザグループの中ではまぁ必要悪なのかもしれぬ。

また正直ちょっとした表現を追加したい時に、WiKicker 用のプラグインを書くのも面倒だというのは確かにある。

WiKicker では開始・終了マーカによる複数行にまたがるブロックを表すための文法は(閉じ忘れを避けるため)意図的に排除してある。 このため、複数行にわけて書きたいような長いデータを扱うような拡張も導入しにくい。

ちょっと手抜きして「生HTML書けちゃえば」という誘惑はなくはない。

大人の事情

ということでまあ自分に言い訳をしつつ、標準ではオフというかたちで HTMLタグ付けブロックを導入することにした。 スイッチは hell mode とかにしたい (今回は syntax.html というプロパティ名にしたけれど)。

記法は単純に、

 normal wiki syntax text...
 <html>
 html tagged text...
 ...
 </html>
 normal wiki syntax text...

のように行頭が <html> である行から、行頭が </html>である行までをHTMLタグ付けブロックとすることに。 このため、<html>ではじまる段落が書けなくなるという小さな非互換が発生するが、いたしかたない。

サニタイズ

HTMLタグを直接使えるようにするとはいえ、全てを許してしまうのはあまりに危険で非人道的すぎる。 有効なHTMLタグや属性は限定的であるべきだ。

このあたりの処理は面倒だが、幸いにしてCPANにモジュールがある。 今回は HTML::Scrubber を使うことにした。 HTML::Parserを使って parse し、指定したルールに従ってサニタイズしてくれる。

ちょっと使ってみた範囲では日本語(UTF-8UTF8 フラグなし)でも問題ないようだし、文法的に正しくなくてもきちんとサニタイズできているようだ。

ということで、これを採用することに。

どの要素・属性を許すかはまだきちんと決めかねる。 当面は様子をみながら、調整していく予定。 サニタイザは設置者が置き換えられるようにプラガブルにしておかねばならないな。

[ 9月13日全て ]

2005年11月21日 (月)

定型書式で内容を記述していくのに便利な形式は?

要求仕様書LaTeX で書いている。 要求と仕様の組をまとめて longtable で記述しているのだが、 LaTeX らしい繁雑さがあってちょっと効率が悪い。 マクロを定義すればある程度書きやすくなると思うが、それでもそこそこまでな気がする。

文書の中にレコードの並びが書けて、レコードの並びの中に文章が書きやすいそんなフォーマットはないものかなぁ。

  • LaTeX + マクロ
    • 整形は綺麗。
    • 記述が繁雑になりがち。\マクロ名とか {} とか。
  • DocBook
    • 仕様デカスギ
    • 以前使ってみたことがあるが、手で書くのにはしんどい。
  • XML
    • 構造的な情報の表現には良いのだが、手で書くのはしんどい。開きタグも閉じタグも。
    • 普通の章節や、マークアップのルールを考えなければならない(定義するか借りてくるか)。
    • LaTeX等へのコンバータを書く必要あり。
  • YAML
    • レコードの並びだけだったら良いが、文書の他の要素を一緒に書くのには適さない。
    • ある程度の構造やボリュームがあると、思ったほど手書きしやすくない。
    • YAML Perl モジュールで痛い目にあっている。

Wiki に慣れきっている自分にとっては Wiki 文法のような感じで記述できて、一部に定型レコードの並びが書けて、そこの整形ルールだけ定義してあげれば LaTeX に変換できるとかそういった感じがのものが欲しい。 定型レコードの部分は RFC822 のヘッダみたいな感じで良くで、値の部分に長めの文章を複数行で書けるものがいい。

構造化テキスト用フォーマット、あるいはWiki フォーマットをアレンジするのがいいかもしれないな。 このあたりのフォーマットは、ソーステキストのままでも十分読み易いことを意識して定義されているので書くのは楽。

  • reStructuredText
    • いいらしい。
    • HTMLLaTeXXML へのコンバータがある。
    • 拡張性も考慮されているらしい。
    • でも Python
  • Markdown
  • WiKicker (Wiki)
    • かなり書き慣れている。
    • レコードの並びの書き方を考える必要あり。
    • 複数行にまたがる処理を書くのが面倒。
    • 自分で書いているシステムなので中身は何でも知っている。
    • マイナー。

レコード部分とは関係ないけれど reStructuredTextMarkdown の「アンダーラインのあるテキストを見出しとする」っていうのはいいな。 普段メールプレーンテキストでちょっと文書を打つときに使っているスタイルと一緒だ。

要求仕様書用に使うかどうかは別として、要チェック。

[ 11月21日全て ]

2005年11月24日 (木)

早速 reStructuredText から LaTeX へのコンバータを書く

要求仕様書を書くのに reStructuredText を使ってみることにしる。 reStructuredText文法の上で、あるルールに従って書いた特定のセクションやフィールドリストを要求レコードや要求仕様レコードとし、自前でコンバータを書いて LaTeX へ変換する形。

まずは最初のアイデア通り rst2xml で XML に変換してから、Perl スクリプトで読み込んで処理することにする。

Perl 側の処理は XML::LibXML で (何となく XML::DOM より好き)。 しかし毎度ながら DOM 面倒くさい。 とりあえず、今必要な要素のみ変換コードを書く。 reStructuredTextXML へ変換した時の DTD があるので、おいおいこれを見ながらきちんと埋めていかねば。

最低限のものができて、早速コンバート。

これで生 LaTeX で書くより随分楽になった。よし。

[ 11月24日全て ]

About Me

Naney Naney

Naney (なにい)です。株式会社ミクシィで SNS 事業の部長をしています。

About nDiki

nDiki1999年1月に始めたコンピュータ日誌を前身とする NaneyWeb 日記(兼パーソナルナレッジベース)です。

#nNote タグがついている記事は他の記事に比べて、より断片的・未整理・不完全なちょっとしたノートです。まだ結論に至っていない考えなども含まれます。頻繁/大幅に更新したり削除したりすることがあります。

※本サイトの内容は個人的見解であり所属組織とは関係ありません。

Other Notes

ナレッジベースアプリケーション Obsidian で書いているノートの一部を notes.naney.org で 公開しています。

最近検索されている記事

月別インデックス
Process Time: 0.056191s / load averages: 0.69, 1.08, 0.94
nDiki by WATANABE Yoshimasa (Naney)
Powered by DiKicker