#region Copyright � 2001-2003 Jean-Claude Manoli [jc@manoli.net]
/*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the author(s) be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
#endregion
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace CodeFormatter
{
///
/// Provides a base class for formatting most programming languages.
///
public abstract class CodeFormat : SourceFormat
{
///
/// Must be overridden to provide a list of keywords defined in
/// each language.
///
///
/// Keywords must be separated with spaces.
///
protected abstract string Keywords
{
get;
}
///
/// Can be overridden to provide a list of preprocessors defined in
/// each language.
///
///
/// Preprocessors must be separated with spaces.
///
protected virtual string Preprocessors
{
get { return ""; }
}
///
/// Must be overridden to provide a regular expression string
/// to match strings literals.
///
protected abstract string StringRegEx
{
get;
}
///
/// Must be overridden to provide a regular expression string
/// to match comments.
///
protected abstract string CommentRegEx
{
get;
}
///
/// Determines if the language is case sensitive.
///
/// true if the language is case sensitive, false
/// otherwise. The default is true.
///
/// A case-insensitive language formatter must override this
/// property to return false.
///
public virtual bool CaseSensitive
{
get { return true; }
}
///
protected CodeFormat()
{
//generate the keyword and preprocessor regexes from the keyword lists
Regex r;
r = new Regex(@"\w+|-\w+|#\w+|@@\w+|#(?:\\(?:s|w)(?:\*|\+)?\w+)+|@\\w\*+");
string regKeyword = r.Replace(Keywords, @"(?<=^|\W)$0(?=\W)");
string regPreproc = r.Replace(Preprocessors, @"(?<=^|\s)$0(?=\s|$)");
r = new Regex(@" +");
regKeyword = r.Replace(regKeyword, @"|");
regPreproc = r.Replace(regPreproc, @"|");
if (regPreproc.Length == 0)
{
regPreproc = "(?!.*)_{37}(? 0)
{
regAll.Append(")|(");
regAll.Append(regPreproc);
}
regAll.Append(")|(");
regAll.Append(regKeyword);
regAll.Append(")");
RegexOptions caseInsensitive = CaseSensitive ? 0 : RegexOptions.IgnoreCase;
CodeRegex = new Regex(regAll.ToString(), RegexOptions.Singleline | caseInsensitive);
}
///
/// Called to evaluate the HTML fragment corresponding to each
/// matching token in the code.
///
/// The resulting from a
/// single regular expression match.
/// A string containing the HTML code fragment.
protected override string MatchEval(Match match)
{
if(match.Groups[1].Success) //comment
{
StringReader reader = new StringReader(match.ToString());
string line;
StringBuilder sb = new StringBuilder();
while ((line = reader.ReadLine()) != null)
{
if(sb.Length > 0)
{
sb.Append("\n");
}
sb.Append("");
sb.Append(line);
sb.Append("");
}
return sb.ToString();
}
if(match.Groups[2].Success) //string literal
{
return "" + match.ToString() + "";
}
if(match.Groups[3].Success) //preprocessor keyword
{
return "" + match.ToString() + "";
}
if(match.Groups[4].Success) //keyword
{
return "" + match.ToString() + "";
}
System.Diagnostics.Debug.Assert(false, "None of the above!");
return ""; //none of the above
}
}
}