1

我需要让这个程序计算 .java 源代码文件中的关键字(它确实如此),但它还需要分解任何注释或字符串中的关键字。任何帮助将不胜感激。!!!

import java.util.*;

import java.io.*;

public class CountKeywords {

public static void main(String[] args) throws Exception {

Scanner input = new Scanner(System.in);
System.out.print("Enter a Java source file: ");
String filename = input.nextLine();

File file = new File(filename);
if (file.exists()) {
  System.out.println("The number of keywords in " + filename
    + " is " + countKeywords(file));
}
else {
  System.out.println("File " + filename + " does not exist");
}
}

public static int countKeywords(File file) throws Exception {

// Array of all Java keywords + true, false and null

String[] keywordString = {"abstract", "assert", "boolean",
    "break", "byte", "case", "catch", "char", "class", "const",
    "continue", "default", "do", "double", "else", "enum",
    "extends", "for", "final", "finally", "float", "goto",
    "if", "implements", "import", "instanceof", "int",
    "interface", "long", "native", "new", "package", "private",
    "protected", "public", "return", "short", "static",
    "strictfp", "super", "switch", "synchronized", "this",
    "throw", "throws", "transient", "try", "void", "volatile",
    "while", "true", "false", "null"};

Set<String> keywordSet =
  new HashSet<String>(Arrays.asList(keywordString));
int count = 0;

Scanner input = new Scanner(file);

while (input.hasNext()) {
  String word = input.next();
  if (keywordSet.contains(word))
    count++;
}

return count;
}
}
4

2 回答 2

4

回答

不要重新发明轮子。尝试那里的众多 java 代码解析器之一。像https://code.google.com/p/javaparser/

否则你需要实现一个完整的解析器。

为什么?

除非你理解解析,否则你会错过一些东西。例如,让我们看看这个算法,看看它是否有效。

  1. 忽略“和”之间的所有代码。
  2. 忽略 /* 和 */ 之间的所有代码
  3. 忽略//后一行的所有代码

看起来很容易?然后你会遇到 "hello \"world"。好吧好吧。我们将考虑转义字符串。

将 1 更改为忽略 " 和 " 之间的所有代码,但忽略字符串中的 \"。

好的,这可以工作......直到 "hello \\"; private String.....好吧,我们只需要考虑......

这就是您滚动自己的解析器时发生的情况。您通常通过反复试验来完成,而不是查看整个解析语法并正确执行。使用来自已阅读该语言的整个 BNF 并构建了一个经过良好测试的解析器的解析器。从长远来看,它会拯救你。

于 2013-04-16T20:04:44.193 回答
0

我要做的是skip()在每个标记之后使用该方法来告诉它跳过注释和字符串。一个可能的模式是:

(/\*.*\*/)|(//.*?\n)|("([^"]|\\")*")

当您将反斜杠和引号转换为要传递给的字符串时,您必须确保正确转义它Pattern

请注意,这仍然无法正确解析所有 Java,因为您很可能没有考虑到您可以使用没有空格的标记 ( true|false) 或 Unicode 转义码 ( \u002a\u002f)。

于 2013-04-16T20:18:06.647 回答