Regex Tokenizer

Runtime

Top Contributor
Hallo Leute,

ich habe da eine Klasse geschrieben, die einen String mit Regex-Patterns splitten sollte. Ich kanns nicht mit string.split("hier wäre ein Regex pattern") machen, weil ich die Methode weder mehrere Patterns annehmen kann, noch die Stücke, in denen der Regex matcht zurückgibt:
Java:
package cyrill.jx.compiler;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

class RegexTokenizer {

    private CharSequence input;
    private Matcher[] matchers;
    private int lastEnd = 0;
    private int line = 0;

    public RegexTokenizer(CharSequence input, Pattern[] patterns) {
        this.input = input;
        matchers = new Matcher[patterns.length];
        for (int i = 0; i < patterns.length; i++) {
            matchers[i] = patterns[i].matcher(input);
        }
    }

    public String nextToken() {
        for (int i = 0; i < input.length(); i++) {
            if (input.charAt(i) == '\n' || input.charAt(i) == '\r') {
                line++;
            }
            if (Character.isWhitespace(input.charAt(i))) {
                continue;
            }
            for (int j = 0; j < matchers.length; j++) {
                System.out.println(matchers[i].find(lastEnd));
                if (matchers[i].find(i) && matchers[i].start() == i) {
                    int start = matchers[i].start();
                    int end = matchers[i].end();
                    i += end;
                    return input.subSequence(start, end).toString();
                }
            }
        }
        //throw new CompilerException("in line: " + line);
        return null;
    }

    public boolean hasNextToken() {
        boolean hasNext = false;
        if (lastEnd == input.length() - 1) {
            return false;
        }
        for (int i = 0; i < matchers.length; i++) {
            if (matchers[i].find(lastEnd)) {
                hasNext = true;
            }
        }
        return hasNext;
    }
}

eingentlich wäre es ja einfach, aber ich bekomms irgendwie nicht hin :bahnhof:. Danke an alle, die mir helfen.

edit:
Grammatikfehler 😀
 
Zuletzt bearbeitet:
was soll denn gesplitted werden? hast du n beispiel? und was soll rauskommen? lässt sich ohne beispiel schwer testen! 🙁
 
Input: "import blablabla;"
Output: null, null, null, null, null, null, null, null, null, null, null, null, null, null...
Alle Regex-Patterns:
Java:
new Object[][] {
                    {
                        END_STATEMENT,
                        STRING,
                        CHARACTER,
                        NUMBER,
                        OPERATOR_ASSIGNMENT,
                        OPERATOR_ADDITION,
                        OPERATOR_SUBTRACTION,
                        OPERATOR_MULTIPLICATION,
                        OPERATOR_DIVISION,
                        OPERATOR_INCREMENT,
                        OPERATOR_DECREMENT,
                        OPERATOR_AND,
                        OPERATOR_CONDITIONAL_AND,
                        OPERATOR_OR,
                        OPERATOR_CONDITIONAL_OR,
                        OPERATOR_XOR,
                        OPERATOR_COMPLEMENT,
                        OPERATOR_NULL_ASSIGN,
                        OPERATOR_FAST_IF_ELSE_QUESTION,
                        OPERATOR_FAST_IF_ELSE_SEPARATOR,
                        OPERATOR_OPEN_SEQUENCE,
                        OPERATOR_CLOSE_SEQUENCE,
                        OPERATOR_OPEN_PARAMETER,
                        OPERATOR_SEPARATE_PARAMETER,
                        OPERATOR_CLOSE_PARAMETER,
                        OPERATOR_OPEN_BLOCK,
                        OPERATOR_CLOSE_BLOCK,
                        OPERATOR_INTERVAL,
                        OPERATOR_POINT,
                        OPERATOR_REMAINDER,
                        OPERATOR_COMPARE_EQUAL,
                        OPERATOR_COMPARE_NOT_EQUAL,
                        OPERATOR_COMPARE_BIGGER_OR_EQUAL,
                        OPERATOR_COMPARE_BIGGER,
                        OPERATOR_COMPARE_LESS_EQUAL,
                        OPERATOR_COMPARE_LESS,
                        OPERATOR_BIT_COMPLEMENT,
                        OPERATOR_BIT_SIGNED_SHIFT_LEFT,
                        OPERATOR_BIT_SIGNED_SHIFT_RIGHT,
                        OPERATOR_BIT_UNSIGNED_SHIFT_RIGHT,
                        KEYWORD_CLASS,
                        KEYWORD_ENUM,
                        KEYWORD_INTERFACE,
                        KEYWORD_IMPORT,
                        KEYWORD_PACKAGE,
                        KEYWORD_BIND,
                        KEYWORD_OPERATOR,
                        KEYWORD_EXTENDS,
                        KEYWORD_IMPLEMENTS,
                        KEYWORD_IF,
                        KEYWORD_ELSE,
                        KEYWORD_TRY,
                        KEYWORD_CATCH,
                        KEYWORD_FINALLY,
                        KEYWORD_INSTANCEOF,
                        KEYWORD_NEW,
                        KEYWORD_SWITCH,
                        KEYWORD_CASE,
                        KEYWORD_SUPER,
                        KEYWORD_THIS,
                        KEYWORD_THROW,
                        KEYWORD_THROWS,
                        KEYWORD_RETURN,
                        KEYWORD_BREAK,
                        KEYWORD_CONTINUE,
                        KEYWORD_GOTO,
                        KEYWORD_WITH,
                        KEYWORD_ACCESS_PUBLIC,
                        KEYWORD_ACCESS_PRIVATE,
                        KEYWORD_ACCESS_PROTECTED,
                        KEYWORD_PROPERTY_ABSTRACT,
                        KEYWORD_PROPERTY_SYNCHRONIZED,
                        KEYWORD_PROPERTY_TRANSIENT,
                        KEYWORD_PROPERTY_FINAL,
                        KEYWORD_PROPERTY_STATIC,
                        KEYWORD_PROPERTY_VOLATILE,
                        KEYWORD_PROPERTY_NATIVE,
                        KEYWORD_PROPERTY_DYNAMIC,
                        KEYWORD_SHORTCUT_BOOLEAN,
                        KEYWORD_SHORTCUT_INTEGER,
                        KEYWORD_SHORTCUT_BYTE,
                        KEYWORD_SHORTCUT_LONG,
                        KEYWORD_SHORTCUT_FLOAT,
                        KEYWORD_SHORTCUT_SHORT,
                        KEYWORD_SHORTCUT_CHARACTER,
                        KEYWORD_SHORTCUT_DOUBLE,
                        KEYWORD_SHORTCUT_VOID,
                        KEYWORD_SHORTCUT_STRING,
                        KEYWORD_SHORTCUT_OBJECT,
                        KEYWORD_LOOP_DO,
                        KEYWORD_LOOP_FOR,
                        KEYWORD_LOOP_WHILE,
                        KEYWORD_LOOP_WHILENOT,
                        OPERATOR_ASSIGN_ADDITION,
                        OPERATOR_ASSIGN_SUBTRACTION,
                        OPERATOR_ASSIGN_DIVISION,
                        OPERATOR_ASSIGN_MULTIPLICATION,
                        OPERATOR_ASSIGN_REMAINDER,
                        IDENTIFIER
                    },
                    {
                        ";",
                        "\"[^\n]{0,}\"",
                        "'[^\n]'",
                        "(0x[\\da-fA-F]{0,})|(\\d{0,}([bilfdBILFD]){0,1})",
                        "(?<![^/*\\-\\+%])=",
                        "\\+(?![=+])",
                        "\\-(?![=-])",
                        "\\*(?!=)",
                        "/(?!=)",
                        "\\+{2}",
                        "\\-{2}",
                        "&{1}",
                        "&{2}",
                        "\\|{1}",
                        "\\|{2}",
                        "\\^",
                        "!(?!=)",
                        "\\?=",
                        "\\?(?!=)",
                        ":",
                        "\\[",
                        "\\]",
                        "\\(",
                        ",",
                        "\\)",
                        "\\{",
                        "\\}",
                        "\\.{2}",
                        "\\.(?!\\.)",
                        "%(?!=)",
                        "={2}",
                        "!=",
                        ">=",
                        ">(?![=>])",
                        "<=",
                        "<(?![=<])",
                        "~",
                        "<{2}",
                        ">>(?!>)",
                        ">{3}",
                        "\\bclass\\b",
                        "\\benum\\b",
                        "\\binterface\\b",
                        "\\bimport\\b",
                        "\\bpackage\\b",
                        "\\bbind\\b",
                        "\\boperator\\b",
                        "\\bextends\\b",
                        "\\bimplements\\b",
                        "\\bif\\b",
                        "\\belse\\b",
                        "\\btry\\b",
                        "\\bcatch\\b",
                        "\\bfinally\\b",
                        "\\binstanceof\\b",
                        "\\bnew\\b",
                        "\\bswitch\\b",
                        "\\bcase\\b",
                        "\\bsuper\\b",
                        "\\bthis\\b",
                        "\\bthrow\\b",
                        "\\bthrows\\b",
                        "\\breturn\\b",
                        "\\bbreak\\b",
                        "\\bcontinue\\b",
                        "\\bgoto\\b",
                        "\\bwith\\b",
                        "\\bpublic\\b",
                        "\\bprivate\\b",
                        "\\bprotected\\b",
                        "\\babstract\\b",
                        "\\bsynchronized\\b",
                        "\\btransient\\b",
                        "\\bfinal\\b",
                        "\\bstatic\\b",
                        "\\bvolatile\\b",
                        "\\bnative\\b",
                        "\\bdynamic\\b",
                        "\\bboolean\\b",
                        "\\binteger\\b",
                        "\\bbyte\\b",
                        "\\blong\\b",
                        "\\bfloat\\b",
                        "\\bshort\\b",
                        "\\bchar\\b",
                        "\\bdouble\\b",
                        "\\bvoid\\b",
                        "\\bstring\\b",
                        "\\bobject\\b",
                        "\\bdo\\b",
                        "\\bfor\\b",
                        "\\bwhile\\b",
                        "\\bwhilenot\\b",
                        "\\+=",
                        "\\-=",
                        "/=",
                        "\\*=",
                        "%=",
                        "\\w{1,}"
                    }
                };

edit:
was rauskommen sollte:
import, blablabla, ;
 
Zuletzt bearbeitet:
hoffe mal ich habe dich richtig verstanden. du könntest z.B. versuchen, dir den nächsten Matcher in hasNextToken zu merken:

Java:
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class RegexTokenizer {

	private CharSequence input;
	private Matcher[] matchers;
	private Matcher nextMatcher;
	private int lastEnd = 0;

	public static void main(String[] args) {
		String test = "hallo welt;das ist ein test,zum splitten eines Strings anhand mehrerer RegEx;mal sehen,ob es klappt";
		Pattern[] patterns = new Pattern[3];
		patterns[0] = Pattern.compile("\\s");
		patterns[1] = Pattern.compile(",");
		patterns[2] = Pattern.compile(";");
		RegexTokenizer rtok = new RegexTokenizer(test, patterns);
		while (rtok.hasNextToken()) {
			System.out.println(rtok.nextToken());
		}
	}
	public RegexTokenizer(CharSequence input, Pattern[] patterns) {
		this.input = input;
		matchers = new Matcher[patterns.length];
		for (int i = 0; i < patterns.length; i++) {
			matchers[i] = patterns[i].matcher(input);
		}
	}

	public CharSequence nextToken() {
		CharSequence token = input.subSequence(lastEnd, nextMatcher.start());
		lastEnd = nextMatcher.end();
		nextMatcher = null;
		return token;
	}

	public boolean hasNextToken() {
		boolean hasNext = false;
		if (lastEnd == input.length() - 1) {
			return false;
		}
		for (int i = 0; i < matchers.length; i++) {
			if (matchers[i].find(lastEnd)) {
				if (nextMatcher == null || matchers[i].start() < nextMatcher.start())
					nextMatcher = matchers[i];
				hasNext = true;
			}
		}
		return hasNext;
	}
}

edit: könntest vllt noch einen zweiten Konstruktor machen, der dir einen boolean returnDelimiters erlaubt. Somit könntest du auch die Trenntokens zurückgeben. Weiß ja nicht, was du damit vor hast.

ahja und anständige Exceptions würde ich auch noch einbauen. z.B. würde eine NPE fliegen, wenn du nextToken() vor hasNextToken() aufrufst oder nextToken() 2x hintereinander. Das kannst du natürlich zum einen etwas geschickt verhindern oder zum anderen eine IllegalStateException oder so schmeissen.
Das Ganze hab ich jetzt in dem Beispiel überhaupt nicht berücksichtigt. Musst du selbst entscheiden, wie du das haben willst.
 
Zuletzt bearbeitet:
Warum machst du es dir so schwer, man kann auch folgendes schreiben :

Java:
meinString.split("\\.|;|\\s");

Hier sind jetzt 3 Trenner angeben
 
Zuletzt bearbeitet:
Es sollte immer den Teil zurückgeben, bei dem es den fühesten match gibt. Übrigens gibt er immer noch nur null werte aus.

also willlst du jetzt sowohl tokens (stücke zwischen den matches) und matches zurückgeben oder nur eines der beiden? Ein Tokenizer macht das Erste und optional das Zweite (siehe mein edit im Vorpost). Wenn du nur das Zweite willst, hat das imho nichts mit einem split/tokenizer Algo zu tun. Wäre allerdings dem obigen Code ziemlich identisch (das Zusammensetzen vom returnwert in nextToken() wird ein bisschen abgeändert).
 
die sache mit split ist eh hinfällig, weil der to was anderes sucht.

@to: wie gesagt: schreib den o.g. Code etwas um, dann sollte er auch das machen, was du suchst...
 
Wenn ich weiss, welche Regex gematcht hat, kann ich auch noch gleich den Typ angeben.

edit: Rechtschreibefehler
 
Zuletzt bearbeitet:

Zurück
Oben