Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在c#中排列匹配的输出?_C# - Fatal编程技术网

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

如何在c#中排列匹配的输出?,c#,C#,我正在匹配单词以创建简单的词汇分析器。 下面是我的示例代码和输出 示例代码: public class { public static void main (String args[]) { System.out.println("Hello"); } } 输出: public = identifier void = identifier main = identifier class = identifier 正如你们所看到的,我的输出并没有随着输

我正在匹配单词以创建简单的词汇分析器。 下面是我的示例代码和输出 示例代码:

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

public = identifier
void = identifier
main = identifier
class = identifier
正如你们所看到的,我的输出并没有随着输入的到来而排列
void
main
在类之后,但在输出中,
位于末尾。我想在输入匹配时打印结果

c#代码:


CodeCaster是对的。你走的路不对。 我有一个词法分析器由我做了一段时间前作为一个项目

我知道我不应该把东西放在盘子里,但是分析器是C++的,所以你必须改变一些东西。
查看源代码,请尝试至少理解它是如何工作的:

从严格意义上讲,所描述行为的原因是,在评估代码中,对
void
的搜索先于对
类的搜索。然而,这种方法对于词法分析来说似乎过于简单,因为它只是检查子字符串。我完全赞同上述评论;根据您在大局中试图实现的目标,可能需要一种更复杂的方法。

您的代码询问以下问题:

  • 输入是否包含文本
    “public”
    ?如果是,请写下“public=identifier”
  • 输入是否包含文本
    “void”
    ?如果是,写下
    “void=identifier”
  • 输入是否包含文本
    “类”
    ?如果是这样,写下
    “class=identifier”
  • 输入是否包含文本
    “main”
    ?如果是,写下
    “main=identifier”
  • 所有这些问题的答案都是肯定的,而且因为它们是按照这个确切的顺序执行的,所以您得到的输出应该不会令人惊讶。注:
    public
    void
    class
    main
    是关键字,而不是标识符

    在空格上拆分?

    因此,您的方法不会帮助您标记输入。更正确的方法是
    input.Split()
    ——它将在空白边界处截断输入,并为您提供一个字符串数组。尽管如此,里面还是有很多空白条目

    input.Split(新字符[]{'、'\t'、'\r'、'\n'}、StringSplitOptions.RemoveEmptyEntries)
    稍好一些,给了我们以下输出:
    public
    class
    public
    static
    void
    main
    (字符串
    args[)
    {
    System.out.println(“你好”);
    }
    }

    但您会注意到,其中一些字符串包含多个“标记”:
    (String
    args[])
    System.out.println(“Hello”);
    。如果字符串中包含空格,它将被拆分为多个标记。显然,仅拆分空格是不够的

    标记化

    此时,您将开始编写一个循环,遍历输入中的每个字符,检查它是空白还是标点字符(例如
    {
    }
    [
    ]
    ,等等)。这些字符应视为上一个标记的结尾,标点符号也应视为其自身的标记。可以跳过空白

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

    在下一个换行符之前(换行符/序列因操作系统而异),应忽略两个正斜杠之后的任何内容(或将其解析为单个“注释”标记)。在遇到
    */
    序列之前,应忽略
    /*
    之后的任何内容

    数字可以选择以减号开头,可以包含点(或以点开头),也可以是负数的科学符号部分(
    e..
    ),还有类型后缀

    换句话说,您正在编写一个状态机,根据您所处的状态,它的行为会有所不同:“string”、“comment”、“block comment”、“numeric literal”等等

    词法分析

    在标记化或作为单独步骤(词法分析)时,为每个标记分配一个类型很有用。
    public
    是一个关键字,
    main
    是一个标识符,
    1234
    是一个整数文本,
    “Hello”
    是一个字符串文本,等等。这将在下一步中有所帮助

    解析

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

    例如,
    public
    protected
    private
    都是关键字标记,它们都是访问修饰符。一旦遇到其中一个,您就知道必须遵循类、函数、字段或属性定义。如果下一个标记是
    while
    关键字,则您会发出错误信号:
    public while
    不是有效的C#构造。但是,如果下一个标记是
    关键字,则您知道它是类定义,并继续解析

    所以你又一次得到了一个状态机,但这次你得到了像“类定义”、“函数定义”、“表达式”这样的状态
        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");
    
        }