OSDN Git Service

#27621 言語間リンク取得時に<includeonly>, <noinclude>を考慮するよう修正,
[wptscs/wpts.git] / Wptscs / Parsers / MediaWikiVariableParser.cs
1 // ================================================================================================
2 // <summary>
3 //      MediaWikiの変数を解析するパーサークラスソース</summary>
4 //
5 // <copyright file="MediaWikiVariableParser.cs" company="honeplusのメモ帳">
6 //      Copyright (C) 2012 Honeplus. All rights reserved.</copyright>
7 // <author>
8 //      Honeplus</author>
9 // ================================================================================================
10
11 namespace Honememo.Wptscs.Parsers
12 {
13     using System;
14     using System.Collections.Generic;
15     using System.Text;
16     using Honememo.Parsers;
17     using Honememo.Utilities;
18
19     /// <summary>
20     /// MediaWikiの変数を解析するパーサークラスです。
21     /// </summary>
22     public class MediaWikiVariableParser : AbstractParser
23     {
24         #region private変数
25
26         /// <summary>
27         /// このパーサーが参照する<see cref="MediaWikiParser"/>。
28         /// </summary>
29         private MediaWikiParser parser;
30
31         #endregion
32         
33         #region コンストラクタ
34
35         /// <summary>
36         /// 指定された<see cref="MediaWikiParser"/>を元に変数を解析するためのパーサーを作成する。
37         /// </summary>
38         /// <param name="parser">このパーサーが参照する<see cref="MediaWikiParser"/>。</param>
39         public MediaWikiVariableParser(MediaWikiParser parser)
40         {
41             this.parser = parser;
42         }
43
44         #endregion
45
46         #region インタフェース実装メソッド
47
48         /// <summary>
49         /// 渡されたテキストをMediaWikiの変数として解析する。
50         /// </summary>
51         /// <param name="s">解析対象の文字列。</param>
52         /// <param name="result">解析した変数。</param>
53         /// <returns>解析に成功した場合<c>true</c>。</returns>
54         public override bool TryParse(string s, out IElement result)
55         {
56             // 出力値初期化
57             result = null;
58
59             // 開始条件 {{{ のチェック
60             if (s == null || !s.StartsWith(MediaWikiVariable.DelimiterStart))
61             {
62                 return false;
63             }
64
65             // ブロック終了まで取得
66             StringBuilder variable = new StringBuilder();
67             IElement value = null;
68             int lastIndex = -1;
69             for (int i = MediaWikiVariable.DelimiterStart.Length; i < s.Length; i++)
70             {
71                 // 終了条件 }}} のチェック
72                 if (StringUtils.StartsWith(s, MediaWikiVariable.DelimiterEnd, i))
73                 {
74                     lastIndex = i + MediaWikiVariable.DelimiterEnd.Length - 1;
75                     break;
76                 }
77
78                 // {{{変数名|デフォルト値}}} といったフォーマットのため、| の前後で処理を変更
79                 if (s[i] == '|')
80                 {
81                     // | の後(変数のデフォルト値など)は何でもありえるので親のパーサーで再帰的に解析
82                     if (!this.parser.TryParseToDelimiter(StringUtils.Substring(s, i + 1), out value, MediaWikiVariable.DelimiterEnd))
83                     {
84                         // 平文でも解析するメソッドのため、基本的に失敗することは無い
85                         // 万が一の場合は解析失敗とする
86                         break;
87                     }
88
89                     i += value.ToString().Length;
90                 }
91                 else
92                 {
93                     // | の前(変数名の部分)のとき、変数・コメントの再帰チェック
94                     IElement element;
95                     if (this.TryParseAt(s, i, out element, this.parser.CommentParser, this.parser.VariableParser))
96                     {
97                         // 変数・コメントなら、解析したブロック単位で変数名に追加
98                         i += element.ToString().Length - 1;
99                         variable.Append(element.ToString());
100                         continue;
101                     }
102
103                     // それ以外の普通の文字なら1文字ずつ変数名に追加
104                     variable.Append(s[i]);
105                 }
106             }
107
108             // 終了条件でループを抜けていない場合、解析失敗
109             if (lastIndex < 0)
110             {
111                 return false;
112             }
113
114             // 変数名・値と、解析した素の文字列を結果に格納して終了
115             result = new MediaWikiVariable(variable.ToString(), value);
116             result.ParsedString = s.Substring(0, lastIndex + 1);
117
118             return true;
119         }
120
121         /// <summary>
122         /// 渡された文字が<see cref="TryParse"/>等の候補となる先頭文字かを判定する。
123         /// </summary>
124         /// <param name="c">解析文字列の先頭文字。</param>
125         /// <returns>候補となる場合<c>true</c>。このクラスでは常に<c>true</c>を返す。</returns>
126         /// <remarks>性能対策などで<see cref="TryParse"/>を呼ぶ前に目処を付けたい場合用。</remarks>
127         public override bool IsPossibleParse(char c)
128         {
129             return MediaWikiVariable.DelimiterStart[0] == c;
130         }
131
132         #endregion
133     }
134 }