Using regexp for any kind of parsing is asking for a major issues, performance-wise.
For ply files, even string tokenizer is enough to parse simple cases. Below there is some code I have written a long time ago (It works with only specific format, I think that there are at least 2 or 3 variations, doing a full loader is a bit more complicated).
For something with acceptable performance and fast to develop, use javacc. For really high performance, you will need to write everything by yourself from the scratch. (I have used javacc to load nwn ascii files, then rewritten it by hand and got a 3 times improvement in speed…).
Here you can check out my handcrafted parser for nwn files
http://cvs.sourceforge.net/viewcvs.py/nwn-j3d/nwn/src/net/sf/nwn/loader/ManualParser.java?rev=1.16&view=markup
and below is some crappy code for ply parsing I have found in my archives
BufferedReader br = new BufferedReader(new FileReader(filename));
StreamTokenizer st = new StreamTokenizer(br);
st.resetSyntax();
st.eolIsSignificant(false);
st.wordChars(0,255);
st.whitespaceChars(' ', ' ');
st.whitespaceChars('\n','\n');
st.whitespaceChars('\r','\r');
st.whitespaceChars('\t','\t');
String str;
float[] vertices = null;
int[] faces = null;
while ( true ) {
int token = st.nextToken();
if ( token == StreamTokenizer.TT_EOF )
break;
if ( token != StreamTokenizer.TT_WORD)
continue;
if ( st.sval.equalsIgnoreCase("element")) {
st.nextToken();
if ( st.sval.equalsIgnoreCase("vertex") ) {
st.nextToken();
vertices = new float[3*Integer.parseInt(st.sval)];
} else if (st.sval.equalsIgnoreCase("face")) {
st.nextToken();
faces = new int[3*Integer.parseInt(st.sval)];
}
} else if (st.sval.equalsIgnoreCase("end_header") ){
break;
}
}
for ( int i =0; i < vertices.length; i+=3) {
st.nextToken();
vertices[i] = Float.parseFloat(st.sval);
st.nextToken();
vertices[i+1] = Float.parseFloat(st.sval);
st.nextToken();
vertices[i+2] = Float.parseFloat(st.sval);
st.nextToken();
st.nextToken();
}
for ( int i =0; i < faces.length; i+=3 ) {
st.nextToken();
st.nextToken();
faces[i] = Integer.parseInt(st.sval);
st.nextToken();
faces[i+1] = Integer.parseInt(st.sval);
st.nextToken();
faces[i+2] = Integer.parseInt(st.sval);
}