145 lines
3.0 KiB
Java
145 lines
3.0 KiB
Java
|
package prc.makedep;
|
||
|
|
||
|
import java.util.*;
|
||
|
import java.util.regex.*;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* A class for parsing NWScript files.
|
||
|
*
|
||
|
* @author Ornedan
|
||
|
*/
|
||
|
public class NWScript {
|
||
|
private static enum STATES{
|
||
|
/**
|
||
|
* Normal code, can switch to the other modes from here.
|
||
|
*/
|
||
|
NORMAL,
|
||
|
/**
|
||
|
* String mode. Exited by an unescaped " (technically should be ended
|
||
|
* by a new line as well, but we assume the code is not that badly fubar'd).
|
||
|
*/
|
||
|
STRING,
|
||
|
/**
|
||
|
* Singe line comment, started by //. Exited by a newline.
|
||
|
*/
|
||
|
SCOMMENT,
|
||
|
/**
|
||
|
* Multi-line comment.
|
||
|
*/
|
||
|
MCOMMENT
|
||
|
};
|
||
|
|
||
|
private static Matcher matcher = Pattern.compile("#include[ \t\u000B\f\r]*\"(.*)\"").matcher("");
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Parses the given source text for #include directives and returns the names of
|
||
|
* the files included.
|
||
|
*
|
||
|
* @param srcText contents of a nwscript source file
|
||
|
* @return array of String containing the names of files included by this one
|
||
|
*/
|
||
|
public static String[] findIncludes(CharSequence srcText){
|
||
|
StringBuffer wip = new StringBuffer(srcText);
|
||
|
ArrayList<String> list = new ArrayList<String>();
|
||
|
|
||
|
removeComments(wip);
|
||
|
|
||
|
// Parse for remaining #include statements
|
||
|
//#include[ \t\x0B\f\r]*"(.*)"
|
||
|
matcher.reset(wip);
|
||
|
//String debug;
|
||
|
while(matcher.find()){
|
||
|
//debug = matcher.group(1);
|
||
|
//list.add(debug);
|
||
|
list.add(matcher.group(1));
|
||
|
}
|
||
|
|
||
|
|
||
|
return list.toArray(new String[0]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Replaces the contents of comments with spaces.
|
||
|
*
|
||
|
* @param sbuf Stringbuffer containing nwscript to strip comments from
|
||
|
*/
|
||
|
private static void removeComments(StringBuffer sbuf){
|
||
|
STATES state = STATES.NORMAL;
|
||
|
char prev = '\u0000', cur;
|
||
|
boolean evenBSlash = true;
|
||
|
|
||
|
for(int i = 0; i < sbuf.length(); i++){
|
||
|
cur = sbuf.charAt(i);
|
||
|
switch(state){
|
||
|
case NORMAL:
|
||
|
if(prev == '/'){
|
||
|
if(cur == '/'){
|
||
|
state = STATES.SCOMMENT;
|
||
|
sbuf.setCharAt(i - 1, ' ');
|
||
|
sbuf.setCharAt(i, ' ');
|
||
|
}
|
||
|
else if(cur == '*'){
|
||
|
state = STATES.MCOMMENT;
|
||
|
sbuf.setCharAt(i - 1, ' ');
|
||
|
sbuf.setCharAt(i, ' ');
|
||
|
|
||
|
// Null current so that /*/ won't get mistakenly detected as having closed
|
||
|
cur = ' ';
|
||
|
}
|
||
|
}
|
||
|
else if(cur == '\"')
|
||
|
state = STATES.STRING;
|
||
|
break;
|
||
|
case STRING:
|
||
|
if(cur == '\"'){
|
||
|
if(evenBSlash)
|
||
|
state = STATES.NORMAL;
|
||
|
}
|
||
|
else if(cur == '\\')
|
||
|
evenBSlash = !evenBSlash;
|
||
|
else
|
||
|
evenBSlash = true;
|
||
|
break;
|
||
|
case SCOMMENT:
|
||
|
if(cur == '\n')
|
||
|
state = STATES.NORMAL;
|
||
|
else
|
||
|
sbuf.setCharAt(i, ' ');
|
||
|
break;
|
||
|
case MCOMMENT:
|
||
|
if(prev == '*' && cur == '/')
|
||
|
state = STATES.NORMAL;
|
||
|
|
||
|
sbuf.setCharAt(i, ' ');
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
prev = cur;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Test main
|
||
|
* @param args
|
||
|
*/
|
||
|
public static void main(String[] args) {
|
||
|
findIncludes(
|
||
|
"/**\n" +
|
||
|
" * Mof! \" \"\n" +
|
||
|
" */\n" +
|
||
|
"#include \"test\"\n" +
|
||
|
"#include \"tset\"\n" +
|
||
|
"/*/ */\n"+
|
||
|
"\n"+
|
||
|
"void main()\n"+
|
||
|
"{// Rar!\n"+
|
||
|
" florb(); /* call florb */\n"+
|
||
|
" /* another call */ florb();\n"+
|
||
|
"}\n"
|
||
|
);
|
||
|
}
|
||
|
}
|