如何在c#中安排匹配的输出?

时间:2014-12-11 13:27:02

标签: c#

我匹配单词来创建简单的词法分析器。 这是我的示例代码和输出 示例代码:

public class 
{
    public static void main (String args[]) 
    {
       System.out.println("Hello");
    }
}

输出:

public = identifier
void = identifier
main = identifier
class = identifier

因为你们都可以看到我的输出没有按照输入来安排。 voidmain在课后出现,但在输出中,class在结尾处出现。我希望在输入匹配时打印结果。

c#c​​ode:

    private void button1_Click(object sender, EventArgs e)
    {
        if (richTextBox1.Text.Contains("public"))
            richTextBox2.AppendText("public = identifier\n");

        if (richTextBox1.Text.Contains("void"))
            richTextBox2.AppendText("void = identifier\n");

        if (richTextBox1.Text.Contains("class"))
            richTextBox2.AppendText("class = identifier\n");

        if (richTextBox1.Text.Contains("main"))
            richTextBox2.AppendText("main = identifier\n");

    }

3 个答案:

答案 0 :(得分:2)

您的代码询问以下问题:

  1. 输入是否包含文字"public"?如果是,请记下"public = identifier"
  2. 输入是否包含文字"void"?如果是,请记下"void = identifier"
  3. 输入是否包含文字"class"?如果是,请记下"class = identifier"
  4. 输入是否包含文字"main"?如果是,请记下"main = identifier"
  5. 所有这些问题的答案都是肯定的,因为它们按照确切的顺序执行,所以你得到的输出应该不会令人惊讶。注意:publicvoidclassmain是关键字,而不是标识符。

    在空白处拆分?

    因此,您的方法无法帮助您对该输入进行标记。在正确的方向上稍微多一些的东西是input.Split() - 这将在空白边界处切断输入并为您提供一个字符串数组。不过,那里还有很多空白条目。

    input.Split(new char[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)稍微好一点,给我们以下输出:publicclass{publicstatic,{ {1}},voidmain(Stringargs[]){System.out.println("Hello");}

    但您会注意到其中一些字符串包含多个标记':}(Stringargs[])。如果你有一个带有空格的字符串,它将被分成多个标记。显然,仅仅分割空白是不够的。

    <强>标记化

    此时,您将开始编写一个遍历输入中每个字符的循环,检查它是否为空格或标点字符(例如System.out.println("Hello");(,{ {1}},){}[]等等。这些字符应被视为前一个标记的结尾,标点字符也应被视为自己的标记。可以跳过空格。

    您还必须考虑字符串文字和注释之类的内容:两个双引号之间的任何内容都不应该被标记化,而应被视为单个字符串的一部分&#39;令牌(包括空格)。此外,字符串可以包含生成单个字符的转义序列(例如.)(双引号不应被视为字符串的结尾,而是作为其内容的一部分)。

    在两个正斜杠之后出现的任何内容都应该被忽略(或解析为单个&#39;注释&#39;令牌,如果你想以某种方式处理评论),直到下一个换行符(换行字符/序列在操作中不同)系统)。在遇到;序列之前,应忽略\"之后的任何内容。

    数字可以选择以减号开头,可以包含一个点(或以点开头),科学记数符部分(/*),也可以是负数,并且有类型后缀...

    换句话说,您正在编写状态机,具有不同的行为,具体取决于您所处的状态:&#39; string&#39;,&#39; comment&#39;,& #39;阻止评论&#39;,&#39;数字文字&#39;等等。

    <强>乐星

    在标记化或单独的步骤(lexing)中为每个标记分配类型很有用。 */是关键字,e..是标识符,public是整数文字,main是字符串文字,依此类推。这将有助于下一步。

    <强>解析

    您现在可以继续解析:将令牌列表转换为抽象语法树(AST)。此时,您可以检查令牌列表是否实际上是有效代码。你基本上重复了上述步骤,但处于更高的水平。

    例如,1234"Hello"public是关键字标记,它们是所有访问修饰符。只要遇到其中一个,就会知道必须遵循类,函数,字段或属性定义。如果下一个标记是protected关键字,则表示错误:private不是有效的C#构造。但是,如果下一个标记是while关键字,那么您就知道它是一个类定义并继续解析。

    所以你再次获得了一台状态机,但这次你有类别定义&#39;,&#39;功能定义&#39;,&#39;等等。 ;表达&#39;,&#39;二进制表达&#39;一元表达&#39;,&#39;语句&#39;,&#39;赋值语句&#39;等等。< / p>

    <强>结论

    这绝不是完整的,但希望它能让您更好地了解所涉及的所有步骤以及如何处理此问题。还有一些工具可以从语法规范生成解析代码,这可以稍微简化工作(尽管你仍然需要学习如何编写这样的语法)。

    您可能还想阅读C#语言规范,特别是有关其语法和词汇结构的部分。该规范可以从Microsofts网站免费下载。

答案 1 :(得分:0)

CodeCaster是对的。你没有走正确的道路。 我不久前作为一个项目制作了一个词法分析器。

我知道,我知道我不应该把东西放在盘子里,但是分析器是针对c ++的,所以你必须改变一些东西。

看看源代码,请尝试了解它至少是如何工作的:C++ Lexical Analyzer

答案 2 :(得分:0)

从严格意义上讲,所描述行为的原因是,在评估代码中,void的搜索在搜索class之前出现。然而,对于词法分析来说,总体方法似乎太简单了,因为它只是检查子串。我完全赞同上述评论;根据你想要在大局中实现的目标,可能需要更复杂的方法。