ソースコードを開くと、正規表現を使って字句解析し、C#の言語仕様で定義されたキーワードとリテラル文字列に色付けし、変換したHTMLをテキストボックスに出力します。
簡素化のため、ここでは次のルールに従ってソースコードが記述されているものとします。
- トークンは、区切り文字列、リテラル文字列、識別子のいずれか。
- 区切り文字列は、区切り記号、演算子、キーワード、改行、空白のいずれか。
- リテラル文字列は、「"」または「'」で囲まれた文字列で、文字列中の「"」「'」は「\」でエスケープされている。
- 区切り文字列でもリテラル文字列でもないものは識別子。
リテラル文字列の色は「#990000」、キーワードの色は「blue」にしています。
このアプリケーション自身のコード(MainWindow.xaml.cs)を開いてみる
生成されたHTMLをブラウザで開いてみる
MainWindow.xaml
<Window x:Class="CsHighlighter.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="Open" Executed="OpenCommandHandler"/>
</Window.CommandBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Menu Grid.Row="0">
<MenuItem Command="Open" />
</Menu>
<TextBox Grid.Row="1" Name="textBox1"
AcceptsReturn="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto" />
</Grid>
</Window>
MainWindow.xaml.cs
using Microsoft.Win32;using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows;
using System.Windows.Input;
namespace CsHighlighter
{
public partial class MainWindow : Window
{
private static readonly string[] keywords = {
"abstract","as","base","bool","break","byte","case","catch"
,"char","checked","class","const","continue","decimal","default"
,"delegate","do","double","else","enum","event","explicit"
,"extern","false","finally","fixed","float","for","foreach"
,"goto","if","implicit","in","int","interface","internal"
,"is","lock","long","namespace","new","null","object","operator"
,"out","override","params","private","protected","public"
,"readonly","ref","return","sbyte","sealed","short","sizeof"
,"stackalloc","static","string","struct","switch","this"
,"throw","true","try","typeof","uint","ulong","unchecked"
,"unsafe","ushort","using","virtual","void","volatile","while"};
private static readonly string[] marks = {
"<<=",">>=","??","::","++","--","&&","||","->","==","!=","<="
,">=","+=","-=","*=","/=","%=","&=","|=","^=","<<",">>","=>",
"{","}","[","]","(",")",".",",",":",";","+","-","*","/","%","&"
,"|","^","!","~","=","<",">","?"};
private static readonly string[] markChars = {
"{","}","[","]","(",")",".",",",":",";","+","-","*","/","%","&"
,"|","^","!","~","=","<",">","?"};
public MainWindow()
{
InitializeComponent();
}
private void OpenCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == true)
{
string content;
using (FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(fs))
{
content = sr.ReadToEnd();
}
List<string> tokens = GetTokens(content);
string htmlCode = GetHtmlCode(tokens);
this.textBox1.Text = "<!DOCTYPE html><html><head><title></title></head><body>" + htmlCode + "</body></html>";
}
}
private static string GetHtmlCode(List<string> tokens)
{
HashSet<string> keywordSet = new HashSet<string>(keywords);
string htmlCode = "";
foreach (string token in tokens)
{
if (token == "\r\n" || token == "\n")
{
htmlCode += "<br/>";
}
else if (keywordSet.Contains(token))
{
htmlCode += "<span style=\"color:blue;\">" + token + "</span>";
}
else
{
string tempHtmlCode = HttpUtility.HtmlEncode(token);
tempHtmlCode = tempHtmlCode.Replace(" ", " ");
if (token.StartsWith("\"") || token.StartsWith("'"))
{
tempHtmlCode = "<span style=\"color:#990000;\">" + tempHtmlCode + "</span>";
}
htmlCode += tempHtmlCode;
}
}
return htmlCode;
}
private static List<string> GetTokens(string content)
{
string marksRegex = "";
foreach (string mark in marks)
{
foreach (char c in mark)
{
marksRegex += "\\" + c;
}
marksRegex += "|";
}
string markCharsRegex = "";
foreach (string c in markChars)
{
markCharsRegex += "\\" + c;
}
Regex regex = new Regex("(\"(?:[^\"\\\\]|\\\\.)*\")|('(?:[^\'\\\\]|\\\\.)*')|\\r?\\n|\\s+|" +
marksRegex + "[^\\s\"\'\\r\\n" + markCharsRegex + "]+");
List<string> tokens = new List<string>();
MatchCollection mc = regex.Matches(content);
foreach (Match m in mc)
{
tokens.Add(m.Value);
}
return tokens;
}
}
}
0 件のコメント:
コメントを投稿