4 * License : The MIT License
5 * Copyright(c) 2009 olyutorskii
8 package jp.osdn.jindolf.parser;
10 import java.util.regex.Pattern;
11 import jp.sourceforge.jindolf.corelib.EventFamily;
12 import jp.sourceforge.jindolf.corelib.GameRole;
13 import jp.sourceforge.jindolf.corelib.SysEventType;
14 import jp.sourceforge.jindolf.corelib.Team;
17 * 人狼BBSシステムが出力する各種イベント表記のパースを行うパーサ。
18 * パース進行に従い{@link SysEventHandler}の各種メソッドが呼び出される。
21 "checkstyle:declarationdistance",
22 "checkstyle:declarationorder",
23 "PMD.FieldDeclarationsShouldBeAtStartOfClass",
24 "PMD.PrematureDeclaration"
26 public class SysEventParser extends AbstractParser{
28 private static final String AVATAR_REGEX =
29 "[^<、" + SPCHAR + "]+\u0020[^<、。" + SPCHAR + "]+";
31 private static final Pattern C_DIV_PATTERN =
32 compile(SP_I+ "</div>" +SP_I);
33 private static final Pattern AVATAR_PATTERN =
34 compile(AVATAR_REGEX);
37 private SysEventHandler sysEventHandler;
39 private int pushedRegionStart = -1;
40 private int pushedRegionEnd = -1;
42 private final SeqRange rangepool_1 = new SeqRange();
43 private final SeqRange rangepool_2 = new SeqRange();
44 private final SeqRange rangepool_3 = new SeqRange();
50 public SysEventParser(ChainedParser parent){
56 * {@link SysEventHandler}ハンドラを登録する。
57 * @param sysEventHandler ハンドラ
59 public void setSysEventHandler(SysEventHandler sysEventHandler){
60 this.sysEventHandler = sysEventHandler;
65 * Announceメッセージをパースする。
66 * @throws HtmlParseException パースエラー
68 public void parseAnnounce() throws HtmlParseException{
69 setContextErrorMessage("Unknown Announce message");
71 this.sysEventHandler.startSysEvent(EventFamily.ANNOUNCE);
73 int regionStart = regionStart();
74 int regionEnd = regionEnd();
90 throw buildParseException();
93 getMatcher().region(regionStart, regionEnd);
96 lookingAtAffirm(C_DIV_PATTERN);
99 this.sysEventHandler.endSysEvent();
104 private static final Pattern STARTENTRY_PATTERN =
106 "昼間は人間のふりをして、夜に正体を現すという人狼。<br />"
108 +"この村に紛れ込んでいるという噂が広がった。<br /><br />"
110 +"村はずれの宿に集められることになった。"
112 private static final Pattern STARTMIRROR_PATTERN =
114 "さあ、自らの姿を鏡に映してみよう。<br />"
116 +"それとも血に飢えた人狼か。<br /><br />"
117 +"例え人狼でも、多人数で立ち向かえば怖くはない。<br />"
118 +"問題は、だれが人狼なのかという事だ。<br />"
119 +"占い師の能力を持つ人間ならば、それを見破れるだろう。"
121 private static final Pattern STARTASSAULT_PATTERN =
123 "ついに犠牲者が出た。人狼はこの村人達のなかにいる。<br />"
124 +"しかし、それを見分ける手段はない。<br /><br />"
125 +"村人達は、疑わしい者を排除するため、"
127 +"無実の犠牲者が出るのもやむをえない。"
128 +"村が全滅するよりは……。<br /><br />"
129 +"最後まで残るのは村人か、それとも人狼か。"
131 private static final Pattern NOMURDER_PATTERN =
133 "今日は犠牲者がいないようだ。人狼は襲撃に失敗したのだろうか。");
134 private static final Pattern WINVILLAGE_PATTERN =
136 "全ての人狼を退治した……。人狼に怯える日々は去ったのだ!"
138 private static final Pattern WINWOLF_PATTERN =
140 "もう人狼に抵抗できるほど村人は残っていない……。<br />"
142 +"別の獲物を求めてこの村を去っていった。"
144 private static final Pattern WINHAMSTER_PATTERN =
146 "全ては終わったかのように見えた。<br />"
148 private static final Pattern PANIC_PATTERN =
150 private static final Pattern SHORTMEMBER_PATTERN =
155 private static final Object[][] SIMPLE_REGEX_TO_TYPE = {
156 { STARTENTRY_PATTERN, SysEventType.STARTENTRY },
157 { STARTMIRROR_PATTERN, SysEventType.STARTMIRROR },
158 { STARTASSAULT_PATTERN, SysEventType.STARTASSAULT },
159 { NOMURDER_PATTERN, SysEventType.NOMURDER },
160 { WINVILLAGE_PATTERN, SysEventType.WINVILLAGE },
161 { WINWOLF_PATTERN, SysEventType.WINWOLF },
162 { WINHAMSTER_PATTERN, SysEventType.WINHAMSTER },
163 { PANIC_PATTERN, SysEventType.PANIC },
164 { SHORTMEMBER_PATTERN, SysEventType.SHORTMEMBER },
168 * 文字列が固定されたシンプルなAnnounceメッセージのパースを試みる。
170 * @throws HtmlParseException パースエラー
172 private boolean probeSimpleAnnounce() throws HtmlParseException{
177 SysEventType matchedType = null;
179 for(Object[] pair : SIMPLE_REGEX_TO_TYPE){
180 Pattern pattern = (Pattern) pair[0];
182 if(lookingAtProbe(pattern)){
184 matchedType = (SysEventType) pair[1];
189 if(matchedType == null){
194 this.sysEventHandler.sysEventType(matchedType);
201 private static final Pattern OPENROLE_HEAD_PATTERN =
202 compile("どうやらこの中には、");
203 private static final Pattern OPENROLE_NUM_PATTERN =
204 compile("が([0-9]+)名(?:、)?");
205 private static final Pattern OPENROLE_TAIL_PATTERN =
209 * OPENROLEメッセージのパースを試みる。
211 * @throws HtmlParseException パースエラー
213 private boolean probeOpenRole() throws HtmlParseException{
218 if( ! lookingAtProbe(OPENROLE_HEAD_PATTERN) ){
224 this.sysEventHandler.sysEventType(SysEventType.OPENROLE);
227 GameRole role = lookingAtRole();
229 if( lookingAtProbe(OPENROLE_TAIL_PATTERN) ){
238 if( ! lookingAtProbe(OPENROLE_NUM_PATTERN) ){
242 int num = parseGroupedInt(1);
245 this.sysEventHandler.sysEventOpenRole(role, num);
253 private static final Pattern SURVIVOR_HEAD_PATTERN =
255 private static final Pattern SURVIVOR_PATTERN =
257 "(" + AVATAR_REGEX + ")"
262 +"\u0020の\u0020([0-9]+)\u0020名。"
267 * SURVIVORメッセージのパースを試みる。
269 * @throws HtmlParseException パースエラー
271 private boolean probeSurvivor() throws HtmlParseException{
272 SeqRange avatarRange = this.rangepool_1;
278 if( ! lookingAtProbe(SURVIVOR_HEAD_PATTERN) ){
284 this.sysEventHandler.sysEventType(SysEventType.SURVIVOR);
288 if( ! lookingAtProbe(SURVIVOR_PATTERN) ){
292 avatarRange.setLastMatchedGroupRange(getMatcher(), 1);
294 .sysEventSurvivor(getContent(), avatarRange);
296 if(isGroupMatched(2)){
297 int num = parseGroupedInt(2);
299 if(num != avatarNum){
300 throw new HtmlParseException(regionStart());
312 private static final Pattern MURDERED_HEAD_PATTERN =
314 private static final Pattern MURDERED_SW_PATTERN =
319 +"\u0020が無残な姿で発見された。"
320 +"(?:<br />)?" // E国対策
325 * MURDEREDメッセージのパースを試みる。
327 * @throws HtmlParseException パースエラー
329 private boolean probeMurdered() throws HtmlParseException{
330 SeqRange avatarRange = this.rangepool_1;
331 SeqRange avatarRange2 = this.rangepool_2;
332 avatarRange .setInvalid();
333 avatarRange2.setInvalid();
339 if( ! lookingAtProbe(MURDERED_HEAD_PATTERN)){
345 this.sysEventHandler.sysEventType(SysEventType.MURDERED);
348 if( ! lookingAtProbe(AVATAR_PATTERN)){
352 if( ! avatarRange.isValid() ){
353 avatarRange.setLastMatchedRange(getMatcher());
354 }else if( ! avatarRange2.isValid() ){
355 avatarRange2.setLastMatchedRange(getMatcher());
358 throw buildParseException();
362 if( ! lookingAtProbe(MURDERED_SW_PATTERN)){
366 if(isGroupMatched(1)){
369 }else if(isGroupMatched(2)){
374 throw buildParseException();
379 .sysEventMurdered(getContent(), avatarRange);
380 if(avatarRange2.isValid()){
382 .sysEventMurdered(getContent(), avatarRange2);
390 private static final Pattern ONSTAGE_NO_PATTERN =
391 compile("([0-9]+)人目、");
392 private static final Pattern ONSTAGE_DOT_PATTERN =
395 +"(?:" + AVATAR_REGEX + ")"
396 +"|)" // F1556プロローグ対策
400 * ONSTAGEメッセージのパースを試みる。
402 * @throws HtmlParseException パースエラー
404 private boolean probeOnStage() throws HtmlParseException{
405 SeqRange avatarRange = this.rangepool_1;
411 if( ! lookingAtProbe(ONSTAGE_NO_PATTERN) ){
415 int entryNo = parseGroupedInt(1);
418 this.sysEventHandler.sysEventType(SysEventType.ONSTAGE);
420 if( ! lookingAtProbe(ONSTAGE_DOT_PATTERN) ){
424 avatarRange.setLastMatchedGroupRange(getMatcher(), 1);
428 .sysEventOnStage(getContent(), entryNo, avatarRange);
435 private static final Pattern SUDDENDEATH_PATTERN =
438 +"(?:" + AVATAR_REGEX + ")"
444 * SUDDENDEATHメッセージのパースを試みる。
446 * @throws HtmlParseException パースエラー
448 private boolean probeSuddenDeath() throws HtmlParseException{
449 SeqRange avatarRange = this.rangepool_1;
455 if( ! lookingAtProbe(SUDDENDEATH_PATTERN)){
459 avatarRange.setLastMatchedGroupRange(getMatcher(), 1);
462 this.sysEventHandler.sysEventType(SysEventType.SUDDENDEATH);
464 .sysEventSuddenDeath(getContent(), avatarRange);
471 private static final Pattern COUNTING_PATTERN =
475 +"(" + AVATAR_REGEX + ")"
476 +"\u0020は村人達の手により処刑された。"
478 +"(" + AVATAR_REGEX + ")"
480 +"(" + AVATAR_REGEX + ")"
487 * COUNTINGメッセージのパースを試みる。
489 * @throws HtmlParseException パースエラー
491 private boolean probeCounting() throws HtmlParseException{
492 SeqRange voteByRange = this.rangepool_1;
493 SeqRange voteToRange = this.rangepool_2;
499 boolean hasVote = false;
501 if( ! lookingAtProbe(COUNTING_PATTERN) ){
504 if(isGroupMatched(1)){
505 voteByRange.setInvalid();
506 voteToRange.setLastMatchedGroupRange(getMatcher(), 1);
509 .sysEventCounting(getContent(),
513 }else if(isGroupMatched(2)){
516 this.sysEventHandler.sysEventType(SysEventType.COUNTING);
518 voteByRange.setLastMatchedGroupRange(getMatcher(), 2);
519 voteToRange.setLastMatchedGroupRange(getMatcher(), 3);
522 .sysEventCounting(getContent(),
527 throw buildParseException();
541 private static final Pattern COUNTING2_PATTERN =
543 "(" + AVATAR_REGEX + ")"
545 +"(" + AVATAR_REGEX + ")"
551 * COUNTING2メッセージのパースを試みる。
553 * @throws HtmlParseException パースエラー
555 private boolean probeCounting2() throws HtmlParseException{
556 SeqRange voteByRange = this.rangepool_1;
557 SeqRange voteToRange = this.rangepool_2;
563 boolean hasVote = false;
565 if( ! lookingAtProbe(COUNTING2_PATTERN) ){
570 this.sysEventHandler.sysEventType(SysEventType.COUNTING2);
572 voteByRange.setLastMatchedGroupRange(getMatcher(), 1);
573 voteToRange.setLastMatchedGroupRange(getMatcher(), 2);
576 .sysEventCounting2(getContent(),
591 private static final Pattern PLAYERID_PATTERN =
593 "\u0020\uff08" // 全角開き括弧
594 +"(?:<a\u0020href=\"([^\"]*)\">)?"
599 private static final Pattern LIVEORDIE_PATTERN =
603 private static final Pattern PLAYER_DELIM_PATTERN =
610 * PLAYERLISTメッセージのパースを試みる。
612 * @throws HtmlParseException パースエラー
614 private boolean probePlayerList() throws HtmlParseException{
615 SeqRange avatarRange = this.rangepool_1;
616 SeqRange anchorRange = this.rangepool_2;
617 SeqRange accountRange = this.rangepool_3;
623 boolean hasPlayerList = false;
626 if( ! lookingAtProbe(AVATAR_PATTERN)){
629 avatarRange.setLastMatchedRange(getMatcher());
632 if( ! lookingAtProbe(PLAYERID_PATTERN)){
636 if(isGroupMatched(1)){
637 anchorRange.setLastMatchedGroupRange(getMatcher(), 1);
639 anchorRange.setInvalid();
641 accountRange.setLastMatchedGroupRange(getMatcher(), 2);
644 boolean isLiving = false;
645 if( ! lookingAtProbe(LIVEORDIE_PATTERN)){
649 if(isGroupMatched(1)){
651 }else if(isGroupMatched(2)){
656 GameRole role = lookingAtRole();
663 if( ! lookingAtProbe(PLAYER_DELIM_PATTERN)){
669 if( ! hasPlayerList ){
670 hasPlayerList = true;
671 this.sysEventHandler.sysEventType(SysEventType.PLAYERLIST);
675 .sysEventPlayerList(getContent(),
683 if( ! hasPlayerList ){
693 private static final Pattern EXECUTION_PATTERN =
696 + "(" + AVATAR_REGEX + ")、([0-9]+)票。(?:<br />)?"
698 +"<br />(" + AVATAR_REGEX + ")\u0020は"
704 * EXECUTIONメッセージのパースを試みる。
706 * @throws HtmlParseException パースエラー
708 private boolean probeExecution() throws HtmlParseException{
709 SeqRange avatarRange = this.rangepool_1;
715 boolean hasExecution = false;
718 if( ! lookingAtProbe(EXECUTION_PATTERN)){
722 if( ! hasExecution ){
724 this.sysEventHandler.sysEventType(SysEventType.EXECUTION);
727 if(isGroupMatched(1)){
728 avatarRange.setLastMatchedGroupRange(getMatcher(), 1);
729 int votes = parseGroupedInt(2);
732 .sysEventExecution(getContent(),
735 }else if(isGroupMatched(3)){
736 avatarRange.setLastMatchedGroupRange(getMatcher(), 3);
739 .sysEventExecution(getContent(),
745 if( ! hasExecution ){
755 private static final Pattern VANISH_PATTERN =
758 +"(" + AVATAR_REGEX + ")"
764 * VANISHメッセージのパースを試みる。
766 * @throws HtmlParseException パースエラー
768 private boolean probeVanish() throws HtmlParseException{
769 SeqRange avatarRange = this.rangepool_1;
775 boolean hasVanish = false;
778 if( ! lookingAtProbe(VANISH_PATTERN)){
784 this.sysEventHandler.sysEventType(SysEventType.VANISH);
786 avatarRange.setLastMatchedGroupRange(getMatcher(), 1);
791 .sysEventVanish(getContent(), avatarRange);
804 private static final Pattern CHECKOUT_PATTERN =
807 +"(" + AVATAR_REGEX + ")"
813 * CHECKOUTメッセージのパースを試みる。
815 * @throws HtmlParseException パースエラー
817 private boolean probeCheckout() throws HtmlParseException{
818 SeqRange avatarRange = this.rangepool_1;
824 boolean hasCheckout = false;
827 if( ! lookingAtProbe(CHECKOUT_PATTERN)){
833 this.sysEventHandler.sysEventType(SysEventType.CHECKOUT);
835 avatarRange.setLastMatchedGroupRange(getMatcher(), 1);
840 .sysEventCheckout(getContent(), avatarRange);
855 * @throws HtmlParseException パースエラー
857 public void parseOrder() throws HtmlParseException{
858 setContextErrorMessage("Unknown Order message");
860 this.sysEventHandler.startSysEvent(EventFamily.ORDER);
862 int regionStart = regionStart();
863 int regionEnd = regionEnd();
869 || probeStayEpilogue()
873 throw buildParseException();
876 getMatcher().region(regionStart, regionEnd);
879 lookingAtAffirm(C_DIV_PATTERN);
882 this.sysEventHandler.endSysEvent();
887 private static final Pattern ASKENTRY_PATTERN =
889 "演じたいキャラクターを選び、発言してください。<br />"
890 +"([0-2][0-9]):([0-5][0-9])\u0020に"
891 +"([0-9]+)名以上がエントリーしていれば進行します。<br />"
892 +"最大([0-9]+)名まで参加可能です。<br /><br />"
893 +"※[\u0020]?エントリーは取り消せません。"
894 +"ルールをよく理解した上でご参加下さい。<br />"
895 +"(?:※始めての方は、村人希望での参加となります。<br />)?"
896 +"(?:※希望能力についての発言は控えてください。<br />)?"
900 * ASKENTRYメッセージのパースを試みる。
902 * @throws HtmlParseException パースエラー
904 private boolean probeAskEntry() throws HtmlParseException{
909 if( ! lookingAtProbe(ASKENTRY_PATTERN)){
914 int hour = parseGroupedInt(1);
915 int minute = parseGroupedInt(2);
916 int minLimit = parseGroupedInt(3);
917 int maxLimit = parseGroupedInt(4);
921 this.sysEventHandler.sysEventType(SysEventType.ASKENTRY);
923 .sysEventAskEntry(hour, minute, minLimit, maxLimit);
930 private static final Pattern ASKCOMMIT_PATTERN =
933 +"([0-2][0-9]):([0-5][0-9])\u0020までに、"
934 +"誰を処刑するべきかの投票先を決定して下さい。<br />"
936 +"同数だった場合はランダムで決定されます。<br /><br />"
939 +"([0-2][0-9]):([0-5][0-9])\u0020までに"
944 * ASKCOMMITメッセージのパースを試みる。
946 * @throws HtmlParseException パースエラー
948 private boolean probeAskCommit() throws HtmlParseException{
953 if( ! lookingAtProbe(ASKCOMMIT_PATTERN)){
959 if(isGroupMatched(1)){
965 int hh1 = parseGroupedInt(1);
966 int mm1 = parseGroupedInt(2);
967 int hh2 = parseGroupedInt(3);
968 int mm2 = parseGroupedInt(4);
972 if( ! is1stDay && (hh1 != hh2 || mm1 != mm2) ){
973 throw new HtmlParseException(regionStart());
976 this.sysEventHandler.sysEventType(SysEventType.ASKCOMMIT);
977 this.sysEventHandler.sysEventAskCommit(hh2, mm2);
984 private static final Pattern NOCOMMENT_HEAD_PATTERN =
985 compile("本日まだ発言していない者は、");
986 private static final Pattern NOCOMMENT_AVATAR_PATTERN =
989 +"(" + AVATAR_REGEX + ")、"
991 +"以上\u0020([0-9]+)\u0020名。"
996 * NOCOMMENTメッセージのパースを試みる。
998 * @throws HtmlParseException パースエラー
1000 private boolean probeNoComment() throws HtmlParseException{
1001 SeqRange avatarRange = this.rangepool_1;
1007 if( ! lookingAtProbe(NOCOMMENT_HEAD_PATTERN)){
1013 this.sysEventHandler.sysEventType(SysEventType.NOCOMMENT);
1017 if( ! lookingAtProbe(NOCOMMENT_AVATAR_PATTERN)){
1022 if(isGroupMatched(1)){
1023 avatarRange.setLastMatchedGroupRange(getMatcher(), 1);
1024 this.sysEventHandler
1025 .sysEventNoComment(getContent(), avatarRange);
1028 }else if(isGroupMatched(2)){
1029 int num = parseGroupedInt(2);
1031 if(num != avatarNum){
1032 throw new HtmlParseException(regionStart());
1043 private static final Pattern STAYEPILOGUE_PATTERN =
1045 "(?:(村人)|(人狼)|(ハムスター))側の勝利です!<br />"
1046 +"全てのログとユーザー名を公開します。"
1047 +"([0-2][0-9]):([0-5][0-9])\u0020まで"
1049 +"今回の感想などをどうぞ。<br />"
1053 * STAYEPILOGUEメッセージのパースを試みる。
1054 * @return マッチしたらtrue
1055 * @throws HtmlParseException パースエラー
1057 private boolean probeStayEpilogue() throws HtmlParseException{
1062 if( ! lookingAtProbe(STAYEPILOGUE_PATTERN)){
1068 if(isGroupMatched(1)){
1069 winner = Team.VILLAGE;
1070 }else if(isGroupMatched(2)){
1072 }else if(isGroupMatched(3)){
1073 winner = Team.HAMSTER;
1076 int hour = parseGroupedInt(4);
1077 int minute = parseGroupedInt(5);
1081 this.sysEventHandler.sysEventType(SysEventType.STAYEPILOGUE);
1082 this.sysEventHandler.sysEventStayEpilogue(winner, hour, minute);
1089 private static final Pattern GAMEOVER_PATTERN =
1090 compile("終了しました。" + "<br />");
1093 * GAMEOVERメッセージのパースを試みる。
1094 * @return マッチしたらtrue
1095 * @throws HtmlParseException パースエラー
1097 private boolean probeGameOver() throws HtmlParseException{
1102 if( ! lookingAtProbe(GAMEOVER_PATTERN)){
1109 this.sysEventHandler.sysEventType(SysEventType.GAMEOVER);
1118 * @throws HtmlParseException パースエラー
1120 public void parseExtra() throws HtmlParseException{
1121 setContextErrorMessage("Unknown Extra message");
1123 this.sysEventHandler.startSysEvent(EventFamily.EXTRA);
1125 int regionStart = regionStart();
1126 int regionEnd = regionEnd();
1131 || probeCounting2();
1133 throw buildParseException();
1136 getMatcher().region(regionStart, regionEnd);
1139 lookingAtAffirm(C_DIV_PATTERN);
1142 this.sysEventHandler.endSysEvent();
1147 private static final Pattern JUDGE_DELIM_PATTERN =
1148 compile("\u0020は、");
1149 private static final Pattern JUDGE_TAIL_PATTERN =
1150 compile("\u0020を占った。");
1153 * JUDGEメッセージのパースを試みる。
1154 * @return マッチしたらtrue
1155 * @throws HtmlParseException パースエラー
1157 private boolean probeJudge() throws HtmlParseException{
1158 SeqRange judgeByRange = this.rangepool_1;
1159 SeqRange judgeToRange = this.rangepool_2;
1165 if( ! lookingAtProbe(AVATAR_PATTERN)){
1169 judgeByRange.setLastMatchedRange(getMatcher());
1172 if( ! lookingAtProbe(JUDGE_DELIM_PATTERN)){
1178 if( ! lookingAtProbe(AVATAR_PATTERN)){
1182 judgeToRange.setLastMatchedRange(getMatcher());
1185 if( ! lookingAtProbe(JUDGE_TAIL_PATTERN)){
1191 this.sysEventHandler.sysEventType(SysEventType.JUDGE);
1192 this.sysEventHandler
1193 .sysEventJudge(getContent(),
1201 private static final Pattern GUARD_DELIM_PATTERN =
1202 compile("\u0020は、");
1203 private static final Pattern GUARD_TAIL_PATTERN =
1204 compile("\u0020を守っている。");
1207 * GUARDメッセージのパースを試みる。
1208 * @return マッチしたらtrue
1209 * @throws HtmlParseException パースエラー
1211 private boolean probeGuard() throws HtmlParseException{
1212 SeqRange guardByRange = this.rangepool_1;
1213 SeqRange guardToRange = this.rangepool_2;
1219 if( ! lookingAtProbe(AVATAR_PATTERN)){
1223 guardByRange.setLastMatchedRange(getMatcher());
1226 if( ! lookingAtProbe(GUARD_DELIM_PATTERN)){
1232 if( ! lookingAtProbe(AVATAR_PATTERN)){
1236 guardToRange.setLastMatchedRange(getMatcher());
1239 if( ! lookingAtProbe(GUARD_TAIL_PATTERN)){
1245 this.sysEventHandler.sysEventType(SysEventType.GUARD);
1246 this.sysEventHandler.sysEventGuard(getContent(),
1254 private static final Pattern CONTENT_PATTERN =
1261 +"<a\u0020href=\"([^\"]*)\">([^<>]*)</a>"
1266 * システムイベントの内容文字列をパースする。
1267 * @throws HtmlParseException パースエラー
1269 private void parseContent() throws HtmlParseException{
1270 SeqRange anchorRange = this.rangepool_1;
1271 SeqRange contentRange = this.rangepool_2;
1276 if( ! lookingAtProbe(CONTENT_PATTERN) ){
1280 if(isGroupMatched(1)){
1281 contentRange.setLastMatchedGroupRange(getMatcher(), 1);
1282 this.sysEventHandler
1283 .sysEventContent(getContent(), contentRange);
1284 }else if(isGroupMatched(2)){
1285 this.sysEventHandler.sysEventContentBreak();
1286 }else if(isGroupMatched(3)){
1287 anchorRange.setLastMatchedGroupRange(getMatcher(), 3);
1288 contentRange.setLastMatchedGroupRange(getMatcher(), 4);
1289 this.sysEventHandler
1290 .sysEventContentAnchor(getContent(),
1305 * 待避できるのは1回のみ。複数回スタックはできない。
1308 private void pushRegion(){
1309 this.pushedRegionStart = regionStart();
1310 this.pushedRegionEnd = regionEnd();
1315 * 一時的に待避した検索領域を復活させる。
1316 * @throws IllegalStateException まだ何も待避していない。
1317 * @see #pushRegion()
1319 private void popRegion() throws IllegalStateException{
1320 if(this.pushedRegionStart < 0 || this.pushedRegionEnd < 0){
1321 throw new IllegalStateException();
1324 if( this.pushedRegionStart != regionStart()
1325 || this.pushedRegionEnd != regionEnd() ){
1326 getMatcher().region(this.pushedRegionStart, this.pushedRegionEnd);
1329 this.pushedRegionStart = -1;
1330 this.pushedRegionEnd = -1;