More working tests.
[castle.git] / Experiments / AnakiaNet / Anakia / CodeFormat / CodeFormat.cs
blob13fa641c3c16ac38119558ea674da94a7bc8dcd2
1 #region Copyright © 2001-2003 Jean-Claude Manoli [jc@manoli.net]
2 /*
3 * This software is provided 'as-is', without any express or implied warranty.
4 * In no event will the author(s) be held liable for any damages arising from
5 * the use of this software.
6 *
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
11 * 1. The origin of this software must not be misrepresented; you must not
12 * claim that you wrote the original software. If you use this software
13 * in a product, an acknowledgment in the product documentation would be
14 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not
17 * be misrepresented as being the original software.
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21 #endregion
23 using System;
24 using System.IO;
25 using System.Text;
26 using System.Text.RegularExpressions;
28 namespace Manoli.Utils.CSharpFormat
30 /// <summary>
31 /// Provides a base class for formatting most programming languages.
32 /// </summary>
33 public abstract class CodeFormat : SourceFormat
35 /// <summary>
36 /// Must be overridden to provide a list of keywords defined in
37 /// each language.
38 /// </summary>
39 /// <remarks>
40 /// Keywords must be separated with spaces.
41 /// </remarks>
42 protected abstract string Keywords
44 get;
47 /// <summary>
48 /// Can be overridden to provide a list of preprocessors defined in
49 /// each language.
50 /// </summary>
51 /// <remarks>
52 /// Preprocessors must be separated with spaces.
53 /// </remarks>
54 protected virtual string Preprocessors
56 get { return ""; }
59 /// <summary>
60 /// Must be overridden to provide a regular expression string
61 /// to match strings literals.
62 /// </summary>
63 protected abstract string StringRegEx
65 get;
68 /// <summary>
69 /// Must be overridden to provide a regular expression string
70 /// to match comments.
71 /// </summary>
72 protected abstract string CommentRegEx
74 get;
77 /// <summary>
78 /// Determines if the language is case sensitive.
79 /// </summary>
80 /// <value><b>true</b> if the language is case sensitive, <b>false</b>
81 /// otherwise. The default is true.</value>
82 /// <remarks>
83 /// A case-insensitive language formatter must override this
84 /// property to return false.
85 /// </remarks>
86 public virtual bool CaseSensitive
88 get { return true; }
91 /// <summary/>
92 protected CodeFormat()
94 //generate the keyword and preprocessor regexes from the keyword lists
95 Regex r;
96 r = new Regex(@"\w+|-\w+|#\w+|@@\w+|#(?:\\(?:s|w)(?:\*|\+)?\w+)+|@\\w\*+");
97 string regKeyword = r.Replace(Keywords, @"(?<=^|\W)$0(?=\W)");
98 string regPreproc = r.Replace(Preprocessors, @"(?<=^|\s)$0(?=\s|$)");
99 r = new Regex(@" +");
100 regKeyword = r.Replace(regKeyword, @"|");
101 regPreproc = r.Replace(regPreproc, @"|");
103 if (regPreproc.Length == 0)
105 regPreproc = "(?!.*)_{37}(?<!.*)"; //use something quite impossible...
108 //build a master regex with capturing groups
109 StringBuilder regAll = new StringBuilder();
110 regAll.Append("(");
111 regAll.Append(CommentRegEx);
112 regAll.Append(")|(");
113 regAll.Append(StringRegEx);
114 if (regPreproc.Length > 0)
116 regAll.Append(")|(");
117 regAll.Append(regPreproc);
119 regAll.Append(")|(");
120 regAll.Append(regKeyword);
121 regAll.Append(")");
123 RegexOptions caseInsensitive = CaseSensitive ? 0 : RegexOptions.IgnoreCase;
124 CodeRegex = new Regex(regAll.ToString(), RegexOptions.Singleline | caseInsensitive);
127 /// <summary>
128 /// Called to evaluate the HTML fragment corresponding to each
129 /// matching token in the code.
130 /// </summary>
131 /// <param name="match">The <see cref="Match"/> resulting from a
132 /// single regular expression match.</param>
133 /// <returns>A string containing the HTML code fragment.</returns>
134 protected override string MatchEval(Match match)
136 if(match.Groups[1].Success) //comment
138 StringReader reader = new StringReader(match.ToString());
139 string line;
140 StringBuilder sb = new StringBuilder();
141 while ((line = reader.ReadLine()) != null)
143 if(sb.Length > 0)
145 sb.Append("\n");
147 sb.Append("<span class=\"rem\">");
148 sb.Append(line);
149 sb.Append("</span>");
151 return sb.ToString();
153 if(match.Groups[2].Success) //string literal
155 return "<span class=\"str\">" + match.ToString() + "</span>";
157 if(match.Groups[3].Success) //preprocessor keyword
159 return "<span class=\"preproc\">" + match.ToString() + "</span>";
161 if(match.Groups[4].Success) //keyword
163 return "<span class=\"kwrd\">" + match.ToString() + "</span>";
165 //System.Diagnostics.Debug.Assert(false, "None of the above!");
166 return ""; //none of the above