public static boolean maybeEmtpy(RegExp re){
  RegExp2 r;
switch (re.type) {
case sym.BAR:
{
      r=(RegExp2)re;
      return maybeEmtpy(r.r1) || maybeEmtpy(r.r2);
    }
case sym.CONCAT:
{
    r=(RegExp2)re;
    return maybeEmtpy(r.r1) && maybeEmtpy(r.r2);
  }
case sym.STAR:
case sym.QUESTION:
return true;
case sym.PLUS:
{
RegExp1 r1=(RegExp1)re;
return maybeEmtpy((RegExp)r1.content);
}
case sym.CCLASS:
case sym.CCLASSNOT:
case sym.CHAR:
case sym.CHAR_I:
return false;
case sym.STRING:
case sym.STRING_I:
{
String content=(String)((RegExp1)re).content;
return content.length() == 0;
}
case sym.TILDE:
return false;
case sym.BANG:
{
RegExp1 r1=(RegExp1)re;
return !maybeEmtpy((RegExp)r1.content);
}
case sym.MACROUSE:
return maybeEmtpy(macros.getDefinition((String)((RegExp1)re).content));
}
throw new Error("Unknown expression type " + re.type + " in "+ re);
}

public static boolean maybeEmtpy ( RegExp re ) { RegExp2 r ; switch ( re . type ) { case sym . BAR : { r = ( RegExp2 ) re ; return maybeEmtpy ( r . r1 ) || maybeEmtpy ( r . r2 ) ; } case sym . CONCAT : { r = ( RegExp2 ) re ; return maybeEmtpy ( r . r1 ) && maybeEmtpy ( r . r2 ) ; } case sym . STAR : case sym . QUESTION : return true ; case sym . PLUS : { RegExp1 r1 = ( RegExp1 ) re ; return maybeEmtpy ( ( RegExp ) r1 . content ) ; } case sym . CCLASS : case sym . CCLASSNOT : case sym . CHAR : case sym . CHAR_I : return false ; case sym . STRING : case sym . STRING_I : { String content = ( String ) ( ( RegExp1 ) re ) . content ; return content . length ( ) == 0 ; } case sym . TILDE : return false ; case sym . BANG : { RegExp1 r1 = ( RegExp1 ) re ; return ! maybeEmtpy ( ( RegExp ) r1 . content ) ; } case sym . MACROUSE : return maybeEmtpy ( macros . getDefinition ( ( String ) ( ( RegExp1 ) re ) . content ) ) ; } throw new Error ( "Unknown expression type " + re . type + " in " + re ) ; }
checks if the expression potentially matches the empty string .
