//
// This software is now distributed according to
// the Lesser Gnu Public License. Please see
// http://www.gnu.org/copyleft/lesser.txt for
// the details.
// -- Happy Computing!
//
package com.stevesoft.ewe_pat;
/** This class provides a method for parsing the "s/.../.../" constructs
of Regex.perlCode.
@see Regex#perlCode
*/
class parsePerl {
final static char close(char c) {
// This switch statement does not behave
// properly when compiled with jdk1.1.5
// and the -O flag.
/*
switch(c) {
case '[':
return ']';
case '(':
return ')';
case '{':
return '}';
}
return c;*/
if(c == '<')
return '>';
if(c == '[')
return ']';
if(c == '(')
return ')';
if(c == '{')
return '}';
return c;
}
final public static String codify(String s,boolean keepbs) {
return codify(s,0,s.length(),keepbs);
}
final public static String codify(String s,int i0,int iN,boolean keepbs) {
StringBuffer sb = new StringBuffer();
boolean ucmode = false, lcmode = false, litmode = false;
boolean uc1 = false, lc1 = false;
boolean modified = false;
for(int i=i0;i<iN;i++) {
char c = s.charAt(i);
boolean mf = true, app=true;
if(c=='\\') {
app=false;
i++;
if(i<s.length()) {
char c2 = s.charAt(i);
switch(c2) {
case 'Q':
litmode = true;
break;
case 'U':
ucmode = true;
break;
case 'L':
lcmode = true;
break;
case 'u':
uc1 = true;
break;
case 'l':
lc1 = true;
break;
case 'E':
uc1=lc1=ucmode=lcmode=litmode=false;
break;
default:
if(keepbs)
sb.append('\\');
c=c2;
if(keepbs) mf = false;
app = true;
break;
}
modified |= mf;
}
}
if(app) {
if(lc1) {
c=lc(c);
lc1=false;
} else if(uc1) {
c=uc(c);
uc1=false;
} else if(ucmode) {
c=uc(c);
} else if(lcmode) {
c=lc(c);
}
if(litmode && needbs(c))
sb.append('\\');
sb.append(c);
}
}
return modified ? sb.toString() : s;
}
final static char uc(char c) {
return CaseMgr.toUpperCase(c);
}
final static char lc(char c) {
return CaseMgr.toLowerCase(c);
}
final static boolean needbs(char c) {
if(c >= 'a' && c <= 'z')
return false;
if(c >= 'A' && c <= 'Z')
return false;
if(c >= '0' && c <= '9')
return false;
if(c == '_')
return false;
return true;
}
final static Regex parse(String s) {
boolean igncase = false, optim = false, gFlag = false;
boolean sFlag = false, mFlag = false, xFlag = false;
StringBuffer s1 = new StringBuffer();
StringBuffer s2 = new StringBuffer();
int i=0,count=0;
char mode,delim='/',cdelim='/';
if(s.length() >= 3 && s.charAt(0)=='s') {
mode = 's';
delim = s.charAt(1);
cdelim = close(delim);
i=2;
} else if(s.length() >= 2 && s.charAt(0)=='m') {
mode = 'm';
delim = s.charAt(1);
cdelim = close(delim);
i=2;
} else if(s.length() >= 1 && s.charAt(0)=='/') {
mode = 'm';
i=1;
} else {
try {
RegSyntaxError.endItAll(
"Regex.perlCode should be of the "+
"form s/// or m// or //");
} catch(RegSyntax rs) {}
return null;
}
for(;i<s.length();i++) {
if(s.charAt(i)=='\\') {
s1.append('\\');
i++;
} else if(s.charAt(i)==cdelim && count==0) {
i++;
break;
} else if(s.charAt(i)==delim && cdelim != delim) {
count++;
} else if(s.charAt(i)==cdelim && cdelim != delim) {
count--;
}
s1.append(s.charAt(i));
}
if(mode=='s' && cdelim != delim) {
while(i<s.length() && Prop.isWhite(s.charAt(i)) )
i++;
if(i>=s.length()) {
try {
RegSyntaxError.endItAll(""+mode+delim+" needs "+cdelim);
} catch(RegSyntax rs) {}
return null;
}
cdelim = close(delim = s.charAt(i));
i++;
}
count=0;
if(mode=='s') {
for(;i<s.length();i++) {
if(s.charAt(i)=='\\') {
s2.append('\\');
i++;
} else if(s.charAt(i)==cdelim && count==0) {
i++;
break;
} else if(s.charAt(i)==delim && cdelim != delim) {
count++;
} else if(s.charAt(i)==cdelim && cdelim != delim) {
count--;
}
s2.append(s.charAt(i));
}
}
for(;i<s.length();i++) {
char c = s.charAt(i);
switch(c) {
case 'x':
xFlag = true;
break;
case 'i':
igncase = true;
break;
case 'o':
optim = true;
break;
case 's':
sFlag = true;
break;
case 'm':
mFlag = true;
break;
case 'g':
gFlag = true;
break;
default:
// syntax error!
try {
RegSyntaxError.endItAll("Illegal flag to pattern: "+c);
} catch(RegSyntax rs) {}
return null;
}
}
Regex r = new Regex();
try {
String pat=s1.toString(),reprul=s2.toString();
if(xFlag) {
pat = strip(pat);
reprul = strip(reprul);
}
r.compile(pat);
r.ignoreCase |= igncase;
r.gFlag |= gFlag;
r.sFlag |= sFlag;
r.mFlag |= mFlag;
if(optim) r.optimize();
if(delim=='\'')
r.setReplaceRule(new StringRule(reprul));
else
r.setReplaceRule(ReplaceRule.perlCode(reprul));
} catch(RegSyntax rs) {
r = null;
}
return r;
}
static String strip(String s) {
StringBuffer sb = new StringBuffer();
for(int i=0;i<s.length();i++) {
char c = s.charAt(i);
if(Prop.isWhite(c)) {
;
} else if(c == '#') {
i++;
while(i<s.length()) {
if(s.charAt(i) == '\n')
break;
i++;
}
} else if(c == '\\') {
sb.append(c);
sb.append(s.charAt(++i));
} else
sb.append(c);
}
return sb.toString();
}
}