Skip to content

RegexSet: get matched strings. #352

Closed
@zstewar1

Description

@zstewar1

RegexSet can be used to build a tokenizer/lexer fairly easily by creating a set of regexes to match each token type:

let rs = RegexSet::new(&[
    r"^\s+", // 0
    r"^[+-]", // 1
    r"^[*/]", // 2
    r"^\(", // 3
    r"^\)", // 4
    r"^([0-9]*\.)?[0-9]+([eE][+-]?[0-9]+)?", // 5
    r"^[\p{Alphabetic}_][\d\p{Alphabetic}_]*", // 6
]);

Lexing is done by running the input string against the RegexSet and constructing a token based on which regex(es) matched (there might be multiple matches if identifiers and keywords are separate regexes, but selecting between conflicting matches is up to the developer of the lexer). However, RegexSet only supports checking if any regex matches or checking which regexes matched. For fixed-size matches, this is acceptable: if the [+-] token matches, the you know to extract just one character, for example. However, for a complex token type like a number (5) or identifier (6), the only way currently to extract the actual matched string would be to have a separate regex for just that token, and run it over the input a second time to find the match length.

This would be much simpler if RegexSet supported a mode where it could capture the complete match from each regex as a string slice or indexes into the input string. This doesn't require handling capture groups, just the complete match.

Another workaround is to try each regex in sequence, though this too is disadvantageous. The biggest issue is exactly the problem RegexSet is intended to solve: the string must be processed repeatedly, for each regex in the set. Another issue is that it makes matching certain kinds of overlapping regexes more difficult; for example, a keyword like and or nil might also be a valid identifier, so the lexer would have to first match them as a single regex and then disambiguate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions