OSDN Git Service

初コミット
[fooeditengine/FooEditEngine.git] / Common / Test / XmlHilighter.cs
1 /*\r
2  * Copyright (C) 2013 FooProject\r
3  * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by\r
4  * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
5 \r
6  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
7  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
8 \r
9 You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
10  */\r
11 using System;\r
12 using System.Text;\r
13 using FooEditEngine;\r
14 \r
15 namespace Test\r
16 {\r
17     enum TextParserMode\r
18     {\r
19         Literal,\r
20         ScriptPart,\r
21         MultiLineComment,\r
22         TextPart,\r
23     }\r
24     class XmlHilighter : IHilighter\r
25     {\r
26         private TextParserMode mode;\r
27         private StringBuilder word;\r
28         private TokenType KeyWordType;\r
29 \r
30         public XmlHilighter()\r
31         {\r
32             this.word = new StringBuilder();\r
33             this.Reset();\r
34         }\r
35 \r
36         #region IHilighter メンバー\r
37 \r
38         public void Reset()\r
39         {\r
40             this.mode = TextParserMode.TextPart;\r
41             this.KeyWordType = TokenType.None;\r
42             this.word.Clear();\r
43         }\r
44 \r
45         public int DoHilight(string text, int length, TokenSpilitHandeler action)\r
46         {\r
47             int encloserLevel = 0;\r
48             int i,wordPos = 0;\r
49             for (i = 0; i < length;)\r
50             {\r
51                 if (IsMatch(text,i,"<!--"))\r
52                 {\r
53                     encloserLevel++;\r
54                     if (TransModeAndAction(TextParserMode.MultiLineComment, action, word, 4, false,ref i, wordPos))\r
55                         break;\r
56                 }\r
57                 else if (IsMatch(text, i, "-->"))\r
58                 {\r
59                     encloserLevel--;\r
60                     if (TransModeAndAction(TextParserMode.TextPart, action, word, 3, true, ref i, wordPos))\r
61                         break;\r
62                 }\r
63                 else if (text[i] == '<' && this.mode != TextParserMode.MultiLineComment)\r
64                 {\r
65                     encloserLevel++;\r
66                     if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 1, true, ref i, wordPos))\r
67                         break;\r
68                     this.KeyWordType = TokenType.Keyword1;\r
69                 }\r
70                 else if (text[i] == '>' && this.mode == TextParserMode.ScriptPart)\r
71                 {\r
72                     encloserLevel--;\r
73                     if (TransModeAndAction(TextParserMode.TextPart, action, word, 1, false, ref i, wordPos))\r
74                         break;\r
75                 }\r
76                 else if (IsMatch(text, i, "![CDATA[") && this.mode == TextParserMode.ScriptPart)\r
77                 {\r
78                     encloserLevel++;\r
79                     if (TransModeAndAction(TextParserMode.Literal, action, word, 8, false, ref i, wordPos))\r
80                         break;\r
81                 }\r
82                 else if ((text[i] == '\"' || text[i] == '\'') && this.mode == TextParserMode.ScriptPart)\r
83                 {\r
84                     encloserLevel++;\r
85                     if (TransModeAndAction(TextParserMode.Literal, action, word, 1, false, ref i, wordPos))\r
86                         break;\r
87                 }\r
88                 else if ((text[i] == '\"' || text[i] == '\'' ) && this.mode == TextParserMode.Literal)\r
89                 {\r
90                     encloserLevel--;\r
91                     if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 1, true, ref i, wordPos))\r
92                         break;\r
93                 }\r
94                 else if (IsMatch(text, i, "]]") && this.mode == TextParserMode.Literal)\r
95                 {\r
96                     encloserLevel--;\r
97                     if (TransModeAndAction(TextParserMode.ScriptPart, action, word, 2, true, ref i, wordPos))\r
98                         break;\r
99                 }\r
100                 else if (text[i] == ' ')\r
101                 {\r
102                     if (TransModeAndAction(this.mode, action, word, 1, false, ref i, wordPos))\r
103                         break;\r
104                     this.KeyWordType = TokenType.Keyword2;\r
105                 }\r
106                 else if (text[i] == '=')\r
107                 {\r
108                     if (TransModeAndAction(this.mode, action, word, 1, false, ref i, wordPos))\r
109                         break;\r
110                     this.KeyWordType = TokenType.None;\r
111                 }\r
112                 else\r
113                 {\r
114                     if (word.Length == 0)\r
115                         wordPos = i;\r
116                     word.Append(text[i]);\r
117                     i++;\r
118                     continue;\r
119                 }\r
120             }\r
121 \r
122             if (word.Length > 0)\r
123             {\r
124                 action(new TokenSpilitEventArgs(wordPos,word.Length, GetMode(this.mode,KeyWordType)));\r
125                 word.Clear();\r
126             }\r
127 \r
128             return encloserLevel;\r
129         }\r
130 \r
131         #endregion\r
132 \r
133         /// <summary>\r
134         /// 文字列が一致するかどうか確かめる\r
135         /// </summary>\r
136         /// <param name="s">検査される文字列</param>\r
137         /// <param name="index">検査を開始するインデックス</param>\r
138         /// <param name="pattern">検査対象の文字列</param>\r
139         /// <returns></returns>\r
140         private bool IsMatch(string s, int index, string pattern)\r
141         {\r
142             if (index  + pattern.Length >= s.Length)\r
143                 return false;\r
144             bool result = false;\r
145             for (int i = index, j = 0; i < index + pattern.Length; i++, j++)\r
146             {\r
147                 if ((j == 0 || j > 0 && result) && s[i] == pattern[j])\r
148                     result = true;\r
149                 else\r
150                     result = false;\r
151             }\r
152 \r
153             return result;\r
154         }\r
155 \r
156         private bool TransModeAndAction(TextParserMode toMode, TokenSpilitHandeler action, StringBuilder word, int tokenLength, bool TranAfterAction, ref int index, int wordPos)\r
157         {\r
158             TokenSpilitEventArgs e = new TokenSpilitEventArgs();\r
159 \r
160             if (word.Length > 0)\r
161             {\r
162                 e.index = wordPos;\r
163                 e.length = word.Length;\r
164                 e.type = GetMode(this.mode, this.KeyWordType);\r
165                 action(e);\r
166                 word.Clear();\r
167                 if (e.breaked)\r
168                     return true;\r
169             }\r
170 \r
171             if (TranAfterAction == false)\r
172                 this.mode = toMode;\r
173 \r
174             e.index = index;\r
175             e.length = tokenLength;\r
176             e.type = GetMode(this.mode, TokenType.None);\r
177             action(e);\r
178             if (e.breaked)\r
179                 return true;\r
180 \r
181             if (TranAfterAction)\r
182                 this.mode = toMode;\r
183 \r
184             index += tokenLength;\r
185 \r
186             return false;\r
187         }\r
188         \r
189         private TokenType GetMode(TextParserMode mode,TokenType isKeyword)\r
190         {\r
191             switch (mode)\r
192             {\r
193                 case TextParserMode.Literal:\r
194                     return TokenType.Literal;\r
195                 case TextParserMode.ScriptPart:\r
196                     return isKeyword;\r
197                 case TextParserMode.MultiLineComment:\r
198                     return TokenType.Comment;\r
199                 default:\r
200                     return TokenType.None;\r
201             }\r
202         }\r
203     }\r
204 }\r