需要一些关于如何在Java中实现这一点的想法(解析字符串)

需要一些关于如何在Java中实现这一点的想法(解析字符串),java,parsing,Java,Parsing,对不起,我想不出更好的标题了,但是谢谢你的阅读 我的最终目标是读取一个.java文件,解析它,并提取每个标识符。然后将它们全部存储在一个列表中。两个先决条件是文件中没有注释,并且所有标识符仅由字母组成 现在我可以读取文件,用空格解析,并将所有内容存储在列表中。如果列表中的任何内容是java保留字,则会将其删除。此外,我删除了任何未附加到任何内容的松散符号(括号和算术符号) 现在我只剩下一堆奇怪的字符串,但至少它们没有空格。我知道我将不得不用一个。分隔符,以便提取标识符,如System.out.p

对不起,我想不出更好的标题了,但是谢谢你的阅读

我的最终目标是读取一个.java文件,解析它,并提取每个标识符。然后将它们全部存储在一个列表中。两个先决条件是文件中没有注释,并且所有标识符仅由字母组成

现在我可以读取文件,用空格解析,并将所有内容存储在列表中。如果列表中的任何内容是java保留字,则会将其删除。此外,我删除了任何未附加到任何内容的松散符号(括号和算术符号)

现在我只剩下一堆奇怪的字符串,但至少它们没有空格。我知道我将不得不用一个。分隔符,以便提取标识符,如System.out.print,但如何处理以下示例中的字符串:

Logger.getLogger(MyHash.class.getName()).log(Level.SEVERE

在通过重新解析后。我将留下更多疯狂的字符串,如:

getLogger(MyHash)

getName())

日志(级别)

严重的


我怎样才能在清除所有垃圾的同时提取出所有标识符?只需通过java代码中可能存在的每个符号重新解析就行了?这似乎很费时费力。我甚至不确定它是否能完全工作。因此,你能建议一种更好的方法吗?

有几种解决方案可供选择使用,而不是黑客自己的解析器:

  • 使用现有的解析器,例如
  • 用于读取字节码,其中包括所有字段和变量
  • 侵入编译器或运行时,使用或-我不确定您可以通过这种方式找到所有标识符,但字段和参数是肯定的

除了破解自己的解析器,您还可以使用几种解决方案:

  • 使用现有的解析器,例如
  • 用于读取字节码,其中包括所有字段和变量
  • 侵入编译器或运行时,使用或-我不确定您可以通过这种方式找到所有标识符,但字段和参数是肯定的

哇,好吧。解析很难——真的很难——做对。正确使用您自己的java解析器将非常困难。您会发现有很多边缘情况您还没有做好准备。要真正做对并处理所有边缘情况,您需要编写一个真正的解析器。一个真正的解析器由许多事情:

  • 词法分析器,用于将输入分解为逻辑块
  • 确定如何解释上述语块的语法
  • 实际的“解析器”,它是使用类似
  • 用于存储标识符的符号表
  • 表示已解析代码的抽象语法树
  • 一旦你拥有了所有这些,你就可以拥有一个真正的解析器。当然你可以跳过抽象语法树,但你需要几乎所有的东西。这就需要编写大约1/3的编译器。如果你真的想自己完成这个项目,你应该看看你是否能找到一个包含先前存在的java语法的ANTLR示例ar定义。这将使您大部分时间都可以使用它,然后您需要使用ANTLR来填充符号表


    或者,你可以使用小Bobby Tables建议的聪明的解决方案(很棒的名字,顺便说一句Bobby).

    哇,好吧。解析很难——真的很难——做对。正确使用您自己的java解析器将非常困难。您会发现有很多边缘情况您还没有做好准备。要真正正确地做,并处理所有边缘情况,您需要编写一个真正的解析器。真正的解析器由数字组成关于事物:

  • 词法分析器,用于将输入分解为逻辑块
  • 确定如何解释上述语块的语法
  • 实际的“解析器”,它是使用类似
  • 用于存储标识符的符号表
  • 表示已解析代码的抽象语法树
  • 一旦你拥有了所有这些,你就可以拥有一个真正的解析器。当然你可以跳过抽象语法树,但你需要几乎所有的东西。这就需要编写大约1/3的编译器。如果你真的想自己完成这个项目,你应该看看你是否能找到一个包含先前存在的java语法的ANTLR示例ar定义。这将使您大部分时间都可以使用它,然后您需要使用ANTLR来填充符号表


    或者,你可以使用小Bobby表(很棒的名字,顺便说一句Bobby)建议的聪明解决方案。

    我不会一次按空格分隔整个文件。相反,我会逐字扫描文件,将每个字符保存在缓冲区中,直到我确定已到达标识符为止

    在伪代码中:

    clean buffer
    for each letter l in file:
        if l is '
            toggle "character mode"
        if l is "
            toggle "string mode"
        if l is a letter AND "character mode" is off AND "string mode" is off
            add l to end of buffer
        else
            if buffer is NOT a keyword or a literal
                add buffer to list of identifiers
            clean buffer
    
    注意,这里的一些行隐藏了进一步的复杂性——例如,要检查缓冲区是否为文本,需要同时检查true、false和null

    此外,伪代码中还有更多的错误-它会发现识别文字的e和L部分(浮点文字中的e,长文字中的L)。我建议添加额外的“模式”来处理它们,但这有点棘手

    此外,如果您想确保它的准确性,还需要做一些事情——例如,您必须确保使用unicode。我强烈建议您调查该语言的使用情况,这样您就不会错过任何东西

    编辑:

    • 这个解决方案可以很容易地扩展到处理带有数字的标识符以及注释
    • 上面的小错误-您需要处理“不同于”,与“和”相同

    我不会立即按照空格分隔整个文件。相反,我会逐字扫描文件,将每个字符保存在缓冲区中,直到