如何匹配括号之间可以包含括号的任何字符串?

How to match any string between paranthesis that can contain paranthesis?

我正在尝试创建 JavaCC 解析器,但遇到了问题。

我想 return 我的文本中括号之间的所有内容,但这些括号之间的字符串可能包含一些。

例如,我有这一行: Node(new MB34(MB78, MB654) => (MB7, M9)) 并且我想要一个等于 "new MB34(MB78, MB654) => (MB7, M9)" 的字符串。括号之间没有特定的模式。

我已经尝试根据 javacc 文档使用词法状态:

SKIP :
{ " " | "\t" | "\n" | "\r" | "\f" | "\r\n" }

TOKEN :
{
  < #LETTER             : ( [ "a"-"z" ] | [ "A"-"Z" ] ) >
| < #DIGIT              : [ "0"-"9" ] >
| < #ALPHA              : ( < LETTER > | < DIGIT > ) >
| < IDENTIFIER          : < LETTER > ( < ALPHA > )* >
}

TOKEN : {
  < "(" > : IN_LABEL
}

< IN_LABEL > TOKEN : {
  < TEXT_LABEL : ~[] >
}

< IN_LABEL > TOKEN : {
  < END_LABEL : ")"> : DEFAULT
}

String LABEL():
{
  Token token_label;
  String label = "";
}
{
  < IDENTIFIER >
  "(" ( token_label = < TEXT_LABEL > { label += token_label.toString(); } )+ < END_LABEL >
   {
     return label;
   }
}

但是,由于要脱离词法状态“IN_LABEL”的字符串是单个字符“)”,所以解析器会匹配所有没有 returning 的文本到默认状态。 我通过将 END_LABEL 标记替换为 :

找到了一个临时解决方案
< IN_LABEL > TOKEN : {
  < END_LABEL : ~[]")"> : DEFAULT
}

但它也不起作用,因为这个标记可以在标签的真正结尾之前匹配。

有人能解决这个问题吗?

可能有更简单的解决方案,但这是我的解决方案:

SKIP :
{ " " | "\t" | "\n" | "\r" | "\f" | "\r\n" }

TOKEN :
{
  < #LETTER             : ( [ "a"-"z" ] | [ "A"-"Z" ] ) >
| < #DIGIT              : [ "0"-"9" ] >
| < #ALPHA              : ( < LETTER > | < DIGIT > ) >
| < IDENTIFIER          : < LETTER > ( < ALPHA > )* >
}

TOKEN_MGR_DECLS :
{
    int parLevel;
}

MORE : {
    "(" : IN_LABEL
}

< IN_LABEL > TOKEN : {
    < TEXT_LABEL: ")" > {
        matchedToken.image = image.substring(1,image.length()-1);
    } : DEFAULT
}

< IN_LABEL > MORE : {
   <~["(", ")"]>
}

< IN_LABEL > MORE : {
    "(" {parLevel = 0;} : IN_LABEL1
}

< IN_LABEL1 > MORE : {
    "(" {++parLevel;}
}

< IN_LABEL1 > MORE : {
    ")" {
        if (0 == parLevel--) {
            SwitchTo(IN_LABEL);
        }
    }
}

< IN_LABEL1 > MORE : {
   <~["(", ")"]>
}

String LABEL():
{
  String label = "";
}
{
  < IDENTIFIER >
  label = < TEXT_LABEL >.image
   {
     return label;
   }
}