新・見出し解析
ルールテーブルとしてこんなレコードを用意して
type
THeadingAction = (haNone, haFirst, haLast);
TParsingAction = (paNone, paEnter, paSwitch, paLeave);
PParsingRule = ^TParsingRule;
TParsingRule = record
Current: WideString;
Token: Byte;
TokenText: WideString;
HeadingAction: THeadingAction;
ParsingAction: TParsingAction;
Next: WideString;
CurrentNum: Integer; //高速化用にCurrentを連番化
NextNum: Integer; //高速化用にNextを連番化
end;
まだ設定できるようにはしてないからルールテーブルは定数埋めこみで
const
HTMLParsingRules: array[0..18] of TParsingRule = (
(Current: ''; Token: sTag; TokenText: '<head'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'HT'),
(Current: ''; Token: sTag; TokenText: '<HEAD'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'HT'),
(Current: 'HT'; Token: sTagOpen; TokenText: ''; HeadingAction: haLast; ParsingAction: paSwitch; Next: ''),
(Current: ''; Token: sTag; TokenText: '<body'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'BT'),
(Current: ''; Token: sTag; TokenText: '<BODY'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'BT'),
(Current: 'BT'; Token: sTagOpen; TokenText: ''; HeadingAction: haLast; ParsingAction: paEnter; Next: 'B'),
(Current: 'B'; Token: sTag; TokenText: '<h1'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<H1'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<h2'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<H2'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<h3'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<H3'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<h4'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<H4'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<h5'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<H5'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<h6'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'B'; Token: sTag; TokenText: '<H6'; HeadingAction: haFirst; ParsingAction: paSwitch; Next: 'H'),
(Current: 'H'; Token: sTagClose; TokenText: ''; HeadingAction: haLast; ParsingAction: paSwitch; Next: 'B'));
現在の状態がCurrentの時にToken, TokenTextに一致するトークン(字句解析で切り出して来た塊)が来たら、HeadingActionとParsingActionを実行。
haFirstとhaLastで囲んだ範囲が見出しに、paEnterは今の状態をpushして新たな状態に、paSwitchは今の状態を忘れて新たな状態に、paLeaveはpaEnterでpushした状態をpopして戻る。paEnter/paLeave間で追加された見出しは直前の見出しの子ノードに。
ちなみにsTagは"
スタックが無いと構文解析はきついということでこんなの作ってみましたが、果たしてこれだけで構造化言語のクラス宣言や関数宣言を抽出できるでしょうか?