用于在不同行上开始和结束的注释的正则表达式

时间:2017-10-22 22:51:34

标签: java regex

好的,所以我已经在这个问题上工作了几个星期,现在我有一个程序,它读取包含一些迷你语言代码的文件,读取然后打印每个令牌,并附上描述令牌是什么。这种迷你语言的一部分是它支持单行和多行评论的能力。

评论的正则表达式为\{[^\}]*\}含义:

  • 评论以张开的大括号\{
  • 开头
  • 除了大括号[^\}]*
  • 之外的任何字符后跟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();
        }
    }
}

就像我之前说过的那样,我尝试了很多不同的方法来解决这个问题。我尝试过的一些事情是添加如下返回序列:\{[^\}]*[\r\n]*\}\{[\r\n]*[^\}]*\}\{[\r\n]*[^\}]*[\r\n]*\}\{[^\}]*\s*\}\{\s*[^\}]*\s*\},{{ 1}}和(?s)\{[^\}]*\},为我的Pattern对象尝试(?m)\{[^\}]*\}DOTALL标志,只是寻找我可以找到的任何教程但我没有运气

我正在阅读的文件如下所示:

MULTILINE

输出应如下所示:

{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

我不确定我做错了什么。非常感谢任何和所有的帮助!

2 个答案:

答案 0 :(得分:1)

你可以继续阅读另一个循环的文件如果你的行以一个开放的花括号开头,但不是以一个紧密的花括号结束,如下所示:

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行使。 :)

答案 1 :(得分:0)

代码无法运行,因为默认情况下,Java Pattern(用于正则表达式)已禁用MULTILINE模式。

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

AFAICS \{[^\}]*\}正则表达式没有(其他)错误,尽管您可能会使用\{.*?\}代替,这稍微更具可读性。