Hi, ich habe folgendes Problem:
Meine Klasse soll C-Quellcode parsieren und die jeweiligen Positionen der Keywords rausfinden, die dann weiterverarbeitet werden. Dafür hab ich einen Scanner geschrieben: die Methode
Die Regex-Pattern werden hier erzeugt:
Das wichtige ist, das ich die jeweilige Position und die Länge rauskriege, die ich dann in den Methoden styleNumber oder styleKeyword weiterverwende.
Mein Problem:
Bei kürzeren Quellcodes also z.B. ein HelloWorld-Programm oder auch etwas länger funktioniert das einwandfrei.
Nur ab einer bestimmten Länge, die ich nicht fest sagen kann, liefert der Scanner Unsinn, bzw. sagt mir dass das Matchresult beispielsweise an Position 1 steht, obwohl es an 2000 oder so stehen müsste. (z.B. in Zeile 55 im ersten Codefragment). Hab die Vermutung, dass er wieder von vorne anfängt zu zählen.
Hat jemand von euch schonmal ähnliches erlebt oder weiß, woran es liegen könnte?
Gruss
Dirk
Meine Klasse soll C-Quellcode parsieren und die jeweiligen Positionen der Keywords rausfinden, die dann weiterverarbeitet werden. Dafür hab ich einen Scanner geschrieben: die Methode
Code:
public void highlight() {
if (styledText == null) {
return;
}
if (oldText == null || (!oldText.equals(styledText.getText()))) {
// we have new text to scan!
oldText = styledText.getText();
styleRanges.clear();
Scanner scanner = new Scanner(oldText);
scanner.useDelimiter(PatternFactory.getDelimiterPattern());
String matchstring;
MatchResult matchresult;
int iStart, iLength;
int iCommentStart = 0, iCommentRange = 0;
boolean bInClosedComment = false;
while (scanner.hasNext()) {
try {
if (!bInClosedComment) {
// check if we got a linecomment
if (scanner.hasNext(patLineComment)) {
matchstring = scanner.next(patLineComment);
matchresult = scanner.match();
iCommentStart = matchresult.start();
iCommentRange = matchstring.length();
// skip the rest of the line
matchstring = scanner.nextLine();
iCommentRange += matchstring.length();
styleComment(iCommentStart, iCommentRange);
iCommentStart = 0;
iCommentRange = 0;
}
// Check if we got a closed comment
else if (scanner.hasNext(patClosedCommentStart)) {
bInClosedComment = true;
matchstring = scanner.next(patClosedCommentStart);
matchresult = scanner.match();
iCommentStart = matchresult.start();
// check if comment ends in this match
if (matchstring.contains("*/")) {
iCommentRange = getCommentLength(matchstring);
styleComment(iCommentStart, iCommentRange);
bInClosedComment = false;
iCommentRange = 0;
iCommentStart=0;
}
}
// check if we got a keyword
else if (scanner.hasNext(patKey)) {
matchstring = scanner.next(patKey);
matchresult = scanner.match();
iStart = matchresult.start();
iLength = matchstring.length();
styleKeyword(iStart, iLength);
} else {
// check if we got a number
if (scanner.hasNext(patNumber)) {
matchstring = scanner.next(patNumber);
matchresult = scanner.match();
iStart = matchresult.start();
iLength = matchstring.length();
styleNumber(iStart, iLength);
} else {
// discard token if we found nothing
scanner.next();
}
}
}// !bInClosedComment
else if (scanner.hasNext(patClosedCommentEnd)) {
// we are in comment block, check for an '*/'
matchstring = scanner.next(patClosedCommentEnd);
matchresult = scanner.match();
iCommentRange = getCommentLength(matchstring) - iCommentStart;
styleComment(iCommentStart, iCommentRange);
iCommentRange = 0;
iCommentStart = 0;
bInClosedComment = false;
} else {
// no comment-end, skip token
scanner.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}
scanner.close();
}
}
Die Regex-Pattern werden hier erzeugt:
Code:
import java.util.regex.Pattern;
public class PatternFactory {
// The patterns we need to search for
private static Pattern patKey = null;
private static Pattern patNumber = null;
private static Pattern patClosedCommentStart = null;
private static Pattern patClosedCommentEnd = null;
private static Pattern patLineComment = null;
private static Pattern patDelimiter=null;
// C++ Keywords
private static String[] keywords = { "asm", "auto", "bool", "break",
"case", "catch", "char", "class", "const", "const_cast",
"continue", "default", "delete", "do", "double", "dynamic_cast",
"else", "enum", "explicit", "export", "extern", "false", "float",
"for", "friend", "goto", "if", "inline", "int", "long", "mutable",
"namespace", "new", "operator", "private", "protected", "public",
"register", "reinterpret_cast", "return", "short", "signed",
"sizeof", "static", "static_cast", "struct", "switch", "template",
"this", "throw", "true", "try", "typedef", "typeid", "typename",
"union", "unsigned", "using", "virtual", "void", "volatile",
"wchar_t", "while", "endif", "include", "ifndef"};
// Regex source strings
private static String numbers = "[0-9]*";
private static String closedcommentstart = "/\\*.*";
private static String closedcommentend = ".*\\*/";
private static String linecomment = "//.*";
private static String delimiter="[|&+\\-%(){}=;\\n\\t ]";
// private constructor, nothing to intanciate
private PatternFactory() {
}
/**
* Returns the keyword pattern
*
* @return
*/
public static Pattern getKeywordPattern() {
if (patKey == null) {
// Prepare keywords with regex
StringBuilder sb = new StringBuilder();
for (int x = 0; x < keywords.length; x++) {
// Before and after a keyword, everything except characters is
// allowed
sb.append("[^a-zA-Z]*");
sb.append(keywords[x]);
sb.append("[^a-zA-Z]*");
if (x <= keywords.length) {
sb.append("|");
}
}
patKey = Pattern.compile(sb.toString());
}
return patKey;
}
/**
* Returns the delimiter pattern
*
* @return
*/
public static Pattern getDelimiterPattern()
{
if(patDelimiter == null)
{
patDelimiter = Pattern.compile(delimiter);
}
return patDelimiter;
}
/**
* Returns the Number pattern
*
* @return
*/
public static Pattern getNumberPattern() {
if (patNumber == null) {
patNumber = Pattern.compile(numbers);
}
return patNumber;
}
/**
* Returns the Closed Comment Start pattern
*
* @return
*/
public static Pattern getClosedCommentStartPattern() {
if (patClosedCommentStart == null) {
patClosedCommentStart = Pattern.compile(closedcommentstart);
}
return patClosedCommentStart;
}
/**
* Returns the closed comment end pattern
*
* @return
*/
public static Pattern getClosedCommentEndPattern() {
if (patClosedCommentEnd == null) {
patClosedCommentEnd = Pattern.compile(closedcommentend);
}
return patClosedCommentEnd;
}
/**
* Returns the line comment pattern
*
* @return
*/
public static Pattern getLineCommentPattern() {
if (patLineComment == null) {
patLineComment = Pattern.compile(linecomment);
}
return patLineComment;
}
}
Mein Problem:
Bei kürzeren Quellcodes also z.B. ein HelloWorld-Programm oder auch etwas länger funktioniert das einwandfrei.
Nur ab einer bestimmten Länge, die ich nicht fest sagen kann, liefert der Scanner Unsinn, bzw. sagt mir dass das Matchresult beispielsweise an Position 1 steht, obwohl es an 2000 oder so stehen müsste. (z.B. in Zeile 55 im ersten Codefragment). Hab die Vermutung, dass er wieder von vorne anfängt zu zählen.
Hat jemand von euch schonmal ähnliches erlebt oder weiß, woran es liegen könnte?
Gruss
Dirk