1 (*********************************************************
3 TSsParser Component - Parser for Sakura Script
4 (C)2001 naruto/CANO-Lab All Rights Reserved.
6 \95K
\82¸
\8eg
\97p
\8fð
\8c\8f\82É
\82µ
\82½
\82ª
\82Á
\82Ä
\82¨
\8eg
\82¢
\82
\82¾
\82³
\82¢
\81B
7 \81\9a\82±
\82Ì
\83R
\83\93\83|
\81[
\83l
\83\93\83g
\82ð
\8eg
\97p
\82µ
\82½
\83v
\83\8d\83O
\83\89\83\80\82ð
\8cö
\8aJ
\82·
\82é
\8fê
\8d\87\82Í
\81A
8 \81@
\81@
\8dì
\8eÒ
\82É
\88ê
\95ñ
\82·
\82é
\95K
\97v
\82ª
\82 \82è
\82Ü
\82·
\81B
\8fÚ
\82µ
\82
\82Í
\90à
\96¾
\8f\91\82ð
\81B
10 **********************************************************)
17 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
20 //
\83}
\81[
\83N
\83A
\83b
\83v
\82Ì
\8eí
\97Þ
\82ð
\8e¦
\82µ
\82Ü
\82·
\81B
21 //mtTag:
\83^
\83O
\82Å
\82·
\81B\e, \t, \s[1]
\82È
\82Ç
\81A\
\82Å
\8en
\82Ü
\82é
\82à
\82Ì
22 //mtMeta:
\83\81\83^
\95¶
\8e\9a\97ñ
\81B%
\82Å
\8en
\82Ü
\82é
\82à
\82Ì
\81B
23 //mtTagErr:
\83^
\83O
\82Ì
\83}
\81[
\83N
\83A
\83b
\83v
\83G
\83\89\81[
\82Æ
\8ev
\82í
\82ê
\82é
\95\94\95ª
\81B
24 //mtStr:
\83}
\81[
\83N
\83A
\83b
\83v
\82Å
\82Í
\82È
\82¢
\95¶
\8e\9a\97ñ
\81B
25 TSsMarkUpType = (mtTag, mtMeta, mtTagErr, mtStr);
27 //
\83X
\83N
\83\8a\83v
\83g
\82Ì
\88ê
\95\94\82Ì
\89ð
\90Í
\82ð
\83R
\81[
\83h
\82Å
\8ds
\82¦
\82Ü
\82·
28 TSsParseEvent = procedure (Sender: TObject; const Script: String;
29 var Len: integer; var MarkType: TSsMarkUpType; var Extra: String) of object;
31 //
\97á
\8aO
\83N
\83\89\83X
32 ESsParserError = class(Exception);
34 //
\93à
\95\94\82Å
\8eg
\97p
\82·
\82é
\83N
\83\89\83X
\82Å
\82·
35 TSsMarkUp = class(TObject)
39 FMarkUpType: TSsMarkUpType;
40 procedure SetExtra(const Value: String);
42 constructor Create(MarkUpType: TSsMarkUpType; Str: String; Extra: String = '');
43 property MarkUpType: TSsMarkUpType read FMarkUpType;
44 property Str: String read FStr;
45 property Extra: String read FExtra write SetExtra;
48 //SsParser
\82Ì
\96{
\91Ì
49 TSsParser = class(TComponent)
51 FTagPattern: TStrings; //SS
\83^
\83O
\83p
\83^
\81[
\83\93\95¶
\8e\9a\97ñ
52 FMetaPattern: TStrings; //SS
\83\81\83^
\95¶
\8e\9a\97ñ
\83p
\83^
\81[
\83\93\95¶
\8e\9a\97ñ
53 FInputString: String; //
\93ü
\97Í
\82µ
\82½
\95¶
\8e\9a\97ñ
55 FLeaveEscape: boolean;
56 FEscapeInvalidMeta: boolean;
57 FOnParse: TSsParseEvent;
58 procedure SetInputString(const Value: String);
59 function GetCount: integer;
60 function GetExtra(Index: integer): String;
61 function GetMarkUpType(Index: integer): TSsMarkUpType;
62 function GetStr(Index: integer): String;
63 procedure SetExtra(Index: integer; const Value: String);
65 procedure SetMetaPattern(const Value: TStrings);
66 procedure SetTagPattern(const Value: TStrings);
67 procedure SetOnParse(const Value: TSsParseEvent);
68 function GetFirstChar(const Str: String): String;
69 function ChopFirstChar(var Str: String): String;
73 constructor Create(AOwner: TComponent); override;
74 destructor Destroy; override;
75 function MatchP(PStr, PPattern: PChar): integer;
76 function Match(Str, Pattern: String): integer;
77 function GetParam(Tag: String; const Index: integer): String;
78 function EscapeParam(const Param: String): String;
79 property Count: integer read GetCount;
80 property MarkUpType[Index: integer]: TSsMarkUpType read GetMarkUpType;
81 property Str[Index: integer]: String read GetStr; default;
82 property Extra[Index: integer]: String read GetExtra write SetExtra;
83 property InputString: String read FInputString write SetInputString;
85 { Published
\90é
\8c¾ }
86 //
\83X
\83N
\83\8a\83v
\83g
\89ð
\90Í
\82Ì
\83p
\83^
\81[
\83\93\82ð
\8e¦
\82·
\81B
\83h
\83L
\83\85\83\81\83\93\83g
\8eQ
\8fÆ
87 property TagPattern: TStrings read FTagPattern write SetTagPattern;
88 property MetaPattern: TStrings read FMetaPattern write SetMetaPattern;
89 //mtStr
\92\86\82Ì
\81u\\
\81v
\82â
\81u\%
\81v
\82Æ
\82¢
\82Á
\82½
\95¶
\8e\9a\97ñ
\82ð
\81u\
\81v
\81u%
\81v
\82É
\95Ï
\8a·
\82¹
\82¸
\95ú
\92u
\82·
\82é
\81B
90 property LeaveEscape: boolean read FLeaveEscape write FLeaveEscape
92 //%
\88È
\8d~
\82Ì
\95¶
\8e\9a\97ñ
\82ªMetaPattern
\82Å
\89ð
\90Í
\82Å
\82«
\82È
\82©
\82Á
\82½
\82Æ
\82«
\81A%
\82ð\%
\82É
\95Ï
\8a·
\82·
\82é
93 property EscapeInvalidMeta: boolean read FEscapeInvalidMeta
94 write FEscapeInvalidMeta default false;
95 //
\89ð
\90Í
\82Ì
\88ê
\95\94\82ð
\83p
\83^
\81[
\83\93\82Å
\82Í
\82È
\82Object Pascal
\82Å
\8f\88\97\9d\82·
\82é
\82½
\82ß
\82Ì
\83C
\83x
\83\93\83g
96 property OnParse: TSsParseEvent read FOnParse write SetOnParse;
105 RegisterComponents('Samples', [TSsParser]);
110 procedure TSsParser.BeginParse;
111 var Str, Talk, T, Ex: String;
118 Str := FInputString; //
\8f\88\97\9d\82·
\82é
\82×
\82«
\95¶
\8e\9a\97ñ
\82ð
\90Ý
\92è
119 //
\95¶
\8e\9a\97ñ
\82Ì
\8dÅ
\8cã
\82ªLeadByte
\82Å
\8fI
\82í
\82é
\95s
\90³
\82È
\95¶
\8e\9a\97ñ
\82Å
\81A
\8f
\82È
\82
\82Æ
\82à
\83A
\83N
\83Z
\83X
\88á
\94½
\82ª
120 //
\8fo
\82È
\82¢
\82æ
\82¤
\82É
\82·
\82é
\82½
\82ß
\82Ì
\8f\88\92u
\81B(
\8c\8b\89Ê
\82ª
\82Ç
\82¤
\82È
\82é
\82©
\82Í
\95Û
\8fØ
\82µ
\82È
\82¢)
122 if Length(Str) = 0 then Exit;
125 while PStr^ <> #0 do begin
126 if PStr^ = '\' then begin
130 //"\\"
\82É
\82æ
\82é
\83G
\83X
\83P
\81[
\83v
137 end else if PStr^ = '%' then
139 //"\%"
\82É
\82æ
\82é
\83G
\83X
\83P
\81[
\83v
149 //
\83^
\83O
\82ç
\82µ
\82¢
150 //
\83C
\83x
\83\93\83g
\94
\8ds
154 if Assigned(FOnParse) then begin
155 FOnParse(Self, String(PStr), Le, Mt, Ex);
157 if (Mt <> mtTag) and (Mt <> mtTagErr) then begin
158 raise ESsParserError.Create('
\90³
\82µ
\82¢
\83G
\83\8c\83\81\83\93\83g
\83^
\83C
\83v
\82ð
\95Ô
\82µ
\82Ä
\82
\82¾
\82³
\82¢');
161 if Mt = mtTagErr then IsErr := true;
164 if Le <= 0 then begin
165 for i := 0 to FTagPattern.Count-1 do begin
167 if Length(T) = 0 then Continue;
169 if T[1] = '!' then begin
172 end else if T[1] <> '\' then
173 raise ESsParserError.CreateFmt('TagPattern
\95\
\8bL
\83~
\83X - %d
\8ds
\96Ú', [i+1]);
174 Le := MatchP(PStr, PChar(T));
175 if Le > 0 then Break;
178 if Length(Talk) > 0 then begin
179 FMarkUpList.Add(TSsMarkUp.Create(mtStr, Talk));
183 //
\89½
\82ç
\82©
\82Ì
\83^
\83O
\83p
\83^
\81[
\83\93\82É
\83}
\83b
\83`
184 T := Copy(String(PStr), 1, Le);
187 FMarkUpList.Add(TSsMarkUp.Create(mtTagErr, T, Ex))
189 FMarkUpList.Add(TSsMarkUp.Create(mtTag, T, Ex));
191 //
\8e\9f\82Ì1
\95¶
\8e\9a\82ð
\8aÜ
\82ß
\82Ä
\83G
\83\89\81[
192 Inc(PStr); // '\'
\94ò
\82Î
\82·
193 if PStr^ in LeadBytes then
195 T := '\' + Copy(String(PStr), 1, 2);
202 FMarkUpList.Add(TSsMarkUp.Create(mtTagErr, T));
205 end else if (PStr^ = '%') then begin
206 //
\83C
\83x
\83\93\83g
\90¶
\90¬
208 if Assigned(FOnParse) then begin
209 FOnParse(Self, String(PStr), Le, Mt, Ex);
211 if Mt <> mtMeta then begin
212 raise ESsParserError.Create('
\90³
\82µ
\82¢
\83G
\83\8c\83\81\83\93\83g
\83^
\83C
\83v
\82ð
\95Ô
\82µ
\82Ä
\82
\82¾
\82³
\82¢');
215 Dec(Le); //
\90æ
\93ª
\82Ì'%'
\82Ì
\92·
\82³
\82ð
\83J
\83b
\83g
218 Inc(PStr); // '%'
\82ª
\94ò
\82Ô
221 for i := 0 to FMetaPattern.Count-1 do
223 if Length(FMetaPattern[i]) = 0 then
225 Le := MatchP(PStr, PChar(FMetaPattern[i]));
232 if Length(Talk) > 0 then
234 FMarkUpList.Add(TSsMarkUp.Create(mtStr, Talk));
237 T := Copy(String(PStr), 1, Le);
239 FMarkUpList.Add(TSsMarkUp.Create(mtMeta, '%' + T, Ex));
242 //%
\88È
\8d~
\82ª
\83\81\83^
\95¶
\8e\9a\97ñ
\82Å
\82Í
\82È
\82¢
\8fê
\8d\87
243 if FEscapeInvalidMeta then
250 if PStr^ in LeadBytes then
252 Talk := Talk + Copy(String(PStr), 1, 2);
256 Talk := Talk + PStr^;
261 if Length(Talk) > 0 then FMarkUpList.Add(TSsMarkUp.Create(mtStr, Talk));
264 function TSsParser.ChopFirstChar(var Str: String): String;
266 Result := GetFirstChar(Str);
267 Delete(Str, 1, Length(Result));
270 procedure TSsParser.ClearList;
273 for i := FMarkUpList.Count-1 downto 0 do begin
274 TSsMarkUp(FMarkUpList[i]).Free;
277 FMarkUpList := TList.Create;
280 constructor TSsParser.Create(AOwner: TComponent);
283 FTagPattern := TStringList.Create;
284 FMetaPattern := TStringList.Create;
285 FMarkUpList := TList.Create;
286 FLeaveEscape := true;
289 destructor TSsParser.Destroy;
298 function TSsParser.EscapeParam(const Param: String): String;
300 //StringReplace
\82ÍMBCS
\82É
\91Î
\89\9e\82µ
\82Ä
\82¢
\82é
301 Result := StringReplace(Param, '\', '\\', [rfReplaceAll]);
302 Result := StringReplace(Param, ']', '\]', [rfReplaceAll]);
305 function TSsParser.GetCount: integer;
307 Result := FMarkUpList.Count;
310 function TSsParser.GetExtra(Index: integer): String;
312 if (Index >= 0) and (Index <= FMarkUpList.Count-1) then
313 Result := TSsMarkUp(FMarkUpList[Index]).Extra
318 function TSsParser.GetFirstChar(const Str: String): String;
320 //SJIS
\82ð
\8dl
\97¶
\82µ
\82Ä
\8dÅ
\8f\89\82Ì
\95¶
\8e\9a\82ð
\90Ø
\82è
\8fo
\82·
321 if Length(Str) <= 1 then begin
324 if ByteType(Str, 1) = mbLeadByte then begin
325 Result := Str[1] + Str[2];
332 function TSsParser.GetMarkUpType(Index: integer): TSsMarkUpType;
334 if (Index >= 0) and (Index <= FMarkUpList.Count-1) then
335 Result := TSsMarkUp(FMarkUpList[Index]).MarkUpType
337 raise ESsParserError.Create('
\83C
\83\93\83f
\83b
\83N
\83X
\82ª
\94Í
\88Í
\82ð
\82±
\82¦
\82Ä
\82¢
\82Ü
\82·');
340 function TSsParser.GetParam(Tag: String;
341 const Index: integer): String;
342 var ParamCount: integer;
343 First, Param: String;
344 Escape, Inside: boolean;
346 if Index <= 0 then Exit;
351 First := ChopFirstChar(Tag);
354 if First = '\' then Param := Param + '\'
355 else if First = ']' then Param := Param + ']'
356 else Param := Param + '\' + First;
358 end else if First = '\' then
360 else if First = ']' then
364 Param := Param + First;
366 end else if First = '[' then begin
372 until (First = '') or ((ParamCount = Index) and not Inside);
373 if ((ParamCount = Index) and not Inside) then
379 function TSsParser.GetStr(Index: integer): String;
381 if (Index >= 0) and (Index <= FMarkUpList.Count-1) then
382 Result := TSsMarkUp(FMarkUpList[Index]).Str
387 function TSsParser.Match(Str, Pattern: String): integer;
389 if (Length(Str) = 0) or (Length(Pattern) = 0) then
392 Result := MatchP(@Str[1], @Pattern[1]);
395 function TSsParser.MatchP(PStr, PPattern: PChar): integer;
396 var Matched, F, Escape: boolean;
400 while Matched and (PPattern^ <> #0) do begin
401 if PPattern^ = '%' then
420 if PStr^ in ['0' .. '9'] then
430 if PStr^ in ['0' .. '9'] then
432 while PStr^ in ['0' .. '9'] do
441 'b': //'[]'
\82Å
\88Í
\82Ü
\82ê
\82½
\95¶
\8e\9a\97ñ
\81B
449 Escape := false; //
\83G
\83X
\83P
\81[
\83v
\92\86
450 Inc(PStr); // '['
\82Ì
\95ª
451 Inc(Result); // '['
\82Ì
\95ª
458 if PStr^ = '\' then Escape := true;
459 if PStr^ = ']' then F := true;
461 if PStr^ in LeadBytes then
470 until (PStr^ = #0) or F;
478 if not (PStr^ in LeadBytes) then
483 end else Matched := false;
487 if (PStr^ in LeadBytes) then
492 end else Matched := false;
495 if (PStr^ in LeadBytes) then
518 if PStr^ <> PPattern^ then
528 if not Matched then Result := 0;
531 procedure TSsParser.SetExtra(Index: integer; const Value: String);
533 if (Index >= 0) and (Index <= FMarkUpList.Count-1) then
534 TSsMarkUp(FMarkUpList[Index]).Extra := Value
536 raise ESsParserError.Create('
\83C
\83\93\83f
\83b
\83N
\83X
\82ª
\94Í
\88Í
\82ð
\82±
\82¦
\82Ä
\82¢
\82Ü
\82·');
539 procedure TSsParser.SetInputString(const Value: String);
541 FInputString := Value;
545 procedure TSsParser.SetMetaPattern(const Value: TStrings);
547 FMetaPattern.Assign(Value);
550 procedure TSsParser.SetOnParse(const Value: TSsParseEvent);
555 procedure TSsParser.SetTagPattern(const Value: TStrings);
557 FTagPattern.Assign(Value);
562 constructor TSsMarkUp.Create(MarkUpType: TSsMarkUpType; Str: String; Extra: String = '');
564 FMarkUpType := MarkUpType;
569 procedure TSsMarkUp.SetExtra(const Value: String);