我正在用 Java 编写一个简单的词法分析器,该类的主要方法如下所示:
public LinkedList<Token> tokenize() {
// Create a matcher for the input string
Matcher matcher = tokensPattern.matcher(input);
// Create an empty list for the result
LinkedList<Token> tokensList = new LinkedList<>();
// While matches are found, keep looping
while (matcher.find()) {
// Get match
String matchStr = matcher.group();
// Check which token matched to create the apropriate Token object
for(PossibleTokens t : PossibleTokens.values()) {
if (matcher.group(t.name()) != null)
tokensList.add(new Token(t.name(), matchStr));
}
}
// Return list of Tokens
return tokensList;
}
我将词法分析器的可能标记保留在名为
PossibleTokens
的枚举中。该枚举中的每个元素都包含它所代表的标记的正则表达式模式。此外,常量的名称用于为每个令牌创建相应的命名捕获组。
代码按预期工作,但我不太喜欢的是,为了验证哪个组已匹配,我需要循环遍历所有组并验证哪个组不为空。
有没有更好的方法来获取匹配的组而不需要循环遍历所有组?
这将非常有用,因为我计划将来扩展此 Lexer 接受的令牌。所以每次都检查每个组是非常低效的。
您可以通过使用映射来存储匹配器中的命名捕获组来简化检查哪个令牌组匹配的逻辑,然后直接根据组名称检查匹配。这样,您就可以避免每次都循环遍历所有可能的标记。
您可以在
tokenize
方法中采取以下方法来提高效率:
public LinkedList<Token> tokenize() {
// Create a matcher for the input string
Matcher matcher = tokensPattern.matcher(input);
// Create an empty list for the result
LinkedList<Token> tokensList = new LinkedList<>();
// While matches are found, keep looping
while (matcher.find()) {
// Create a map to store the named-capturing groups
Map<String, String> namedGroups = new HashMap<>();
// Get all named groups from the matcher
for (String group : tokensPattern.namedGroups()) {
namedGroups.put(group, matcher.group(group));
}
// Check which token matched to create the appropriate Token object
for(PossibleTokens t : PossibleTokens.values()) {
String tokenValue = namedGroups.get(t.name());
if (tokenValue != null) {
tokensList.add(new Token(t.name(), tokenValue));
break; // Exit the loop once a match is found
}
}
}
// Return list of Tokens
return tokensList;
}
通过使用 Map 来存储命名捕获组并直接根据组名称检查是否匹配,可以提高确定哪个 token 匹配的效率,而无需每次都循环遍历所有可能的 token。