16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"HTLM の TABLE タグを解析"
この発言に対し以下のコメントが寄せられています
#00960 DUDE さん RE:HTML の TABLE タグを解析(1)
#00961 DUDE さん RE:HTLM の TABLE タグを解析(2)
Turbo Pascal 用の lex & yacc (もちろん Delphi でも使えます)があること
を教えてもらったので、それを使って HTML Parser もどきを書いてみました。
●Turbo Pascal Lex/Yacc written by Albert Graef
http://www.musikwissenschaft.uni-mainz.de/~ag/tply/tply.html
ただし、この lex ライブラリはコンソール専用&短い文字列専用にできている
ので、GUI アプリケーションで使うためには若干の修正が必要です。
tply41.zip に含まれる LexLib.pas を以下のように変更します。
・ファイルの先頭に {$H-} を追加。
・ファイルの末尾を以下のように変更。
{$IFDEF CONSOLE}
assign(yyinput, '');
assign(yyoutput, '');
reset(yyinput); rewrite(yyoutput);
{$ENDIF}
yacc の方はそのまま使えますが、%type で長い文字列が使えないという制限が
あります(レコードの可変部に長い文字列が置けないため)。
このサンプルは HTML ファイルを解析して、その中に含まれる TABLE タグを抽
出し、ツリーにして表示するものです。入れ子になった TABLE に対応していな
いのと(構文は対応していますが、アクションが対応していません)、文字列の
長さが255文字に制限されます。また、連続して複数の HTML を開く事ができま
せん。
Main という名前でフォーム(名前は TForm1)用のユニットを作り、それにボタ
ン(TButton; 名前は Button1)1個と、ツリービューコントロール
(TTreeView; 名前は TreeView1)1個を置いてください。ボタンのハンドラは
ソースにある通りです。その他にはイベントハンドラはありません。
テキストファイルは3つ(token.l、pars.y、main.pas)、フォームファイルが
1つ(main.dfm)、プロジェクトファイルが1つ(htmlp.dpr)の構成です。
同じものをパッケージにまとめたものを
http://member.nifty.ne.jp/dude/files/htmlp.lzh
にも置いておきました。
------------------------------------------------------------------------------
<---- token.l ----
%%
"<"[Tt][Aa][Bb][Ll][Ee](">"|" "+[^>]*">") return(TABLE);
"</"[Tt][Aa][Bb][Ll][Ee](">"|" "+[^>]*">") return(_TABLE);
"<"[Tt][Rr](">"|" "+[^>]*">") return(TR);
"</"[Tt][Rr](">"|" "+[^>]*">") return(_TR);
"<"[Tt][Hh](">"|" "+[^>]*">") return(TH);
"</"[Tt][Hh](">"|" "+[^>]*">") return(_TH);
"<"[Tt][Dd](">"|" "+[^>]*">") return(TD);
"</"[Tt][Dd](">"|" "+[^>]*">") return(_TD);
"<!-".*"->" ; /* comment */
[\n\t ]+ begin
yylval.yyShortString := yytext;
return(SP);
end;
. begin
yylval.yyShortString := yytext;
return(CH);
end;
<---- pars.y ----
/*
HTML TABLE tag parser for sample-gura.
Written by Yutaka Iizuka(DUDE)
*/
%{
unit pars;
interface
uses YaccLib, LexLib, Main;
function yyparse : Integer;
implementation
%}
%token TABLE
%token _TABLE
%token TR
%token _TR
%token TH
%token _TH
%token TD
%token _TD
%token <ShortString> SP
%token <ShortString> CH
%token ILLEGAL
%type <ShortString> string
%%
s
: /* empty */
| s element
;
element
: table
| string
{ if Assigned(CurrentCell) then
begin
Form1.TreeView1.Items.AddChild(CurrentCell, $1);
end;
}
;
table
: table_begin table_rows table_end
;
table_begin
: TABLE
{ CurrentTable :=
Form1.TreeView1.Items.AddChild(CurrentCell, 'TABLE');
}
;
table_end
: _TABLE
{ CurrentTable := nil; }
;
table_rows
: /* empty */
| table_rows table_row
;
table_row
: tr_begin table_data_list tr_end
| SP
;
tr_begin
: TR
{ if Assigned(CurrentTable) then
begin
CurrentRow :=
Form1.TreeView1.Items.AddChild(CurrentTable, 'TR');
end;
}
;
tr_end
: _TR
{ CurrentRow := nil; }
| /* empty */
{ CurrentRow := nil; }
;
table_data_list
: /* empty */
| table_data_list table_data
;
table_data
: th_begin element th_end
| td_begin element td_end
| SP
;
th_begin
: TH
{ if Assigned(CurrentRow) then
begin
CurrentCell := Form1.TreeView1.Items.AddChild(CurrentRow, 'TH');
end;
}
;
th_end
: _TH
{ CurrentCell := nil; }
;
td_begin
: TD
{ if Assigned(CurrentRow) then
begin
CurrentCell := Form1.TreeView1.Items.AddChild(CurrentRow, 'TD');
end;
}
;
td_end
: _TD
{ CurrentCell := nil; }
;
string
: /* empty */
{ $$ := ''; }
| string CH
{ $$ := $1 + $2; }
| string SP
{ $$ := $1 + $2; }
;
%%
{$I token.pas}
begin
end.
<---- main.pas ----
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
TreeView1: TTreeView;
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
CurrentTable:TTreeNode;
CurrentRow:TTreeNode;
CurrentCell:TTreeNode;
implementation
{$R *.DFM}
uses Pars, LexLib, YaccLib;
procedure TForm1.Button1Click(Sender: TObject);
begin
with TOpenDialog.Create(Self) do
begin
Options := [ofHideReadOnly];
Filter := 'HTML Files|*.html;*.htm|Text Files|*.txt';
if Execute then
begin
CurrentTable := nil;
CurrentRow := nil;
CurrentCell := nil;
AssignFile(yyinput, FileName);
Reset(yyinput);
yyparse;
TreeView1.Items.BeginUpdate;
try
TreeView1.FullExpand;
finally
TreeView1.Items.EndUpdate;
end;
end;
end;
end;
end.
99/10/4(Mon) 08:45pm [AirCraft開発] PFF01344 DUDE
http://member.nifty.ne.jp/dude/
Original document by DUDE 氏 ID:(PFF01344)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|