【问题标题】:Java Syntax AnalyzerJava 语法分析器
【发布时间】:2018-02-13 23:39:01
【问题描述】:

我的令牌类

public class Token {
public enum TokenType {
RELATIONALOPERATOR("==|<>|<=|>=|>|<"), MULTIPLYINGOPERATOR("[*/]"), SIGNADDINGOP("[+-]"), LEFTPAREN(
    "\\("), RIGHTPAREN("\\)"), COMMA(","), PEROID("\\."), ASSIGNMENTOP("="), SEMICOLON(";"), WHILE(
        "while"), IF("if"), ELSE("else"), COMMENT("//"), PUBLIC("public"), PRIVATE("private"), PACKAGE(
            "package"), IMPORT("import"), ENUM("enum"), CONSTANT(
                "[0-9]*"), VARIABLE("[a-zA-Z][a-zA-Z0-9]*"), SKIP("[\\s+\\t]*"), INVALID(".*");

public final String pattern;

private TokenType(String pattern) {
    this.pattern = pattern;
}
}

public TokenType type;
public String data;

public Token(TokenType type, String data) {
  this.type = type;
  this.data = data;
}

@Override
public String toString() {
  return String.format("[ %s, %s ]", type.name(), this.data);
}
}

我的词法分析器类:

public static ArrayList<Token> lex(String input) {
// The tokens to return
ArrayList<Token> tokens = new ArrayList<Token>();

StringBuffer tokenPatternsBuffer = new StringBuffer();
for (TokenType tokenType : TokenType.values()) {
    // format everything to match |(?<EXAMPLE> [0-9]*)
    tokenPatternsBuffer.append(String.format("|(?<%s>%s)", tokenType.name(), tokenType.pattern));

}
Pattern tokenPatterns = Pattern.compile(tokenPatternsBuffer.substring(1));
//System.out.println(tokenPatternsBuffer.substring(1));

// Object that finds matches of pattern tokenPatterns
Matcher matcher = tokenPatterns.matcher(input);
while (matcher.find()) {
    int i = 0;
    System.out.println(matcher.group());
    for (TokenType tk : TokenType.values()) {
    // don't want to grab spaces
    if (matcher.group(TokenType.SKIP.toString()) != null) {
        continue;
    }
    // grab anything that isn't a space and add TokenType to the
    // matcher group using .named() because the text matching
    // exactly is vital
    else if (matcher.group(tk.name()) != null) {
        tokens.add(new Token(tk, matcher.group(tk.name())));
        i++;
        continue;
    }

    }
}

return tokens;
}

static String readFile(String path) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded);
}

public static void main(String[] args) throws IOException {
String toDebugg = readFile("Test.java");
ArrayList<Token> myTokens = lex(toDebugg);
// System.out.println(toDebugg);
// for (Token tok : myTokens) {
// System.out.println(tok);
// }
}

我已将问题范围缩小到 while(matcher.find()) 循环。在循环内打印 matcher.group() 不会产生任何结果。当我在上述主要方法中运行代码时,我收到 1 个 [PACKAGE, package] 打印件,然后是 40 个“[CONSTANT, ]”打印件,而下一个匹配的标记应该是“[Variable, myLex]”(包名)我一直在测试我的词法分析器的文件名为 Test.java,它的内容是

package myLex;
public class Test {

   public static void main(String[] args) {

   }

}

我希望它以 [TYPENAMEHERE, actualRegexMatchHere] 的形式打印 [PUBLIC, public], [CLASS, class] 等...,直到它读取整个文件。多亏了 Erwins 的建议,特殊字符现已被转义,但问题仍然存在。

【问题讨论】:

  • 不是答案,但您的解析器将需要 &gt;=,&lt;=,==,&lt;,&gt;,+,-,*,/,% 等的不同标记。否则您必须扫描所有内容两次。不要在词法分析中丢失信息。
  • 您应该像 lparen 一样转义标记中的特殊字符,否则它们将被解释为正则表达式特殊字符。

标签: java regex tokenize


【解决方案1】:

最初我的正则表达式被定义为
CONSTANT("[0-9]*"), VARIABLE("[a-zA-Z][a-zA-Z0-9]*"), SKIP("[\\s+\\t]*"), INVALID(".*");

[0-9]* 将匹配任何因为星号字符。将正则表达式中的所有 * 替换为 + 即可解决问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多