以不同行开始和结束的注释的正则表达式



好吧,我已经解决这个问题好几个星期了,我有一个程序可以读取一个文件,其中包含来自迷你语言的一些代码,读取并打印每个令牌,其中包含令牌的描述。这个迷你语言的一部分是它支持单行和多行注释的能力。

注释的正则表达式是{[^}]*},意思是:

  • 注释以大括号{开头
  • 后面跟0个或多个除大括号[^}]*之外的任何字符
  • 后跟一个大括号,结束注释}

旁注:注释不能嵌套,这意味着如果我有一个注释(如{This is a {nested} comment}),则不会被视为有效的注释,因为它只能有一个大括号。尽管如此,像{This is another {comment}这样的注释是有效的,因为只有一个大括号

在测试这个程序时,我遇到了一个问题,我的程序会读取一个文件,并遇到一个多行注释,但程序不能将注释识别为多行,而是打印出注释内部的内容,而不是整个注释本身。我花了整整一周或一周半的时间试图让它发挥作用。我尝试了各种正则表达式的组合以及if语句的放置位置,但都没有找到解决方案。我已经尽了一切努力来修复它,但由于我对正则表达式没有太多经验,我一定错过了一些非常明显的东西。

这里我有一段代码
旁注:我让我的程序通过另一个类中的用户输入来接受文件名。

import java.io.*;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;    
public class Analyzer {
public void lex(String filename) {
try {
Scanner scanFile = new Scanner(file);
while(scanFile.hasNextLine()) {
String str = scanFile.nextLine();
String keyword = "(\bWHILE\b|\bENDWHILE\b|\bIF\b|\bENDIF\b|\bPRINT\b)";
String comment = "(\{[^\}]*\})";
String literal = "(\b[0-9]+\b)";
String identifier = "(\b[a-z]+\b)";
String symbol = "((\()|(\))|(;))";
String operator = "((\+)|(\-)|(\*)|(/)|(\=)|(\<)|(\:\=))";
String keywordERROR = "(PRINT\w+)";
String commentERROR = "(\{.*\}.*\})";
String literalERROR = "([0-9]+[a-zA-Z_]+)";
String identERROR = "([a-z]+[A-Z_0-9]+)";
String alphabetERROR = "(~|`|\!|@|#|\$|%|\^|\&|_|\||\:|'|"|\?|\>|\.|\,|\\)";
String regex = keyword + "|" + keywordERROR + "|" + comment + "|" + commentERROR + "|" + literal + "|" + literalERROR
+ "|" + identifier + "|" + identERROR + "|" + symbol + "|" + operator + "|" + alphabetERROR;
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()) {
if(matcher.group(1) != null)
System.out.println(matcher.group(1) + "tKeyword");
else if(matcher.group(2) != null)
System.out.println(matcher.group(2) + "tError");
if(matcher.group(3) != null)
System.out.println(matcher.group(3) + "tComment");
else if(matcher.group(4) != null)
System.out.println(matcher.group(4) + "tError");
if(matcher.group(5) != null)
System.out.println(matcher.group(5) + "tLiteral");
else if(matcher.group(6) != null)
System.out.println(matcher.group(6) + "tError");
if(matcher.group(7) != null)
System.out.println(matcher.group(7) + "tIdentifier");
else if(matcher.group(8) != null)
System.out.println(matcher.group(8) + "tError");
if(matcher.group(9) != null) {
if(matcher.group(10) != null)
System.out.println(matcher.group(10) + "tOpen Parenthesis");
if(matcher.group(11) != null)
System.out.println(matcher.group(11) + "tClose Parenthesis");
if(matcher.group(12) != null)
System.out.println(matcher.group(12) + "tSemi-colon");
}
if(matcher.group(13) != null) {
if(matcher.group(14) != null)
System.out.println(matcher.group(14) + "tAddition Operator");
if(matcher.group(15) != null)
System.out.println(matcher.group(15) + "tSubtraction Operator");
if(matcher.group(16) != null)
System.out.println(matcher.group(16) + "tMultiplication Operator");
if(matcher.group(17) != null)
System.out.println(matcher.group(17) + "tDivision Operator");
if(matcher.group(18) != null)
System.out.println(matcher.group(18) + "tEquality Comparison Operator");
if(matcher.group(19) != null)
System.out.println(matcher.group(19) + "tLess Than Operator");
if(matcher.group(20) != null)
System.out.println(matcher.group(20) + "tAssignment Operator");
}
if(matcher.group(21) != null) 
System.out.println(matcher.group(21) + "tError");
}
}
scanFile.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}

正如我之前所说,我已经尝试了许多不同的方法来解决这个问题。我尝试过的一些事情是添加这样的返回序列:{[^}]*[rn]*}{[rn]*[^}]*}{[rn]*[^}]*[rn]*}{[^}]*s*}{s*[^}]*s*}(?s){[^}]*}(?m){[^}]*},尝试为我的Pattern对象使用DOTALLMULTILINE标志,只是在寻找我能找到的任何教程,但我没有找到任何运气。

我正在读取的文件如下:

{This is
a multi-line
comment.}
WHILE(x<10)
PRINT x;
x:=x+2;
ENDWHILE

输出应该是这样的:

{This is a multi-line comment}    Comment
WHILE    Keyword
(    Open Parenthesis
x    Identifier
<    Less Than Operator
10   Literal
)    Close Parenthesis
PRINT    Keyword
x    Identifier
;    Semi-colon
x    Identifier
:=   Assignment Operator
x    Identifier
+    Addition Operator
2    Literal
;    Semi-colon
ENDWHILE    Keyword

但相反,输出看起来是这样的:

is  Identifier
a   Identifier
multi   Identifier
-   Subtraction Operator
line    Identifier
comment Identifier
.   Error
WHILE   Keyword
(   Open Parenthesis
x   Identifier
<   Less Than Operator
10  Literal
)   Close Parenthesis
PRINT   Keyword
x   Identifier
;   Semi-colon
x   Identifier
:=  Assignment Operator
x   Identifier
+   Addition Operator
2   Literal
;   Semi-colon
ENDWHILE    Keyword

我不确定我做错了什么。非常感谢您的帮助!

您可以在循环时使用另一个继续读取文件,如果您的行以大括号开头,但没有以大括号结尾,则如下所示:

while(scanFile.hasNextLine()) {
String str = scanFile.nextLine().trim();  // trim off indents etc.
// If the line is blank just read in the next line.
if (str.equals("")) { continue; }
// If this is a multi-line comment then
if (str.startsWith("{") && !str.endsWith("}")) { 
while(scanFile.hasNextLine()) {
String commentStr = scanFile.nextLine().trim();
str+= " " + commentStr;
if (commentStr.endsWith("}")) { break; }
}
}
// Do the rest of your processing....
// ..................................
// ..................................
}

另一方面。。。。我不会使用RegEx来解析这个文件内容,但也许出于某种原因你需要这样做。无论如何,良好的RegEx练习。:)

由于Java的Pattern(用于正则表达式)默认禁用了MULTILINE模式,因此代码无法工作。

尝试在正则表达式字符串的开头使用(?m)启用它。或者以其他方式将Pattern的配置设置为使用MULTILINE。

AFAICS{[^}]*}正则表达式没有任何(其他)问题,尽管您可能可以使用{.*?},它的可读性稍高。

最新更新