public static int length(RegExp re){
  RegExp2 r;
switch (re.type) {
case sym.BAR:
{
      r=(RegExp2)re;
      int l1=length(r.r1);
      if (l1 < 0)       return -1;
      int l2=length(r.r2);
      if (l1 == l2)       return l1;
 else       return -1;
    }
case sym.CONCAT:
{
    r=(RegExp2)re;
    int l1=length(r.r1);
    if (l1 < 0)     return -1;
    int l2=length(r.r2);
    if (l2 < 0)     return -1;
    return l1 + l2;
  }
case sym.STAR:
case sym.PLUS:
case sym.QUESTION:
return -1;
case sym.CCLASS:
case sym.CCLASSNOT:
case sym.CHAR:
case sym.CHAR_I:
return 1;
case sym.STRING:
case sym.STRING_I:
{
String content=(String)((RegExp1)re).content;
return content.length();
}
case sym.TILDE:
case sym.BANG:
return -1;
case sym.MACROUSE:
return length(macros.getDefinition((String)((RegExp1)re).content));
}
throw new Error("Unkown expression type " + re.type + " in "+ re);
}

public static int length ( RegExp re ) { RegExp2 r ; switch ( re . type ) { case sym . BAR : { r = ( RegExp2 ) re ; int l1 = length ( r . r1 ) ; if ( l1 < 0 ) return - 1 ; int l2 = length ( r . r2 ) ; if ( l1 == l2 ) return l1 ; else return - 1 ; } case sym . CONCAT : { r = ( RegExp2 ) re ; int l1 = length ( r . r1 ) ; if ( l1 < 0 ) return - 1 ; int l2 = length ( r . r2 ) ; if ( l2 < 0 ) return - 1 ; return l1 + l2 ; } case sym . STAR : case sym . PLUS : case sym . QUESTION : return - 1 ; case sym . CCLASS : case sym . CCLASSNOT : case sym . CHAR : case sym . CHAR_I : return 1 ; case sym . STRING : case sym . STRING_I : { String content = ( String ) ( ( RegExp1 ) re ) . content ; return content . length ( ) ; } case sym . TILDE : case sym . BANG : return - 1 ; case sym . MACROUSE : return length ( macros . getDefinition ( ( String ) ( ( RegExp1 ) re ) . content ) ) ; } throw new Error ( "Unkown expression type " + re . type + " in " + re ) ; }
returns length if expression has fixed length , - 1 otherwise . negation operators are treated as always variable length .
