代码改变世界

WPF外观词法分析器

2010-01-05 17:13  花晓霜  阅读(602)  评论(0编辑  收藏  举报

写这个词法分析器,我主要是利用基于.NET 3.0的WPF来实现的界面的,通过一个自己写的analyser的类来实现词法分析的主要过程。
我在WPF的界面放置两个Textbox把他们的wrap属性置为True,然后第一个文本框里输入原始字符串,我在放置一个button,通过调用button的点击事件来实现将原字符串经过analyser的analyse方法返回的字符串从第二个textbox输出。
在analyse类中我用一个二维数组来存储特殊字符的信息,大致分为四类:数字,关键字,数学运算符和关系运算法,其余的非数字字符置为标示符。然后我用7个状态来区分他们,用一个叫currencyStatus储存状态。这些状态分别是:A.初始状态 B.转到界符状态 C.转到算术运算符状态 D.转到比较运算符状态 E.转到数字状态 F.转到字符状态 G.结束

具体代码如下:

1. WPF界面的XAML代码如下:

Window1.xaml文件:

<Window x:Class="Jeramine.WPF.Lexer.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Jeramine.WPF.Lexer" Height="300" Width="690">
    <Grid>
        <!--author by Jermaine-->
        <TextBox HorizontalAlignment="Left" Margin="12,12,0,12" Name="txtInit" Width="270" TextWrapping="Wrap" />
        <TextBox HorizontalAlignment="Right" Margin="0,12,12,12" Name="txtAnalysis" Width="270" TextWrapping="Wrap" />
        <Button Height="23" Margin="296,27,295,0" Name="btnAnlyze" VerticalAlignment="Top" Content="分析" Click="btnAnlyze_Click"></Button>
    </Grid>
</Window>

2. 后台的cs代码如下,它通过一个button的点击事件来实现把原文本框里面的文本经过词法分析analyse类解析出来各个符号的作用。

/**Main WPF Window 逻辑代码
 *author by Jermaine 
 */
namespace Jeramine.WPF.Lexer
{
    /// <summary>
    /// Window1.xaml 的交互逻辑
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void btnAnlyze_Click(object sender, RoutedEventArgs e)
        {
            Analyser ansr = new Analyser();
            txtAnalysis.Text = ansr.Analyse(txtInit.Text).ToString();
        }
    }
}

3. 词法解析核心类analyser,主要包含了两个方法,analyse和checkletter,主要逻辑是通过在analyse方法中调用checkletter方法来区分字符是属于哪一种状态的,然后在analyse中实现各种类型的区分

Analyser.cs文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
/**主要分析程序
 * author by Jermaine
 */
namespace Jeramine.WPF.Lexer
{
     public  class Analyser
    {
         /*定义各种符号的数组和状态*/
         const int KeyNum = 4;
         public static string[][] key = new string[KeyNum][];
         static char currencyStatus;//用来存储状态

         /*
         状态表
         * A 初始状态
         * B 转到界符状态
         * C 转到算术运算符状态
         * D 转到比较运算符状态
         * E 转到数字状态
         * F 转到字符状态
         * G over
        */

         /*类型表
          * 关键字 0
          * 界符 1
          * 算术运算符 2 
          * 关系运算符   3
          * 标识符   4
          * 数字 5
         */
        /// <summary>
        ///
        /// </summary>
        /// <param name="source">原始文本</param>
        /// <returns>格式化文本</returns>
        public StringBuilder Analyse(string source)
        {
            StringBuilder destiny = new StringBuilder();
            //数组定义,除此之外字母为标示符
            key[0] = new string[] { "while", "if", "for", "int", "main" };//关键字
            key[1] = new string[] { ",", ";", "(", ")", "{", "}" };//界符
            key[2] = new string[] { "=", "*", "+", "/", "-", "++","--"};//算术运算符
            key[3] = new string[] { ">", ">=", "==", "<=", "<" };//关系运算符

            StringReader str = new StringReader(source);//以流的方式读出字符串
            string sen = String.Empty;
            string word = String.Empty;//用来截取字符串
            while ((sen = str.ReadLine()) != null)
             {
                 sen = sen + '\0';
                 currencyStatus = 'A';
                 for (int i = 0; i < sen.Length; i++)
                 {
                     char newStatus;
                     newStatus = CheckLetter(sen[i], currencyStatus);
                     if (newStatus != currencyStatus)
                     {
                         if (currencyStatus == 'F')
                         {
                             int flag = 1;//关键字和标识符的标志
                             for (int j = 0; j < key[0].Length; j++)
                             {
                                 if (word.ToString() == key[0][j].ToString())
                                 {
                                     destiny.Append(word + "是关键字\n");
                                     flag = 0;
                                     break;
                                 }
                               
                             }
                             if (flag == 1)
                             {
                                 destiny.Append(word + " 是标识符\n");
                             }
                         }
                         
                         else if (currencyStatus == 'B')
                         {
                             foreach (char a in word)
                             {
                                 for (int j = 0; j < key[1].Length; j++)
                                 {
                                     if (a.ToString() == key[1][j].ToString())
                                     {
                                        destiny.Append(a.ToString() + " 是界符\n");
                                         break;
                                     }
                                 }
                             }
                         }

                           else if (currencyStatus == 'C')
                        {
                            for (int j = 0; j < key[2].Length; j++)
                            {
                                if (word.ToString() == key[2][j].ToString())
                                {
                                   destiny.Append(word + "是算术运算符\n");
                                    break;
                                }
                            }
                        }

                        else if (currencyStatus == 'D')
                        {
                            for (int j = 0; j < key[3].Length; j++)
                            {
                                if (word.ToString() == key[3][j].ToString())
                                {
                                    destiny.Append(word + " 是关系运算符\n");
                                    break;
                                }
                            }
                        }

                        else if (currencyStatus == 'E')
                        {
                           destiny.Append(word + " 是数字\n");
 
                        }
                        word = sen[i].ToString().Trim();

                    }
                    else
                    {
                        word = word + sen[i].ToString().Trim();
                    }
                     currencyStatus = newStatus;
                 }
             }
            return destiny;
        }
         /// <summary>
         /// 
         /// </summary>
         /// <param name="letter"></param>
         /// <param name="currencyStatus"></param>
         /// <returns></returns>
        static char CheckLetter(char letter, char currencyStatus)
        {
            //跳转 or 保持 字符状态
            if (char.IsLetter(letter) == true)
                return 'F';
            else if (char.IsNumber(letter) == true && currencyStatus == 'F')
                return 'F';
            //跳转 or 保持 数字状态
            else if (char.IsNumber(letter) == true)
                return 'E';
            //界符
            else if (letter == ',' || letter == ';' || letter == '(' || letter == ')' || letter == '{' || letter == '}' || letter == '[' || letter == ']')
                return 'B';
            //算术运算符
            else if (letter == '*' || letter == '+' || letter == '-' || letter == '/')
                return 'C';
            //比较运算符
            else if (letter == '=' || letter == '>' || letter == '<')
                return 'D';
            //结束
            else return 'G';
        }
    }
}

项目工程截图如下:

clip_image002

运行截图如下:

clip_image004