public final Token readToken() {
        while (this.position < this.expression.length()) {
            if (Character.isWhitespace(this.expression.charAt(this.position)))
                ++this.position;
            else
                break;
        }

        if (this.position == this.expression.length())
            return null;

        String input = this.expression.substring(this.position);
/*
        final class Match {
            private final Matcher matcher;
            private final TokenRule lexeme;
            public Match(Matcher match, TokenRule lexeme) {
                this.matcher = match;
                this.lexeme = lexeme;
            }
            public Matcher getMatcher() {
                return  this.matcher;
            }
            public TokenRule getLexeme() {
                return  this.lexeme;
            }
        }
*/
        for (TokenRule rule : this.tokenRules()) {
            Matcher m = rule.regex().matcher(input);
            if (!m.find())
                continue;

            //Match match = new Match(m, rule);

            this.position += m.group().length();
            String value = m.group();
            if (rule.mutator() != null)
                value = rule.mutator().mutate(value);

            return new Token(rule.tokenType(), rule.tokenSubType(), value);
        }

        //StreamSupport.stream(this.tokenRules().spliterator(), false).
/*
        var match = this.TokenRules.Select(l => new { Match = l.Regex.Match(input), Lexeme = l })
        .Where(m => m.Match != null && m.Match.Success)
        .GroupBy(m => m.Match.Length)
        .OrderByDescending(g => g.Key)
        .FirstOrDefault();

        if (match == null)
            throw new Exception("Could not identify token \"" + this._expression[this._position] + " at position " + this._position);

        var matches = match.ToList();
        this.position += matches[0].Match.Value.Length;

        var value = matches[0].Match.Value;
        var lex = matches[0].Lexeme;
*/
        //if (lex.getMutator() != null)
        //    value = lex.getMutator(value);

        //return new Token(lex.tokenType(), lex.tokenSubType(), value);
        return null;
    }